Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Mar 2018 23:59:01 +0000 (16:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Mar 2018 23:59:01 +0000 (16:59 -0700)
Pull SCSI fixes from James Bottomley:

 - one driver patch (qla2xxx) which fixes a problem caused by an
   existing regression fix (FCP discovery is failing)

 - one generic fix to a longstanding bug in libsas that causes I/O
   eventually to hang to the device in the face of ATA error recovery.

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: qla2xxx: Remove FC_NO_LOOP_ID for FCP and FC-NVMe Discovery
  scsi: libsas: defer ata device eh commands to libata

1  2 
drivers/scsi/libsas/sas_scsi_host.c

index 6de9681ace82603370005590238e315b36df19b4,a372af68d9a94bf1b7bd9a97433a8597f00e252e..ceab5e5c41c277a25f879348885be5fa847c4cd8
@@@ -223,6 -223,7 +223,7 @@@ out_done
  static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
  {
        struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
+       struct domain_device *dev = cmd_to_domain_dev(cmd);
        struct sas_task *task = TO_SAS_TASK(cmd);
  
        /* At this point, we only get called following an actual abort
         */
        sas_end_task(cmd, task);
  
+       if (dev_is_sata(dev)) {
+               /* defer commands to libata so that libata EH can
+                * handle ata qcs correctly
+                */
+               list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
+               return;
+       }
        /* now finish the command and move it on to the error
         * handler done list, this also takes it off the
         * error handler pending list.
        scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
  }
  
- static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
- {
-       struct domain_device *dev = cmd_to_domain_dev(cmd);
-       struct sas_ha_struct *ha = dev->port->ha;
-       struct sas_task *task = TO_SAS_TASK(cmd);
-       if (!dev_is_sata(dev)) {
-               sas_eh_finish_cmd(cmd);
-               return;
-       }
-       /* report the timeout to libata */
-       sas_end_task(cmd, task);
-       list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
- }
  static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
  {
        struct scsi_cmnd *cmd, *n;
        list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
                if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
                    cmd->device->lun == my_cmd->device->lun)
-                       sas_eh_defer_cmd(cmd);
+                       sas_eh_finish_cmd(cmd);
        }
  }
  
@@@ -487,28 -480,15 +480,28 @@@ static int sas_queue_reset(struct domai
  
  int sas_eh_abort_handler(struct scsi_cmnd *cmd)
  {
 -      int res;
 +      int res = TMF_RESP_FUNC_FAILED;
        struct sas_task *task = TO_SAS_TASK(cmd);
        struct Scsi_Host *host = cmd->device->host;
 +      struct domain_device *dev = cmd_to_domain_dev(cmd);
        struct sas_internal *i = to_sas_internal(host->transportt);
 +      unsigned long flags;
  
        if (!i->dft->lldd_abort_task)
                return FAILED;
  
 -      res = i->dft->lldd_abort_task(task);
 +      spin_lock_irqsave(host->host_lock, flags);
 +      /* We cannot do async aborts for SATA devices */
 +      if (dev_is_sata(dev) && !host->host_eh_scheduled) {
 +              spin_unlock_irqrestore(host->host_lock, flags);
 +              return FAILED;
 +      }
 +      spin_unlock_irqrestore(host->host_lock, flags);
 +
 +      if (task)
 +              res = i->dft->lldd_abort_task(task);
 +      else
 +              SAS_DPRINTK("no task to abort\n");
        if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE)
                return SUCCESS;
  
@@@ -631,12 -611,12 +624,12 @@@ static void sas_eh_handle_sas_errors(st
                case TASK_IS_DONE:
                        SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
                                    task);
-                       sas_eh_defer_cmd(cmd);
+                       sas_eh_finish_cmd(cmd);
                        continue;
                case TASK_IS_ABORTED:
                        SAS_DPRINTK("%s: task 0x%p is aborted\n",
                                    __func__, task);
-                       sas_eh_defer_cmd(cmd);
+                       sas_eh_finish_cmd(cmd);
                        continue;
                case TASK_IS_AT_LU:
                        SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
                                            "recovered\n",
                                            SAS_ADDR(task->dev),
                                            cmd->device->lun);
-                               sas_eh_defer_cmd(cmd);
+                               sas_eh_finish_cmd(cmd);
                                sas_scsi_clear_queue_lu(work_q, cmd);
                                goto Again;
                        }