Commit 0d643ff3 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: aacraid: use aac_tmf_callback for reset fib

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: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarRaghava Aditya Renukunta  <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f799319e
...@@ -814,8 +814,8 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) ...@@ -814,8 +814,8 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
return ret; return ret;
} }
static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, static u8 aac_eh_tmf_lun_reset_fib(struct aac_hba_map_info *info,
int bus, int cid, u64 tmf_lun) struct fib *fib, u64 tmf_lun)
{ {
struct aac_hba_tm_req *tmf; struct aac_hba_tm_req *tmf;
u64 address; u64 address;
...@@ -824,7 +824,7 @@ static u8 aac_eh_tmf_lun_reset_fib(struct aac_dev *aac, struct fib *fib, ...@@ -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; tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
memset(tmf, 0, sizeof(*tmf)); memset(tmf, 0, sizeof(*tmf));
tmf->tmf = HBA_TMF_LUN_RESET; 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); int_to_scsilun(tmf_lun, (struct scsi_lun *)tmf->lun);
address = (u64)fib->hw_error_pa; 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, ...@@ -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; return HBA_IU_TYPE_SCSI_TM_REQ;
} }
static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, static u8 aac_eh_tmf_hard_reset_fib(struct aac_hba_map_info *info,
int bus, int cid) struct fib *fib)
{ {
struct aac_hba_reset_req *rst; struct aac_hba_reset_req *rst;
u64 address; u64 address;
...@@ -847,8 +847,7 @@ static u8 aac_eh_tmf_hard_reset_fib(struct aac_dev *aac, struct fib *fib, ...@@ -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 */ /* already tried, start a hard reset now */
rst = (struct aac_hba_reset_req *)fib->hw_fib_va; rst = (struct aac_hba_reset_req *)fib->hw_fib_va;
memset(rst, 0, sizeof(*rst)); memset(rst, 0, sizeof(*rst));
/* reset_type is already zero... */ rst->it_nexus = info->rmw_nexus;
rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
address = (u64)fib->hw_error_pa; address = (u64)fib->hw_error_pa;
rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32)); 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, ...@@ -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; 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 * aac_eh_dev_reset - Device reset command handling
* @scsi_cmd: SCSI command block causing the reset * @scsi_cmd: SCSI command block causing the reset
...@@ -870,6 +896,7 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) ...@@ -870,6 +896,7 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
struct scsi_device * dev = cmd->device; struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host; struct Scsi_Host * host = dev->host;
struct aac_dev * aac = (struct aac_dev *)host->hostdata; struct aac_dev * aac = (struct aac_dev *)host->hostdata;
struct aac_hba_map_info *info;
int count; int count;
u32 bus, cid; u32 bus, cid;
struct fib *fib; struct fib *fib;
...@@ -879,8 +906,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) ...@@ -879,8 +906,12 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
bus = aac_logical_to_phys(scmd_channel(cmd)); bus = aac_logical_to_phys(scmd_channel(cmd));
cid = scmd_id(cmd); cid = scmd_id(cmd);
info = &aac->hba_map[bus][cid];
if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || 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; return FAILED;
pr_err("%s: Host adapter reset request. SCSI hang ?\n", pr_err("%s: Host adapter reset request. SCSI hang ?\n",
...@@ -890,21 +921,19 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd) ...@@ -890,21 +921,19 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
if (!fib) if (!fib)
return ret; return ret;
/* start a HBA_TMF_LUN_RESET TMF request */ /* start a HBA_TMF_LUN_RESET TMF request */
command = aac_eh_tmf_lun_reset_fib(aac, fib, bus, cid, command = aac_eh_tmf_lun_reset_fib(info, fib, dev->lun);
cmd->device->lun);
cmd->SCp.sent_command = 0; info->reset_state = 1;
status = aac_hba_send(command, fib, status = aac_hba_send(command, fib,
(fib_callback) aac_hba_callback, (fib_callback) aac_tmf_callback,
(void *) cmd); (void *) info);
/* Wait up to 15 seconds for completion */ /* Wait up to 15 seconds for completion */
for (count = 0; count < 15; ++count) { for (count = 0; count < 15; ++count) {
if (cmd->SCp.sent_command) { if (info->reset_state == 0) {
ret = SUCCESS; ret = info->reset_state == 0 ? SUCCESS : FAILED;
break; break;
} }
msleep(1000); msleep(1000);
...@@ -923,6 +952,7 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) ...@@ -923,6 +952,7 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
struct scsi_device * dev = cmd->device; struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host; struct Scsi_Host * host = dev->host;
struct aac_dev * aac = (struct aac_dev *)host->hostdata; struct aac_dev * aac = (struct aac_dev *)host->hostdata;
struct aac_hba_map_info *info;
int count; int count;
u32 bus, cid; u32 bus, cid;
int ret = FAILED; int ret = FAILED;
...@@ -932,8 +962,12 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) ...@@ -932,8 +962,12 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
bus = aac_logical_to_phys(scmd_channel(cmd)); bus = aac_logical_to_phys(scmd_channel(cmd));
cid = scmd_id(cmd); cid = scmd_id(cmd);
info = &aac->hba_map[bus][cid];
if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS || 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; return FAILED;
pr_err("%s: Host adapter reset request. SCSI hang ?\n", pr_err("%s: Host adapter reset request. SCSI hang ?\n",
...@@ -945,18 +979,18 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd) ...@@ -945,18 +979,18 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
/* already tried, start a hard reset now */ /* 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, status = aac_hba_send(command, fib,
(fib_callback) aac_hba_callback, (fib_callback) aac_tmf_callback,
(void *) cmd); (void *) info);
/* Wait up to 15 seconds for completion */ /* Wait up to 15 seconds for completion */
for (count = 0; count < 15; ++count) { for (count = 0; count < 15; ++count) {
if (cmd->SCp.sent_command) { if (info->reset_state <= 0) {
ret = SUCCESS; ret = info->reset_state == 0 ? SUCCESS : FAILED;
break; break;
} }
msleep(1000); msleep(1000);
...@@ -1044,8 +1078,23 @@ int aac_eh_host_reset(struct scsi_cmnd *cmd) ...@@ -1044,8 +1078,23 @@ int aac_eh_host_reset(struct scsi_cmnd *cmd)
&& aac_check_reset && aac_check_reset
&& (aac_check_reset != -1 || !is_ignore_reset)) { && (aac_check_reset != -1 || !is_ignore_reset)) {
/* Bypass wait for command quiesce */ /* Bypass wait for command quiesce */
aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET); if (aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET) == 0)
ret = SUCCESS; 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; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment