diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-17 15:57:22 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-17 15:57:22 -0800 |
commit | 4410731b3396b2c744d9384a664d7cd37297c431 (patch) | |
tree | 4db44e625f9ffb6fa13baf2fed7f136753e75a6b /pci | |
parent | f37752a5fedef203decdcf6197f53b9cffa04416 (diff) | |
download | patches-4410731b3396b2c744d9384a664d7cd37297c431.tar.gz |
refresh for 2.6.16-rc1 and drop the pci-error-recovery patches
Diffstat (limited to 'pci')
-rw-r--r-- | pci/pci-error-recovery-e100-network-device-driver.patch | 105 | ||||
-rw-r--r-- | pci/pci-error-recovery-e1000-network-device-driver.patch | 150 | ||||
-rw-r--r-- | pci/pci-error-recovery-ipr-scsi-device-driver.patch | 135 | ||||
-rw-r--r-- | pci/pci-error-recovery-ixgb-network-device-driver.patch | 136 | ||||
-rw-r--r-- | pci/pci-error-recovery-symbios-scsi-device-driver.patch | 234 |
5 files changed, 0 insertions, 760 deletions
diff --git a/pci/pci-error-recovery-e100-network-device-driver.patch b/pci/pci-error-recovery-e100-network-device-driver.patch deleted file mode 100644 index 6a26dd29ca32b..0000000000000 --- a/pci/pci-error-recovery-e100-network-device-driver.patch +++ /dev/null @@ -1,105 +0,0 @@ -From linas@austin.ibm.com Fri Nov 18 14:09:21 2005 -Date: Fri, 18 Nov 2005 16:23:26 -0600 -From: linas <linas@austin.ibm.com> -To: greg@kroah.com -Subject: PCI Error Recovery: e100 network device driver -Message-ID: <20051118222326.GC12645@austin.ibm.com> -Content-Disposition: inline - -Various PCI bus errors can be signaled by newer PCI controllers. This -patch adds the PCI error recovery callbacks to the intel ethernet e100 -device driver. The patch has been tested, and appears to work well. - -Signed-off-by: Linas Vepstas <linas@linas.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/net/e100.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 70 insertions(+) - ---- gregkh-2.6.orig/drivers/net/e100.c -+++ gregkh-2.6/drivers/net/e100.c -@@ -2730,6 +2730,75 @@ static void e100_shutdown(struct pci_dev - } - - -+/* ------------------ PCI Error Recovery infrastructure -------------- */ -+/** e100_io_error_detected() is called when PCI error is detected */ -+static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ -+ /* Same as calling e100_down(netdev_priv(netdev)), but generic */ -+ netdev->stop(netdev); -+ -+ /* Is a detach needed ?? */ -+ // netif_device_detach(netdev); -+ -+ /* Request a slot reset. */ -+ return PCI_ERS_RESULT_NEED_RESET; -+} -+ -+/** e100_io_slot_reset is called after the pci bus has been reset. -+ * Restart the card from scratch. */ -+static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct nic *nic = netdev_priv(netdev); -+ -+ if(pci_enable_device(pdev)) { -+ printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); -+ return PCI_ERS_RESULT_DISCONNECT; -+ } -+ pci_set_master(pdev); -+ -+ /* Only one device per card can do a reset */ -+ if (0 != PCI_FUNC (pdev->devfn)) -+ return PCI_ERS_RESULT_RECOVERED; -+ -+ e100_hw_reset(nic); -+ e100_phy_init(nic); -+ -+ if(e100_hw_init(nic)) { -+ DPRINTK(HW, ERR, "e100_hw_init failed\n"); -+ return PCI_ERS_RESULT_DISCONNECT; -+ } -+ -+ return PCI_ERS_RESULT_RECOVERED; -+} -+ -+/** e100_io_resume is called when the error recovery driver -+ * tells us that its OK to resume normal operation. -+ */ -+static void e100_io_resume(struct pci_dev *pdev) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct nic *nic = netdev_priv(netdev); -+ -+ /* ack any pending wake events, disable PME */ -+ pci_enable_wake(pdev, 0, 0); -+ -+ netif_device_attach(netdev); -+ if(netif_running(netdev)) { -+ e100_open (netdev); -+ mod_timer(&nic->watchdog, jiffies); -+ } -+} -+ -+static struct pci_error_handlers e100_err_handler = { -+ .error_detected = e100_io_error_detected, -+ .slot_reset = e100_io_slot_reset, -+ .resume = e100_io_resume, -+}; -+ -+ - static struct pci_driver e100_driver = { - .name = DRV_NAME, - .id_table = e100_id_table, -@@ -2740,6 +2809,7 @@ static struct pci_driver e100_driver = { - .resume = e100_resume, - #endif - .shutdown = e100_shutdown, -+ .err_handler = &e100_err_handler, - }; - - static int __init e100_init_module(void) diff --git a/pci/pci-error-recovery-e1000-network-device-driver.patch b/pci/pci-error-recovery-e1000-network-device-driver.patch deleted file mode 100644 index 950b10146acbf..0000000000000 --- a/pci/pci-error-recovery-e1000-network-device-driver.patch +++ /dev/null @@ -1,150 +0,0 @@ -From linas@austin.ibm.com Fri Nov 18 14:09:23 2005 -Date: Fri, 18 Nov 2005 16:23:54 -0600 -From: linas <linas@austin.ibm.com> -To: greg@kroah.com -Subject: PCI Error Recovery: e1000 network device driver -Message-ID: <20051118222354.GD12645@austin.ibm.com> -Content-Disposition: inline - -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> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/net/e1000/e1000_main.c | 101 ++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 100 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/net/e1000/e1000_main.c -+++ gregkh-2.6/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, <linux.nics@intel.com>"); -@@ -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); -+ } -+ -+ 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 */ diff --git a/pci/pci-error-recovery-ipr-scsi-device-driver.patch b/pci/pci-error-recovery-ipr-scsi-device-driver.patch deleted file mode 100644 index 6c78e493d0d85..0000000000000 --- a/pci/pci-error-recovery-ipr-scsi-device-driver.patch +++ /dev/null @@ -1,135 +0,0 @@ -From linas@austin.ibm.com Fri Nov 18 14:09:18 2005 -Date: Fri, 18 Nov 2005 16:22:38 -0600 -From: linas <linas@austin.ibm.com> -To: greg@kroah.com -Subject: PCI Error Recovery: IPR SCSI device driver -Message-ID: <20051118222238.GA12645@austin.ibm.com> -Content-Disposition: inline - -Various PCI bus errors can be signaled by newer PCI controllers. This -patch adds the PCI error recovery callbacks to the IPR SCSI device driver. -The patch has been tested, and appears to work well. - -Signed-off-by: Linas Vepstas <linas@linas.org> -Signed-off-by: Brian King <brking@us.ibm.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - --- ---- - drivers/scsi/ipr.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 92 insertions(+) - ---- gregkh-2.6.orig/drivers/scsi/ipr.c -+++ gregkh-2.6/drivers/scsi/ipr.c -@@ -5868,6 +5868,92 @@ static void ipr_initiate_ioa_reset(struc - shutdown_type); - } - -+/* --------------- PCI Error Recovery infrastructure ----------- */ -+/** If the PCI slot is frozen, hold off all i/o -+ * activity; then, as soon as the slot is available again, -+ * initiate an adapter reset. -+ */ -+static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd) -+{ -+ /* Disallow new interrupts, avoid loop */ -+ ipr_cmd->ioa_cfg->allow_interrupts = 0; -+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q); -+ ipr_cmd->done = ipr_reset_ioa_job; -+ return IPR_RC_JOB_RETURN; -+} -+ -+/** ipr_eeh_frozen -- called when slot has experience PCI bus error. -+ * This routine is called to tell us that the PCI bus is down. -+ * Can't do anything here, except put the device driver into a -+ * holding pattern, waiting for the PCI bus to come back. -+ */ -+static void ipr_eeh_frozen (struct pci_dev *pdev) -+{ -+ unsigned long flags = 0; -+ struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); -+ -+ spin_lock_irqsave(ioa_cfg->host->host_lock, flags); -+ _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_freeze, IPR_SHUTDOWN_NONE); -+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); -+} -+ -+/** ipr_eeh_slot_reset - called when pci slot has been reset. -+ * -+ * This routine is called by the pci error recovery recovery -+ * code after the PCI slot has been reset, just before we -+ * should resume normal operations. -+ */ -+static pci_ers_result_t ipr_eeh_slot_reset(struct pci_dev *pdev) -+{ -+ unsigned long flags = 0; -+ struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); -+ -+ spin_lock_irqsave(ioa_cfg->host->host_lock, flags); -+ _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, -+ IPR_SHUTDOWN_NONE); -+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); -+ -+ return PCI_ERS_RESULT_RECOVERED; -+} -+ -+/** This routine is called when the PCI bus has permanently -+ * failed. This routine should purge all pending I/O and -+ * shut down the device driver (close and unload). -+ */ -+static void ipr_eeh_perm_failure(struct pci_dev *pdev) -+{ -+ unsigned long flags = 0; -+ struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); -+ -+ spin_lock_irqsave(ioa_cfg->host->host_lock, flags); -+ if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) -+ ioa_cfg->sdt_state = ABORT_DUMP; -+ ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES; -+ ioa_cfg->in_ioa_bringdown = 1; -+ ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); -+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); -+} -+ -+static pci_ers_result_t ipr_eeh_error_detected(struct pci_dev *pdev, -+ pci_channel_state_t state) -+{ -+ switch (state) { -+ case pci_channel_io_frozen: -+ ipr_eeh_frozen (pdev); -+ return PCI_ERS_RESULT_NEED_RESET; -+ -+ case pci_channel_io_perm_failure: -+ ipr_eeh_perm_failure (pdev); -+ return PCI_ERS_RESULT_DISCONNECT; -+ break; -+ default: -+ break; -+ } -+ return PCI_ERS_RESULT_NEED_RESET; -+} -+ -+/* ------------- end of PCI Error Recovery suport ----------- */ -+ - /** - * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) - * @ioa_cfg: ioa cfg struct -@@ -6640,12 +6726,18 @@ static struct pci_device_id ipr_pci_tabl - }; - MODULE_DEVICE_TABLE(pci, ipr_pci_table); - -+static struct pci_error_handlers ipr_err_handler = { -+ .error_detected = ipr_eeh_error_detected, -+ .slot_reset = ipr_eeh_slot_reset, -+}; -+ - static struct pci_driver ipr_driver = { - .name = IPR_NAME, - .id_table = ipr_pci_table, - .probe = ipr_probe, - .remove = ipr_remove, - .shutdown = ipr_shutdown, -+ .err_handler = &ipr_err_handler, - }; - - /** diff --git a/pci/pci-error-recovery-ixgb-network-device-driver.patch b/pci/pci-error-recovery-ixgb-network-device-driver.patch deleted file mode 100644 index 05642fb237da4..0000000000000 --- a/pci/pci-error-recovery-ixgb-network-device-driver.patch +++ /dev/null @@ -1,136 +0,0 @@ -From linas@austin.ibm.com Fri Nov 18 14:14:32 2005 -Date: Fri, 18 Nov 2005 16:24:20 -0600 -From: linas <linas@austin.ibm.com> -To: greg@kroah.com -Subject: PCI Error Recovery: ixgb network device driver -Message-ID: <20051118222420.GE12645@austin.ibm.com> -Content-Disposition: inline - -Various PCI bus errors can be signaled by newer PCI controllers. This -patch adds the PCI error recovery callbacks to the intel ten-gigabit -ethernet ixgb device driver. The patch has been tested, and appears -to work well. - -Signed-off-by: Linas Vepstas <linas@linas.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/net/ixgb/ixgb_main.c | 86 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 86 insertions(+) - ---- gregkh-2.6.orig/drivers/net/ixgb/ixgb_main.c -+++ gregkh-2.6/drivers/net/ixgb/ixgb_main.c -@@ -132,6 +132,16 @@ static void ixgb_restore_vlan(struct ixg - static void ixgb_netpoll(struct net_device *dev); - #endif - -+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, pci_channel_state_t state); -+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev); -+static void ixgb_io_resume (struct pci_dev *pdev); -+ -+static struct pci_error_handlers ixgb_err_handler = { -+ .error_detected = ixgb_io_error_detected, -+ .slot_reset = ixgb_io_slot_reset, -+ .resume = ixgb_io_resume, -+}; -+ - /* Exported from other modules */ - - extern void ixgb_check_options(struct ixgb_adapter *adapter); -@@ -141,6 +151,8 @@ static struct pci_driver ixgb_driver = { - .id_table = ixgb_pci_tbl, - .probe = ixgb_probe, - .remove = __devexit_p(ixgb_remove), -+ .err_handler = &ixgb_err_handler, -+ - }; - - MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); -@@ -1654,8 +1666,16 @@ ixgb_intr(int irq, void *data, struct pt - unsigned int i; - #endif - -+#ifdef XXX_CONFIG_IXGB_EEH_RECOVERY -+ if(unlikely(icr==EEH_IO_ERROR_VALUE(4))) { -+ if (eeh_slot_is_isolated (adapter->pdev)) -+ // disable_irq_nosync (adapter->pdev->irq); -+ return IRQ_NONE; /* Not our interrupt */ -+ } -+#else - if(unlikely(!icr)) - return IRQ_NONE; /* Not our interrupt */ -+#endif /* CONFIG_IXGB_EEH_RECOVERY */ - - if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) { - mod_timer(&adapter->watchdog_timer, jiffies); -@@ -2125,4 +2145,70 @@ static void ixgb_netpoll(struct net_devi - } - #endif - -+/* -------------- PCI Error Recovery infrastructure ---------------- */ -+/** ixgb_io_error_detected() is called when PCI error is detected */ -+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, pci_channel_state_t state) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct ixgb_adapter *adapter = netdev->priv; -+ -+ if(netif_running(netdev)) -+ ixgb_down(adapter, TRUE); -+ -+ /* Request a slot reset. */ -+ return PCI_ERS_RESULT_NEED_RESET; -+} -+ -+/** ixgb_io_slot_reset is called after the pci bus has been reset. -+ * Restart the card from scratch. -+ * Implementation resembles the first-half of the -+ * ixgb_resume routine. -+ */ -+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct ixgb_adapter *adapter = netdev->priv; -+ -+ if(pci_enable_device(pdev)) { -+ printk(KERN_ERR "ixgb: Cannot re-enable PCI device after reset.\n"); -+ return PCI_ERS_RESULT_DISCONNECT; -+ } -+ pci_set_master(pdev); -+ -+ /* Perform card reset only on one instance of the card */ -+ if (0 != PCI_FUNC (pdev->devfn)) -+ return PCI_ERS_RESULT_RECOVERED; -+ -+ ixgb_reset(adapter); -+ -+ return PCI_ERS_RESULT_RECOVERED; -+} -+ -+/** ixgb_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 -+ * ixgb_resume routine. -+ */ -+static void ixgb_io_resume (struct pci_dev *pdev) -+{ -+ struct net_device *netdev = pci_get_drvdata(pdev); -+ struct ixgb_adapter *adapter = netdev->priv; -+ -+ if(netif_running(netdev)) { -+ if(ixgb_up(adapter)) { -+ printk ("ixgb: can't bring device back up after reset\n"); -+ return; -+ } -+ } -+ -+ netif_device_attach(netdev); -+ if(netif_running(netdev)) -+ mod_timer(&adapter->watchdog_timer, jiffies); -+ -+ /* Reading all-ff's from the adapter will completely hose -+ * the counts and statistics. So just clear them out */ -+ memset(&adapter->stats, 0, sizeof(struct ixgb_hw_stats)); -+ ixgb_update_stats(adapter); -+} -+ - /* ixgb_main.c */ diff --git a/pci/pci-error-recovery-symbios-scsi-device-driver.patch b/pci/pci-error-recovery-symbios-scsi-device-driver.patch deleted file mode 100644 index 2b4217ebb3e47..0000000000000 --- a/pci/pci-error-recovery-symbios-scsi-device-driver.patch +++ /dev/null @@ -1,234 +0,0 @@ -From linas@austin.ibm.com Fri Nov 18 14:09:19 2005 -Date: Fri, 18 Nov 2005 16:23:04 -0600 -From: linas <linas@austin.ibm.com> -To: greg@kroah.com -Subject: PCI Error Recovery: Symbios SCSI device driver -Message-ID: <20051118222304.GB12645@austin.ibm.com> -Content-Disposition: inline - -Various PCI bus errors can be signaled by newer PCI controllers. This -patch adds the PCI error recovery callbacks to the Symbios SCSI device driver. -The patch has been tested, and appears to work well. - -Signed-off-by: Linas Vepstas <linas@linas.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/scsi/sym53c8xx_2/sym_glue.c | 113 ++++++++++++++++++++++++++++++++++++ - drivers/scsi/sym53c8xx_2/sym_glue.h | 4 + - drivers/scsi/sym53c8xx_2/sym_hipd.c | 15 ++++ - 3 files changed, 132 insertions(+) - ---- gregkh-2.6.orig/drivers/scsi/sym53c8xx_2/sym_glue.c -+++ gregkh-2.6/drivers/scsi/sym53c8xx_2/sym_glue.c -@@ -716,6 +716,10 @@ static irqreturn_t sym53c8xx_intr(int ir - - if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); - -+ /* Avoid spinloop trying to handle interrupts on frozen device */ -+ if (np->s.io_state != pci_channel_io_normal) -+ return IRQ_HANDLED; -+ - spin_lock_irqsave(np->s.host->host_lock, flags); - sym_interrupt(np); - spin_unlock_irqrestore(np->s.host->host_lock, flags); -@@ -789,6 +793,25 @@ static void sym_eh_done(struct scsi_cmnd - */ - static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); } - -+static void sym_eeh_timeout(u_long p) -+{ -+ struct sym_eh_wait *ep = (struct sym_eh_wait *) p; -+ if (!ep) -+ return; -+ complete(&ep->done); -+} -+ -+static void sym_eeh_done(struct sym_eh_wait *ep) -+{ -+ if (!ep) -+ return; -+ ep->timed_out = 0; -+ if (!del_timer(&ep->timer)) -+ return; -+ -+ complete(&ep->done); -+} -+ - /* - * Generic method for our eh processing. - * The 'op' argument tells what we have to do. -@@ -829,6 +852,35 @@ prepare: - - /* Try to proceed the operation we have been asked for */ - sts = -1; -+ -+ /* We may be in an error condition because the PCI bus -+ * went down. In this case, we need to wait until the -+ * PCI bus is reset, the card is reset, and only then -+ * proceed with the scsi error recovery. We'll wait -+ * for 15 seconds for this to happen. -+ */ -+#define WAIT_FOR_PCI_RECOVERY 15 -+ if (np->s.io_state != pci_channel_io_normal) { -+ struct sym_eh_wait eeh, *eep = &eeh; -+ np->s.io_reset_wait = eep; -+ init_completion(&eep->done); -+ init_timer(&eep->timer); -+ eep->to_do = SYM_EH_DO_WAIT; -+ eep->timer.expires = jiffies + (WAIT_FOR_PCI_RECOVERY*HZ); -+ eep->timer.function = sym_eeh_timeout; -+ eep->timer.data = (u_long)eep; -+ eep->timed_out = 1; /* Be pessimistic for once :) */ -+ add_timer(&eep->timer); -+ spin_unlock_irq(np->s.host->host_lock); -+ wait_for_completion(&eep->done); -+ spin_lock_irq(np->s.host->host_lock); -+ if (eep->timed_out) { -+ printk (KERN_ERR "%s: Timed out waiting for PCI reset\n", -+ sym_name(np)); -+ } -+ np->s.io_reset_wait = NULL; -+ } -+ - switch(op) { - case SYM_EH_ABORT: - sts = sym_abort_scsiio(np, cmd, 1); -@@ -1630,6 +1682,8 @@ static struct Scsi_Host * __devinit sym_ - np->maxoffs = dev->chip.offset_max; - np->maxburst = dev->chip.burst_max; - np->myaddr = dev->host_id; -+ np->s.io_state = pci_channel_io_normal; -+ np->s.io_reset_wait = NULL; - - /* - * Edit its name. -@@ -1962,6 +2016,58 @@ static int sym_detach(struct sym_hcb *np - return 1; - } - -+/* ------------- PCI Error Recovery infrastructure -------------- */ -+/** sym2_io_error_detected() is called when PCI error is detected */ -+static pci_ers_result_t sym2_io_error_detected (struct pci_dev *pdev, pci_channel_state_t state) -+{ -+ struct sym_hcb *np = pci_get_drvdata(pdev); -+ -+ np->s.io_state = state; -+ // XXX If slot is permanently frozen, then what? -+ // Should we scsi_remove_host() maybe ?? -+ -+ /* Request a slot slot reset. */ -+ return PCI_ERS_RESULT_NEED_RESET; -+} -+ -+/** sym2_io_slot_reset is called when the pci bus has been reset. -+ * Restart the card from scratch. */ -+static pci_ers_result_t sym2_io_slot_reset (struct pci_dev *pdev) -+{ -+ struct sym_hcb *np = pci_get_drvdata(pdev); -+ -+ printk (KERN_INFO "%s: recovering from a PCI slot reset\n", -+ sym_name(np)); -+ -+ if (pci_enable_device(pdev)) -+ printk (KERN_ERR "%s: device setup failed most egregiously\n", -+ sym_name(np)); -+ -+ pci_set_master(pdev); -+ enable_irq (pdev->irq); -+ -+ /* Perform host reset only on one instance of the card */ -+ if (0 == PCI_FUNC (pdev->devfn)) -+ sym_reset_scsi_bus(np, 0); -+ -+ return PCI_ERS_RESULT_RECOVERED; -+} -+ -+/** sym2_io_resume is called when the error recovery driver -+ * tells us that its OK to resume normal operation. -+ */ -+static void sym2_io_resume (struct pci_dev *pdev) -+{ -+ struct sym_hcb *np = pci_get_drvdata(pdev); -+ -+ /* Perform device startup only once for this card. */ -+ if (0 == PCI_FUNC (pdev->devfn)) -+ sym_start_up (np, 1); -+ -+ np->s.io_state = pci_channel_io_normal; -+ sym_eeh_done (np->s.io_reset_wait); -+} -+ - /* - * Driver host template. - */ -@@ -2219,11 +2325,18 @@ static struct pci_device_id sym2_id_tabl - - MODULE_DEVICE_TABLE(pci, sym2_id_table); - -+static struct pci_error_handlers sym2_err_handler = { -+ .error_detected = sym2_io_error_detected, -+ .slot_reset = sym2_io_slot_reset, -+ .resume = sym2_io_resume, -+}; -+ - static struct pci_driver sym2_driver = { - .name = NAME53C8XX, - .id_table = sym2_id_table, - .probe = sym2_probe, - .remove = __devexit_p(sym2_remove), -+ .err_handler = &sym2_err_handler, - }; - - static int __init sym2_init(void) ---- gregkh-2.6.orig/drivers/scsi/sym53c8xx_2/sym_glue.h -+++ gregkh-2.6/drivers/scsi/sym53c8xx_2/sym_glue.h -@@ -180,6 +180,10 @@ struct sym_shcb { - char chip_name[8]; - struct pci_dev *device; - -+ /* pci bus i/o state; waiter for clearing of i/o state */ -+ pci_channel_state_t io_state; -+ struct sym_eh_wait *io_reset_wait; -+ - struct Scsi_Host *host; - - void __iomem * ioaddr; /* MMIO kernel io address */ ---- gregkh-2.6.orig/drivers/scsi/sym53c8xx_2/sym_hipd.c -+++ gregkh-2.6/drivers/scsi/sym53c8xx_2/sym_hipd.c -@@ -2761,6 +2761,7 @@ void sym_interrupt (struct sym_hcb *np) - u_char istat, istatc; - u_char dstat; - u_short sist; -+ u_int icnt; - - /* - * interrupt on the fly ? -@@ -2802,6 +2803,7 @@ void sym_interrupt (struct sym_hcb *np) - sist = 0; - dstat = 0; - istatc = istat; -+ icnt = 0; - do { - if (istatc & SIP) - sist |= INW(np, nc_sist); -@@ -2809,6 +2811,19 @@ void sym_interrupt (struct sym_hcb *np) - dstat |= INB(np, nc_dstat); - istatc = INB(np, nc_istat); - istat |= istatc; -+ -+ /* Prevent deadlock waiting on a condition that may never clear. */ -+ /* XXX this is a temporary kludge; the correct to detect -+ * a PCI bus error would be to use the io_check interfaces -+ * proposed by Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> -+ * Problem with polling like that is the state flag might not -+ * be set. -+ */ -+ icnt ++; -+ if (100 < icnt) { -+ if (np->s.device->error_state != pci_channel_io_normal) -+ return; -+ } - } while (istatc & (SIP|DIP)); - - if (DEBUG_FLAGS & DEBUG_TINY) |