aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeungwon Jeon <tgih.jun@samsung.com>2013-08-31 12:10:19 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-06 18:57:55 -0400
commit1c2623c50dfd38c823a62c57af2ca9551a861b21 (patch)
tree605ff68795ada0019cffae758f41c71dcd070557
parent2b4857c30ed04e4e5c1dd88516a4388d2919e3ff (diff)
[SCSI] ufs: find out sense data over scsi status values
Unlike 'GOOD' and 'CHECK CONDITION', other status values in Response UPIU may or may not contain sense data. That is returning sense data isn't obvious. So, in this case the Data Segment Length field should be checked. If a non-zero value, it means that UPIU has Sense Data in the Data Segment area. Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org> Tested-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/ufs/ufs.h1
-rw-r--r--drivers/scsi/ufs/ufshcd.c37
2 files changed, 23 insertions, 15 deletions
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index bce09a6898c4..721050090520 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -177,6 +177,7 @@ enum {
177 MASK_TASK_RESPONSE = 0xFF00, 177 MASK_TASK_RESPONSE = 0xFF00,
178 MASK_RSP_UPIU_RESULT = 0xFFFF, 178 MASK_RSP_UPIU_RESULT = 0xFFFF,
179 MASK_QUERY_DATA_SEG_LEN = 0xFFFF, 179 MASK_QUERY_DATA_SEG_LEN = 0xFFFF,
180 MASK_RSP_UPIU_DATA_SEG_LEN = 0xFFFF,
180 MASK_RSP_EXCEPTION_EVENT = 0x10000, 181 MASK_RSP_EXCEPTION_EVENT = 0x10000,
181}; 182};
182 183
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b36ca9a2dfbb..6c34f6ae8870 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -260,6 +260,20 @@ ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr)
260 return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT; 260 return be32_to_cpu(ucd_rsp_ptr->header.dword_1) & MASK_RSP_UPIU_RESULT;
261} 261}
262 262
263/*
264 * ufshcd_get_rsp_upiu_data_seg_len - Get the data segment length
265 * from response UPIU
266 * @ucd_rsp_ptr: pointer to response UPIU
267 *
268 * Return the data segment length.
269 */
270static inline unsigned int
271ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr)
272{
273 return be32_to_cpu(ucd_rsp_ptr->header.dword_2) &
274 MASK_RSP_UPIU_DATA_SEG_LEN;
275}
276
263/** 277/**
264 * ufshcd_is_exception_event - Check if the device raised an exception event 278 * ufshcd_is_exception_event - Check if the device raised an exception event
265 * @ucd_rsp_ptr: pointer to response UPIU 279 * @ucd_rsp_ptr: pointer to response UPIU
@@ -355,7 +369,8 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
355static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) 369static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
356{ 370{
357 int len; 371 int len;
358 if (lrbp->sense_buffer) { 372 if (lrbp->sense_buffer &&
373 ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) {
359 len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len); 374 len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len);
360 memcpy(lrbp->sense_buffer, 375 memcpy(lrbp->sense_buffer,
361 lrbp->ucd_rsp_ptr->sr.sense_data, 376 lrbp->ucd_rsp_ptr->sr.sense_data,
@@ -1788,32 +1803,24 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status)
1788 int result = 0; 1803 int result = 0;
1789 1804
1790 switch (scsi_status) { 1805 switch (scsi_status) {
1791 case SAM_STAT_GOOD:
1792 result |= DID_OK << 16 |
1793 COMMAND_COMPLETE << 8 |
1794 SAM_STAT_GOOD;
1795 break;
1796 case SAM_STAT_CHECK_CONDITION: 1806 case SAM_STAT_CHECK_CONDITION:
1807 ufshcd_copy_sense_data(lrbp);
1808 case SAM_STAT_GOOD:
1797 result |= DID_OK << 16 | 1809 result |= DID_OK << 16 |
1798 COMMAND_COMPLETE << 8 | 1810 COMMAND_COMPLETE << 8 |
1799 SAM_STAT_CHECK_CONDITION; 1811 scsi_status;
1800 ufshcd_copy_sense_data(lrbp);
1801 break;
1802 case SAM_STAT_BUSY:
1803 result |= SAM_STAT_BUSY;
1804 break; 1812 break;
1805 case SAM_STAT_TASK_SET_FULL: 1813 case SAM_STAT_TASK_SET_FULL:
1806
1807 /* 1814 /*
1808 * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue 1815 * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue
1809 * depth needs to be adjusted to the exact number of 1816 * depth needs to be adjusted to the exact number of
1810 * outstanding commands the LUN can handle at any given time. 1817 * outstanding commands the LUN can handle at any given time.
1811 */ 1818 */
1812 ufshcd_adjust_lun_qdepth(lrbp->cmd); 1819 ufshcd_adjust_lun_qdepth(lrbp->cmd);
1813 result |= SAM_STAT_TASK_SET_FULL; 1820 case SAM_STAT_BUSY:
1814 break;
1815 case SAM_STAT_TASK_ABORTED: 1821 case SAM_STAT_TASK_ABORTED:
1816 result |= SAM_STAT_TASK_ABORTED; 1822 ufshcd_copy_sense_data(lrbp);
1823 result |= scsi_status;
1817 break; 1824 break;
1818 default: 1825 default:
1819 result |= DID_ERROR << 16; 1826 result |= DID_ERROR << 16;