RE: [PATCH] PCI Error Recovery: e1000 network device driver

2006-04-28 Thread Zhang, Yanmin
>>-Original Message-
>>From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Linas Vepstas
>>Sent: 2006年3月25日 11:22
>>To: Greg KH
>>Cc: Jeff Garzik; Ronciak, John; Brandeburg, Jesse; Kirsher, Jeffrey T; 
>>linux-kernel@vger.kernel.org; netdev@vger.kernel.org;
>>[EMAIL PROTECTED]; [EMAIL PROTECTED]; Linux NICS
>>Subject: Re: [PATCH] PCI Error Recovery: e1000 network device driver
>>
>>On Fri, Mar 24, 2006 at 06:22:06PM -0800, Greg KH wrote:
>>> ... a bit
>>> different from the traditional kernel coding style.
>>
>>Sorry, this is due to inattention on my part; I get cross-eyed
>>after staring at the same code for too long. The patch below should
>>fix things.
>>
>>--linas
>>
>>
>>[PATCH] PCI Error Recovery: e1000 network device driver
>>
>>Various PCI bus errors can be signaled by newer PCI controllers.  This
>>patch adds the PCI error recovery callbacks to the intel gigabit
>>ethernet e1000 device driver. The patch has been tested, and appears
>>to work well.
>>
>>Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
>>Acked-by: Jesse Brandeburg <[EMAIL PROTECTED]>
>>
>>
>>
>> drivers/net/e1000/e1000_main.c |  114 
>> -
>> 1 files changed, 113 insertions(+), 1 deletion(-)
>>
>>Index: linux-2.6.16-git6/drivers/net/e1000/e1000_main.c
>>===
>>--- linux-2.6.16-git6.orig/drivers/net/e1000/e1000_main.c 2006-03-23 
>>15:48:01.0 -0600
>>+++ linux-2.6.16-git6/drivers/net/e1000/e1000_main.c  2006-03-24 
>>15:14:40.431371705 -0600
>>@@ -226,6 +226,16 @@ static int e1000_resume(struct pci_dev *
>>+/**
>>+ * e1000_io_error_detected - called when PCI error is detected
>>+ * @pdev: Pointer to PCI device
>>+ * @state: The current pci conneection state
>>+ *
>>+ * This function is called after a PCI bus error affecting
>>+ * this device has been detected.
>>+ */
>>+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
>>pci_channel_state_t state)
>>+{
>>+ struct net_device *netdev = pci_get_drvdata(pdev);
>>+ struct e1000_adapter *adapter = netdev->priv;
>>+
>>+ netif_device_detach(netdev);
>>+
>>+ if (netif_running(netdev))
>>+ e1000_down(adapter);
[YM] e1000_down will do device IO. So it's not appropriate to do so here.


>>+
>>+ /* Request a slot slot reset. */
>>+ return PCI_ERS_RESULT_NEED_RESET;
>>+}
>>+
>>+/**
>>+ * e1000_io_slot_reset - called after the pci bus has been reset.
>>+ * @pdev: Pointer to PCI device
>>+ *
>>+ * Restart the card from scratch, as if from a cold-boot. Implementation
>>+ * resembles the first-half of the e1000_resume routine.
>>+ */
>>+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
>>+{
>>+ struct net_device *netdev = pci_get_drvdata(pdev);
>>+ struct e1000_adapter *adapter = netdev->priv;
>>+
>>+ if (pci_enable_device(pdev)) {
>>+ printk(KERN_ERR "e1000: Cannot re-enable PCI device after 
>>reset.\n");
>>+ return PCI_ERS_RESULT_DISCONNECT;
>>+ }
>>+ pci_set_master(pdev);
>>+
>>+ pci_enable_wake(pdev, 3, 0);
>>+ pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
[YM] Suggest using PCI_D3hot and PCI_D3cold instead of hard-coded numbers.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] PCI Error Recovery: e1000 network device driver

2006-03-24 Thread Linas Vepstas
On Fri, Mar 24, 2006 at 06:22:06PM -0800, Greg KH wrote:
> ... a bit
> different from the traditional kernel coding style.

Sorry, this is due to inattention on my part; I get cross-eyed 
after staring at the same code for too long. The patch below should
fix things.  

--linas


[PATCH] PCI Error Recovery: e1000 network device driver

Various PCI bus errors can be signaled by newer PCI controllers.  This
patch adds the PCI error recovery callbacks to the intel gigabit
ethernet e1000 device driver. The patch has been tested, and appears
to work well.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
Acked-by: Jesse Brandeburg <[EMAIL PROTECTED]>



 drivers/net/e1000/e1000_main.c |  114 -
 1 files changed, 113 insertions(+), 1 deletion(-)

Index: linux-2.6.16-git6/drivers/net/e1000/e1000_main.c
===
--- linux-2.6.16-git6.orig/drivers/net/e1000/e1000_main.c   2006-03-23 
15:48:01.0 -0600
+++ linux-2.6.16-git6/drivers/net/e1000/e1000_main.c2006-03-24 
15:14:40.431371705 -0600
@@ -226,6 +226,16 @@ static int e1000_resume(struct pci_dev *
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+   .error_detected = e1000_io_error_detected,
+   .slot_reset = e1000_io_slot_reset,
+   .resume = e1000_io_resume,
+};
 
 static struct pci_driver e1000_driver = {
.name = e1000_driver_name,
@@ -235,8 +245,9 @@ static struct pci_driver e1000_driver = 
/* Power Managment Hooks */
 #ifdef CONFIG_PM
.suspend  = e1000_suspend,
-   .resume   = e1000_resume
+   .resume   = e1000_resume,
 #endif
+   .err_handler = &e1000_err_handler,
 };
 
 MODULE_AUTHOR("Intel Corporation, <[EMAIL PROTECTED]>");
@@ -3063,6 +3074,10 @@ e1000_update_stats(struct e1000_adapter 
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+   /* Prevent stats update while adapter is being reset */
+   if (adapter->link_speed == 0)
+   return;
+
spin_lock_irqsave(&adapter->stats_lock, flags);
 
/* these counters are modified from e1000_adjust_tbi_stats,
@@ -4631,4 +4646,101 @@ e1000_netpoll(struct net_device *netdev)
 }
 #endif
 
+/**
+ * e1000_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   netif_device_detach(netdev);
+
+   if (netif_running(netdev))
+   e1000_down(adapter);
+
+   /* Request a slot slot reset. */
+   return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e1000_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (pci_enable_device(pdev)) {
+   printk(KERN_ERR "e1000: Cannot re-enable PCI device after 
reset.\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+   }
+   pci_set_master(pdev);
+
+   pci_enable_wake(pdev, 3, 0);
+   pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+   /* Perform card reset only on one instance of the card */
+   if (PCI_FUNC (pdev->devfn) != 0)
+   return PCI_ERS_RESULT_RECOVERED;
+
+   e1000_reset(adapter);
+   E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+
+   return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e1000_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the e1000_resume routine.
+ */
+static void e1000_io_resume(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+   uint32_t manc, swsm;
+
+   if (netif_running(netdev)) {
+   if (e1000_up(adapter)) {
+   printk("e1000: can't bring device back up after 
reset\n");
+   

Re: [PATCH] PCI Error Recovery: e1000 network device driver

2006-03-24 Thread Greg KH
On Fri, Mar 24, 2006 at 04:00:02PM -0600, Linas Vepstas wrote:
> + /* Perform card reset only on one instance of the card */
> + if(0 != PCI_FUNC (pdev->devfn))
> + return PCI_ERS_RESULT_RECOVERED;

You seem to have forgotton to put a ' ' after the 'if' in a number of
different places in this patch.  Also the (0 != foo) form is a bit
different from the traditional kernel coding style.

> + switch(adapter->hw.mac_type) {

And here too.

Remember, "if" and "switch" are not functions...

thanks,

greg k-h
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] PCI Error Recovery: e1000 network device driver

2006-03-24 Thread Linas Vepstas

Jeff, 
Can you please review and forward this patch upstream?  A previous
version of this patch has been ack'ed by Jesse Brandeburg, one
of the e1000 maintainers.

--linas


[PATCH] PCI Error Recovery: e1000 network device driver

Various PCI bus errors can be signaled by newer PCI controllers.  This
patch adds the PCI error recovery callbacks to the intel gigabit
ethernet e1000 device driver. The patch has been tested, and appears
to work well.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
Acked-by: Jesse Brandeburg <[EMAIL PROTECTED]>



 drivers/net/e1000/e1000_main.c |  114 -
 1 files changed, 113 insertions(+), 1 deletion(-)

Index: linux-2.6.16-git6/drivers/net/e1000/e1000_main.c
===
--- linux-2.6.16-git6.orig/drivers/net/e1000/e1000_main.c   2006-03-23 
15:48:01.0 -0600
+++ linux-2.6.16-git6/drivers/net/e1000/e1000_main.c2006-03-24 
15:14:40.431371705 -0600
@@ -226,6 +226,16 @@ static int e1000_resume(struct pci_dev *
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+   .error_detected = e1000_io_error_detected,
+   .slot_reset = e1000_io_slot_reset,
+   .resume = e1000_io_resume,
+};
 
 static struct pci_driver e1000_driver = {
.name = e1000_driver_name,
@@ -235,8 +245,9 @@ static struct pci_driver e1000_driver = 
/* Power Managment Hooks */
 #ifdef CONFIG_PM
.suspend  = e1000_suspend,
-   .resume   = e1000_resume
+   .resume   = e1000_resume,
 #endif
+   .err_handler = &e1000_err_handler,
 };
 
 MODULE_AUTHOR("Intel Corporation, <[EMAIL PROTECTED]>");
@@ -3063,6 +3074,10 @@ e1000_update_stats(struct e1000_adapter 
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+   /* Prevent stats update while adapter is being reset */
+   if (adapter->link_speed == 0)
+   return;
+
spin_lock_irqsave(&adapter->stats_lock, flags);
 
/* these counters are modified from e1000_adjust_tbi_stats,
@@ -4631,4 +4646,101 @@ e1000_netpoll(struct net_device *netdev)
 }
 #endif
 
+/**
+ * e1000_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   netif_device_detach(netdev);
+
+   if (netif_running(netdev))
+   e1000_down(adapter);
+
+   /* Request a slot slot reset. */
+   return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e1000_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (pci_enable_device(pdev)) {
+   printk(KERN_ERR "e1000: Cannot re-enable PCI device after 
reset.\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+   }
+   pci_set_master(pdev);
+
+   pci_enable_wake(pdev, 3, 0);
+   pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+   /* Perform card reset only on one instance of the card */
+   if(0 != PCI_FUNC (pdev->devfn))
+   return PCI_ERS_RESULT_RECOVERED;
+
+   e1000_reset(adapter);
+   E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+
+   return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e1000_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the e1000_resume routine.
+ */
+static void e1000_io_resume(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+   uint32_t manc, swsm;
+
+   if(netif_running(netdev)) {
+   if (e1000_up(adapter)) {
+   printk("e1000: can't bring device back up after 
reset\n");
+   return;
+   }
+   }
+
+   netif_device_attach(netdev);
+
+   if(adapter-&

[PATCH] PCI Error Recovery: e1000 network device driver

2006-01-18 Thread linas

Hi Jeff,

Please review, apply and forward this patch upstream,
as appropriate. 

--linas


[PATCH] PCI Error Recovery: e1000 network device driver

Various PCI bus errors can be signaled by newer PCI controllers.  This
patch adds the PCI error recovery callbacks to the intel gigabit
ethernet e1000 device driver. The patch has been tested, and appears
to work well.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>

---
commit 113cc803a20d72ee5e3c92302ac5a06e0c651d01
tree aae6aa3b20f14a36eba84867c2406cbe385affad
parent 5a02e3abf1e74c159deca91d6af01297379eede7
author linas <[EMAIL PROTECTED]> Fri, 18 Nov 2005 16:23:54 -0600
committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Thu, 05 Jan 2006 21:54:55 -0800

 drivers/net/e1000/e1000_main.c |  101 
 1 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 438a931..76352fe 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -206,6 +206,16 @@ static void e1000_netpoll (struct net_de
 void e1000_rx_schedule(void *data);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+   .error_detected = e1000_io_error_detected,
+   .slot_reset = e1000_io_slot_reset,
+   .resume = e1000_io_resume,
+};
+
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -218,8 +228,9 @@ static struct pci_driver e1000_driver = 
/* Power Managment Hooks */
 #ifdef CONFIG_PM
.suspend  = e1000_suspend,
-   .resume   = e1000_resume
+   .resume   = e1000_resume,
 #endif
+   .err_handler = &e1000_err_handler,
 };
 
 MODULE_AUTHOR("Intel Corporation, <[EMAIL PROTECTED]>");
@@ -2941,6 +2952,10 @@ e1000_update_stats(struct e1000_adapter 
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+   /* Prevent stats update while adapter is being reset */
+   if (adapter->link_speed == 0)
+   return;
+
spin_lock_irqsave(&adapter->stats_lock, flags);
 
/* these counters are modified from e1000_adjust_tbi_stats,
@@ -4331,4 +4346,88 @@ e1000_netpoll(struct net_device *netdev)
 }
 #endif
 
+/* --- PCI Error Recovery infrastructure  */
+/** e1000_io_error_detected() is called when PCI error is detected */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (netif_running(netdev))
+   e1000_down(adapter);
+
+   /* Request a slot slot reset. */
+   return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/** e1000_io_slot_reset is called after the pci bus has been reset.
+ *  Restart the card from scratch.
+ *  Implementation resembles the first-half of the
+ *  e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (pci_enable_device(pdev)) {
+   printk(KERN_ERR "e1000: Cannot re-enable PCI device after 
reset.\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+   }
+   pci_set_master(pdev);
+
+   pci_enable_wake(pdev, 3, 0);
+   pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+   /* Perform card reset only on one instance of the card */
+   if(0 != PCI_FUNC (pdev->devfn))
+   return PCI_ERS_RESULT_RECOVERED;
+
+   e1000_reset(adapter);
+   E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+
+   return PCI_ERS_RESULT_RECOVERED;
+}
+
+/** e1000_io_resume is called when the error recovery driver
+ *  tells us that its OK to resume normal operation.
+ *  Implementation resembles the second-half of the
+ *  e1000_resume routine.
+ */
+static void e1000_io_resume(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+   uint32_t manc, swsm;
+
+   if(netif_running(netdev)) {
+   if (e1000_up(adapter)) {
+   printk("e1000: can't bring device back up after 
reset\n");
+   return;
+   }
+   }
+
+   netif_device_attach(netdev);
+
+   if(adapter->hw.mac_type >= e1000_82540 &&
+   adapter->hw.media_type == e1000_media_type_copper) {
+   manc = E1000_READ_REG(&adapter->hw, MANC);
+   manc &= ~(E1000_MANC_ARP_EN);
+   E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ 

Re: [EMAIL PROTECTED]: [PATCH] PCI Error Recovery: e1000 network device driver]

2006-01-11 Thread Jesse Brandeburg
On 1/6/06, linas <[EMAIL PROTECTED]> wrote:
>
> Here's the correspondig patch fo the e1000
> --linas
>
> > Hi,
> >
> > The following patch to the e100 device driver is in the current
> > 2.6.15-mm1 tree, and is being pushed to the mainline 2.6.15 tree.
> >
> > I wrote this patch, and I believe I've cc'ed you on previous
> > versions, but certainly not recently. Please review, comment,
> > ACK or NAK as appropriate.

acked-by: Jesse Brandeburg <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[EMAIL PROTECTED]: [PATCH] PCI Error Recovery: e1000 network device driver]

2006-01-06 Thread linas

Here's the correspondig patch fo the e1000
--linas

> Hi,
> 
> The following patch to the e100 device driver is in the current
> 2.6.15-mm1 tree, and is being pushed to the mainline 2.6.15 tree.
> 
> I wrote this patch, and I believe I've cc'ed you on previous
> versions, but certainly not recently. Please review, comment,
> ACK or NAK as appropriate.
> 
> Background: Newer PCI controllers can detect and respond to
> serious PCI bus errors, typically by isolating the PCI slot
> (cutting off i/o to the failing card). An arch-specific
> framework can report these errors back to the device driver,
> and coordinate the recovery of the card. Detailed documentation
> for this is in the kernel tree, at Documentation/pci-error-recovery.txt
> 
> This patch adds the detection and recovery callbacks to the
> e100 driver. A version of this patch has been shipping as
> a part of SUSE SLES9 for about a year, and so has been
> tested in the field.
> 
> Similar patches to follow for the e1000 and the ixgb.
> 
> --linas

----- Forwarded message from Greg KH <[EMAIL PROTECTED]> -

Subject: [PATCH] PCI Error Recovery: e1000 network device driver
To: [EMAIL PROTECTED]
From: Greg KH <[EMAIL PROTECTED]>

[PATCH] PCI Error Recovery: e1000 network device driver

Various PCI bus errors can be signaled by newer PCI controllers.  This
patch adds the PCI error recovery callbacks to the intel gigabit
ethernet e1000 device driver. The patch has been tested, and appears
to work well.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
commit 113cc803a20d72ee5e3c92302ac5a06e0c651d01
tree aae6aa3b20f14a36eba84867c2406cbe385affad
parent 5a02e3abf1e74c159deca91d6af01297379eede7
author linas <[EMAIL PROTECTED]> Fri, 18 Nov 2005 16:23:54 -0600
committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Thu, 05 Jan 2006 21:54:55 -0800

 drivers/net/e1000/e1000_main.c |  101 
 1 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 438a931..76352fe 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -206,6 +206,16 @@ static void e1000_netpoll (struct net_de
 void e1000_rx_schedule(void *data);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+   .error_detected = e1000_io_error_detected,
+   .slot_reset = e1000_io_slot_reset,
+   .resume = e1000_io_resume,
+};
+
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
@@ -218,8 +228,9 @@ static struct pci_driver e1000_driver = 
/* Power Managment Hooks */
 #ifdef CONFIG_PM
.suspend  = e1000_suspend,
-   .resume   = e1000_resume
+   .resume   = e1000_resume,
 #endif
+   .err_handler = &e1000_err_handler,
 };
 
 MODULE_AUTHOR("Intel Corporation, <[EMAIL PROTECTED]>");
@@ -2941,6 +2952,10 @@ e1000_update_stats(struct e1000_adapter 
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+   /* Prevent stats update while adapter is being reset */
+   if (adapter->link_speed == 0)
+   return;
+
spin_lock_irqsave(&adapter->stats_lock, flags);
 
/* these counters are modified from e1000_adjust_tbi_stats,
@@ -4331,4 +4346,88 @@ e1000_netpoll(struct net_device *netdev)
 }
 #endif
 
+/* --- PCI Error Recovery infrastructure  */
+/** e1000_io_error_detected() is called when PCI error is detected */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, 
pci_channel_state_t state)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (netif_running(netdev))
+   e1000_down(adapter);
+
+   /* Request a slot slot reset. */
+   return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/** e1000_io_slot_reset is called after the pci bus has been reset.
+ *  Restart the card from scratch.
+ *  Implementation resembles the first-half of the
+ *  e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct e1000_adapter *adapter = netdev->priv;
+
+   if (pci_enable_device(pdev)) {
+   printk(KERN_ERR "e1000: Cannot re-enable PCI device after 
reset.\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+   }
+   pci_set_master(pdev);
+
+   pci_enable_wake(pdev, 3, 0);
+   pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+   /* Perf