* [PATCH] PCI Error Recovery: e1000 network device driver
@ 2006-03-24 22:00 Linas Vepstas
2006-03-25 2:22 ` Greg KH
0 siblings, 1 reply; 4+ messages in thread
From: Linas Vepstas @ 2006-03-24 22:00 UTC (permalink / raw)
To: Jeff Garzik, john.ronciak, jesse.brandeburg, jeffrey.t.kirsher
Cc: netdev, linux-pci, linux-kernel, linuxppc-dev
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 <linas@linas.org>
Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
----
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.000000000 -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 *
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, <linux.nics@intel.com>");
@@ -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->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);
+ }
+
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
+ if(netif_running(netdev))
+ mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
/* e1000_main.c */
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PCI Error Recovery: e1000 network device driver
2006-03-24 22:00 [PATCH] PCI Error Recovery: e1000 network device driver Linas Vepstas
@ 2006-03-25 2:22 ` Greg KH
2006-03-25 3:21 ` Linas Vepstas
0 siblings, 1 reply; 4+ messages in thread
From: Greg KH @ 2006-03-25 2:22 UTC (permalink / raw)
To: Linas Vepstas
Cc: netdev, linux-kernel, jesse.brandeburg, linuxppc-dev,
john.ronciak, jeffrey.t.kirsher, linux-pci, Jeff Garzik
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PCI Error Recovery: e1000 network device driver
2006-03-25 2:22 ` Greg KH
@ 2006-03-25 3:21 ` Linas Vepstas
0 siblings, 0 replies; 4+ messages in thread
From: Linas Vepstas @ 2006-03-25 3:21 UTC (permalink / raw)
To: Greg KH
Cc: linux.nics, netdev, linux-kernel, jesse.brandeburg, linuxppc-dev,
john.ronciak, jeffrey.t.kirsher, linux-pci, Jeff Garzik
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 <linas@linas.org>
Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
----
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.000000000 -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 *
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, <linux.nics@intel.com>");
@@ -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");
+ 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);
+ }
+
+ switch (adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
+ if (netif_running(netdev))
+ mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
/* e1000_main.c */
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] PCI Error Recovery: e1000 network device driver
@ 2006-04-29 3:26 Zhang, Yanmin
0 siblings, 0 replies; 4+ messages in thread
From: Zhang, Yanmin @ 2006-04-29 3:26 UTC (permalink / raw)
To: Linas Vepstas, Greg KH
Cc: netdev, linux-kernel, Brandeburg, Jesse, linuxppc-dev,
Ronciak, John, Kirsher, Jeffrey T, linux-pci, Jeff Garzik,
Linux NICS
>>-----Original Message-----
>>From: linux-kernel-owner@vger.kernel.org =
[mailto:linux-kernel-owner@vger.kernel.org] On Behalf Of Linas Vepstas
>>Sent: 2006=C4=EA3=D4=C225=C8=D5 11:22
>>To: Greg KH
>>Cc: Jeff Garzik; Ronciak, John; Brandeburg, Jesse; Kirsher, Jeffrey T; =
linux-kernel@vger.kernel.org; netdev@vger.kernel.org;
>>linux-pci@atrey.karlin.mff.cuni.cz; linuxppc-dev@ozlabs.org; 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 <linas@linas.org>
>>Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
>>
>>----
>>
>> 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
>>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>--- linux-2.6.16-git6.orig/drivers/net/e1000/e1000_main.c 2006-03-23 =
15:48:01.000000000 -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 =3D pci_get_drvdata(pdev);
>>+ struct e1000_adapter *adapter =3D 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 =3D pci_get_drvdata(pdev);
>>+ struct e1000_adapter *adapter =3D 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 =3D=3D D3 cold */
[YM] Suggest using PCI_D3hot and PCI_D3cold instead of hard-coded =
numbers.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-04-29 3:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-24 22:00 [PATCH] PCI Error Recovery: e1000 network device driver Linas Vepstas
2006-03-25 2:22 ` Greg KH
2006-03-25 3:21 ` Linas Vepstas
-- strict thread matches above, loose matches on Subject: below --
2006-04-29 3:26 Zhang, Yanmin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).