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

Message ID 1666693096-180008-10-git-send-email-john.garry@huawei.com
State New
Headers
Series blk-mq/libata/scsi: SCSI driver tagging improvements Part I |

Commit Message

John Garry Oct. 25, 2022, 10:18 a.m. UTC
  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(-)
  

Patch

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;