[PATCH 1/6] scsi: mpt3sas: don't use .device_busy in device reset routine

Ming Lei
2020-01-19T07:15:02Z

scsih_dev_reset() uses scsi_device->device_busy to check if there is
inflight commands aimed to this LUN.

Uses block layer's helper of blk_mq_tagset_busy_iter() to do that, so
we can prepare for bypassing .device_busy for SSD since it is quite
expensive to inc/dec the global atomic counter in IO path.

With this change, no driver uses scsi_device->device_busy any more.

Cc: Sathya Prakash <sathya.prakash@broadcom.com>
Cc: Chaitra P B <chaitra.basappa@broadcom.com>
Cc: Suganath Prabu Subramani <suganath-prabu.subramani@broadcom.com>
Cc: Kashyap Desai <kashyap.desai@broadcom.com>
Cc: Sumit Saxena <sumit.saxena@broadcom.com>
Cc: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Cc: Ewan D. Milne <emilne@redhat.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
drivers/scsi/mpt3sas/mpt3sas_scsih.c | 32 +++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index c597d544eb39..91766c172d8f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2994,6 +2994,36 @@ scsih_abort(struct scsi_cmnd *scmd)
return r;
}

+struct device_busy {
+ struct scsi_device *dev;
+ unsigned int cnt;
+};
+
+static bool scsi_device_check_in_flight(struct request *rq, void *data,
+ bool reserved)
+{
+ struct device_busy *busy = data;
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+ if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state) && cmd->device ==
+ busy->dev)
+ (busy->cnt)++;
+
+ return true;
+}
+
+static bool scsih_dev_busy(struct scsi_device *device)
+{
+ struct device_busy data = {
+ .dev = device,
+ .cnt = 0,
+ };
+
+ blk_mq_tagset_busy_iter(&device->host->tag_set,
+ scsi_device_check_in_flight, &data);
+ return data.cnt > 0;
+}
+
/**
* scsih_dev_reset - eh threads main device reset routine
* @scmd: pointer to scsi command object
@@ -3060,7 +3090,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0,
tr_timeout, tr_method);
/* Check for busy commands after reset */
- if (r == SUCCESS && atomic_read(&scmd->device->device_busy))
+ if (r == SUCCESS && scsih_dev_busy(scmd->device))
r = FAILED;
out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(0x%p)\n",
--
2.20.1