From: yangxingui <yangxingui(a)huawei.com>
driver inclusion
category: bugfix
bugzilla: NA
CVE: NA
---------------------------
In the data underflow scenario, if correct sense data and response frame
have been written to the host memory and the CQ RSPNS_GOOD bit is 0,
then driver sends the sense data to the upper layer.
Signed-off-by: yangxingui <yangxingui(a)huawei.com>
Reviewed-by: Xiang Chen <chenxiang66(a)hisilicon.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/scsi/hisi_sas/hisi_sas.h | 8 +++++--
drivers/scsi/hisi_sas/hisi_sas_main.c | 17 -------------
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 33 ++++++++++++++++++++++----
3 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 193fc960d87fd..742ffcaeaa95c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -102,6 +102,12 @@ enum hisi_sas_dev_type {
HISI_SAS_DEV_TYPE_SATA,
};
+enum datapres_field {
+ NO_DATA = 0,
+ RESPONSE_DATA = 1,
+ SENSE_DATA = 2,
+};
+
struct hisi_sas_hw_error {
u32 irq_msk;
u32 msk;
@@ -571,8 +577,6 @@ extern void hisi_sas_free(struct hisi_hba *hisi_hba);
extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
int direction);
extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
-extern void hisi_sas_set_sense_data(struct sas_task *task,
- struct hisi_sas_slot *slot);
extern void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot);
extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index ea08d53c11495..67befcc033126 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -105,23 +105,6 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
}
EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);
-void hisi_sas_set_sense_data(struct sas_task *task,
- struct hisi_sas_slot *slot)
-{
- struct ssp_response_iu *iu =
- hisi_sas_status_buf_addr_mem(slot) +
- sizeof(struct hisi_sas_err_record);
- if (iu->datapres == 2) {
- struct task_status_struct *ts = &task->task_status;
-
- ts->buf_valid_size =
- min_t(int, SAS_STATUS_BUF_SIZE,
- be32_to_cpu(iu->sense_data_len));
- memcpy(ts->buf, iu->sense_data, ts->buf_valid_size);
- }
-}
-EXPORT_SYMBOL_GPL(hisi_sas_set_sense_data);
-
void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot)
{
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 06b4f2db62f7b..9ce1177a8e455 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -395,6 +395,8 @@
#define CMPLT_HDR_ERROR_PHASE_MSK (0xff << CMPLT_HDR_ERROR_PHASE_OFF)
#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
+#define CMPLT_HDR_RSPNS_GOOD_MSK (0x1 << CMPLT_HDR_RSPNS_GOOD_OFF)
#define CMPLT_HDR_ERX_OFF 12
#define CMPLT_HDR_ERX_MSK (0x1 << CMPLT_HDR_ERX_OFF)
#define CMPLT_HDR_ABORT_STAT_OFF 13
@@ -2208,6 +2210,24 @@ static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
return IRQ_HANDLED;
}
+static void hisi_sas_set_sense_data(struct sas_task *task,
+ struct hisi_sas_slot *slot)
+{
+ struct ssp_response_iu *iu =
+ hisi_sas_status_buf_addr_mem(slot) +
+ sizeof(struct hisi_sas_err_record);
+ if ((iu->status == SAM_STAT_CHECK_CONDITION) &&
+ (iu->datapres == SENSE_DATA)) {
+ struct task_status_struct *ts = &task->task_status;
+
+ ts->buf_valid_size =
+ min_t(int, SAS_STATUS_BUF_SIZE,
+ be32_to_cpu(iu->sense_data_len));
+ memcpy(ts->buf, iu->sense_data, ts->buf_valid_size);
+ ts->stat = SAM_STAT_CHECK_CONDITION;
+ }
+}
+
static void
slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot)
@@ -2224,17 +2244,20 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
switch (task->task_proto) {
case SAS_PROTOCOL_SSP:
- if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) {
- ts->stat = SAS_QUEUE_FULL;
- slot->abort = 1;
- } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
+ if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
ts->residual = trans_tx_fail_type;
ts->stat = SAS_DATA_UNDERRUN;
+ if ((!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK)) &&
+ (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)) {
+ hisi_sas_set_sense_data(task, slot);
+ }
+ } else if (complete_hdr->dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) {
+ ts->stat = SAS_QUEUE_FULL;
+ slot->abort = 1;
} else {
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
}
- hisi_sas_set_sense_data(task, slot);
break;
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
--
2.25.1