diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
| -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 2bba5e55d7bc..5890e5f92d82 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 | /** |
