blob: 308ffeef2bba82f527b5c7473a20479b6db17664 [file] [log] [blame]
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -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 <arch/ops.h>
30#include <sys/types.h>
31#include <kernel/thread.h>
32#include <debug.h>
33#include <err.h>
34#include <reg.h>
35#include <string.h>
36#include <malloc.h>
37#include <stdlib.h>
38#include <ufs_hw.h>
39#include <utp.h>
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -070040#include <ufs.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070041#include <platform/iomap.h>
42#include <platform/clock.h>
Sridhar Parasuramc02d1072014-11-06 12:55:42 -080043#include <platform/timer.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070044#include <arch/ops.h>
45#include <endian.h>
46#include <stdlib.h>
47#include <sys/types.h>
48
49void utp_process_req_completion(struct ufs_req_irq_type *irq)
50{
51 struct ufs_req_node *req;
52 struct list_node *prev;
53 uint32_t val;
54
55 /* Make sure we have more nodes than just the head in the list. */
56 if (list_next(irq->list, irq->list) == NULL)
57 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080058 dprintf(CRITICAL, "%s:%d UTRD/ UTMRD processed signalled and the wait queue is empty\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070059 ASSERT(0);
60 }
61
62 /* Read the door bell register. */
63 val = readl(irq->door_bell_reg);
64
65 list_for_every_entry(irq->list, req, struct ufs_req_node, list_node)
66 {
67 if (!(req->door_bell_bit & val))
68 {
69 /* Transaction is complete: Either transaction completed in a normal way.
70 * Delete and Signal all requests that have completed.
71 */
72 prev = req->list_node.prev;
73 /* TODO: move delete to the caller function. */
74 list_delete(&(req->list_node));
75
76 if (event_signal(req->event, false))
77 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080078 dprintf(CRITICAL, "%s:%d Event signal failed.\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070079 ASSERT(0);
80
81 }
82 req = containerof(prev, struct ufs_req_node, list_node);
83 }
84 }
85
86 return;
87}
88
89/* Always called within critical section: utrd_bitmap_mutex/ utmrd_bitmap_mutex. */
90static uint32_t utp_get_door_bell_bit(uint32_t reg, uint32_t *reg_bitmap, uint32_t *bit_num)
91{
92 uint32_t val = 0;
93 uint32_t doorbell_bit_val;
94 uint32_t found = 0;
95
96 *bit_num = 0;
97
98 val = readl(reg) | *reg_bitmap;
99 doorbell_bit_val = 1;
100
101 /* Find an empty slot. */
102 do
103 {
104 (*bit_num)++;
105
106 if (!(doorbell_bit_val & val))
107 {
108 found = 1;
109 *reg_bitmap |= doorbell_bit_val;
110 break;
111 }
112 doorbell_bit_val <<= 1;
113 }while (doorbell_bit_val <= (uint32_t) (1 << 31));
114
115 if (!found)
116 {
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700117 doorbell_bit_val = 0;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800118 dprintf(CRITICAL, "%s:%d Unable to find a free slot for transaction.\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700119 }
120
121 return doorbell_bit_val;
122}
123
124static void utp_ring_door_bell(uint32_t reg, uint32_t doorbell_bit)
125{
126 writel(doorbell_bit, reg);
127}
128
129static int utp_utrd_process_timeout_req(struct ufs_dev *dev,
130 struct utp_utrd_req_build_type *utrd_req,
131 struct ufs_req_node *req)
132{
133 switch (utrd_req->req_upiu->trans_type)
134 {
135 case UPIU_TYPE_NOP_OUT:
136 writel(~req->door_bell_bit, UFS_UTRLCLR(dev->base));
137 return -UFS_RETRY;
138 default:
139 /* TODO : Add ufs hci sw reset.*/
140 ASSERT(0);
141 return -UFS_FAILURE;
142 }
143}
144
145static int utp_remove_from_bitmap(struct utp_bitmap_access_type *req)
146{
147
148 if (mutex_acquire(req->mutx))
149 {
150 return -UFS_FAILURE;
151 }
152
153 *(req->bitmap) &= ~req->door_bell_bit;
154
155 if (mutex_release(req->mutx))
156 {
157 return -UFS_FAILURE;
158 }
159
160 return UFS_SUCCESS;
161}
162
163static void utp_enqueue_utrd_fill_desc(struct utp_trans_req_desc *desc, struct utp_utrd_req_build_type *utrd_req)
164{
165 /* Fill transfer desc. */
166 memset(desc, 0, UPIU_HDR_LEN);
167 desc->cmd_type_dd_irq = UTP_REQ_BUILD_CMD_DD_IRQ_FIELD(utrd_req->cmd_type, utrd_req->dd, utrd_req->irq);
168 desc->overall_cmd_status = utrd_req->ocs;
169 /* Bits 0 - 6 are reserved in cmd_desc_base_addr[0] field. */
170 desc->cmd_desc_base_addr[0] = ((uint32_t) utrd_req->req_upiu) & 0xC0;
171 desc->cmd_desc_base_addr[1] = ((uint32_t) utrd_req->req_upiu >> 8) & 0xFF;
172 desc->cmd_desc_base_addr[2] = ((uint32_t) utrd_req->req_upiu >> 16) & 0xFF;
173 desc->cmd_desc_base_addr[3] = ((uint32_t) utrd_req->req_upiu >> 24) & 0xFF;
174 desc->resp_upiu_offset = ROUNDUP(utrd_req->req_upiu_len, UPIU_HDR_LEN) / 4;
175 desc->resp_upiu_len = utrd_req->resp_upiu_len;
176
177 if (utrd_req->dd != UTRD_NO_DATA_TRANSFER)
178 {
179 /* Data transfer command.
180 * Fill in PRDT data.
181 */
182 desc->prdt_offset = utrd_req->prdt_offset / 4;
183 desc->prdt_len = utrd_req->prdt_len;
184 }
185
186 /* Flush UTRD to memory. */
187 cache_clean_invalidate_unaligned_start_addr((addr_t)desc, sizeof(struct utp_trans_req_desc));
188}
189
190static struct utp_trans_req_desc* utp_get_desc_slot_addr(struct ufs_dev *dev, struct utp_utrd_req_build_type *utrd_req, uint32_t *door_bell_val)
191{
192 struct utp_trans_req_desc *desc = NULL;
193 uint32_t door_bell_slot;
194
195 if (mutex_acquire(&(dev->utrd_data.bitmap_mutex)))
196 {
197 goto utp_get_desc_slot_addr_err;
198 }
199
200 *door_bell_val = utp_get_door_bell_bit(UFS_UTRLDBR(dev->base), &dev->utrd_data.bitmap, &door_bell_slot);
201 if (!(*door_bell_val))
202 {
203 goto utp_get_desc_slot_addr_err;
204 }
205
206 if (mutex_release(&(dev->utrd_data.bitmap_mutex)))
207 {
208 goto utp_get_desc_slot_addr_err;
209 }
210
211 desc = (struct utp_trans_req_desc *) ((addr_t)dev->utrd_data.list_base_addr + (door_bell_slot - 1) * sizeof(struct utp_trans_req_desc));
212
213utp_get_desc_slot_addr_err:
214 return desc;
215}
216
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700217int utp_poll_utrd_complete(struct ufs_dev *dev)
218{
Mayank Groverce21a082017-10-18 14:10:50 +0530219 int ret = ERROR;
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700220 struct ufs_req_irq_type irq;
Sridhar Parasuramea079c02014-10-09 16:37:27 -0700221 uint32_t val, base, retry = 0;
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700222 base = dev->base;
223 val = readl(UFS_IS(base));
224 irq.irq_handled = 0;
225 /* Wait till the desc has been processed. */
226 while(((val & UFS_IS_UTRCS) == 0) && ((val & UFS_IS_UTMRCS) == 0))
227 {
228 val = readl(UFS_IS(base));
Sridhar Parasuramea079c02014-10-09 16:37:27 -0700229 retry++;
230 udelay(1);
231 if(retry == UTP_MAX_COMMAND_RETRY)
232 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800233 dprintf(CRITICAL, "%s:%d UTP command never completed.\n", __func__, __LINE__);
234 return ERR_TIMED_OUT;
Sridhar Parasuramea079c02014-10-09 16:37:27 -0700235 }
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700236#ifdef DEBUG_UFS
237 dprintf(INFO, "Waiting for UTRCS/URMRCS Completion...\n");
238#endif
239 }
240 if (readl(UFS_IS(base)) & UFS_IS_UTRCS)
241 {
242 val = readl(UFS_IS(base)) & UFS_IS_UTRCS;
243 writel(UFS_IS_UTRCS, UFS_IS(base));
244 irq.irq_handled = UFS_IS_UTRCS;
245 irq.list = &(dev->utrd_data.list_head.list_node);
246 irq.door_bell_reg = UFS_UTRLDBR(base);
247 utp_process_req_completion(&irq);
248 ret = INT_NO_RESCHEDULE;
249 }
250 else if (readl(UFS_IS(base)) & (UFS_IS_UTMRCS))
251 {
252 val = readl(UFS_IS(base)) & UFS_IS_UTMRCS;
253 writel(UFS_IS_UTMRCS, UFS_IS(base));
254 irq.irq_handled = UFS_IS_UTMRCS;
255 irq.list = &(dev->utmrd_data.list_head.list_node);
256 utp_process_req_completion(&irq);
257 ret = INT_NO_RESCHEDULE;
258 }
259 return ret;
260}
261
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700262static int utp_enqueue_utrd(struct ufs_dev *dev, struct utp_utrd_req_build_type *utrd_req)
263{
264 int ret;
265 struct utp_trans_req_desc *desc;
266 event_t utrd_evt;
Mayank Groverce21a082017-10-18 14:10:50 +0530267 struct ufs_req_node *req;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700268 uint32_t door_bell_bit_val;
269 struct utp_bitmap_access_type bitmap_req;
270
271 ret = UFS_SUCCESS;
Mayank Groverce21a082017-10-18 14:10:50 +0530272 req = (struct ufs_req_node *)malloc(sizeof(struct ufs_req_node));
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700273
274 event_init(&utrd_evt, false, EVENT_FLAG_AUTOUNSIGNAL);
275
276 desc = utp_get_desc_slot_addr(dev, utrd_req, &door_bell_bit_val);
277 if (!desc)
278 {
279 ret = UFS_FAILURE;
280 goto utp_enqueue_utrd_err;
281 }
282
283 /* Check register UTRLRSR and make sure it is read ‘1’ before continuing. */
284 if (!readl(UFS_UTRLRSR(dev->base)))
285 {
286 ret = -UFS_FAILURE;
287 goto utp_enqueue_utrd_err;
288 }
289
290 utp_enqueue_utrd_fill_desc(desc, utrd_req);
291
Mayank Groverce21a082017-10-18 14:10:50 +0530292 req->door_bell_bit = door_bell_bit_val;
293 req->event = &utrd_evt;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700294
295 /* Enqueue the req in the device utrd list. */
Mayank Groverce21a082017-10-18 14:10:50 +0530296 list_add_head(&(dev->utrd_data.list_head.list_node), &(req->list_node));
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700297
298 dsb();
299
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700300#ifdef DEBUG_UFS
301 // print IS before write
302 ufs_dump_is_register(dev);
303#endif
304
305 utp_ring_door_bell(UFS_UTRLDBR(dev->base), door_bell_bit_val);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700306
307 dsb();
308
Sridhar Parasuram7357e9b2014-10-01 12:19:11 -0700309#ifdef DEBUG_UFS
310 // print IS after write
311 ufs_dump_is_register(dev);
312#endif
313 ret = utp_poll_utrd_complete(dev);
314
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800315 if (ret == ERR_TIMED_OUT)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700316 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800317 /* Transaction not completed even after timeout ms. */
318 dprintf(CRITICAL, "%s:%d Transaction timeout after polling %d times\n",__func__, __LINE__, UTP_MAX_COMMAND_RETRY);
Mayank Groverce21a082017-10-18 14:10:50 +0530319 ret = utp_utrd_process_timeout_req(dev, utrd_req, req);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700320 goto utp_enqueue_utrd_err;
321 }
322 else
323 {
324 /* Reset ret before returning. */
325 ret = UFS_SUCCESS;
326
327 /* Force read UTRD from memory. */
328 dsb();
329 cache_clean_invalidate_unaligned_start_addr((addr_t) desc, sizeof(struct ufs_req_node));
330
331 /* Check the response. */
332 if (desc->overall_cmd_status != UTRD_OCS_SUCCESS)
333 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800334 dprintf(CRITICAL, "%s:%d Command failed. command type = %x\n", __func__, __LINE__, utrd_req->cmd_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700335 ret = -UFS_FAILURE;
336 goto utp_enqueue_utrd_err;
337 }
338 }
339
340 /* Signal slot as free. */
341 bitmap_req.bitmap = &dev->utrd_data.bitmap;
Mayank Groverce21a082017-10-18 14:10:50 +0530342 bitmap_req.door_bell_bit = req->door_bell_bit;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700343 bitmap_req.mutx = &(dev->utrd_data.bitmap_mutex);
344
345 ret = utp_remove_from_bitmap(&bitmap_req);
346 if (ret)
347 goto utp_enqueue_utrd_err;
348
349utp_enqueue_utrd_err:
350 return ret;
351}
352
353static int utp_get_prdt_len(uint32_t data_len, uint32_t *num_prdt)
354{
355 /* Calculate the prdt entries required. */
356 *num_prdt = ROUNDUP(data_len, UTP_MAX_PRD_DATA_BYTE_CNT);
357 *num_prdt >>= UTP_MAX_PRD_DATA_BYTE_CNT_BYTE_SHIFT;
358
359 if (*num_prdt > UTP_MAX_PRD_TABLE_ENTRIES)
360 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800361 dprintf(CRITICAL, "%s:%d Data length exceeds for a single upiu transfer.\n", __func__,__LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700362 return -UFS_FAILURE;
363 }
364
365 return UFS_SUCCESS;
366}
367
368static int utp_fill_req_upiu(struct ufs_dev *dev, struct upiu_req_build_type *upiu_data, struct upiu_gen_hdr *req_upiu)
369{
370 memset(req_upiu, 0, UPIU_HDR_LEN);
371
372 if (upiu_data->trans_type == UPIU_TYPE_QUERY_REQ)
373 {
374 /* Fill in query specific fields. */
375 if (utp_build_query_req_upiu((struct upiu_trans_mgmt_query_hdr *) req_upiu, upiu_data))
376 {
377 return -UFS_FAILURE;
378 }
379 }
380
381 /* If a data transfer cmd, check the alignment and length of the buffer. */
382 if (upiu_data->expected_data_len)
383 {
384 if (upiu_data->data_buffer_addr & 0x3)
385 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800386 dprintf(CRITICAL, "%s:%d Alignment and length check failed for data tranfer command.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700387 return -UFS_FAILURE;
388 }
389 }
390
391 req_upiu->basic_hdr.trans_type = upiu_data->trans_type;
392 req_upiu->basic_hdr.flags = upiu_data->flags;
393 req_upiu->basic_hdr.cmd_set_type = upiu_data->cmd_set_type;
394 req_upiu->basic_hdr.data_seg_len = upiu_data->data_seg_len;
395 req_upiu->basic_hdr.lun = upiu_data->lun;
396 req_upiu->basic_hdr.total_ehs_len = upiu_data->ehs_len;
397 req_upiu->basic_hdr.task_tag = atomic_add((int *) &(dev->utrd_data.task_id), 1);
398 if (upiu_data->cdb)
399 memcpy(&(req_upiu->trans_specific_fields[4]), (void *) upiu_data->cdb, 16);
400 /* If command upiu, fill in data length. */
401 if (req_upiu->basic_hdr.trans_type == UPIU_TYPE_COMMAND)
402 ((struct upiu_cmd_hdr *)req_upiu)->data_expected_len = BE32(upiu_data->expected_data_len);
403
404 return UFS_SUCCESS;
405
406}
407
408static void utp_fill_utrd_properties(struct upiu_req_build_type *upiu_data,
409 struct utp_utrd_req_build_type *utrd,
410 struct utrd_cmd_desc *cmd_desc)
411{
412 utrd->cmd_type = upiu_data->cmd_type;
413 utrd->dd = upiu_data->dd;
414 utrd->irq = UTRD_IRQ_CMD;
415 utrd->prdt_offset = UPIU_HDR_LEN + cmd_desc->resp_upiu_len;
416 utrd->prdt_len = cmd_desc->num_prdt;
417 utrd->req_upiu = (struct upiu_basic_hdr *) cmd_desc->req_upiu;
418 utrd->req_upiu_len = UPIU_HDR_LEN;
419 utrd->resp_upiu_len = cmd_desc->resp_upiu_len;
420 utrd->ocs = 0xF;
421 utrd->timeout = upiu_data->timeout_msecs;
422}
423
424static void utp_fill_prdt_entries(struct upiu_req_build_type *upiu_data, struct utp_prdt_entry *prdt_entry)
425{
426 uint64_t buf;
427 uint64_t bytes_remaining;
428 uint32_t prd_dbc;
429
430 buf = upiu_data->data_buffer_addr;
431 bytes_remaining = upiu_data->expected_data_len;
432
433 while (bytes_remaining)
434 {
435 prdt_entry->data_base_addr = buf;
436 prdt_entry->data_upper_addr = buf >> 32;
437 prd_dbc = MIN(UTP_MAX_PRD_DATA_BYTE_CNT, bytes_remaining) - 1;
438 prdt_entry->data_byte_cnt = prd_dbc;
439 if (bytes_remaining <= UTP_MAX_PRD_DATA_BYTE_CNT)
440 break;
441 buf += UTP_MAX_PRD_DATA_BYTE_CNT;
442 bytes_remaining -= UTP_MAX_PRD_DATA_BYTE_CNT;
443 prdt_entry++;
444 }
445
446}
447
448int utp_enqueue_upiu(struct ufs_dev *dev, struct upiu_req_build_type *upiu_data)
449{
450 struct upiu_gen_hdr *req_upiu;
451 struct utp_utrd_req_build_type utrd;
452 uint32_t num_prdt;
453 struct utp_prdt_entry *prdt_entry;
454 int ret = UFS_SUCCESS;
455 uint32_t resp_len;
456 uint32_t cmd_desc_len;
457 struct utrd_cmd_desc cmd_desc;
458
459 /* Round up resp_upiu_len to a DWORD boundary.
460 * Also, make sure it is of min required length.
461 */
462 resp_len = ROUNDUP(upiu_data->resp_data_len, 4) + UPIU_HDR_LEN;
463
464 if (utp_get_prdt_len(upiu_data->expected_data_len, &num_prdt))
465 return -UFS_FAILURE;
466
467 /* Calculate the length. */
468 cmd_desc_len = UPIU_HDR_LEN + resp_len + num_prdt * sizeof(struct utp_prdt_entry);
469
470 /* Allocate memory for UTP Command Descriptor. */
471 req_upiu = (struct upiu_gen_hdr*) memalign((size_t ) lcm(CACHE_LINE, UTP_CMD_DESC_BASE_ALIGNMENT_SIZE), ROUNDUP(cmd_desc_len, CACHE_LINE));
472 if (!req_upiu)
473 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800474 dprintf(CRITICAL, "%s:%d Unable to allocate request upiu\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700475 return -UFS_FAILURE;
476 }
477
478 /* Fill req upiu. */
479 ret = utp_fill_req_upiu(dev, upiu_data, req_upiu);
480 if (ret)
481 {
482 goto utp_enqueue_upiu_err;
483 }
484
485 /* Fill UTRD properties. */
486 cmd_desc.num_prdt = num_prdt;
487 cmd_desc.req_upiu = req_upiu;
488 cmd_desc.resp_upiu_len = resp_len;
489 utp_fill_utrd_properties(upiu_data, &utrd, &cmd_desc);
490
491 prdt_entry = (struct utp_prdt_entry *) ((uint32_t) req_upiu + UPIU_HDR_LEN + resp_len);
492
493 /* Fill PRDT entries. */
494 if (num_prdt)
495 utp_fill_prdt_entries(upiu_data, prdt_entry);
496
497 /* Flush req_upiu */
498 dsb();
499 arch_clean_invalidate_cache_range((addr_t) req_upiu, cmd_desc_len);
500
501 /* Check the response. */
502 ret = utp_enqueue_utrd(dev, &utrd);
503 if (ret)
504 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800505 dprintf(CRITICAL, "%s:%d Command failed. command = %x\n", __func__, __LINE__, req_upiu->basic_hdr.trans_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700506 goto utp_enqueue_upiu_err;
507 }
508
509 /* UPIU processed. Invalidate cache to update resp. */
510 arch_invalidate_cache_range((addr_t) req_upiu, cmd_desc_len);
511
512 /* Save the response. */
513 memcpy(upiu_data->resp_ptr, (void *) ((uint32_t)req_upiu + UPIU_HDR_LEN), upiu_data->resp_len);
514 memcpy((void *) upiu_data->resp_data_ptr, (void *) ((uint32_t)req_upiu + 2 * UPIU_HDR_LEN), upiu_data->resp_data_len);
515
516utp_enqueue_upiu_err:
517 free(req_upiu);
518 return ret;
519}