提交 9a26603c 编写于 作者: X Xingui Yang 提交者: Yongqiang Liu

scsi: hisi_sas: Add SATA_DISK_ERR bit handling for v3 hw

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

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

When CQ header dw3 SATA_DISK_ERR is set it means this SATA disk is in
error state and the current IPTT is invalid. An invalid IPTT does not
correspond to any slot. In this scenario, new I/Os that delivered to disk
will be rejected by the, controller and all I/Os remained on the disk
should be aborted, which we add here with the ata_link_abort() call.
Signed-off-by: NXingui Yang <yangxingui@huawei.com>
Reviewed-by: Nkang fenglong <kangfenglong@huawei.com>
Signed-off-by: NYongqiang Liu <liuyongqiang13@huawei.com>
上级 338ab8d0
......@@ -1642,6 +1642,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
struct hisi_sas_tmf_task tmf_task;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_sas_slot *slot = task->lldd_task;
struct hisi_hba *hisi_hba;
struct device *dev;
int rc = TMF_RESP_FUNC_FAILED;
......@@ -1655,7 +1656,6 @@ static int hisi_sas_abort_task(struct sas_task *task)
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
struct hisi_sas_slot *slot = task->lldd_task;
struct hisi_sas_cq *cq;
if (slot) {
......@@ -1675,7 +1675,6 @@ static int hisi_sas_abort_task(struct sas_task *task)
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_slot *slot = task->lldd_task;
u32 tag = slot->idx;
int rc2;
......@@ -1707,6 +1706,9 @@ 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;
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0);
if (rc < 0) {
......@@ -1714,11 +1716,16 @@ static int hisi_sas_abort_task(struct sas_task *task)
goto out;
}
hisi_sas_dereg_device(hisi_hba, device);
rc = hisi_sas_softreset_ata_disk(device);
if (link->eh_info.action & ATA_EH_RESET) {
slot->task = NULL;
rc = TMF_RESP_FUNC_COMPLETE;
} else {
rc = hisi_sas_softreset_ata_disk(device);
}
}
} else if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
struct hisi_sas_slot *slot = task->lldd_task;
u32 tag = slot->idx;
struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
......
......@@ -413,6 +413,8 @@
#define CMPLT_HDR_DEV_ID_OFF 16
#define CMPLT_HDR_DEV_ID_MSK (0xffff << CMPLT_HDR_DEV_ID_OFF)
/* dw3 */
#define COMLT_HDR_SATA_DISK_ERR_OFF 16
#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)
......@@ -2543,12 +2545,34 @@ static void cq_tasklet_v3_hw(unsigned long val)
while (rd_point != wr_point) {
struct hisi_sas_complete_v3_hdr *complete_hdr;
struct device *dev = hisi_hba->dev;
u32 dw0, dw1, dw3;
int iptt;
complete_hdr = &complete_queue[rd_point];
iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK;
if (likely(iptt < HISI_SAS_COMMAND_ENTRIES_V3_HW)) {
dw0 = le32_to_cpu(complete_hdr->dw0);
dw1 = le32_to_cpu(complete_hdr->dw1);
dw3 = le32_to_cpu(complete_hdr->dw3);
iptt = dw1 & CMPLT_HDR_IPTT_MSK;
if (unlikely((dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) &&
(dw3 & CMPLT_HDR_SATA_DISK_ERR_MSK)) {
int device_id = (dw1 & CMPLT_HDR_DEV_ID_MSK) >>
CMPLT_HDR_DEV_ID_OFF;
struct hisi_sas_itct *itct =
&hisi_hba->itct[device_id];
struct hisi_sas_device *sas_dev =
&hisi_hba->devices[device_id];
struct domain_device *device = sas_dev->sas_device;
struct ata_port *ap = device->sata_dev.ap;
struct ata_link *link = &ap->link;
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);
link->eh_info.err_mask |= AC_ERR_DEV;
link->eh_info.action |= ATA_EH_RESET;
ata_link_abort(link);
} else if (likely(iptt < HISI_SAS_COMMAND_ENTRIES_V3_HW)) {
slot = &hisi_hba->slot_info[iptt];
slot->cmplt_queue_slot = rd_point;
slot->cmplt_queue = queue;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册