scsi: pm8001: Use libsas internal abort support
authorJohn Garry <john.garry@huawei.com>
Fri, 11 Mar 2022 12:23:51 +0000 (20:23 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 15 Mar 2022 03:33:24 +0000 (23:33 -0400)
New special handling is added for SAS_PROTOCOL_INTERNAL_ABORT proto so that
we may use the common queue command API.

Link: https://lore.kernel.org/r/1647001432-239276-4-git-send-email-john.garry@huawei.com
Tested-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Acked-by: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.h

index 048ff41..f7466a8 100644 (file)
@@ -4477,22 +4477,25 @@ pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 }
 
 static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
-       u32 dev_id, u8 flag, u32 task_tag, u32 cmd_tag)
+       u32 dev_id, enum sas_internal_abort type, u32 task_tag, u32 cmd_tag)
 {
        struct task_abort_req task_abort;
 
        memset(&task_abort, 0, sizeof(task_abort));
-       if (ABORT_SINGLE == (flag & ABORT_MASK)) {
+       if (type == SAS_INTERNAL_ABORT_SINGLE) {
                task_abort.abort_all = 0;
                task_abort.device_id = cpu_to_le32(dev_id);
                task_abort.tag_to_abort = cpu_to_le32(task_tag);
-               task_abort.tag = cpu_to_le32(cmd_tag);
-       } else if (ABORT_ALL == (flag & ABORT_MASK)) {
+       } else if (type == SAS_INTERNAL_ABORT_DEV) {
                task_abort.abort_all = cpu_to_le32(1);
                task_abort.device_id = cpu_to_le32(dev_id);
-               task_abort.tag = cpu_to_le32(cmd_tag);
+       } else {
+               pm8001_dbg(pm8001_ha, EH, "unknown type (%d)\n", type);
+               return -EIO;
        }
 
+       task_abort.tag = cpu_to_le32(cmd_tag);
+
        return pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &task_abort,
                                    sizeof(task_abort), 0);
 }
@@ -4501,12 +4504,16 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc,
  * pm8001_chip_abort_task - SAS abort task when error or exception happened.
  */
 int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
-       struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag)
+       struct pm8001_ccb_info *ccb)
 {
-       u32 opc, device_id;
+       struct sas_task *task = ccb->task;
+       struct sas_internal_abort_task *abort = &task->abort_task;
+       struct pm8001_device *pm8001_dev = ccb->device;
        int rc = TMF_RESP_FUNC_FAILED;
+       u32 opc, device_id;
+
        pm8001_dbg(pm8001_ha, EH, "cmd_tag = %x, abort task tag = 0x%x\n",
-                  cmd_tag, task_tag);
+                  ccb->ccb_tag, abort->tag);
        if (pm8001_dev->dev_type == SAS_END_DEVICE)
                opc = OPC_INB_SSP_ABORT;
        else if (pm8001_dev->dev_type == SAS_SATA_DEV)
@@ -4514,8 +4521,8 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
        else
                opc = OPC_INB_SMP_ABORT;/* SMP */
        device_id = pm8001_dev->device_id;
-       rc = send_task_abort(pm8001_ha, opc, device_id, flag,
-               task_tag, cmd_tag);
+       rc = send_task_abort(pm8001_ha, opc, device_id, abort->type,
+                            abort->tag, ccb->ccb_tag);
        if (rc != TMF_RESP_FUNC_COMPLETE)
                pm8001_dbg(pm8001_ha, EH, "rc= %d\n", rc);
        return rc;
index d1f3aa9..961d046 100644 (file)
@@ -434,11 +434,6 @@ struct task_abort_req {
        u32     reserved[11];
 } __attribute__((packed, aligned(4)));
 
