aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2008-10-02 19:33:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-02 21:28:12 -0400
commita8f88ff5a5abc2ce9f7d7d2694178b2c617d713a (patch)
treeeb621b61dc32327b52f80911b73956c7515df7ae /drivers/net/e1000e
parent37f40239f49fbc0b489d0327a700fee5b3898ac2 (diff)
e1000e: do not ever sleep in interrupt context
e1000e was apparently calling two functions that attempted to reserve the SWFLAG bit for exclusive (to hardware and firmware) access to the PHY and NVM (aka eeprom). These accesses could possibly call msleep to wait for the resource which is not allowed from interrupt context. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r--drivers/net/e1000e/e1000.h2
-rw-r--r--drivers/net/e1000e/netdev.c31
2 files changed, 30 insertions, 3 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index f0c48a2a6799..8087bda97218 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -284,6 +284,8 @@ struct e1000_adapter {
284 unsigned long led_status; 284 unsigned long led_status;
285 285
286 unsigned int flags; 286 unsigned int flags;
287 struct work_struct downshift_task;
288 struct work_struct update_phy_task;
287}; 289};
288 290
289struct e1000_info { 291struct e1000_info {
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 1f767feda9a7..803545b2fc8c 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1115,6 +1115,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
1115 writel(0, adapter->hw.hw_addr + rx_ring->tail); 1115 writel(0, adapter->hw.hw_addr + rx_ring->tail);
1116} 1116}
1117 1117
1118static void e1000e_downshift_workaround(struct work_struct *work)
1119{
1120 struct e1000_adapter *adapter = container_of(work,
1121 struct e1000_adapter, downshift_task);
1122
1123 e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
1124}
1125
1118/** 1126/**
1119 * e1000_intr_msi - Interrupt Handler 1127 * e1000_intr_msi - Interrupt Handler
1120 * @irq: interrupt number 1128 * @irq: interrupt number
@@ -1139,7 +1147,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
1139 */ 1147 */
1140 if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && 1148 if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
1141 (!(er32(STATUS) & E1000_STATUS_LU))) 1149 (!(er32(STATUS) & E1000_STATUS_LU)))
1142 e1000e_gig_downshift_workaround_ich8lan(hw); 1150 schedule_work(&adapter->downshift_task);
1143 1151
1144 /* 1152 /*
1145 * 80003ES2LAN workaround-- For packet buffer work-around on 1153 * 80003ES2LAN workaround-- For packet buffer work-around on
@@ -1205,7 +1213,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
1205 */ 1213 */
1206 if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && 1214 if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
1207 (!(er32(STATUS) & E1000_STATUS_LU))) 1215 (!(er32(STATUS) & E1000_STATUS_LU)))
1208 e1000e_gig_downshift_workaround_ich8lan(hw); 1216 schedule_work(&adapter->downshift_task);
1209 1217
1210 /* 1218 /*
1211 * 80003ES2LAN workaround-- 1219 * 80003ES2LAN workaround--
@@ -2912,6 +2920,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
2912 return 0; 2920 return 0;
2913} 2921}
2914 2922
2923/**
2924 * e1000e_update_phy_task - work thread to update phy
2925 * @work: pointer to our work struct
2926 *
2927 * this worker thread exists because we must acquire a
2928 * semaphore to read the phy, which we could msleep while
2929 * waiting for it, and we can't msleep in a timer.
2930 **/
2931static void e1000e_update_phy_task(struct work_struct *work)
2932{
2933 struct e1000_adapter *adapter = container_of(work,
2934 struct e1000_adapter, update_phy_task);
2935 e1000_get_phy_info(&adapter->hw);
2936}
2937
2915/* 2938/*
2916 * Need to wait a few seconds after link up to get diagnostic information from 2939 * Need to wait a few seconds after link up to get diagnostic information from
2917 * the phy 2940 * the phy
@@ -2919,7 +2942,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
2919static void e1000_update_phy_info(unsigned long data) 2942static void e1000_update_phy_info(unsigned long data)
2920{ 2943{
2921 struct e1000_adapter *adapter = (struct e1000_adapter *) data; 2944 struct e1000_adapter *adapter = (struct e1000_adapter *) data;
2922 e1000_get_phy_info(&adapter->hw); 2945 schedule_work(&adapter->update_phy_task);
2923} 2946}
2924 2947
2925/** 2948/**
@@ -4578,6 +4601,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
4578 4601
4579 INIT_WORK(&adapter->reset_task, e1000_reset_task); 4602 INIT_WORK(&adapter->reset_task, e1000_reset_task);
4580 INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); 4603 INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
4604 INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
4605 INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
4581 4606
4582 /* Initialize link parameters. User can change them with ethtool */ 4607 /* Initialize link parameters. User can change them with ethtool */
4583 adapter->hw.mac.autoneg = 1; 4608 adapter->hw.mac.autoneg = 1;