Commit 4f5deeb4 authored by Ruksar Devadi's avatar Ruksar Devadi Committed by Martin K. Petersen

scsi: pm80xx: Completing pending I/O after fatal error

When controller runs into fatal error, I/Os get stuck with no response,
handler event is defined to complete the pending I/Os (SAS task and
internal task) and also perform the cleanup for the drives.

Link: https://lore.kernel.org/r/20210415103352.3580-7-Viswas.G@microchip.comAcked-by: default avatarJack Wang <jinpu.wang@cloud.ionos.com>
Signed-off-by: default avatarRuksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: default avatarViswas G <Viswas.G@microchip.com>
Signed-off-by: default avatarAshokkumar N <Ashokkumar.N@microchip.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b0c306e6
......@@ -1499,12 +1499,14 @@ void pm8001_work_fn(struct work_struct *work)
* was cancelled. This nullification happens when the device
* goes away.
*/
pm8001_dev = pw->data; /* Most stash device structure */
if ((pm8001_dev == NULL)
|| ((pw->handler != IO_XFER_ERROR_BREAK)
&& (pm8001_dev->dev_type == SAS_PHY_UNUSED))) {
kfree(pw);
return;
if (pw->handler != IO_FATAL_ERROR) {
pm8001_dev = pw->data; /* Most stash device structure */
if ((pm8001_dev == NULL)
|| ((pw->handler != IO_XFER_ERROR_BREAK)
&& (pm8001_dev->dev_type == SAS_PHY_UNUSED))) {
kfree(pw);
return;
}
}
switch (pw->handler) {
......@@ -1668,6 +1670,58 @@ void pm8001_work_fn(struct work_struct *work)
dev = pm8001_dev->sas_device;
pm8001_I_T_nexus_reset(dev);
break;
case IO_FATAL_ERROR:
{
struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha;
struct pm8001_ccb_info *ccb;
struct task_status_struct *ts;
struct sas_task *task;
int i;
u32 tag, device_id;
for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
ccb = &pm8001_ha->ccb_info[i];
task = ccb->task;
ts = &task->task_status;
tag = ccb->ccb_tag;
/* check if tag is NULL */
if (!tag) {
pm8001_dbg(pm8001_ha, FAIL,
"tag Null\n");
continue;
}
if (task != NULL) {
dev = task->dev;
if (!dev) {
pm8001_dbg(pm8001_ha, FAIL,
"dev is NULL\n");
continue;
}
/*complete sas task and update to top layer */
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
ts->resp = SAS_TASK_COMPLETE;
task->task_done(task);
} else if (tag != 0xFFFFFFFF) {
/* complete the internal commands/non-sas task */
pm8001_dev = ccb->device;
if (pm8001_dev->dcompletion) {
complete(pm8001_dev->dcompletion);
pm8001_dev->dcompletion = NULL;
}
complete(pm8001_ha->nvmd_completion);
pm8001_tag_free(pm8001_ha, tag);
}
}
/* Deregister all the device ids */
for (i = 0; i < PM8001_MAX_DEVICES; i++) {
pm8001_dev = &pm8001_ha->devices[i];
device_id = pm8001_dev->device_id;
if (device_id) {
PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id);
pm8001_free_dev(pm8001_dev);
}
}
} break;
}
kfree(pw);
}
......
......@@ -805,6 +805,7 @@ struct set_dev_state_resp {
#define IO_ABORT_IN_PROGRESS 0x40
#define IO_ABORT_DELAYED 0x41
#define IO_INVALID_LENGTH 0x42
#define IO_FATAL_ERROR 0x51
/* WARNING: This error code must always be the last number.
* If you add error code, modify this code also
......
......@@ -590,7 +590,7 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
return NULL;
}
static void pm8001_free_dev(struct pm8001_device *pm8001_dev)
void pm8001_free_dev(struct pm8001_device *pm8001_dev)
{
u32 id = pm8001_dev->id;
memset(pm8001_dev, 0, sizeof(*pm8001_dev));
......
......@@ -726,6 +726,7 @@ ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
int pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha);
void pm8001_free_dev(struct pm8001_device *pm8001_dev);
/* ctl shared API */
extern struct device_attribute *pm8001_host_attrs[];
......
......@@ -4126,6 +4126,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
pm8001_dbg(pm8001_ha, FAIL,
"Firmware Fatal error! Regval:0x%x\n",
regval);
pm8001_handle_event(pm8001_ha, NULL, IO_FATAL_ERROR);
print_scratchpad_registers(pm8001_ha);
return ret;
}
......
......@@ -1272,6 +1272,7 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t;
#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE 0x47
#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED 0x48
#define IO_DS_INVALID 0x49
#define IO_FATAL_ERROR 0x51
/* WARNING: the value is not contiguous from here */
#define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52
#define IO_XFER_DMA_ACTIVATE_TIMEOUT 0x53
......
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