> -----Original Message----- > From: Hannes Reinecke [mailto:hare@xxxxxxx] > Sent: Friday, June 30, 2017 10:18 AM > To: Martin K. Petersen <martin.petersen@xxxxxxxxxx> > Cc: Christoph Hellwig <hch@xxxxxx>; James Bottomley > <james.bottomley@xxxxxxxxxxxxxxxxxxxxx>; linux-scsi@xxxxxxxxxxxxxxx; > Raghava Aditya Renukunta <RaghavaAditya.Renukunta@xxxxxxxxxxxxx>; > Hannes Reinecke <hare@xxxxxxx>; Hannes Reinecke <hare@xxxxxxxx> > Subject: [PATCH 4/7] aacraid: use aac_tmf_callback for reset fib > > EXTERNAL EMAIL > > > When sending a reset fib we shouldn't rely on the scsi command, > but rather set the TMF status in the map_info->reset_state variable. > That allows us to send a TMF independent on a scsi command. > > Signed-off-by: Hannes Reinecke <hare@xxxxxxxx> > --- > drivers/scsi/aacraid/linit.c | 99 +++++++++++++++++++++++++++++++++--- > -------- > 1 file changed, 74 insertions(+), 25 deletions(-) > > diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c > index 57b2077..e5d2d91 100644 > --- a/drivers/scsi/aacraid/linit.c > +++ b/drivers/scsi/aacraid/linit.c > @@ -814,8 +814,8 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) > return ret; > } > > -static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, > - int bus, int cid, u64 tmf_lun) > +static u8 aac_eh_tmf_lun_reset_fib(struct aac_hba_map_info *info, > + struct fib *fib, u64 tmf_lun) > { > struct aac_hba_tm_req *tmf; > u64 address; > @@ -824,7 +824,7 @@ static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev > *aac, struct fib *fib, > tmf = (struct aac_hba_tm_req *)fib->hw_fib_va; > memset(tmf, 0, sizeof(*tmf)); > tmf->tmf = HBA_TMF_LUN_RESET; > - tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus; > + tmf->it_nexus = info->rmw_nexus; > int_to_scsilun(tmf_lun, (struct scsi_lun *)tmf->lun); > > address = (u64)fib->hw_error_pa; > @@ -838,8 +838,8 @@ static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev > *aac, struct fib *fib, > return HBA_IU_TYPE_SCSI_TM_REQ; > } > > -static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, > - int bus, int cid) > +static u8 aac_eh_tmf_hard_reset_fib(struct aac_hba_map_info *info, > + struct fib *fib) > { > struct aac_hba_reset_req *rst; > u64 address; > @@ -847,8 +847,7 @@ static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev > *aac, struct fib *fib, > /* already tried, start a hard reset now */ > rst = (struct aac_hba_reset_req *)fib->hw_fib_va; > memset(rst, 0, sizeof(*rst)); > - /* reset_type is already zero... */ > - rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus; > + rst->it_nexus = info->rmw_nexus; > > address = (u64)fib->hw_error_pa; > rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); > @@ -860,6 +859,33 @@ static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev > *aac, struct fib *fib, > return HBA_IU_TYPE_SATA_REQ; > } > > +void aac_tmf_callback(void *context, struct fib *fibptr) > +{ > + struct aac_hba_resp *err = > + &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err; > + struct aac_hba_map_info *info = context; > + int res; > + > + switch (err->service_response) { > + case HBA_RESP_SVCRES_TMF_REJECTED: > + res = -1; > + break; > + case HBA_RESP_SVCRES_TMF_LUN_INVALID: > + res = 0; > + break; > + case HBA_RESP_SVCRES_TMF_COMPLETE: > + case HBA_RESP_SVCRES_TMF_SUCCEEDED: > + res = 0; > + break; > + default: > + res = -2; > + break; > + } > + aac_fib_complete(fibptr); > + > + info->reset_state = res; > +} > + > /* > * aac_eh_dev_reset - Device reset command handling > * @scsi_cmd: SCSI command block causing the reset > @@ -870,6 +896,7 @@ static int aac_eh_dev_reset(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; > + struct aac_hba_map_info *info; > int count; > u32 bus, cid; > struct fib *fib; > @@ -879,8 +906,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) > > bus = aac_logical_to_phys(scmd_channel(cmd)); > cid = scmd_id(cmd); > + info = &aac->hba_map[bus][cid]; > if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || > - aac->hba_map[bus][cid].devtype != AAC_DEVTYPE_NATIVE_RAW) > + info->devtype != AAC_DEVTYPE_NATIVE_RAW) > + return FAILED; > + > + if (info->reset_state > 0) > return FAILED; > > pr_err("%s: Host adapter reset request. SCSI hang ?\n", > @@ -890,21 +921,19 @@ static int aac_eh_dev_reset(struct scsi_cmnd > *cmd) > if (!fib) > return ret; > > - > /* start a HBA_TMF_LUN_RESET TMF request */ > - command = aac_eh_tmf_lun_reset_fib(aac, fib, bus, cid, > - cmd->device->lun); > + command = aac_eh_tmf_lun_reset_fib(info, fib, dev->lun); > > - cmd->SCp.sent_command = 0; > + info->reset_state = 1; > > status = aac_hba_send(command, fib, > - (fib_callback) aac_hba_callback, > - (void *) cmd); > + (fib_callback) aac_tmf_callback, > + (void *) info); > > /* Wait up to 15 seconds for completion */ > for (count = 0; count < 15; ++count) { > - if (cmd->SCp.sent_command) { > - ret = SUCCESS; > + if (info->reset_state == 0) { > + ret = info->reset_state == 0 ? SUCCESS : FAILED; > break; > } > msleep(1000); > @@ -923,6 +952,7 @@ static int aac_eh_target_reset(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; > + struct aac_hba_map_info *info; > int count; > u32 bus, cid; > int ret = FAILED; > @@ -932,8 +962,12 @@ static int aac_eh_target_reset(struct scsi_cmnd > *cmd) > > bus = aac_logical_to_phys(scmd_channel(cmd)); > cid = scmd_id(cmd); > + info = &aac->hba_map[bus][cid]; > if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || > - aac->hba_map[bus][cid].devtype != AAC_DEVTYPE_NATIVE_RAW) > + info->devtype != AAC_DEVTYPE_NATIVE_RAW) > + return FAILED; > + > + if (info->reset_state > 0) > return FAILED; > > pr_err("%s: Host adapter reset request. SCSI hang ?\n", > @@ -945,18 +979,18 @@ static int aac_eh_target_reset(struct scsi_cmnd > *cmd) > > > /* already tried, start a hard reset now */ > - command = aac_eh_tmf_hard_reset_fib(aac, fib, bus, cid); > + command = aac_eh_tmf_hard_reset_fib(info, fib); > > - cmd->SCp.sent_command = 0; > + info->reset_state = 2; > > status = aac_hba_send(command, fib, > - (fib_callback) aac_hba_callback, > - (void *) cmd); > + (fib_callback) aac_tmf_callback, > + (void *) info); > > /* Wait up to 15 seconds for completion */ > for (count = 0; count < 15; ++count) { > - if (cmd->SCp.sent_command) { > - ret = SUCCESS; > + if (info->reset_state <= 0) { > + ret = info->reset_state == 0 ? SUCCESS : FAILED; > break; > } > msleep(1000); > @@ -1044,8 +1078,23 @@ int aac_eh_host_reset(struct scsi_cmnd *cmd) > && aac_check_reset > && (aac_check_reset != -1 || !is_ignore_reset)) { > /* Bypass wait for command quiesce */ > - aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET); > - ret = SUCCESS; > + if (aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET) == 0) > + ret = SUCCESS; > + } > + /* > + * Reset EH state > + */ > + if (ret == SUCCESS) { > + int bus, cid; > + struct aac_hba_map_info *info; > + > + for (bus = 0; bus < AAC_MAX_BUSES; bus++) { > + for (cid = 0; cid < AAC_MAX_TARGETS; cid++) { > + info = &aac->hba_map[bus][cid]; > + if (info->devtype == AAC_DEVTYPE_NATIVE_RAW) > + info->reset_state = 0; > + } > + } > } > return ret; > } > -- > 1.8.5.6 Reviewed-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@xxxxxxxxxxxxx>