diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 39a11ef34ea742cf4026fdfbfe72d2a33a27f483..7c896ddd9c7336e056c5fe54fdb5b87f495d6222 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;