-/* These flags used for SSP SMP & SATA Abort */
-#define ABORT_MASK             0x3
-#define ABORT_SINGLE           0x0
-#define ABORT_ALL              0x1
-
 /**
  * brief the data structure of SSP SATA SMP Abort Response
  * use to describe SSP SMP & SATA Abort Response ( 64 bytes)
index ac9c40c..3a863d7 100644 (file)
@@ -325,6 +325,18 @@ static int pm8001_task_prep_ata(struct pm8001_hba_info *pm8001_ha,
 }
 
 /**
+  * pm8001_task_prep_internal_abort - the dispatcher function, prepare data
+  *                                  for internal abort task
+  * @pm8001_ha: our hba card information
+  * @ccb: the ccb which attached to sata task
+  */
+static int pm8001_task_prep_internal_abort(struct pm8001_hba_info *pm8001_ha,
+                                          struct pm8001_ccb_info *ccb)
+{
+       return PM8001_CHIP_DISP->task_abort(pm8001_ha, ccb);
+}
+
+/**
   * pm8001_task_prep_ssp_tm - the dispatcher function, prepare task management data
   * @pm8001_ha: our hba card information
   * @ccb: the ccb which attached to TM
@@ -367,6 +379,35 @@ static int sas_find_local_port_id(struct domain_device *dev)
 #define DEV_IS_GONE(pm8001_dev)        \
        ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
 
+
+static int pm8001_deliver_command(struct pm8001_hba_info *pm8001_ha,
+                                 struct pm8001_ccb_info *ccb)
+{
+       struct sas_task *task = ccb->task;
+       enum sas_protocol task_proto = task->task_proto;
+       struct sas_tmf_task *tmf = task->tmf;
+       int is_tmf = !!tmf;
+
+       switch (task_proto) {
+       case SAS_PROTOCOL_SMP:
+               return pm8001_task_prep_smp(pm8001_ha, ccb);
+       case SAS_PROTOCOL_SSP:
+               if (is_tmf)
+                       return pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf);
+               return pm8001_task_prep_ssp(pm8001_ha, ccb);
+       case SAS_PROTOCOL_SATA:
+       case SAS_PROTOCOL_STP:
+               return pm8001_task_prep_ata(pm8001_ha, ccb);
+       case SAS_PROTOCOL_INTERNAL_ABORT:
+               return pm8001_task_prep_internal_abort(pm8001_ha, ccb);
+       default:
+               dev_err(pm8001_ha->dev, "unknown sas_task proto: 0x%x\n",
+                       task_proto);
+       }
+
+       return -EINVAL;
+}
+
 /**
   * pm8001_queue_command - register for upper layer used, all IO commands sent
   * to HBA are from this interface.
@@ -379,16 +420,15 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
        enum sas_protocol task_proto = task->task_proto;
        struct domain_device *dev = task->dev;
        struct pm8001_device *pm8001_dev = dev->lldd_dev;
+       bool internal_abort = sas_is_internal_abort(task);
        struct pm8001_hba_info *pm8001_ha;
        struct pm8001_port *port = NULL;
        struct pm8001_ccb_info *ccb;
-       struct sas_tmf_task *tmf = task->tmf;
-       int is_tmf = !!task->tmf;
        unsigned long flags;
        u32 n_elem = 0;
        int rc = 0;
 
-       if (!dev->port) {
+       if (!internal_abort && !dev->port) {
                ts->resp = SAS_TASK_UNDELIVERED;
                ts->stat = SAS_PHY_DOWN;
                if (dev->dev_type != SAS_SATA_DEV)
@@ -410,7 +450,8 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
        pm8001_dev = dev->lldd_dev;
        port = &pm8001_ha->port[sas_find_local_port_id(dev)];
 
-       if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
+       if (!internal_abort &&
+           (DEV_IS_GONE(pm8001_dev) || !port->port_attached)) {
                ts->resp = SAS_TASK_UNDELIVERED;
                ts->stat = SAS_PHY_DOWN;
                if (sas_protocol_ata(task_proto)) {
@@ -448,27 +489,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
 
        atomic_inc(&pm8001_dev->running_req);
 
-       switch (task_proto) {
-       case SAS_PROTOCOL_SMP:
-               rc = pm8001_task_prep_smp(pm8001_ha, ccb);
-               break;
-       case SAS_PROTOCOL_SSP:
-               if (is_tmf)
-                       rc = pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf);
-               else
-                       rc = pm8001_task_prep_ssp(pm8001_ha, ccb);
-               break;
-       case SAS_PROTOCOL_SATA:
-       case SAS_PROTOCOL_STP:
-               rc = pm8001_task_prep_ata(pm8001_ha, ccb);
-               break;
-       default:
-               dev_printk(KERN_ERR, pm8001_ha->dev,
-                          "unknown sas_task proto: 0x%x\n", task_proto);
-               rc = -EINVAL;
-               break;
-       }
-
+       rc = pm8001_deliver_command(pm8001_ha, ccb);
        if (rc) {
                atomic_dec(&pm8001_dev->running_req);
                if (!sas_protocol_ata(task_proto) && n_elem)
@@ -668,87 +689,7 @@ void pm8001_task_done(struct sas_task *task)
        complete(&task->slow_task->completion);
 }
 
-static void pm8001_tmf_timedout(struct timer_list *t)
-{
-       struct sas_task_slow *slow = from_timer(slow, t, timer);
-       struct sas_task *task = slow->task;
-       unsigned long flags;
-
-       spin_lock_irqsave(&task->task_state_lock, flags);
-       if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-               task->task_state_flags |= SAS_TASK_STATE_ABORTED;
-               complete(&task->slow_task->completion);
-       }
-       spin_unlock_irqrestore(&task->task_state_lock, flags);
-}
-
 #define PM8001_TASK_TIMEOUT 20
-static int
-pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
-       struct pm8001_device *pm8001_dev, struct domain_device *dev, u32 flag,
-       u32 task_tag)
-{
-       int res, retry;
-       struct pm8001_ccb_info *ccb;
-       struct sas_task *task = NULL;
-
-       for (retry = 0; retry < 3; retry++) {
-               task = sas_alloc_slow_task(GFP_KERNEL);
-               if (!task)
-                       return -ENOMEM;
-
-               task->dev = dev;
-               task->task_proto = dev->tproto;
-               task->task_done = pm8001_task_done;
-               task->slow_task->timer.function = pm8001_tmf_timedout;
-               task->slow_task->timer.expires =
-                       jiffies + PM8001_TASK_TIMEOUT * HZ;
-               add_timer(&task->slow_task->timer);
-
-               ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
-               if (!ccb) {
-                       res = -SAS_QUEUE_FULL;
-                       break;
-               }
-
-               res = PM8001_CHIP_DISP->task_abort(pm8001_ha, pm8001_dev, flag,
-                                                  task_tag, ccb->ccb_tag);
-               if (res) {
-                       del_timer(&task->slow_task->timer);
-                       pm8001_dbg(pm8001_ha, FAIL,
-                                  "Executing internal task failed\n");
-                       pm8001_ccb_free(pm8001_ha, ccb);
-                       break;
-               }
-
-               wait_for_completion(&task->slow_task->completion);
-               res = TMF_RESP_FUNC_FAILED;
-
-               /* Even TMF timed out, return direct. */
-               if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
-                       pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
-                       break;
-               }
-
-               if (task->task_status.resp == SAS_TASK_COMPLETE &&
-                       task->task_status.stat == SAS_SAM_STAT_GOOD) {
-                       res = TMF_RESP_FUNC_COMPLETE;
-                       break;
-               }
-
-               pm8001_dbg(pm8001_ha, EH,
-                          " Task to dev %016llx response: 0x%x status 0x%x\n",
-                          SAS_ADDR(dev->sas_addr),
-                          task->task_status.resp,
-                          task->task_status.stat);
-               sas_free_task(task);
-               task = NULL;
-       }
-
-       BUG_ON(retry == 3 && task != NULL);
-       sas_free_task(task);
-       return res;
-}
 
 /**
   * pm8001_dev_gone_notify - see the comments for "pm8001_dev_found_notify"
@@ -769,8 +710,7 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)
                           pm8001_dev->device_id, pm8001_dev->dev_type);
                if (atomic_read(&pm8001_dev->running_req)) {
                        spin_unlock_irqrestore(&pm8001_ha->lock, flags);
-                       pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                                                       dev, 1, 0);
+                       sas_execute_internal_abort_dev(dev, 0, NULL);
                        while (atomic_read(&pm8001_dev->running_req))
                                msleep(20);
                        spin_lock_irqsave(&pm8001_ha->lock, flags);
@@ -893,8 +833,7 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
                        goto out;
                }
                msleep(2000);
-               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                                                    dev, 1, 0);
+               rc = sas_execute_internal_abort_dev(dev, 0, NULL);
                if (rc) {
                        pm8001_dbg(pm8001_ha, EH, "task abort failed %x\n"
                                   "with rc %d\n", pm8001_dev->device_id, rc);
@@ -939,8 +878,7 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
                        goto out;
                }
                /* send internal ssp/sata/smp abort command to FW */
