Commit 8fdd6417 authored by Xingui Yang's avatar Xingui Yang Committed by Yongqiang Liu
Browse files

scsi: hisi_sas: Fix SAS disk sense info print incorrectly sometimes

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4ZO9V


CVE: NA

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

Sometimes disk response sense info, but driver print data underflow without
sense, and it's not correct. we use scsi_normalize_sense instead of
hisi_sas_get_sense_data to parse the sense info.

before:
data underflow without sense, rsp_code:0xf0, rc:-2.

after:
data underflow, rsp_code:0x70, sensekey:0x5, ASC:0x21, ASCQ:0x0.

Signed-off-by: default avatarXingui Yang <yangxingui@huawei.com>
Reviewed-by: default avatarkang fenglong <kangfenglong@huawei.com>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent fec3e16d
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <scsi/scsi_common.h>
#include <scsi/sas_ata.h>
#include <scsi/libsas.h>

@@ -572,12 +573,6 @@ struct hisi_sas_slot_dif_buf_table {
	struct hisi_sas_sge_dif_page sge_dif_page;
};

struct hisi_sas_sense_data {
	int sense_key;
	int add_sense_code;
	int add_sense_code_qua;
};

extern bool hisi_sas_debugfs_enable;
extern struct dentry *hisi_sas_debugfs_dir;
extern int skip_bus_flag;
+22 −50
Original line number Diff line number Diff line
@@ -2291,56 +2291,24 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
	}
}

static int hisi_sas_get_sense_data(struct ssp_response_iu *iu,
	struct hisi_sas_sense_data *sense_data)
{
	int rc = 0;

	switch (iu->resp_data[0]) {
	case 0x70:
	case 0x71: {
		if (iu->sense_data_len > 13) {
			sense_data->sense_key = (iu->resp_data[2] & 0xF);
			sense_data->add_sense_code = iu->resp_data[12];
			sense_data->add_sense_code_qua = iu->resp_data[13];
		} else
			rc = -1;
		break;
	}
	case 0x72:
	case 0x73: {
		if (iu->sense_data_len > 4) {
			sense_data->sense_key = (iu->resp_data[1] & 0xF);
			sense_data->add_sense_code = iu->resp_data[2];
			sense_data->add_sense_code_qua = iu->resp_data[3];
		} else
			rc = -1;
		break;
	}
	default:
		rc = -2;
		break;
	}

	return rc;
}

static int ssp_need_spin_up(struct hisi_sas_slot *slot)
{
	int rc;
	struct hisi_sas_sense_data sense_data;
	bool rc;
	int sb_len;
	u8 *sense_buffer;
	struct scsi_sense_hdr sshdr;
	struct ssp_response_iu *iu =
		hisi_sas_status_buf_addr_mem(slot) +
		sizeof(struct hisi_sas_err_record);
	rc = hisi_sas_get_sense_data(iu, &sense_data);
	sb_len = iu->sense_data_len;
	sense_buffer = iu->sense_data;
	rc = scsi_normalize_sense(sense_buffer, sb_len, &sshdr);

	/*
	 * if the SAS disk response with ASC=04h,
	 * ASCQ=11h, host should send NOTIFY primitive.
	 */
	if (rc == 0 &&
		sense_data.add_sense_code == 0x4 &&
		sense_data.add_sense_code_qua == 0x11)
	if (rc && sshdr.asc == 0x4 && sshdr.ascq == 0x11)
		return 1;

	return 0;
@@ -2444,22 +2412,26 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
		if ((error_info[3] & RX_DATA_LEN_UNDERFLOW_MSK) &&
			(task->task_proto == SAS_PROTOCOL_SSP)) {
			/*print detail sense info when data underflow happened*/
			int rc;
			struct hisi_sas_sense_data sense_data;
			bool rc;
			int sb_len;
			u8 *sense_buffer;
			struct scsi_sense_hdr sshdr;
			struct ssp_response_iu *iu =
				hisi_sas_status_buf_addr_mem(slot) +
				sizeof(struct hisi_sas_err_record);
			rc = hisi_sas_get_sense_data(iu, &sense_data);

			if (!rc)
			sb_len = iu->sense_data_len;
			sense_buffer = iu->sense_data;
			rc = scsi_normalize_sense(sense_buffer, sb_len, &sshdr);
			if (rc)
				dev_info(dev, "data underflow, rsp_code:0x%x, sensekey:0x%x, ASC:0x%x, ASCQ:0x%x.\n",
					iu->resp_data[0],
					sense_data.sense_key,
					sense_data.add_sense_code,
					sense_data.add_sense_code_qua);
					sshdr.response_code,
					sshdr.sense_key,
					sshdr.asc,
					sshdr.ascq);
			else
				dev_info(dev, "data underflow without sense, rsp_code:0x%x, rc:%d.\n",
					iu->resp_data[0], rc);
				dev_info(dev, "data underflow without sense, rsp_code:0x%02x.\n",
					iu->resp_data[0]);
		}
		if (unlikely(slot->abort)) {
			sas_task_abort(task);