]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
scsi: smartpqi: Fix driver synchronization issues
authorKevin Barnett <kevin.barnett@microchip.com>
Thu, 11 Mar 2021 20:17:07 +0000 (14:17 -0600)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Thu, 15 Jul 2021 17:23:46 +0000 (19:23 +0200)
BugLink: https://bugs.launchpad.net/bugs/1933518
 - Synchronize OFA and controller offline events. Prevent I/O during the
   above conditions.

 - Cleanup pqi_device_wait_for_pending_io() by checking the
   device->scsi_cmds_outstanding instead of walking the device's list of
   commands.

 - Stop failing all I/O for all devices. This was causing OS to retry them,
   delaying OFA.

 - Clean up cache flush. The controller is checked for offline status in
   lower level functions.

Link: https://lore.kernel.org/r/161549382770.25025.789855864026860170.stgit@brunhilda
Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Signed-off-by: Kevin Barnett <kevin.barnett@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
(cherry picked from commit 3268b8a8cf77dbc1f84e9a328069144506636c87)
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
drivers/scsi/smartpqi/smartpqi_init.c

index bc0ea2158d1eebe6d0d9a1398ed23534eb37753a..e8ea478c85e75ba6f4b1a588683842cab35dfaba 100644 (file)
@@ -813,13 +813,6 @@ static int pqi_flush_cache(struct pqi_ctrl_info *ctrl_info,
        int rc;
        struct bmic_flush_cache *flush_cache;
 
-       /*
-        * Don't bother trying to flush the cache if the controller is
-        * locked up.
-        */
-       if (pqi_ctrl_offline(ctrl_info))
-               return -ENXIO;
-
        flush_cache = kzalloc(sizeof(*flush_cache), GFP_KERNEL);
        if (!flush_cache)
                return -ENOMEM;
@@ -998,9 +991,6 @@ static void pqi_update_time_worker(struct work_struct *work)
        ctrl_info = container_of(to_delayed_work(work), struct pqi_ctrl_info,
                update_time_work);
 
-       if (pqi_ctrl_offline(ctrl_info))
-               return;
-
        rc = pqi_write_current_time_to_host_wellness(ctrl_info);
        if (rc)
                dev_warn(&ctrl_info->pci_dev->dev,
@@ -5725,7 +5715,6 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scm
        }
 
 out:
-       pqi_ctrl_unbusy(ctrl_info);
        if (rc)
                atomic_dec(&device->scsi_cmds_outstanding);
 
@@ -5837,102 +5826,22 @@ static void pqi_fail_io_queued_for_device(struct pqi_ctrl_info *ctrl_info,
        }
 }
 