-               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                                                    dev, 1, 0);
+               sas_execute_internal_abort_dev(dev, 0, NULL);
                msleep(100);
 
                /* deregister the target device */
@@ -955,8 +893,7 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
                wait_for_completion(&completion_setstate);
        } else {
                /* send internal ssp/sata/smp abort command to FW */
-               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                                                    dev, 1, 0);
+               sas_execute_internal_abort_dev(dev, 0, NULL);
                msleep(100);
 
                /* deregister the target device */
@@ -983,8 +920,7 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
        DECLARE_COMPLETION_ONSTACK(completion_setstate);
        if (dev_is_sata(dev)) {
                struct sas_phy *phy = sas_get_local_phy(dev);
-               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                                                    dev, 1, 0);
+               sas_execute_internal_abort_dev(dev, 0, NULL);
                rc = sas_phy_reset(phy, 1);
                sas_put_local_phy(phy);
                pm8001_dev->setds_completion = &completion_setstate;
@@ -1084,8 +1020,7 @@ int pm8001_abort_task(struct sas_task *task)
        spin_unlock_irqrestore(&task->task_state_lock, flags);
        if (task->task_proto & SAS_PROTOCOL_SSP) {
                rc = sas_abort_task(task, tag);
-               pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                       pm8001_dev->sas_device, 0, tag);
+               sas_execute_internal_abort_single(dev, tag, 0, NULL);
        } else if (task->task_proto & SAS_PROTOCOL_SATA ||
                task->task_proto & SAS_PROTOCOL_STP) {
                if (pm8001_ha->chip_id == chip_8006) {
@@ -1158,8 +1093,7 @@ int pm8001_abort_task(struct sas_task *task)
                         * is removed from the ccb. on success the caller is
                         * going to free the task.
                         */
-                       ret = pm8001_exec_internal_task_abort(pm8001_ha,
-                               pm8001_dev, pm8001_dev->sas_device, 1, tag);
+                       ret = sas_execute_internal_abort_dev(dev, 0, NULL);
                        if (ret)
                                goto out;
                        ret = wait_for_completion_timeout(
@@ -1175,14 +1109,12 @@ int pm8001_abort_task(struct sas_task *task)
                                pm8001_dev, DS_OPERATIONAL);
                        wait_for_completion(&completion);
                } else {
-                       rc = pm8001_exec_internal_task_abort(pm8001_ha,
-                               pm8001_dev, pm8001_dev->sas_device, 0, tag);
+                       ret = sas_execute_internal_abort_single(dev, tag, 0, NULL);
                }
                rc = TMF_RESP_FUNC_COMPLETE;
        } else if (task->task_proto & SAS_PROTOCOL_SMP) {
                /* SMP */
-               rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-                       pm8001_dev->sas_device, 0, tag);
+               rc = sas_execute_internal_abort_single(dev, tag, 0, NULL);
 
        }
 out:
