[PATCH RFC v2 20/24] aacraid: use scsi_host_tagset_busy_iter() to traverse outstanding commands

From: John Garry
Date: Tue Mar 10 2020 - 12:31:26 EST


From: Hannes Reinecke <hare@xxxxxxx>

Instead of walking the array of potential commands and trying to figure out
which one might be pending the driver should be using
scsi_host_tagset_busy_iter() to traverse all outstanding commands.

Signed-off-by: Hannes Reinecke <hare@xxxxxxxx>
---
drivers/scsi/aacraid/commsup.c | 49 +++++----
drivers/scsi/aacraid/linit.c | 188 ++++++++++++++++++++-------------
2 files changed, 142 insertions(+), 95 deletions(-)

diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index c0c2c87c4ae3..5e82f4741d82 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1459,6 +1459,32 @@ static void aac_schedule_bus_scan(struct aac_dev *aac)
aac_schedule_src_reinit_aif_worker(aac);
}

+static bool aac_close_sync_fib_iter(struct scsi_cmnd *command, void *data,
+ bool reserved)
+{
+ struct Scsi_Host *host = command->device->host;
+ struct aac_dev *aac = (struct aac_dev *)host->hostdata;
+ struct fib *fib = &aac->fibs[command->request->tag];
+ int *retval = data;
+ __le32 XferState = fib->hw_fib_va->header.XferState;
+ bool is_response_expected = false;
+
+ if (!(XferState & cpu_to_le32(NoResponseExpected | Async)) &&
+ (XferState & cpu_to_le32(ResponseExpected)))
+ is_response_expected = true;
+
+ if (is_response_expected
+ || fib->flags & FIB_CONTEXT_FLAG_WAIT) {
+ unsigned long flagv;
+ spin_lock_irqsave(&fib->event_lock, flagv);
+ complete(&fib->event_wait);
+ spin_unlock_irqrestore(&fib->event_lock, flagv);
+ schedule();
+ *retval = 0;
+ }
+ return true;
+}
+
static bool aac_reset_adapter_iter(struct scsi_cmnd *command, void *data,
bool reserved)
{
@@ -1482,7 +1508,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
int jafo = 0;
int bled;
u64 dmamask;
- int num_of_fibs = 0;

/*
* Assumptions:
@@ -1518,27 +1543,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
* Loop through the fibs, close the synchronous FIBS
*/
retval = 1;
- num_of_fibs = aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB;
- for (index = 0; index < num_of_fibs; index++) {
-
- struct fib *fib = &aac->fibs[index];
- __le32 XferState = fib->hw_fib_va->header.XferState;
- bool is_response_expected = false;
-
- if (!(XferState & cpu_to_le32(NoResponseExpected | Async)) &&
- (XferState & cpu_to_le32(ResponseExpected)))
- is_response_expected = true;
-
- if (is_response_expected
- || fib->flags & FIB_CONTEXT_FLAG_WAIT) {
- unsigned long flagv;
- spin_lock_irqsave(&fib->event_lock, flagv);
- complete(&fib->event_wait);
- spin_unlock_irqrestore(&fib->event_lock, flagv);
- schedule();
- retval = 0;
- }
- }
+ scsi_host_tagset_busy_iter(host, aac_close_sync_fib_iter, &retval);
/* Give some extra time for ioctls to complete. */
if (retval == 0)
ssleep(2);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 2da2f3bfcdc1..457bf342aa82 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -681,14 +681,87 @@ static int get_num_of_incomplete_fibs(struct aac_dev *aac)
return iter_data.mlcnt + iter_data.llcnt + iter_data.ehcnt + iter_data.fwcnt;
}

