提交 64d37f3f 编写于 作者: X Xingui Yang 提交者: Yongqiang Liu

scsi: hisi_sas: Release resource directly in hisi_sas_abort_task() when NCQ error

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5SXSB
CVE: NA

------------------------------------------------

When the port is detached, EH will clear ATA_EH_RESET in ehc->i.action when
call ata_eh_reset(), and device reset won't be executed.

As the disk won't return other I/Os normally after NCQ Error. In addition,
the abort operation is added, then resource release is safe, so release NCQ
command lldd resource directly in hisi_sas_abort_task() when NCQ error
without soft reset to make sure read log command can be executed success
later. But Soft reset still need to be used in other scenario.
Signed-off-by: NXingui Yang <yangxingui@huawei.com>
Reviewed-by: Nkang fenglong <kangfenglong@huawei.com>
Signed-off-by: NYongqiang Liu <liuyongqiang13@huawei.com>
上级 f32bc74e
......@@ -101,6 +101,7 @@ enum {
enum dev_status {
HISI_SAS_DEV_INIT,
HISI_SAS_DEV_NORMAL,
HISI_SAS_DEV_NCQ_ERR,
};
enum {
......
......@@ -1673,7 +1673,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
if (slot && task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
u32 tag = slot->idx;
int rc2;
......@@ -1706,8 +1706,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
if (task->dev->dev_type == SAS_SATA_DEV) {
struct ata_port *ap = device->sata_dev.ap;
struct ata_link *link = &ap->link;
struct ata_queued_cmd *qc = task->uldd_task;
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0);
......@@ -1717,14 +1716,19 @@ static int hisi_sas_abort_task(struct sas_task *task)
}
hisi_sas_dereg_device(hisi_hba, device);
if (link->eh_info.action & ATA_EH_RESET) {
slot->task = NULL;
/*
* If an ATA internal command times out in ATA EH, it
* need to execute soft reset, so check the scsicmd
*/
if ((sas_dev->dev_status == HISI_SAS_DEV_NCQ_ERR) &&
qc && qc->scsicmd) {
hisi_sas_do_release_task(hisi_hba, task, slot);
rc = TMF_RESP_FUNC_COMPLETE;
} else {
rc = hisi_sas_softreset_ata_disk(device);
}
}
} else if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SMP) {
} else if (slot && task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
u32 tag = slot->idx;
struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
......@@ -1843,8 +1847,12 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
{
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
int rc;
if (sas_dev->dev_status == HISI_SAS_DEV_NCQ_ERR)
sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0);
if (rc < 0) {
......
......@@ -398,6 +398,8 @@
#define CMPLT_HDR_CMPLT_MSK (0x3 << CMPLT_HDR_CMPLT_OFF)
#define CMPLT_HDR_ERROR_PHASE_OFF 2
#define CMPLT_HDR_ERROR_PHASE_MSK (0xff << CMPLT_HDR_ERROR_PHASE_OFF)
/* bit[9:2] Error Phase */
#define ERR_PHASE_RESPONSE_FRAME_REV_STAGE BIT(8)
#define CMPLT_HDR_RSPNS_XFRD_OFF 10
#define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
#define CMPLT_HDR_RSPNS_GOOD_OFF 11
......@@ -423,6 +425,10 @@
#define CMPLT_HDR_SATA_DISK_ERR_MSK (0x1 << COMLT_HDR_SATA_DISK_ERR_OFF)
#define CMPLT_HDR_IO_IN_TARGET_OFF 17
#define CMPLT_HDR_IO_IN_TARGET_MSK (0x1 << CMPLT_HDR_IO_IN_TARGET_OFF)
/* bit[23:18] ERR_FIS_ATA_STATUS */
#define FIS_ATA_STATUS_ERR BIT(18)
/* bit[31:24] ERR_FIS_TYPE */
#define FIS_TYPE_SDB BIT(31)
/* ITCT header */
/* qw0 */
......@@ -2247,6 +2253,18 @@ static void hisi_sas_set_sense_data(struct sas_task *task,
}
}
static bool is_ncq_err(struct hisi_sas_complete_v3_hdr *complete_hdr)
{
u32 dw0, dw3;
dw0 = le32_to_cpu(complete_hdr->dw0);
dw3 = le32_to_cpu(complete_hdr->dw3);
return (dw0 & ERR_PHASE_RESPONSE_FRAME_REV_STAGE) &&
(dw3 & FIS_TYPE_SDB) &&
(dw3 & FIS_ATA_STATUS_ERR);
}
static void
slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot)
......@@ -2582,6 +2600,10 @@ static void cq_tasklet_v3_hw(unsigned long val)
dev_err(dev, "erroneous completion disk err dev id=%d sas_addr=0x%llx CQ hdr: 0x%x 0x%x 0x%x 0x%x\n",
device_id, itct->sas_addr, dw0, dw1,
complete_hdr->act, dw3);
if (is_ncq_err(complete_hdr))
sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR;
link->eh_info.err_mask |= AC_ERR_DEV;
link->eh_info.action |= ATA_EH_RESET;
ata_link_abort(link);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册