mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 09:14:19 +08:00
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.com Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com> Signed-off-by: Viswas G <Viswas.G@microchip.com> Signed-off-by: Ashokkumar N <Ashokkumar.N@microchip.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b0c306e621
commit
4f5deeb40f
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user