From 34948a947d1a576c10afee6d14792fd237549577 Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Fri, 6 Apr 2012 07:20:21 +0000 Subject: ixgbe: add missing rtnl_lock in PM resume path Upon resume from standby, ixgbe may trigger the ASSERT_RTNL() in netif_set_real_num_tx_queues(). The call stack is: netif_set_real_num_tx_queues ixgbe_set_num_queues ixgbe_init_interrupt_scheme ixgbe_resume Signed-off-by: Benjamin Poirier Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index dac7c01f8332..9e2be8c45c2d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4836,7 +4836,9 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_wake_from_d3(pdev, false); + rtnl_lock(); err = ixgbe_init_interrupt_scheme(adapter); + rtnl_unlock(); if (err) { e_dev_err("Cannot initialize interrupts for device\n"); return err; -- cgit v1.2.2 From b2db497eb25510052fc2d3152384f964b3312004 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 7 Apr 2012 04:57:29 +0000 Subject: ixgbe: Identify FCoE rings earlier to resolve memory corruption w/ FCoE This patch makes it so that we identify FCoE rings earlier than ixgbe_set_rx_buffer_len. Instead we identify the Rx FCoE rings at allocation time in ixgbe_alloc_q_vector. The motivation behind this change is to avoid memory corruption when FCoE is enabled. Without this change we were initializing the rings at 0, and 2K on systems with 4K pages, then when we bumped the buffer size to 4K with order 1 pages we were accessing offsets 2K and 6K instead of 0 and 4K. This was resulting in memory corruptions. Signed-off-by: Alexander Duyck Acked-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 10 ++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 027d7a75be39..ed1b47dc0834 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -622,6 +622,16 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx, if (adapter->hw.mac.type == ixgbe_mac_82599EB) set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state); +#ifdef IXGBE_FCOE + if (adapter->netdev->features & NETIF_F_FCOE_MTU) { + struct ixgbe_ring_feature *f; + f = &adapter->ring_feature[RING_F_FCOE]; + if ((rxr_idx >= f->mask) && + (rxr_idx < f->mask + f->indices)) + set_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state); + } + +#endif /* IXGBE_FCOE */ /* apply Rx specific ring traits */ ring->count = adapter->rx_ring_count; ring->queue_index = rxr_idx; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9e2be8c45c2d..a7f3cd872caf 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3154,14 +3154,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) set_ring_rsc_enabled(rx_ring); else clear_ring_rsc_enabled(rx_ring); -#ifdef IXGBE_FCOE - if (netdev->features & NETIF_F_FCOE_MTU) { - struct ixgbe_ring_feature *f; - f = &adapter->ring_feature[RING_F_FCOE]; - if ((i >= f->mask) && (i < f->mask + f->indices)) - set_bit(__IXGBE_RX_FCOE_BUFSZ, &rx_ring->state); - } -#endif /* IXGBE_FCOE */ } } -- cgit v1.2.2 From 5b76d0600b2b08eef77f8e9226938b7b6bde3099 Mon Sep 17 00:00:00 2001 From: Christian Riesch Date: Mon, 16 Apr 2012 04:35:25 +0000 Subject: davinci_mdio: Fix MDIO timeout check Under heavy load (flood ping) it is possible for the MDIO timeout to expire before the loop checks the GO bit again. This patch adds an additional check whether the operation was done before actually returning -ETIMEDOUT. To reproduce this bug, flood ping the device, e.g., ping -f -l 1000 After some time, a "timed out waiting for user access" warning may appear. And even worse, link may go down since the PHY reported a timeout. Signed-off-by: Christian Riesch Cc: Cc: Cyril Chemparathy Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_mdio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 2757c7d6e633..e4e47088e26b 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -181,6 +181,11 @@ static inline int wait_for_user_access(struct davinci_mdio_data *data) __davinci_mdio_reset(data); return -EAGAIN; } + + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + dev_err(data->dev, "timed out waiting for user access\n"); return -ETIMEDOUT; } -- cgit v1.2.2 From 716af4abd6e6370226f567af50bfaca274515980 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 19 Apr 2012 10:00:19 +0300 Subject: ksz884x: don't copy too much in netdev_set_mac_address() MAX_ADDR_LEN is 32. ETH_ALEN is 6. mac->sa_data is a 14 byte array, so the memcpy() is doing a read past the end of the array. I asked about this on netdev and Ben Hutchings told me it's supposed to be copying ETH_ALEN bytes (thanks Ben). Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/ethernet/micrel/ksz884x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index ef723b185d85..eaf9ff0262a9 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5675,7 +5675,7 @@ static int netdev_set_mac_address(struct net_device *dev, void *addr) memcpy(hw->override_addr, mac->sa_data, ETH_ALEN); } - memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN); + memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN); interrupt = hw_block_intr(hw); -- cgit v1.2.2 From 7e5998aa74065d3ab31d17e667f40ffebf4b8425 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 17 Apr 2012 20:53:42 +0000 Subject: bnx2x: off by one in bnx2x_ets_e3b0_sp_pri_to_cos_set() The sp_pri_to_cos[] array size depends on the config but lets say it is BX_E3B0_MAX_NUM_COS_PORT0 and max_num_of_cos is also DCBX_E3B0_MAX_NUM_COS_PORT0. In the original code "pri == max_num_of_cos" was accepted but it is one past the end of the array. Also we used "pri" before capping it. It's a harmless read past the end of the array, but it would affect which error message gets printed. Signed-off-by: Dan Carpenter Acked-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index ad95324dc042..64392ec410a3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -942,6 +942,12 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params, const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 : DCBX_E3B0_MAX_NUM_COS_PORT0; + if (pri >= max_num_of_cos) { + DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " + "parameter Illegal strict priority\n"); + return -EINVAL; + } + if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) { DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " "parameter There can't be two COS's with " @@ -949,12 +955,6 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params, return -EINVAL; } - if (pri > max_num_of_cos) { - DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " - "parameter Illegal strict priority\n"); - return -EINVAL; - } - sp_pri_to_cos[pri] = cos_entry; return 0; -- cgit v1.2.2 From c5a99937a9cf74a623384023201a7d98b51e7e3b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 18 Apr 2012 17:25:58 +0000 Subject: ks8851: Fix mutex deadlock in ks8851_net_stop() There is a potential deadlock scenario when the ks8851 driver is removed. The interrupt handler schedules a workqueue which acquires a mutex that ks8851_net_stop() also acquires before flushing the workqueue. Previously lockdep wouldn't be able to find this problem but now that it has the support we can trigger this lockdep warning by rmmoding the driver after an ifconfig up. Fix the possible deadlock by disabling the interrupts in the chip and then release the lock across the workqueue flushing. The mutex is only there to proect the registers anyway so this should be ok. ======================================================= [ INFO: possible circular locking dependency detected ] 3.0.21-00021-g8b33780-dirty #2911 ------------------------------------------------------- rmmod/125 is trying to acquire lock: ((&ks->irq_work)){+.+...}, at: [] flush_work+0x0/0xac but task is already holding lock: (&ks->lock){+.+...}, at: [] ks8851_net_stop+0x64/0x138 [ks8851] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&ks->lock){+.+...}: [] __lock_acquire+0x940/0x9f8 [] lock_acquire+0x10c/0x130 [] mutex_lock_nested+0x68/0x3dc [] ks8851_irq_work+0x24/0x46c [ks8851] [] process_one_work+0x2d8/0x518 [] worker_thread+0x220/0x3a0 [] kthread+0x88/0x94 [] kernel_thread_exit+0x0/0x8 -> #0 ((&ks->irq_work)){+.+...}: [] validate_chain+0x914/0x1018 [] __lock_acquire+0x940/0x9f8 [] lock_acquire+0x10c/0x130 [] flush_work+0x4c/0xac [] ks8851_net_stop+0x6c/0x138 [ks8851] [] __dev_close_many+0x98/0xcc [] dev_close_many+0x68/0xd0 [] rollback_registered_many+0xcc/0x2b8 [] rollback_registered+0x28/0x34 [] unregister_netdevice_queue+0x58/0x7c [] unregister_netdev+0x18/0x20 [] ks8851_remove+0x64/0xb4 [ks8851] [] spi_drv_remove+0x18/0x1c [] __device_release_driver+0x7c/0xbc [] driver_detach+0x8c/0xb4 [] bus_remove_driver+0xb8/0xe8 [] sys_delete_module+0x1e8/0x27c [] ret_fast_syscall+0x0/0x3c other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&ks->lock); lock((&ks->irq_work)); lock(&ks->lock); lock((&ks->irq_work)); *** DEADLOCK *** 4 locks held by rmmod/125: #0: (&__lockdep_no_validate__){+.+.+.}, at: [] driver_detach+0x6c/0xb4 #1: (&__lockdep_no_validate__){+.+.+.}, at: [] driver_detach+0x78/0xb4 #2: (rtnl_mutex){+.+.+.}, at: [] unregister_netdev+0xc/0x20 #3: (&ks->lock){+.+...}, at: [] ks8851_net_stop+0x64/0x138 [ks8851] Cc: Ben Dooks Signed-off-by: Stephen Boyd Signed-off-by: David S. Miller --- drivers/net/ethernet/micrel/ks8851.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index e5dc0757f077..ad10759e3459 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -889,16 +889,17 @@ static int ks8851_net_stop(struct net_device *dev) netif_stop_queue(dev); mutex_lock(&ks->lock); + /* turn off the IRQs and ack any outstanding */ + ks8851_wrreg16(ks, KS_IER, 0x0000); + ks8851_wrreg16(ks, KS_ISR, 0xffff); + mutex_unlock(&ks->lock); /* stop any outstanding work */ flush_work(&ks->irq_work); flush_work(&ks->tx_work); flush_work(&ks->rxctrl_work); - /* turn off the IRQs and ack any outstanding */ - ks8851_wrreg16(ks, KS_IER, 0x0000); - ks8851_wrreg16(ks, KS_ISR, 0xffff); - + mutex_lock(&ks->lock); /* shutdown RX process */ ks8851_wrreg16(ks, KS_RXCR1, 0x0000); @@ -907,6 +908,7 @@ static int ks8851_net_stop(struct net_device *dev) /* set powermode to soft power down to save power */ ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); + mutex_unlock(&ks->lock); /* ensure any queued tx buffers are dumped */ while (!skb_queue_empty(&ks->txq)) { @@ -918,7 +920,6 @@ static int ks8851_net_stop(struct net_device *dev) dev_kfree_skb(txb); } - mutex_unlock(&ks->lock); return 0; } -- cgit v1.2.2 From e8195b24feb208f6e944e7542779f4397776794d Mon Sep 17 00:00:00 2001 From: Matt Renzelmann Date: Thu, 19 Apr 2012 07:17:17 +0000 Subject: ks8851: Fix request_irq/free_irq mismatch The dev_id parameter passed to free_irq needs to match the one passed to the corresponding request_irq. Signed-off-by: Matt Renzelmann Acked-by: Stephen Boyd Signed-off-by: David S. Miller --- drivers/net/ethernet/micrel/ks8851.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index ad10759e3459..f8dda009d3c0 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1525,7 +1525,7 @@ static int __devinit ks8851_probe(struct spi_device *spi) err_netdev: - free_irq(ndev->irq, ndev); + free_irq(ndev->irq, ks); err_id: err_irq: -- cgit v1.2.2 From 163faf31778e536ac6125bc8b14f4667adc910e9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 19 Apr 2012 10:36:33 +0000 Subject: drivers/net: Do not free an IRQ if its request failed Refrain from attempting to free an interrupt line if the request fails and hence, there is no IRQ to free. CC: netdev@vger.kernel.org Signed-off-by: Lee Jones Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smsc911x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net/ethernet') diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 5aa2dbe2bfb5..cd3defb11ffb 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2378,7 +2378,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, &pdev->dev); pdata = netdev_priv(dev); - dev->irq = irq_res->start; irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; pdata->ioaddr = ioremap_nocache(res->start, res_size); @@ -2442,7 +2441,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (retval) { SMSC_WARN(pdata, probe, "Unable to claim requested irq: %d", dev->irq); - goto out_free_irq; + goto out_disable_resources; } retval = register_netdev(dev); -- cgit v1.2.2