Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 9 Mar 2009 16:15:40 +0000 (09:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 9 Mar 2009 16:15:40 +0000 (09:15 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (29 commits)
  p54: fix race condition in memory management
  cfg80211: test before subtraction on unsigned
  iwlwifi: fix error flow in iwl*_pci_probe
  rt2x00 : more devices to rt73usb.c
  rt2x00 : more devices to rt2500usb.c
  bonding: Fix device passed into ->ndo_neigh_setup().
  vlan: Fix vlan-in-vlan crashes.
  net: Fix missing dev->neigh_setup in register_netdevice().
  tmspci: fix request_irq race
  pkt_sched: act_police: Fix a rate estimator test.
  tg3: Fix 5906 link problems
  SCTP: change sctp_ctl_sock_init() to try IPv4 if IPv6 fails
  IPv6: add "disable" module parameter support to ipv6.ko
  sungem: another error printed one too early
  aoe: error printed 1 too early
  net pcmcia: worklimit reaches -1
  net: more timeouts that reach -1
  net: fix tokenring license
  dm9601: new vendor/product IDs
  netlink: invert error code in netlink_set_err()
  ...

36 files changed:
Documentation/networking/ipv6.txt [new file with mode: 0644]
arch/arm/mach-omap2/board-ldp.c
drivers/block/aoe/aoedev.c
drivers/net/arm/ks8695net.c
drivers/net/bonding/bond_main.c
drivers/net/jme.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/smc911x.h
drivers/net/sungem.c
drivers/net/tg3.c
drivers/net/tokenring/tmspci.c
drivers/net/ucc_geth_mii.c
drivers/net/usb/dm9601.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt73usb.c
include/linux/netdevice.h
include/net/net_namespace.h
net/802/tr.c
net/8021q/vlan_dev.c
net/core/dev.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/ipv4/icmp.c
net/ipv4/tcp_ipv4.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/netlink/af_netlink.c
net/sched/act_police.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/wireless/reg.c

diff --git a/Documentation/networking/ipv6.txt b/Documentation/networking/ipv6.txt
new file mode 100644 (file)
index 0000000..268e5c1
--- /dev/null
@@ -0,0 +1,35 @@
+
+Options for the ipv6 module are supplied as parameters at load time.
+
+Module options may be given as command line arguments to the insmod
+or modprobe command, but are usually specified in either the
+/etc/modules.conf or /etc/modprobe.conf configuration file, or in a
+distro-specific configuration file.
+
+The available ipv6 module parameters are listed below.  If a parameter
+is not specified the default value is used.
+
+The parameters are as follows:
+
+disable
+
+       Specifies whether to load the IPv6 module, but disable all
+       its functionality.  This might be used when another module
+       has a dependency on the IPv6 module being loaded, but no
+       IPv6 addresses or operations are desired.
+
+       The possible values and their effects are:
+
+       0
+               IPv6 is enabled.
+
+               This is the default value.
+
+       1
+               IPv6 is disabled.
+
+               No IPv6 addresses will be added to interfaces, and
+               it will not be possible to open an IPv6 socket.
+
+               A reboot is required to enable IPv6.
+
index f6a1345..6031e17 100644 (file)
@@ -81,7 +81,7 @@ static inline void __init ldp_init_smc911x(void)
        }
 
        ldp_smc911x_resources[0].start = cs_mem_base + 0x0;
-       ldp_smc911x_resources[0].end   = cs_mem_base + 0xf;
+       ldp_smc911x_resources[0].end   = cs_mem_base + 0xff;
        udelay(100);
 
        eth_gpio = LDP_SMC911X_GPIO;
index cc25057..eeea477 100644 (file)
@@ -173,7 +173,7 @@ skbfree(struct sk_buff *skb)
                return;
        while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0)
                msleep(Sms);
-       if (i <= 0) {
+       if (i < 0) {
                printk(KERN_ERR
                        "aoe: %s holds ref: %s\n",
                        skb->dev ? skb->dev->name : "netif",
index 1cf2f94..f3a1274 100644 (file)
@@ -560,7 +560,7 @@ ks8695_reset(struct ks8695_priv *ksp)
                msleep(1);
        }
 
-       if (reset_timeout == 0) {
+       if (reset_timeout < 0) {
                dev_crit(ksp->dev,
                         "Timeout waiting for DMA engines to reset\n");
                /* And blithely carry on */
index 9fb3883..e0578fe 100644 (file)
@@ -4113,7 +4113,7 @@ static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
                const struct net_device_ops *slave_ops
                        = slave->dev->netdev_ops;
                if (slave_ops->ndo_neigh_setup)
-                       return slave_ops->ndo_neigh_setup(dev, parms);
+                       return slave_ops->ndo_neigh_setup(slave->dev, parms);
        }
        return 0;
 }
index 08b3405..a6e1a35 100644 (file)
@@ -957,13 +957,14 @@ jme_process_receive(struct jme_adapter *jme, int limit)
                goto out_inc;
 
        i = atomic_read(&rxring->next_to_clean);
-       while (limit-- > 0) {
+       while (limit > 0) {
                rxdesc = rxring->desc;
                rxdesc += i;
 
                if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) ||
                !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL))
                        goto out;
+               --limit;
 
                desccnt = rxdesc->descwb.desccnt & RXWBDCNT_DCNT;
 
index e5cb6b1..2404a83 100644 (file)
@@ -1035,7 +1035,8 @@ static int el3_rx(struct net_device *dev, int worklimit)
        DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
                  dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
        while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) &&