-static void pqi_fail_io_queued_for_all_devices(struct pqi_ctrl_info *ctrl_info)
-{
-       unsigned int i;
-       unsigned int path;
-       struct pqi_queue_group *queue_group;
-       unsigned long flags;
-       struct pqi_io_request *io_request;
-       struct pqi_io_request *next;
-       struct scsi_cmnd *scmd;
-
-       for (i = 0; i < ctrl_info->num_queue_groups; i++) {
-               queue_group = &ctrl_info->queue_groups[i];
-
-               for (path = 0; path < 2; path++) {
-                       spin_lock_irqsave(&queue_group->submit_lock[path],
-                                               flags);
-
-                       list_for_each_entry_safe(io_request, next,
-                               &queue_group->request_list[path],
-                               request_list_entry) {
-
-                               scmd = io_request->scmd;
-                               if (!scmd)
-                                       continue;
-
-                               list_del(&io_request->request_list_entry);
-                               set_host_byte(scmd, DID_RESET);
-                               pqi_free_io_request(io_request);
-                               scsi_dma_unmap(scmd);
-                               pqi_scsi_done(scmd);
-                       }
-
-                       spin_unlock_irqrestore(
-                               &queue_group->submit_lock[path], flags);
-               }
-       }
-}
-
 static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info,
        struct pqi_scsi_dev *device, unsigned long timeout_secs)
 {
        unsigned long timeout;
 
-       timeout = (timeout_secs * PQI_HZ) + jiffies;
-
-       while (atomic_read(&device->scsi_cmds_outstanding)) {
-               pqi_check_ctrl_health(ctrl_info);
-               if (pqi_ctrl_offline(ctrl_info))
-                       return -ENXIO;
-               if (timeout_secs != NO_TIMEOUT) {
-                       if (time_after(jiffies, timeout)) {
-                               dev_err(&ctrl_info->pci_dev->dev,
-                                       "timed out waiting for pending IO\n");
-                               return -ETIMEDOUT;
-                       }
-               }
-               usleep_range(1000, 2000);
-       }
-
-       return 0;
-}
-
-static int pqi_ctrl_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info,
-       unsigned long timeout_secs)
-{
-       bool io_pending;
-       unsigned long flags;
-       unsigned long timeout;
-       struct pqi_scsi_dev *device;
 
        timeout = (timeout_secs * PQI_HZ) + jiffies;
-       while (1) {
-               io_pending = false;
-
-               spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
-               list_for_each_entry(device, &ctrl_info->scsi_device_list,
-                       scsi_device_list_entry) {
-                       if (atomic_read(&device->scsi_cmds_outstanding)) {
-                               io_pending = true;
-                               break;
-                       }
-               }
-               spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
-                                       flags);
-
-               if (!io_pending)
-                       break;
 
+       while (atomic_read(&device->scsi_cmds_outstanding)) {
                pqi_check_ctrl_health(ctrl_info);
                if (pqi_ctrl_offline(ctrl_info))
                        return -ENXIO;
-
                if (timeout_secs != NO_TIMEOUT) {
                        if (time_after(jiffies, timeout)) {
                                dev_err(&ctrl_info->pci_dev->dev,
-                                       "timed out waiting for pending IO\n");
+                                       "timed out waiting for pending I/O\n");
                                return -ETIMEDOUT;
                        }
                }
@@ -6013,8 +5922,6 @@ static int pqi_lun_reset(struct pqi_ctrl_info *ctrl_info,
        return rc;
 }
 
-/* Performs a reset at the LUN level. */
-
 #define PQI_LUN_RESET_RETRIES                  3
 #define PQI_LUN_RESET_RETRY_INTERVAL_MSECS     10000
 #define PQI_LUN_RESET_PENDING_IO_TIMEOUT_SECS  120
@@ -7659,8 +7566,6 @@ static int pqi_force_sis_mode(struct pqi_ctrl_info *ctrl_info)
        return pqi_revert_to_sis_mode(ctrl_info);
 }
 
-#define PQI_POST_RESET_DELAY_B4_MSGU_READY     5000
-
 static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 {
        int rc;
@@ -7668,7 +7573,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 
        if (reset_devices) {
                sis_soft_reset(ctrl_info);
-               msleep(PQI_POST_RESET_DELAY_B4_MSGU_READY);
+               msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ);
        } else {
                rc = pqi_force_sis_mode(ctrl_info);
                if (rc)
@@ -8222,12 +8127,7 @@ static void pqi_ofa_ctrl_quiesce(struct pqi_ctrl_info *ctrl_info)
        pqi_ctrl_block_device_reset(ctrl_info);
        pqi_ctrl_block_requests(ctrl_info);
        pqi_ctrl_wait_until_quiesced(ctrl_info);
-       pqi_ctrl_wait_for_pending_io(ctrl_info, PQI_PENDING_IO_TIMEOUT_SECS);
-       pqi_fail_io_queued_for_all_devices(ctrl_info);
-       pqi_wait_until_inbound_queues_empty(ctrl_info);
        pqi_stop_heartbeat_timer(ctrl_info);
-       ctrl_info->pqi_mode_enabled = false;
-       pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
 }
 
 static void pqi_ofa_ctrl_unquiesce(struct pqi_ctrl_info *ctrl_info)