platform: msm_shared: Fix the retrival of sense buffer
When a SCSI command fails, the reponse contains the
sense request. We need to parse the response to get
the sense buffer instead of sending a additional
sense request command which would then return data
that is not useful.
Change-Id: I95b7174978068209d1b5ed4b3fb7d3669a04c3af
diff --git a/platform/msm_shared/dme.c b/platform/msm_shared/dme.c
index 61efb47..431672b 100644
--- a/platform/msm_shared/dme.c
+++ b/platform/msm_shared/dme.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -137,7 +137,7 @@
req_upiu.idn = query->idn;
req_upiu.trans_type = UPIU_TYPE_QUERY_REQ;
req_upiu.dd = UTRD_NO_DATA_TRANSFER;
- req_upiu.resp_ptr = (struct upiu_basic_hdr *) &resp_upiu;
+ req_upiu.resp_ptr = (struct upiu_basic_resp_hdr *) &resp_upiu;
req_upiu.resp_len = sizeof(resp_upiu);
req_upiu.resp_data_ptr = query->buf;
req_upiu.timeout_msecs = UTP_GENERIC_CMD_TIMEOUT;
@@ -430,7 +430,7 @@
int dme_send_nop_query(struct ufs_dev *dev)
{
struct upiu_req_build_type req_upiu;
- struct upiu_basic_hdr resp_upiu;
+ struct upiu_basic_resp_hdr resp_upiu;
int ret;
unsigned try_again;
diff --git a/platform/msm_shared/include/ucs.h b/platform/msm_shared/include/ucs.h
index 094946e..48c50db 100644
--- a/platform/msm_shared/include/ucs.h
+++ b/platform/msm_shared/include/ucs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -175,4 +175,6 @@
int ucs_do_scsi_rpmb_read(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt,
uint32_t *resp_buffer, uint32_t *response_length);
+/* This function parses the first byte of the sense data and returns the sense key */
+int parse_sense_key(uint32_t sense_data);
#endif
diff --git a/platform/msm_shared/include/upiu.h b/platform/msm_shared/include/upiu.h
index 1c9968d..e081909 100644
--- a/platform/msm_shared/include/upiu.h
+++ b/platform/msm_shared/include/upiu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -44,6 +44,27 @@
uint16_t data_seg_len;
} __PACKED;
+
+struct upiu_basic_resp_hdr
+{
+ uint8_t trans_type;
+ uint8_t flags;
+ uint8_t lun;
+ uint8_t task_tag;
+ uint8_t cmd_set_type;
+ uint8_t query_task_mgmt_func;
+ uint8_t response;
+ uint8_t status;
+ uint8_t total_ehs_len;
+ uint8_t device_info;
+ uint16_t data_seg_len;
+ uint32_t residual_transfer_count;
+ uint32_t reserved[4];
+ uint16_t sense_length;
+ uint16_t sense_response_code;
+ uint32_t sense_data[4];
+} __PACKED;
+
struct upiu_trans_mgmt_query_hdr
{
struct upiu_basic_hdr basic_hdr;
@@ -149,7 +170,7 @@
uint8_t idn;
uint8_t index;
uint8_t selector;
- struct upiu_basic_hdr *resp_ptr;
+ struct upiu_basic_resp_hdr *resp_ptr;
uint64_t resp_len;
uint16_t resp_data_len;
addr_t resp_data_ptr;
diff --git a/platform/msm_shared/ucs.c b/platform/msm_shared/ucs.c
index e77f2d1..f820734 100644
--- a/platform/msm_shared/ucs.c
+++ b/platform/msm_shared/ucs.c
@@ -37,8 +37,7 @@
int ucs_do_scsi_cmd(struct ufs_dev *dev, struct scsi_req_build_type *req)
{
struct upiu_req_build_type req_upiu;
- struct upiu_basic_hdr resp_upiu;
- int ret;
+ struct upiu_basic_resp_hdr resp_upiu;
memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
@@ -68,9 +67,14 @@
{
if (resp_upiu.status == SCSI_STATUS_CHK_COND && (*((uint8_t *)(req->cdb)) != SCSI_CMD_SENSE_REQ))
{
- ret = ucs_do_request_sense(dev);
- if (ret)
- dprintf(CRITICAL, "SCSI request sense failed.\n");
+ dprintf(CRITICAL, "Data segment length: %x\n", BE16(resp_upiu.data_seg_len));
+ if (BE16(resp_upiu.data_seg_len))
+ {
+ dprintf(CRITICAL, "SCSI Request failed and we have sense data\n");
+ dprintf(CRITICAL, "Sense Data Length/Response Code: 0x%x/0x%x\n", BE16(resp_upiu.sense_length), BE16(resp_upiu.sense_response_code));
+ parse_sense_key(resp_upiu.sense_data[0]);
+ dprintf(CRITICAL, "Sense Buffer (HEX): 0x%x 0x%x 0x%x 0x%x\n", BE32(resp_upiu.sense_data[0]), BE32(resp_upiu.sense_data[1]), BE32(resp_upiu.sense_data[2]), BE32(resp_upiu.sense_data[3]));
+ }
}
dprintf(CRITICAL, "ucs_do_scsi_cmd failed status = %x\n", resp_upiu.status);
@@ -80,6 +84,57 @@
return UFS_SUCCESS;
}
+int parse_sense_key(uint32_t sense_data)
+{
+ uint32_t key = BE32(sense_data) >> 24;
+ dprintf(CRITICAL, "Sense Key: 0x%x\n", key);
+ switch(key)
+ {
+ case 0x0:
+ dprintf(INFO, "NO SENSE: No information available to be reported\n");
+ break;
+ case 0x1:
+ dprintf(INFO, "RECOVERED ERROR: Additional sense buffer bytes indicate further details\n");
+ break;
+ case 0x2:
+ dprintf(INFO, "NOT READY: Logical Unit Not Ready and cannot be accessed at this time\n");
+ break;
+ case 0x3:
+ dprintf(INFO, "MEDIUM ERROR: Last command unsuccessful due to non-recoverable error condition\n");
+ break;
+ case 0x4:
+ dprintf(INFO, "HARDWARE ERROR: Target detected a non-recoverable hardware error\n");
+ break;
+ case 0x5:
+ dprintf(INFO, "ILLEGAL REQUEST: Illegal parameter in the command descriptor block in the command sent\n");
+ break;
+ case 0x6:
+ dprintf(INFO, "UNIT ATTENTION: Unit has been reset/unexpectedly power on/removable media has changed\n");
+ break;
+ case 0x7:
+ dprintf(INFO, "DATA PROTECT: Read/Write operation attempted on a block that is protected from this operation\n");
+ break;
+ case 0x8:
+ dprintf(INFO, "BLANK CHECK: Target encountered blank or unformatted media while reading or writing\n");
+ break;
+ case 0x9:
+ dprintf(INFO, "VENDOR SPECIFIC: Vendor specific error or exceptional conditions\n");
+ break;
+ case 0xB:
+ dprintf(INFO, "ABORTED COMMAND: Target aborted the execution of the command\n");
+ break;
+ case 0xD:
+ dprintf(INFO, "VOLUME OVERFLOW: Buffered peripheral device has reached the end of partition\n");
+ break;
+ case 0xE:
+ dprintf(INFO, "MISCOMPARE: Source data did not match the data read from the media\n");
+ break;
+ default:
+ dprintf(INFO, "INVALID sense key\n");
+ }
+ return key;
+}
+
int ucs_do_scsi_rpmb_read(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt,
uint32_t *resp_buf, uint32_t *resp_len)
{