-                  (--worklimit >= 0)) {
+                       worklimit > 0) {
+               worklimit--;
                if (rx_status & 0x4000) { /* Error, update stats. */
                        short error = rx_status & 0x3800;
                        dev->stats.rx_errors++;
index 73ecc65..1e01b8a 100644 (file)
@@ -857,7 +857,8 @@ static int el3_rx(struct net_device *dev)
     DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
          dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
     while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
-          (--worklimit >= 0)) {
+                   worklimit > 0) {
+       worklimit--;
        if (rx_status & 0x4000) { /* Error, update stats. */
            short error = rx_status & 0x3800;
            dev->stats.rx_errors++;
index 870b4c3..a45952e 100644 (file)
   #define SMC_USE_16BIT                0
   #define SMC_USE_32BIT                1
   #define SMC_IRQ_SENSE                IRQF_TRIGGER_LOW
+#elif defined(CONFIG_ARCH_OMAP34XX)
+  #define SMC_USE_16BIT                0
+  #define SMC_USE_32BIT                1
+  #define SMC_IRQ_SENSE                IRQF_TRIGGER_LOW
+  #define SMC_MEM_RESERVED     1
+#elif defined(CONFIG_ARCH_OMAP24XX)
+  #define SMC_USE_16BIT                0
+  #define SMC_USE_32BIT                1
+  #define SMC_IRQ_SENSE                IRQF_TRIGGER_LOW
+  #define SMC_MEM_RESERVED     1
 #else
 /*
  * Default configuration
@@ -675,6 +685,7 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
 #define CHIP_9116      0x0116
 #define CHIP_9117      0x0117
 #define CHIP_9118      0x0118
+#define CHIP_9211      0x9211
 #define CHIP_9215      0x115A
 #define CHIP_9217      0x117A
 #define CHIP_9218      0x118A
@@ -689,6 +700,7 @@ static const struct chip_id chip_ids[] =  {
        { CHIP_9116, "LAN9116" },
        { CHIP_9117, "LAN9117" },
        { CHIP_9118, "LAN9118" },
+       { CHIP_9211, "LAN9211" },
        { CHIP_9215, "LAN9215" },
        { CHIP_9217, "LAN9217" },
        { CHIP_9218, "LAN9218" },
index 8d64b1d..0fcb750 100644 (file)
@@ -1229,7 +1229,7 @@ static void gem_reset(struct gem *gp)
                        break;
        } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST));
 
-       if (limit <= 0)
+       if (limit < 0)
                printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
 
        if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes)
index b080f94..dabdf59 100644 (file)
@@ -1473,7 +1473,8 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
 {
        u32 reg;
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                return;
 
        reg = MII_TG3_MISC_SHDW_WREN |
index 5f60177..e2150b3 100644 (file)
@@ -121,11 +121,6 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
                goto err_out_trdev;
        }
 
-       ret = request_irq(pdev->irq, tms380tr_interrupt, IRQF_SHARED,
-                         dev->name, dev);
-       if (ret)
-               goto err_out_region;
-
        dev->base_addr  = pci_ioaddr;
        dev->irq        = pci_irq_line;
        dev->dma        = 0;
@@ -142,7 +137,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
        ret = tmsdev_init(dev, &pdev->dev);
        if (ret) {
                printk("%s: unable to get memory for dev->priv.\n", dev->name);
-               goto err_out_irq;
+               goto err_out_region;
        }
 
        tp = netdev_priv(dev);
@@ -157,6 +152,11 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
 
        tp->tmspriv = cardinfo;
 
+       ret = request_irq(pdev->irq, tms380tr_interrupt, IRQF_SHARED,
+                         dev->name, dev);
+       if (ret)
+               goto err_out_tmsdev;
+
        dev->open = tms380tr_open;
        dev->stop = tms380tr_close;
        pci_set_drvdata(pdev, dev);
@@ -164,15 +164,15 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
 
        ret = register_netdev(dev);
        if (ret)
-               goto err_out_tmsdev;
+               goto err_out_irq;
        
        return 0;
 
+err_out_irq:
+       free_irq(pdev->irq, dev);
 err_out_tmsdev:
        pci_set_drvdata(pdev, NULL);
        tmsdev_term(dev);
-err_out_irq:
-       free_irq(pdev->irq, dev);
 err_out_region:
        release_region(pci_ioaddr, TMS_PCI_IO_EXTENT);
 err_out_trdev:
index 5463591..0ada4ed 100644 (file)
@@ -107,7 +107,7 @@ int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 static int uec_mdio_reset(struct mii_bus *bus)
 {
        struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
-       unsigned int timeout = PHY_INIT_TIMEOUT;
+       int timeout = PHY_INIT_TIMEOUT;
 
        mutex_lock(&bus->mdio_lock);
 
@@ -123,7 +123,7 @@ static int uec_mdio_reset(struct mii_bus *bus)
 
        mutex_unlock(&bus->mdio_lock);
 
-       if (timeout <= 0) {
+       if (timeout < 0) {
                printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name);
                return -EBUSY;
        }
index 5b67bbf..81682c6 100644 (file)
@@ -635,6 +635,10 @@ static const struct usb_device_id products[] = {
        USB_DEVICE(0x0a47, 0x9601),     /* Hirose USB-100 */
        .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+       USB_DEVICE(0x0fe6, 0x8101),     /* DM9601 USB to Fast Ethernet Adapter */
+       .driver_info = (unsigned long)&dm9601_info,
+        },
        {},                     // END
 };
 
index 36bafeb..129e2d3 100644 (file)
@@ -3868,7 +3868,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        err = iwl_eeprom_check_version(priv);
        if (err)
-               goto out_iounmap;
+               goto out_free_eeprom;
 
        /* extract MAC Address */
        iwl_eeprom_get_mac(priv, priv->mac_addr);
@@ -3945,6 +3945,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
  out_remove_sysfs:
+       destroy_workqueue(priv->workqueue);
+       priv->workqueue = NULL;
        sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
  out_uninit_drv:
        iwl_uninit_drv(priv);
@@ -3953,8 +3955,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  out_iounmap:
        pci_iounmap(pdev, priv->hw_base);
  out_pci_release_regions:
-       pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
+       pci_release_regions(pdev);
  out_pci_disable_device:
        pci_disable_device(pdev);
  out_ieee80211_free_hw:
index 93be74a..57dd34e 100644 (file)
@@ -7911,7 +7911,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                                CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
        if (err < 0) {
                IWL_DEBUG_INFO("Failed to init the card\n");
-               goto out_remove_sysfs;
+               goto out_iounmap;
        }
 
        /***********************
@@ -7921,7 +7921,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        err = iwl3945_eeprom_init(priv);
        if (err) {
                IWL_ERROR("Unable to init EEPROM\n");
-               goto out_remove_sysfs;
+               goto out_iounmap;
        }
        /* MAC Address location in EEPROM same for 3945/4965 */
        get_eeprom_mac(priv, priv->mac_addr);
@@ -7975,7 +7975,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        err = iwl3945_init_channel_map(priv);
        if (err) {
                IWL_ERROR("initializing regulatory failed: %d\n", err);
-               goto out_release_irq;
+               goto out_unset_hw_setting;
        }
 
        err = iwl3945_init_geos(priv);
@@ -8045,25 +8045,22 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        return 0;
 
  out_remove_sysfs:
+       destroy_workqueue(priv->workqueue);
+       priv->workqueue = NULL;
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
  out_free_geos:
        iwl3945_free_geos(priv);
  out_free_channel_map:
        iwl3945_free_channel_map(priv);
-
-
- out_release_irq:
-       destroy_workqueue(priv->workqueue);
-       priv->workqueue = NULL;
+ out_unset_hw_setting:
        iwl3945_unset_hw_setting(priv);
-
  out_iounmap:
        pci_iounmap(pdev, priv->hw_base);
  out_pci_release_regions:
        pci_release_regions(pdev);
  out_pci_disable_device:
-       pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
  out_ieee80211_free_hw:
        ieee80211_free_hw(priv->hw);
  out:
index 34561e6..f170106 100644 (file)
@@ -710,10 +710,11 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
                                           __le32 req_id)
 {
        struct p54_common *priv = dev->priv;
-       struct sk_buff *entry = priv->tx_queue.next;
+       struct sk_buff *entry;
        unsigned long flags;
 
        spin_lock_irqsave(&priv->tx_queue.lock, flags);
+       entry = priv->tx_queue.next;
        while (entry != (struct sk_buff *)&priv->tx_queue) {
                struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
 
@@ -732,7 +733,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
        struct p54_common *priv = dev->priv;
        struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
        struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
-       struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
+       struct sk_buff *entry;
        u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
        struct memrecord *range = NULL;
        u32 freed = 0;
@@ -741,6 +742,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
        int count, idx;
 
        spin_lock_irqsave(&priv->tx_queue.lock, flags);
+       entry = (struct sk_buff *) priv->tx_queue.next;
        while (entry != (struct sk_buff *)&priv->tx_queue) {
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
                struct p54_hdr *entry_hdr;
@@ -976,7 +978,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
                               struct p54_hdr *data, u32 len)
 {
        struct p54_common *priv = dev->priv;
-       struct sk_buff *entry = priv->tx_queue.next;
+       struct sk_buff *entry;
        struct sk_buff *target_skb = NULL;
        struct ieee80211_tx_info *info;
        struct memrecord *range;
@@ -1014,6 +1016,7 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
                }
        }
 
+       entry = priv->tx_queue.next;
        while (left--) {
                u32 hole_size;
                info = IEEE80211_SKB_CB(entry);
index af6b584..3e2ac2b 100644 (file)
@@ -1952,6 +1952,8 @@ static struct usb_device_id rt2500usb_device_table[] = {
        { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) },
        { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) },
        { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) },