index d522bd0..060ab68 100644 (file)
@@ -196,8 +196,7 @@ struct pm8001_dispatch {
        int (*phy_ctl_req)(struct pm8001_hba_info *pm8001_ha,
                u32 phy_id, u32 phy_op);
        int (*task_abort)(struct pm8001_hba_info *pm8001_ha,
-               struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag,
-               u32 cmd_tag);
+               struct pm8001_ccb_info *ccb);
        int (*ssp_tm_req)(struct pm8001_hba_info *pm8001_ha,
                struct pm8001_ccb_info *ccb, struct sas_tmf_task *tmf);
        int (*get_nvmd_req)(struct pm8001_hba_info *pm8001_ha, void *payload);
@@ -683,8 +682,7 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha,
                                struct pm8001_ccb_info *ccb,
                                struct sas_tmf_task *tmf);
 int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
-                               struct pm8001_device *pm8001_dev,
-                               u8 flag, u32 task_tag, u32 cmd_tag);
+                               struct pm8001_ccb_info *ccb);
 int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id);
 void pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd);
 void pm8001_work_fn(struct work_struct *work);
index b9d9d11..acf6e30 100644 (file)
@@ -672,11 +672,6 @@ struct task_abort_req {
        u32     reserved[27];
 } __attribute__((packed, aligned(4)));
 
-/* These flags used for SSP SMP & SATA Abort */
-#define ABORT_MASK             0x3
-#define ABORT_SINGLE           0x0
-#define ABORT_ALL              0x1
-
 /**
  * brief the data structure of SSP SATA SMP Abort Response
  * use to describe SSP SMP & SATA Abort Response ( 64 bytes)