[RFC PATCH 04/12] e1000e: do not ever sleep in interrupt context

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Jesse Brandeburg
Date: Monday, September 29, 2008 - 8:19 pm

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>
CC: Thomas Gleixner <tglx@linutronix.de>
---

 drivers/net/e1000e/e1000.h  |    2 ++
 drivers/net/e1000e/netdev.c |   31 ++++++++++++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index ac4e506..ed9d974 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -284,6 +284,8 @@ struct e1000_adapter {
 	unsigned long led_status;
 
 	unsigned int flags;
+	struct work_struct downshift_task;
+	struct work_struct update_phy_task;
 };
 
 struct e1000_info {
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index d266510..f8c6c32 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)
 	writel(0, adapter->hw.hw_addr + rx_ring->tail);
 }
 
+static void e1000e_downshift_workaround(struct work_struct *work)
+{
+	struct e1000_adapter *adapter = container_of(work,
+					struct e1000_adapter, downshift_task);
+
+	e1000e_gig_downshift_workaround_ich8lan(&adapter->hw);
+}
+
 /**
  * e1000_intr_msi - Interrupt Handler
  * @irq: interrupt number
@@ -1139,7 +1147,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
 		 */
 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			e1000e_gig_downshift_workaround_ich8lan(hw);
+			schedule_work(&adapter->downshift_task);
 
 		/*
 		 * 80003ES2LAN workaround-- For packet buffer work-around on
@@ -1205,7 +1213,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
 		 */
 		if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
 		    (!(er32(STATUS) & E1000_STATUS_LU)))
-			e1000e_gig_downshift_workaround_ich8lan(hw);
+			schedule_work(&adapter->downshift_task);
 
 		/*
 		 * 80003ES2LAN workaround--
@@ -2912,6 +2920,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
 	return 0;
 }
 
+/**
+ * e1000e_update_phy_task - work thread to update phy
+ * @work: pointer to our work struct
+ *
+ * this worker thread exists because we must acquire a
+ * semaphore to read the phy, which we could msleep while
+ * waiting for it, and we can't msleep in a timer.
+ **/
+static void e1000e_update_phy_task(struct work_struct *work)
+{
+	struct e1000_adapter *adapter = container_of(work,
+					struct e1000_adapter, update_phy_task);
+	e1000_get_phy_info(&adapter->hw);
+}
+
 /*
  * Need to wait a few seconds after link up to get diagnostic information from
  * the phy
@@ -2919,7 +2942,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
 static void e1000_update_phy_info(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-	e1000_get_phy_info(&adapter->hw);
+	schedule_work(&adapter->update_phy_task);
 }
 
 /**
@@ -4572,6 +4595,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
 	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
+	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
+	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
 
 	e1000e_check_options(adapter);
 

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[RFC PATCH 00/12] e1000e debug and protection patches, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 01/12] x86: export set_memory_ro and set_memory_rw, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 02/12] On Tue, 23 Sep 2008, David Miller wrote:, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 04/12] e1000e: do not ever sleep in interrupt c ..., Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 05/12] e1000e: fix lockdep issues, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 06/12] e1000e: drop stats lock, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 07/12] e1000e: debug contention on NVM SWFLAG, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 08/12] e1000e: allow bad checksum, Jesse Brandeburg, (Mon Sep 29, 8:19 pm)
[RFC PATCH 09/12] e1000e: dump eeprom to dmesg for ich8/9, Jesse Brandeburg, (Mon Sep 29, 8:20 pm)
[RFC PATCH 12/12] update version, Jesse Brandeburg, (Mon Sep 29, 8:20 pm)
Re: [RFC PATCH 08/12] e1000e: allow bad checksum, Jiri Kosina, (Tue Sep 30, 1:38 am)
RE: [RFC PATCH 07/12] e1000e: debug contention on NVM SWFLAG, Brandeburg, Jesse, (Thu Oct 2, 9:27 am)
RE: [RFC PATCH 07/12] e1000e: debug contention on NVM SWFLAG, Thomas Gleixner, (Thu Oct 2, 11:02 am)
Re: [RFC PATCH 07/12] e1000e: debug contention on NVM SWFLAG, Thomas Gleixner, (Thu Oct 2, 11:58 am)
[PATCH] e1000e: prevent concurrent access to NVRAM, Thomas Gleixner, (Thu Oct 2, 4:42 pm)
Re: [PATCH] e1000e: prevent concurrent access to NVRAM, Jesse Brandeburg, (Thu Oct 2, 5:19 pm)
Re: [PATCH] e1000e: prevent concurrent access to NVRAM, Thomas Gleixner, (Thu Oct 2, 5:28 pm)