From f7a803aec918b46c6fdc9e46ef21fc5af4b070c6 Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Wed, 5 Dec 2018 17:18:01 +0800 Subject: [PATCH] scsi: hisi_sas: fix bug of LM fail to add list which caused by IO release when receive underflow cq when we unplug the disk with IO running,sas controller will retry IO for 5s. As disk havn't receive any response from initiator for long time , it will return underflow to tell controller that initiator response timeout have happened. At current handle of receive underflow, we direct release IPTT of io without clean the residue of IPTT remained at hardware logic.If we reuse this IPTT and send a new IO to logic before logic clean the residue,it will cause LM fail to add list. So we should modify the handle of underflow to avoid directly release IPTT but to enter error handle base on flag: CMPLT_HDR_IO_IN_TARGET_MSK And we should enable the verify of Data transfer length for rw IO only, so we can prevent the generate of underflow cq when scan the disk. we should ensure not to enter the error handle when inquiry the disk. For the different command we use to inquiry the SAS(INQUIRY) and SATA (IDENTIFY DEVICE), underflow will not be report during SATA disk inquiry, so we only check for rw IO at func:prep_ssp_v3_hw. BTW, we also add some print to get the sensekey of underflow at func:slot_complete_v3_hw to help debug. Signed-off-by: Luo Jiaxing Feature or Bugfix:Bugfix Signed-off-by: luojiaxing Reviewed-by: chenxiang Signed-off-by: Yang Yingliang --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 41 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 39a11ef34ea7..7c896ddd9c73 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -407,6 +407,13 @@ struct hisi_sas_err_record_v3 { #define HISI_SAS_CQ_INT_BASE_VECTORS_V3_HW 16 +#define HISI_SAS_IS_RW_CMD(op) \ + ((op == READ_6) || (op == WRITE_6) || \ + (op == READ_10) || (op == WRITE_10) || \ + (op == READ_12) || (op == WRITE_12) || \ + (op == READ_16) || (op == WRITE_16) || \ + (op == READ_32) || (op == WRITE_32)) + static bool hisi_sas_intr_conv; MODULE_PARM_DESC(intr_conv, "interrupt converge on or off:0 or 1(def=0)"); @@ -1119,6 +1126,17 @@ static void hisi_sas_fill_prot_v3_hw(struct scsi_cmnd *scsi_cmnd, prot->dw0 |= INCR_LBRT_MSK; } +static u32 set_hdr_vdtl(u8 *cmnd) +{ + u32 res; + + if (!HISI_SAS_IS_RW_CMD(cmnd[0])) + res = 0 << CMD_HDR_VDTL_OFF; + else + res = 1 << CMD_HDR_VDTL_OFF; + return res; +} + static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) { @@ -1140,11 +1158,11 @@ static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba, (priority << CMD_HDR_PRIORITY_OFF) | (1 << CMD_HDR_CMD_OFF)); /* ssp */ - dw1 = 1 << CMD_HDR_VDTL_OFF; if (tmf) { dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF; dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF; } else { + dw1 = set_hdr_vdtl(&scsi_cmnd->cmnd[0]); dw1 |= 1 << CMD_HDR_FRAME_TYPE_OFF; switch (scsi_cmnd->sc_data_direction) { case DMA_TO_DEVICE: @@ -1873,17 +1891,10 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, hisi_hba->complete_hdr[slot->cmplt_queue]; struct hisi_sas_complete_v3_hdr *complete_hdr = &complete_queue[slot->cmplt_queue_slot]; - struct hisi_sas_err_record_v3 *record = - hisi_sas_status_buf_addr_mem(slot); - u32 dma_rx_err_type = record->dma_rx_err_type; - u32 trans_tx_fail_type = record->trans_tx_fail_type; switch (task->task_proto) { case SAS_PROTOCOL_SSP: - if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { - ts->residual = trans_tx_fail_type; - ts->stat = SAS_DATA_UNDERRUN; - } else if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { + if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { ts->stat = SAS_QUEUE_FULL; slot->abort = 1; } else { @@ -1894,10 +1905,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { - ts->residual = trans_tx_fail_type; - ts->stat = SAS_DATA_UNDERRUN; - } else if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { + if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) { ts->stat = SAS_PHY_DOWN; slot->abort = 1; } else { @@ -1993,6 +2001,13 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot) complete_hdr->act, complete_hdr->dw3, error_info[0], error_info[1], error_info[2], error_info[3]); + if (error_info[3] & RX_DATA_LEN_UNDERFLOW_MSK) { + u32 *tmp_err = hisi_sas_status_buf_addr_mem(slot) + + sizeof(struct hisi_sas_err_record); + dev_info(dev, "underflow, sensekey:0x%x, code:0x%x.\n", + ((*(tmp_err + 6)) & 0xff0000) >> 16, + ((*(tmp_err + 9)) & 0xff)); + } if (unlikely(slot->abort)) return ts->stat; goto out; -- GitLab