aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDolev Raviv <draviv@codeaurora.org>2014-06-29 02:40:17 -0400
committerChristoph Hellwig <hch@lst.de>2014-07-25 17:17:01 -0400
commitd44a5f98bb49b2c15348fa65cee73df4a157bfbf (patch)
treec4ac73142a1d3d199481af1ba72b76649652b7e3
parent6d67726bd898151e688d8729b3997ba8417c2c6b (diff)
ufs: query descriptor API
Introduces the API for sending queries with descriptors. A descriptor is a block or page of parameters that describe the device. The descriptors are classified into types and can range in size from 2 bytes through 255 bytes. All descriptors have a length value as their first element, and a type identification element as their second byte. All descriptors are readable and some may be write once. They are accessed using their type, index and selector. Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Raviv Shvili <rshvili@codeaurora.org> Acked-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/scsi/ufs/ufs.h17
-rw-r--r--drivers/scsi/ufs/ufshcd.c139
2 files changed, 128 insertions, 28 deletions
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f42d1cee652a..1545cd7877d0 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -41,7 +41,8 @@
41 41
42#define MAX_CDB_SIZE 16 42#define MAX_CDB_SIZE 16
43#define GENERAL_UPIU_REQUEST_SIZE 32 43#define GENERAL_UPIU_REQUEST_SIZE 32
44#define QUERY_DESC_MAX_SIZE 256 44#define QUERY_DESC_MAX_SIZE 255
45#define QUERY_DESC_MIN_SIZE 2
45#define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ 46#define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \
46 (sizeof(struct utp_upiu_header))) 47 (sizeof(struct utp_upiu_header)))
47 48
@@ -117,6 +118,20 @@ enum attr_idn {
117 QUERY_ATTR_IDN_EE_STATUS = 0x0E, 118 QUERY_ATTR_IDN_EE_STATUS = 0x0E,
118}; 119};
119 120
121/* Descriptor idn for Query requests */
122enum desc_idn {
123 QUERY_DESC_IDN_DEVICE = 0x0,
124 QUERY_DESC_IDN_CONFIGURAION = 0x1,
125 QUERY_DESC_IDN_UNIT = 0x2,
126 QUERY_DESC_IDN_RFU_0 = 0x3,
127 QUERY_DESC_IDN_INTERCONNECT = 0x4,
128 QUERY_DESC_IDN_STRING = 0x5,
129 QUERY_DESC_IDN_RFU_1 = 0x6,
130 QUERY_DESC_IDN_GEOMETRY = 0x7,
131 QUERY_DESC_IDN_POWER = 0x8,
132 QUERY_DESC_IDN_RFU_2 = 0x9,
133};
134
120/* Exception event mask values */ 135/* Exception event mask values */
121enum { 136enum {
122 MASK_EE_STATUS = 0xFFFF, 137 MASK_EE_STATUS = 0xFFFF,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0c2877251251..ed533f43f231 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -459,7 +459,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
459 459
460 /* Get the descriptor */ 460 /* Get the descriptor */
461 if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) { 461 if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) {
462 u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr + 462 u8 *descp = (u8 *)lrbp->ucd_rsp_ptr +
463 GENERAL_UPIU_REQUEST_SIZE; 463 GENERAL_UPIU_REQUEST_SIZE;
464 u16 len; 464 u16 len;
465 465
@@ -1134,6 +1134,30 @@ out_put_tag:
1134} 1134}
1135 1135
1136/** 1136/**
1137 * ufshcd_init_query() - init the query response and request parameters
1138 * @hba: per-adapter instance
1139 * @request: address of the request pointer to be initialized
1140 * @response: address of the response pointer to be initialized
1141 * @opcode: operation to perform
1142 * @idn: flag idn to access
1143 * @index: LU number to access
1144 * @selector: query/flag/descriptor further identification
1145 */
1146static inline void ufshcd_init_query(struct ufs_hba *hba,
1147 struct ufs_query_req **request, struct ufs_query_res **response,
1148 enum query_opcode opcode, u8 idn, u8 index, u8 selector)
1149{
1150 *request = &hba->dev_cmd.query.request;
1151 *response = &hba->dev_cmd.query.response;
1152 memset(*request, 0, sizeof(struct ufs_query_req));
1153 memset(*response, 0, sizeof(struct ufs_query_res));
1154 (*request)->upiu_req.opcode = opcode;
1155 (*request)->upiu_req.idn = idn;
1156 (*request)->upiu_req.index = index;
1157 (*request)->upiu_req.selector = selector;
1158}
1159
1160/**
1137 * ufshcd_query_flag() - API function for sending flag query requests 1161 * ufshcd_query_flag() - API function for sending flag query requests
1138 * hba: per-adapter instance 1162 * hba: per-adapter instance
1139 * query_opcode: flag query to perform 1163 * query_opcode: flag query to perform
@@ -1145,17 +1169,15 @@ out_put_tag:
1145static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, 1169static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
1146 enum flag_idn idn, bool *flag_res) 1170 enum flag_idn idn, bool *flag_res)
1147{ 1171{
1148 struct ufs_query_req *request; 1172 struct ufs_query_req *request = NULL;
1149 struct ufs_query_res *response; 1173 struct ufs_query_res *response = NULL;
1150 int err; 1174 int err, index = 0, selector = 0;
1151 1175
1152 BUG_ON(!hba); 1176 BUG_ON(!hba);
1153 1177
1154 mutex_lock(&hba->dev_cmd.lock); 1178 mutex_lock(&hba->dev_cmd.lock);
1155 request = &hba->dev_cmd.query.request; 1179 ufshcd_init_query(hba, &request, &response, opcode, idn, index,
1156 response = &hba->dev_cmd.query.response; 1180 selector);
1157 memset(request, 0, sizeof(struct ufs_query_req));
1158 memset(response, 0, sizeof(struct ufs_query_res));
1159 1181
1160 switch (opcode) { 1182 switch (opcode) {
1161 case UPIU_QUERY_OPCODE_SET_FLAG: 1183 case UPIU_QUERY_OPCODE_SET_FLAG:
@@ -1180,12 +1202,8 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
1180 err = -EINVAL; 1202 err = -EINVAL;
1181 goto out_unlock; 1203 goto out_unlock;
1182 } 1204 }
1183 request->upiu_req.opcode = opcode;
1184 request->upiu_req.idn = idn;
1185 1205
1186 /* Send query request */ 1206 err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
1187 err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
1188 QUERY_REQ_TIMEOUT);
1189 1207
1190 if (err) { 1208 if (err) {
1191 dev_err(hba->dev, 1209 dev_err(hba->dev,
@@ -1217,8 +1235,8 @@ out_unlock:
1217static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, 1235static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
1218 enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) 1236 enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
1219{ 1237{
1220 struct ufs_query_req *request; 1238 struct ufs_query_req *request = NULL;
1221 struct ufs_query_res *response; 1239 struct ufs_query_res *response = NULL;
1222 int err; 1240 int err;
1223 1241
1224 BUG_ON(!hba); 1242 BUG_ON(!hba);
@@ -1231,10 +1249,8 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
1231 } 1249 }
1232 1250
1233 mutex_lock(&hba->dev_cmd.lock); 1251 mutex_lock(&hba->dev_cmd.lock);
1234 request = &hba->dev_cmd.query.request; 1252 ufshcd_init_query(hba, &request, &response, opcode, idn, index,
1235 response = &hba->dev_cmd.query.response; 1253 selector);
1236 memset(request, 0, sizeof(struct ufs_query_req));
1237 memset(response, 0, sizeof(struct ufs_query_res));
1238 1254
1239 switch (opcode) { 1255 switch (opcode) {
1240 case UPIU_QUERY_OPCODE_WRITE_ATTR: 1256 case UPIU_QUERY_OPCODE_WRITE_ATTR:
@@ -1251,14 +1267,7 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
1251 goto out_unlock; 1267 goto out_unlock;
1252 } 1268 }
1253 1269
1254 request->upiu_req.opcode = opcode; 1270 err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
1255 request->upiu_req.idn = idn;
1256 request->upiu_req.index = index;
1257 request->upiu_req.selector = selector;
1258
1259 /* Send query request */
1260 err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY,
1261 QUERY_REQ_TIMEOUT);
1262 1271
1263 if (err) { 1272 if (err) {
1264 dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", 1273 dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
@@ -1275,6 +1284,82 @@ out:
1275} 1284}
1276 1285
1277/** 1286/**
1287 * ufshcd_query_descriptor - API function for sending descriptor requests
1288 * hba: per-adapter instance
1289 * opcode: attribute opcode
1290 * idn: attribute idn to access
1291 * index: index field
1292 * selector: selector field
1293 * desc_buf: the buffer that contains the descriptor
1294 * buf_len: length parameter passed to the device
1295 *
1296 * Returns 0 for success, non-zero in case of failure.
1297 * The buf_len parameter will contain, on return, the length parameter
1298 * received on the response.
1299 */
1300int ufshcd_query_descriptor(struct ufs_hba *hba,
1301 enum query_opcode opcode, enum desc_idn idn, u8 index,
1302 u8 selector, u8 *desc_buf, int *buf_len)
1303{
1304 struct ufs_query_req *request = NULL;
1305 struct ufs_query_res *response = NULL;
1306 int err;
1307
1308 BUG_ON(!hba);
1309
1310 if (!desc_buf) {
1311 dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n",
1312 __func__, opcode);
1313 err = -EINVAL;
1314 goto out;
1315 }
1316
1317 if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) {
1318 dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n",
1319 __func__, *buf_len);
1320 err = -EINVAL;
1321 goto out;
1322 }
1323
1324 mutex_lock(&hba->dev_cmd.lock);
1325 ufshcd_init_query(hba, &request, &response, opcode, idn, index,
1326 selector);
1327 hba->dev_cmd.query.descriptor = desc_buf;
1328 request->upiu_req.length = *buf_len;
1329
1330 switch (opcode) {
1331 case UPIU_QUERY_OPCODE_WRITE_DESC:
1332 request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
1333 break;
1334 case UPIU_QUERY_OPCODE_READ_DESC:
1335 request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
1336 break;
1337 default:
1338 dev_err(hba->dev,
1339 "%s: Expected query descriptor opcode but got = 0x%.2x\n",
1340 __func__, opcode);
1341 err = -EINVAL;
1342 goto out_unlock;
1343 }
1344
1345 err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
1346
1347 if (err) {
1348 dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n",
1349 __func__, opcode, idn, err);
1350 goto out_unlock;
1351 }
1352
1353 hba->dev_cmd.query.descriptor = NULL;
1354 *buf_len = response->upiu_res.length;
1355
1356out_unlock:
1357 mutex_unlock(&hba->dev_cmd.lock);
1358out:
1359 return err;
1360}
1361
1362/**
1278 * ufshcd_memory_alloc - allocate memory for host memory space data structures 1363 * ufshcd_memory_alloc - allocate memory for host memory space data structures
1279 * @hba: per adapter instance 1364 * @hba: per adapter instance
1280 * 1365 *