scsi: smartpqi: enhance reset logic
authorKevin Barnett <kevin.barnett@microsemi.com>
Wed, 31 Aug 2016 19:54:35 +0000 (14:54 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 2 Sep 2016 10:21:37 +0000 (06:21 -0400)
Eliminated timeout from LUN reset logic.

Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/smartpqi/smartpqi.h
drivers/scsi/smartpqi/smartpqi_init.c

index dbcdb03feabfd4af533ce38dc678439c724cdf02..053be6be20778d6a1879485b4f3ec72e4c208ff5 100644 (file)
@@ -370,7 +370,6 @@ struct pqi_task_management_request {
 };
 
 #define SOP_TASK_MANAGEMENT_LUN_RESET  0x8
-#define PQI_ABORT_TIMEOUT_MSECS                (20 * 1000)
 
 struct pqi_task_management_response {
        struct pqi_iu_header header;
@@ -762,7 +761,6 @@ struct pqi_scsi_dev {
 
        struct pqi_sas_port *sas_port;
        struct scsi_device *sdev;
-       bool    reset_in_progress;
 
        struct list_head scsi_device_list_entry;
        struct list_head new_device_list_entry;
index 198a7c2ab9603e469fca97af9c24f5ae6c49ae13..dbc8b40cd8ca22aa783199d601074fa545d9f2e2 100644 (file)
@@ -4537,13 +4537,6 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost,
        bool raid_bypassed;
 
        device = scmd->device->hostdata;
-
-       if (device->reset_in_progress) {
-               set_host_byte(scmd, DID_RESET);
-               pqi_scsi_done(scmd);
-               return 0;
-       }
-
        ctrl_info = shost_to_hba(shost);
 
        if (pqi_ctrl_offline(ctrl_info)) {
@@ -4585,61 +4578,47 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost,
        return rc;
 }
 
-static inline void pqi_complete_queued_requests_queue_group(
-       struct pqi_queue_group *queue_group,
-       struct pqi_scsi_dev *device_in_reset)
+static void pqi_lun_reset_complete(struct pqi_io_request *io_request,
+       void *context)
 {
-       unsigned int path;
-       unsigned long flags;
-       struct pqi_io_request *io_request;
-       struct pqi_io_request *next;
-       struct scsi_cmnd *scmd;
-       struct pqi_scsi_dev *device;
+       struct completion *waiting = context;
 
-       for (path = 0; path < 2; path++) {
-               spin_lock_irqsave(&queue_group->submit_lock[path], flags);
+       complete(waiting);
+}
 
-               list_for_each_entry_safe(io_request, next,
-                       &queue_group->request_list[path],
-                       request_list_entry) {
-                       scmd = io_request->scmd;
-                       if (!scmd)
-                               continue;
-                       device = scmd->device->hostdata;
-                       if (device == device_in_reset) {
-                               set_host_byte(scmd, DID_RESET);
-                               pqi_scsi_done(scmd);
-                               list_del(&io_request->
-                                       request_list_entry);
-                       }
+#define PQI_LUN_RESET_TIMEOUT_SECS     10
+
+static int pqi_wait_for_lun_reset_completion(struct pqi_ctrl_info *ctrl_info,
+       struct pqi_scsi_dev *device, struct completion *wait)
+{
+       int rc;
+       unsigned int wait_secs = 0;
+
+       while (1) {
+               if (wait_for_completion_io_timeout(wait,
+                       PQI_LUN_RESET_TIMEOUT_SECS * HZ)) {
+                       rc = 0;
+                       break;
                }
 
-               spin_unlock_irqrestore(&queue_group->submit_lock[path], flags);
-       }
-}
+               pqi_check_ctrl_health(ctrl_info);
+               if (pqi_ctrl_offline(ctrl_info)) {
+                       rc = -ETIMEDOUT;
+                       break;
+               }
 
-static void pqi_complete_queued_requests(struct pqi_ctrl_info *ctrl_info,
-       struct pqi_scsi_dev *device_in_reset)
-{
-       unsigned int i;
-       struct pqi_queue_group *queue_group;
+               wait_secs += PQI_LUN_RESET_TIMEOUT_SECS;
 
-       for (i = 0; i < ctrl_info->num_queue_groups; i++) {
-               queue_group = &ctrl_info->queue_groups[i];
-               pqi_complete_queued_requests_queue_group(queue_group,
-                       device_in_reset);
+               dev_err(&ctrl_info->pci_dev->dev,
+                       "resetting scsi %d:%d:%d:%d - waiting %u seconds\n",
+                       ctrl_info->scsi_host->host_no, device->bus,
+                       device->target, device->lun, wait_secs);
        }
-}
 
-static void pqi_reset_lun_complete(struct pqi_io_request *io_request,
-       void *context)
-{
-       struct completion *waiting = context;
-
-       complete(waiting);
+       return rc;
 }
 
-static int pqi_reset_lun(struct pqi_ctrl_info *ctrl_info,
+static int pqi_lun_reset(struct pqi_ctrl_info *ctrl_info,
        struct pqi_scsi_dev *device)
 {
        int rc;
@@ -4650,7 +4629,7 @@ static int pqi_reset_lun(struct pqi_ctrl_info *ctrl_info,
        down(&ctrl_info->lun_reset_sem);
 
        io_request = pqi_alloc_io_request(ctrl_info);
-       io_request->io_complete_callback = pqi_reset_lun_complete;
+       io_request->io_complete_callback = pqi_lun_reset_complete;
        io_request->context = &wait;
 
        request = io_request->iu;
@@ -4668,12 +4647,9 @@ static int pqi_reset_lun(struct pqi_ctrl_info *ctrl_info,
                &ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH,
                io_request);
 
-       if (!wait_for_completion_io_timeout(&wait,
-               msecs_to_jiffies(PQI_ABORT_TIMEOUT_MSECS))) {
-               rc = -ETIMEDOUT;
-       } else {
+       rc = pqi_wait_for_lun_reset_completion(ctrl_info, device, &wait);
+       if (rc == 0)
                rc = io_request->status;
-       }
 
        pqi_free_io_request(io_request);
        up(&ctrl_info->lun_reset_sem);
@@ -4692,15 +4668,9 @@ static int pqi_device_reset(struct pqi_ctrl_info *ctrl_info,
        if (pqi_ctrl_offline(ctrl_info))
                return FAILED;
 
-       device->reset_in_progress = true;
-       pqi_complete_queued_requests(ctrl_info, device);
-       rc = pqi_reset_lun(ctrl_info, device);
-       device->reset_in_progress = false;
-
-       if (rc)
-               return FAILED;
+       rc = pqi_lun_reset(ctrl_info, device);
 
-       return SUCCESS;
+       return rc == 0 ? SUCCESS : FAILED;
 }
 
 static int pqi_eh_device_reset_handler(struct scsi_cmnd *scmd)
@@ -4710,7 +4680,6 @@ static int pqi_eh_device_reset_handler(struct scsi_cmnd *scmd)
        struct pqi_scsi_dev *device;
 
        ctrl_info = shost_to_hba(scmd->device->host);
-
        device = scmd->device->hostdata;
 
        dev_err(&ctrl_info->pci_dev->dev,