+struct aac_eh_abort_iter_data {
+ struct aac_dev *aac;
+ struct scsi_cmnd *cmd;
+ int ret;
+};
+
+static bool aac_eh_abort_busy_iter(struct scsi_cmnd *cmd, void *data,
+ bool reserved)
+{
+ struct aac_eh_abort_iter_data *iter_data = data;
+ struct aac_dev *aac = iter_data->aac;
+ struct fib *fib = &aac->fibs[cmd->request->tag];
+
+ if (cmd != iter_data->cmd)
+ return true;
+
+ if (*(u8 *)fib->hw_fib_va != 0 &&
+ (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
+ (fib->callback_data == cmd)) {
+ iter_data->ret = SUCCESS;
+ return false;
+ }
+ return true;
+}
+
+static bool aac_eh_abort_cmd_iter(struct scsi_cmnd *cmd, void *data,
+ bool reserved)
+{
+ struct aac_eh_abort_iter_data *iter_data = data;
+ struct fib *fib = &iter_data->aac->fibs[cmd->request->tag];
+
+ if (cmd != iter_data->cmd)
+ return true;
+
+ if (fib->hw_fib_va->header.XferState &&
+ (fib->flags & FIB_CONTEXT_FLAG) &&
+ (fib->callback_data == iter_data->cmd)) {
+ fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+ cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ iter_data->ret = SUCCESS;
+ }
+ return true;
+}
+
+static bool aac_eh_abort_tur_iter(struct scsi_cmnd *cmd, void *data,
+ bool reserved)
+{
+ struct aac_eh_abort_iter_data *iter_data = data;
+ struct fib *fib = &iter_data->aac->fibs[cmd->request->tag];
+ struct scsi_cmnd *command;
+
+ if (cmd != iter_data->cmd)
+ return true;
+
+ command = fib->callback_data;
+ if ((fib->hw_fib_va->header.XferState &
+ cpu_to_le32(Async | NoResponseExpected)) &&
+ (fib->flags & FIB_CONTEXT_FLAG) &&
+ ((command)) && (command->device == cmd->device)) {
+ fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+ command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ if (command == cmd)
+ iter_data->ret = SUCCESS;
+ }
+ return true;
+}
+
static int aac_eh_abort(struct scsi_cmnd* cmd)
{
struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host;
struct aac_dev * aac = (struct aac_dev *)host->hostdata;
- int count, found;
+ int count;
u32 bus, cid;
int ret = FAILED;
+ struct aac_eh_abort_iter_data iter_data = {
+ .aac = aac,
+ .cmd = cmd,
+ .ret = FAILED,
+ };
+

if (aac_adapter_check_health(aac))
return ret;
@@ -705,17 +778,9 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
AAC_DRIVERNAME,
host->host_no, sdev_channel(dev), sdev_id(dev), (int)dev->lun);

- found = 0;
- for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
- fib = &aac->fibs[count];
- if (*(u8 *)fib->hw_fib_va != 0 &&
- (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
- (fib->callback_data == cmd)) {
- found = 1;
- break;
- }
- }
- if (!found)
+ scsi_host_tagset_busy_iter(host, aac_eh_abort_busy_iter,
+ &iter_data);
+ if (iter_data.ret == FAILED)
return ret;

/* start a HBA_TMF_ABORT_TASK TMF request */
@@ -773,49 +838,18 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
* Mark associated FIB to not complete,
* eh handler does this
*/
- for (count = 0;
- count < (host->can_queue + AAC_NUM_MGT_FIB);
- ++count) {
- struct fib *fib = &aac->fibs[count];
-
- if (fib->hw_fib_va->header.XferState &&
- (fib->flags & FIB_CONTEXT_FLAG) &&
- (fib->callback_data == cmd)) {
- fib->flags |=
- FIB_CONTEXT_FLAG_TIMED_OUT;
- cmd->SCp.phase =
- AAC_OWNER_ERROR_HANDLER;
- ret = SUCCESS;
- }
- }
+ scsi_host_tagset_busy_iter(host, aac_eh_abort_cmd_iter,
+ &iter_data);
+ ret = iter_data.ret;
break;
case TEST_UNIT_READY:
/*
* Mark associated FIB to not complete,
* eh handler does this
*/
- for (count = 0;
- count < (host->can_queue + AAC_NUM_MGT_FIB);
- ++count) {
- struct scsi_cmnd *command;
- struct fib *fib = &aac->fibs[count];
-
- command = fib->callback_data;
-
- if ((fib->hw_fib_va->header.XferState &
- cpu_to_le32
- (Async | NoResponseExpected)) &&
- (fib->flags & FIB_CONTEXT_FLAG) &&
- ((command)) &&
- (command->device == cmd->device)) {
- fib->flags |=
- FIB_CONTEXT_FLAG_TIMED_OUT;
- command->SCp.phase =
- AAC_OWNER_ERROR_HANDLER;
- if (command == cmd)
- ret = SUCCESS;
- }
- }
+ scsi_host_tagset_busy_iter(host, aac_eh_abort_tur_iter,
+ &iter_data);
+ ret = iter_data.ret;
break;
}
}
@@ -1010,6 +1044,36 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
return ret;
}

+static bool aac_eh_bus_reset_iter(struct scsi_cmnd *cmd, void *data,
+ bool reserved)
+{
+ struct Scsi_Host *host = cmd->device->host;
+ struct aac_dev *aac = (struct aac_dev *)host->hostdata;
+ struct fib *fib = &aac->fibs[cmd->request->tag];
+ int *cmd_bus = data;
+
+ if (fib->hw_fib_va->header.XferState &&
+ (fib->flags & FIB_CONTEXT_FLAG) &&
+ (fib->flags & FIB_CONTEXT_FLAG_SCSI_CMD)) {
+ struct aac_hba_map_info *info;
+ u32 bus, cid;
+
+ if (cmd != (struct scsi_cmnd *)fib->callback_data)
+ return true;
+ bus = aac_logical_to_phys(scmd_channel(cmd));
+ if (bus != *cmd_bus)
+ return true;
+ cid = scmd_id(cmd);
+ info = &aac->hba_map[bus][cid];
+ if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS ||
+ info->devtype != AAC_DEVTYPE_NATIVE_RAW) {
+ fib->flags |= FIB_CONTEXT_FLAG_EH_RESET;
+ cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ }
+ }
+ return true;
+}
+
/*
* aac_eh_bus_reset - Bus reset command handling
* @scsi_cmd: SCSI command block causing the reset
@@ -1024,32 +1088,10 @@ static int aac_eh_bus_reset(struct scsi_cmnd* cmd)
u32 cmd_bus;
int status = 0;

-
cmd_bus = aac_logical_to_phys(scmd_channel(cmd));
- /* Mark the assoc. FIB to not complete, eh handler does this */
- for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
- struct fib *fib = &aac->fibs[count];
-
- if (fib->hw_fib_va->header.XferState &&
- (fib->flags & FIB_CONTEXT_FLAG) &&
- (fib->flags & FIB_CONTEXT_FLAG_SCSI_CMD)) {
- struct aac_hba_map_info *info;
- u32 bus, cid;
-
- cmd = (struct scsi_cmnd *)fib->callback_data;
- bus = aac_logical_to_phys(scmd_channel(cmd));
- if (bus != cmd_bus)
- continue;
- cid = scmd_id(cmd);
- info = &aac->hba_map[bus][cid];
- if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS ||
- info->devtype != AAC_DEVTYPE_NATIVE_RAW) {
- fib->flags |= FIB_CONTEXT_FLAG_EH_RESET;
- cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
- }
- }
- }

+ /* Mark the assoc. FIB to not complete, eh handler does this */
+ scsi_host_tagset_busy_iter(host, aac_eh_bus_reset_iter, &cmd_bus);
pr_err("%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME);

/*
--
2.17.1