diff options
author | Tony Zelenoff <antonz@parallels.com> | 2012-04-11 02:15:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-27 12:51:20 -0400 |
commit | bb2f6102c815c14572642205191eb0fa883d8723 (patch) | |
tree | 4158479d3746658d5b2c1efcf3c9c86010105be5 | |
parent | 4a1abcbd24d856fe49029c3dc6f7fe8dc66ddaac (diff) |
atl1: fix kernel panic in case of DMA errors
[ Upstream commit 03662e41c7cff64a776bfb1b3816de4be43de881 ]
Problem:
There was two separate work_struct structures which share one
handler. Unfortunately getting atl1_adapter structure from
work_struct in case of DMA error was done from incorrect
offset which cause kernel panics.
Solution:
The useless work_struct for DMA error removed and
handler name changed to more generic one.
Signed-off-by: Tony Zelenoff <antonz@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/net/atlx/atl1.c | 12 | ||||
-rw-r--r-- | drivers/net/atlx/atl1.h | 3 | ||||
-rw-r--r-- | drivers/net/atlx/atlx.c | 2 |
3 files changed, 7 insertions, 10 deletions
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index cd5789ff372..48c27d34eac 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
@@ -2476,7 +2476,7 @@ static irqreturn_t atl1_intr(int irq, void *data) | |||
2476 | "pcie phy link down %x\n", status); | 2476 | "pcie phy link down %x\n", status); |
2477 | if (netif_running(adapter->netdev)) { /* reset MAC */ | 2477 | if (netif_running(adapter->netdev)) { /* reset MAC */ |
2478 | iowrite32(0, adapter->hw.hw_addr + REG_IMR); | 2478 | iowrite32(0, adapter->hw.hw_addr + REG_IMR); |
2479 | schedule_work(&adapter->pcie_dma_to_rst_task); | 2479 | schedule_work(&adapter->reset_dev_task); |
2480 | return IRQ_HANDLED; | 2480 | return IRQ_HANDLED; |
2481 | } | 2481 | } |
2482 | } | 2482 | } |
@@ -2488,7 +2488,7 @@ static irqreturn_t atl1_intr(int irq, void *data) | |||
2488 | "pcie DMA r/w error (status = 0x%x)\n", | 2488 | "pcie DMA r/w error (status = 0x%x)\n", |
2489 | status); | 2489 | status); |
2490 | iowrite32(0, adapter->hw.hw_addr + REG_IMR); | 2490 | iowrite32(0, adapter->hw.hw_addr + REG_IMR); |
2491 | schedule_work(&adapter->pcie_dma_to_rst_task); | 2491 | schedule_work(&adapter->reset_dev_task); |
2492 | return IRQ_HANDLED; | 2492 | return IRQ_HANDLED; |
2493 | } | 2493 | } |
2494 | 2494 | ||
@@ -2633,10 +2633,10 @@ static void atl1_down(struct atl1_adapter *adapter) | |||
2633 | atl1_clean_rx_ring(adapter); | 2633 | atl1_clean_rx_ring(adapter); |
2634 | } | 2634 | } |
2635 | 2635 | ||
2636 | static void atl1_tx_timeout_task(struct work_struct *work) | 2636 | static void atl1_reset_dev_task(struct work_struct *work) |
2637 | { | 2637 | { |
2638 | struct atl1_adapter *adapter = | 2638 | struct atl1_adapter *adapter = |
2639 | container_of(work, struct atl1_adapter, tx_timeout_task); | 2639 | container_of(work, struct atl1_adapter, reset_dev_task); |
2640 | struct net_device *netdev = adapter->netdev; | 2640 | struct net_device *netdev = adapter->netdev; |
2641 | 2641 | ||
2642 | netif_device_detach(netdev); | 2642 | netif_device_detach(netdev); |
@@ -3034,12 +3034,10 @@ static int __devinit atl1_probe(struct pci_dev *pdev, | |||
3034 | (unsigned long)adapter); | 3034 | (unsigned long)adapter); |
3035 | adapter->phy_timer_pending = false; | 3035 | adapter->phy_timer_pending = false; |
3036 | 3036 | ||
3037 | INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task); | 3037 | INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task); |
3038 | 3038 | ||
3039 | INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task); | 3039 | INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task); |
3040 | 3040 | ||
3041 | INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task); | ||
3042 | |||
3043 | err = register_netdev(netdev); | 3041 | err = register_netdev(netdev); |
3044 | if (err) | 3042 | if (err) |
3045 | goto err_common; | 3043 | goto err_common; |
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index 68de8cbfb3e..c27b724a834 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h | |||
@@ -759,9 +759,8 @@ struct atl1_adapter { | |||
759 | u16 link_speed; | 759 | u16 link_speed; |
760 | u16 link_duplex; | 760 | u16 link_duplex; |
761 | spinlock_t lock; | 761 | spinlock_t lock; |
762 | struct work_struct tx_timeout_task; | 762 | struct work_struct reset_dev_task; |
763 | struct work_struct link_chg_task; | 763 | struct work_struct link_chg_task; |
764 | struct work_struct pcie_dma_to_rst_task; | ||
765 | 764 | ||
766 | struct timer_list phy_config_timer; | 765 | struct timer_list phy_config_timer; |
767 | bool phy_timer_pending; | 766 | bool phy_timer_pending; |
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index afb7f7dd1bb..2b7af060d49 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c | |||
@@ -193,7 +193,7 @@ static void atlx_tx_timeout(struct net_device *netdev) | |||
193 | { | 193 | { |
194 | struct atlx_adapter *adapter = netdev_priv(netdev); | 194 | struct atlx_adapter *adapter = netdev_priv(netdev); |
195 | /* Do the reset outside of interrupt context */ | 195 | /* Do the reset outside of interrupt context */ |
196 | schedule_work(&adapter->tx_timeout_task); | 196 | schedule_work(&adapter->reset_dev_task); |
197 | } | 197 | } |
198 | 198 | ||
199 | /* | 199 | /* |