+       /* CNet */
+       { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* Conceptronic */
        { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* D-LINK */
@@ -1976,14 +1978,20 @@ static struct usb_device_id rt2500usb_device_table[] = {
        { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) },
        { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) },
        { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+       /* Sagem */
+       { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* Siemens */
        { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* SMC */
        { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* Spairon */
        { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) },
+       /* SURECOM */
+       { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* Trust */
        { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+       /* VTech */
+       { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) },
        /* Zinwell */
        { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) },
        { 0, }
index 96a8d69..cefee1b 100644 (file)
@@ -2281,7 +2281,18 @@ static const struct rt2x00_ops rt73usb_ops = {
  */
 static struct usb_device_id rt73usb_device_table[] = {
        /* AboCom */
+       { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* AL */
+       { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Amigo */
+       { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* AMIT  */
+       { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Askey */
        { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
        /* ASUS */
@@ -2294,7 +2305,9 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Billionton */
        { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Buffalo */
+       { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
        /* CNet */
        { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2308,6 +2321,11 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Edimax */
+       { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gemtek */
        { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gigabyte */
@@ -2328,22 +2346,34 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Ralink */
+       { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Qcom */
        { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Samsung */
+       { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Senao */
        { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Surecom */
        { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Planex */
        { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Zcom */
+       { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* ZyXEL */
+       { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
        { 0, }
 };
 
index ec54785..6593667 100644 (file)
@@ -1079,6 +1079,7 @@ extern void               synchronize_net(void);
 extern int             register_netdevice_notifier(struct notifier_block *nb);
 extern int             unregister_netdevice_notifier(struct notifier_block *nb);
 extern int             init_dummy_netdev(struct net_device *dev);
+extern void            netdev_resync_ops(struct net_device *dev);
 
 extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 extern struct net_device       *dev_get_by_index(struct net *net, int ifindex);
index 6fc13d9..ded434b 100644 (file)
@@ -109,11 +109,6 @@ extern struct list_head net_namespace_list;
 #ifdef CONFIG_NET_NS
 extern void __put_net(struct net *net);
 
-static inline int net_alive(struct net *net)
-{
-       return net && atomic_read(&net->count);
-}
-
 static inline struct net *get_net(struct net *net)
 {
        atomic_inc(&net->count);
@@ -145,11 +140,6 @@ int net_eq(const struct net *net1, const struct net *net2)
 }
 #else
 
-static inline int net_alive(struct net *net)
-{
-       return 1;
-}
-
 static inline struct net *get_net(struct net *net)
 {
        return net;
@@ -234,6 +224,23 @@ struct pernet_operations {
        void (*exit)(struct net *net);
 };
 
+/*
+ * Use these carefully.  If you implement a network device and it
+ * needs per network namespace operations use device pernet operations,
+ * otherwise use pernet subsys operations.
+ *
+ * This is critically important.  Most of the network code cleanup
+ * runs with the assumption that dev_remove_pack has been called so no
+ * new packets will arrive during and after the cleanup functions have
+ * been called.  dev_remove_pack is not per namespace so instead the
+ * guarantee of no more packets arriving in a network namespace is
+ * provided by ensuring that all network devices and all sockets have
+ * left the network namespace before the cleanup methods are called.
+ *
+ * For the longest time the ipv4 icmp code was registered as a pernet
+ * device which caused kernel oops, and panics during network
+ * namespace cleanup.   So please don't get this wrong.
+ */
 extern int register_pernet_subsys(struct pernet_operations *);
 extern void unregister_pernet_subsys(struct pernet_operations *);
 extern int register_pernet_gen_subsys(int *id, struct pernet_operations *);
index 158150f..f47ae28 100644 (file)
@@ -668,3 +668,5 @@ module_init(rif_init);
 
 EXPORT_SYMBOL(tr_type_trans);
 EXPORT_SYMBOL(alloc_trdev);
+
+MODULE_LICENSE("GPL");
index 4a19acd..1b34135 100644 (file)
@@ -553,7 +553,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
        int err = 0;
 
        if (netif_device_present(real_dev) && ops->ndo_neigh_setup)
-               err = ops->ndo_neigh_setup(dev, pa);
+               err = ops->ndo_neigh_setup(real_dev, pa);
 
        return err;
 }
@@ -639,6 +639,7 @@ static int vlan_dev_init(struct net_device *dev)
                dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
                dev->netdev_ops         = &vlan_netdev_ops;
        }
+       netdev_resync_ops(dev);
 
        if (is_vlan_dev(real_dev))
                subclass = 1;
index 72b0d26..f112970 100644 (file)
@@ -2267,12 +2267,6 @@ int netif_receive_skb(struct sk_buff *skb)
 
        rcu_read_lock();
 
-       /* Don't receive packets in an exiting network namespace */
-       if (!net_alive(dev_net(skb->dev))) {
-               kfree_skb(skb);
-               goto out;
-       }
-
 #ifdef CONFIG_NET_CLS_ACT
        if (skb->tc_verd & TC_NCLS) {
                skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -4288,6 +4282,39 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
+/* Some devices need to (re-)set their netdev_ops inside
+ * ->init() or similar.  If that happens, we have to setup
+ * the compat pointers again.
+ */
+void netdev_resync_ops(struct net_device *dev)
+{
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       dev->init = ops->ndo_init;
+       dev->uninit = ops->ndo_uninit;
+       dev->open = ops->ndo_open;
+       dev->change_rx_flags = ops->ndo_change_rx_flags;
+       dev->set_rx_mode = ops->ndo_set_rx_mode;
+       dev->set_multicast_list = ops->ndo_set_multicast_list;
+       dev->set_mac_address = ops->ndo_set_mac_address;
+       dev->validate_addr = ops->ndo_validate_addr;
+       dev->do_ioctl = ops->ndo_do_ioctl;
+       dev->set_config = ops->ndo_set_config;
+       dev->change_mtu = ops->ndo_change_mtu;
+       dev->neigh_setup = ops->ndo_neigh_setup;
+       dev->tx_timeout = ops->ndo_tx_timeout;
+       dev->get_stats = ops->ndo_get_stats;
+       dev->vlan_rx_register = ops->ndo_vlan_rx_register;
+       dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
+       dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = ops->ndo_poll_controller;
+#endif
+#endif
+}
+EXPORT_SYMBOL(netdev_resync_ops);
+
 /**
  *     register_netdevice      - register a network device
  *     @dev: device to register
@@ -4332,27 +4359,7 @@ int register_netdevice(struct net_device *dev)
         * This is temporary until all network devices are converted.
         */
        if (dev->netdev_ops) {
-               const struct net_device_ops *ops = dev->netdev_ops;
-
-               dev->init = ops->ndo_init;
-               dev->uninit = ops->ndo_uninit;
-               dev->open = ops->ndo_open;
-               dev->change_rx_flags = ops->ndo_change_rx_flags;
-               dev->set_rx_mode = ops->ndo_set_rx_mode;
-               dev->set_multicast_list = ops->ndo_set_multicast_list;
-               dev->set_mac_address = ops->ndo_set_mac_address;
-               dev->validate_addr = ops->ndo_validate_addr;
-               dev->do_ioctl = ops->ndo_do_ioctl;
-               dev->set_config = ops->ndo_set_config;
-               dev->change_mtu = ops->ndo_change_mtu;
-               dev->tx_timeout = ops->ndo_tx_timeout;
-               dev->get_stats = ops->ndo_get_stats;
-               dev->vlan_rx_register = ops->ndo_vlan_rx_register;
-               dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
-               dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-               dev->poll_controller = ops->ndo_poll_controller;
-#endif
+               netdev_resync_ops(dev);
        } else {
                char drivername[64];
                pr_info("%s (%s): not using net_device_ops yet\n",
index 6ac29a4..484f587 100644 (file)
@@ -77,7 +77,9 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
        if (endp == buf)
                goto err;
 
-       rtnl_lock();
+       if (!rtnl_trylock())
+               return -ERESTARTSYS;
+
        if (dev_isalive(net)) {
                if ((ret = (*set)(net, new)) == 0)
                        ret = len;
index 2adb1a7..e3bebd3 100644 (file)
@@ -157,9 +157,6 @@ static void cleanup_net(struct work_struct *work)
        struct pernet_operations *ops;
        struct net *net;
 
-       /* Be very certain incoming network packets will not find us */
-       rcu_barrier();
-
        net = container_of(work, struct net, work);
 
        mutex_lock(&net_mutex);
index 705b33b..fc562d2 100644 (file)
@@ -1205,7 +1205,7 @@ static struct pernet_operations __net_initdata icmp_sk_ops = {
 
 int __init icmp_init(void)
 {
-       return register_pernet_device(&icmp_sk_ops);
+       return register_pernet_subsys(&icmp_sk_ops);
 }
 
 EXPORT_SYMBOL(icmp_err_convert);
index 19d7b42..cf74c41 100644 (file)
@@ -2443,7 +2443,7 @@ static struct pernet_operations __net_initdata tcp_sk_ops = {
 void __init tcp_v4_init(void)
 {
        inet_hashinfo_init(&tcp_hashinfo);
-       if (register_pernet_device(&tcp_sk_ops))
+       if (register_pernet_subsys(&tcp_sk_ops))
                panic("Failed to create the TCP control socket.\n");
 }
 
index f9afb45..1220e2c 100644 (file)
@@ -493,15 +493,17 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
        read_unlock(&dev_base_lock);
 }
 
-static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 {
        struct net *net;
 
        net = (struct net *)table->extra2;
        if (p == &net->ipv6.devconf_dflt->forwarding)
-               return;
+               return 0;
+
+       if (!rtnl_trylock())
+               return -ERESTARTSYS;
 
-       rtnl_lock();
        if (p == &net->ipv6.devconf_all->forwarding) {
                __s32 newf = net->ipv6.devconf_all->forwarding;
                net->ipv6.devconf_dflt->forwarding = newf;
@@ -512,6 +514,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
 
        if (*p)
                rt6_purge_dflt_routers(net);
+       return 1;
 }
 #endif
 
@@ -2608,9 +2611,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 
        ASSERT_RTNL();
 
-       if ((dev->flags & IFF_LOOPBACK) && how == 1)
-               how = 0;
-
        rt6_ifdown(net, dev);
        neigh_ifdown(&nd_tbl, dev);
 
@@ -3983,7 +3983,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
        ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
        if (write)
-               addrconf_fixup_forwarding(ctl, valp, val);
+               ret = addrconf_fixup_forwarding(ctl, valp, val);
        return ret;
 }
 
@@ -4019,8 +4019,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
        }
 
        *valp = new;
-       addrconf_fixup_forwarding(table, valp, val);
-       return 1;
+       return addrconf_fixup_forwarding(table, valp, val);
 }
 
 static struct addrconf_sysctl_table
@@ -4446,25 +4445,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
 
 EXPORT_SYMBOL(unregister_inet6addr_notifier);
 
-static void addrconf_net_exit(struct net *net)
-{
-       struct net_device *dev;
-
-       rtnl_lock();
-       /* clean dev list */
-       for_each_netdev(net, dev) {
-               if (__in6_dev_get(dev) == NULL)
-                       continue;
-               addrconf_ifdown(dev, 1);
-       }
-       addrconf_ifdown(net->loopback_dev, 2);
-       rtnl_unlock();
-}
-
-static struct pernet_operations addrconf_net_ops = {
-       .exit = addrconf_net_exit,
-};
-
 /*
  *     Init / cleanup code
  */
@@ -4506,10 +4486,6 @@ int __init addrconf_init(void)
        if (err)
                goto errlo;
 
-       err = register_pernet_device(&addrconf_net_ops);
-       if (err)
-               return err;
-
        register_netdevice_notifier(&ipv6_dev_notf);
 
        addrconf_verify(0);
@@ -4539,15 +4515,22 @@ errlo:
 void addrconf_cleanup(void)
 {
        struct inet6_ifaddr *ifa;
+       struct net_device *dev;
        int i;
 
        unregister_netdevice_notifier(&ipv6_dev_notf);
-       unregister_pernet_device(&addrconf_net_ops);
-
        unregister_pernet_subsys(&addrconf_ops);
 
        rtnl_lock();
 
+       /* clean dev list */
+       for_each_netdev(&init_net, dev) {
+               if (__in6_dev_get(dev) == NULL)
+                       continue;
+               addrconf_ifdown(dev, 1);
+       }
+       addrconf_ifdown(init_net.loopback_dev, 2);
+
        /*
         *      Check hash table.
         */
@@ -4568,6 +4551,4 @@ void addrconf_cleanup(void)
 
        del_timer(&addr_chk_timer);
        rtnl_unlock();
-
-       unregister_pernet_subsys(&addrconf_net_ops);
 }
index c802bc1..da944ec 100644 (file)
@@ -72,6 +72,10 @@ MODULE_LICENSE("GPL");
 static struct list_head inetsw6[SOCK_MAX];
 static DEFINE_SPINLOCK(inetsw6_lock);
 
+static int disable_ipv6 = 0;
+module_param_named(disable, disable_ipv6, int, 0);
+MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
+
 static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
 {
        const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
@@ -991,10 +995,21 @@ static int __init inet6_init(void)
 {
        struct sk_buff *dummy_skb;
        struct list_head *r;
-       int err;
+       int err = 0;
 
        BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb));
 
+       /* Register the socket-side information for inet6_create.  */
+       for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
+               INIT_LIST_HEAD(r);
+
+       if (disable_ipv6) {
+               printk(KERN_INFO
+                      "IPv6: Loaded, but administratively disabled, "
+                      "reboot required to enable\n");
+               goto out;
+       }
+
        err = proto_register(&tcpv6_prot, 1);
        if (err)
                goto out;
@@ -1012,10 +1027,6 @@ static int __init inet6_init(void)
                goto out_unregister_udplite_proto;
 
 
-       /* Register the socket-side information for inet6_create.  */
-       for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
-               INIT_LIST_HEAD(r);
-
        /* We MUST register RAW sockets before we create the ICMP6,
         * IGMP6, or NDISC control sockets.
         */
index 9eb895c..3ae3cb8 100644 (file)
@@ -1084,6 +1084,13 @@ out:
        return 0;
 }
 
+/**
+ * netlink_set_err - report error to broadcast listeners
+ * @ssk: the kernel netlink socket, as returned by netlink_kernel_create()
+ * @pid: the PID of a process that we want to skip (if any)
+ * @groups: the broadcast group that will notice the error
+ * @code: error code, must be negative (as usual in kernelspace)
+ */
 void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
 {
        struct netlink_set_err_data info;
@@ -1093,7 +1100,8 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
        info.exclude_sk = ssk;
        info.pid = pid;
        info.group = group;
-       info.code = code;
+       /* sk->sk_err wants a positive error value */
+       info.code = -code;
 
        read_lock(&nl_table_lock);
 
index 5c72a11..f8f047b 100644 (file)
@@ -183,13 +183,6 @@ override:
                if (R_tab == NULL)
                        goto failure;
 
-               if (!est && (ret == ACT_P_CREATED ||
-                            !gen_estimator_active(&police->tcf_bstats,
-                                                  &police->tcf_rate_est))) {
-                       err = -EINVAL;
-                       goto failure;
-               }
-
                if (parm->peakrate.rate) {
                        P_tab = qdisc_get_rtab(&parm->peakrate,
                                               tb[TCA_POLICE_PEAKRATE]);
@@ -205,6 +198,12 @@ override:
                                            &police->tcf_lock, est);
                if (err)
                        goto failure_unlock;
+       } else if (tb[TCA_POLICE_AVRATE] &&
+                  (ret == ACT_P_CREATED ||
+                   !gen_estimator_active(&police->tcf_bstats,
+                                         &police->tcf_rate_est))) {
+               err = -EINVAL;
+               goto failure_unlock;
        }
 
        /* No failure allowed after this point */
index b78e3be..c4986d0 100644 (file)
@@ -717,15 +717,20 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 static int sctp_ctl_sock_init(void)
 {
        int err;
-       sa_family_t family;
+       sa_family_t family = PF_INET;
 
        if (sctp_get_pf_specific(PF_INET6))
                family = PF_INET6;
-       else
-               family = PF_INET;
 
        err = inet_ctl_sock_create(&sctp_ctl_sock, family,
                                   SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+
+       /* If IPv6 socket could not be created, try the IPv4 socket */
+       if (err < 0 && family == PF_INET6)
+               err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
+                                          SOCK_SEQPACKET, IPPROTO_SCTP,
+                                          &init_net);
+
        if (err < 0) {
                printk(KERN_ERR
                       "SCTP: Failed to create the SCTP control socket.\n");
@@ -1322,9 +1327,8 @@ SCTP_STATIC __init int sctp_init(void)
 out:
        return status;
 err_v6_add_protocol:
-       sctp_v6_del_protocol();
-err_add_protocol:
        sctp_v4_del_protocol();
+err_add_protocol:
        inet_ctl_sock_destroy(sctp_ctl_sock);
 err_ctl_sock_init:
        sctp_v6_protosw_exit();
@@ -1335,7 +1339,6 @@ err_protosw_init:
        sctp_v4_pf_exit();
        sctp_v6_pf_exit();
        sctp_sysctl_unregister();
-       list_del(&sctp_af_inet.list);
        free_pages((unsigned long)sctp_port_hashtable,
                   get_order(sctp_port_hashsize *
                             sizeof(struct sctp_bind_hashbucket)));
@@ -1383,7 +1386,6 @@ SCTP_STATIC __exit void sctp_exit(void)
        sctp_v4_pf_exit();
 
        sctp_sysctl_unregister();
-       list_del(&sctp_af_inet.list);
 
        free_pages((unsigned long)sctp_assoc_hashtable,
                   get_order(sctp_assoc_hashsize *
index e1d6076..b5495ae 100644 (file)
@@ -787,36 +787,48 @@ static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds,
                                   struct sctp_association *asoc,
                                   struct sctp_chunk *chunk)
 {
-       struct sctp_operr_chunk *operr_chunk;
        struct sctp_errhdr *err_hdr;
+       struct sctp_ulpevent *ev;
 
-       operr_chunk = (struct sctp_operr_chunk *)chunk->chunk_hdr;
-       err_hdr = &operr_chunk->err_hdr;
+       while (chunk->chunk_end > chunk->skb->data) {
+               err_hdr = (struct sctp_errhdr *)(chunk->skb->data);
 
-       switch (err_hdr->cause) {
-       case SCTP_ERROR_UNKNOWN_CHUNK:
-       {
-               struct sctp_chunkhdr *unk_chunk_hdr;
+               ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0,
+                                                    GFP_ATOMIC);
+               if (!ev)
+                       return;
 
-               unk_chunk_hdr = (struct sctp_chunkhdr *)err_hdr->variable;
-               switch (unk_chunk_hdr->type) {
-               /* ADDIP 4.1 A9) If the peer responds to an ASCONF with an
-                * ERROR chunk reporting that it did not recognized the ASCONF
-                * chunk type, the sender of the ASCONF MUST NOT send any
-                * further ASCONF chunks and MUST stop its T-4 timer.
-                */
-               case SCTP_CID_ASCONF:
-                       asoc->peer.asconf_capable = 0;
-                       sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP,
+               sctp_ulpq_tail_event(&asoc->ulpq, ev);
+
+               switch (err_hdr->cause) {
+               case SCTP_ERROR_UNKNOWN_CHUNK:
+               {
+                       sctp_chunkhdr_t *unk_chunk_hdr;
+
+                       unk_chunk_hdr = (sctp_chunkhdr_t *)err_hdr->variable;
+                       switch (unk_chunk_hdr->type) {
+                       /* ADDIP 4.1 A9) If the peer responds to an ASCONF with
+                        * an ERROR chunk reporting that it did not recognized
+                        * the ASCONF chunk type, the sender of the ASCONF MUST
+                        * NOT send any further ASCONF chunks and MUST stop its
+                        * T-4 timer.
+                        */
+                       case SCTP_CID_ASCONF:
+                               if (asoc->peer.asconf_capable == 0)
+                                       break;
+
+                               asoc->peer.asconf_capable = 0;
+                               sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP,
                                        SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+                               break;
+                       default:
+                               break;
+                       }
                        break;
+               }
                default:
                        break;
                }
-               break;
-       }
-       default:
-               break;
        }
 }
 
index 3a0cd07..f88dfde 100644 (file)
@@ -3163,7 +3163,6 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
                                        sctp_cmd_seq_t *commands)
 {
        struct sctp_chunk *chunk = arg;
-       struct sctp_ulpevent *ev;
 
        if (!sctp_vtag_verify(chunk, asoc))
                return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3173,21 +3172,10 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
                return sctp_sf_violation_chunklen(ep, asoc, type, arg,
                                                  commands);
 
-       while (chunk->chunk_end > chunk->skb->data) {
-               ev = sctp_ulpevent_make_remote_error(asoc, chunk, 0,
-                                                    GFP_ATOMIC);
-               if (!ev)
-                       goto nomem;
+       sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
+                       SCTP_CHUNK(chunk));
 
-               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-                               SCTP_ULPEVENT(ev));
-               sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
-                               SCTP_CHUNK(chunk));
-       }
        return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-       return SCTP_DISPOSITION_NOMEM;
 }
 
 /*
index 85c9034..bd0a16c 100644 (file)
@@ -380,7 +380,8 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 
        freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
 
-       if (freq_diff <= 0 || freq_range->max_bandwidth_khz > freq_diff)
+       if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
+                       freq_range->max_bandwidth_khz > freq_diff)
                return false;
 
        return true;