diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ipr.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2bba5e55d7b..5890e5f92d8 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -5831,6 +5831,109 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg, | |||
5831 | } | 5831 | } |
5832 | 5832 | ||
5833 | /** | 5833 | /** |
5834 | * ipr_reset_freeze - Hold off all I/O activity | ||
5835 | * @ipr_cmd: ipr command struct | ||
5836 | * | ||
5837 | * Description: If the PCI slot is frozen, hold off all I/O | ||
5838 | * activity; then, as soon as the slot is available again, | ||
5839 | * initiate an adapter reset. | ||
5840 | */ | ||
5841 | static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd) | ||
5842 | { | ||
5843 | /* Disallow new interrupts, avoid loop */ | ||
5844 | ipr_cmd->ioa_cfg->allow_interrupts = 0; | ||
5845 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q); | ||
5846 | ipr_cmd->done = ipr_reset_ioa_job; | ||
5847 | return IPR_RC_JOB_RETURN; | ||
5848 | } | ||
5849 | |||
5850 | /** | ||
5851 | * ipr_pci_frozen - Called when slot has experienced a PCI bus error. | ||
5852 | * @pdev: PCI device struct | ||
5853 | * | ||
5854 | * Description: This routine is called to tell us that the PCI bus | ||
5855 | * is down. Can't do anything here, except put the device driver | ||
5856 | * into a holding pattern, waiting for the PCI bus to come back. | ||
5857 | */ | ||
5858 | static void ipr_pci_frozen(struct pci_dev *pdev) | ||
5859 | { | ||
5860 | unsigned long flags = 0; | ||
5861 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | ||
5862 | |||
5863 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | ||
5864 | _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_freeze, IPR_SHUTDOWN_NONE); | ||
5865 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | ||
5866 | } | ||
5867 | |||
5868 | /** | ||
5869 | * ipr_pci_slot_reset - Called when PCI slot has been reset. | ||
5870 | * @pdev: PCI device struct | ||
5871 | * | ||
5872 | * Description: This routine is called by the pci error recovery | ||
5873 | * code after the PCI slot has been reset, just before we | ||
5874 | * should resume normal operations. | ||
5875 | */ | ||
5876 | static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev) | ||
5877 | { | ||
5878 | unsigned long flags = 0; | ||
5879 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | ||
5880 | |||
5881 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | ||
5882 | _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, | ||
5883 | IPR_SHUTDOWN_NONE); | ||
5884 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | ||
5885 | return PCI_ERS_RESULT_RECOVERED; | ||
5886 | } | ||
5887 | |||
5888 | /** | ||
5889 | * ipr_pci_perm_failure - Called when PCI slot is dead for good. | ||
5890 | * @pdev: PCI device struct | ||
5891 | * | ||
5892 | * Description: This routine is called when the PCI bus has | ||
5893 | * permanently failed. | ||
5894 | */ | ||
5895 | static void ipr_pci_perm_failure(struct pci_dev *pdev) | ||
5896 | { | ||
5897 | unsigned long flags = 0; | ||
5898 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | ||
5899 | |||
5900 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | ||
5901 | if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) | ||
5902 | ioa_cfg->sdt_state = ABORT_DUMP; | ||
5903 | ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES; | ||
5904 | ioa_cfg->in_ioa_bringdown = 1; | ||
5905 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
5906 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | ||
5907 | } | ||
5908 | |||
5909 | /** | ||
5910 | * ipr_pci_error_detected - Called when a PCI error is detected. | ||
5911 | * @pdev: PCI device struct | ||
5912 | * @state: PCI channel state | ||
5913 | * | ||
5914 | * Description: Called when a PCI error is detected. | ||
5915 | * | ||
5916 | * Return value: | ||
5917 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT | ||
5918 | */ | ||
5919 | static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, | ||
5920 | pci_channel_state_t state) | ||
5921 | { | ||
5922 | switch (state) { | ||
5923 | case pci_channel_io_frozen: | ||
5924 | ipr_pci_frozen(pdev); | ||
5925 | return PCI_ERS_RESULT_NEED_RESET; | ||
5926 | case pci_channel_io_perm_failure: | ||
5927 | ipr_pci_perm_failure(pdev); | ||
5928 | return PCI_ERS_RESULT_DISCONNECT; | ||
5929 | break; | ||
5930 | default: | ||
5931 | break; | ||
5932 | } | ||
5933 | return PCI_ERS_RESULT_NEED_RESET; | ||
5934 | } | ||
5935 | |||
5936 | /** | ||
5834 | * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) | 5937 | * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) |
5835 | * @ioa_cfg: ioa cfg struct | 5938 | * @ioa_cfg: ioa cfg struct |
5836 | * | 5939 | * |
@@ -6601,12 +6704,18 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
6601 | }; | 6704 | }; |
6602 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); | 6705 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); |
6603 | 6706 | ||
6707 | static struct pci_error_handlers ipr_err_handler = { | ||
6708 | .error_detected = ipr_pci_error_detected, | ||
6709 | .slot_reset = ipr_pci_slot_reset, | ||
6710 | }; | ||
6711 | |||
6604 | static struct pci_driver ipr_driver = { | 6712 | static struct pci_driver ipr_driver = { |
6605 | .name = IPR_NAME, | 6713 | .name = IPR_NAME, |
6606 | .id_table = ipr_pci_table, | 6714 | .id_table = ipr_pci_table, |
6607 | .probe = ipr_probe, | 6715 | .probe = ipr_probe, |
6608 | .remove = ipr_remove, | 6716 | .remove = ipr_remove, |
6609 | .shutdown = ipr_shutdown, | 6717 | .shutdown = ipr_shutdown, |
6718 | .err_handler = &ipr_err_handler, | ||
6610 | }; | 6719 | }; |
6611 | 6720 | ||
6612 | /** | 6721 | /** |