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) ...@@ -1499,12 +1499,14 @@ void pm8001_work_fn(struct work_struct *work)
* was cancelled. This nullification happens when the device * was cancelled. This nullification happens when the device
* goes away. * goes away.
*/ */
pm8001_dev = pw->data; /* Most stash device structure */ if (pw->handler != IO_FATAL_ERROR) {
if ((pm8001_dev == NULL) pm8001_dev = pw->data; /* Most stash device structure */
|| ((pw->handler != IO_XFER_ERROR_BREAK) if ((pm8001_dev == NULL)
&& (pm8001_dev->dev_type == SAS_PHY_UNUSED))) { || ((pw->handler != IO_XFER_ERROR_BREAK)
kfree(pw); && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) {
return; kfree(pw);
return;
}
} }
switch (pw->handler) { switch (pw->handler) {
...@@ -1668,6 +1670,58 @@ void pm8001_work_fn(struct work_struct *work) ...@@ -1668,6 +1670,58 @@ void pm8001_work_fn(struct work_struct *work)
dev = pm8001_dev->sas_device; dev = pm8001_dev->sas_device;
pm8001_I_T_nexus_reset(dev); pm8001_I_T_nexus_reset(dev);
break; 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); kfree(pw);
} }
......
...@@ -805,6 +805,7 @@ struct set_dev_state_resp { ...@@ -805,6 +805,7 @@ struct set_dev_state_resp {
#define IO_ABORT_IN_PROGRESS 0x40 #define IO_ABORT_IN_PROGRESS 0x40
#define IO_ABORT_DELAYED 0x41 #define IO_ABORT_DELAYED 0x41
#define IO_INVALID_LENGTH 0x42 #define IO_INVALID_LENGTH 0x42
#define IO_FATAL_ERROR 0x51
/* WARNING: This error code must always be the last number. /* WARNING: This error code must always be the last number.
* If you add error code, modify this code also * 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, ...@@ -590,7 +590,7 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
return NULL; 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; u32 id = pm8001_dev->id;
memset(pm8001_dev, 0, sizeof(*pm8001_dev)); memset(pm8001_dev, 0, sizeof(*pm8001_dev));
......
...@@ -726,6 +726,7 @@ ssize_t pm80xx_get_non_fatal_dump(struct device *cdev, ...@@ -726,6 +726,7 @@ ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf); ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
int pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha); int pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha);
void pm8001_free_dev(struct pm8001_device *pm8001_dev);
/* ctl shared API */ /* ctl shared API */
extern struct device_attribute *pm8001_host_attrs[]; extern struct device_attribute *pm8001_host_attrs[];
......
...@@ -4126,6 +4126,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) ...@@ -4126,6 +4126,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
pm8001_dbg(pm8001_ha, FAIL, pm8001_dbg(pm8001_ha, FAIL,
"Firmware Fatal error! Regval:0x%x\n", "Firmware Fatal error! Regval:0x%x\n",
regval); regval);
pm8001_handle_event(pm8001_ha, NULL, IO_FATAL_ERROR);
print_scratchpad_registers(pm8001_ha); print_scratchpad_registers(pm8001_ha);
return ret; return ret;
} }
......
...@@ -1272,6 +1272,7 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; ...@@ -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_OPEN_COLLIDE 0x47
#define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED 0x48 #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED 0x48
#define IO_DS_INVALID 0x49 #define IO_DS_INVALID 0x49
#define IO_FATAL_ERROR 0x51
/* WARNING: the value is not contiguous from here */ /* WARNING: the value is not contiguous from here */
#define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52 #define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52
#define IO_XFER_DMA_ACTIVATE_TIMEOUT 0x53 #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