Skip to content

Commit da461ce

Browse files
Subhash JadavaniChristoph Hellwig
authored andcommitted
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 <[email protected]> Signed-off-by: Dolev Raviv <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 6a771a6 commit da461ce

File tree

2 files changed

+153
-39
lines changed

2 files changed

+153
-39
lines changed

drivers/scsi/ufs/ufs.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
5151
(byte1 << 8) | (byte0))
5252

53+
#define UFS_UPIU_MAX_GENERAL_LUN 8
54+
5355
/*
5456
* UFS Protocol Information Unit related definitions
5557
*/
@@ -129,10 +131,29 @@ enum desc_idn {
129131
QUERY_DESC_IDN_RFU_1 = 0x6,
130132
QUERY_DESC_IDN_GEOMETRY = 0x7,
131133
QUERY_DESC_IDN_POWER = 0x8,
132-
QUERY_DESC_IDN_RFU_2 = 0x9,
134+
QUERY_DESC_IDN_MAX,
135+
};
136+
137+
enum desc_header_offset {
138+
QUERY_DESC_LENGTH_OFFSET = 0x00,
139+
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
140+
};
141+
142+
enum 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,
133155
};
134156

135-
#define UNIT_DESC_MAX_SIZE 0x22
136157
/* Unit descriptor parameters offsets in bytes*/
137158
enum unit_desc_param {
138159
UNIT_DESC_PARAM_LEN = 0x0,

drivers/scsi/ufs/ufshcd.c

Lines changed: 130 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@
7878
_ret; \
7979
})
8080

81+
static 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+
8194
enum {
8295
UFSHCD_MAX_CHANNEL = 0,
8396
UFSHCD_MAX_ID = 1,
@@ -124,8 +137,6 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba);
124137
static void ufshcd_async_scan(void *data, async_cookie_t cookie);
125138
static int ufshcd_reset_and_restore(struct ufs_hba *hba);
126139
static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
127-
static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
128-
struct scsi_device *sdev);
129140

130141
/*
131142
* ufshcd_wait_for_register - wait for register value to change
@@ -1392,6 +1403,115 @@ static int ufshcd_query_descriptor(struct ufs_hba *hba,
13921403
return err;
13931404
}
13941405

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+
*/
1417+
static 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);
1466+
out:
1467+
if (is_kmalloc)
1468+
kfree(desc_buf);
1469+
return ret;
1470+
}
1471+
1472+
static 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+
1481+
static 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+
*/
1498+
static 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,
1512+
param_offset, param_read_buf, param_size);
1513+
}
1514+
13951515
/**
13961516
* ufshcd_memory_alloc - allocate memory for host memory space data structures
13971517
* @hba: per adapter instance
@@ -2011,7 +2131,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
20112131
static int ufshcd_slave_alloc(struct scsi_device *sdev)
20122132
{
20132133
struct ufs_hba *hba;
2014-
int lun_qdepth;
2134+
u8 lun_qdepth;
2135+
int ret;
20152136

20162137
hba = shost_priv(sdev->host);
20172138
sdev->tagged_supported = 1;
@@ -2026,8 +2147,12 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
20262147
/* REPORT SUPPORTED OPERATION CODES is not supported */
20272148
sdev->no_report_opcodes = 1;
20282149

2029-
lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev);
2030-
if (lun_qdepth <= 0)
2150+
ret = ufshcd_read_unit_desc_param(hba,
2151+
sdev->lun,
2152+
UNIT_DESC_PARAM_LU_Q_DEPTH,
2153+
&lun_qdepth,
2154+
sizeof(lun_qdepth));
2155+
if (!ret || !lun_qdepth)
20312156
/* eventually, we can figure out the real queue depth */
20322157
lun_qdepth = hba->nutrs;
20332158
else
@@ -3117,38 +3242,6 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
31173242
return err;
31183243
}
31193244

3120-
/**
3121-
* ufshcd_read_sdev_qdepth - read the lun command queue depth
3122-
* @hba: Pointer to adapter instance
3123-
* @sdev: pointer to SCSI device
3124-
*
3125-
* Return in case of success the lun's queue depth else error.
3126-
*/
3127-
static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
3128-
struct scsi_device *sdev)
3129-
{
3130-
int ret;
3131-
int buff_len = UNIT_DESC_MAX_SIZE;
3132-
u8 desc_buf[UNIT_DESC_MAX_SIZE];
3133-
3134-
ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
3135-
QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len);
3136-
3137-
if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) {
3138-
dev_err(hba->dev,
3139-
"%s:Failed reading unit descriptor. len = %d ret = %d"
3140-
, __func__, buff_len, ret);
3141-
if (!ret)
3142-
ret = -EINVAL;
3143-
3144-
goto out;
3145-
}
3146-
3147-
ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF;
3148-
out:
3149-
return ret;
3150-
}
3151-
31523245
/**
31533246
* ufshcd_async_scan - asynchronous execution for link startup
31543247
* @data: data pointer to pass to this function

0 commit comments

Comments
 (0)