summaryrefslogtreecommitdiff
path: root/drivers/scsi/pm8001/pm8001_sas.c
diff options
context:
space:
mode:
authorDamien Le Moal <damien.lemoal@opensource.wdc.com>2022-02-20 06:18:05 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2022-02-23 05:31:21 +0300
commit99df0edb5a9849ef8d63b972e3ccba463b0053de (patch)
tree3077126da13982b263926ebd9a6251a35dc39b31 /drivers/scsi/pm8001/pm8001_sas.c
parentbf67e693fc40d7b2e32f79427f1284d98ba1c809 (diff)
downloadlinux-99df0edb5a9849ef8d63b972e3ccba463b0053de.tar.xz
scsi: pm8001: Introduce ccb alloc/free helpers
Introduce the pm8001_ccb_alloc() and pm8001_ccb_free() helpers to replace the typical code patterns: res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) ... ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; ccb->ccb_tag = ccb_tag; ccb->task = task; ccb->n_elem = 0; and ccb->task = NULL; ccb->ccb_tag = PM8001_INVALID_TAG; pm8001_tag_free(pm8001_ha, tag); With the simpler function calls: ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task); if (!ccb) ... and pm8001_ccb_free(pm8001_ha, ccb); The pm8001_ccb_alloc() helper ensures that all fields of the ccb info structure for the newly allocated tag are all initialized, except the buf_prd field. The pm8001_ccb_free() helper clears the initialized fields and the ccb tag to ensure that iteration over the adapter ccb_info array detects ccbs that are in use. All call site of the pm8001_tag_alloc() function that use a ccb info associated with an allocated tag are converted to use the new helpers. Link: https://lore.kernel.org/r/20220220031810.738362-27-damien.lemoal@opensource.wdc.com Reviewed-by: John Garry <john.garry@huawei.com> Reviewed-by: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_sas.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c46
1 files changed, 19 insertions, 27 deletions
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 55859d24edd3..6e5d1af12230 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -74,7 +74,7 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
* @pm8001_ha: our hba struct
* @tag_out: the found empty tag .
*/
-inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
+int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
{
unsigned int tag;
void *bitmap = pm8001_ha->tags;
@@ -381,7 +381,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
struct pm8001_port *port = NULL;
struct sas_task *t = task;
struct pm8001_ccb_info *ccb;
- u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
+ u32 rc = 0, n_elem = 0;
unsigned long flags = 0;
enum sas_protocol task_proto = t->task_proto;
struct sas_tmf_task *tmf = task->tmf;
@@ -427,10 +427,12 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
continue;
}
}
- rc = pm8001_tag_alloc(pm8001_ha, &tag);
- if (rc)
+
+ ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, t);
+ if (!ccb) {
+ rc = -SAS_QUEUE_FULL;
goto err_out;
- ccb = &pm8001_ha->ccb_info[tag];
+ }
if (!sas_protocol_ata(task_proto)) {
if (t->num_scatter) {
@@ -440,7 +442,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
t->data_dir);
if (!n_elem) {
rc = -ENOMEM;
- goto err_out_tag;
+ goto err_out_ccb;
}
}
} else {
@@ -449,9 +451,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
t->lldd_task = ccb;
ccb->n_elem = n_elem;
- ccb->ccb_tag = tag;
- ccb->task = t;
- ccb->device = pm8001_dev;
+
switch (task_proto) {
case SAS_PROTOCOL_SMP:
atomic_inc(&pm8001_dev->running_req);
@@ -480,15 +480,15 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
if (rc) {
pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
atomic_dec(&pm8001_dev->running_req);
- goto err_out_tag;
+ goto err_out_ccb;
}
/* TODO: select normal or high priority */
} while (0);
rc = 0;
goto out_done;
-err_out_tag:
- pm8001_tag_free(pm8001_ha, tag);
+err_out_ccb:
+ pm8001_ccb_free(pm8001_ha, ccb);
err_out:
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
if (!sas_protocol_ata(task_proto))
@@ -548,10 +548,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
}
task->lldd_task = NULL;
- ccb->task = NULL;
- ccb->ccb_tag = PM8001_INVALID_TAG;
- ccb->open_retry = 0;
- pm8001_tag_free(pm8001_ha, ccb_idx);
+ pm8001_ccb_free(pm8001_ha, ccb);
}
/**
@@ -707,7 +704,6 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
u32 task_tag)
{
int res, retry;
- u32 ccb_tag;
struct pm8001_ccb_info *ccb;
struct sas_task *task = NULL;
@@ -724,23 +720,19 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
jiffies + PM8001_TASK_TIMEOUT * HZ;
add_timer(&task->slow_task->timer);
- res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
- if (res)
+ ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
+ if (!ccb) {
+ res = -SAS_QUEUE_FULL;
break;
-
- ccb = &pm8001_ha->ccb_info[ccb_tag];
- ccb->device = pm8001_dev;
- ccb->ccb_tag = ccb_tag;
- ccb->task = task;
- ccb->n_elem = 0;
+ }
res = PM8001_CHIP_DISP->task_abort(pm8001_ha, pm8001_dev, flag,
- task_tag, ccb_tag);
+ task_tag, ccb->ccb_tag);
if (res) {
del_timer(&task->slow_task->timer);
pm8001_dbg(pm8001_ha, FAIL,
"Executing internal task failed\n");
- pm8001_tag_free(pm8001_ha, ccb_tag);
+ pm8001_ccb_free(pm8001_ha, ccb);
break;
}