diff --git a/[refs] b/[refs] index 705e422c5288..686492c157ce 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 024c378f0b719d43b01b875caefa19f2612e103a +refs/heads/master: 8e5b2308489dbca27c104fc6a557d4c9348552e5 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index e71ff7c67a63..6bd1cd5c60df 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3502,9 +3502,9 @@ F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h MARVELL MWL8K WIRELESS DRIVER -M: Lennert Buytenhek +M: Lennert Buytenhek L: linux-wireless@vger.kernel.org -S: Maintained +S: Supported F: drivers/net/wireless/mwl8k.c MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER diff --git a/trunk/drivers/bluetooth/btmrvl_sdio.c b/trunk/drivers/bluetooth/btmrvl_sdio.c index 57d965b7f521..94f1f55f81f0 100644 --- a/trunk/drivers/bluetooth/btmrvl_sdio.c +++ b/trunk/drivers/bluetooth/btmrvl_sdio.c @@ -976,7 +976,7 @@ static struct sdio_driver bt_mrvl_sdio = { .remove = btmrvl_sdio_remove, }; -static int btmrvl_sdio_init_module(void) +static int __init btmrvl_sdio_init_module(void) { if (sdio_register_driver(&bt_mrvl_sdio) != 0) { BT_ERR("SDIO Driver Registration Failed"); @@ -989,7 +989,7 @@ static int btmrvl_sdio_init_module(void) return 0; } -static void btmrvl_sdio_exit_module(void) +static void __exit btmrvl_sdio_exit_module(void) { /* Set the flag as user is removing this module. */ user_rmmod = 1; diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index 381887ba677c..d3f739a295df 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -7743,9 +7743,10 @@ bnx2_get_pci_speed(struct bnx2 *bp) static void __devinit bnx2_read_vpd_fw_ver(struct bnx2 *bp) { - int rc, i, j; + int rc, i, v0_len = 0; u8 *data; - unsigned int block_end, rosize, len; + u8 *v0_str = NULL; + bool mn_match = false; #define BNX2_VPD_NVRAM_OFFSET 0x300 #define BNX2_VPD_LEN 128 @@ -7767,42 +7768,53 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) data[i + 3] = data[i + BNX2_VPD_LEN]; } - i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA); - if (i < 0) - goto vpd_done; + for (i = 0; i <= BNX2_VPD_LEN - 3; ) { + unsigned char val = data[i]; + unsigned int block_end; - rosize = pci_vpd_lrdt_size(&data[i]); - i += PCI_VPD_LRDT_TAG_SIZE; - block_end = i + rosize; + if (val == 0x82 || val == 0x91) { + i = (i + 3 + (data[i + 1] + (data[i + 2] << 8))); + continue; + } - if (block_end > BNX2_VPD_LEN) - goto vpd_done; + if (val != 0x90) + goto vpd_done; - j = pci_vpd_find_info_keyword(data, i, rosize, - PCI_VPD_RO_KEYWORD_MFR_ID); - if (j < 0) - goto vpd_done; + block_end = (i + 3 + (data[i + 1] + (data[i + 2] << 8))); + i += 3; - len = pci_vpd_info_field_size(&data[j]); + if (block_end > BNX2_VPD_LEN) + goto vpd_done; - j += PCI_VPD_INFO_FLD_HDR_SIZE; - if (j + len > block_end || len != 4 || - memcmp(&data[j], "1028", 4)) - goto vpd_done; + while (i < (block_end - 2)) { + int len = data[i + 2]; - j = pci_vpd_find_info_keyword(data, i, rosize, - PCI_VPD_RO_KEYWORD_VENDOR0); - if (j < 0) - goto vpd_done; + if (i + 3 + len > block_end) + goto vpd_done; - len = pci_vpd_info_field_size(&data[j]); + if (data[i] == 'M' && data[i + 1] == 'N') { + if (len != 4 || + memcmp(&data[i + 3], "1028", 4)) + goto vpd_done; + mn_match = true; - j += PCI_VPD_INFO_FLD_HDR_SIZE; - if (j + len > block_end || len > BNX2_MAX_VER_SLEN) - goto vpd_done; + } else if (data[i] == 'V' && data[i + 1] == '0') { + if (len > BNX2_MAX_VER_SLEN) + goto vpd_done; + + v0_len = len; + v0_str = &data[i + 3]; + } + i += 3 + len; - memcpy(bp->fw_version, &data[j], len); - bp->fw_version[len] = ' '; + if (mn_match && v0_str) { + memcpy(bp->fw_version, v0_str, v0_len); + bp->fw_version[v0_len] = ' '; + goto vpd_done; + } + } + goto vpd_done; + } vpd_done: kfree(data); diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 430c02267d7e..1787e3c86573 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -4946,8 +4946,6 @@ int bond_create(struct net *net, const char *name) } res = register_netdevice(bond_dev); - if (res < 0) - goto out_netdev; out: rtnl_unlock(); diff --git a/trunk/drivers/net/fs_enet/Kconfig b/trunk/drivers/net/fs_enet/Kconfig index fc073b5a38c7..562ea68ed99b 100644 --- a/trunk/drivers/net/fs_enet/Kconfig +++ b/trunk/drivers/net/fs_enet/Kconfig @@ -1,13 +1,9 @@ config FS_ENET tristate "Freescale Ethernet Driver" - depends on CPM1 || CPM2 || PPC_MPC512x + depends on CPM1 || CPM2 select MII select PHYLIB -config FS_ENET_MPC5121_FEC - def_bool y if (FS_ENET && PPC_MPC512x) - select FS_ENET_HAS_FEC - config FS_ENET_HAS_SCC bool "Chip has an SCC usable for ethernet" depends on FS_ENET && (CPM1 || CPM2) @@ -20,13 +16,13 @@ config FS_ENET_HAS_FCC config FS_ENET_HAS_FEC bool "Chip has an FEC usable for ethernet" - depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) + depends on FS_ENET && CPM1 select FS_ENET_MDIO_FEC default y config FS_ENET_MDIO_FEC tristate "MDIO driver for FEC" - depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) + depends on FS_ENET && CPM1 config FS_ENET_MDIO_FCC tristate "MDIO driver for FCC" diff --git a/trunk/drivers/net/fs_enet/fs_enet-main.c b/trunk/drivers/net/fs_enet/fs_enet-main.c index 0770e2f6da6b..ec2f5034457f 100644 --- a/trunk/drivers/net/fs_enet/fs_enet-main.c +++ b/trunk/drivers/net/fs_enet/fs_enet-main.c @@ -108,7 +108,9 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) * the last indicator should be set. */ if ((sc & BD_ENET_RX_LAST) == 0) - dev_warn(fep->dev, "rcv is not +last\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s rcv is not +last\n", + dev->name); /* * Check for errors. @@ -176,8 +178,9 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) received++; netif_receive_skb(skb); } else { - dev_warn(fep->dev, - "Memory squeeze, dropping packet.\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s Memory squeeze, dropping packet.\n", + dev->name); fep->stats.rx_dropped++; skbn = skb; } @@ -239,7 +242,9 @@ static int fs_enet_rx_non_napi(struct net_device *dev) * the last indicator should be set. */ if ((sc & BD_ENET_RX_LAST) == 0) - dev_warn(fep->dev, "rcv is not +last\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s rcv is not +last\n", + dev->name); /* * Check for errors. @@ -308,8 +313,9 @@ static int fs_enet_rx_non_napi(struct net_device *dev) received++; netif_rx(skb); } else { - dev_warn(fep->dev, - "Memory squeeze, dropping packet.\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s Memory squeeze, dropping packet.\n", + dev->name); fep->stats.rx_dropped++; skbn = skb; } @@ -382,10 +388,10 @@ static void fs_enet_tx(struct net_device *dev) } else fep->stats.tx_packets++; - if (sc & BD_ENET_TX_READY) { - dev_warn(fep->dev, - "HEY! Enet xmit interrupt and TX_READY.\n"); - } + if (sc & BD_ENET_TX_READY) + printk(KERN_WARNING DRV_MODULE_NAME + ": %s HEY! Enet xmit interrupt and TX_READY.\n", + dev->name); /* * Deferred means some collisions occurred during transmit, @@ -505,8 +511,9 @@ void fs_init_bds(struct net_device *dev) for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) { skb = dev_alloc_skb(ENET_RX_FRSIZE); if (skb == NULL) { - dev_warn(fep->dev, - "Memory squeeze, unable to allocate skb\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s Memory squeeze, unable to allocate skb\n", + dev->name); break; } skb_align(skb, ENET_RX_ALIGN); @@ -580,40 +587,6 @@ void fs_cleanup_bds(struct net_device *dev) /**********************************************************************************/ -#ifdef CONFIG_FS_ENET_MPC5121_FEC -/* - * MPC5121 FEC requeries 4-byte alignment for TX data buffer! - */ -static struct sk_buff *tx_skb_align_workaround(struct net_device *dev, - struct sk_buff *skb) -{ - struct sk_buff *new_skb; - struct fs_enet_private *fep = netdev_priv(dev); - - /* Alloc new skb */ - new_skb = dev_alloc_skb(skb->len + 4); - if (!new_skb) { - if (net_ratelimit()) { - dev_warn(fep->dev, - "Memory squeeze, dropping tx packet.\n"); - } - return NULL; - } - - /* Make sure new skb is properly aligned */ - skb_align(new_skb, 4); - - /* Copy data to new skb ... */ - skb_copy_from_linear_data(skb, new_skb->data, skb->len); - skb_put(new_skb, skb->len); - - /* ... and free an old one */ - dev_kfree_skb_any(skb); - - return new_skb; -} -#endif - static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -622,19 +595,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) u16 sc; unsigned long flags; -#ifdef CONFIG_FS_ENET_MPC5121_FEC - if (((unsigned long)skb->data) & 0x3) { - skb = tx_skb_align_workaround(dev, skb); - if (!skb) { - /* - * We have lost packet due to memory allocation error - * in tx_skb_align_workaround(). Hopefully original - * skb is still valid, so try transmit it later. - */ - return NETDEV_TX_BUSY; - } - } -#endif spin_lock_irqsave(&fep->tx_lock, flags); /* @@ -650,7 +610,8 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * Ooops. All transmit buffers are full. Bail out. * This should not happen, since the tx queue should be stopped. */ - dev_warn(fep->dev, "tx queue full!.\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s tx queue full!.\n", dev->name); return NETDEV_TX_BUSY; } @@ -827,7 +788,8 @@ static int fs_enet_open(struct net_device *dev) r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, "fs_enet-mac", dev); if (r != 0) { - dev_err(fep->dev, "Could not allocate FS_ENET IRQ!"); + printk(KERN_ERR DRV_MODULE_NAME + ": %s Could not allocate FS_ENET IRQ!", dev->name); if (fep->fpi->use_napi) napi_disable(&fep->napi); return -EINVAL; @@ -1091,7 +1053,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, if (ret) goto out_free_bd; - pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); + printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); return 0; @@ -1141,17 +1103,10 @@ static struct of_device_id fs_enet_match[] = { }, #endif #ifdef CONFIG_FS_ENET_HAS_FEC -#ifdef CONFIG_FS_ENET_MPC5121_FEC - { - .compatible = "fsl,mpc5121-fec", - .data = (void *)&fs_fec_ops, - }, -#else { .compatible = "fsl,pq1-fec-enet", .data = (void *)&fs_fec_ops, }, -#endif #endif {} }; diff --git a/trunk/drivers/net/fs_enet/fs_enet.h b/trunk/drivers/net/fs_enet/fs_enet.h index 1ece4b1a689e..ef01e09781a5 100644 --- a/trunk/drivers/net/fs_enet/fs_enet.h +++ b/trunk/drivers/net/fs_enet/fs_enet.h @@ -13,56 +13,9 @@ #ifdef CONFIG_CPM1 #include -#endif - -#if defined(CONFIG_FS_ENET_HAS_FEC) -#include - -#if defined(CONFIG_FS_ENET_MPC5121_FEC) -/* MPC5121 FEC has different register layout */ -struct fec { - u32 fec_reserved0; - u32 fec_ievent; /* Interrupt event reg */ - u32 fec_imask; /* Interrupt mask reg */ - u32 fec_reserved1; - u32 fec_r_des_active; /* Receive descriptor reg */ - u32 fec_x_des_active; /* Transmit descriptor reg */ - u32 fec_reserved2[3]; - u32 fec_ecntrl; /* Ethernet control reg */ - u32 fec_reserved3[6]; - u32 fec_mii_data; /* MII manage frame reg */ - u32 fec_mii_speed; /* MII speed control reg */ - u32 fec_reserved4[7]; - u32 fec_mib_ctrlstat; /* MIB control/status reg */ - u32 fec_reserved5[7]; - u32 fec_r_cntrl; /* Receive control reg */ - u32 fec_reserved6[15]; - u32 fec_x_cntrl; /* Transmit Control reg */ - u32 fec_reserved7[7]; - u32 fec_addr_low; /* Low 32bits MAC address */ - u32 fec_addr_high; /* High 16bits MAC address */ - u32 fec_opd; /* Opcode + Pause duration */ - u32 fec_reserved8[10]; - u32 fec_hash_table_high; /* High 32bits hash table */ - u32 fec_hash_table_low; /* Low 32bits hash table */ - u32 fec_grp_hash_table_high; /* High 32bits hash table */ - u32 fec_grp_hash_table_low; /* Low 32bits hash table */ - u32 fec_reserved9[7]; - u32 fec_x_wmrk; /* FIFO transmit water mark */ - u32 fec_reserved10; - u32 fec_r_bound; /* FIFO receive bound reg */ - u32 fec_r_fstart; /* FIFO receive start reg */ - u32 fec_reserved11[11]; - u32 fec_r_des_start; /* Receive descriptor ring */ - u32 fec_x_des_start; /* Transmit descriptor ring */ - u32 fec_r_buff_size; /* Maximum receive buff size */ - u32 fec_reserved12[26]; - u32 fec_dma_control; /* DMA Endian and other ctrl */ -}; -#endif struct fec_info { - struct fec __iomem *fecp; + fec_t __iomem *fecp; u32 mii_speed; }; #endif diff --git a/trunk/drivers/net/fs_enet/mac-fcc.c b/trunk/drivers/net/fs_enet/mac-fcc.c index cf4f674f9e2e..a761d31e3d6d 100644 --- a/trunk/drivers/net/fs_enet/mac-fcc.c +++ b/trunk/drivers/net/fs_enet/mac-fcc.c @@ -476,9 +476,8 @@ static void clear_int_events(struct net_device *dev, u32 int_events) static void ev_error(struct net_device *dev, u32 int_events) { - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "FS_ENET ERROR(s) 0x%x\n", int_events); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) diff --git a/trunk/drivers/net/fs_enet/mac-fec.c b/trunk/drivers/net/fs_enet/mac-fec.c index cd2c6cca5f24..ca806d1ab3f6 100644 --- a/trunk/drivers/net/fs_enet/mac-fec.c +++ b/trunk/drivers/net/fs_enet/mac-fec.c @@ -80,7 +80,7 @@ */ #define FEC_RESET_DELAY 50 -static int whack_reset(struct fec __iomem *fecp) +static int whack_reset(fec_t __iomem *fecp) { int i; @@ -168,7 +168,7 @@ static void cleanup_data(struct net_device *dev) static void set_promiscuous_mode(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FS(fecp, r_cntrl, FEC_RCNTRL_PROM); } @@ -216,7 +216,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac) static void set_multicast_finish(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; /* if all multi or too many multicasts; just enable all */ if ((dev->flags & IFF_ALLMULTI) != 0 || @@ -246,7 +246,7 @@ static void set_multicast_list(struct net_device *dev) static void restart(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; const struct fs_platform_info *fpi = fep->fpi; dma_addr_t rx_bd_base_phys, tx_bd_base_phys; int r; @@ -257,7 +257,8 @@ static void restart(struct net_device *dev) r = whack_reset(fep->fec.fecp); if (r != 0) - dev_err(fep->dev, "FEC Reset FAILED!\n"); + printk(KERN_ERR DRV_MODULE_NAME + ": %s FEC Reset FAILED!\n", dev->name); /* * Set station address. */ @@ -280,11 +281,7 @@ static void restart(struct net_device *dev) * Set maximum receive buffer size. */ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); -#ifdef CONFIG_FS_ENET_MPC5121_FEC - FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16); -#else FW(fecp, r_hash, PKT_MAXBUF_SIZE); -#endif /* get physical address */ rx_bd_base_phys = fep->ring_mem_addr; @@ -301,11 +298,7 @@ static void restart(struct net_device *dev) /* * Enable big endian and don't care about SDMA FC. */ -#ifdef CONFIG_FS_ENET_MPC5121_FEC - FS(fecp, dma_control, 0xC0000000); -#else FW(fecp, fun_code, 0x78000000); -#endif /* * Set MII speed. @@ -316,17 +309,9 @@ static void restart(struct net_device *dev) * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); -#ifndef CONFIG_FS_ENET_MPC5121_FEC FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ -#else - /* - * Only set MII mode - do not touch maximum frame length - * configured before. - */ - FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); -#endif /* * adjust to duplex mode */ @@ -355,7 +340,7 @@ static void stop(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); const struct fs_platform_info *fpi = fep->fpi; - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; struct fec_info* feci= fep->phydev->bus->priv; @@ -370,7 +355,9 @@ static void stop(struct net_device *dev) udelay(1); if (i == FEC_RESET_DELAY) - dev_warn(fep->dev, "FEC timeout on graceful transmit stop\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s FEC timeout on graceful transmit stop\n", + dev->name); /* * Disable FEC. Let only MII interrupts. */ @@ -391,7 +378,7 @@ static void stop(struct net_device *dev) static void napi_clear_rx_event(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); } @@ -399,7 +386,7 @@ static void napi_clear_rx_event(struct net_device *dev) static void napi_enable_rx(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); } @@ -407,7 +394,7 @@ static void napi_enable_rx(struct net_device *dev) static void napi_disable_rx(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); } @@ -415,7 +402,7 @@ static void napi_disable_rx(struct net_device *dev) static void rx_bd_done(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FW(fecp, r_des_active, 0x01000000); } @@ -423,7 +410,7 @@ static void rx_bd_done(struct net_device *dev) static void tx_kickstart(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FW(fecp, x_des_active, 0x01000000); } @@ -431,7 +418,7 @@ static void tx_kickstart(struct net_device *dev) static u32 get_int_events(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; return FR(fecp, ievent) & FR(fecp, imask); } @@ -439,33 +426,32 @@ static u32 get_int_events(struct net_device *dev) static void clear_int_events(struct net_device *dev, u32 int_events) { struct fs_enet_private *fep = netdev_priv(dev); - struct fec __iomem *fecp = fep->fec.fecp; + fec_t __iomem *fecp = fep->fec.fecp; FW(fecp, ievent, int_events); } static void ev_error(struct net_device *dev, u32 int_events) { - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "FEC ERROR(s) 0x%x\n", int_events); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) { struct fs_enet_private *fep = netdev_priv(dev); - if (*sizep < sizeof(struct fec)) + if (*sizep < sizeof(fec_t)) return -EINVAL; - memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec)); + memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t)); return 0; } static int get_regs_len(struct net_device *dev) { - return sizeof(struct fec); + return sizeof(fec_t); } static void tx_restart(struct net_device *dev) diff --git a/trunk/drivers/net/fs_enet/mac-scc.c b/trunk/drivers/net/fs_enet/mac-scc.c index c490a466cae1..5bfc99b9475e 100644 --- a/trunk/drivers/net/fs_enet/mac-scc.c +++ b/trunk/drivers/net/fs_enet/mac-scc.c @@ -367,7 +367,9 @@ static void stop(struct net_device *dev) udelay(1); if (i == SCC_RESET_DELAY) - dev_warn(fep->dev, "SCC timeout on graceful transmit stop\n"); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s SCC timeout on graceful transmit stop\n", + dev->name); W16(sccp, scc_sccm, 0); C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); @@ -427,9 +429,8 @@ static void clear_int_events(struct net_device *dev, u32 int_events) static void ev_error(struct net_device *dev, u32 int_events) { - struct fs_enet_private *fep = netdev_priv(dev); - - dev_warn(fep->dev, "SCC ERROR(s) 0x%x\n", int_events); + printk(KERN_WARNING DRV_MODULE_NAME + ": %s SCC ERROR(s) 0x%x\n", dev->name, int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) diff --git a/trunk/drivers/net/fs_enet/mii-fec.c b/trunk/drivers/net/fs_enet/mii-fec.c index 5944b65082cb..96eba4280c5c 100644 --- a/trunk/drivers/net/fs_enet/mii-fec.c +++ b/trunk/drivers/net/fs_enet/mii-fec.c @@ -52,7 +52,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) { struct fec_info* fec = bus->priv; - struct fec __iomem *fecp = fec->fecp; + fec_t __iomem *fecp = fec->fecp; int i, ret = -1; BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); @@ -75,7 +75,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) { struct fec_info* fec = bus->priv; - struct fec __iomem *fecp = fec->fecp; + fec_t __iomem *fecp = fec->fecp; int i; /* this must never happen */ diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 45e3532b166f..a961da2f98c0 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -5639,14 +5639,8 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) return txq; } #endif - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - if (skb->priority == TC_PRIO_CONTROL) - txq = adapter->ring_feature[RING_F_DCB].indices-1; - else - txq = (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) - >> 13; - return txq; - } + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) + return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13; return skb_tx_hash(dev, skb); } @@ -5673,9 +5667,14 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; tx_flags |= IXGBE_TX_FLAGS_VLAN; } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - tx_flags |= ((skb->queue_mapping & 0x7) << 13); - tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; - tx_flags |= IXGBE_TX_FLAGS_VLAN; + if (skb->priority != TC_PRIO_CONTROL) { + tx_flags |= ((skb->queue_mapping & 0x7) << 13); + tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; + tx_flags |= IXGBE_TX_FLAGS_VLAN; + } else { + skb->queue_mapping = + adapter->ring_feature[RING_F_DCB].indices-1; + } } tx_ring = adapter->tx_ring[skb->queue_mapping]; diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 0fa7688ab483..0d06e4007f44 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -12547,8 +12547,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[TG3_NVM_VPD_LEN]; /* in little-endian format */ - unsigned int block_end, rosize, len; - int i = 0; + unsigned int i; u32 magic; if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || @@ -12570,7 +12569,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } } else { ssize_t cnt; - unsigned int pos = 0; + unsigned int pos = 0, i = 0; for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) { cnt = pci_read_vpd(tp->pdev, pos, @@ -12585,33 +12584,51 @@ static void __devinit tg3_read_partno(struct tg3 *tp) goto out_not_found; } - i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN, - PCI_VPD_LRDT_RO_DATA); - if (i < 0) - goto out_not_found; + /* Now parse and find the part number. */ + for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) { + unsigned char val = vpd_data[i]; + unsigned int block_end; + + if (val == 0x82 || val == 0x91) { + i = (i + 3 + + (vpd_data[i + 1] + + (vpd_data[i + 2] << 8))); + continue; + } - rosize = pci_vpd_lrdt_size(&vpd_data[i]); - block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; - i += PCI_VPD_LRDT_TAG_SIZE; + if (val != 0x90) + goto out_not_found; - if (block_end > TG3_NVM_VPD_LEN) - goto out_not_found; + block_end = (i + 3 + + (vpd_data[i + 1] + + (vpd_data[i + 2] << 8))); + i += 3; - i = pci_vpd_find_info_keyword(vpd_data, i, rosize, - PCI_VPD_RO_KEYWORD_PARTNO); - if (i < 0) - goto out_not_found; + if (block_end > TG3_NVM_VPD_LEN) + goto out_not_found; - len = pci_vpd_info_field_size(&vpd_data[i]); + while (i < (block_end - 2)) { + if (vpd_data[i + 0] == 'P' && + vpd_data[i + 1] == 'N') { + int partno_len = vpd_data[i + 2]; - i += PCI_VPD_INFO_FLD_HDR_SIZE; - if (len > TG3_BPN_SIZE || - (len + i) > TG3_NVM_VPD_LEN) - goto out_not_found; + i += 3; + if (partno_len > TG3_BPN_SIZE || + (partno_len + i) > TG3_NVM_VPD_LEN) + goto out_not_found; - memcpy(tp->board_part_number, &vpd_data[i], len); + memcpy(tp->board_part_number, + &vpd_data[i], partno_len); + + /* Success. */ + return; + } + i += 3 + vpd_data[i + 2]; + } - return; + /* Part number not found. */ + goto out_not_found; + } out_not_found: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) diff --git a/trunk/drivers/net/veth.c b/trunk/drivers/net/veth.c index b583d4968add..35609e64f6fd 100644 --- a/trunk/drivers/net/veth.c +++ b/trunk/drivers/net/veth.c @@ -333,17 +333,19 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, struct veth_priv *priv; char ifname[IFNAMSIZ]; struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; - struct ifinfomsg *ifmp; struct net *net; /* * create and register peer first + * + * struct ifinfomsg is at the head of VETH_INFO_PEER, but we + * skip it since no info from it is useful yet */ + if (data != NULL && data[VETH_INFO_PEER] != NULL) { struct nlattr *nla_peer; nla_peer = data[VETH_INFO_PEER]; - ifmp = nla_data(nla_peer); err = nla_parse(peer_tb, IFLA_MAX, nla_data(nla_peer) + sizeof(struct ifinfomsg), nla_len(nla_peer) - sizeof(struct ifinfomsg), @@ -356,10 +358,8 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, return err; tbp = peer_tb; - } else { - ifmp = NULL; + } else tbp = tb; - } if (tbp[IFLA_IFNAME]) nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ); @@ -387,10 +387,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, netif_carrier_off(peer); - err = rtnl_configure_link(peer, ifmp); - if (err < 0) - goto err_configure_peer; - /* * register dev last * @@ -432,7 +428,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, err_register_dev: /* nothing to do */ err_alloc_name: -err_configure_peer: unregister_netdevice(peer); return err; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 2e767cf22f1e..f00f5c744f48 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -1310,16 +1310,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, * Necessary to avoid issues on AR5416 2.0 */ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); - - /* - * Disable RIFS search on some chips to avoid baseband - * hang issues. - */ - if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { - val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); - val &= ~AR_PHY_RIFS_INIT_DELAY; - REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); - } } static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, diff --git a/trunk/drivers/net/wireless/ath/ath9k/phy.h b/trunk/drivers/net/wireless/ath/ath9k/phy.h index 0999a495fd46..31de27dc0c4a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/phy.h @@ -384,9 +384,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 -#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC -#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 - #define AR_PHY_M_SLEEP 0x99f0 #define AR_PHY_REFCLKDLY 0x99f4 #define AR_PHY_REFCLKPD 0x99f8 diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index 0a00d42642cd..073be566d05e 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -3,6 +3,7 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && HAS_DMA select SSB select FW_LOADER + select SSB_BLOCKIO ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -78,14 +79,6 @@ config B43_SDIO If unsure, say N. -#Data transfers to the device via PIO. We want it as a fallback even -# if we can do DMA. -config B43_PIO - bool - depends on B43 - select SSB_BLOCKIO - default y - config B43_NPHY bool "Pre IEEE 802.11n support (BROKEN)" depends on B43 && EXPERIMENTAL && BROKEN @@ -137,12 +130,4 @@ config B43_DEBUG for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. -config B43_FORCE_PIO - bool "Force usage of PIO instead of DMA" - depends on B43 && B43_DEBUG - ---help--- - This will disable DMA and always enable PIO instead. - Say N! - This is only for debugging the PIO engine code. You do - _NOT_ want to enable this. diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index b8807fb12c92..6a6ab0f630e5 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -702,7 +702,6 @@ struct b43_wldev { bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool qos_enabled; /* TRUE, if QoS is used. */ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ - bool use_pio; /* TRUE if next init should use PIO */ /* PHY/Radio device. */ struct b43_phy phy; @@ -887,12 +886,6 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev) return dev->__using_pio_transfers; } -#ifdef CONFIG_B43_FORCE_PIO -# define B43_PIO_DEFAULT 1 -#else -# define B43_PIO_DEFAULT 0 -#endif - /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 1521b1e78d21..aa33d741e5e6 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -107,9 +107,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -int b43_modparam_pio = B43_PIO_DEFAULT; -module_param_named(pio, b43_modparam_pio, int, 0644); -MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); +static int modparam_pio; +module_param_named(pio, modparam_pio, int, 0444); +MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -1804,9 +1804,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) dma_reason[4], dma_reason[5]); b43err(dev->wl, "This device does not support DMA " "on your system. Please use PIO instead.\n"); - /* Fall back to PIO transfers if we get fatal DMA errors! */ - dev->use_pio = 1; - b43_controller_restart(dev, "DMA error"); + b43err(dev->wl, "Unload the b43 module and reload " + "with 'pio=1'\n"); return; } if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { @@ -4358,7 +4357,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - dev->use_pio) { + modparam_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { @@ -4825,7 +4824,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) if (!wldev) goto out; - wldev->use_pio = b43_modparam_pio; wldev->dev = dev; wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index 6aeb82b6992f..af60b178ad4b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - return iwl_tx_agg_start(priv, sta->addr, tid, ssn); + ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); + if (ret == 0) { + priv->agg_tids_count++; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); + } + return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwl_tx_agg_stop(priv, sta->addr, tid); + if ((ret == 0) && (priv->agg_tids_count > 0)) { + priv->agg_tids_count--; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); + } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else @@ -3365,6 +3376,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; + priv->agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..ab3c77b92cc8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2623,7 +2623,6 @@ struct iwl_ssid_ie { #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 -#define IWL_MAX_CMD_SIZE 4096 #define IWL_MAX_PROBE_REQUEST 200 /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index ab891b958042..7914d65a5a55 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1084,6 +1084,9 @@ struct iwl_priv { /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; + /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ + u8 agg_tids_count; + /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index df257bc15f49..0d09f571e185 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) +/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ +#define ACK_CNT_RATIO (50) +#define BA_TIMEOUT_CNT (5) +#define BA_TIMEOUT_MAX (16) + #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -625,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; + int actual_ack_cnt_delta; + int expected_ack_cnt_delta; + int ba_timeout_delta; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), @@ -639,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif + actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - + le32_to_cpu(priv->statistics.tx.actual_ack_cnt); + expected_ack_cnt_delta = le32_to_cpu( + pkt->u.stats.tx.expected_ack_cnt) - + le32_to_cpu(priv->statistics.tx.expected_ack_cnt); + ba_timeout_delta = le32_to_cpu( + pkt->u.stats.tx.agg.ba_timeout) - + le32_to_cpu(priv->statistics.tx.agg.ba_timeout); + if ((priv->agg_tids_count > 0) && + (expected_ack_cnt_delta > 0) && + (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < + ACK_CNT_RATIO) && + (ba_timeout_delta > BA_TIMEOUT_CNT)) { + IWL_DEBUG_RADIO(priv, + "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", + actual_ack_cnt_delta, expected_ack_cnt_delta); + +#ifdef CONFIG_IWLWIFI_DEBUG + IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", + priv->delta_statistics.tx.rx_detected_cnt); + IWL_DEBUG_RADIO(priv, + "ack_or_ba_timeout_collision delta = %d\n", + priv->delta_statistics.tx.ack_or_ba_timeout_collision); +#endif + IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", + ba_timeout_delta); + if ((actual_ack_cnt_delta == 0) && + (ba_timeout_delta >= + BA_TIMEOUT_MAX)) { + IWL_DEBUG_RADIO(priv, + "call iwl_force_reset(IWL_FW_RESET)\n"); + iwl_force_reset(priv, IWL_FW_RESET); + } else { + IWL_DEBUG_RADIO(priv, + "call iwl_force_reset(IWL_RF_RESET)\n"); + iwl_force_reset(priv, IWL_RF_RESET); + } + } /* * check for plcp_err and trigger radio reset if it exceeds * the plcp error threshold plcp_delta. diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c index 1ed5206721ec..10701b8eef23 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -364,7 +364,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, for (i = 0; i < actual_slots; i++) { /* only happens for cmd queue */ if (i == slots_num) - len = IWL_MAX_CMD_SIZE; + len += IWL_MAX_SCAN_SIZE; txq->cmd[i] = kmalloc(len, GFP_KERNEL); if (!txq->cmd[i]) @@ -1023,12 +1023,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries - * Also, check to see if command buffer should not exceed the size - * of device_cmd and max_cmd_size. */ + * we will need to increase the size of the TFD entries */ BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->flags & CMD_SIZE_HUGE)); - BUG_ON(fix_size > IWL_MAX_CMD_SIZE); if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", @@ -1072,8 +1069,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; len = sizeof(struct iwl_device_cmd); - if (idx == TFD_CMD_SLOTS) - len = IWL_MAX_CMD_SIZE; + len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; + #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { diff --git a/trunk/drivers/pci/Makefile b/trunk/drivers/pci/Makefile index b2f6d777a084..4df48d58eaa6 100644 --- a/trunk/drivers/pci/Makefile +++ b/trunk/drivers/pci/Makefile @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ - irq.o vpd.o + irq.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSFS) += slot.o diff --git a/trunk/drivers/pci/vpd.c b/trunk/drivers/pci/vpd.c deleted file mode 100644 index a5a5ca17cfe6..000000000000 --- a/trunk/drivers/pci/vpd.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * File: vpd.c - * Purpose: Provide PCI VPD support - * - * Copyright (C) 2010 Broadcom Corporation. - */ - -#include - -int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt) -{ - int i; - - for (i = off; i < len; ) { - u8 val = buf[i]; - - if (val & PCI_VPD_LRDT) { - /* Don't return success of the tag isn't complete */ - if (i + PCI_VPD_LRDT_TAG_SIZE > len) - break; - - if (val == rdt) - return i; - - i += PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&buf[i]); - } else { - u8 tag = val & ~PCI_VPD_SRDT_LEN_MASK; - - if (tag == rdt) - return i; - - if (tag == PCI_VPD_SRDT_END) - break; - - i += PCI_VPD_SRDT_TAG_SIZE + - pci_vpd_srdt_size(&buf[i]); - } - } - - return -ENOENT; -} -EXPORT_SYMBOL_GPL(pci_vpd_find_tag); - -int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, - unsigned int len, const char *kw) -{ - int i; - - for (i = off; i + PCI_VPD_INFO_FLD_HDR_SIZE <= off + len;) { - if (buf[i + 0] == kw[0] && - buf[i + 1] == kw[1]) - return i; - - i += PCI_VPD_INFO_FLD_HDR_SIZE + - pci_vpd_info_field_size(&buf[i]); - } - - return -ENOENT; -} -EXPORT_SYMBOL_GPL(pci_vpd_find_info_keyword); diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index c79a88be7c33..682d02521bbc 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -137,7 +137,7 @@ static inline bool dev_xmit_complete(int rc) * used. */ -#if defined(CONFIG_WLAN) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +#if defined(CONFIG_WLAN_80211) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else @@ -924,12 +924,7 @@ struct net_device { NETREG_UNREGISTERED, /* completed unregister todo */ NETREG_RELEASED, /* called free_netdev */ NETREG_DUMMY, /* dummy device for NAPI poll */ - } reg_state:16; - - enum { - RTNL_LINK_INITIALIZED, - RTNL_LINK_INITIALIZING, - } rtnl_link_state:16; + } reg_state; /* Called from unregister, can be used to call free_netdev */ void (*destructor)(struct net_device *dev); @@ -1587,9 +1582,7 @@ extern int dev_valid_name(const char *name); extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); extern int dev_ethtool(struct net *net, struct ifreq *); extern unsigned dev_get_flags(const struct net_device *); -extern int __dev_change_flags(struct net_device *, unsigned int flags); extern int dev_change_flags(struct net_device *, unsigned); -extern void __dev_notify_flags(struct net_device *, unsigned int old_flags); extern int dev_change_name(struct net_device *, const char *); extern int dev_set_alias(struct net_device *, const char *, size_t); extern int dev_change_net_namespace(struct net_device *, diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 1f4a52131c99..e2575f86133a 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -1349,93 +1349,5 @@ static inline bool pci_is_pcie(struct pci_dev *dev) void pci_request_acs(void); - -#define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */ -#define PCI_VPD_LRDT_ID(x) (x | PCI_VPD_LRDT) - -/* Large Resource Data Type Tag Item Names */ -#define PCI_VPD_LTIN_ID_STRING 0x02 /* Identifier String */ -#define PCI_VPD_LTIN_RO_DATA 0x10 /* Read-Only Data */ -#define PCI_VPD_LTIN_RW_DATA 0x11 /* Read-Write Data */ - -#define PCI_VPD_LRDT_ID_STRING PCI_VPD_LRDT_ID(PCI_VPD_LTIN_ID_STRING) -#define PCI_VPD_LRDT_RO_DATA PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RO_DATA) -#define PCI_VPD_LRDT_RW_DATA PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA) - -/* Small Resource Data Type Tag Item Names */ -#define PCI_VPD_STIN_END 0x78 /* End */ - -#define PCI_VPD_SRDT_END PCI_VPD_STIN_END - -#define PCI_VPD_SRDT_TIN_MASK 0x78 -#define PCI_VPD_SRDT_LEN_MASK 0x07 - -#define PCI_VPD_LRDT_TAG_SIZE 3 -#define PCI_VPD_SRDT_TAG_SIZE 1 - -#define PCI_VPD_INFO_FLD_HDR_SIZE 3 - -#define PCI_VPD_RO_KEYWORD_PARTNO "PN" -#define PCI_VPD_RO_KEYWORD_MFR_ID "MN" -#define PCI_VPD_RO_KEYWORD_VENDOR0 "V0" - -/** - * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length - * @lrdt: Pointer to the beginning of the Large Resource Data Type tag - * - * Returns the extracted Large Resource Data Type length. - */ -static inline u16 pci_vpd_lrdt_size(const u8 *lrdt) -{ - return (u16)lrdt[1] + ((u16)lrdt[2] << 8); -} - -/** - * pci_vpd_srdt_size - Extracts the Small Resource Data Type length - * @lrdt: Pointer to the beginning of the Small Resource Data Type tag - * - * Returns the extracted Small Resource Data Type length. - */ -static inline u8 pci_vpd_srdt_size(const u8 *srdt) -{ - return (*srdt) & PCI_VPD_SRDT_LEN_MASK; -} - -/** - * pci_vpd_info_field_size - Extracts the information field length - * @lrdt: Pointer to the beginning of an information field header - * - * Returns the extracted information field length. - */ -static inline u8 pci_vpd_info_field_size(const u8 *info_field) -{ - return info_field[2]; -} - -/** - * pci_vpd_find_tag - Locates the Resource Data Type tag provided - * @buf: Pointer to buffered vpd data - * @off: The offset into the buffer at which to begin the search - * @len: The length of the vpd buffer - * @rdt: The Resource Data Type to search for - * - * Returns the index where the Resource Data Type was found or - * -ENOENT otherwise. - */ -int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt); - -/** - * pci_vpd_find_info_keyword - Locates an information field keyword in the VPD - * @buf: Pointer to buffered vpd data - * @off: The offset into the buffer at which to begin the search - * @len: The length of the buffer area, relative to off, in which to search - * @kw: The keyword to search for - * - * Returns the index where the information field keyword was found or - * -ENOENT otherwise. - */ -int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, - unsigned int len, const char *kw); - #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index d266eeef522d..ba0f8e3a9cda 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -315,23 +315,22 @@ struct sk_buff { struct sk_buff *next; struct sk_buff *prev; - ktime_t tstamp; - struct sock *sk; + ktime_t tstamp; struct net_device *dev; + unsigned long _skb_dst; +#ifdef CONFIG_XFRM + struct sec_path *sp; +#endif /* * This is the control buffer. It is free to use for every * layer. Please put your private variables there. If you * want to keep them across layers you have to do a skb_clone() * first. This is owned by whoever has the skb queued ATM. */ - char cb[48] __aligned(8); + char cb[48]; - unsigned long _skb_dst; -#ifdef CONFIG_XFRM - struct sec_path *sp; -#endif unsigned int len, data_len; __u16 mac_len, diff --git a/trunk/include/net/rtnetlink.h b/trunk/include/net/rtnetlink.h index af60fd050844..48d3efcb0880 100644 --- a/trunk/include/net/rtnetlink.h +++ b/trunk/include/net/rtnetlink.h @@ -87,8 +87,6 @@ extern void rtnl_link_unregister(struct rtnl_link_ops *ops); extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net, char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]); -extern int rtnl_configure_link(struct net_device *dev, - const struct ifinfomsg *ifm); extern const struct nla_policy ifla_policy[IFLA_MAX+1]; #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) diff --git a/trunk/net/bridge/Kconfig b/trunk/net/bridge/Kconfig index 19a6b9629c51..e143ca678881 100644 --- a/trunk/net/bridge/Kconfig +++ b/trunk/net/bridge/Kconfig @@ -31,16 +31,3 @@ config BRIDGE will be called bridge. If unsure, say N. - -config BRIDGE_IGMP_SNOOPING - bool "IGMP snooping" - depends on BRIDGE - default y - ---help--- - If you say Y here, then the Ethernet bridge will be able selectively - forward multicast traffic based on IGMP traffic received from each - port. - - Say N to exclude this support and reduce the binary size. - - If unsure, say Y. diff --git a/trunk/net/bridge/Makefile b/trunk/net/bridge/Makefile index d0359ea8ee79..f444c12cde5a 100644 --- a/trunk/net/bridge/Makefile +++ b/trunk/net/bridge/Makefile @@ -12,6 +12,4 @@ bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o -bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o - obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/ diff --git a/trunk/net/bridge/br_device.c b/trunk/net/bridge/br_device.c index eb7062d2e9e5..1a99c4e04e85 100644 --- a/trunk/net/bridge/br_device.c +++ b/trunk/net/bridge/br_device.c @@ -25,9 +25,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct net_bridge *br = netdev_priv(dev); const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; - struct net_bridge_mdb_entry *mdst; - - BR_INPUT_SKB_CB(skb)->brdev = dev; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -35,21 +32,13 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); - if (dest[0] & 1) { - if (br_multicast_rcv(br, NULL, skb)) - goto out; - - mdst = br_mdb_get(br, skb); - if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) - br_multicast_deliver(mdst, skb); - else - br_flood_deliver(br, skb); - } else if ((dst = __br_fdb_get(br, dest)) != NULL) + if (dest[0] & 1) + br_flood_deliver(br, skb); + else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); else br_flood_deliver(br, skb); -out: return NETDEV_TX_OK; } @@ -60,7 +49,6 @@ static int br_dev_open(struct net_device *dev) br_features_recompute(br); netif_start_queue(dev); br_stp_enable_bridge(br); - br_multicast_open(br); return 0; } @@ -71,10 +59,7 @@ static void br_dev_set_multicast_list(struct net_device *dev) static int br_dev_stop(struct net_device *dev) { - struct net_bridge *br = netdev_priv(dev); - - br_stp_disable_bridge(br); - br_multicast_stop(br); + br_stp_disable_bridge(netdev_priv(dev)); netif_stop_queue(dev); diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index d61e6f741125..bc1704ac6cd9 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -11,7 +11,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include #include @@ -104,49 +103,10 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) kfree_skb(skb); } -static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, - void (*__packet_hook)(const struct net_bridge_port *p, - struct sk_buff *skb)) -{ - skb = skb_clone(skb, GFP_ATOMIC); - if (!skb) { - struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; - - dev->stats.tx_dropped++; - return -ENOMEM; - } - - __packet_hook(prev, skb); - return 0; -} - -static struct net_bridge_port *maybe_deliver( - struct net_bridge_port *prev, struct net_bridge_port *p, - struct sk_buff *skb, - void (*__packet_hook)(const struct net_bridge_port *p, - struct sk_buff *skb)) -{ - int err; - - if (!should_deliver(p, skb)) - return prev; - - if (!prev) - goto out; - - err = deliver_clone(prev, skb, __packet_hook); - if (err) - return ERR_PTR(err); - -out: - return p; -} - /* called under bridge lock */ static void br_flood(struct net_bridge *br, struct sk_buff *skb, - struct sk_buff *skb0, - void (*__packet_hook)(const struct net_bridge_port *p, - struct sk_buff *skb)) + void (*__packet_hook)(const struct net_bridge_port *p, + struct sk_buff *skb)) { struct net_bridge_port *p; struct net_bridge_port *prev; @@ -154,102 +114,40 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, prev = NULL; list_for_each_entry_rcu(p, &br->port_list, list) { - prev = maybe_deliver(prev, p, skb, __packet_hook); - if (IS_ERR(prev)) - goto out; - } - - if (!prev) - goto out; - - if (skb0) - deliver_clone(prev, skb, __packet_hook); - else - __packet_hook(prev, skb); - return; - -out: - if (!skb0) - kfree_skb(skb); -} - + if (should_deliver(p, skb)) { + if (prev != NULL) { + struct sk_buff *skb2; -/* called with rcu_read_lock */ -void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) -{ - br_flood(br, skb, NULL, __br_deliver); -} - -/* called under bridge lock */ -void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, - struct sk_buff *skb2) -{ - br_flood(br, skb, skb2, __br_forward); -} - -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING -/* called with rcu_read_lock */ -static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb, struct sk_buff *skb0, - void (*__packet_hook)( - const struct net_bridge_port *p, - struct sk_buff *skb)) -{ - struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; - struct net_bridge *br = netdev_priv(dev); - struct net_bridge_port *port; - struct net_bridge_port *lport, *rport; - struct net_bridge_port *prev; - struct net_bridge_port_group *p; - struct hlist_node *rp; - - prev = NULL; - - rp = br->router_list.first; - p = mdst ? mdst->ports : NULL; - while (p || rp) { - lport = p ? p->port : NULL; - rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : - NULL; + if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { + br->dev->stats.tx_dropped++; + kfree_skb(skb); + return; + } - port = (unsigned long)lport > (unsigned long)rport ? - lport : rport; + __packet_hook(prev, skb2); + } - prev = maybe_deliver(prev, port, skb, __packet_hook); - if (IS_ERR(prev)) - goto out; - - if ((unsigned long)lport >= (unsigned long)port) - p = p->next; - if ((unsigned long)rport >= (unsigned long)port) - rp = rp->next; + prev = p; + } } - if (!prev) - goto out; - - if (skb0) - deliver_clone(prev, skb, __packet_hook); - else + if (prev != NULL) { __packet_hook(prev, skb); - return; + return; + } -out: - if (!skb0) - kfree_skb(skb); + kfree_skb(skb); } + /* called with rcu_read_lock */ -void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb) +void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) { - br_multicast_flood(mdst, skb, NULL, __br_deliver); + br_flood(br, skb, __br_deliver); } -/* called with rcu_read_lock */ -void br_multicast_forward(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb, struct sk_buff *skb2) +/* called under bridge lock */ +void br_flood_forward(struct net_bridge *br, struct sk_buff *skb) { - br_multicast_flood(mdst, skb, skb2, __br_forward); + br_flood(br, skb, __br_forward); } -#endif diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index b6a3872f5681..bc2b1badab88 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -147,8 +147,6 @@ static void del_nbp(struct net_bridge_port *p) rcu_assign_pointer(dev->br_port, NULL); - br_multicast_del_port(p); - kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); @@ -209,7 +207,6 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name) br_netfilter_rtable_init(br); br_stp_timer_init(br); - br_multicast_init(br); return dev; } @@ -261,7 +258,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, br_init_port(p); p->state = BR_STATE_DISABLED; br_stp_port_timer_init(p); - br_multicast_add_port(p); return p; } diff --git a/trunk/net/bridge/br_input.c b/trunk/net/bridge/br_input.c index 53b39851d87d..5ee1a3682bf2 100644 --- a/trunk/net/bridge/br_input.c +++ b/trunk/net/bridge/br_input.c @@ -20,9 +20,9 @@ /* Bridge group multicast address 802.1d (pg 51). */ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; -static int br_pass_frame_up(struct sk_buff *skb) +static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) { - struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; + struct net_device *indev, *brdev = br->dev; brdev->stats.rx_packets++; brdev->stats.rx_bytes += skb->len; @@ -30,8 +30,8 @@ static int br_pass_frame_up(struct sk_buff *skb) indev = skb->dev; skb->dev = brdev; - return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, - netif_receive_skb); + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, + netif_receive_skb); } /* note: already called with rcu_read_lock (preempt_disabled) */ @@ -41,7 +41,6 @@ int br_handle_frame_finish(struct sk_buff *skb) struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); struct net_bridge *br; struct net_bridge_fdb_entry *dst; - struct net_bridge_mdb_entry *mdst; struct sk_buff *skb2; if (!p || p->state == BR_STATE_DISABLED) @@ -51,15 +50,9 @@ int br_handle_frame_finish(struct sk_buff *skb) br = p->br; br_fdb_update(br, p, eth_hdr(skb)->h_source); - if (is_multicast_ether_addr(dest) && - br_multicast_rcv(br, p, skb)) - goto drop; - if (p->state == BR_STATE_LEARNING) goto drop; - BR_INPUT_SKB_CB(skb)->brdev = br->dev; - /* The packet skb2 goes to the local host (NULL to skip). */ skb2 = NULL; @@ -69,35 +62,27 @@ int br_handle_frame_finish(struct sk_buff *skb) dst = NULL; if (is_multicast_ether_addr(dest)) { - mdst = br_mdb_get(br, skb); - if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) { - if ((mdst && !hlist_unhashed(&mdst->mglist)) || - br_multicast_is_router(br)) - skb2 = skb; - br_multicast_forward(mdst, skb, skb2); - skb = NULL; - if (!skb2) - goto out; - } else - skb2 = skb; - br->dev->stats.multicast++; + skb2 = skb; } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { skb2 = skb; /* Do not forward the packet since it's local. */ skb = NULL; } + if (skb2 == skb) + skb2 = skb_clone(skb, GFP_ATOMIC); + + if (skb2) + br_pass_frame_up(br, skb2); + if (skb) { if (dst) br_forward(dst->dst, skb); else - br_flood_forward(br, skb, skb2); + br_flood_forward(br, skb); } - if (skb2) - return br_pass_frame_up(skb2); - out: return 0; drop: diff --git a/trunk/net/bridge/br_multicast.c b/trunk/net/bridge/br_multicast.c deleted file mode 100644 index 2559fb539836..000000000000 --- a/trunk/net/bridge/br_multicast.c +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * Bridge multicast support. - * - * Copyright (c) 2010 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "br_private.h" - -static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) -{ - return jhash_1word(mdb->secret, (u32)ip) & (mdb->max - 1); -} - -static struct net_bridge_mdb_entry *__br_mdb_ip_get( - struct net_bridge_mdb_htable *mdb, __be32 dst, int hash) -{ - struct net_bridge_mdb_entry *mp; - struct hlist_node *p; - - hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { - if (dst == mp->addr) - return mp; - } - - return NULL; -} - -static struct net_bridge_mdb_entry *br_mdb_ip_get( - struct net_bridge_mdb_htable *mdb, __be32 dst) -{ - return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); -} - -struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, - struct sk_buff *skb) -{ - struct net_bridge_mdb_htable *mdb = br->mdb; - - if (!mdb || br->multicast_disabled) - return NULL; - - switch (skb->protocol) { - case htons(ETH_P_IP): - if (BR_INPUT_SKB_CB(skb)->igmp) - break; - return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr); - } - - return NULL; -} - -static void br_mdb_free(struct rcu_head *head) -{ - struct net_bridge_mdb_htable *mdb = - container_of(head, struct net_bridge_mdb_htable, rcu); - struct net_bridge_mdb_htable *old = mdb->old; - - mdb->old = NULL; - kfree(old->mhash); - kfree(old); -} - -static int br_mdb_copy(struct net_bridge_mdb_htable *new, - struct net_bridge_mdb_htable *old, - int elasticity) -{ - struct net_bridge_mdb_entry *mp; - struct hlist_node *p; - int maxlen; - int len; - int i; - - for (i = 0; i < old->max; i++) - hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) - hlist_add_head(&mp->hlist[new->ver], - &new->mhash[br_ip_hash(new, mp->addr)]); - - if (!elasticity) - return 0; - - maxlen = 0; - for (i = 0; i < new->max; i++) { - len = 0; - hlist_for_each_entry(mp, p, &new->mhash[i], hlist[new->ver]) - len++; - if (len > maxlen) - maxlen = len; - } - - return maxlen > elasticity ? -EINVAL : 0; -} - -static void br_multicast_free_pg(struct rcu_head *head) -{ - struct net_bridge_port_group *p = - container_of(head, struct net_bridge_port_group, rcu); - - kfree(p); -} - -static void br_multicast_free_group(struct rcu_head *head) -{ - struct net_bridge_mdb_entry *mp = - container_of(head, struct net_bridge_mdb_entry, rcu); - - kfree(mp); -} - -static void br_multicast_group_expired(unsigned long data) -{ - struct net_bridge_mdb_entry *mp = (void *)data; - struct net_bridge *br = mp->br; - struct net_bridge_mdb_htable *mdb; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || timer_pending(&mp->timer)) - goto out; - - if (!hlist_unhashed(&mp->mglist)) - hlist_del_init(&mp->mglist); - - if (mp->ports) - goto out; - - mdb = br->mdb; - hlist_del_rcu(&mp->hlist[mdb->ver]); - mdb->size--; - - del_timer(&mp->query_timer); - call_rcu_bh(&mp->rcu, br_multicast_free_group); - -out: - spin_unlock(&br->multicast_lock); -} - -static void br_multicast_del_pg(struct net_bridge *br, - struct net_bridge_port_group *pg) -{ - struct net_bridge_mdb_htable *mdb = br->mdb; - struct net_bridge_mdb_entry *mp; - struct net_bridge_port_group *p; - struct net_bridge_port_group **pp; - - mp = br_mdb_ip_get(mdb, pg->addr); - if (WARN_ON(!mp)) - return; - - for (pp = &mp->ports; (p = *pp); pp = &p->next) { - if (p != pg) - continue; - - *pp = p->next; - hlist_del_init(&p->mglist); - del_timer(&p->timer); - del_timer(&p->query_timer); - call_rcu_bh(&p->rcu, br_multicast_free_pg); - - if (!mp->ports && hlist_unhashed(&mp->mglist) && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - - return; - } - - WARN_ON(1); -} - -static void br_multicast_port_group_expired(unsigned long data) -{ - struct net_bridge_port_group *pg = (void *)data; - struct net_bridge *br = pg->port->br; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || timer_pending(&pg->timer) || - hlist_unhashed(&pg->mglist)) - goto out; - - br_multicast_del_pg(br, pg); - -out: - spin_unlock(&br->multicast_lock); -} - -static int br_mdb_rehash(struct net_bridge_mdb_htable **mdbp, int max, - int elasticity) -{ - struct net_bridge_mdb_htable *old = *mdbp; - struct net_bridge_mdb_htable *mdb; - int err; - - mdb = kmalloc(sizeof(*mdb), GFP_ATOMIC); - if (!mdb) - return -ENOMEM; - - mdb->max = max; - mdb->old = old; - - mdb->mhash = kzalloc(max * sizeof(*mdb->mhash), GFP_ATOMIC); - if (!mdb->mhash) { - kfree(mdb); - return -ENOMEM; - } - - mdb->size = old ? old->size : 0; - mdb->ver = old ? old->ver ^ 1 : 0; - - if (!old || elasticity) - get_random_bytes(&mdb->secret, sizeof(mdb->secret)); - else - mdb->secret = old->secret; - - if (!old) - goto out; - - err = br_mdb_copy(mdb, old, elasticity); - if (err) { - kfree(mdb->mhash); - kfree(mdb); - return err; - } - - call_rcu_bh(&mdb->rcu, br_mdb_free); - -out: - rcu_assign_pointer(*mdbp, mdb); - - return 0; -} - -static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, - __be32 group) -{ - struct sk_buff *skb; - struct igmphdr *ih; - struct ethhdr *eth; - struct iphdr *iph; - - skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) + - sizeof(*ih) + 4); - if (!skb) - goto out; - - skb->protocol = htons(ETH_P_IP); - - skb_reset_mac_header(skb); - eth = eth_hdr(skb); - - memcpy(eth->h_source, br->dev->dev_addr, 6); - eth->h_dest[0] = 1; - eth->h_dest[1] = 0; - eth->h_dest[2] = 0x5e; - eth->h_dest[3] = 0; - eth->h_dest[4] = 0; - eth->h_dest[5] = 1; - eth->h_proto = htons(ETH_P_IP); - skb_put(skb, sizeof(*eth)); - - skb_set_network_header(skb, skb->len); - iph = ip_hdr(skb); - - iph->version = 4; - iph->ihl = 6; - iph->tos = 0xc0; - iph->tot_len = htons(sizeof(*iph) + sizeof(*ih) + 4); - iph->id = 0; - iph->frag_off = htons(IP_DF); - iph->ttl = 1; - iph->protocol = IPPROTO_IGMP; - iph->saddr = 0; - iph->daddr = htonl(INADDR_ALLHOSTS_GROUP); - ((u8 *)&iph[1])[0] = IPOPT_RA; - ((u8 *)&iph[1])[1] = 4; - ((u8 *)&iph[1])[2] = 0; - ((u8 *)&iph[1])[3] = 0; - ip_send_check(iph); - skb_put(skb, 24); - - skb_set_transport_header(skb, skb->len); - ih = igmp_hdr(skb); - ih->type = IGMP_HOST_MEMBERSHIP_QUERY; - ih->code = (group ? br->multicast_last_member_interval : - br->multicast_query_response_interval) / - (HZ / IGMP_TIMER_SCALE); - ih->group = group; - ih->csum = 0; - ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr)); - skb_put(skb, sizeof(*ih)); - - __skb_pull(skb, sizeof(*eth)); - -out: - return skb; -} - -static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) -{ - struct net_bridge *br = mp->br; - struct sk_buff *skb; - - skb = br_multicast_alloc_query(br, mp->addr); - if (!skb) - goto timer; - - netif_rx(skb); - -timer: - if (++mp->queries_sent < br->multicast_last_member_count) - mod_timer(&mp->query_timer, - jiffies + br->multicast_last_member_interval); -} - -static void br_multicast_group_query_expired(unsigned long data) -{ - struct net_bridge_mdb_entry *mp = (void *)data; - struct net_bridge *br = mp->br; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || hlist_unhashed(&mp->mglist) || - mp->queries_sent >= br->multicast_last_member_count) - goto out; - - br_multicast_send_group_query(mp); - -out: - spin_unlock(&br->multicast_lock); -} - -static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) -{ - struct net_bridge_port *port = pg->port; - struct net_bridge *br = port->br; - struct sk_buff *skb; - - skb = br_multicast_alloc_query(br, pg->addr); - if (!skb) - goto timer; - - br_deliver(port, skb); - -timer: - if (++pg->queries_sent < br->multicast_last_member_count) - mod_timer(&pg->query_timer, - jiffies + br->multicast_last_member_interval); -} - -static void br_multicast_port_group_query_expired(unsigned long data) -{ - struct net_bridge_port_group *pg = (void *)data; - struct net_bridge_port *port = pg->port; - struct net_bridge *br = port->br; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || - pg->queries_sent >= br->multicast_last_member_count) - goto out; - - br_multicast_send_port_group_query(pg); - -out: - spin_unlock(&br->multicast_lock); -} - -static struct net_bridge_mdb_entry *br_multicast_get_group( - struct net_bridge *br, struct net_bridge_port *port, __be32 group, - int hash) -{ - struct net_bridge_mdb_htable *mdb = br->mdb; - struct net_bridge_mdb_entry *mp; - struct hlist_node *p; - unsigned count = 0; - unsigned max; - int elasticity; - int err; - - hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { - count++; - if (unlikely(group == mp->addr)) { - return mp; - } - } - - elasticity = 0; - max = mdb->max; - - if (unlikely(count > br->hash_elasticity && count)) { - if (net_ratelimit()) - printk(KERN_INFO "%s: Multicast hash table " - "chain limit reached: %s\n", - br->dev->name, port ? port->dev->name : - br->dev->name); - - elasticity = br->hash_elasticity; - } - - if (mdb->size >= max) { - max *= 2; - if (unlikely(max >= br->hash_max)) { - printk(KERN_WARNING "%s: Multicast hash table maximum " - "reached, disabling snooping: %s, %d\n", - br->dev->name, port ? port->dev->name : - br->dev->name, - max); - err = -E2BIG; -disable: - br->multicast_disabled = 1; - goto err; - } - } - - if (max > mdb->max || elasticity) { - if (mdb->old) { - if (net_ratelimit()) - printk(KERN_INFO "%s: Multicast hash table " - "on fire: %s\n", - br->dev->name, port ? port->dev->name : - br->dev->name); - err = -EEXIST; - goto err; - } - - err = br_mdb_rehash(&br->mdb, max, elasticity); - if (err) { - printk(KERN_WARNING "%s: Cannot rehash multicast " - "hash table, disabling snooping: " - "%s, %d, %d\n", - br->dev->name, port ? port->dev->name : - br->dev->name, - mdb->size, err); - goto disable; - } - - err = -EAGAIN; - goto err; - } - - return NULL; - -err: - mp = ERR_PTR(err); - return mp; -} - -static struct net_bridge_mdb_entry *br_multicast_new_group( - struct net_bridge *br, struct net_bridge_port *port, __be32 group) -{ - struct net_bridge_mdb_htable *mdb = br->mdb; - struct net_bridge_mdb_entry *mp; - int hash; - - if (!mdb) { - if (br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0)) - return NULL; - goto rehash; - } - - hash = br_ip_hash(mdb, group); - mp = br_multicast_get_group(br, port, group, hash); - switch (PTR_ERR(mp)) { - case 0: - break; - - case -EAGAIN: -rehash: - mdb = br->mdb; - hash = br_ip_hash(mdb, group); - break; - - default: - goto out; - } - - mp = kzalloc(sizeof(*mp), GFP_ATOMIC); - if (unlikely(!mp)) - goto out; - - mp->br = br; - mp->addr = group; - setup_timer(&mp->timer, br_multicast_group_expired, - (unsigned long)mp); - setup_timer(&mp->query_timer, br_multicast_group_query_expired, - (unsigned long)mp); - - hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); - mdb->size++; - -out: - return mp; -} - -static int br_multicast_add_group(struct net_bridge *br, - struct net_bridge_port *port, __be32 group) -{ - struct net_bridge_mdb_entry *mp; - struct net_bridge_port_group *p; - struct net_bridge_port_group **pp; - unsigned long now = jiffies; - int err; - - if (ipv4_is_local_multicast(group)) - return 0; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || - (port && port->state == BR_STATE_DISABLED)) - goto out; - - mp = br_multicast_new_group(br, port, group); - err = PTR_ERR(mp); - if (unlikely(IS_ERR(mp) || !mp)) - goto err; - - if (!port) { - hlist_add_head(&mp->mglist, &br->mglist); - mod_timer(&mp->timer, now + br->multicast_membership_interval); - goto out; - } - - for (pp = &mp->ports; (p = *pp); pp = &p->next) { - if (p->port == port) - goto found; - if ((unsigned long)p->port < (unsigned long)port) - break; - } - - p = kzalloc(sizeof(*p), GFP_ATOMIC); - err = -ENOMEM; - if (unlikely(!p)) - goto err; - - p->addr = group; - p->port = port; - p->next = *pp; - hlist_add_head(&p->mglist, &port->mglist); - setup_timer(&p->timer, br_multicast_port_group_expired, - (unsigned long)p); - setup_timer(&p->query_timer, br_multicast_port_group_query_expired, - (unsigned long)p); - - rcu_assign_pointer(*pp, p); - -found: - mod_timer(&p->timer, now + br->multicast_membership_interval); -out: - err = 0; - -err: - spin_unlock(&br->multicast_lock); - return err; -} - -static void br_multicast_router_expired(unsigned long data) -{ - struct net_bridge_port *port = (void *)data; - struct net_bridge *br = port->br; - - spin_lock(&br->multicast_lock); - if (port->multicast_router != 1 || - timer_pending(&port->multicast_router_timer) || - hlist_unhashed(&port->rlist)) - goto out; - - hlist_del_init_rcu(&port->rlist); - -out: - spin_unlock(&br->multicast_lock); -} - -static void br_multicast_local_router_expired(unsigned long data) -{ -} - -static void br_multicast_send_query(struct net_bridge *br, - struct net_bridge_port *port, u32 sent) -{ - unsigned long time; - struct sk_buff *skb; - - if (!netif_running(br->dev) || br->multicast_disabled || - timer_pending(&br->multicast_querier_timer)) - return; - - skb = br_multicast_alloc_query(br, 0); - if (!skb) - goto timer; - - if (port) { - __skb_push(skb, sizeof(struct ethhdr)); - skb->dev = port->dev; - NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); - } else - netif_rx(skb); - -timer: - time = jiffies; - time += sent < br->multicast_startup_query_count ? - br->multicast_startup_query_interval : - br->multicast_query_interval; - mod_timer(port ? &port->multicast_query_timer : - &br->multicast_query_timer, time); -} - -static void br_multicast_port_query_expired(unsigned long data) -{ - struct net_bridge_port *port = (void *)data; - struct net_bridge *br = port->br; - - spin_lock(&br->multicast_lock); - if (port && (port->state == BR_STATE_DISABLED || - port->state == BR_STATE_BLOCKING)) - goto out; - - if (port->multicast_startup_queries_sent < - br->multicast_startup_query_count) - port->multicast_startup_queries_sent++; - - br_multicast_send_query(port->br, port, - port->multicast_startup_queries_sent); - -out: - spin_unlock(&br->multicast_lock); -} - -void br_multicast_add_port(struct net_bridge_port *port) -{ - port->multicast_router = 1; - - setup_timer(&port->multicast_router_timer, br_multicast_router_expired, - (unsigned long)port); - setup_timer(&port->multicast_query_timer, - br_multicast_port_query_expired, (unsigned long)port); -} - -void br_multicast_del_port(struct net_bridge_port *port) -{ - del_timer_sync(&port->multicast_router_timer); -} - -static void __br_multicast_enable_port(struct net_bridge_port *port) -{ - port->multicast_startup_queries_sent = 0; - - if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || - del_timer(&port->multicast_query_timer)) - mod_timer(&port->multicast_query_timer, jiffies); -} - -void br_multicast_enable_port(struct net_bridge_port *port) -{ - struct net_bridge *br = port->br; - - spin_lock(&br->multicast_lock); - if (br->multicast_disabled || !netif_running(br->dev)) - goto out; - - __br_multicast_enable_port(port); - -out: - spin_unlock(&br->multicast_lock); -} - -void br_multicast_disable_port(struct net_bridge_port *port) -{ - struct net_bridge *br = port->br; - struct net_bridge_port_group *pg; - struct hlist_node *p, *n; - - spin_lock(&br->multicast_lock); - hlist_for_each_entry_safe(pg, p, n, &port->mglist, mglist) - br_multicast_del_pg(br, pg); - - if (!hlist_unhashed(&port->rlist)) - hlist_del_init_rcu(&port->rlist); - del_timer(&port->multicast_router_timer); - del_timer(&port->multicast_query_timer); - spin_unlock(&br->multicast_lock); -} - -static int br_multicast_igmp3_report(struct net_bridge *br, - struct net_bridge_port *port, - struct sk_buff *skb) -{ - struct igmpv3_report *ih; - struct igmpv3_grec *grec; - int i; - int len; - int num; - int type; - int err = 0; - __be32 group; - - if (!pskb_may_pull(skb, sizeof(*ih))) - return -EINVAL; - - ih = igmpv3_report_hdr(skb); - num = ntohs(ih->ngrec); - len = sizeof(*ih); - - for (i = 0; i < num; i++) { - len += sizeof(*grec); - if (!pskb_may_pull(skb, len)) - return -EINVAL; - - grec = (void *)(skb->data + len); - group = grec->grec_mca; - type = grec->grec_type; - - len += grec->grec_nsrcs * 4; - if (!pskb_may_pull(skb, len)) - return -EINVAL; - - /* We treat this as an IGMPv2 report for now. */ - switch (type) { - case IGMPV3_MODE_IS_INCLUDE: - case IGMPV3_MODE_IS_EXCLUDE: - case IGMPV3_CHANGE_TO_INCLUDE: - case IGMPV3_CHANGE_TO_EXCLUDE: - case IGMPV3_ALLOW_NEW_SOURCES: - case IGMPV3_BLOCK_OLD_SOURCES: - break; - - default: - continue; - } - - err = br_multicast_add_group(br, port, group); - if (err) - break; - } - - return err; -} - -static void br_multicast_add_router(struct net_bridge *br, - struct net_bridge_port *port) -{ - struct hlist_node *p; - struct hlist_node **h; - - for (h = &br->router_list.first; - (p = *h) && - (unsigned long)container_of(p, struct net_bridge_port, rlist) > - (unsigned long)port; - h = &p->next) - ; - - port->rlist.pprev = h; - port->rlist.next = p; - rcu_assign_pointer(*h, &port->rlist); - if (p) - p->pprev = &port->rlist.next; -} - -static void br_multicast_mark_router(struct net_bridge *br, - struct net_bridge_port *port) -{ - unsigned long now = jiffies; - - if (!port) { - if (br->multicast_router == 1) - mod_timer(&br->multicast_router_timer, - now + br->multicast_querier_interval); - return; - } - - if (port->multicast_router != 1) - return; - - if (!hlist_unhashed(&port->rlist)) - goto timer; - - br_multicast_add_router(br, port); - -timer: - mod_timer(&port->multicast_router_timer, - now + br->multicast_querier_interval); -} - -static void br_multicast_query_received(struct net_bridge *br, - struct net_bridge_port *port, - __be32 saddr) -{ - if (saddr) - mod_timer(&br->multicast_querier_timer, - jiffies + br->multicast_querier_interval); - else if (timer_pending(&br->multicast_querier_timer)) - return; - - br_multicast_mark_router(br, port); -} - -static int br_multicast_query(struct net_bridge *br, - struct net_bridge_port *port, - struct sk_buff *skb) -{ - struct iphdr *iph = ip_hdr(skb); - struct igmphdr *ih = igmp_hdr(skb); - struct net_bridge_mdb_entry *mp; - struct igmpv3_query *ih3; - struct net_bridge_port_group *p; - struct net_bridge_port_group **pp; - unsigned long max_delay; - unsigned long now = jiffies; - __be32 group; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || - (port && port->state == BR_STATE_DISABLED)) - goto out; - - br_multicast_query_received(br, port, iph->saddr); - - group = ih->group; - - if (skb->len == sizeof(*ih)) { - max_delay = ih->code * (HZ / IGMP_TIMER_SCALE); - - if (!max_delay) { - max_delay = 10 * HZ; - group = 0; - } - } else { - if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) - return -EINVAL; - - ih3 = igmpv3_query_hdr(skb); - if (ih3->nsrcs) - return 0; - - max_delay = ih3->code ? 1 : - IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE); - } - - if (!group) - goto out; - - mp = br_mdb_ip_get(br->mdb, group); - if (!mp) - goto out; - - max_delay *= br->multicast_last_member_count; - - if (!hlist_unhashed(&mp->mglist) && - (timer_pending(&mp->timer) ? - time_after(mp->timer.expires, now + max_delay) : - try_to_del_timer_sync(&mp->timer) >= 0)) - mod_timer(&mp->timer, now + max_delay); - - for (pp = &mp->ports; (p = *pp); pp = &p->next) { - if (timer_pending(&p->timer) ? - time_after(p->timer.expires, now + max_delay) : - try_to_del_timer_sync(&p->timer) >= 0) - mod_timer(&mp->timer, now + max_delay); - } - -out: - spin_unlock(&br->multicast_lock); - return 0; -} - -static void br_multicast_leave_group(struct net_bridge *br, - struct net_bridge_port *port, - __be32 group) -{ - struct net_bridge_mdb_htable *mdb; - struct net_bridge_mdb_entry *mp; - struct net_bridge_port_group *p; - unsigned long now; - unsigned long time; - - if (ipv4_is_local_multicast(group)) - return; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || - (port && port->state == BR_STATE_DISABLED) || - timer_pending(&br->multicast_querier_timer)) - goto out; - - mdb = br->mdb; - mp = br_mdb_ip_get(mdb, group); - if (!mp) - goto out; - - now = jiffies; - time = now + br->multicast_last_member_count * - br->multicast_last_member_interval; - - if (!port) { - if (!hlist_unhashed(&mp->mglist) && - (timer_pending(&mp->timer) ? - time_after(mp->timer.expires, time) : - try_to_del_timer_sync(&mp->timer) >= 0)) { - mod_timer(&mp->timer, time); - - mp->queries_sent = 0; - mod_timer(&mp->query_timer, now); - } - - goto out; - } - - for (p = mp->ports; p; p = p->next) { - if (p->port != port) - continue; - - if (!hlist_unhashed(&p->mglist) && - (timer_pending(&p->timer) ? - time_after(p->timer.expires, time) : - try_to_del_timer_sync(&p->timer) >= 0)) { - mod_timer(&p->timer, time); - - p->queries_sent = 0; - mod_timer(&p->query_timer, now); - } - - break; - } - -out: - spin_unlock(&br->multicast_lock); -} - -static int br_multicast_ipv4_rcv(struct net_bridge *br, - struct net_bridge_port *port, - struct sk_buff *skb) -{ - struct sk_buff *skb2 = skb; - struct iphdr *iph; - struct igmphdr *ih; - unsigned len; - unsigned offset; - int err; - - BR_INPUT_SKB_CB(skb)->igmp = 0; - BR_INPUT_SKB_CB(skb)->mrouters_only = 0; - - /* We treat OOM as packet loss for now. */ - if (!pskb_may_pull(skb, sizeof(*iph))) - return -EINVAL; - - iph = ip_hdr(skb); - - if (iph->ihl < 5 || iph->version != 4) - return -EINVAL; - - if (!pskb_may_pull(skb, ip_hdrlen(skb))) - return -EINVAL; - - iph = ip_hdr(skb); - - if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) - return -EINVAL; - - if (iph->protocol != IPPROTO_IGMP) - return 0; - - len = ntohs(iph->tot_len); - if (skb->len < len || len < ip_hdrlen(skb)) - return -EINVAL; - - if (skb->len > len) { - skb2 = skb_clone(skb, GFP_ATOMIC); - if (!skb2) - return -ENOMEM; - - err = pskb_trim_rcsum(skb2, len); - if (err) - return err; - } - - len -= ip_hdrlen(skb2); - offset = skb_network_offset(skb2) + ip_hdrlen(skb2); - __skb_pull(skb2, offset); - skb_reset_transport_header(skb2); - - err = -EINVAL; - if (!pskb_may_pull(skb2, sizeof(*ih))) - goto out; - - iph = ip_hdr(skb2); - - switch (skb2->ip_summed) { - case CHECKSUM_COMPLETE: - if (!csum_fold(skb2->csum)) - break; - /* fall through */ - case CHECKSUM_NONE: - skb2->csum = 0; - if (skb_checksum_complete(skb2)) - return -EINVAL; - } - - err = 0; - - BR_INPUT_SKB_CB(skb)->igmp = 1; - ih = igmp_hdr(skb2); - - switch (ih->type) { - case IGMP_HOST_MEMBERSHIP_REPORT: - case IGMPV2_HOST_MEMBERSHIP_REPORT: - BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; - err = br_multicast_add_group(br, port, ih->group); - break; - case IGMPV3_HOST_MEMBERSHIP_REPORT: - err = br_multicast_igmp3_report(br, port, skb2); - break; - case IGMP_HOST_MEMBERSHIP_QUERY: - err = br_multicast_query(br, port, skb2); - break; - case IGMP_HOST_LEAVE_MESSAGE: - br_multicast_leave_group(br, port, ih->group); - break; - } - -out: - __skb_push(skb2, offset); - if (skb2 != skb) - kfree_skb(skb2); - return err; -} - -int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, - struct sk_buff *skb) -{ - if (br->multicast_disabled) - return 0; - - switch (skb->protocol) { - case htons(ETH_P_IP): - return br_multicast_ipv4_rcv(br, port, skb); - } - - return 0; -} - -static void br_multicast_query_expired(unsigned long data) -{ - struct net_bridge *br = (void *)data; - - spin_lock(&br->multicast_lock); - if (br->multicast_startup_queries_sent < - br->multicast_startup_query_count) - br->multicast_startup_queries_sent++; - - br_multicast_send_query(br, NULL, br->multicast_startup_queries_sent); - - spin_unlock(&br->multicast_lock); -} - -void br_multicast_init(struct net_bridge *br) -{ - br->hash_elasticity = 4; - br->hash_max = 512; - - br->multicast_router = 1; - br->multicast_last_member_count = 2; - br->multicast_startup_query_count = 2; - - br->multicast_last_member_interval = HZ; - br->multicast_query_response_interval = 10 * HZ; - br->multicast_startup_query_interval = 125 * HZ / 4; - br->multicast_query_interval = 125 * HZ; - br->multicast_querier_interval = 255 * HZ; - br->multicast_membership_interval = 260 * HZ; - - spin_lock_init(&br->multicast_lock); - setup_timer(&br->multicast_router_timer, - br_multicast_local_router_expired, 0); - setup_timer(&br->multicast_querier_timer, - br_multicast_local_router_expired, 0); - setup_timer(&br->multicast_query_timer, br_multicast_query_expired, - (unsigned long)br); -} - -void br_multicast_open(struct net_bridge *br) -{ - br->multicast_startup_queries_sent = 0; - - if (br->multicast_disabled) - return; - - mod_timer(&br->multicast_query_timer, jiffies); -} - -void br_multicast_stop(struct net_bridge *br) -{ - struct net_bridge_mdb_htable *mdb; - struct net_bridge_mdb_entry *mp; - struct hlist_node *p, *n; - u32 ver; - int i; - - del_timer_sync(&br->multicast_router_timer); - del_timer_sync(&br->multicast_querier_timer); - del_timer_sync(&br->multicast_query_timer); - - spin_lock_bh(&br->multicast_lock); - mdb = br->mdb; - if (!mdb) - goto out; - - br->mdb = NULL; - - ver = mdb->ver; - for (i = 0; i < mdb->max; i++) { - hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], - hlist[ver]) { - del_timer(&mp->timer); - del_timer(&mp->query_timer); - call_rcu_bh(&mp->rcu, br_multicast_free_group); - } - } - - if (mdb->old) { - spin_unlock_bh(&br->multicast_lock); - synchronize_rcu_bh(); - spin_lock_bh(&br->multicast_lock); - WARN_ON(mdb->old); - } - - mdb->old = mdb; - call_rcu_bh(&mdb->rcu, br_mdb_free); - -out: - spin_unlock_bh(&br->multicast_lock); -} - -int br_multicast_set_router(struct net_bridge *br, unsigned long val) -{ - int err = -ENOENT; - - spin_lock_bh(&br->multicast_lock); - if (!netif_running(br->dev)) - goto unlock; - - switch (val) { - case 0: - case 2: - del_timer(&br->multicast_router_timer); - /* fall through */ - case 1: - br->multicast_router = val; - err = 0; - break; - - default: - err = -EINVAL; - break; - } - -unlock: - spin_unlock_bh(&br->multicast_lock); - - return err; -} - -int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) -{ - struct net_bridge *br = p->br; - int err = -ENOENT; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || p->state == BR_STATE_DISABLED) - goto unlock; - - switch (val) { - case 0: - case 1: - case 2: - p->multicast_router = val; - err = 0; - - if (val < 2 && !hlist_unhashed(&p->rlist)) - hlist_del_init_rcu(&p->rlist); - - if (val == 1) - break; - - del_timer(&p->multicast_router_timer); - - if (val == 0) - break; - - br_multicast_add_router(br, p); - break; - - default: - err = -EINVAL; - break; - } - -unlock: - spin_unlock(&br->multicast_lock); - - return err; -} - -int br_multicast_toggle(struct net_bridge *br, unsigned long val) -{ - struct net_bridge_port *port; - int err = -ENOENT; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev)) - goto unlock; - - err = 0; - if (br->multicast_disabled == !val) - goto unlock; - - br->multicast_disabled = !val; - if (br->multicast_disabled) - goto unlock; - - if (br->mdb) { - if (br->mdb->old) { - err = -EEXIST; -rollback: - br->multicast_disabled = !!val; - goto unlock; - } - - err = br_mdb_rehash(&br->mdb, br->mdb->max, - br->hash_elasticity); - if (err) - goto rollback; - } - - br_multicast_open(br); - list_for_each_entry(port, &br->port_list, list) { - if (port->state == BR_STATE_DISABLED || - port->state == BR_STATE_BLOCKING) - continue; - - __br_multicast_enable_port(port); - } - -unlock: - spin_unlock(&br->multicast_lock); - - return err; -} - -int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) -{ - int err = -ENOENT; - u32 old; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev)) - goto unlock; - - err = -EINVAL; - if (!is_power_of_2(val)) - goto unlock; - if (br->mdb && val < br->mdb->size) - goto unlock; - - err = 0; - - old = br->hash_max; - br->hash_max = val; - - if (br->mdb) { - if (br->mdb->old) { - err = -EEXIST; -rollback: - br->hash_max = old; - goto unlock; - } - - err = br_mdb_rehash(&br->mdb, br->hash_max, - br->hash_elasticity); - if (err) - goto rollback; - } - -unlock: - spin_unlock(&br->multicast_lock); - - return err; -} diff --git a/trunk/net/bridge/br_private.h b/trunk/net/bridge/br_private.h index 9191198c4f1b..1f0c4f44b765 100644 --- a/trunk/net/bridge/br_private.h +++ b/trunk/net/bridge/br_private.h @@ -57,41 +57,6 @@ struct net_bridge_fdb_entry unsigned char is_static; }; -struct net_bridge_port_group { - struct net_bridge_port *port; - struct net_bridge_port_group *next; - struct hlist_node mglist; - struct rcu_head rcu; - struct timer_list timer; - struct timer_list query_timer; - __be32 addr; - u32 queries_sent; -}; - -struct net_bridge_mdb_entry -{ - struct hlist_node hlist[2]; - struct hlist_node mglist; - struct net_bridge *br; - struct net_bridge_port_group *ports; - struct rcu_head rcu; - struct timer_list timer; - struct timer_list query_timer; - __be32 addr; - u32 queries_sent; -}; - -struct net_bridge_mdb_htable -{ - struct hlist_head *mhash; - struct rcu_head rcu; - struct net_bridge_mdb_htable *old; - u32 size; - u32 max; - u32 secret; - u32 ver; -}; - struct net_bridge_port { struct net_bridge *br; @@ -119,15 +84,6 @@ struct net_bridge_port unsigned long flags; #define BR_HAIRPIN_MODE 0x00000001 - -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING - u32 multicast_startup_queries_sent; - unsigned char multicast_router; - struct timer_list multicast_router_timer; - struct timer_list multicast_query_timer; - struct hlist_head mglist; - struct hlist_node rlist; -#endif }; struct net_bridge @@ -168,35 +124,6 @@ struct net_bridge unsigned char topology_change; unsigned char topology_change_detected; -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING - unsigned char multicast_router; - - u8 multicast_disabled:1; - - u32 hash_elasticity; - u32 hash_max; - - u32 multicast_last_member_count; - u32 multicast_startup_queries_sent; - u32 multicast_startup_query_count; - - unsigned long multicast_last_member_interval; - unsigned long multicast_membership_interval; - unsigned long multicast_querier_interval; - unsigned long multicast_query_interval; - unsigned long multicast_query_response_interval; - unsigned long multicast_startup_query_interval; - - spinlock_t multicast_lock; - struct net_bridge_mdb_htable *mdb; - struct hlist_head router_list; - struct hlist_head mglist; - - struct timer_list multicast_router_timer; - struct timer_list multicast_querier_timer; - struct timer_list multicast_query_timer; -#endif - struct timer_list hello_timer; struct timer_list tcn_timer; struct timer_list topology_change_timer; @@ -204,14 +131,6 @@ struct net_bridge struct kobject *ifobj; }; -struct br_input_skb_cb { - struct net_device *brdev; - int igmp; - int mrouters_only; -}; - -#define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) - extern struct notifier_block br_device_notifier; extern const u8 br_group_address[ETH_ALEN]; @@ -255,8 +174,7 @@ extern void br_forward(const struct net_bridge_port *to, struct sk_buff *skb); extern int br_forward_finish(struct sk_buff *skb); extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); -extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, - struct sk_buff *skb2); +extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb); /* br_if.c */ extern void br_port_carrier_check(struct net_bridge_port *p); @@ -279,90 +197,6 @@ extern struct sk_buff *br_handle_frame(struct net_bridge_port *p, extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg); -/* br_multicast.c */ -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING -extern int br_multicast_rcv(struct net_bridge *br, - struct net_bridge_port *port, - struct sk_buff *skb); -extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, - struct sk_buff *skb); -extern void br_multicast_add_port(struct net_bridge_port *port); -extern void br_multicast_del_port(struct net_bridge_port *port); -extern void br_multicast_enable_port(struct net_bridge_port *port); -extern void br_multicast_disable_port(struct net_bridge_port *port); -extern void br_multicast_init(struct net_bridge *br); -extern void br_multicast_open(struct net_bridge *br); -extern void br_multicast_stop(struct net_bridge *br); -extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb); -extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb, struct sk_buff *skb2); -extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); -extern int br_multicast_set_port_router(struct net_bridge_port *p, - unsigned long val); -extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); -extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); -#else -static inline int br_multicast_rcv(struct net_bridge *br, - struct net_bridge_port *port, - struct sk_buff *skb) -{ - return 0; -} - -static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, - struct sk_buff *skb) -{ - return NULL; -} - -static inline void br_multicast_add_port(struct net_bridge_port *port) -{ -} - -static inline void br_multicast_del_port(struct net_bridge_port *port) -{ -} - -static inline void br_multicast_enable_port(struct net_bridge_port *port) -{ -} - -static inline void br_multicast_disable_port(struct net_bridge_port *port) -{ -} - -static inline void br_multicast_init(struct net_bridge *br) -{ -} - -static inline void br_multicast_open(struct net_bridge *br) -{ -} - -static inline void br_multicast_stop(struct net_bridge *br) -{ -} - -static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb) -{ -} - -static inline void br_multicast_forward(struct net_bridge_mdb_entry *mdst, - struct sk_buff *skb, - struct sk_buff *skb2) -{ -} -#endif - -static inline bool br_multicast_is_router(struct net_bridge *br) -{ - return br->multicast_router == 2 || - (br->multicast_router == 1 && - timer_pending(&br->multicast_router_timer)); -} - /* br_netfilter.c */ #ifdef CONFIG_BRIDGE_NETFILTER extern int br_netfilter_init(void); diff --git a/trunk/net/bridge/br_stp.c b/trunk/net/bridge/br_stp.c index edcf14b560f6..fd3f8d6c0998 100644 --- a/trunk/net/bridge/br_stp.c +++ b/trunk/net/bridge/br_stp.c @@ -386,8 +386,6 @@ static void br_make_forwarding(struct net_bridge_port *p) else p->state = BR_STATE_LEARNING; - br_multicast_enable_port(p); - br_log_state(p); if (br->forward_delay != 0) diff --git a/trunk/net/bridge/br_stp_if.c b/trunk/net/bridge/br_stp_if.c index d527119e9f54..9a52ac5b4525 100644 --- a/trunk/net/bridge/br_stp_if.c +++ b/trunk/net/bridge/br_stp_if.c @@ -108,7 +108,6 @@ void br_stp_disable_port(struct net_bridge_port *p) del_timer(&p->hold_timer); br_fdb_delete_by_port(br, p, 0); - br_multicast_disable_port(p); br_configuration_update(br); diff --git a/trunk/net/bridge/br_sysfs_br.c b/trunk/net/bridge/br_sysfs_br.c index dd321e39e621..bee4f300d0c8 100644 --- a/trunk/net/bridge/br_sysfs_br.c +++ b/trunk/net/bridge/br_sysfs_br.c @@ -345,273 +345,6 @@ static ssize_t store_flush(struct device *d, } static DEVICE_ATTR(flush, S_IWUSR, NULL, store_flush); -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING -static ssize_t show_multicast_router(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%d\n", br->multicast_router); -} - -static ssize_t store_multicast_router(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, br_multicast_set_router); -} -static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, - store_multicast_router); - -static ssize_t show_multicast_snooping(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%d\n", !br->multicast_disabled); -} - -static ssize_t store_multicast_snooping(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, br_multicast_toggle); -} -static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, - show_multicast_snooping, store_multicast_snooping); - -static ssize_t show_hash_elasticity(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%u\n", br->hash_elasticity); -} - -static int set_elasticity(struct net_bridge *br, unsigned long val) -{ - br->hash_elasticity = val; - return 0; -} - -static ssize_t store_hash_elasticity(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, set_elasticity); -} -static DEVICE_ATTR(hash_elasticity, S_IRUGO | S_IWUSR, show_hash_elasticity, - store_hash_elasticity); - -static ssize_t show_hash_max(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%u\n", br->hash_max); -} - -static ssize_t store_hash_max(struct device *d, struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, br_multicast_set_hash_max); -} -static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max, - store_hash_max); - -static ssize_t show_multicast_last_member_count(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%u\n", br->multicast_last_member_count); -} - -static int set_last_member_count(struct net_bridge *br, unsigned long val) -{ - br->multicast_last_member_count = val; - return 0; -} - -static ssize_t store_multicast_last_member_count(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, set_last_member_count); -} -static DEVICE_ATTR(multicast_last_member_count, S_IRUGO | S_IWUSR, - show_multicast_last_member_count, - store_multicast_last_member_count); - -static ssize_t show_multicast_startup_query_count( - struct device *d, struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%u\n", br->multicast_startup_query_count); -} - -static int set_startup_query_count(struct net_bridge *br, unsigned long val) -{ - br->multicast_startup_query_count = val; - return 0; -} - -static ssize_t store_multicast_startup_query_count( - struct device *d, struct device_attribute *attr, const char *buf, - size_t len) -{ - return store_bridge_parm(d, buf, len, set_startup_query_count); -} -static DEVICE_ATTR(multicast_startup_query_count, S_IRUGO | S_IWUSR, - show_multicast_startup_query_count, - store_multicast_startup_query_count); - -static ssize_t show_multicast_last_member_interval( - struct device *d, struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%lu\n", - jiffies_to_clock_t(br->multicast_last_member_interval)); -} - -static int set_last_member_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_last_member_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_last_member_interval( - struct device *d, struct device_attribute *attr, const char *buf, - size_t len) -{ - return store_bridge_parm(d, buf, len, set_last_member_interval); -} -static DEVICE_ATTR(multicast_last_member_interval, S_IRUGO | S_IWUSR, - show_multicast_last_member_interval, - store_multicast_last_member_interval); - -static ssize_t show_multicast_membership_interval( - struct device *d, struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%lu\n", - jiffies_to_clock_t(br->multicast_membership_interval)); -} - -static int set_membership_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_membership_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_membership_interval( - struct device *d, struct device_attribute *attr, const char *buf, - size_t len) -{ - return store_bridge_parm(d, buf, len, set_membership_interval); -} -static DEVICE_ATTR(multicast_membership_interval, S_IRUGO | S_IWUSR, - show_multicast_membership_interval, - store_multicast_membership_interval); - -static ssize_t show_multicast_querier_interval(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%lu\n", - jiffies_to_clock_t(br->multicast_querier_interval)); -} - -static int set_querier_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_querier_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_querier_interval(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, set_querier_interval); -} -static DEVICE_ATTR(multicast_querier_interval, S_IRUGO | S_IWUSR, - show_multicast_querier_interval, - store_multicast_querier_interval); - -static ssize_t show_multicast_query_interval(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf(buf, "%lu\n", - jiffies_to_clock_t(br->multicast_query_interval)); -} - -static int set_query_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_query_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_query_interval(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) -{ - return store_bridge_parm(d, buf, len, set_query_interval); -} -static DEVICE_ATTR(multicast_query_interval, S_IRUGO | S_IWUSR, - show_multicast_query_interval, - store_multicast_query_interval); - -static ssize_t show_multicast_query_response_interval( - struct device *d, struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf( - buf, "%lu\n", - jiffies_to_clock_t(br->multicast_query_response_interval)); -} - -static int set_query_response_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_query_response_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_query_response_interval( - struct device *d, struct device_attribute *attr, const char *buf, - size_t len) -{ - return store_bridge_parm(d, buf, len, set_query_response_interval); -} -static DEVICE_ATTR(multicast_query_response_interval, S_IRUGO | S_IWUSR, - show_multicast_query_response_interval, - store_multicast_query_response_interval); - -static ssize_t show_multicast_startup_query_interval( - struct device *d, struct device_attribute *attr, char *buf) -{ - struct net_bridge *br = to_bridge(d); - return sprintf( - buf, "%lu\n", - jiffies_to_clock_t(br->multicast_startup_query_interval)); -} - -static int set_startup_query_interval(struct net_bridge *br, unsigned long val) -{ - br->multicast_startup_query_interval = clock_t_to_jiffies(val); - return 0; -} - -static ssize_t store_multicast_startup_query_interval( - struct device *d, struct device_attribute *attr, const char *buf, - size_t len) -{ - return store_bridge_parm(d, buf, len, set_startup_query_interval); -} -static DEVICE_ATTR(multicast_startup_query_interval, S_IRUGO | S_IWUSR, - show_multicast_startup_query_interval, - store_multicast_startup_query_interval); -#endif - static struct attribute *bridge_attrs[] = { &dev_attr_forward_delay.attr, &dev_attr_hello_time.attr, @@ -631,20 +364,6 @@ static struct attribute *bridge_attrs[] = { &dev_attr_gc_timer.attr, &dev_attr_group_addr.attr, &dev_attr_flush.attr, -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING - &dev_attr_multicast_router.attr, - &dev_attr_multicast_snooping.attr, - &dev_attr_hash_elasticity.attr, - &dev_attr_hash_max.attr, - &dev_attr_multicast_last_member_count.attr, - &dev_attr_multicast_startup_query_count.attr, - &dev_attr_multicast_last_member_interval.attr, - &dev_attr_multicast_membership_interval.attr, - &dev_attr_multicast_querier_interval.attr, - &dev_attr_multicast_query_interval.attr, - &dev_attr_multicast_query_response_interval.attr, - &dev_attr_multicast_startup_query_interval.attr, -#endif NULL }; diff --git a/trunk/net/bridge/br_sysfs_if.c b/trunk/net/bridge/br_sysfs_if.c index 696596cd3384..820643a3ba9c 100644 --- a/trunk/net/bridge/br_sysfs_if.c +++ b/trunk/net/bridge/br_sysfs_if.c @@ -159,21 +159,6 @@ static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v) static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR, show_hairpin_mode, store_hairpin_mode); -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING -static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->multicast_router); -} - -static ssize_t store_multicast_router(struct net_bridge_port *p, - unsigned long v) -{ - return br_multicast_set_port_router(p, v); -} -static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, - store_multicast_router); -#endif - static struct brport_attribute *brport_attrs[] = { &brport_attr_path_cost, &brport_attr_priority, @@ -191,9 +176,6 @@ static struct brport_attribute *brport_attrs[] = { &brport_attr_hold_timer, &brport_attr_flush, &brport_attr_hairpin_mode, -#ifdef CONFIG_BRIDGE_IGMP_SNOOPING - &brport_attr_multicast_router, -#endif NULL }; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index e5972f7f7e1b..eb7f1a4fefc6 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1113,13 +1113,32 @@ void dev_load(struct net *net, const char *name) } EXPORT_SYMBOL(dev_load); -static int __dev_open(struct net_device *dev) +/** + * dev_open - prepare an interface for use. + * @dev: device to open + * + * Takes a device from down to up state. The device's private open + * function is invoked and then the multicast lists are loaded. Finally + * the device is moved into the up state and a %NETDEV_UP message is + * sent to the netdev notifier chain. + * + * Calling this function on an active interface is a nop. On a failure + * a negative errno code is returned. + */ +int dev_open(struct net_device *dev) { const struct net_device_ops *ops = dev->netdev_ops; int ret; ASSERT_RTNL(); + /* + * Is it already up? + */ + + if (dev->flags & IFF_UP) + return 0; + /* * Is it even present? */ @@ -1168,57 +1187,36 @@ static int __dev_open(struct net_device *dev) * Wakeup transmit queue engine */ dev_activate(dev); + + /* + * ... and announce new interface. + */ + call_netdevice_notifiers(NETDEV_UP, dev); } return ret; } +EXPORT_SYMBOL(dev_open); /** - * dev_open - prepare an interface for use. - * @dev: device to open - * - * Takes a device from down to up state. The device's private open - * function is invoked and then the multicast lists are loaded. Finally - * the device is moved into the up state and a %NETDEV_UP message is - * sent to the netdev notifier chain. + * dev_close - shutdown an interface. + * @dev: device to shutdown * - * Calling this function on an active interface is a nop. On a failure - * a negative errno code is returned. + * This function moves an active device into down state. A + * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device + * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier + * chain. */ -int dev_open(struct net_device *dev) -{ - int ret; - - /* - * Is it already up? - */ - if (dev->flags & IFF_UP) - return 0; - - /* - * Open device - */ - ret = __dev_open(dev); - if (ret < 0) - return ret; - - /* - * ... and announce new interface. - */ - rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); - call_netdevice_notifiers(NETDEV_UP, dev); - - return ret; -} -EXPORT_SYMBOL(dev_open); - -static int __dev_close(struct net_device *dev) +int dev_close(struct net_device *dev) { const struct net_device_ops *ops = dev->netdev_ops; - ASSERT_RTNL(); + might_sleep(); + if (!(dev->flags & IFF_UP)) + return 0; + /* * Tell people we are going down, so that they can * prepare to death, when device is still operating. @@ -1254,34 +1252,14 @@ static int __dev_close(struct net_device *dev) dev->flags &= ~IFF_UP; /* - * Shutdown NET_DMA + * Tell people we are down */ - net_dmaengine_put(); - - return 0; -} - -/** - * dev_close - shutdown an interface. - * @dev: device to shutdown - * - * This function moves an active device into down state. A - * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device - * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier - * chain. - */ -int dev_close(struct net_device *dev) -{ - if (!(dev->flags & IFF_UP)) - return 0; - - __dev_close(dev); + call_netdevice_notifiers(NETDEV_DOWN, dev); /* - * Tell people we are down + * Shutdown NET_DMA */ - rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); - call_netdevice_notifiers(NETDEV_DOWN, dev); + net_dmaengine_put(); return 0; } @@ -4321,10 +4299,18 @@ unsigned dev_get_flags(const struct net_device *dev) } EXPORT_SYMBOL(dev_get_flags); -int __dev_change_flags(struct net_device *dev, unsigned int flags) +/** + * dev_change_flags - change device settings + * @dev: device + * @flags: device state flags + * + * Change settings on device based state flags. The flags are + * in the userspace exported format. + */ +int dev_change_flags(struct net_device *dev, unsigned flags) { + int ret, changes; int old_flags = dev->flags; - int ret; ASSERT_RTNL(); @@ -4355,12 +4341,17 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags) ret = 0; if ((old_flags ^ flags) & IFF_UP) { /* Bit is different ? */ - ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); + ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); if (!ret) dev_set_rx_mode(dev); } + if (dev->flags & IFF_UP && + ((old_flags ^ dev->flags) & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | + IFF_VOLATILE))) + call_netdevice_notifiers(NETDEV_CHANGE, dev); + if ((flags ^ dev->gflags) & IFF_PROMISC) { int inc = (flags & IFF_PROMISC) ? 1 : -1; @@ -4379,47 +4370,11 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags) dev_set_allmulti(dev, inc); } - return ret; -} - -void __dev_notify_flags(struct net_device *dev, unsigned int old_flags) -{ - unsigned int changes = dev->flags ^ old_flags; - - if (changes & IFF_UP) { - if (dev->flags & IFF_UP) - call_netdevice_notifiers(NETDEV_UP, dev); - else - call_netdevice_notifiers(NETDEV_DOWN, dev); - } - - if (dev->flags & IFF_UP && - (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) - call_netdevice_notifiers(NETDEV_CHANGE, dev); -} - -/** - * dev_change_flags - change device settings - * @dev: device - * @flags: device state flags - * - * Change settings on device based state flags. The flags are - * in the userspace exported format. - */ -int dev_change_flags(struct net_device *dev, unsigned flags) -{ - int ret, changes; - int old_flags = dev->flags; - - ret = __dev_change_flags(dev, flags); - if (ret < 0) - return ret; - - changes = old_flags ^ dev->flags; + /* Exclude state transition flags, already notified */ + changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING); if (changes) rtmsg_ifinfo(RTM_NEWLINK, dev, changes); - __dev_notify_flags(dev, old_flags); return ret; } EXPORT_SYMBOL(dev_change_flags); @@ -4910,10 +4865,6 @@ static void rollback_registered_many(struct list_head *head) */ call_netdevice_notifiers(NETDEV_UNREGISTER, dev); - if (!dev->rtnl_link_ops || - dev->rtnl_link_state == RTNL_LINK_INITIALIZED) - rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); - /* * Flush the unicast and multicast chains */ @@ -5140,9 +5091,7 @@ int register_netdevice(struct net_device *dev) * Prevent userspace races by waiting until the network * device is fully setup before sending notifications. */ - if (!dev->rtnl_link_ops || - dev->rtnl_link_state == RTNL_LINK_INITIALIZED) - rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); + rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); out: return ret; diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index d1472a423323..4dd4c3cdc442 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -549,19 +549,6 @@ static void set_operstate(struct net_device *dev, unsigned char transition) } } -static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, - const struct ifinfomsg *ifm) -{ - unsigned int flags = ifm->ifi_flags; - - /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ - if (ifm->ifi_change) - flags = (flags & ifm->ifi_change) | - (dev->flags & ~ifm->ifi_change); - - return flags; -} - static void copy_rtnl_link_stats(struct rtnl_link_stats *a, const struct net_device_stats *b) { @@ -917,7 +904,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, } if (ifm->ifi_flags || ifm->ifi_change) { - err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); + unsigned int flags = ifm->ifi_flags; + + /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ + if (ifm->ifi_change) + flags = (flags & ifm->ifi_change) | + (dev->flags & ~ifm->ifi_change); + err = dev_change_flags(dev, flags); if (err < 0) goto errout; } @@ -1060,26 +1053,6 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return 0; } -int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) -{ - unsigned int old_flags; - int err; - - old_flags = dev->flags; - if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { - err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); - if (err < 0) - return err; - } - - dev->rtnl_link_state = RTNL_LINK_INITIALIZED; - rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); - - __dev_notify_flags(dev, old_flags); - return 0; -} -EXPORT_SYMBOL(rtnl_configure_link); - struct net_device *rtnl_create_link(struct net *src_net, struct net *net, char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) { @@ -1101,7 +1074,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, dev_net_set(dev, net); dev->rtnl_link_ops = ops; - dev->rtnl_link_state = RTNL_LINK_INITIALIZING; dev->real_num_tx_queues = real_num_queues; if (strchr(dev->name, '%')) { @@ -1231,7 +1203,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (!(nlh->nlmsg_flags & NLM_F_CREATE)) return -ENODEV; - if (ifm->ifi_index) + if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) return -EOPNOTSUPP; if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) return -EOPNOTSUPP; @@ -1262,15 +1234,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) err = ops->newlink(net, dev, tb, data); else err = register_netdevice(dev); - if (err < 0 && !IS_ERR(dev)) { + if (err < 0 && !IS_ERR(dev)) free_netdev(dev); - goto out; - } - err = rtnl_configure_link(dev, ifm); - if (err < 0) - unregister_netdevice(dev); -out: put_net(dest_net); return err; } @@ -1459,14 +1425,17 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi struct net_device *dev = ptr; switch (event) { + case NETDEV_UNREGISTER: + rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); + break; case NETDEV_UP: case NETDEV_DOWN: - case NETDEV_PRE_UP: + rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); + break; case NETDEV_POST_INIT: case NETDEV_REGISTER: case NETDEV_CHANGE: case NETDEV_GOING_DOWN: - case NETDEV_UNREGISTER: case NETDEV_UNREGISTER_BATCH: break; default: diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 06c33b68d8e5..ec8f767ba95b 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -558,12 +558,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) debugfs_hw_add(local); - /* - * if the driver doesn't specify a max listen interval we - * use 5 which should be a safe default - */ if (local->hw.max_listen_interval == 0) - local->hw.max_listen_interval = 5; + local->hw.max_listen_interval = 1; local->hw.conf.listen_interval = local->hw.max_listen_interval; diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index 1e1ea3007b06..7e708d5c88b4 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -869,7 +869,6 @@ static void ieee80211_work_work(struct work_struct *work) break; case IEEE80211_WORK_ABORT: rma = WORK_ACT_TIMEOUT; - break; case IEEE80211_WORK_DIRECT_PROBE: rma = ieee80211_direct_probe(wk); break;