aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2014-09-25 08:32:25 -0400
committerChristoph Hellwig <hch@lst.de>2014-10-01 07:11:20 -0400
commitda461cec9a1ff0a074cd1db47598ba36a1686ef4 (patch)
treeb947fe64044eb45b8bdfcc928459de10e5d0ca6a
parent6a771a656041f404fae143e5d753d37f5c0688e7 (diff)
ufs: refactor query descriptor API support
Currently reading query descriptor is more tightened to each descriptor type. This patch generalize the approach and allows reading any parameter from any query descriptor. Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/ufs/ufs.h25
-rw-r--r--drivers/scsi/ufs/ufshcd.c167
2 files changed, 153 insertions, 39 deletions
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 9bb691962c47..f76a304e7408 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -50,6 +50,8 @@
50 cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ 50 cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
51 (byte1 << 8) | (byte0)) 51 (byte1 << 8) | (byte0))
52 52
53#define UFS_UPIU_MAX_GENERAL_LUN 8
54
53/* 55/*
54 * UFS Protocol Information Unit related definitions 56 * UFS Protocol Information Unit related definitions
55 */ 57 */
@@ -129,10 +131,29 @@ enum desc_idn {
129 QUERY_DESC_IDN_RFU_1 = 0x6, 131 QUERY_DESC_IDN_RFU_1 = 0x6,
130 QUERY_DESC_IDN_GEOMETRY = 0x7, 132 QUERY_DESC_IDN_GEOMETRY = 0x7,
131 QUERY_DESC_IDN_POWER = 0x8, 133 QUERY_DESC_IDN_POWER = 0x8,
132 QUERY_DESC_IDN_RFU_2 = 0x9, 134 QUERY_DESC_IDN_MAX,
135};
136
137enum desc_header_offset {
138 QUERY_DESC_LENGTH_OFFSET = 0x00,
139 QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
140};
141
142enum ufs_desc_max_size {
143 QUERY_DESC_DEVICE_MAX_SIZE = 0x1F,
144 QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90,
145 QUERY_DESC_UNIT_MAX_SIZE = 0x23,
146 QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06,
147 /*
148 * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes
149 * of descriptor header.
150 */
151 QUERY_DESC_STRING_MAX_SIZE = 0xFE,
152 QUERY_DESC_GEOMETRY_MAZ_SIZE = 0x44,
153 QUERY_DESC_POWER_MAX_SIZE = 0x62,
154 QUERY_DESC_RFU_MAX_SIZE = 0x00,
133}; 155};
134 156
135#define UNIT_DESC_MAX_SIZE 0x22
136/* Unit descriptor parameters offsets in bytes*/ 157/* Unit descriptor parameters offsets in bytes*/
137enum unit_desc_param { 158enum unit_desc_param {
138 UNIT_DESC_PARAM_LEN = 0x0, 159 UNIT_DESC_PARAM_LEN = 0x0,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 26301b8325e8..3f2b30db80cc 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -78,6 +78,19 @@
78 _ret; \ 78 _ret; \
79 }) 79 })
80 80
81static u32 ufs_query_desc_max_size[] = {
82 QUERY_DESC_DEVICE_MAX_SIZE,
83 QUERY_DESC_CONFIGURAION_MAX_SIZE,
84 QUERY_DESC_UNIT_MAX_SIZE,
85 QUERY_DESC_RFU_MAX_SIZE,
86 QUERY_DESC_INTERCONNECT_MAX_SIZE,
87 QUERY_DESC_STRING_MAX_SIZE,
88 QUERY_DESC_RFU_MAX_SIZE,
89 QUERY_DESC_GEOMETRY_MAZ_SIZE,
90 QUERY_DESC_POWER_MAX_SIZE,
91 QUERY_DESC_RFU_MAX_SIZE,
92};
93
81enum { 94enum {
82 UFSHCD_MAX_CHANNEL = 0, 95 UFSHCD_MAX_CHANNEL = 0,
83 UFSHCD_MAX_ID = 1, 96 UFSHCD_MAX_ID = 1,
@@ -124,8 +137,6 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba);
124static void ufshcd_async_scan(void *data, async_cookie_t cookie); 137static void ufshcd_async_scan(void *data, async_cookie_t cookie);
125static int ufshcd_reset_and_restore(struct ufs_hba *hba); 138static int ufshcd_reset_and_restore(struct ufs_hba *hba);
126static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); 139static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
127static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
128 struct scsi_device *sdev);
129 140
130/* 141/*
131 * ufshcd_wait_for_register - wait for register value to change 142 * ufshcd_wait_for_register - wait for register value to change
@@ -1393,6 +1404,115 @@ out:
1393} 1404}
1394 1405
1395/** 1406/**
1407 * ufshcd_read_desc_param - read the specified descriptor parameter
1408 * @hba: Pointer to adapter instance
1409 * @desc_id: descriptor idn value
1410 * @desc_index: descriptor index
1411 * @param_offset: offset of the parameter to read
1412 * @param_read_buf: pointer to buffer where parameter would be read
1413 * @param_size: sizeof(param_read_buf)
1414 *
1415 * Return 0 in case of success, non-zero otherwise
1416 */
1417static int ufshcd_read_desc_param(struct ufs_hba *hba,
1418 enum desc_idn desc_id,
1419 int desc_index,
1420 u32 param_offset,
1421 u8 *param_read_buf,
1422 u32 param_size)
1423{
1424 int ret;
1425 u8 *desc_buf;
1426 u32 buff_len;
1427 bool is_kmalloc = true;
1428
1429 /* safety checks */
1430 if (desc_id >= QUERY_DESC_IDN_MAX)
1431 return -EINVAL;
1432
1433 buff_len = ufs_query_desc_max_size[desc_id];
1434 if ((param_offset + param_size) > buff_len)
1435 return -EINVAL;
1436
1437 if (!param_offset && (param_size == buff_len)) {
1438 /* memory space already available to hold full descriptor */
1439 desc_buf = param_read_buf;
1440 is_kmalloc = false;
1441 } else {
1442 /* allocate memory to hold full descriptor */
1443 desc_buf = kmalloc(buff_len, GFP_KERNEL);
1444 if (!desc_buf)
1445 return -ENOMEM;
1446 }
1447
1448 ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
1449 desc_id, desc_index, 0, desc_buf,
1450 &buff_len);
1451
1452 if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) ||
1453 (desc_buf[QUERY_DESC_LENGTH_OFFSET] !=
1454 ufs_query_desc_max_size[desc_id])
1455 || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) {
1456 dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d",
1457 __func__, desc_id, param_offset, buff_len, ret);
1458 if (!ret)
1459 ret = -EINVAL;
1460
1461 goto out;
1462 }
1463
1464 if (is_kmalloc)
1465 memcpy(param_read_buf, &desc_buf[param_offset], param_size);
1466out:
1467 if (is_kmalloc)
1468 kfree(desc_buf);
1469 return ret;
1470}
1471
1472static inline int ufshcd_read_desc(struct ufs_hba *hba,
1473 enum desc_idn desc_id,
1474 int desc_index,
1475 u8 *buf,
1476 u32 size)
1477{
1478 return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size);
1479}
1480
1481static inline int ufshcd_read_power_desc(struct ufs_hba *hba,
1482 u8 *buf,
1483 u32 size)
1484{
1485 return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size);
1486}
1487
1488/**
1489 * ufshcd_read_unit_desc_param - read the specified unit descriptor parameter
1490 * @hba: Pointer to adapter instance
1491 * @lun: lun id
1492 * @param_offset: offset of the parameter to read
1493 * @param_read_buf: pointer to buffer where parameter would be read
1494 * @param_size: sizeof(param_read_buf)
1495 *
1496 * Return 0 in case of success, non-zero otherwise
1497 */
1498static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
1499 int lun,
1500 enum unit_desc_param param_offset,
1501 u8 *param_read_buf,
1502 u32 param_size)
1503{
1504 /*
1505 * Unit descriptors are only available for general purpose LUs (LUN id
1506 * from 0 to 7) and RPMB Well known LU.
1507 */
1508 if (lun >= UFS_UPIU_MAX_GENERAL_LUN)
1509 return -EOPNOTSUPP;
1510
1511 return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,