提交 6df69b59 编写于 作者: X Xingui Yang 提交者: Yongqiang Liu

scsi: hisi_sas: Fix normally completed I/O analysed as failed

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

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

pio read command has no response frame and the struct iu[1024] won't be
filled, and it's found that I/Os that are normally completed will be
analysed as failed in sas_ata_task_done() when iu contain abnormal dirty
data. So ending_fis should not be filled by iu when the response frame
hasn't been written to the memory.

Fixes: d380f555 ("scsi: hisi_sas: Don't bother clearing status buffer IU in task prep")
Signed-off-by: NXingui Yang <yangxingui@huawei.com>
Reviewed-by: NXiang Chen <chenxiang66@hisilicon.com>
Reviewed-by: Nkang fenglong <kangfenglong@huawei.com>
Signed-off-by: NYongqiang Liu <liuyongqiang13@huawei.com>
上级 803f7f8d
......@@ -2033,6 +2033,11 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
u16 dma_tx_err_type = cpu_to_le16(err_record->dma_tx_err_type);
u16 sipc_rx_err_type = cpu_to_le16(err_record->sipc_rx_err_type);
u32 dma_rx_err_type = cpu_to_le32(err_record->dma_rx_err_type);
struct hisi_sas_complete_v2_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v2_hdr *complete_hdr =
&complete_queue[slot->cmplt_queue_slot];
u32 dw0 = le32_to_cpu(complete_hdr->dw0);
int error = -1;
if (err_phase == 1) {
......@@ -2318,7 +2323,8 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
break;
}
}
hisi_sas_sata_done(task, slot);
if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
hisi_sas_sata_done(task, slot);
}
break;
default:
......@@ -2342,6 +2348,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
&complete_queue[slot->cmplt_queue_slot];
unsigned long flags;
bool is_internal = slot->is_internal;
u32 dw0;
if (unlikely(!task || !task->lldd_task || !task->dev))
return -EINVAL;
......@@ -2366,7 +2373,8 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
}
/* Use SAS+TMF status codes */
switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK)
dw0 = le32_to_cpu(complete_hdr->dw0);
switch ((dw0 & CMPLT_HDR_ABORT_STAT_MSK)
>> CMPLT_HDR_ABORT_STAT_OFF) {
case STAT_IO_ABORTED:
/* this io has been aborted by abort command */
......@@ -2392,9 +2400,9 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
break;
}
if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) &&
(!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
u32 err_phase = (complete_hdr->dw0 & CMPLT_HDR_ERR_PHASE_MSK)
if ((dw0 & CMPLT_HDR_ERX_MSK) &&
(!(dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
u32 err_phase = (dw0 & CMPLT_HDR_ERR_PHASE_MSK)
>> CMPLT_HDR_ERR_PHASE_OFF;
u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
......@@ -2409,7 +2417,7 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
"CQ hdr: 0x%x 0x%x 0x%x 0x%x "
"Error info: 0x%x 0x%x 0x%x 0x%x\n",
slot->idx, task, sas_dev->device_id,
complete_hdr->dw0, complete_hdr->dw1,
dw0, complete_hdr->dw1,
complete_hdr->act, complete_hdr->dw3,
error_info[0], error_info[1],
error_info[2], error_info[3]);
......@@ -2456,7 +2464,8 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
{
ts->stat = SAM_STAT_GOOD;
hisi_sas_sata_done(task, slot);
if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
hisi_sas_sata_done(task, slot);
break;
}
default:
......
......@@ -2353,7 +2353,8 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
}
hisi_sas_sata_done(task, slot);
if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
hisi_sas_sata_done(task, slot);
break;
case SAS_PROTOCOL_SMP:
ts->stat = SAM_STAT_CHECK_CONDITION;
......@@ -2402,6 +2403,7 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
&complete_queue[slot->cmplt_queue_slot];
unsigned long flags;
bool is_internal = slot->is_internal;
u32 dw0, dw1, dw3;
if (unlikely(!task || !task->lldd_task || !task->dev))
return -EINVAL;
......@@ -2425,10 +2427,14 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
goto out;
}
dw0 = le32_to_cpu(complete_hdr->dw0);
dw1 = le32_to_cpu(complete_hdr->dw1);
dw3 = le32_to_cpu(complete_hdr->dw3);
/*
* Use SAS+TMF status codes
*/
switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK)
switch ((dw0 & CMPLT_HDR_ABORT_STAT_MSK)
>> CMPLT_HDR_ABORT_STAT_OFF) {
case STAT_IO_ABORTED:
/* this IO has been aborted by abort command */
......@@ -2452,9 +2458,9 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
}
/* check for erroneous completion, 0x3 means abnormal */
if ((complete_hdr->dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) {
if ((dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) {
u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
u32 device_id = (complete_hdr->dw1 & 0xffff0000) >> 16;
u32 device_id = (dw1 & 0xffff0000) >> 16;
struct hisi_sas_itct *itct = &hisi_hba->itct[device_id];
set_aborted_iptt(hisi_hba, slot);
......@@ -2464,12 +2470,12 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
"Error info: 0x%x 0x%x 0x%x 0x%x\n",
slot->idx, task, sas_dev->device_id,
itct->sas_addr,
complete_hdr->dw0, complete_hdr->dw1,
complete_hdr->act, complete_hdr->dw3,
dw0, dw1,
complete_hdr->act, dw3,
error_info[0], error_info[1],
error_info[2], error_info[3]);
if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
(task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP)) {
struct hisi_sas_status_buffer *status_buf =
......@@ -2559,7 +2565,8 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
ts->stat = SAM_STAT_GOOD;
hisi_sas_sata_done(task, slot);
if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
hisi_sas_sata_done(task, slot);
break;
default:
ts->stat = SAM_STAT_CHECK_CONDITION;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册