Commit 99df0edb authored by Damien Le Moal's avatar Damien Le Moal Committed by Martin K. Petersen

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.comReviewed-by: default avatarJohn Garry <john.garry@huawei.com>
Reviewed-by: default avatarJack Wang <jinpu.wang@ionos.com>
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@opensource.wdc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent bf67e693
This diff is collapsed.
...@@ -74,7 +74,7 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) ...@@ -74,7 +74,7 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
* @pm8001_ha: our hba struct * @pm8001_ha: our hba struct
* @tag_out: the found empty tag . * @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; unsigned int tag;
void *bitmap = pm8001_ha->tags; void *bitmap = pm8001_ha->tags;
...@@ -381,7 +381,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -381,7 +381,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
struct pm8001_port *port = NULL; struct pm8001_port *port = NULL;
struct sas_task *t = task; struct sas_task *t = task;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
u32 tag = 0xdeadbeef, rc = 0, n_elem = 0; u32 rc = 0, n_elem = 0;
unsigned long flags = 0; unsigned long flags = 0;
enum sas_protocol task_proto = t->task_proto; enum sas_protocol task_proto = t->task_proto;
struct sas_tmf_task *tmf = task->tmf; struct sas_tmf_task *tmf = task->tmf;
...@@ -427,10 +427,12 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -427,10 +427,12 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
continue; 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; goto err_out;
ccb = &pm8001_ha->ccb_info[tag]; }
if (!sas_protocol_ata(task_proto)) { if (!sas_protocol_ata(task_proto)) {
if (t->num_scatter) { if (t->num_scatter) {
...@@ -440,7 +442,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -440,7 +442,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
t->data_dir); t->data_dir);
if (!n_elem) { if (!n_elem) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out_tag; goto err_out_ccb;
} }
} }
} else { } else {
...@@ -449,9 +451,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -449,9 +451,7 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
t->lldd_task = ccb; t->lldd_task = ccb;
ccb->n_elem = n_elem; ccb->n_elem = n_elem;
ccb->ccb_tag = tag;
ccb->task = t;
ccb->device = pm8001_dev;
switch (task_proto) { switch (task_proto) {
case SAS_PROTOCOL_SMP: case SAS_PROTOCOL_SMP:
atomic_inc(&pm8001_dev->running_req); atomic_inc(&pm8001_dev->running_req);
...@@ -480,15 +480,15 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags) ...@@ -480,15 +480,15 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
if (rc) { if (rc) {
pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc); pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
atomic_dec(&pm8001_dev->running_req); atomic_dec(&pm8001_dev->running_req);
goto err_out_tag; goto err_out_ccb;
} }
/* TODO: select normal or high priority */ /* TODO: select normal or high priority */
} while (0); } while (0);
rc = 0; rc = 0;
goto out_done; goto out_done;
err_out_tag: err_out_ccb:
pm8001_tag_free(pm8001_ha, tag); pm8001_ccb_free(pm8001_ha, ccb);
err_out: err_out:
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc); dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
if (!sas_protocol_ata(task_proto)) if (!sas_protocol_ata(task_proto))
...@@ -548,10 +548,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, ...@@ -548,10 +548,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
} }
task->lldd_task = NULL; task->lldd_task = NULL;
ccb->task = NULL; pm8001_ccb_free(pm8001_ha, ccb);
ccb->ccb_tag = PM8001_INVALID_TAG;
ccb->open_retry = 0;
pm8001_tag_free(pm8001_ha, ccb_idx);
} }
/** /**
...@@ -707,7 +704,6 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, ...@@ -707,7 +704,6 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
u32 task_tag) u32 task_tag)
{ {
int res, retry; int res, retry;
u32 ccb_tag;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
struct sas_task *task = NULL; struct sas_task *task = NULL;
...@@ -724,23 +720,19 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, ...@@ -724,23 +720,19 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
jiffies + PM8001_TASK_TIMEOUT * HZ; jiffies + PM8001_TASK_TIMEOUT * HZ;
add_timer(&task->slow_task->timer); add_timer(&task->slow_task->timer);
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, task);
if (res) if (!ccb) {
res = -SAS_QUEUE_FULL;
break; 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, res = PM8001_CHIP_DISP->task_abort(pm8001_ha, pm8001_dev, flag,
task_tag, ccb_tag); task_tag, ccb->ccb_tag);
if (res) { if (res) {
del_timer(&task->slow_task->timer); del_timer(&task->slow_task->timer);
pm8001_dbg(pm8001_ha, FAIL, pm8001_dbg(pm8001_ha, FAIL,
"Executing internal task failed\n"); "Executing internal task failed\n");
pm8001_tag_free(pm8001_ha, ccb_tag); pm8001_ccb_free(pm8001_ha, ccb);
break; break;
} }
......
...@@ -734,6 +734,53 @@ extern const struct attribute_group *pm8001_host_groups[]; ...@@ -734,6 +734,53 @@ extern const struct attribute_group *pm8001_host_groups[];
#define PM8001_INVALID_TAG ((u32)-1) #define PM8001_INVALID_TAG ((u32)-1)
/*
* Allocate a new tag and return the corresponding ccb after initializing it.
*/
static inline struct pm8001_ccb_info *
pm8001_ccb_alloc(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *dev, struct sas_task *task)
{
struct pm8001_ccb_info *ccb;
u32 tag;
if (pm8001_tag_alloc(pm8001_ha, &tag)) {
pm8001_dbg(pm8001_ha, FAIL, "Failed to allocate a tag\n");
return NULL;
}
ccb = &pm8001_ha->ccb_info[tag];
ccb->task = task;
ccb->n_elem = 0;
ccb->ccb_tag = tag;
ccb->device = dev;
ccb->fw_control_context = NULL;
ccb->open_retry = 0;
return ccb;
}
/*
* Free the tag of an initialized ccb.
*/
static inline void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha,
struct pm8001_ccb_info *ccb)
{
u32 tag = ccb->ccb_tag;
/*
* Cleanup the ccb to make sure that a manual scan of the adapter
* ccb_info array can detect ccb's that are in use.
* C.f. pm8001_open_reject_retry()
*/
ccb->task = NULL;
ccb->ccb_tag = PM8001_INVALID_TAG;
ccb->device = NULL;
ccb->fw_control_context = NULL;
pm8001_tag_free(pm8001_ha, tag);
}
static inline void static inline void
pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
struct sas_task *task, struct pm8001_ccb_info *ccb, struct sas_task *task, struct pm8001_ccb_info *ccb,
......
...@@ -1767,8 +1767,6 @@ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) ...@@ -1767,8 +1767,6 @@ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *pm8001_ha_dev) struct pm8001_device *pm8001_ha_dev)
{ {
int res;
u32 ccb_tag;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
struct sas_task *task = NULL; struct sas_task *task = NULL;
struct task_abort_req task_abort; struct task_abort_req task_abort;
...@@ -1790,31 +1788,25 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, ...@@ -1790,31 +1788,25 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
task->task_done = pm8001_task_done; task->task_done = pm8001_task_done;
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
if (res) { if (!ccb) {
sas_free_task(task); sas_free_task(task);
return; return;
} }
ccb = &pm8001_ha->ccb_info[ccb_tag];
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
ccb->n_elem = 0;
circularQ = &pm8001_ha->inbnd_q_tbl[0]; circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&task_abort, 0, sizeof(task_abort)); memset(&task_abort, 0, sizeof(task_abort));
task_abort.abort_all = cpu_to_le32(1); task_abort.abort_all = cpu_to_le32(1);
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
task_abort.tag = cpu_to_le32(ccb_tag); task_abort.tag = cpu_to_le32(ccb->ccb_tag);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
sizeof(task_abort), 0); sizeof(task_abort), 0);
pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n"); pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n");
if (ret) { if (ret) {
sas_free_task(task); sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag); pm8001_ccb_free(pm8001_ha, ccb);
} }
} }
...@@ -1823,7 +1815,6 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, ...@@ -1823,7 +1815,6 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
{ {
struct sata_start_req sata_cmd; struct sata_start_req sata_cmd;
int res; int res;
u32 ccb_tag;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
struct sas_task *task = NULL; struct sas_task *task = NULL;
struct host_to_dev_fis fis; struct host_to_dev_fis fis;
...@@ -1839,20 +1830,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, ...@@ -1839,20 +1830,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
} }
task->task_done = pm8001_task_done; task->task_done = pm8001_task_done;
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); /*
if (res) { * Allocate domain device by ourselves as libsas is not going to
sas_free_task(task); * provide any.
pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n"); */
return;
}
/* allocate domain device by ourselves as libsas
* is not going to provide any
*/
dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
if (!dev) { if (!dev) {
sas_free_task(task); sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
pm8001_dbg(pm8001_ha, FAIL, pm8001_dbg(pm8001_ha, FAIL,
"Domain device cannot be allocated\n"); "Domain device cannot be allocated\n");
return; return;
...@@ -1861,11 +1845,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, ...@@ -1861,11 +1845,13 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
task->dev = dev; task->dev = dev;
task->dev->lldd_dev = pm8001_ha_dev; task->dev->lldd_dev = pm8001_ha_dev;
ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_ha_dev, task);
ccb->device = pm8001_ha_dev; if (!ccb) {
ccb->ccb_tag = ccb_tag; sas_free_task(task);
ccb->task = task; kfree(dev);
ccb->n_elem = 0; return;
}
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG; pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG; pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
...@@ -1880,7 +1866,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, ...@@ -1880,7 +1866,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
fis.lbal = 0x10; fis.lbal = 0x10;
fis.sector_count = 0x1; fis.sector_count = 0x1;
sata_cmd.tag = cpu_to_le32(ccb_tag); sata_cmd.tag = cpu_to_le32(ccb->ccb_tag);
sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9))); sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
...@@ -1890,7 +1876,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, ...@@ -1890,7 +1876,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n"); pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n");
if (res) { if (res) {
sas_free_task(task); sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag); pm8001_ccb_free(pm8001_ha, ccb);
kfree(dev); kfree(dev);
} }
} }
...@@ -4834,7 +4820,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4834,7 +4820,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
u32 stp_sspsmp_sata = 0x4; u32 stp_sspsmp_sata = 0x4;
struct inbound_queue_table *circularQ; struct inbound_queue_table *circularQ;
u32 linkrate, phy_id; u32 linkrate, phy_id;
int rc, tag = 0xdeadbeef; int rc;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
u8 retryFlag = 0x1; u8 retryFlag = 0x1;
u16 firstBurstSize = 0; u16 firstBurstSize = 0;
...@@ -4845,13 +4831,11 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4845,13 +4831,11 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
circularQ = &pm8001_ha->inbnd_q_tbl[0]; circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&payload, 0, sizeof(payload)); memset(&payload, 0, sizeof(payload));
rc = pm8001_tag_alloc(pm8001_ha, &tag); ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);
if (rc) if (!ccb)
return rc; return -SAS_QUEUE_FULL;
ccb = &pm8001_ha->ccb_info[tag];
ccb->device = pm8001_dev; payload.tag = cpu_to_le32(ccb->ccb_tag);
ccb->ccb_tag = tag;
payload.tag = cpu_to_le32(tag);
if (flag == 1) { if (flag == 1) {
stp_sspsmp_sata = 0x02; /*direct attached sata */ stp_sspsmp_sata = 0x02; /*direct attached sata */
...@@ -4888,7 +4872,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4888,7 +4872,7 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
sizeof(payload), 0); sizeof(payload), 0);
if (rc) if (rc)
pm8001_tag_free(pm8001_ha, tag); pm8001_ccb_free(pm8001_ha, ccb);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment