blob: 61efb47bcf7a8ad84f82b26c9e70c37a93a81ea5 [file] [log] [blame]
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -07001/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <string.h>
31#include <reg.h>
32#include <arch/defines.h>
33#include <sys/types.h>
34#include <stdlib.h>
35#include <endian.h>
36#include <ufs.h>
37#include <dme.h>
38#include <uic.h>
39#include <utp.h>
Sridhar Parasuram9374faa2014-10-23 19:56:12 -070040#include <ucs.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070041
42int dme_send_linkstartup_req(struct ufs_dev *dev)
43{
44 struct uic_cmd cmd;
45
46 cmd.uiccmd = UICCMDR_DME_LINKSTARTUP;
47 cmd.num_args = UICCMD_NO_ARGS;
48 cmd.timeout_msecs = DME_LINK_START_TIMEOUT;
49
50 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
51 goto dme_send_linkstartup_req_err;
52
53 return UFS_SUCCESS;
54
55dme_send_linkstartup_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080056 dprintf(CRITICAL, "%s:%d DME_LINKSTARTUP command failed.\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070057 return -UFS_FAILURE;
58}
59
60int dme_get_req(struct ufs_dev *dev, struct dme_get_req_type *req)
61{
62 struct uic_cmd cmd;
63
64 cmd.uiccmd = UICCMDR_DME_GET;
65 cmd.num_args = UICCMD_ONE_ARGS;
66 cmd.uiccmdarg1 = req->attribute << 16 | req->index;
67 cmd.timeout_msecs = INFINITE_TIME;
68
69 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
70 goto dme_get_req_err;
71
72 /* Return the result. */
73 *(req->mibval) = cmd.uiccmdarg3;
74
75 return UFS_SUCCESS;
76
77dme_get_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080078 dprintf(CRITICAL, "%s:%d DME_GET command failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070079 return -UFS_FAILURE;
80}
81
82static int dme_get_query_resp(struct ufs_dev *dev,
83 struct upiu_req_build_type *req_upiu,
84 addr_t buffer,
85 size_t buf_len)
86{
87 struct upiu_trans_mgmt_query_hdr *resp_upiu;
88
89 resp_upiu = (struct upiu_trans_mgmt_query_hdr *) req_upiu->resp_ptr;
90
91 if (resp_upiu->opcode != req_upiu->opcode)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080092 {
93 dprintf(CRITICAL, "%s:%d Opcode from respose does not match with Opcode from request\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070094 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080095 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070096 if (resp_upiu->basic_hdr.response != UPIU_QUERY_RESP_SUCCESS)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080097 {
98 dprintf(CRITICAL, "%s:%d UPIU Response is not SUCCESS\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070099 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800100 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700101
102 switch (resp_upiu->opcode)
103 {
104 case UPIU_QUERY_OP_READ_FLAG:
105 case UPIU_QUERY_OP_SET_FLAG:
106 if (buf_len < sizeof(uint32_t))
107 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800108 dprintf(CRITICAL, "%s:%d Insufficient buffer space.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700109 return -UFS_FAILURE;
110 }
111
112 *((uint32_t *) buffer) = resp_upiu->flag_value;
113 break;
114 case UPIU_QUERY_OP_TOGGLE_FLAG:
115 case UPIU_QUERY_OP_CLEAR_FLAG:
116 case UPIU_QUERY_OP_READ_DESCRIPTOR:
117 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800118 default:
119 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
120 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700121 }
122
123 return UFS_SUCCESS;
124}
125
126static int dme_send_query_upiu(struct ufs_dev *dev, struct utp_query_req_upiu_type *query)
127{
128 struct upiu_trans_mgmt_query_hdr resp_upiu;
129 struct upiu_req_build_type req_upiu;
130 int ret;
131
132 memset(&req_upiu, 0, sizeof(req_upiu));
133
134 req_upiu.opcode = query->opcode;
135 req_upiu.selector = query->selector;
136 req_upiu.index = query->index;
137 req_upiu.idn = query->idn;
138 req_upiu.trans_type = UPIU_TYPE_QUERY_REQ;
139 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
140 req_upiu.resp_ptr = (struct upiu_basic_hdr *) &resp_upiu;
141 req_upiu.resp_len = sizeof(resp_upiu);
142 req_upiu.resp_data_ptr = query->buf;
143 req_upiu.timeout_msecs = UTP_GENERIC_CMD_TIMEOUT;
144
145 if (query->opcode == UPIU_QUERY_OP_READ_DESCRIPTOR)
146 {
147 req_upiu.resp_data_len = query->buf_len;
148 }
149
150 ret = utp_enqueue_upiu(dev, &req_upiu);
151 if (ret)
152 goto utp_send_query_upiu_err;
153
154 ret = dme_get_query_resp(dev, &req_upiu, query->buf, query->buf_len);
155 if (ret)
156 goto utp_send_query_upiu_err;
157
158utp_send_query_upiu_err:
159 return ret;
160}
161
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700162int dme_set_fpoweronwpen(struct ufs_dev *dev)
163{
164 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
165 uint32_t try_again = DME_FPOWERONWPEN_RETRIES;
166 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
167 UFS_IDX_fPowerOnWPEn,
168 0,
169 0,
170 (addr_t) result,
171 sizeof(uint32_t)};
172 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
173 UFS_IDX_fPowerOnWPEn,
174 0,
175 0,
176 (addr_t) result,
177 sizeof(uint32_t)};
178
179
180 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800181 {
182 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700183 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800184 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700185
186 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
187
188 if (*result == 1)
189 goto utp_set_fpoweronwpen_done;
190
191 do
192 {
193 try_again--;
194 dprintf(CRITICAL, "Power on Write Protect request failed. Retrying again.\n");
195
196 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800197 {
198 dprintf(CRITICAL, "%s:%d DME Power On Write Set Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700199 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800200 }
201
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700202 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800203 {
204 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700205 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800206 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700207
208 if (*result == 1)
209 break;
210 } while (try_again);
211
212utp_set_fpoweronwpen_done:
213 dprintf(INFO,"Power on Write Protect status: %u\n", *result);
214 return UFS_SUCCESS;
215}
216
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700217int dme_set_fdeviceinit(struct ufs_dev *dev)
218{
219 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
220 uint32_t try_again = DME_FDEVICEINIT_RETRIES;
221 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
222 UFS_IDX_fDeviceInit,
223 0,
224 0,
225 (addr_t) result,
226 sizeof(uint32_t)};
227 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
228 UFS_IDX_fDeviceInit,
229 0,
230 0,
231 (addr_t) result,
232 sizeof(uint32_t)};
233
234
235 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800236 {
237 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700238 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800239 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700240
241 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
242
243 if (*result == 1)
244 goto utp_set_fdeviceinit_done;
245
246 do
247 {
248 try_again--;
249
250 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800251 {
252 dprintf(CRITICAL, "%s:%d DME Device Init Set request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700253 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800254 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700255
256 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800257 {
258 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700259 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800260 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700261
262 if (*result == 1)
263 break;
264 } while (try_again);
265
266utp_set_fdeviceinit_done:
267 return UFS_SUCCESS;
268}
269
270int dme_read_string_desc(struct ufs_dev *dev, uint8_t index, struct ufs_string_desc *desc)
271{
272 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
273 UFS_DESC_IDN_STRING,
274 index,
275 0,
276 (addr_t) desc,
277 sizeof(struct ufs_string_desc)};
278
279 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800280 {
281 dprintf(CRITICAL, "%s:%d DME Read String Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700282 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800283 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700284
285 if (desc->desc_len != 0)
286 return UFS_SUCCESS;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800287 dprintf(CRITICAL, "%s:%d DME Read String Descriptor is length 0\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700288 return -UFS_FAILURE;
289}
290
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700291static uint32_t dme_parse_serial_no(struct ufs_string_desc *desc)
292{
293 uint32_t serial_no=0;
294 uint16_t *ptr;
295 int index=0,len=0;
296
297 if(desc->desc_len <= 0)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800298 {
299 dprintf(CRITICAL, "%s:%d Invalid string descriptor length\n", __func__, __LINE__);
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700300 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800301 }
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700302
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800303 ptr = (uint16_t *) desc->serial_num;
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700304 len = (desc->desc_len-2)/2;
305
306 for(index=0; index<len; index++)
307 {
308 serial_no += *ptr;
309 ptr++;
310 }
311
312 return serial_no;
313}
314
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700315int dme_read_device_desc(struct ufs_dev *dev)
316{
317 STACKBUF_DMA_ALIGN(dev_desc, sizeof(struct ufs_dev_desc));
318 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_string_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800319 struct ufs_dev_desc *device_desc = (struct ufs_dev_desc *) dev_desc;
320 struct ufs_string_desc *str_desc = (struct ufs_string_desc *) desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700321 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
322 UFS_DESC_IDN_DEVICE,
323 0,
324 0,
325 (addr_t) dev_desc,
326 sizeof(struct ufs_dev_desc)};
327
328 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800329 {
330 dprintf(CRITICAL, "%s:%d DME Read Device Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700331 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800332 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700333
334 /* Flush buffer. */
335 arch_invalidate_cache_range((addr_t) device_desc, sizeof(struct ufs_dev_desc));
336
337 /* Store all relevant data */
338 dev->num_lus = device_desc->num_lu;
339
340 /* Get serial number for the device based on the string index. */
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800341 if (dme_read_string_desc(dev, device_desc->serial_num, (struct ufs_string_desc *) desc))
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700342 return -UFS_FAILURE;
343
344 /* Flush buffer. */
345 arch_invalidate_cache_range((addr_t) str_desc, sizeof(struct ufs_string_desc));
346
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700347 dev->serial_num = dme_parse_serial_no(str_desc);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700348
349 return UFS_SUCCESS;
350}
351
352
353int dme_read_geo_desc(struct ufs_dev *dev)
354{
355 struct ufs_geometry_desc *desc;
356 STACKBUF_DMA_ALIGN(geometry_desc, sizeof(struct ufs_geometry_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800357 desc = (struct ufs_geometry_desc *) geometry_desc;
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700358 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
359 UFS_DESC_IDN_GEOMETRY,
360 0,
361 0,
362 (addr_t) geometry_desc,
363 sizeof(struct ufs_geometry_desc)};
364
365 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800366 {
367 dprintf(CRITICAL, "%s:%d DME Read Geometry Descriptor request failed\n", __func__, __LINE__);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700368 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800369 }
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700370
371 // Flush buffer.
372 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_geometry_desc));
373 dev->rpmb_rw_size = desc->rpmb_read_write_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700374 return UFS_SUCCESS;
375}
376
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700377int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700378{
379 STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800380 struct ufs_unit_desc *desc = (struct ufs_unit_desc *) unit_desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700381 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
382 UFS_DESC_IDN_UNIT,
383 index,
384 0,
385 (addr_t) unit_desc,
386 sizeof(struct ufs_unit_desc)};
387
388 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800389 {
390 dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700391 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800392 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700393 /* Flush buffer. */
394 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc));
395
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800396 dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700397
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800398 dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700399
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700400 // use only the lower 32 bits for rpmb partition size
401 if (index == UFS_WLUN_RPMB)
402 dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);
403
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700404 return UFS_SUCCESS;
405}
406
407int dme_read_config_desc(struct ufs_dev *dev)
408{
409 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_config_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800410 struct ufs_config_desc *config_desc = (struct ufs_config_desc *)desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700411 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
412 UFS_DESC_IDN_CONFIGURATION,
413 0,
414 0,
415 (addr_t) config_desc,
416 sizeof(struct ufs_config_desc)};
417
418 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800419 {
420 dprintf(CRITICAL, "%s:%d DME Read Config Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700421 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800422 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700423
424 /* Flush buffer. */
425 arch_invalidate_cache_range((addr_t) config_desc, sizeof(struct ufs_config_desc));
426
427 return UFS_SUCCESS;
428}
429
430int dme_send_nop_query(struct ufs_dev *dev)
431{
432 struct upiu_req_build_type req_upiu;
433 struct upiu_basic_hdr resp_upiu;
434 int ret;
435 unsigned try_again;
436
437 ret = UFS_SUCCESS;
438 try_again = DME_NOP_NUM_RETRIES;
439
440 memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
441
442 req_upiu.trans_type = UPIU_TYPE_NOP_OUT;
443 req_upiu.flags = 0;
444 req_upiu.query_mgmt_func = 0;
445 req_upiu.cmd_type = UTRD_DEV_MGMT_FUNC;
446 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
447 req_upiu.resp_ptr = &resp_upiu;
448 req_upiu.resp_len = sizeof(struct upiu_basic_hdr);
449 req_upiu.timeout_msecs = DME_NOP_QUERY_TIMEOUT;
450
451 while (try_again)
452 {
453 try_again--;
454
455 ret = utp_enqueue_upiu(dev, &req_upiu);
456
457 if (ret == -UFS_RETRY)
458 {
459 continue;
460 }
461 else if (ret == -UFS_FAILURE)
462 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800463 dprintf(CRITICAL, "%s:%d Sending nop out failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700464 goto upiu_send_nop_out_err;
465 }
466
467 /* Check response UPIU */
468 if (resp_upiu.trans_type != UPIU_TYPE_NOP_IN)
469 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800470 dprintf(CRITICAL, "%s:%d Command failed. command = %x. Invalid response.\n",__func__,__LINE__, req_upiu.trans_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700471 ret = -UFS_FAILURE;
472 goto upiu_send_nop_out_err;
473 }
474 else
475 break;
476 }
477
478upiu_send_nop_out_err:
479 return ret;
480}
481
482int utp_build_query_req_upiu(struct upiu_trans_mgmt_query_hdr *req_upiu,
483 struct upiu_req_build_type *upiu_data)
484{
485 req_upiu->opcode = upiu_data->opcode;
486 req_upiu->idn = upiu_data->idn;
487 req_upiu->index = upiu_data->index;
488 req_upiu->selector = upiu_data->selector;
489 req_upiu->resp_len = BE16(upiu_data->resp_data_len);
490
491 switch (upiu_data->opcode)
492 {
493 case UPIU_QUERY_OP_READ_FLAG:
494 case UPIU_QUERY_OP_READ_DESCRIPTOR:
495 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_READ_REQ;
496 break;
497 case UPIU_QUERY_OP_TOGGLE_FLAG:
498 case UPIU_QUERY_OP_CLEAR_FLAG:
499 case UPIU_QUERY_OP_SET_FLAG:
500 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_WRITE_REQ;
501 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800502 default:
503 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
504 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700505 }
506
507 return UFS_SUCCESS;
508}