diff --git a/[refs] b/[refs] index 576aebc5d374..b0321eed0aa9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dddc045e2fdd4eb8d7dfac29bff191d639fff8c3 +refs/heads/master: 038659e7c6b385065cb223872771ac437ef70b62 diff --git a/trunk/arch/arm/kernel/signal.c b/trunk/arch/arm/kernel/signal.c index 614c9f642878..80b8b5c7e07a 100644 --- a/trunk/arch/arm/kernel/signal.c +++ b/trunk/arch/arm/kernel/signal.c @@ -532,7 +532,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, return err; } -static inline void setup_syscall_restart(struct pt_regs *regs) +static inline void restart_syscall(struct pt_regs *regs) { regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; @@ -567,7 +567,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, } /* fallthrough */ case -ERESTARTNOINTR: - setup_syscall_restart(regs); + restart_syscall(regs); } } @@ -691,7 +691,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR) { - setup_syscall_restart(regs); + restart_syscall(regs); } } single_step_set(current); diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index 27227561bad6..803d7be0938f 100644 --- a/trunk/arch/avr32/kernel/signal.c +++ b/trunk/arch/avr32/kernel/signal.c @@ -212,7 +212,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return err; } -static inline void setup_syscall_restart(struct pt_regs *regs) +static inline void restart_syscall(struct pt_regs *regs) { if (regs->r12 == -ERESTART_RESTARTBLOCK) regs->r8 = __NR_restart_syscall; @@ -296,7 +296,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) } /* fall through */ case -ERESTARTNOINTR: - setup_syscall_restart(regs); + restart_syscall(regs); } } diff --git a/trunk/drivers/net/chelsio/cphy.h b/trunk/drivers/net/chelsio/cphy.h index 1f095a9fc739..8b5165a5af3f 100644 --- a/trunk/drivers/net/chelsio/cphy.h +++ b/trunk/drivers/net/chelsio/cphy.h @@ -137,11 +137,10 @@ static inline int simple_mdio_write(struct cphy *cphy, int reg, } /* Convenience initializer */ -static inline void cphy_init(struct cphy *phy, struct net_device *dev, +static inline void cphy_init(struct cphy *phy, adapter_t *adapter, int phy_addr, struct cphy_ops *phy_ops, const struct mdio_ops *mdio_ops) { - struct adapter *adapter = netdev_priv(dev); phy->adapter = adapter; phy->ops = phy_ops; if (mdio_ops) { @@ -151,13 +150,12 @@ static inline void cphy_init(struct cphy *phy, struct net_device *dev, phy->mdio.mdio_read = mdio_ops->read; phy->mdio.mdio_write = mdio_ops->write; } - phy->mdio.dev = dev; } /* Operations of the PHY-instance factory */ struct gphy { /* Construct a PHY instance with the given PHY address */ - struct cphy *(*create)(struct net_device *dev, int phy_addr, + struct cphy *(*create)(adapter_t *adapter, int phy_addr, const struct mdio_ops *mdio_ops); /* diff --git a/trunk/drivers/net/chelsio/mv88e1xxx.c b/trunk/drivers/net/chelsio/mv88e1xxx.c index 809047a99e96..0632be0d6494 100644 --- a/trunk/drivers/net/chelsio/mv88e1xxx.c +++ b/trunk/drivers/net/chelsio/mv88e1xxx.c @@ -353,16 +353,15 @@ static struct cphy_ops mv88e1xxx_ops = { .get_link_status = mv88e1xxx_get_link_status, }; -static struct cphy *mv88e1xxx_phy_create(struct net_device *dev, int phy_addr, +static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { - struct adapter *adapter = netdev_priv(dev); struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); if (!cphy) return NULL; - cphy_init(cphy, dev, phy_addr, &mv88e1xxx_ops, mdio_ops); + cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops); /* Configure particular PHY's to run in a different mode. */ if ((board_info(adapter)->caps & SUPPORTED_TP) && diff --git a/trunk/drivers/net/chelsio/mv88x201x.c b/trunk/drivers/net/chelsio/mv88x201x.c index f7136b2fd1e5..29e0cba48d53 100644 --- a/trunk/drivers/net/chelsio/mv88x201x.c +++ b/trunk/drivers/net/chelsio/mv88x201x.c @@ -86,8 +86,7 @@ static int mv88x201x_reset(struct cphy *cphy, int wait) static int mv88x201x_interrupt_enable(struct cphy *cphy) { /* Enable PHY LASI interrupts. */ - cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, - MDIO_PMA_LASI_LSALARM); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x1); /* Enable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -103,7 +102,7 @@ static int mv88x201x_interrupt_enable(struct cphy *cphy) static int mv88x201x_interrupt_disable(struct cphy *cphy) { /* Disable PHY LASI interrupts. */ - cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0x0); + cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x0); /* Disable Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { @@ -123,9 +122,9 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy) #ifdef MV88x2010_LINK_STATUS_BUGS /* Required to read twice before clear takes affect. */ - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val); /* Read this register after the others above it else * the register doesn't clear correctly. @@ -136,12 +135,12 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy) /* Clear link status. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); /* Clear PHY LASI interrupts. */ - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val); #ifdef MV88x2010_LINK_STATUS_BUGS /* Do it again. */ - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); - cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val); + cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val); #endif /* Clear Marvell interrupts through Elmer0. */ @@ -209,7 +208,7 @@ static struct cphy_ops mv88x201x_ops = { MDIO_DEVS_PHYXS | MDIO_DEVS_WIS), }; -static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr, +static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { u32 val; @@ -218,7 +217,7 @@ static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr, if (!cphy) return NULL; - cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops); + cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops); /* Commands the PHY to enable XFP's clock. */ cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val); diff --git a/trunk/drivers/net/chelsio/my3126.c b/trunk/drivers/net/chelsio/my3126.c index 4c6028512d10..977c7e08b0e0 100644 --- a/trunk/drivers/net/chelsio/my3126.c +++ b/trunk/drivers/net/chelsio/my3126.c @@ -167,7 +167,7 @@ static struct cphy_ops my3126_ops = { MDIO_DEVS_PHYXS), }; -static struct cphy *my3126_phy_create(struct net_device *dev, +static struct cphy *my3126_phy_create(adapter_t *adapter, int phy_addr, const struct mdio_ops *mdio_ops) { struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL); @@ -175,7 +175,7 @@ static struct cphy *my3126_phy_create(struct net_device *dev, if (!cphy) return NULL; - cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops); + cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops); INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); cphy->bmsr = 0; diff --git a/trunk/drivers/net/chelsio/subr.c b/trunk/drivers/net/chelsio/subr.c index 17720c6e5bfe..2564312b3056 100644 --- a/trunk/drivers/net/chelsio/subr.c +++ b/trunk/drivers/net/chelsio/subr.c @@ -1135,13 +1135,14 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, struct cmac *mac; int phy_addr = bi->mdio_phybaseaddr + i; - adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev, - phy_addr, bi->mdio_ops); + adapter->port[i].phy = bi->gphy->create(adapter, phy_addr, + bi->mdio_ops); if (!adapter->port[i].phy) { CH_ERR("%s: PHY %d initialization failed\n", adapter->name, i); goto error; } + adapter->port[i].phy->mdio.dev = adapter->port[i].dev; adapter->port[i].mac = mac = bi->gmac->create(adapter, i); if (!mac) { diff --git a/trunk/drivers/net/cxgb3/ael1002.c b/trunk/drivers/net/cxgb3/ael1002.c index df1f58576689..bebc00d2424d 100644 --- a/trunk/drivers/net/cxgb3/ael1002.c +++ b/trunk/drivers/net/cxgb3/ael1002.c @@ -1007,8 +1007,7 @@ static int ael2005_reset(struct cphy *phy, int wait) int err; unsigned int lasi_ctrl; - err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, - &lasi_ctrl); + err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_CTRL, &lasi_ctrl); if (err) return err; diff --git a/trunk/drivers/net/cxgb3/common.h b/trunk/drivers/net/cxgb3/common.h index 79a113b99e2f..3147789aecec 100644 --- a/trunk/drivers/net/cxgb3/common.h +++ b/trunk/drivers/net/cxgb3/common.h @@ -521,6 +521,16 @@ enum { MAC_RXFIFO_SIZE = 32768 }; +/* LASI control and status registers */ +enum { + RX_ALARM_CTRL = 0x9000, + TX_ALARM_CTRL = 0x9001, + LASI_CTRL = 0x9002, + RX_ALARM_STAT = 0x9003, + TX_ALARM_STAT = 0x9004, + LASI_STAT = 0x9005 +}; + /* PHY loopback direction */ enum { PHY_LOOPBACK_TX = 1, diff --git a/trunk/drivers/net/cxgb3/t3_hw.c b/trunk/drivers/net/cxgb3/t3_hw.c index fc7db8a9ba89..c8a865a7e26c 100644 --- a/trunk/drivers/net/cxgb3/t3_hw.c +++ b/trunk/drivers/net/cxgb3/t3_hw.c @@ -472,31 +472,29 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) int t3_phy_lasi_intr_enable(struct cphy *phy) { - return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, - MDIO_PMA_LASI_LSALARM); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 1); } int t3_phy_lasi_intr_disable(struct cphy *phy) { - return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0); + return t3_mdio_write(phy, MDIO_MMD_PMAPMD, LASI_CTRL, 0); } int t3_phy_lasi_intr_clear(struct cphy *phy) { u32 val; - return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); + return t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &val); } int t3_phy_lasi_intr_handler(struct cphy *phy) { unsigned int status; - int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, - &status); + int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, LASI_STAT, &status); if (err) return err; - return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0; + return (status & 1) ? cphy_cause_link_change : 0; } static const struct adapter_info t3_adap_info[] = { @@ -3866,11 +3864,11 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, return -EINVAL; } - p->phy.mdio.dev = adapter->port[i]; ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, ai->mdio_ops); if (ret) return ret; + p->phy.mdio.dev = adapter->port[i]; mac_prep(&p->mac, adapter, j); /* diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index 2ec98091948b..ffd731539997 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -996,11 +996,6 @@ void igb_down(struct igb_adapter *adapter) igb_reset(adapter); igb_clean_all_tx_rings(adapter); igb_clean_all_rx_rings(adapter); -#ifdef CONFIG_IGB_DCA - - /* since we reset the hardware DCA settings were cleared */ - igb_setup_dca(adapter); -#endif } void igb_reinit_locked(struct igb_adapter *adapter) @@ -1462,6 +1457,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&pdev->dev, "DCA enabled\n"); + /* Always use CB2 mode, difference is masked + * in the CB driver. */ + wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); igb_setup_dca(adapter); } #endif @@ -3773,15 +3771,11 @@ static void igb_update_tx_dca(struct igb_ring *tx_ring) static void igb_setup_dca(struct igb_adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; int i; if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) return; - /* Always use CB2 mode, difference is masked in the CB driver. */ - wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); - for (i = 0; i < adapter->num_tx_queues; i++) { adapter->tx_ring[i].cpu = -1; igb_update_tx_dca(&adapter->tx_ring[i]); diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index e52798c4816b..3d5f7f575ae3 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -411,9 +411,6 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) return; - /* always use CB2 mode, difference is masked in the CB driver */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); - for (i = 0; i < adapter->num_tx_queues; i++) { adapter->tx_ring[i].cpu = -1; ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]); @@ -435,6 +432,9 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) /* if we're already enabled, don't do it again */ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) break; + /* Always use CB2 mode, difference is masked + * in the CB driver. */ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); if (dca_add_requester(dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; ixgbe_setup_dca(adapter); @@ -2767,6 +2767,13 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); +#ifdef CONFIG_IXGBE_DCA + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { + adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; + dca_remove_requester(&adapter->pdev->dev); + } + +#endif if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); @@ -2774,7 +2781,13 @@ void ixgbe_down(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCA /* since we reset the hardware DCA settings were cleared */ - ixgbe_setup_dca(adapter); + if (dca_add_requester(&adapter->pdev->dev) == 0) { + adapter->flags |= IXGBE_FLAG_DCA_ENABLED; + /* always use CB2 mode, difference is masked + * in the CB driver */ + IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); + ixgbe_setup_dca(adapter); + } #endif } @@ -5341,6 +5354,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, #ifdef CONFIG_IXGBE_DCA if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; + /* always use CB2 mode, difference is masked + * in the CB driver */ + IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2); ixgbe_setup_dca(adapter); } #endif diff --git a/trunk/drivers/net/mlx4/en_cq.c b/trunk/drivers/net/mlx4/en_cq.c index 21786ad4455e..a276125b709b 100644 --- a/trunk/drivers/net/mlx4/en_cq.c +++ b/trunk/drivers/net/mlx4/en_cq.c @@ -89,9 +89,6 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) *cq->mcq.arm_db = 0; memset(cq->buf, 0, cq->buf_size); - if (!cq->is_tx) - cq->size = priv->rx_ring[cq->ring].actual_size; - err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx); if (err) diff --git a/trunk/drivers/net/mlx4/en_netdev.c b/trunk/drivers/net/mlx4/en_netdev.c index 0cd185a2e089..7bcc49de1637 100644 --- a/trunk/drivers/net/mlx4/en_netdev.c +++ b/trunk/drivers/net/mlx4/en_netdev.c @@ -556,8 +556,10 @@ int mlx4_en_start_port(struct net_device *dev) struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_cq *cq; struct mlx4_en_tx_ring *tx_ring; + struct mlx4_en_rx_ring *rx_ring; int rx_index = 0; int tx_index = 0; + u16 stride; int err = 0; int i; int j; @@ -571,15 +573,12 @@ int mlx4_en_start_port(struct net_device *dev) dev->mtu = min(dev->mtu, priv->max_mtu); mlx4_en_calc_rx_buf(dev); mlx4_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_skb_size); - + stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) + + DS_SIZE * priv->num_frags); /* Configure rx cq's and rings */ - err = mlx4_en_activate_rx_rings(priv); - if (err) { - mlx4_err(mdev, "Failed to activate RX rings\n"); - return err; - } for (i = 0; i < priv->rx_ring_num; i++) { cq = &priv->rx_cq[i]; + rx_ring = &priv->rx_ring[i]; err = mlx4_en_activate_cq(priv, cq); if (err) { @@ -595,14 +594,20 @@ int mlx4_en_start_port(struct net_device *dev) goto cq_err; } mlx4_en_arm_cq(priv, cq); - priv->rx_ring[i].cqn = cq->mcq.cqn; + ++rx_index; } + err = mlx4_en_activate_rx_rings(priv); + if (err) { + mlx4_err(mdev, "Failed to activate RX rings\n"); + goto cq_err; + } + err = mlx4_en_config_rss_steer(priv); if (err) { mlx4_err(mdev, "Failed configuring rss steering\n"); - goto cq_err; + goto rx_err; } /* Configure tx cq's and rings */ @@ -689,11 +694,12 @@ int mlx4_en_start_port(struct net_device *dev) } mlx4_en_release_rss_steer(priv); +rx_err: + for (i = 0; i < priv->rx_ring_num; i++) + mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); cq_err: while (rx_index--) mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); - for (i = 0; i < priv->rx_ring_num; i++) - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); return err; /* need to close devices */ } diff --git a/trunk/drivers/net/mlx4/en_rx.c b/trunk/drivers/net/mlx4/en_rx.c index 6bfab6e5ba1d..9ee873e872b3 100644 --- a/trunk/drivers/net/mlx4/en_rx.c +++ b/trunk/drivers/net/mlx4/en_rx.c @@ -202,35 +202,12 @@ static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring) *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff); } -static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, - int index) -{ - struct mlx4_en_dev *mdev = priv->mdev; - struct skb_frag_struct *skb_frags; - struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride); - dma_addr_t dma; - int nr; - - skb_frags = ring->rx_info + (index << priv->log_rx_info); - for (nr = 0; nr < priv->num_frags; nr++) { - mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr); - dma = be64_to_cpu(rx_desc->data[nr].addr); - - mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma); - pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, - PCI_DMA_FROMDEVICE); - put_page(skb_frags[nr].page); - } -} - static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_rx_ring *ring; int ring_ind; int buf_ind; - int new_size; for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) { for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { @@ -243,30 +220,18 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) "enough rx buffers\n"); return -ENOMEM; } else { - new_size = rounddown_pow_of_two(ring->actual_size); - mlx4_warn(mdev, "Only %d buffers allocated " - "reducing ring size to %d", - ring->actual_size, new_size); - goto reduce_rings; + if (netif_msg_rx_err(priv)) + mlx4_warn(mdev, + "Only %d buffers allocated\n", + ring->actual_size); + goto out; } } ring->actual_size++; ring->prod++; } } - return 0; - -reduce_rings: - for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) { - ring = &priv->rx_ring[ring_ind]; - while (ring->actual_size > new_size) { - ring->actual_size--; - ring->prod--; - mlx4_en_free_rx_desc(priv, ring, ring->actual_size); - } - ring->size_mask = ring->actual_size - 1; - } - +out: return 0; } @@ -290,7 +255,7 @@ static int mlx4_en_fill_rx_buf(struct net_device *dev, ++num; ++ring->prod; } - if ((u32) (ring->prod - ring->cons) == ring->actual_size) + if ((u32) (ring->prod - ring->cons) == ring->size) ring->full = 1; return num; @@ -299,17 +264,33 @@ static int mlx4_en_fill_rx_buf(struct net_device *dev, static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring) { + struct mlx4_en_dev *mdev = priv->mdev; + struct skb_frag_struct *skb_frags; + struct mlx4_en_rx_desc *rx_desc; + dma_addr_t dma; int index; + int nr; mlx4_dbg(DRV, priv, "Freeing Rx buf - cons:%d prod:%d\n", ring->cons, ring->prod); /* Unmap and free Rx buffers */ - BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size); + BUG_ON((u32) (ring->prod - ring->cons) > ring->size); while (ring->cons != ring->prod) { index = ring->cons & ring->size_mask; + rx_desc = ring->buf + (index << ring->log_stride); + skb_frags = ring->rx_info + (index << priv->log_rx_info); mlx4_dbg(DRV, priv, "Processing descriptor:%d\n", index); - mlx4_en_free_rx_desc(priv, ring, index); + + for (nr = 0; nr < priv->num_frags; nr++) { + mlx4_dbg(DRV, priv, "Freeing fragment:%d\n", nr); + dma = be64_to_cpu(rx_desc->data[nr].addr); + + mlx4_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma); + pci_unmap_single(mdev->pdev, dma, skb_frags[nr].size, + PCI_DMA_FROMDEVICE); + put_page(skb_frags[nr].page); + } ++ring->cons; } } @@ -473,7 +454,7 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) mlx4_en_update_rx_prod_db(ring); /* Configure SRQ representing the ring */ - ring->srq.max = ring->actual_size; + ring->srq.max = ring->size; ring->srq.max_gs = max_gs; ring->srq.wqe_shift = ilog2(ring->stride); diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 7e28b4610122..c9a9aca43675 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.5.0-1.418" +#define MYRI10GE_VERSION_STR "1.5.0-1.415" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -327,6 +327,10 @@ static int myri10ge_debug = -1; /* defaults above */ module_param(myri10ge_debug, int, 0); MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); +static int myri10ge_lro = 1; +module_param(myri10ge_lro, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload"); + static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS; module_param(myri10ge_lro_max_pkts, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_lro_max_pkts, @@ -1418,7 +1422,6 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) { struct myri10ge_rx_done *rx_done = &ss->rx_done; struct myri10ge_priv *mgp = ss->mgp; - struct net_device *netdev = mgp->dev; unsigned long rx_bytes = 0; unsigned long rx_packets = 0; unsigned long rx_ok; @@ -1452,7 +1455,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ss->stats.rx_packets += rx_packets; ss->stats.rx_bytes += rx_bytes; - if (netdev->features & NETIF_F_LRO) + if (myri10ge_lro) lro_flush_all(&rx_done->lro_mgr); /* restock receive rings if needed */ @@ -3914,13 +3917,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dac_enabled) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LRO; - - netdev->vlan_features |= mgp->features; - if (mgp->fw_ver_tiny < 37) - netdev->vlan_features &= ~NETIF_F_TSO6; - if (mgp->fw_ver_tiny < 32) - netdev->vlan_features &= ~NETIF_F_TSO; + if (myri10ge_lro) + netdev->features |= NETIF_F_LRO; /* make sure we can get an irq, and that MSI can be * setup (if available). Also ensure netdev->irq diff --git a/trunk/drivers/net/wireless/ath/regd.c b/trunk/drivers/net/wireless/ath/regd.c index fdf07c822081..7a89f9fac7d4 100644 --- a/trunk/drivers/net/wireless/ath/regd.c +++ b/trunk/drivers/net/wireless/ath/regd.c @@ -200,8 +200,10 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, ch->center_freq, - &bandwidth, ®_rule); + r = freq_reg_info(wiphy, + ch->center_freq, + bandwidth, + ®_rule); if (r) continue; /* @@ -265,7 +267,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, */ ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) @@ -273,7 +275,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, } ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) diff --git a/trunk/drivers/s390/net/ctcm_main.c b/trunk/drivers/s390/net/ctcm_main.c index 54c4649a493b..77f4033a0f4f 100644 --- a/trunk/drivers/s390/net/ctcm_main.c +++ b/trunk/drivers/s390/net/ctcm_main.c @@ -1677,8 +1677,10 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev) BUG_ON(priv == NULL); CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, - "removing device %p, proto : %d", - cgdev, priv->protocol); + "removing device %s, r/w = %s/%s, proto : %d", + priv->channel[READ]->netdev->name, + priv->channel[READ]->id, priv->channel[WRITE]->id, + priv->protocol); if (cgdev->state == CCWGROUP_ONLINE) ctcm_shutdown_device(cgdev); diff --git a/trunk/drivers/s390/net/qeth_core_main.c b/trunk/drivers/s390/net/qeth_core_main.c index 2994aa1ed466..c827d69b5a91 100644 --- a/trunk/drivers/s390/net/qeth_core_main.c +++ b/trunk/drivers/s390/net/qeth_core_main.c @@ -952,7 +952,6 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, buf->buffer->element[i].addr = NULL; buf->buffer->element[i].flags = 0; } - buf->buffer->element[15].flags = 0; buf->next_element_to_fill = 0; atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } @@ -1141,8 +1140,6 @@ static int qeth_setup_card(struct qeth_card *card) card->ipato.enabled = 0; card->ipato.invert4 = 0; card->ipato.invert6 = 0; - if (card->info.type == QETH_CARD_TYPE_IQD) - card->options.checksum_type = NO_CHECKSUMMING; /* init QDIO stuff */ qeth_init_qdio_info(card); return 0; diff --git a/trunk/drivers/s390/net/qeth_core_mpc.c b/trunk/drivers/s390/net/qeth_core_mpc.c index ec24901c802c..06f4de1f0507 100644 --- a/trunk/drivers/s390/net/qeth_core_mpc.c +++ b/trunk/drivers/s390/net/qeth_core_mpc.c @@ -181,8 +181,6 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"}, {IPA_RC_L2_DUP_LAYER3_MAC, "Duplicate with layer 3 MAC"}, {IPA_RC_L2_GMAC_NOT_FOUND, "GMAC not found"}, - {IPA_RC_L2_MAC_NOT_AUTH_BY_HYP, "L2 mac not authorized by hypervisor"}, - {IPA_RC_L2_MAC_NOT_AUTH_BY_ADP, "L2 mac not authorized by adapter"}, {IPA_RC_L2_MAC_NOT_FOUND, "L2 mac address not found"}, {IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"}, {IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"}, diff --git a/trunk/drivers/s390/net/qeth_core_mpc.h b/trunk/drivers/s390/net/qeth_core_mpc.h index eecb2ee62e85..18548822e37c 100644 --- a/trunk/drivers/s390/net/qeth_core_mpc.h +++ b/trunk/drivers/s390/net/qeth_core_mpc.h @@ -168,8 +168,6 @@ enum qeth_ipa_return_codes { IPA_RC_L2_ADDR_TABLE_FULL = 0x2006, IPA_RC_L2_DUP_LAYER3_MAC = 0x200a, IPA_RC_L2_GMAC_NOT_FOUND = 0x200b, - IPA_RC_L2_MAC_NOT_AUTH_BY_HYP = 0x200c, - IPA_RC_L2_MAC_NOT_AUTH_BY_ADP = 0x200d, IPA_RC_L2_MAC_NOT_FOUND = 0x2010, IPA_RC_L2_INVALID_VLAN_ID = 0x2015, IPA_RC_L2_DUP_VLAN_ID = 0x2016, diff --git a/trunk/drivers/s390/net/qeth_l2_main.c b/trunk/drivers/s390/net/qeth_l2_main.c index 9ca6bab7c9ba..172031baedc1 100644 --- a/trunk/drivers/s390/net/qeth_l2_main.c +++ b/trunk/drivers/s390/net/qeth_l2_main.c @@ -130,7 +130,7 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; mac = &cmd->data.setdelmac.mac[0]; /* MAC already registered, needed in couple/uncouple case */ - if (cmd->hdr.return_code == IPA_RC_L2_DUP_MAC) { + if (cmd->hdr.return_code == 0x2005) { QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s \n", mac, QETH_CARD_IFNAME(card)); cmd->hdr.return_code = 0; @@ -502,30 +502,6 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, if (cmd->hdr.return_code) { QETH_DBF_TEXT_(TRACE, 2, "L2er%x", cmd->hdr.return_code); card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; - switch (cmd->hdr.return_code) { - case IPA_RC_L2_DUP_MAC: - case IPA_RC_L2_DUP_LAYER3_MAC: - dev_warn(&card->gdev->dev, - "MAC address " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - "already exists\n", - card->dev->dev_addr[0], card->dev->dev_addr[1], - card->dev->dev_addr[2], card->dev->dev_addr[3], - card->dev->dev_addr[4], card->dev->dev_addr[5]); - break; - case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: - case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: - dev_warn(&card->gdev->dev, - "MAC address " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - "is not authorized\n", - card->dev->dev_addr[0], card->dev->dev_addr[1], - card->dev->dev_addr[2], card->dev->dev_addr[3], - card->dev->dev_addr[4], card->dev->dev_addr[5]); - break; - default: - break; - } cmd->hdr.return_code = -EIO; } else { card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; @@ -863,7 +839,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) { @@ -999,9 +974,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) dev_warn(&card->gdev->dev, "The LAN is offline\n"); card->lan_online = 0; - return 0; } - goto out_remove; + return rc; } else card->lan_online = 1; diff --git a/trunk/drivers/s390/net/qeth_l3_main.c b/trunk/drivers/s390/net/qeth_l3_main.c index b36b5cdf9000..0ba3817cb6a7 100644 --- a/trunk/drivers/s390/net/qeth_l3_main.c +++ b/trunk/drivers/s390/net/qeth_l3_main.c @@ -1920,22 +1920,16 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); } - switch (card->options.checksum_type) { - case SW_CHECKSUMMING: - skb->ip_summed = CHECKSUM_NONE; - break; - case NO_CHECKSUMMING: - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - case HW_CHECKSUMMING: + skb->ip_summed = card->options.checksum_type; + if (card->options.checksum_type == HW_CHECKSUMMING) { if ((hdr->hdr.l3.ext_flags & - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) == - (QETH_HDR_EXT_CSUM_HDR_REQ | - QETH_HDR_EXT_CSUM_TRANSP_REQ)) + (QETH_HDR_EXT_CSUM_HDR_REQ | + QETH_HDR_EXT_CSUM_TRANSP_REQ)) == + (QETH_HDR_EXT_CSUM_HDR_REQ | + QETH_HDR_EXT_CSUM_TRANSP_REQ)) skb->ip_summed = CHECKSUM_UNNECESSARY; else - skb->ip_summed = CHECKSUM_NONE; + skb->ip_summed = SW_CHECKSUMMING; } return vlan_id; @@ -3076,7 +3070,6 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (cgdev->state == CCWGROUP_ONLINE) { @@ -3148,9 +3141,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) dev_warn(&card->gdev->dev, "The LAN is offline\n"); card->lan_online = 0; - return 0; } - goto out_remove; + return rc; } else card->lan_online = 1; qeth_set_large_send(card, card->options.large_send); diff --git a/trunk/include/linux/if_packet.h b/trunk/include/linux/if_packet.h index dea7d6b7cf98..5b2badeb9497 100644 --- a/trunk/include/linux/if_packet.h +++ b/trunk/include/linux/if_packet.h @@ -145,6 +145,5 @@ struct packet_mreq #define PACKET_MR_MULTICAST 0 #define PACKET_MR_PROMISC 1 #define PACKET_MR_ALLMULTI 2 -#define PACKET_MR_UNICAST 3 #endif diff --git a/trunk/include/linux/net_dropmon.h b/trunk/include/linux/net_dropmon.h index e8a8b5c50ed0..0217fb81a630 100644 --- a/trunk/include/linux/net_dropmon.h +++ b/trunk/include/linux/net_dropmon.h @@ -2,20 +2,12 @@ #define __NET_DROPMON_H #include -#include struct net_dm_drop_point { __u8 pc[8]; __u32 count; }; -#define is_drop_point_hw(x) do {\ - int ____i, ____j;\ - for (____i = 0; ____i < 8; i ____i++)\ - ____j |= x[____i];\ - ____j;\ -} while (0) - #define NET_DM_CFG_VERSION 0 #define NET_DM_CFG_ALERT_COUNT 1 #define NET_DM_CFG_ALERT_DELAY 2 diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 9e17a83d3432..282d58d52fce 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -70,6 +70,9 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, }; +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_FAT_ABOVE | IEEE80211_CHAN_NO_FAT_BELOW) + /** * struct ieee80211_channel - channel definition * @@ -1303,9 +1306,10 @@ extern void wiphy_apply_custom_regulatory( * freq_reg_info - get regulatory information for the given frequency * @wiphy: the wiphy for which we want to process this rule for * @center_freq: Frequency in KHz for which we want regulatory information for - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. + * @desired_bw_khz: the desired max bandwidth you want to use per + * channel. Note that this is still 20 MHz if you want to use HT40 + * as HT40 makes use of two channels for its 40 MHz width bandwidth. + * If set to 0 we'll assume you want the standard 20 MHz. * @reg_rule: the regulatory rule which we have for this frequency * * Use this function to get the regulatory rule for a specific frequency on @@ -1320,7 +1324,9 @@ extern void wiphy_apply_custom_regulatory( * freq_in_rule_band() for our current definition of a band -- this is purely * subjective and right now its 802.11 specific. */ -extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, +extern int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule); /* diff --git a/trunk/include/net/fib_rules.h b/trunk/include/net/fib_rules.h index ca4b2e840078..b9b63395d002 100644 --- a/trunk/include/net/fib_rules.h +++ b/trunk/include/net/fib_rules.h @@ -54,6 +54,7 @@ struct fib_rules_ops struct fib_rule_hdr *, struct nlattr **); int (*fill)(struct fib_rule *, struct sk_buff *, + struct nlmsghdr *, struct fib_rule_hdr *); u32 (*default_pref)(struct fib_rules_ops *ops); size_t (*nlmsg_payload)(struct fib_rule *); diff --git a/trunk/include/net/genetlink.h b/trunk/include/net/genetlink.h index 1b0e3ee4ddd8..747c255d1df0 100644 --- a/trunk/include/net/genetlink.h +++ b/trunk/include/net/genetlink.h @@ -88,8 +88,6 @@ struct genl_ops }; extern int genl_register_family(struct genl_family *family); -extern int genl_register_family_with_ops(struct genl_family *family, - struct genl_ops *ops, size_t n_ops); extern int genl_unregister_family(struct genl_family *family); extern int genl_register_ops(struct genl_family *, struct genl_ops *ops); extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops); diff --git a/trunk/include/trace/napi.h b/trunk/include/trace/napi.h deleted file mode 100644 index a8989c4547e7..000000000000 --- a/trunk/include/trace/napi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _TRACE_NAPI_H_ -#define _TRACE_NAPI_H_ - -#include -#include - -DECLARE_TRACE(napi_poll, - TP_PROTO(struct napi_struct *napi), - TP_ARGS(napi)); - -#endif diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 3942266d1f6c..92ebeca29901 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -126,7 +126,6 @@ #include #include #include -#include #include "net-sysfs.h" @@ -2772,10 +2771,8 @@ static void net_rx_action(struct softirq_action *h) * accidently calling ->poll() when NAPI is not scheduled. */ work = 0; - if (test_bit(NAPI_STATE_SCHED, &n->state)) { + if (test_bit(NAPI_STATE_SCHED, &n->state)) work = n->poll(n, weight); - trace_napi_poll(n); - } WARN_ON_ONCE(work > weight); diff --git a/trunk/net/core/drop_monitor.c b/trunk/net/core/drop_monitor.c index a6c2ac2828fb..2797b711a978 100644 --- a/trunk/net/core/drop_monitor.c +++ b/trunk/net/core/drop_monitor.c @@ -22,10 +22,8 @@ #include #include #include -#include #include -#include #include @@ -40,8 +38,7 @@ static void send_dm_alert(struct work_struct *unused); * and the work handle that will send up * netlink alerts */ -static int trace_state = TRACE_OFF; -static spinlock_t trace_state_lock = SPIN_LOCK_UNLOCKED; +struct sock *dm_sock; struct per_cpu_dm_data { struct work_struct dm_alert_work; @@ -50,13 +47,6 @@ struct per_cpu_dm_data { struct timer_list send_timer; }; -struct dm_hw_stat_delta { - struct net_device *dev; - struct list_head list; - struct rcu_head rcu; - unsigned long last_drop_val; -}; - static struct genl_family net_drop_monitor_family = { .id = GENL_ID_GENERATE, .hdrsize = 0, @@ -69,8 +59,7 @@ static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); static int dm_hit_limit = 64; static int dm_delay = 1; -static unsigned long dm_hw_check_delta = 2*HZ; -static LIST_HEAD(hw_stats_list); + static void reset_per_cpu_data(struct per_cpu_dm_data *data) { @@ -126,7 +115,7 @@ static void sched_send_work(unsigned long unused) schedule_work(&data->dm_alert_work); } -static void trace_drop_common(struct sk_buff *skb, void *location) +static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) { struct net_dm_alert_msg *msg; struct nlmsghdr *nlh; @@ -170,80 +159,24 @@ static void trace_drop_common(struct sk_buff *skb, void *location) return; } -static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) -{ - trace_drop_common(skb, location); -} - -static void trace_napi_poll_hit(struct napi_struct *napi) -{ - struct dm_hw_stat_delta *new_stat; - - /* - * Ratelimit our check time to dm_hw_check_delta jiffies - */ - if (!time_after(jiffies, napi->dev->last_rx + dm_hw_check_delta)) - return; - - rcu_read_lock(); - list_for_each_entry_rcu(new_stat, &hw_stats_list, list) { - if ((new_stat->dev == napi->dev) && - (napi->dev->stats.rx_dropped != new_stat->last_drop_val)) { - trace_drop_common(NULL, NULL); - new_stat->last_drop_val = napi->dev->stats.rx_dropped; - break; - } - } - rcu_read_unlock(); -} - - -static void free_dm_hw_stat(struct rcu_head *head) -{ - struct dm_hw_stat_delta *n; - n = container_of(head, struct dm_hw_stat_delta, rcu); - kfree(n); -} - static int set_all_monitor_traces(int state) { int rc = 0; - struct dm_hw_stat_delta *new_stat = NULL; - struct dm_hw_stat_delta *temp; - - spin_lock(&trace_state_lock); switch (state) { case TRACE_ON: rc |= register_trace_kfree_skb(trace_kfree_skb_hit); - rc |= register_trace_napi_poll(trace_napi_poll_hit); break; case TRACE_OFF: rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit); - rc |= unregister_trace_napi_poll(trace_napi_poll_hit); tracepoint_synchronize_unregister(); - - /* - * Clean the device list - */ - list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) { - if (new_stat->dev == NULL) { - list_del_rcu(&new_stat->list); - call_rcu(&new_stat->rcu, free_dm_hw_stat); - } - } break; default: rc = 1; break; } - if (!rc) - trace_state = state; - - spin_unlock(&trace_state_lock); - if (rc) return -EINPROGRESS; return rc; @@ -271,44 +204,6 @@ static int net_dm_cmd_trace(struct sk_buff *skb, return -ENOTSUPP; } -static int dropmon_net_event(struct notifier_block *ev_block, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - struct dm_hw_stat_delta *new_stat = NULL; - struct dm_hw_stat_delta *tmp; - - switch (event) { - case NETDEV_REGISTER: - new_stat = kzalloc(sizeof(struct dm_hw_stat_delta), GFP_KERNEL); - - if (!new_stat) - goto out; - - new_stat->dev = dev; - INIT_RCU_HEAD(&new_stat->rcu); - spin_lock(&trace_state_lock); - list_add_rcu(&new_stat->list, &hw_stats_list); - spin_unlock(&trace_state_lock); - break; - case NETDEV_UNREGISTER: - spin_lock(&trace_state_lock); - list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) { - if (new_stat->dev == dev) { - new_stat->dev = NULL; - if (trace_state == TRACE_OFF) { - list_del_rcu(&new_stat->list); - call_rcu(&new_stat->rcu, free_dm_hw_stat); - break; - } - } - } - spin_unlock(&trace_state_lock); - break; - } -out: - return NOTIFY_DONE; -} static struct genl_ops dropmon_ops[] = { { @@ -325,10 +220,6 @@ static struct genl_ops dropmon_ops[] = { }, }; -static struct notifier_block dropmon_net_notifier = { - .notifier_call = dropmon_net_event -}; - static int __init init_net_drop_monitor(void) { int cpu; @@ -352,18 +243,12 @@ static int __init init_net_drop_monitor(void) ret = genl_register_ops(&net_drop_monitor_family, &dropmon_ops[i]); if (ret) { - printk(KERN_CRIT "Failed to register operation %d\n", + printk(KERN_CRIT "failed to register operation %d\n", dropmon_ops[i].cmd); goto out_unreg; } } - rc = register_netdevice_notifier(&dropmon_net_notifier); - if (rc < 0) { - printk(KERN_CRIT "Failed to register netdevice notifier\n"); - goto out_unreg; - } - rc = 0; for_each_present_cpu(cpu) { @@ -374,7 +259,6 @@ static int __init init_net_drop_monitor(void) data->send_timer.data = cpu; data->send_timer.function = sched_send_work; } - goto out; out_unreg: diff --git a/trunk/net/core/fib_rules.c b/trunk/net/core/fib_rules.c index bd309384f8b8..17d9f497b797 100644 --- a/trunk/net/core/fib_rules.c +++ b/trunk/net/core/fib_rules.c @@ -500,7 +500,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, if (rule->target) NLA_PUT_U32(skb, FRA_GOTO, rule->target); - if (ops->fill(rule, skb, frh) < 0) + if (ops->fill(rule, skb, nlh, frh) < 0) goto nla_put_failure; return nlmsg_end(skb, nlh); diff --git a/trunk/net/core/net-traces.c b/trunk/net/core/net-traces.c index b07b25bd2cde..c8fb45665e4f 100644 --- a/trunk/net/core/net-traces.c +++ b/trunk/net/core/net-traces.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -28,6 +27,3 @@ DEFINE_TRACE(kfree_skb); EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); - -DEFINE_TRACE(napi_poll); -EXPORT_TRACEPOINT_SYMBOL_GPL(napi_poll); diff --git a/trunk/net/core/net_namespace.c b/trunk/net/core/net_namespace.c index b7292a2719dc..6b3edc9e6f19 100644 --- a/trunk/net/core/net_namespace.c +++ b/trunk/net/core/net_namespace.c @@ -196,7 +196,9 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) static int __init net_ns_init(void) { struct net_generic *ng; + int err; + printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net)); #ifdef CONFIG_NET_NS net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), SMP_CACHE_BYTES, @@ -215,14 +217,15 @@ static int __init net_ns_init(void) rcu_assign_pointer(init_net.gen, ng); mutex_lock(&net_mutex); - if (setup_net(&init_net)) - panic("Could not setup the initial network namespace"); + err = setup_net(&init_net); rtnl_lock(); list_add_tail(&init_net.list, &net_namespace_list); rtnl_unlock(); mutex_unlock(&net_mutex); + if (err) + panic("Could not setup the initial network namespace"); return 0; } diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index 67b4f3e3d4a5..64f51eec6576 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -24,7 +24,6 @@ #include #include #include -#include /* * We maintain a small pool of fully-sized skbs, to make sure the @@ -138,7 +137,6 @@ static int poll_one_napi(struct netpoll_info *npinfo, set_bit(NAPI_STATE_NPSVC, &napi->state); work = napi->poll(napi, budget); - trace_napi_poll(napi); clear_bit(NAPI_STATE_NPSVC, &napi->state); atomic_dec(&trapped); diff --git a/trunk/net/decnet/dn_rules.c b/trunk/net/decnet/dn_rules.c index 72495f25269f..a2690b12e03c 100644 --- a/trunk/net/decnet/dn_rules.c +++ b/trunk/net/decnet/dn_rules.c @@ -192,7 +192,7 @@ unsigned dnet_addr_type(__le16 addr) } static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct fib_rule_hdr *frh) + struct nlmsghdr *nlh, struct fib_rule_hdr *frh) { struct dn_fib_rule *r = (struct dn_fib_rule *)rule; diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index 92d9d97ec5e3..38904be4102e 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -209,7 +209,7 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, } static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct fib_rule_hdr *frh) + struct nlmsghdr *nlh, struct fib_rule_hdr *frh) { struct fib4_rule *rule4 = (struct fib4_rule *) rule; diff --git a/trunk/net/ipv6/fib6_rules.c b/trunk/net/ipv6/fib6_rules.c index 00a7a5e4ac97..e1a36dbb5a27 100644 --- a/trunk/net/ipv6/fib6_rules.c +++ b/trunk/net/ipv6/fib6_rules.c @@ -211,7 +211,7 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, } static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct fib_rule_hdr *frh) + struct nlmsghdr *nlh, struct fib_rule_hdr *frh) { struct fib6_rule *rule6 = (struct fib6_rule *) rule; diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index ea37741062a9..d9dd94b6bf66 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -941,8 +941,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } -static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, - struct sk_buff *skb) +struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) { struct ipv6hdr *iph = skb_gro_network_header(skb); @@ -962,8 +961,9 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, return tcp_gro_receive(head, skb); } +EXPORT_SYMBOL(tcp6_gro_receive); -static int tcp6_gro_complete(struct sk_buff *skb) +int tcp6_gro_complete(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); struct tcphdr *th = tcp_hdr(skb); @@ -974,6 +974,7 @@ static int tcp6_gro_complete(struct sk_buff *skb) return tcp_gro_complete(skb); } +EXPORT_SYMBOL(tcp6_gro_complete); static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, struct tcp_md5sig_key *key, int rst) diff --git a/trunk/net/irda/irnetlink.c b/trunk/net/irda/irnetlink.c index 8dd7ed7e7c1f..82c6118d82c6 100644 --- a/trunk/net/irda/irnetlink.c +++ b/trunk/net/irda/irnetlink.c @@ -148,8 +148,21 @@ static struct genl_ops irda_nl_ops[] = { int irda_nl_register(void) { - return genl_register_family_with_ops(&irda_nl_family, - irda_nl_ops, ARRAY_SIZE(irda_nl_ops)); + int err, i; + + err = genl_register_family(&irda_nl_family); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) { + err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]); + if (err) + goto err_out; + } + return 0; + err_out: + genl_unregister_family(&irda_nl_family); + return err; } void irda_nl_unregister(void) diff --git a/trunk/net/netfilter/ipvs/ip_vs_ctl.c b/trunk/net/netfilter/ipvs/ip_vs_ctl.c index 7c1333c67ff3..e01061f49cdc 100644 --- a/trunk/net/netfilter/ipvs/ip_vs_ctl.c +++ b/trunk/net/netfilter/ipvs/ip_vs_ctl.c @@ -3345,8 +3345,22 @@ static struct genl_ops ip_vs_genl_ops[] __read_mostly = { static int __init ip_vs_genl_register(void) { - return genl_register_family_with_ops(&ip_vs_genl_family, - ip_vs_genl_ops, ARRAY_SIZE(ip_vs_genl_ops)); + int ret, i; + + ret = genl_register_family(&ip_vs_genl_family); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(ip_vs_genl_ops); i++) { + ret = genl_register_ops(&ip_vs_genl_family, &ip_vs_genl_ops[i]); + if (ret) + goto err_out; + } + return 0; + +err_out: + genl_unregister_family(&ip_vs_genl_family); + return ret; } static void ip_vs_genl_unregister(void) diff --git a/trunk/net/netlabel/netlabel_cipso_v4.c b/trunk/net/netlabel/netlabel_cipso_v4.c index e639298bc9c8..bf1ab1a6790d 100644 --- a/trunk/net/netlabel/netlabel_cipso_v4.c +++ b/trunk/net/netlabel/netlabel_cipso_v4.c @@ -785,6 +785,18 @@ static struct genl_ops netlbl_cipsov4_ops[] = { */ int __init netlbl_cipsov4_genl_init(void) { - return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family, - netlbl_cipsov4_ops, ARRAY_SIZE(netlbl_cipsov4_ops)); + int ret_val, i; + + ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); + if (ret_val != 0) + return ret_val; + + for (i = 0; i < ARRAY_SIZE(netlbl_cipsov4_ops); i++) { + ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, + &netlbl_cipsov4_ops[i]); + if (ret_val != 0) + return ret_val; + } + + return 0; } diff --git a/trunk/net/netlabel/netlabel_mgmt.c b/trunk/net/netlabel/netlabel_mgmt.c index 8203623e65ad..1821c5d50fb8 100644 --- a/trunk/net/netlabel/netlabel_mgmt.c +++ b/trunk/net/netlabel/netlabel_mgmt.c @@ -779,6 +779,18 @@ static struct genl_ops netlbl_mgmt_genl_ops[] = { */ int __init netlbl_mgmt_genl_init(void) { - return genl_register_family_with_ops(&netlbl_mgmt_gnl_family, - netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops)); + int ret_val, i; + + ret_val = genl_register_family(&netlbl_mgmt_gnl_family); + if (ret_val != 0) + return ret_val; + + for (i = 0; i < ARRAY_SIZE(netlbl_mgmt_genl_ops); i++) { + ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, + &netlbl_mgmt_genl_ops[i]); + if (ret_val != 0) + return ret_val; + } + + return 0; } diff --git a/trunk/net/netlabel/netlabel_unlabeled.c b/trunk/net/netlabel/netlabel_unlabeled.c index fb357f010189..f3c5c68c6848 100644 --- a/trunk/net/netlabel/netlabel_unlabeled.c +++ b/trunk/net/netlabel/netlabel_unlabeled.c @@ -1478,8 +1478,20 @@ static struct genl_ops netlbl_unlabel_genl_ops[] = { */ int __init netlbl_unlabel_genl_init(void) { - return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, - netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops)); + int ret_val, i; + + ret_val = genl_register_family(&netlbl_unlabel_gnl_family); + if (ret_val != 0) + return ret_val; + + for (i = 0; i < ARRAY_SIZE(netlbl_unlabel_genl_ops); i++) { + ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, + &netlbl_unlabel_genl_ops[i]); + if (ret_val != 0) + return ret_val; + } + + return 0; } /* diff --git a/trunk/net/netlink/genetlink.c b/trunk/net/netlink/genetlink.c index eed4c6a8afc0..1d3dd30099df 100644 --- a/trunk/net/netlink/genetlink.c +++ b/trunk/net/netlink/genetlink.c @@ -383,52 +383,6 @@ int genl_register_family(struct genl_family *family) return err; } -/** - * genl_register_family_with_ops - register a generic netlink family - * @family: generic netlink family - * @ops: operations to be registered - * @n_ops: number of elements to register - * - * Registers the specified family and operations from the specified table. - * Only one family may be registered with the same family name or identifier. - * - * The family id may equal GENL_ID_GENERATE causing an unique id to - * be automatically generated and assigned. - * - * Either a doit or dumpit callback must be specified for every registered - * operation or the function will fail. Only one operation structure per - * command identifier may be registered. - * - * See include/net/genetlink.h for more documenation on the operations - * structure. - * - * This is equivalent to calling genl_register_family() followed by - * genl_register_ops() for every operation entry in the table taking - * care to unregister the family on error path. - * - * Return 0 on success or a negative error code. - */ -int genl_register_family_with_ops(struct genl_family *family, - struct genl_ops *ops, size_t n_ops) -{ - int err, i; - - err = genl_register_family(family); - if (err) - return err; - - for (i = 0; i < n_ops; ++i, ++ops) { - err = genl_register_ops(family, ops); - if (err) - goto err_out; - } - return 0; -err_out: - genl_unregister_family(family); - return err; -} -EXPORT_SYMBOL(genl_register_family_with_ops); - /** * genl_unregister_family - unregister generic netlink family * @family: generic netlink family diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index c7c5d524967e..766e6b41f7ca 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -1570,9 +1570,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, switch (i->type) { case PACKET_MR_MULTICAST: if (what > 0) - return dev_mc_add(dev, i->addr, i->alen, 0); + dev_mc_add(dev, i->addr, i->alen, 0); else - return dev_mc_delete(dev, i->addr, i->alen, 0); + dev_mc_delete(dev, i->addr, i->alen, 0); break; case PACKET_MR_PROMISC: return dev_set_promiscuity(dev, what); @@ -1580,12 +1580,6 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, case PACKET_MR_ALLMULTI: return dev_set_allmulti(dev, what); break; - case PACKET_MR_UNICAST: - if (what > 0) - return dev_unicast_add(dev, i->addr, i->alen); - else - return dev_unicast_delete(dev, i->addr, i->alen); - break; default:; } return 0; diff --git a/trunk/net/tipc/netlink.c b/trunk/net/tipc/netlink.c index 3c57005e44d1..c387217bb230 100644 --- a/trunk/net/tipc/netlink.c +++ b/trunk/net/tipc/netlink.c @@ -68,7 +68,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) return 0; } -static struct genl_family tipc_genl_family = { +static struct genl_family family = { .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, @@ -76,33 +76,39 @@ static struct genl_family tipc_genl_family = { .maxattr = 0, }; -static struct genl_ops tipc_genl_ops = { +static struct genl_ops ops = { .cmd = TIPC_GENL_CMD, .doit = handle_cmd, }; -static int tipc_genl_family_registered; +static int family_registered = 0; int tipc_netlink_start(void) { - int res; - res = genl_register_family_with_ops(&tipc_genl_family, - &tipc_genl_ops, 1); - if (res) { - err("Failed to register netlink interface\n"); - return res; - } - tipc_genl_family_registered = 1; + if (genl_register_family(&family)) + goto err; + + family_registered = 1; + + if (genl_register_ops(&family, &ops)) + goto err_unregister; + return 0; + + err_unregister: + genl_unregister_family(&family); + family_registered = 0; + err: + err("Failed to register netlink interface\n"); + return -EFAULT; } void tipc_netlink_stop(void) { - if (!tipc_genl_family_registered) - return; - - genl_unregister_family(&tipc_genl_family); - tipc_genl_family_registered = 0; + if (family_registered) { + genl_unregister_family(&family); + family_registered = 0; + } } diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index a3a152f55dd0..ade40d503bf0 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -3912,13 +3912,18 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy, int nl80211_init(void) { - int err; + int err, i; - err = genl_register_family_with_ops(&nl80211_fam, - nl80211_ops, ARRAY_SIZE(nl80211_ops)); + err = genl_register_family(&nl80211_fam); if (err) return err; + for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) { + err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]); + if (err) + goto err_out; + } + err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); if (err) goto err_out; diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 537af62ec42b..d897528ee7fc 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -48,12 +48,6 @@ static struct regulatory_request *last_request; /* To trigger userspace events */ static struct platform_device *reg_pdev; -/* Keep the ordering from large to small */ -static u32 supported_bandwidths[] = { - MHZ_TO_KHZ(40), - MHZ_TO_KHZ(20), -}; - /* * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no @@ -435,19 +429,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) return true; } -/* Returns value in KHz */ -static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, - u32 freq) +static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, + u32 center_freq_khz, + u32 bw_khz) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { - u32 start_freq_khz = freq - supported_bandwidths[i]/2; - u32 end_freq_khz = freq + supported_bandwidths[i]/2; - if (start_freq_khz >= freq_range->start_freq_khz && - end_freq_khz <= freq_range->end_freq_khz) - return supported_bandwidths[i]; - } - return 0; + u32 start_freq_khz, end_freq_khz; + + start_freq_khz = center_freq_khz - (bw_khz/2); + end_freq_khz = center_freq_khz + (bw_khz/2); + + if (start_freq_khz >= freq_range->start_freq_khz && + end_freq_khz <= freq_range->end_freq_khz) + return true; + + return false; } /** @@ -847,14 +842,17 @@ static u32 map_regdom_flags(u32 rd_flags) static int freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, - u32 *bandwidth, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule, const struct ieee80211_regdomain *custom_regd) { int i; bool band_rule_found = false; const struct ieee80211_regdomain *regd; - u32 max_bandwidth = 0; + bool bw_fits = false; + + if (!desired_bw_khz) + desired_bw_khz = MHZ_TO_KHZ(20); regd = custom_regd ? custom_regd : cfg80211_regdomain; @@ -887,38 +885,54 @@ static int freq_reg_info_regd(struct wiphy *wiphy, if (!band_rule_found) band_rule_found = freq_in_rule_band(fr, center_freq); - max_bandwidth = freq_max_bandwidth(fr, center_freq); + bw_fits = reg_does_bw_fit(fr, + center_freq, + desired_bw_khz); - if (max_bandwidth && *bandwidth <= max_bandwidth) { + if (band_rule_found && bw_fits) { *reg_rule = rr; - *bandwidth = max_bandwidth; - break; + return 0; } } if (!band_rule_found) return -ERANGE; - return !max_bandwidth; + return -EINVAL; } EXPORT_SYMBOL(freq_reg_info); -int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule) +int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, + const struct ieee80211_reg_rule **reg_rule) { assert_cfg80211_lock(); - return freq_reg_info_regd(wiphy, center_freq, - bandwidth, reg_rule, NULL); + return freq_reg_info_regd(wiphy, + center_freq, + desired_bw_khz, + reg_rule, + NULL); } +/* + * Note that right now we assume the desired channel bandwidth + * is always 20 MHz for each individual channel (HT40 uses 20 MHz + * per channel, the primary and the extension channel). To support + * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a + * new ieee80211_channel.target_bw and re run the regulatory check + * on the wiphy with the target_bw specified. Then we can simply use + * that below for the desired_bw_khz below. + */ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx) { int r; - u32 flags; - u32 max_bandwidth = 0; + u32 flags, bw_flags = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; struct wiphy *request_wiphy = NULL; @@ -933,8 +947,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, flags = chan->orig_flags; - r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule); + r = freq_reg_info(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule); if (r) { /* @@ -977,6 +993,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && @@ -987,19 +1007,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * settings */ chan->flags = chan->orig_flags = - map_regdom_flags(reg_rule->flags); + map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = chan->orig_mag = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = chan->orig_mpwr = (int) MBM_TO_DBM(power_rule->max_eirp); return; } - chan->flags = flags | map_regdom_flags(reg_rule->flags); + chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); if (chan->orig_mpwr) chan->max_power = min(chan->orig_mpwr, (int) MBM_TO_DBM(power_rule->max_eirp)); @@ -1156,6 +1176,93 @@ static void reg_process_beacons(struct wiphy *wiphy) wiphy_update_beacon_reg(wiphy); } +static bool is_ht40_not_allowed(struct ieee80211_channel *chan) +{ + if (!chan) + return true; + if (chan->flags & IEEE80211_CHAN_DISABLED) + return true; + /* This would happen when regulatory rules disallow HT40 completely */ + if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40))) + return true; + return false; +} + +static void reg_process_ht_flags_channel(struct wiphy *wiphy, + enum ieee80211_band band, + unsigned int chan_idx) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *channel; + struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; + unsigned int i; + + assert_cfg80211_lock(); + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + channel = &sband->channels[chan_idx]; + + if (is_ht40_not_allowed(channel)) { + channel->flags |= IEEE80211_CHAN_NO_HT40; + return; + } + + /* + * We need to ensure the extension channels exist to + * be able to use HT40- or HT40+, this finds them (or not) + */ + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *c = &sband->channels[i]; + if (c->center_freq == (channel->center_freq - 20)) + channel_before = c; + if (c->center_freq == (channel->center_freq + 20)) + channel_after = c; + } + + /* + * Please note that this assumes target bandwidth is 20 MHz, + * if that ever changes we also need to change the below logic + * to include that as well. + */ + if (is_ht40_not_allowed(channel_before)) + channel->flags |= IEEE80211_CHAN_NO_FAT_BELOW; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_BELOW; + + if (is_ht40_not_allowed(channel_after)) + channel->flags |= IEEE80211_CHAN_NO_FAT_ABOVE; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_ABOVE; +} + +static void reg_process_ht_flags_band(struct wiphy *wiphy, + enum ieee80211_band band) +{ + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) + reg_process_ht_flags_channel(wiphy, band, i); +} + +static void reg_process_ht_flags(struct wiphy *wiphy) +{ + enum ieee80211_band band; + + if (!wiphy) + return; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + reg_process_ht_flags_band(wiphy, band); + } + +} + void wiphy_update_regulatory(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { @@ -1169,6 +1276,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, } out: reg_process_beacons(wiphy); + reg_process_ht_flags(wiphy); if (wiphy->reg_notifier) wiphy->reg_notifier(wiphy, last_request); } @@ -1179,9 +1287,11 @@ static void handle_channel_custom(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { int r; - u32 max_bandwidth = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); + u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; @@ -1191,8 +1301,11 @@ static void handle_channel_custom(struct wiphy *wiphy, BUG_ON(chan_idx >= sband->n_channels); chan = &sband->channels[chan_idx]; - r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule, regd); + r = freq_reg_info_regd(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule, + regd); if (r) { chan->flags = IEEE80211_CHAN_DISABLED; @@ -1200,10 +1313,14 @@ static void handle_channel_custom(struct wiphy *wiphy, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; - chan->flags |= map_regdom_flags(reg_rule->flags); + chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); }