[PATCH RFC v3 09/22] scsi: libsas: Add sas_alloc_slow_task_rq()

John Garry
2022-10-25T09:50:43Z

Add a function to add a slow task with a request associated.

The next step will be to send tasks same as we do for other requests -
through the block layer.

Signed-off-by: John Garry <john.garry@huawei.com>
---
drivers/scsi/libsas/sas_init.c | 51 ++++++++++++++++++++++++++++++
drivers/scsi/libsas/sas_internal.h | 1 +
include/scsi/libsas.h | 2 +-
3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index f2c05ebeb72f..90e63ff5e966 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -56,9 +56,60 @@ struct sas_task *sas_alloc_slow_task(gfp_t flags)
return task;
}

+struct sas_task *sas_alloc_slow_task_rq(struct domain_device *device, gfp_t flags)
+{
+ struct sas_ha_struct *sas_ha = device->port->ha;
+ struct Scsi_Host *shost = sas_ha->core.shost;
+ struct scsi_device *sdev, *found_sdev = NULL;
+ struct scsi_cmnd *scmd;
+ struct sas_task *task;
+ struct request *rq;
+
+ shost_for_each_device(sdev, shost) {
+ struct scsi_target *starget = sdev->sdev_target;
+
+ if (starget->hostdata == device) {
+ found_sdev = sdev;
+ break;
+ }
+ }
+
+ if (!found_sdev)
+ return NULL;
+
+ scsi_device_put(found_sdev);
+
+ task = sas_alloc_slow_task(flags);
+ if (!task)
+ return NULL;
+
+ task->dev = device;
+
+ rq = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN,
+ BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
+ if (IS_ERR(rq)) {
+ sas_free_task(task);
+ return NULL;
+ }
+
+ scmd = blk_mq_rq_to_pdu(rq);
+
+ task->uldd_task = scmd;
+ rq->end_io_data = task;
+
+ return task;
+}
+
void sas_free_task(struct sas_task *task)
{
if (task) {
+ if (task->slow_task && task->uldd_task) {
+ struct scsi_cmnd *scmd = task->uldd_task;
+ struct request *rq = scsi_cmd_to_rq(scmd);
+
+ BUG_ON(!blk_mq_is_reserved_rq(rq));
+ blk_mq_free_request(rq);
+ }
kfree(task->slow_task);
kmem_cache_free(sas_task_cache, task);
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 6cf190ade35e..f5ae4de382f7 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -54,6 +54,7 @@ void sas_free_event(struct asd_sas_event *event);

struct sas_task *sas_alloc_task(gfp_t flags);
struct sas_task *sas_alloc_slow_task(gfp_t flags);
+struct sas_task *sas_alloc_slow_task_rq(struct domain_device *device, gfp_t flags);
void sas_free_task(struct sas_task *task);

int sas_register_ports(struct sas_ha_struct *sas_ha);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 1aee3d0ebbb2..4c4d8c91b1c1 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -648,7 +648,7 @@ static inline struct request *sas_task_find_rq(struct sas_task *task)
{
struct scsi_cmnd *scmd;

- if (task->task_proto & SAS_PROTOCOL_STP_ALL) {
+ if (!task->slow_task && task->task_proto & SAS_PROTOCOL_STP_ALL) {
struct ata_queued_cmd *qc = task->uldd_task;

scmd = qc ? qc->scsicmd : NULL;
--
2.35.3