diff options
Diffstat (limited to 'drivers/scsi/smartpqi')
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi.h | 7 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 48 | ||||
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_sis.c | 2 |
3 files changed, 52 insertions, 5 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h index aa8663e1b98b..f1145ded843e 100644 --- a/drivers/scsi/smartpqi/smartpqi.h +++ b/drivers/scsi/smartpqi/smartpqi.h @@ -1269,6 +1269,12 @@ struct pqi_event { #define PQI_CTRL_PRODUCT_REVISION_A 0 #define PQI_CTRL_PRODUCT_REVISION_B 1 +enum pqi_ctrl_removal_state { + PQI_CTRL_PRESENT = 0, + PQI_CTRL_GRACEFUL_REMOVAL, + PQI_CTRL_SURPRISE_REMOVAL +}; + struct pqi_ctrl_info { unsigned int ctrl_id; struct pci_dev *pci_dev; @@ -1389,6 +1395,7 @@ struct pqi_ctrl_info { struct work_struct ofa_quiesce_work; u32 ofa_bytes_requested; u16 ofa_cancel_reason; + enum pqi_ctrl_removal_state ctrl_removal_state; }; enum pqi_ctrl_mode { diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 11a8e224fe84..27b83db3e3dc 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -95,6 +95,7 @@ static void pqi_ofa_free_host_buffer(struct pqi_ctrl_info *ctrl_info); static int pqi_ofa_host_memory_update(struct pqi_ctrl_info *ctrl_info); static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, u8 lun, unsigned long timeout_msecs); +static void pqi_fail_all_outstanding_requests(struct pqi_ctrl_info *ctrl_info); /* for flags argument to pqi_submit_raid_request_synchronous() */ #define PQI_SYNC_FLAGS_INTERRUPTABLE 0x1 @@ -6157,9 +6158,11 @@ static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info, warning_timeout = (PQI_PENDING_IO_WARNING_TIMEOUT_SECS * HZ) + start_jiffies; while ((cmds_outstanding = atomic_read(&device->scsi_cmds_outstanding[lun])) > 0) { - pqi_check_ctrl_health(ctrl_info); - if (pqi_ctrl_offline(ctrl_info)) - return -ENXIO; + if (ctrl_info->ctrl_removal_state != PQI_CTRL_GRACEFUL_REMOVAL) { + pqi_check_ctrl_health(ctrl_info); + if (pqi_ctrl_offline(ctrl_info)) + return -ENXIO; + } msecs_waiting = jiffies_to_msecs(jiffies - start_jiffies); if (msecs_waiting >= timeout_msecs) { dev_err(&ctrl_info->pci_dev->dev, @@ -6945,6 +6948,9 @@ static ssize_t pqi_unique_id_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -6981,6 +6987,9 @@ static ssize_t pqi_lunid_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7016,6 +7025,9 @@ static ssize_t pqi_path_info_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7093,6 +7105,9 @@ static ssize_t pqi_sas_address_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7119,6 +7134,9 @@ static ssize_t pqi_ssd_smart_path_enabled_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7148,6 +7166,9 @@ static ssize_t pqi_raid_level_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7178,6 +7199,9 @@ static ssize_t pqi_raid_bypass_cnt_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -7205,6 +7229,9 @@ static ssize_t pqi_sas_ncq_prio_enable_show(struct device *dev, sdev = to_scsi_device(dev); ctrl_info = shost_to_hba(sdev->host); + if (pqi_ctrl_offline(ctrl_info)) + return -ENODEV; + spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags); device = sdev->hostdata; @@ -8547,7 +8574,6 @@ static void pqi_free_interrupts(struct pqi_ctrl_info *ctrl_info) static void pqi_free_ctrl_resources(struct pqi_ctrl_info *ctrl_info) { - pqi_stop_heartbeat_timer(ctrl_info); pqi_free_interrupts(ctrl_info); if (ctrl_info->queue_memory_base) dma_free_coherent(&ctrl_info->pci_dev->dev, @@ -8572,8 +8598,15 @@ static void pqi_free_ctrl_resources(struct pqi_ctrl_info *ctrl_info) static void pqi_remove_ctrl(struct pqi_ctrl_info *ctrl_info) { + ctrl_info->controller_online = false; + pqi_stop_heartbeat_timer(ctrl_info); + pqi_ctrl_block_requests(ctrl_info); pqi_cancel_rescan_worker(ctrl_info); pqi_cancel_update_time_worker(ctrl_info); + if (ctrl_info->ctrl_removal_state == PQI_CTRL_SURPRISE_REMOVAL) { + pqi_fail_all_outstanding_requests(ctrl_info); + ctrl_info->pqi_mode_enabled = false; + } pqi_remove_all_scsi_devices(ctrl_info); pqi_unregister_scsi(ctrl_info); if (ctrl_info->pqi_mode_enabled) @@ -8914,11 +8947,18 @@ error: static void pqi_pci_remove(struct pci_dev *pci_dev) { struct pqi_ctrl_info *ctrl_info; + u16 vendor_id; ctrl_info = pci_get_drvdata(pci_dev); if (!ctrl_info) return; + pci_read_config_word(ctrl_info->pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &vendor_id); + if (vendor_id == 0xffff) + ctrl_info->ctrl_removal_state = PQI_CTRL_SURPRISE_REMOVAL; + else + ctrl_info->ctrl_removal_state = PQI_CTRL_GRACEFUL_REMOVAL; + pqi_remove_ctrl(ctrl_info); } diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c index 2b99b6e9cd71..59d9c2792371 100644 --- a/drivers/scsi/smartpqi/smartpqi_sis.c +++ b/drivers/scsi/smartpqi/smartpqi_sis.c @@ -138,7 +138,7 @@ bool sis_is_firmware_running(struct pqi_ctrl_info *ctrl_info) status = readl(&ctrl_info->registers->sis_firmware_status); - if (status & SIS_CTRL_KERNEL_PANIC) + if (status != ~0 && (status & SIS_CTRL_KERNEL_PANIC)) running = false; else running = true; |