blob: 195799e0eae30015759a8cc30a3d272f762d5512 [file] [log] [blame]
Skylar Changc01a7f42017-06-22 19:59:57 -07001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Amir Levy9659e592016-10-27 18:08:27 +03002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/delay.h>
14#include <linux/ipa_mhi.h>
15#include <linux/ipa.h>
16#include "../ipa_v3/ipa_i.h"
17#include "../../gsi/gsi.h"
18#include "../../gsi/gsi_reg.h"
19#include "ipa_ut_framework.h"
20
21#define IPA_MHI_TEST_NUM_CHANNELS 8
22#define IPA_MHI_TEST_NUM_EVENT_RINGS 8
23#define IPA_MHI_TEST_FIRST_CHANNEL_ID 100
24#define IPA_MHI_TEST_FIRST_EVENT_RING_ID 100
25#define IPA_MHI_TEST_LAST_CHANNEL_ID \
26 (IPA_MHI_TEST_FIRST_CHANNEL_ID + IPA_MHI_TEST_NUM_CHANNELS - 1)
27#define IPA_MHI_TEST_LAST_EVENT_RING_ID \
28 (IPA_MHI_TEST_FIRST_EVENT_RING_ID + IPA_MHI_TEST_NUM_EVENT_RINGS - 1)
29#define IPA_MHI_TEST_MAX_DATA_BUF_SIZE 1500
30#define IPA_MHI_TEST_SEQ_TYPE_DMA 0x00000000
31
32#define IPA_MHI_TEST_LOOP_NUM 5
33#define IPA_MHI_RUN_TEST_UNIT_IN_LOOP(test_unit, rc, args...) \
34 do { \
35 int __i; \
36 for (__i = 0; __i < IPA_MHI_TEST_LOOP_NUM; __i++) { \
37 IPA_UT_LOG(#test_unit " START iter %d\n", __i); \
38 rc = test_unit(args); \
39 if (!rc) \
40 continue; \
41 IPA_UT_LOG(#test_unit " failed %d\n", rc); \
42 break; \
43 } \
44 } while (0)
45
46/**
47 * check for MSI interrupt for one or both channels:
48 * OUT channel MSI my be missed as it
49 * will be overwritten by the IN channel MSI
50 */
51#define IPA_MHI_TEST_CHECK_MSI_INTR(__both, __timeout) \
52 do { \
53 int i; \
54 for (i = 0; i < 20; i++) { \
55 if (*((u32 *)test_mhi_ctx->msi.base) == \
56 (0x10000000 | \
57 (IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1))) { \
58 __timeout = false; \
59 break; \
60 } \
61 if (__both && (*((u32 *)test_mhi_ctx->msi.base) == \
62 (0x10000000 | \
63 (IPA_MHI_TEST_FIRST_EVENT_RING_ID)))) { \
64 /* sleep to be sure IN MSI is generated */ \
65 msleep(20); \
66 __timeout = false; \
67 break; \
68 } \
69 msleep(20); \
70 } \
71 } while (0)
72
73static DECLARE_COMPLETION(mhi_test_ready_comp);
74static DECLARE_COMPLETION(mhi_test_wakeup_comp);
75
76/**
77 * enum ipa_mhi_ring_elements_type - MHI ring elements types.
78 */
79enum ipa_mhi_ring_elements_type {
80 IPA_MHI_RING_ELEMENT_NO_OP = 1,
81 IPA_MHI_RING_ELEMENT_TRANSFER = 2
82};
83
84/**
85 * enum ipa_mhi_channel_direction - MHI channel directions
86 */
87enum ipa_mhi_channel_direction {
88 IPA_MHI_OUT_CHAHNNEL = 1,
89 IPA_MHI_IN_CHAHNNEL = 2,
90};
91
92/**
93 * struct ipa_mhi_channel_context_array - MHI Channel context array entry
94 *
95 * mapping is taken from MHI spec
96 */
97struct ipa_mhi_channel_context_array {
98 u32 chstate:8; /*0-7*/
99 u32 brsmode:2; /*8-9*/
100 u32 pollcfg:6; /*10-15*/
101 u32 reserved:16; /*16-31*/
102 u32 chtype; /*channel type (inbound/outbound)*/
103 u32 erindex; /*event ring index*/
104 u64 rbase; /*ring base address in the host addr spc*/
105 u64 rlen; /*ring length in bytes*/
106 u64 rp; /*read pointer in the host system addr spc*/
107 u64 wp; /*write pointer in the host system addr spc*/
108} __packed;
109
110/**
111 * struct ipa_mhi_event_context_array - MGI event ring context array entry
112 *
113 * mapping is taken from MHI spec
114 */
115struct ipa_mhi_event_context_array {
116 u16 intmodc;
117 u16 intmodt;/* Interrupt moderation timer (in microseconds) */
118 u32 ertype;
119 u32 msivec; /* MSI vector for interrupt (MSI data)*/
120 u64 rbase; /* ring base address in host address space*/
121 u64 rlen; /* ring length in bytes*/
122 u64 rp; /* read pointer in the host system address space*/
123 u64 wp; /* write pointer in the host system address space*/
124} __packed;
125
126/**
127 *
128 * struct ipa_mhi_mmio_register_set - MHI configuration registers,
129 * control registers, status registers, pointers to doorbell arrays,
130 * pointers to channel and event context arrays.
131 *
132 * The structure is defined in mhi spec (register names are taken from there).
133 * Only values accessed by HWP or test are documented
134 */
135struct ipa_mhi_mmio_register_set {
136 u32 mhireglen;
137 u32 reserved_08_04;
138 u32 mhiver;
139 u32 reserved_10_0c;
140 struct mhicfg {
141 u8 nch;
142 u8 reserved_15_8;
143 u8 ner;
144 u8 reserved_31_23;
145 } __packed mhicfg;
146
147 u32 reserved_18_14;
148 u32 chdboff;
149 u32 reserved_20_1C;
150 u32 erdboff;
151 u32 reserved_28_24;
152 u32 bhioff;
153 u32 reserved_30_2C;
154 u32 debugoff;
155 u32 reserved_38_34;
156
157 struct mhictrl {
158 u32 rs : 1;
159 u32 reset : 1;
160 u32 reserved_7_2 : 6;
161 u32 mhistate : 8;
162 u32 reserved_31_16 : 16;
163 } __packed mhictrl;
164
165 u64 reserved_40_3c;
166 u32 reserved_44_40;
167
168 struct mhistatus {
169 u32 ready : 1;
170 u32 reserved_3_2 : 1;
171 u32 syserr : 1;
172 u32 reserved_7_3 : 5;
173 u32 mhistate : 8;
174 u32 reserved_31_16 : 16;
175 } __packed mhistatus;
176
177 /**
178 * Register is not accessed by HWP.
179 * In test register carries the handle for
180 * the buffer of channel context array
181 */
182 u32 reserved_50_4c;
183
184 u32 mhierror;
185
186 /**
187 * Register is not accessed by HWP.
188 * In test register carries the handle for
189 * the buffer of event ring context array
190 */
191 u32 reserved_58_54;
192
193 /**
194 * 64-bit pointer to the channel context array in the host memory space
195 * host sets the pointer to the channel context array during
196 * initialization.
197 */
198 u64 ccabap;
199 /**
200 * 64-bit pointer to the event context array in the host memory space
201 * host sets the pointer to the event context array during
202 * initialization
203 */
204 u64 ecabap;
205 /**
206 * Register is not accessed by HWP.
207 * In test register carries the pointer of virtual address
208 * for the buffer of channel context array
209 */
210 u64 crcbap;
211 /**
212 * Register is not accessed by HWP.
213 * In test register carries the pointer of virtual address
214 * for the buffer of event ring context array
215 */
216 u64 crdb;
217
218 u64 reserved_80_78;
219
220 struct mhiaddr {
221 /**
222 * Base address (64-bit) of the memory region in
223 * the host address space where the MHI control
224 * data structures are allocated by the host,
225 * including channel context array, event context array,
226 * and rings.
227 * The device uses this information to set up its internal
228 * address translation tables.
229 * value must be aligned to 4 Kbytes.
230 */
231 u64 mhicrtlbase;
232 /**
233 * Upper limit address (64-bit) of the memory region in
234 * the host address space where the MHI control
235 * data structures are allocated by the host.
236 * The device uses this information to setup its internal
237 * address translation tables.
238 * The most significant 32 bits of MHICTRLBASE and
239 * MHICTRLLIMIT registers must be equal.
240 */
241 u64 mhictrllimit;
242 u64 reserved_18_10;
243 /**
244 * Base address (64-bit) of the memory region in
245 * the host address space where the MHI data buffers
246 * are allocated by the host.
247 * The device uses this information to setup its
248 * internal address translation tables.
249 * value must be aligned to 4 Kbytes.
250 */
251 u64 mhidatabase;
252 /**
253 * Upper limit address (64-bit) of the memory region in
254 * the host address space where the MHI data buffers
255 * are allocated by the host.
256 * The device uses this information to setup its
257 * internal address translation tables.
258 * The most significant 32 bits of MHIDATABASE and
259 * MHIDATALIMIT registers must be equal.
260 */
261 u64 mhidatalimit;
262 u64 reserved_30_28;
263 } __packed mhiaddr;
264
265} __packed;
266
267/**
268 * struct ipa_mhi_event_ring_element - MHI Event ring element
269 *
270 * mapping is taken from MHI spec
271 */
272struct ipa_mhi_event_ring_element {
273 /**
274 * pointer to ring element that generated event in
275 * the host system address space
276 */
277 u64 ptr;
278 union {
279 struct {
280 u32 len : 24;
281 u32 code : 8;
282 } __packed bits;
283 u32 dword;
284 } __packed dword_8;
285 u16 reserved;
286 u8 type;
287 u8 chid;
288} __packed;
289
290/**
291* struct ipa_mhi_transfer_ring_element - MHI Transfer ring element
292*
293* mapping is taken from MHI spec
294*/
295struct ipa_mhi_transfer_ring_element {
296 u64 ptr; /*pointer to buffer in the host system address space*/
297 u16 len; /*transaction length in bytes*/
298 u16 reserved0;
299 union {
300 struct {
301 u16 chain : 1;
302 u16 reserved_7_1 : 7;
303 u16 ieob : 1;
304 u16 ieot : 1;
305 u16 bei : 1;
306 u16 reserved_15_11 : 5;
307 } __packed bits;
308 u16 word;
309 } __packed word_C;
310 u8 type;
311 u8 reserved1;
312} __packed;
313
314/**
315 * struct ipa_test_mhi_context - MHI test context
316 */
317struct ipa_test_mhi_context {
318 void __iomem *gsi_mmio;
319 struct ipa_mem_buffer msi;
320 struct ipa_mem_buffer ch_ctx_array;
321 struct ipa_mem_buffer ev_ctx_array;
322 struct ipa_mem_buffer mmio_buf;
323 struct ipa_mem_buffer xfer_ring_bufs[IPA_MHI_TEST_NUM_CHANNELS];
324 struct ipa_mem_buffer ev_ring_bufs[IPA_MHI_TEST_NUM_EVENT_RINGS];
325 struct ipa_mem_buffer in_buffer;
326 struct ipa_mem_buffer out_buffer;
327 u32 prod_hdl;
328 u32 cons_hdl;
Skylar Changc01a7f42017-06-22 19:59:57 -0700329 u32 test_prod_hdl;
Amir Levy9659e592016-10-27 18:08:27 +0300330};
331
332static struct ipa_test_mhi_context *test_mhi_ctx;
333
334static void ipa_mhi_test_cb(void *priv,
335 enum ipa_mhi_event_type event, unsigned long data)
336{
337 IPA_UT_DBG("Entry\n");
338
339 if (event == IPA_MHI_EVENT_DATA_AVAILABLE)
340 complete_all(&mhi_test_wakeup_comp);
341 else if (event == IPA_MHI_EVENT_READY)
342 complete_all(&mhi_test_ready_comp);
343 else
344 WARN_ON(1);
345}
346
347static void ipa_test_mhi_free_mmio_space(void)
348{
349 IPA_UT_DBG("Entry\n");
350
351 if (!test_mhi_ctx)
352 return;
353
354 dma_free_coherent(ipa3_ctx->pdev, test_mhi_ctx->mmio_buf.size,
355 test_mhi_ctx->mmio_buf.base,
356 test_mhi_ctx->mmio_buf.phys_base);
357
358 dma_free_coherent(ipa3_ctx->pdev, test_mhi_ctx->ev_ctx_array.size,
359 test_mhi_ctx->ev_ctx_array.base,
360 test_mhi_ctx->ev_ctx_array.phys_base);
361
362 dma_free_coherent(ipa3_ctx->pdev, test_mhi_ctx->ch_ctx_array.size,
363 test_mhi_ctx->ch_ctx_array.base,
364 test_mhi_ctx->ch_ctx_array.phys_base);
365
366 dma_free_coherent(ipa3_ctx->pdev, test_mhi_ctx->msi.size,
367 test_mhi_ctx->msi.base, test_mhi_ctx->msi.phys_base);
368}
369
370static int ipa_test_mhi_alloc_mmio_space(void)
371{
372 int rc = 0;
373 struct ipa_mem_buffer *msi;
374 struct ipa_mem_buffer *ch_ctx_array;
375 struct ipa_mem_buffer *ev_ctx_array;
376 struct ipa_mem_buffer *mmio_buf;
377 struct ipa_mhi_mmio_register_set *p_mmio;
378
379 IPA_UT_DBG("Entry\n");
380
381 msi = &test_mhi_ctx->msi;
382 ch_ctx_array = &test_mhi_ctx->ch_ctx_array;
383 ev_ctx_array = &test_mhi_ctx->ev_ctx_array;
384 mmio_buf = &test_mhi_ctx->mmio_buf;
385
386 /* Allocate MSI */
387 msi->size = 4;
388 msi->base = dma_alloc_coherent(ipa3_ctx->pdev, msi->size,
389 &msi->phys_base, GFP_KERNEL);
390 if (!msi->base) {
391 IPA_UT_ERR("no mem for msi\n");
392 return -ENOMEM;
393 }
394
395 IPA_UT_DBG("msi: base 0x%pK phys_addr 0x%pad size %d\n",
396 msi->base, &msi->phys_base, msi->size);
397
398 /* allocate buffer for channel context */
399 ch_ctx_array->size = sizeof(struct ipa_mhi_channel_context_array) *
400 IPA_MHI_TEST_NUM_CHANNELS;
401 ch_ctx_array->base = dma_alloc_coherent(ipa3_ctx->pdev,
402 ch_ctx_array->size, &ch_ctx_array->phys_base, GFP_KERNEL);
403 if (!ch_ctx_array->base) {
404 IPA_UT_ERR("no mem for ch ctx array\n");
405 rc = -ENOMEM;
406 goto fail_free_msi;
407 }
408 IPA_UT_DBG("channel ctx array: base 0x%pK phys_addr %pad size %d\n",
409 ch_ctx_array->base, &ch_ctx_array->phys_base,
410 ch_ctx_array->size);
411
412 /* allocate buffer for event context */
413 ev_ctx_array->size = sizeof(struct ipa_mhi_event_context_array) *
414 IPA_MHI_TEST_NUM_EVENT_RINGS;
415 ev_ctx_array->base = dma_alloc_coherent(ipa3_ctx->pdev,
416 ev_ctx_array->size, &ev_ctx_array->phys_base, GFP_KERNEL);
417 if (!ev_ctx_array->base) {
418 IPA_UT_ERR("no mem for ev ctx array\n");
419 rc = -ENOMEM;
420 goto fail_free_ch_ctx_arr;
421 }
422 IPA_UT_DBG("event ctx array: base 0x%pK phys_addr %pad size %d\n",
423 ev_ctx_array->base, &ev_ctx_array->phys_base,
424 ev_ctx_array->size);
425
426 /* allocate buffer for mmio */
427 mmio_buf->size = sizeof(struct ipa_mhi_mmio_register_set);
428 mmio_buf->base = dma_alloc_coherent(ipa3_ctx->pdev, mmio_buf->size,
429 &mmio_buf->phys_base, GFP_KERNEL);
430 if (!mmio_buf->base) {
431 IPA_UT_ERR("no mem for mmio buf\n");
432 rc = -ENOMEM;
433 goto fail_free_ev_ctx_arr;
434 }
435 IPA_UT_DBG("mmio buffer: base 0x%pK phys_addr %pad size %d\n",
436 mmio_buf->base, &mmio_buf->phys_base, mmio_buf->size);
437
438 /* initlize table */
439 p_mmio = (struct ipa_mhi_mmio_register_set *)mmio_buf->base;
440
441 /**
442 * 64-bit pointer to the channel context array in the host memory space;
443 * Host sets the pointer to the channel context array
444 * during initialization.
445 */
446 p_mmio->ccabap = (u32)ch_ctx_array->phys_base -
447 (IPA_MHI_TEST_FIRST_CHANNEL_ID *
448 sizeof(struct ipa_mhi_channel_context_array));
449 IPA_UT_DBG("pMmio->ccabap 0x%llx\n", p_mmio->ccabap);
450
451 /**
452 * 64-bit pointer to the event context array in the host memory space;
453 * Host sets the pointer to the event context array
454 * during initialization
455 */
456 p_mmio->ecabap = (u32)ev_ctx_array->phys_base -
457 (IPA_MHI_TEST_FIRST_EVENT_RING_ID *
458 sizeof(struct ipa_mhi_event_context_array));
459 IPA_UT_DBG("pMmio->ecabap 0x%llx\n", p_mmio->ecabap);
460
461 /**
462 * Register is not accessed by HWP.
463 * In test register carries the pointer of
464 * virtual address for the buffer of channel context array
465 */
466 p_mmio->crcbap = (unsigned long)ch_ctx_array->base;
467
468 /**
469 * Register is not accessed by HWP.
470 * In test register carries the pointer of
471 * virtual address for the buffer of channel context array
472 */
473 p_mmio->crdb = (unsigned long)ev_ctx_array->base;
474
475 /* test is running only on device. no need to translate addresses */
476 p_mmio->mhiaddr.mhicrtlbase = 0x04;
477 p_mmio->mhiaddr.mhictrllimit = 0xFFFFFFFF;
478 p_mmio->mhiaddr.mhidatabase = 0x04;
479 p_mmio->mhiaddr.mhidatalimit = 0xFFFFFFFF;
480
481 return rc;
482
483fail_free_ev_ctx_arr:
484 dma_free_coherent(ipa3_ctx->pdev, ev_ctx_array->size,
485 ev_ctx_array->base, ev_ctx_array->phys_base);
486 ev_ctx_array->base = NULL;
487fail_free_ch_ctx_arr:
488 dma_free_coherent(ipa3_ctx->pdev, ch_ctx_array->size,
489 ch_ctx_array->base, ch_ctx_array->phys_base);
490 ch_ctx_array->base = NULL;
491fail_free_msi:
492 dma_free_coherent(ipa3_ctx->pdev, msi->size, msi->base,
493 msi->phys_base);
494 msi->base = NULL;
495 return rc;
496}
497
498static void ipa_mhi_test_destroy_channel_context(
499 struct ipa_mem_buffer transfer_ring_bufs[],
500 struct ipa_mem_buffer event_ring_bufs[],
501 u8 channel_id,
502 u8 event_ring_id)
503{
504 u32 ev_ring_idx;
505 u32 ch_idx;
506
507 IPA_UT_DBG("Entry\n");
508
509 if ((channel_id < IPA_MHI_TEST_FIRST_CHANNEL_ID) ||
510 (channel_id > IPA_MHI_TEST_LAST_CHANNEL_ID)) {
511 IPA_UT_ERR("channal_id invalid %d\n", channel_id);
512 return;
513 }
514
515 if ((event_ring_id < IPA_MHI_TEST_FIRST_EVENT_RING_ID) ||
516 (event_ring_id > IPA_MHI_TEST_LAST_EVENT_RING_ID)) {
517 IPA_UT_ERR("event_ring_id invalid %d\n", event_ring_id);
518 return;
519 }
520
521 ch_idx = channel_id - IPA_MHI_TEST_FIRST_CHANNEL_ID;
522 ev_ring_idx = event_ring_id - IPA_MHI_TEST_FIRST_EVENT_RING_ID;
523
524 if (transfer_ring_bufs[ch_idx].base) {
525 dma_free_coherent(ipa3_ctx->pdev,
526 transfer_ring_bufs[ch_idx].size,
527 transfer_ring_bufs[ch_idx].base,
528 transfer_ring_bufs[ch_idx].phys_base);
529 transfer_ring_bufs[ch_idx].base = NULL;
530 }
531
532 if (event_ring_bufs[ev_ring_idx].base) {
533 dma_free_coherent(ipa3_ctx->pdev,
534 event_ring_bufs[ev_ring_idx].size,
535 event_ring_bufs[ev_ring_idx].base,
536 event_ring_bufs[ev_ring_idx].phys_base);
537 event_ring_bufs[ev_ring_idx].base = NULL;
538 }
539}
540
541static int ipa_mhi_test_config_channel_context(
542 struct ipa_mem_buffer *mmio,
543 struct ipa_mem_buffer transfer_ring_bufs[],
544 struct ipa_mem_buffer event_ring_bufs[],
545 u8 channel_id,
546 u8 event_ring_id,
547 u16 transfer_ring_size,
548 u16 event_ring_size,
549 u8 ch_type)
550{
551 struct ipa_mhi_mmio_register_set *p_mmio;
552 struct ipa_mhi_channel_context_array *p_channels;
553 struct ipa_mhi_event_context_array *p_events;
554 u32 ev_ring_idx;
555 u32 ch_idx;
556
557 IPA_UT_DBG("Entry\n");
558
559 if ((channel_id < IPA_MHI_TEST_FIRST_CHANNEL_ID) ||
560 (channel_id > IPA_MHI_TEST_LAST_CHANNEL_ID)) {
561 IPA_UT_DBG("channal_id invalid %d\n", channel_id);
562 return -EFAULT;
563 }
564
565 if ((event_ring_id < IPA_MHI_TEST_FIRST_EVENT_RING_ID) ||
566 (event_ring_id > IPA_MHI_TEST_LAST_EVENT_RING_ID)) {
567 IPA_UT_DBG("event_ring_id invalid %d\n", event_ring_id);
568 return -EFAULT;
569 }
570
571 p_mmio = (struct ipa_mhi_mmio_register_set *)mmio->base;
572 p_channels =
573 (struct ipa_mhi_channel_context_array *)
574 ((unsigned long)p_mmio->crcbap);
575 p_events = (struct ipa_mhi_event_context_array *)
576 ((unsigned long)p_mmio->crdb);
577
578 IPA_UT_DBG("p_mmio: %pK p_channels: %pK p_events: %pK\n",
579 p_mmio, p_channels, p_events);
580
581 ch_idx = channel_id - IPA_MHI_TEST_FIRST_CHANNEL_ID;
582 ev_ring_idx = event_ring_id - IPA_MHI_TEST_FIRST_EVENT_RING_ID;
583
584 IPA_UT_DBG("ch_idx: %u ev_ring_idx: %u\n", ch_idx, ev_ring_idx);
585 if (transfer_ring_bufs[ch_idx].base) {
586 IPA_UT_ERR("ChannelId %d is already allocated\n", channel_id);
587 return -EFAULT;
588 }
589
590 /* allocate and init event ring if needed */
591 if (!event_ring_bufs[ev_ring_idx].base) {
592 IPA_UT_LOG("Configuring event ring...\n");
593 event_ring_bufs[ev_ring_idx].size =
594 event_ring_size *
595 sizeof(struct ipa_mhi_event_ring_element);
596 event_ring_bufs[ev_ring_idx].base =
597 dma_alloc_coherent(ipa3_ctx->pdev,
598 event_ring_bufs[ev_ring_idx].size,
599 &event_ring_bufs[ev_ring_idx].phys_base,
600 GFP_KERNEL);
601 if (!event_ring_bufs[ev_ring_idx].base) {
602 IPA_UT_ERR("no mem for ev ring buf\n");
603 return -ENOMEM;
604 }
605 p_events[ev_ring_idx].intmodc = 1;
606 p_events[ev_ring_idx].intmodt = 0;
607 p_events[ev_ring_idx].msivec = event_ring_id;
608 p_events[ev_ring_idx].rbase =
609 (u32)event_ring_bufs[ev_ring_idx].phys_base;
610 p_events[ev_ring_idx].rlen =
611 event_ring_bufs[ev_ring_idx].size;
612 p_events[ev_ring_idx].rp =
613 (u32)event_ring_bufs[ev_ring_idx].phys_base;
614 p_events[ev_ring_idx].wp =
Michael Adisumarta6f78ef42017-12-13 17:22:13 -0800615 (u32)event_ring_bufs[ev_ring_idx].phys_base +
616 event_ring_bufs[ev_ring_idx].size - 16;
Amir Levy9659e592016-10-27 18:08:27 +0300617 } else {
618 IPA_UT_LOG("Skip configuring event ring - already done\n");
619 }
620
621 transfer_ring_bufs[ch_idx].size =
622 transfer_ring_size *
623 sizeof(struct ipa_mhi_transfer_ring_element);
624 transfer_ring_bufs[ch_idx].base =
625 dma_alloc_coherent(ipa3_ctx->pdev,
626 transfer_ring_bufs[ch_idx].size,
627 &transfer_ring_bufs[ch_idx].phys_base,
628 GFP_KERNEL);
629 if (!transfer_ring_bufs[ch_idx].base) {
630 IPA_UT_ERR("no mem for xfer ring buf\n");
631 dma_free_coherent(ipa3_ctx->pdev,
632 event_ring_bufs[ev_ring_idx].size,
633 event_ring_bufs[ev_ring_idx].base,
634 event_ring_bufs[ev_ring_idx].phys_base);
635 event_ring_bufs[ev_ring_idx].base = NULL;
636 return -ENOMEM;
637 }
638
639 p_channels[ch_idx].erindex = event_ring_id;
640 p_channels[ch_idx].rbase = (u32)transfer_ring_bufs[ch_idx].phys_base;
641 p_channels[ch_idx].rlen = transfer_ring_bufs[ch_idx].size;
642 p_channels[ch_idx].rp = (u32)transfer_ring_bufs[ch_idx].phys_base;
643 p_channels[ch_idx].wp = (u32)transfer_ring_bufs[ch_idx].phys_base;
644 p_channels[ch_idx].chtype = ch_type;
645 p_channels[ch_idx].brsmode = IPA_MHI_BURST_MODE_DEFAULT;
646 p_channels[ch_idx].pollcfg = 0;
647
648 return 0;
649}
650
651static void ipa_mhi_test_destroy_data_structures(void)
652{
653 IPA_UT_DBG("Entry\n");
654
655 /* Destroy OUT data buffer */
656 if (test_mhi_ctx->out_buffer.base) {
657 dma_free_coherent(ipa3_ctx->pdev,
658 test_mhi_ctx->out_buffer.size,
659 test_mhi_ctx->out_buffer.base,
660 test_mhi_ctx->out_buffer.phys_base);
661 test_mhi_ctx->out_buffer.base = NULL;
662 }
663
664 /* Destroy IN data buffer */
665 if (test_mhi_ctx->in_buffer.base) {
666 dma_free_coherent(ipa3_ctx->pdev,
667 test_mhi_ctx->in_buffer.size,
668 test_mhi_ctx->in_buffer.base,
669 test_mhi_ctx->in_buffer.phys_base);
670 test_mhi_ctx->in_buffer.base = NULL;
671 }
672
673 /* Destroy IN channel ctx */
674 ipa_mhi_test_destroy_channel_context(
675 test_mhi_ctx->xfer_ring_bufs,
676 test_mhi_ctx->ev_ring_bufs,
677 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
678 IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1);
679
680 /* Destroy OUT channel ctx */
681 ipa_mhi_test_destroy_channel_context(
682 test_mhi_ctx->xfer_ring_bufs,
683 test_mhi_ctx->ev_ring_bufs,
684 IPA_MHI_TEST_FIRST_CHANNEL_ID,
685 IPA_MHI_TEST_FIRST_EVENT_RING_ID);
686}
687
688static int ipa_mhi_test_setup_data_structures(void)
689{
690 int rc = 0;
691
692 IPA_UT_DBG("Entry\n");
693
694 /* Config OUT Channel Context */
695 rc = ipa_mhi_test_config_channel_context(
696 &test_mhi_ctx->mmio_buf,
697 test_mhi_ctx->xfer_ring_bufs,
698 test_mhi_ctx->ev_ring_bufs,
699 IPA_MHI_TEST_FIRST_CHANNEL_ID,
700 IPA_MHI_TEST_FIRST_EVENT_RING_ID,
701 0x100,
702 0x80,
703 IPA_MHI_OUT_CHAHNNEL);
704 if (rc) {
705 IPA_UT_ERR("Fail to config OUT ch ctx - err %d", rc);
706 return rc;
707 }
708
709 /* Config IN Channel Context */
710 rc = ipa_mhi_test_config_channel_context(
711 &test_mhi_ctx->mmio_buf,
712 test_mhi_ctx->xfer_ring_bufs,
713 test_mhi_ctx->ev_ring_bufs,
714 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
715 IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1,
716 0x100,
717 0x80,
718 IPA_MHI_IN_CHAHNNEL);
719 if (rc) {
720 IPA_UT_ERR("Fail to config IN ch ctx - err %d", rc);
721 goto fail_destroy_out_ch_ctx;
722 }
723
724 /* allocate IN data buffer */
725 test_mhi_ctx->in_buffer.size = IPA_MHI_TEST_MAX_DATA_BUF_SIZE;
726 test_mhi_ctx->in_buffer.base = dma_alloc_coherent(
727 ipa3_ctx->pdev, test_mhi_ctx->in_buffer.size,
728 &test_mhi_ctx->in_buffer.phys_base, GFP_KERNEL);
729 if (!test_mhi_ctx->in_buffer.base) {
730 IPA_UT_ERR("no mem for In data buffer\n");
731 rc = -ENOMEM;
732 goto fail_destroy_in_ch_ctx;
733 }
734 memset(test_mhi_ctx->in_buffer.base, 0,
735 IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
736
737 /* allocate OUT data buffer */
738 test_mhi_ctx->out_buffer.size = IPA_MHI_TEST_MAX_DATA_BUF_SIZE;
739 test_mhi_ctx->out_buffer.base = dma_alloc_coherent(
740 ipa3_ctx->pdev, test_mhi_ctx->out_buffer.size,
741 &test_mhi_ctx->out_buffer.phys_base, GFP_KERNEL);
742 if (!test_mhi_ctx->out_buffer.base) {
743 IPA_UT_ERR("no mem for Out data buffer\n");
744 rc = -EFAULT;
745 goto fail_destroy_in_data_buf;
746 }
747 memset(test_mhi_ctx->out_buffer.base, 0,
748 IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
749
750 return 0;
751
752fail_destroy_in_data_buf:
753 dma_free_coherent(ipa3_ctx->pdev,
754 test_mhi_ctx->in_buffer.size,
755 test_mhi_ctx->in_buffer.base,
756 test_mhi_ctx->in_buffer.phys_base);
757 test_mhi_ctx->in_buffer.base = NULL;
758fail_destroy_in_ch_ctx:
759 ipa_mhi_test_destroy_channel_context(
760 test_mhi_ctx->xfer_ring_bufs,
761 test_mhi_ctx->ev_ring_bufs,
762 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
763 IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1);
764fail_destroy_out_ch_ctx:
765 ipa_mhi_test_destroy_channel_context(
766 test_mhi_ctx->xfer_ring_bufs,
767 test_mhi_ctx->ev_ring_bufs,
768 IPA_MHI_TEST_FIRST_CHANNEL_ID,
769 IPA_MHI_TEST_FIRST_EVENT_RING_ID);
770 return 0;
771}
772
773/**
774 * ipa_test_mhi_suite_setup() - Suite setup function
775 */
776static int ipa_test_mhi_suite_setup(void **ppriv)
777{
778 int rc = 0;
Skylar Changc01a7f42017-06-22 19:59:57 -0700779 struct ipa_sys_connect_params sys_in;
Amir Levy9659e592016-10-27 18:08:27 +0300780
781 IPA_UT_DBG("Start Setup\n");
782
783 if (!gsi_ctx) {
784 IPA_UT_ERR("No GSI ctx\n");
785 return -EINVAL;
786 }
787
788 if (!ipa3_ctx) {
789 IPA_UT_ERR("No IPA ctx\n");
790 return -EINVAL;
791 }
792
793 test_mhi_ctx = kzalloc(sizeof(struct ipa_test_mhi_context),
794 GFP_KERNEL);
795 if (!test_mhi_ctx) {
796 IPA_UT_ERR("failed allocated ctx\n");
797 return -ENOMEM;
798 }
799
800 test_mhi_ctx->gsi_mmio = ioremap_nocache(gsi_ctx->per.phys_addr,
801 gsi_ctx->per.size);
802 if (!test_mhi_ctx) {
803 IPA_UT_ERR("failed to remap GSI HW size=%lu\n",
804 gsi_ctx->per.size);
805 rc = -EFAULT;
806 goto fail_free_ctx;
807 }
808
809 rc = ipa_test_mhi_alloc_mmio_space();
810 if (rc) {
811 IPA_UT_ERR("failed to alloc mmio space");
812 goto fail_iounmap;
813 }
814
815 rc = ipa_mhi_test_setup_data_structures();
816 if (rc) {
817 IPA_UT_ERR("failed to setup data structures");
818 goto fail_free_mmio_spc;
819 }
820
Skylar Changc01a7f42017-06-22 19:59:57 -0700821 /* connect PROD pipe for remote wakeup */
822 memset(&sys_in, 0, sizeof(struct ipa_sys_connect_params));
823 sys_in.client = IPA_CLIENT_TEST_PROD;
824 sys_in.desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ;
825 sys_in.ipa_ep_cfg.mode.mode = IPA_DMA;
826 sys_in.ipa_ep_cfg.mode.dst = IPA_CLIENT_MHI_CONS;
827 if (ipa_setup_sys_pipe(&sys_in, &test_mhi_ctx->test_prod_hdl)) {
828 IPA_UT_ERR("setup sys pipe failed.\n");
829 goto fail_destroy_data_structures;
830 }
831
Amir Levy9659e592016-10-27 18:08:27 +0300832 *ppriv = test_mhi_ctx;
833 return 0;
834
Skylar Changc01a7f42017-06-22 19:59:57 -0700835fail_destroy_data_structures:
836 ipa_mhi_test_destroy_data_structures();
Amir Levy9659e592016-10-27 18:08:27 +0300837fail_free_mmio_spc:
838 ipa_test_mhi_free_mmio_space();
839fail_iounmap:
840 iounmap(test_mhi_ctx->gsi_mmio);
841fail_free_ctx:
842 kfree(test_mhi_ctx);
843 test_mhi_ctx = NULL;
844 return rc;
845}
846
847/**
848 * ipa_test_mhi_suite_teardown() - Suite teardown function
849 */
850static int ipa_test_mhi_suite_teardown(void *priv)
851{
852 IPA_UT_DBG("Start Teardown\n");
853
854 if (!test_mhi_ctx)
855 return 0;
856
Skylar Changc01a7f42017-06-22 19:59:57 -0700857 ipa_teardown_sys_pipe(test_mhi_ctx->test_prod_hdl);
Amir Levy9659e592016-10-27 18:08:27 +0300858 ipa_mhi_test_destroy_data_structures();
859 ipa_test_mhi_free_mmio_space();
860 iounmap(test_mhi_ctx->gsi_mmio);
861 kfree(test_mhi_ctx);
862 test_mhi_ctx = NULL;
863
864 return 0;
865}
866
867/**
868 * ipa_mhi_test_initialize_driver() - MHI init and possibly start and connect
869 *
870 * To be run during tests
871 * 1. MHI init (Ready state)
Ghanim Fodie6bb7a82017-10-02 17:59:58 +0300872 * 2. Conditional MHI start and connect (M0 state)
Amir Levy9659e592016-10-27 18:08:27 +0300873 */
874static int ipa_mhi_test_initialize_driver(bool skip_start_and_conn)
875{
876 int rc = 0;
877 struct ipa_mhi_init_params init_params;
878 struct ipa_mhi_start_params start_params;
879 struct ipa_mhi_connect_params prod_params;
880 struct ipa_mhi_connect_params cons_params;
881 struct ipa_mhi_mmio_register_set *p_mmio;
882 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
Amir Levy9659e592016-10-27 18:08:27 +0300883 u64 phys_addr;
884
885 IPA_UT_LOG("Entry\n");
886
887 p_mmio = test_mhi_ctx->mmio_buf.base;
888
889 /* start IPA MHI */
890 memset(&init_params, 0, sizeof(init_params));
891 init_params.msi.addr_low = test_mhi_ctx->msi.phys_base;
892 init_params.msi.data = 0x10000000;
893 init_params.msi.mask = ~0x10000000;
894 /* MMIO not needed for GSI */
895 init_params.first_ch_idx = IPA_MHI_TEST_FIRST_CHANNEL_ID;
896 init_params.first_er_idx = IPA_MHI_TEST_FIRST_EVENT_RING_ID;
897 init_params.assert_bit40 = false;
898 init_params.notify = ipa_mhi_test_cb;
899 init_params.priv = NULL;
900 init_params.test_mode = true;
901
902 rc = ipa_mhi_init(&init_params);
903 if (rc) {
904 IPA_UT_LOG("ipa_mhi_init failed %d\n", rc);
905 return rc;
906 }
907
908 IPA_UT_LOG("Wait async ready event\n");
909 if (wait_for_completion_timeout(&mhi_test_ready_comp, 10 * HZ) == 0) {
910 IPA_UT_LOG("timeout waiting for READY event");
911 IPA_UT_TEST_FAIL_REPORT("failed waiting for state ready");
912 return -ETIME;
913 }
914
Amir Levy9659e592016-10-27 18:08:27 +0300915 if (!skip_start_and_conn) {
916 memset(&start_params, 0, sizeof(start_params));
917 start_params.channel_context_array_addr = p_mmio->ccabap;
918 start_params.event_context_array_addr = p_mmio->ecabap;
919
920 IPA_UT_LOG("BEFORE mhi_start\n");
921 rc = ipa_mhi_start(&start_params);
922 if (rc) {
923 IPA_UT_LOG("mhi_start failed %d\n", rc);
924 IPA_UT_TEST_FAIL_REPORT("fail start mhi");
925 return rc;
926 }
927 IPA_UT_LOG("AFTER mhi_start\n");
928
929 phys_addr = p_mmio->ccabap + (IPA_MHI_TEST_FIRST_CHANNEL_ID *
930 sizeof(struct ipa_mhi_channel_context_array));
931 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
932 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
933 IPA_UT_LOG("ch: %d base: 0x%pK phys_addr 0x%llx chstate: %s\n",
934 IPA_MHI_TEST_FIRST_CHANNEL_ID,
935 p_ch_ctx_array, phys_addr,
936 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
937
938 memset(&prod_params, 0, sizeof(prod_params));
939 prod_params.sys.client = IPA_CLIENT_MHI_PROD;
940 prod_params.sys.ipa_ep_cfg.mode.mode = IPA_DMA;
941 prod_params.sys.ipa_ep_cfg.mode.dst = IPA_CLIENT_MHI_CONS;
942 prod_params.sys.ipa_ep_cfg.seq.seq_type =
943 IPA_MHI_TEST_SEQ_TYPE_DMA;
944 prod_params.sys.ipa_ep_cfg.seq.set_dynamic = true;
945 prod_params.channel_id = IPA_MHI_TEST_FIRST_CHANNEL_ID;
946 IPA_UT_LOG("BEFORE connect_pipe (PROD): client:%d ch_id:%u\n",
947 prod_params.sys.client, prod_params.channel_id);
948 rc = ipa_mhi_connect_pipe(&prod_params,
949 &test_mhi_ctx->prod_hdl);
950 if (rc) {
951 IPA_UT_LOG("mhi_connect_pipe failed %d\n", rc);
952 IPA_UT_TEST_FAIL_REPORT("fail connect PROD pipe");
953 return rc;
954 }
955
956 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
957 IPA_UT_LOG("MHI_PROD: chstate is not RUN chstate:%s\n",
958 ipa_mhi_get_state_str(
959 p_ch_ctx_array->chstate));
960 IPA_UT_TEST_FAIL_REPORT("PROD pipe state is not run");
961 return -EFAULT;
962 }
963
964 phys_addr = p_mmio->ccabap +
965 ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
966 sizeof(struct ipa_mhi_channel_context_array));
967 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
968 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
969 IPA_UT_LOG("ch: %d base: 0x%pK phys_addr 0x%llx chstate: %s\n",
970 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
971 p_ch_ctx_array, phys_addr,
972 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
973
974 memset(&cons_params, 0, sizeof(cons_params));
975 cons_params.sys.client = IPA_CLIENT_MHI_CONS;
976 cons_params.sys.skip_ep_cfg = true;
977 cons_params.channel_id = IPA_MHI_TEST_FIRST_CHANNEL_ID + 1;
978 IPA_UT_LOG("BEFORE connect_pipe (CONS): client:%d ch_id:%u\n",
979 cons_params.sys.client, cons_params.channel_id);
980 rc = ipa_mhi_connect_pipe(&cons_params,
981 &test_mhi_ctx->cons_hdl);
982 if (rc) {
983 IPA_UT_LOG("mhi_connect_pipe failed %d\n", rc);
984 IPA_UT_TEST_FAIL_REPORT("fail connect CONS pipe");
985 return rc;
986 }
987
988 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
989 IPA_UT_LOG("MHI_CONS: chstate is not RUN chstate:%s\n",
990 ipa_mhi_get_state_str(
991 p_ch_ctx_array->chstate));
992 IPA_UT_TEST_FAIL_REPORT("CONS pipe state is not run");
993 return -EFAULT;
994 }
995 }
996
997 return 0;
998}
999
1000/**
1001 * To be run during test
1002 * 1. MHI destroy
1003 * 2. re-configure the channels
1004 */
1005static int ipa_mhi_test_destroy(struct ipa_test_mhi_context *ctx)
1006{
1007 struct ipa_mhi_mmio_register_set *p_mmio;
1008 u64 phys_addr;
1009 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
1010 int rc;
1011
1012 IPA_UT_LOG("Entry\n");
1013
1014 if (unlikely(!ctx)) {
1015 IPA_UT_LOG("Input err invalid ctx\n");
1016 return -EINVAL;
1017 }
1018
1019 p_mmio = ctx->mmio_buf.base;
1020
1021 phys_addr = p_mmio->ccabap +
1022 ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
1023 sizeof(struct ipa_mhi_channel_context_array));
1024 p_ch_ctx_array = ctx->ch_ctx_array.base +
1025 (phys_addr - ctx->ch_ctx_array.phys_base);
1026 IPA_UT_LOG("channel id %d (CONS): chstate %s\n",
1027 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1028 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1029
1030 phys_addr = p_mmio->ccabap +
1031 ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
1032 sizeof(struct ipa_mhi_channel_context_array));
1033 p_ch_ctx_array = ctx->ch_ctx_array.base +
1034 (phys_addr - ctx->ch_ctx_array.phys_base);
1035 IPA_UT_LOG("channel id %d (PROD): chstate %s\n",
1036 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1037 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1038
1039 IPA_UT_LOG("MHI Destroy\n");
1040 ipa_mhi_destroy();
1041 IPA_UT_LOG("Post MHI Destroy\n");
1042
1043 ctx->prod_hdl = 0;
1044 ctx->cons_hdl = 0;
1045
1046 dma_free_coherent(ipa3_ctx->pdev, ctx->xfer_ring_bufs[1].size,
1047 ctx->xfer_ring_bufs[1].base, ctx->xfer_ring_bufs[1].phys_base);
1048 ctx->xfer_ring_bufs[1].base = NULL;
1049
1050 IPA_UT_LOG("config channel context for channel %d (MHI CONS)\n",
1051 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1);
1052 rc = ipa_mhi_test_config_channel_context(
1053 &ctx->mmio_buf,
1054 ctx->xfer_ring_bufs,
1055 ctx->ev_ring_bufs,
1056 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1057 IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1,
1058 0x100,
1059 0x80,
1060 IPA_MHI_IN_CHAHNNEL);
1061 if (rc) {
1062 IPA_UT_LOG("config channel context failed %d, channel %d\n",
1063 rc, IPA_MHI_TEST_FIRST_CHANNEL_ID + 1);
1064 IPA_UT_TEST_FAIL_REPORT("fail config CONS channel ctx");
1065 return -EFAULT;
1066 }
1067
1068 dma_free_coherent(ipa3_ctx->pdev, ctx->xfer_ring_bufs[0].size,
1069 ctx->xfer_ring_bufs[0].base, ctx->xfer_ring_bufs[0].phys_base);
1070 ctx->xfer_ring_bufs[0].base = NULL;
1071
1072 IPA_UT_LOG("config channel context for channel %d (MHI PROD)\n",
1073 IPA_MHI_TEST_FIRST_CHANNEL_ID);
1074 rc = ipa_mhi_test_config_channel_context(
1075 &ctx->mmio_buf,
1076 ctx->xfer_ring_bufs,
1077 ctx->ev_ring_bufs,
1078 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1079 IPA_MHI_TEST_FIRST_EVENT_RING_ID,
1080 0x100,
1081 0x80,
1082 IPA_MHI_OUT_CHAHNNEL);
1083 if (rc) {
1084 IPA_UT_LOG("config channel context failed %d, channel %d\n",
1085 rc, IPA_MHI_TEST_FIRST_CHANNEL_ID);
1086 IPA_UT_TEST_FAIL_REPORT("fail config PROD channel ctx");
1087 return -EFAULT;
1088 }
1089
1090 return 0;
1091}
1092
1093/**
1094 * To be run during test
1095 * 1. Destroy
1096 * 2. Initialize (to Ready or M0 states)
1097 */
1098static int ipa_mhi_test_reset(struct ipa_test_mhi_context *ctx,
1099 bool skip_start_and_conn)
1100{
1101 int rc;
1102
1103 IPA_UT_LOG("Entry\n");
1104
1105 rc = ipa_mhi_test_destroy(ctx);
1106 if (rc) {
1107 IPA_UT_LOG("destroy failed rc=%d", rc);
1108 IPA_UT_TEST_FAIL_REPORT("destroy fail");
1109 return rc;
1110 }
1111
1112 rc = ipa_mhi_test_initialize_driver(skip_start_and_conn);
1113 if (rc) {
1114 IPA_UT_LOG("driver init failed skip_start_and_con=%d rc=%d\n",
1115 skip_start_and_conn, rc);
1116 IPA_UT_TEST_FAIL_REPORT("init fail");
1117 return rc;
1118 }
1119
1120 return 0;
1121}
1122
1123/**
1124 * To be run during test
1125 * 1. disconnect cons channel
1126 * 2. config cons channel
1127 * 3. disconnect prod channel
1128 * 4. config prod channel
1129 * 5. connect prod
1130 * 6. connect cons
1131 */
1132static int ipa_mhi_test_channel_reset(void)
1133{
1134 int rc;
1135 struct ipa_mhi_connect_params prod_params;
1136 struct ipa_mhi_connect_params cons_params;
1137 struct ipa_mhi_mmio_register_set *p_mmio;
1138 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
1139 u64 phys_addr;
1140
1141 p_mmio = test_mhi_ctx->mmio_buf.base;
1142
1143 IPA_UT_LOG("Before pipe disconnect (CONS) client hdl=%u=\n",
1144 test_mhi_ctx->cons_hdl);
1145 rc = ipa_mhi_disconnect_pipe(test_mhi_ctx->cons_hdl);
1146 if (rc) {
1147 IPA_UT_LOG("disconnect_pipe failed (CONS) %d\n", rc);
1148 IPA_UT_TEST_FAIL_REPORT("CONS pipe disconnect fail");
1149 return -EFAULT;
1150 }
1151 test_mhi_ctx->cons_hdl = 0;
1152
1153 phys_addr = p_mmio->ccabap +
1154 ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
1155 sizeof(struct ipa_mhi_channel_context_array));
1156 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1157 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1158 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_DISABLE) {
1159 IPA_UT_LOG("chstate is not disabled! ch %d chstate %s\n",
1160 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1161 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1162 IPA_UT_TEST_FAIL_REPORT("CONS pipe state is not disabled");
1163 return -EFAULT;
1164 }
1165
1166 dma_free_coherent(ipa3_ctx->pdev,
1167 test_mhi_ctx->xfer_ring_bufs[1].size,
1168 test_mhi_ctx->xfer_ring_bufs[1].base,
1169 test_mhi_ctx->xfer_ring_bufs[1].phys_base);
1170 test_mhi_ctx->xfer_ring_bufs[1].base = NULL;
1171 rc = ipa_mhi_test_config_channel_context(
1172 &test_mhi_ctx->mmio_buf,
1173 test_mhi_ctx->xfer_ring_bufs,
1174 test_mhi_ctx->ev_ring_bufs,
1175 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1176 IPA_MHI_TEST_FIRST_EVENT_RING_ID + 1,
1177 0x100,
1178 0x80,
1179 IPA_MHI_IN_CHAHNNEL);
1180 if (rc) {
1181 IPA_UT_LOG("config_channel_context IN failed %d\n", rc);
1182 IPA_UT_TEST_FAIL_REPORT("fail config CONS channel context");
1183 return -EFAULT;
1184 }
1185 IPA_UT_LOG("Before pipe disconnect (CONS) client hdl=%u=\n",
1186 test_mhi_ctx->prod_hdl);
1187 rc = ipa_mhi_disconnect_pipe(test_mhi_ctx->prod_hdl);
1188 if (rc) {
1189 IPA_UT_LOG("disconnect_pipe failed (PROD) %d\n", rc);
1190 IPA_UT_TEST_FAIL_REPORT("PROD pipe disconnect fail");
1191 return -EFAULT;
1192 }
1193 test_mhi_ctx->prod_hdl = 0;
1194
1195 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
1196 sizeof(struct ipa_mhi_channel_context_array));
1197 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1198 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1199 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_DISABLE) {
1200 IPA_UT_LOG("chstate is not disabled! ch %d chstate %s\n",
1201 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1202 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1203 IPA_UT_TEST_FAIL_REPORT("PROD pipe state is not disabled");
1204 return -EFAULT;
1205 }
1206
1207 dma_free_coherent(ipa3_ctx->pdev, test_mhi_ctx->xfer_ring_bufs[0].size,
1208 test_mhi_ctx->xfer_ring_bufs[0].base,
1209 test_mhi_ctx->xfer_ring_bufs[0].phys_base);
1210 test_mhi_ctx->xfer_ring_bufs[0].base = NULL;
1211 rc = ipa_mhi_test_config_channel_context(
1212 &test_mhi_ctx->mmio_buf,
1213 test_mhi_ctx->xfer_ring_bufs,
1214 test_mhi_ctx->ev_ring_bufs,
1215 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1216 IPA_MHI_TEST_FIRST_EVENT_RING_ID,
1217 0x100,
1218 0x80,
1219 IPA_MHI_OUT_CHAHNNEL);
1220 if (rc) {
1221 IPA_UT_LOG("config_channel_context OUT failed %d\n", rc);
1222 IPA_UT_TEST_FAIL_REPORT("PROD pipe state is not disabled");
1223 return -EFAULT;
1224 }
1225
1226 memset(&prod_params, 0, sizeof(prod_params));
1227 prod_params.sys.client = IPA_CLIENT_MHI_PROD;
1228 prod_params.sys.ipa_ep_cfg.mode.mode = IPA_DMA;
1229 prod_params.sys.ipa_ep_cfg.mode.dst = IPA_CLIENT_MHI_CONS;
1230 prod_params.sys.ipa_ep_cfg.seq.seq_type = IPA_MHI_TEST_SEQ_TYPE_DMA;
1231 prod_params.sys.ipa_ep_cfg.seq.set_dynamic = true;
1232 prod_params.channel_id = IPA_MHI_TEST_FIRST_CHANNEL_ID;
1233 IPA_UT_LOG("BEFORE connect PROD\n");
1234 rc = ipa_mhi_connect_pipe(&prod_params, &test_mhi_ctx->prod_hdl);
1235 if (rc) {
1236 IPA_UT_LOG("connect_pipe failed %d\n", rc);
1237 IPA_UT_TEST_FAIL_REPORT("fail connect PROD pipe");
1238 return rc;
1239 }
1240
1241 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
1242 sizeof(struct ipa_mhi_channel_context_array));
1243 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1244 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1245 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1246 IPA_UT_LOG("chstate is not run! ch %d chstate %s\n",
1247 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1248 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1249 IPA_UT_TEST_FAIL_REPORT("PROD pipe state is not run");
1250 return -EFAULT;
1251 }
1252
1253 memset(&cons_params, 0, sizeof(cons_params));
1254 cons_params.sys.client = IPA_CLIENT_MHI_CONS;
1255 cons_params.sys.skip_ep_cfg = true;
1256 cons_params.channel_id = IPA_MHI_TEST_FIRST_CHANNEL_ID + 1;
1257 IPA_UT_LOG("BEFORE connect CONS\n");
1258 rc = ipa_mhi_connect_pipe(&cons_params, &test_mhi_ctx->cons_hdl);
1259 if (rc) {
1260 IPA_UT_LOG("ipa_mhi_connect_pipe failed %d\n", rc);
1261 IPA_UT_TEST_FAIL_REPORT("fail connect CONS pipe");
1262 return rc;
1263 }
1264
1265 phys_addr = p_mmio->ccabap +
1266 ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
1267 sizeof(struct ipa_mhi_channel_context_array));
1268 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1269 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1270 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1271 IPA_UT_LOG("chstate is not run! ch %d chstate %s\n",
1272 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1273 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1274 IPA_UT_TEST_FAIL_REPORT("CONS pipe state is not run");
1275 return -EFAULT;
1276 }
1277
1278 return 0;
1279}
1280
1281/**
1282 * To be run during test
1283 * Send data
1284 */
1285static int ipa_mhi_test_q_transfer_re(struct ipa_mem_buffer *mmio,
1286 struct ipa_mem_buffer xfer_ring_bufs[],
1287 struct ipa_mem_buffer ev_ring_bufs[],
1288 u8 channel_id,
1289 struct ipa_mem_buffer buf_array[],
1290 int buf_array_size,
1291 bool ieob,
1292 bool ieot,
1293 bool bei,
1294 bool trigger_db)
1295{
1296 struct ipa_mhi_transfer_ring_element *curr_re;
1297 struct ipa_mhi_mmio_register_set *p_mmio;
1298 struct ipa_mhi_channel_context_array *p_channels;
1299 struct ipa_mhi_event_context_array *p_events;
1300 u32 channel_idx;
1301 u32 event_ring_index;
1302 u32 wp_ofst;
1303 u32 rp_ofst;
1304 u32 next_wp_ofst;
1305 int i;
1306 u32 num_of_ed_to_queue;
1307
1308 IPA_UT_LOG("Entry\n");
1309
1310 p_mmio = (struct ipa_mhi_mmio_register_set *)mmio->base;
1311 p_channels = (struct ipa_mhi_channel_context_array *)
1312 ((unsigned long)p_mmio->crcbap);
1313 p_events = (struct ipa_mhi_event_context_array *)
1314 ((unsigned long)p_mmio->crdb);
1315
1316 if (ieob)
1317 num_of_ed_to_queue = buf_array_size;
1318 else
1319 num_of_ed_to_queue = ieot ? 1 : 0;
1320
1321 if (channel_id >=
1322 (IPA_MHI_TEST_FIRST_CHANNEL_ID + IPA_MHI_TEST_NUM_CHANNELS) ||
1323 channel_id < IPA_MHI_TEST_FIRST_CHANNEL_ID) {
1324 IPA_UT_LOG("Invalud Channel ID %d\n", channel_id);
1325 return -EFAULT;
1326 }
1327
1328 channel_idx = channel_id - IPA_MHI_TEST_FIRST_CHANNEL_ID;
1329
1330 if (!xfer_ring_bufs[channel_idx].base) {
1331 IPA_UT_LOG("Channel is not allocated\n");
1332 return -EFAULT;
1333 }
1334 if (p_channels[channel_idx].brsmode == IPA_MHI_BURST_MODE_DEFAULT ||
1335 p_channels[channel_idx].brsmode == IPA_MHI_BURST_MODE_ENABLE)
1336 num_of_ed_to_queue += 1; /* for OOB/DB mode event */
1337
1338 /* First queue EDs */
1339 event_ring_index = p_channels[channel_idx].erindex -
1340 IPA_MHI_TEST_FIRST_EVENT_RING_ID;
1341
1342 wp_ofst = (u32)(p_events[event_ring_index].wp -
1343 p_events[event_ring_index].rbase);
1344
1345 if (p_events[event_ring_index].rlen & 0xFFFFFFFF00000000) {
1346 IPA_UT_LOG("invalid ev rlen %llu\n",
1347 p_events[event_ring_index].rlen);
1348 return -EFAULT;
1349 }
1350
1351 next_wp_ofst = (wp_ofst + num_of_ed_to_queue *
1352 sizeof(struct ipa_mhi_event_ring_element)) %
1353 (u32)p_events[event_ring_index].rlen;
1354
1355 /* set next WP */
1356 p_events[event_ring_index].wp =
1357 (u32)p_events[event_ring_index].rbase + next_wp_ofst;
1358
1359 /* write value to event ring doorbell */
1360 IPA_UT_LOG("DB to event 0x%llx: base %pa ofst 0x%x\n",
1361 p_events[event_ring_index].wp,
1362 &(gsi_ctx->per.phys_addr), GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS(
Ghanim Fodic823bc62017-10-21 17:29:53 +03001363 event_ring_index + ipa3_ctx->mhi_evid_limits[0], 0));
Amir Levy9659e592016-10-27 18:08:27 +03001364 iowrite32(p_events[event_ring_index].wp,
1365 test_mhi_ctx->gsi_mmio +
1366 GSI_EE_n_EV_CH_k_DOORBELL_0_OFFS(
Ghanim Fodic823bc62017-10-21 17:29:53 +03001367 event_ring_index + ipa3_ctx->mhi_evid_limits[0], 0));
Amir Levy9659e592016-10-27 18:08:27 +03001368
1369 for (i = 0; i < buf_array_size; i++) {
1370 /* calculate virtual pointer for current WP and RP */
1371 wp_ofst = (u32)(p_channels[channel_idx].wp -
1372 p_channels[channel_idx].rbase);
1373 rp_ofst = (u32)(p_channels[channel_idx].rp -
1374 p_channels[channel_idx].rbase);
1375 (void)rp_ofst;
1376 curr_re = (struct ipa_mhi_transfer_ring_element *)
1377 ((unsigned long)xfer_ring_bufs[channel_idx].base +
1378 wp_ofst);
1379 if (p_channels[channel_idx].rlen & 0xFFFFFFFF00000000) {
1380 IPA_UT_LOG("invalid ch rlen %llu\n",
1381 p_channels[channel_idx].rlen);
1382 return -EFAULT;
1383 }
1384 next_wp_ofst = (wp_ofst +
1385 sizeof(struct ipa_mhi_transfer_ring_element)) %
1386 (u32)p_channels[channel_idx].rlen;
1387
1388 /* write current RE */
1389 curr_re->type = IPA_MHI_RING_ELEMENT_TRANSFER;
1390 curr_re->len = (u16)buf_array[i].size;
1391 curr_re->ptr = (u32)buf_array[i].phys_base;
1392 curr_re->word_C.bits.bei = bei;
1393 curr_re->word_C.bits.ieob = ieob;
1394 curr_re->word_C.bits.ieot = ieot;
1395
1396 /* set next WP */
1397 p_channels[channel_idx].wp =
1398 p_channels[channel_idx].rbase + next_wp_ofst;
1399
1400 if (i == (buf_array_size - 1)) {
1401 /* last buffer */
1402 curr_re->word_C.bits.chain = 0;
1403 if (trigger_db) {
1404 IPA_UT_LOG(
1405 "DB to channel 0x%llx: base %pa ofst 0x%x\n"
1406 , p_channels[channel_idx].wp
1407 , &(gsi_ctx->per.phys_addr)
1408 , GSI_EE_n_GSI_CH_k_DOORBELL_0_OFFS(
1409 channel_idx, 0));
1410 iowrite32(p_channels[channel_idx].wp,
1411 test_mhi_ctx->gsi_mmio +
1412 GSI_EE_n_GSI_CH_k_DOORBELL_0_OFFS(
1413 channel_idx, 0));
1414 }
1415 } else {
1416 curr_re->word_C.bits.chain = 1;
1417 }
1418 }
1419
1420 return 0;
1421}
1422
1423/**
1424 * To be run during test
1425 * Send data in loopback (from In to OUT) and compare
1426 */
1427static int ipa_mhi_test_loopback_data_transfer(void)
1428{
1429 struct ipa_mem_buffer *p_mmio;
1430 int i;
1431 int rc;
1432 static int val;
1433 bool timeout = true;
1434
1435 IPA_UT_LOG("Entry\n");
1436
1437 p_mmio = &test_mhi_ctx->mmio_buf;
1438
1439 /* invalidate spare register value (for msi) */
1440 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
1441
1442 val++;
1443
1444 memset(test_mhi_ctx->in_buffer.base, 0,
1445 IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1446 for (i = 0; i < IPA_MHI_TEST_MAX_DATA_BUF_SIZE; i++)
1447 memset(test_mhi_ctx->out_buffer.base + i, (val + i) & 0xFF, 1);
1448
1449 /* queue RE for IN side and trigger doorbell */
1450 rc = ipa_mhi_test_q_transfer_re(p_mmio,
1451 test_mhi_ctx->xfer_ring_bufs,
1452 test_mhi_ctx->ev_ring_bufs,
1453 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1454 &test_mhi_ctx->in_buffer,
1455 1,
1456 true,
1457 true,
1458 false,
1459 true);
1460
1461 if (rc) {
1462 IPA_UT_LOG("q_transfer_re failed %d\n", rc);
1463 IPA_UT_TEST_FAIL_REPORT("fail IN q xfer re");
1464 return rc;
1465 }
1466
1467 /* queue REs for OUT side and trigger doorbell */
1468 rc = ipa_mhi_test_q_transfer_re(p_mmio,
1469 test_mhi_ctx->xfer_ring_bufs,
1470 test_mhi_ctx->ev_ring_bufs,
1471 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1472 &test_mhi_ctx->out_buffer,
1473 1,
1474 true,
1475 true,
1476 false,
1477 true);
1478
1479 if (rc) {
1480 IPA_UT_LOG("q_transfer_re failed %d\n", rc);
1481 IPA_UT_TEST_FAIL_REPORT("fail OUT q xfer re");
1482 return rc;
1483 }
1484
1485 IPA_MHI_TEST_CHECK_MSI_INTR(true, timeout);
1486 if (timeout) {
1487 IPA_UT_LOG("transfer timeout. MSI = 0x%x\n",
1488 *((u32 *)test_mhi_ctx->msi.base));
1489 IPA_UT_TEST_FAIL_REPORT("xfter timeout");
1490 return -EFAULT;
1491 }
1492
1493 /* compare the two buffers */
1494 if (memcmp(test_mhi_ctx->in_buffer.base, test_mhi_ctx->out_buffer.base,
1495 IPA_MHI_TEST_MAX_DATA_BUF_SIZE)) {
1496 IPA_UT_LOG("buffer are not equal\n");
1497 IPA_UT_TEST_FAIL_REPORT("non-equal buffers after xfer");
1498 return -EFAULT;
1499 }
1500
1501 return 0;
1502}
1503
1504/**
1505 * To be run during test
1506 * Do suspend and check channel states to be suspend if should success
1507 */
1508static int ipa_mhi_test_suspend(bool force, bool should_success)
1509{
1510 int rc;
1511 struct ipa_mhi_mmio_register_set *p_mmio;
1512 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
1513 u64 phys_addr;
1514
1515 IPA_UT_LOG("Entry\n");
1516
1517 rc = ipa_mhi_suspend(force);
1518 if (should_success && rc != 0) {
1519 IPA_UT_LOG("ipa_mhi_suspend failed %d\n", rc);
1520 IPA_UT_TEST_FAIL_REPORT("suspend failed");
1521 return -EFAULT;
1522 }
1523
1524 if (!should_success && rc != -EAGAIN) {
Ghanim Fodie6bb7a82017-10-02 17:59:58 +03001525 IPA_UT_LOG("ipa_mhi_suspend did not return -EAGAIN fail %d\n",
Amir Levy9659e592016-10-27 18:08:27 +03001526 rc);
1527 IPA_UT_TEST_FAIL_REPORT("suspend succeeded unexpectedly");
1528 return -EFAULT;
1529 }
1530
1531 p_mmio = test_mhi_ctx->mmio_buf.base;
1532
1533 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
1534 sizeof(struct ipa_mhi_channel_context_array));
1535 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1536 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1537 if (should_success) {
1538 if (p_ch_ctx_array->chstate !=
1539 IPA_HW_MHI_CHANNEL_STATE_SUSPEND) {
1540 IPA_UT_LOG("chstate is not suspend. ch %d chstate %s\n",
1541 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1542 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1543 IPA_UT_TEST_FAIL_REPORT("channel state not suspend");
1544 return -EFAULT;
1545 }
1546 if (!force && p_ch_ctx_array->rp != p_ch_ctx_array->wp) {
1547 IPA_UT_LOG("rp not updated ch %d rp 0x%llx wp 0x%llx\n",
1548 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1549 p_ch_ctx_array->rp, p_ch_ctx_array->wp);
1550 IPA_UT_TEST_FAIL_REPORT("rp was not updated");
1551 return -EFAULT;
1552 }
1553 } else {
1554 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1555 IPA_UT_LOG("chstate is not running! ch %d chstate %s\n",
1556 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1557 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1558 IPA_UT_TEST_FAIL_REPORT("channel state not run");
1559 return -EFAULT;
1560 }
1561 }
1562
1563 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
1564 sizeof(struct ipa_mhi_channel_context_array));
1565 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1566 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1567 if (should_success) {
1568 if (p_ch_ctx_array->chstate !=
1569 IPA_HW_MHI_CHANNEL_STATE_SUSPEND) {
1570 IPA_UT_LOG("chstate is not running! ch %d chstate %s\n",
1571 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1572 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1573 IPA_UT_TEST_FAIL_REPORT("channel state not suspend");
1574 return -EFAULT;
1575 }
1576 if (!force && p_ch_ctx_array->rp != p_ch_ctx_array->wp) {
1577 IPA_UT_LOG("rp not updated ch %d rp 0x%llx wp 0x%llx\n",
1578 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1579 p_ch_ctx_array->rp, p_ch_ctx_array->wp);
1580 IPA_UT_TEST_FAIL_REPORT("rp was not updated");
1581 return -EFAULT;
1582 }
1583 } else {
1584 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1585 IPA_UT_LOG("chstate is not running! ch %d chstate %s\n",
1586 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1587 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1588 IPA_UT_TEST_FAIL_REPORT("channel state not run");
1589 return -EFAULT;
1590 }
1591 }
1592
1593 return 0;
1594}
1595
1596/**
1597 * To be run during test
1598 * Do resume and check channel state to be running
1599 */
1600static int ipa_test_mhi_resume(void)
1601{
1602 int rc;
1603 struct ipa_mhi_mmio_register_set *p_mmio;
1604 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
1605 u64 phys_addr;
1606
1607 rc = ipa_mhi_resume();
1608 if (rc) {
1609 IPA_UT_LOG("resume failed %d\n", rc);
1610 IPA_UT_TEST_FAIL_REPORT("resume failed");
1611 return -EFAULT;
1612 }
1613
1614 p_mmio = test_mhi_ctx->mmio_buf.base;
1615
1616 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID + 1) *
1617 sizeof(struct ipa_mhi_channel_context_array));
1618 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1619 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1620 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1621 IPA_UT_LOG("chstate is not running! ch %d chstate %s\n",
1622 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1623 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1624 IPA_UT_TEST_FAIL_REPORT("channel state not run");
1625 return -EFAULT;
1626 }
1627
1628 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
1629 sizeof(struct ipa_mhi_channel_context_array));
1630 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
1631 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
1632 if (p_ch_ctx_array->chstate != IPA_HW_MHI_CHANNEL_STATE_RUN) {
1633 IPA_UT_LOG("chstate is not running! ch %d chstate %s\n",
1634 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1635 ipa_mhi_get_state_str(p_ch_ctx_array->chstate));
1636 IPA_UT_TEST_FAIL_REPORT("channel state not run");
1637 return -EFAULT;
1638 }
1639
1640 return 0;
1641}
1642
1643/**
1644 * To be run during test
1645 * 1. suspend
1646 * 2. queue RE for IN and OUT and send data
1647 * 3. should get MSI timeout due to suspend
1648 * 4. resume
1649 * 5. should get the MSIs now
1650 * 6. comapre the IN and OUT buffers
1651 */
1652static int ipa_mhi_test_suspend_resume(void)
1653{
1654 int rc;
1655 int i;
1656 bool timeout = true;
1657
1658 IPA_UT_LOG("Entry\n");
1659
1660 IPA_UT_LOG("BEFORE suspend\n");
1661 rc = ipa_mhi_test_suspend(false, true);
1662 if (rc) {
1663 IPA_UT_LOG("suspend failed %d\n", rc);
1664 IPA_UT_TEST_FAIL_REPORT("suspend failed");
1665 return rc;
1666 }
1667 IPA_UT_LOG("AFTER suspend\n");
1668
1669 /* invalidate spare register value (for msi) */
1670 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
1671
1672 memset(test_mhi_ctx->in_buffer.base, 0, IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1673 for (i = 0; i < IPA_MHI_TEST_MAX_DATA_BUF_SIZE; i++)
1674 memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
1675
1676 /* queue RE for IN side and trigger doorbell */
1677 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
1678 test_mhi_ctx->xfer_ring_bufs,
1679 test_mhi_ctx->ev_ring_bufs,
1680 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1681 &test_mhi_ctx->in_buffer,
1682 1,
1683 true,
1684 true,
1685 false,
1686 true);
1687 if (rc) {
1688 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n", rc);
1689 IPA_UT_TEST_FAIL_REPORT("fail IN q xfer re");
1690 return rc;
1691 }
1692
1693 /* queue REs for OUT side and trigger doorbell */
1694 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
1695 test_mhi_ctx->xfer_ring_bufs,
1696 test_mhi_ctx->ev_ring_bufs,
1697 IPA_MHI_TEST_FIRST_CHANNEL_ID,
1698 &test_mhi_ctx->out_buffer,
1699 1,
1700 true,
1701 true,
1702 false,
1703 true);
1704
1705 if (rc) {
1706 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n", rc);
1707 IPA_UT_TEST_FAIL_REPORT("fail OUT q xfer re");
1708 return rc;
1709 }
1710
1711 IPA_MHI_TEST_CHECK_MSI_INTR(true, timeout);
1712 if (!timeout) {
1713 IPA_UT_LOG("Error: transfer success on suspend\n");
1714 IPA_UT_TEST_FAIL_REPORT("xfer suceeded unexpectedly");
1715 return -EFAULT;
1716 }
1717
1718 IPA_UT_LOG("BEFORE resume\n");
1719 rc = ipa_test_mhi_resume();
1720 if (rc) {
1721 IPA_UT_LOG("ipa_mhi_resume failed %d\n", rc);
1722 IPA_UT_TEST_FAIL_REPORT("resume fail");
1723 return rc;
1724 }
1725 IPA_UT_LOG("AFTER resume\n");
1726
1727 IPA_MHI_TEST_CHECK_MSI_INTR(true, timeout);
1728 if (timeout) {
1729 IPA_UT_LOG("Error: transfer timeout\n");
1730 IPA_UT_TEST_FAIL_REPORT("xfer timeout");
1731 return -EFAULT;
1732 }
1733
1734 /* compare the two buffers */
1735 if (memcmp(test_mhi_ctx->in_buffer.base,
1736 test_mhi_ctx->out_buffer.base,
1737 IPA_MHI_TEST_MAX_DATA_BUF_SIZE)) {
1738 IPA_UT_LOG("Error: buffers are not equal\n");
1739 IPA_UT_TEST_FAIL_REPORT("non-equal buffers after xfer");
1740 return -EFAULT;
1741 }
1742
1743 return 0;
1744}
1745
1746/**
1747 * To be run during test
1748 * 1. enable aggregation
1749 * 2. queue IN RE (ring element)
1750 * 3. allocate skb with data
1751 * 4. send it (this will create open aggr frame)
1752 */
1753static int ipa_mhi_test_create_aggr_open_frame(void)
1754{
1755 struct ipa_ep_cfg_aggr ep_aggr;
1756 struct sk_buff *skb;
1757 int rc;
1758 int i;
1759 u32 aggr_state_active;
1760
1761 IPA_UT_LOG("Entry\n");
1762
1763 memset(&ep_aggr, 0, sizeof(ep_aggr));
1764 ep_aggr.aggr_en = IPA_ENABLE_AGGR;
1765 ep_aggr.aggr = IPA_GENERIC;
1766 ep_aggr.aggr_pkt_limit = 2;
1767
1768 rc = ipa3_cfg_ep_aggr(test_mhi_ctx->cons_hdl, &ep_aggr);
1769 if (rc) {
1770 IPA_UT_LOG("failed to configure aggr");
1771 IPA_UT_TEST_FAIL_REPORT("failed to configure aggr");
1772 return rc;
1773 }
1774
1775 /* invalidate spare register value (for msi) */
1776 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
1777
1778 /* queue RE for IN side and trigger doorbell */
1779 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
1780 test_mhi_ctx->xfer_ring_bufs,
1781 test_mhi_ctx->ev_ring_bufs,
1782 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1783 &test_mhi_ctx->in_buffer,
1784 1,
1785 true,
1786 true,
1787 false,
1788 true);
1789 if (rc) {
1790 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n", rc);
1791 IPA_UT_TEST_FAIL_REPORT("fail IN q xfer re");
1792 return rc;
1793 }
1794
1795 skb = dev_alloc_skb(IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1796 if (!skb) {
1797 IPA_UT_LOG("non mem for skb\n");
1798 IPA_UT_TEST_FAIL_REPORT("fail alloc skb");
1799 return -ENOMEM;
1800 }
1801 skb_put(skb, IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1802 for (i = 0; i < IPA_MHI_TEST_MAX_DATA_BUF_SIZE; i++) {
1803 memset(skb->data + i, i & 0xFF, 1);
1804 memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
1805 }
1806
Skylar Changc01a7f42017-06-22 19:59:57 -07001807 rc = ipa_tx_dp(IPA_CLIENT_TEST_PROD, skb, NULL);
Amir Levy9659e592016-10-27 18:08:27 +03001808 if (rc) {
1809 IPA_UT_LOG("ipa_tx_dp failed %d\n", rc);
1810 IPA_UT_TEST_FAIL_REPORT("ipa tx dp fail");
1811 return rc;
1812 }
1813
1814 msleep(20);
1815
1816 aggr_state_active = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
1817 IPA_UT_LOG("IPA_STATE_AGGR_ACTIVE 0x%x\n", aggr_state_active);
1818 if (aggr_state_active == 0) {
1819 IPA_UT_LOG("No aggregation frame open!\n");
1820 IPA_UT_TEST_FAIL_REPORT("No aggregation frame open");
1821 return -EFAULT;
1822 }
1823
1824 return 0;
1825}
1826
1827/**
1828 * To be run during test
1829 * 1. create open aggr by sending data
1830 * 2. suspend - if force it should succeed, otherwize it fails
1831 * 3. if force - wait for wakeup event - it should arrive
1832 * 4. if force - resume
1833 * 5. force close the aggr.
1834 * 6. wait for MSI - it should arrive
1835 * 7. compare IN and OUT buffers
1836 * 8. disable aggr.
1837 */
1838static int ipa_mhi_test_suspend_aggr_open(bool force)
1839{
1840 int rc;
1841 struct ipa_ep_cfg_aggr ep_aggr;
1842 bool timeout = true;
1843
1844 IPA_UT_LOG("Entry\n");
1845
1846 rc = ipa_mhi_test_create_aggr_open_frame();
1847 if (rc) {
1848 IPA_UT_LOG("failed create open aggr\n");
1849 IPA_UT_TEST_FAIL_REPORT("fail create open aggr");
1850 return rc;
1851 }
1852
1853 if (force)
1854 reinit_completion(&mhi_test_wakeup_comp);
1855
1856 IPA_UT_LOG("BEFORE suspend\n");
1857 /**
1858 * if suspend force, then suspend should succeed.
1859 * otherwize it should fail due to open aggr.
1860 */
1861 rc = ipa_mhi_test_suspend(force, force);
1862 if (rc) {
1863 IPA_UT_LOG("suspend failed %d\n", rc);
1864 IPA_UT_TEST_FAIL_REPORT("suspend fail");
1865 return rc;
1866 }
1867 IPA_UT_LOG("AFTER suspend\n");
1868
1869 if (force) {
1870 if (!wait_for_completion_timeout(&mhi_test_wakeup_comp, HZ)) {
1871 IPA_UT_LOG("timeout waiting for wakeup event\n");
1872 IPA_UT_TEST_FAIL_REPORT("timeout waitinf wakeup event");
1873 return -ETIME;
1874 }
1875
1876 IPA_UT_LOG("BEFORE resume\n");
1877 rc = ipa_test_mhi_resume();
1878 if (rc) {
1879 IPA_UT_LOG("resume failed %d\n", rc);
1880 IPA_UT_TEST_FAIL_REPORT("resume failed");
1881 return rc;
1882 }
1883 IPA_UT_LOG("AFTER resume\n");
1884 }
1885
1886 ipahal_write_reg(IPA_AGGR_FORCE_CLOSE, (1 << test_mhi_ctx->cons_hdl));
1887
1888 IPA_MHI_TEST_CHECK_MSI_INTR(false, timeout);
1889 if (timeout) {
1890 IPA_UT_LOG("fail: transfer not completed\n");
1891 IPA_UT_TEST_FAIL_REPORT("timeout on transferring data");
1892 return -EFAULT;
1893 }
1894
1895 /* compare the two buffers */
1896 if (memcmp(test_mhi_ctx->in_buffer.base,
1897 test_mhi_ctx->out_buffer.base,
1898 IPA_MHI_TEST_MAX_DATA_BUF_SIZE)) {
1899 IPA_UT_LOG("fail: buffer are not equal\n");
1900 IPA_UT_TEST_FAIL_REPORT("non-equal buffers after xfer");
1901 return -EFAULT;
1902 }
1903
1904 memset(&ep_aggr, 0, sizeof(ep_aggr));
1905 rc = ipa3_cfg_ep_aggr(test_mhi_ctx->cons_hdl, &ep_aggr);
1906 if (rc) {
1907 IPA_UT_LOG("failed to configure aggr");
1908 IPA_UT_TEST_FAIL_REPORT("fail to disable aggr");
1909 return rc;
1910 }
1911
1912 return 0;
1913}
1914
1915/**
1916 * To be run during test
1917 * 1. suspend
1918 * 2. queue IN RE (ring element)
1919 * 3. allocate skb with data
1920 * 4. send it (this will create open aggr frame)
1921 * 5. wait for wakeup event - it should arrive
1922 * 6. resume
1923 * 7. wait for MSI - it should arrive
1924 * 8. compare IN and OUT buffers
1925 */
1926static int ipa_mhi_test_suspend_host_wakeup(void)
1927{
1928 int rc;
1929 int i;
1930 bool timeout = true;
1931 struct sk_buff *skb;
1932
1933 reinit_completion(&mhi_test_wakeup_comp);
1934
1935 IPA_UT_LOG("BEFORE suspend\n");
1936 rc = ipa_mhi_test_suspend(false, true);
1937 if (rc) {
1938 IPA_UT_LOG("suspend failed %d\n", rc);
1939 IPA_UT_TEST_FAIL_REPORT("suspend fail");
1940 return rc;
1941 }
1942 IPA_UT_LOG("AFTER suspend\n");
1943
1944 /* invalidate spare register value (for msi) */
1945 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
1946
1947 memset(test_mhi_ctx->in_buffer.base, 0, IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1948 /* queue RE for IN side and trigger doorbell*/
1949 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
1950 test_mhi_ctx->xfer_ring_bufs,
1951 test_mhi_ctx->ev_ring_bufs,
1952 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
1953 &test_mhi_ctx->in_buffer,
1954 1,
1955 true,
1956 true,
1957 false,
1958 true);
1959
1960 if (rc) {
1961 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n", rc);
1962 IPA_UT_TEST_FAIL_REPORT("fail IN q xfer re");
1963 return rc;
1964 }
1965
1966 skb = dev_alloc_skb(IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1967 if (!skb) {
1968 IPA_UT_LOG("non mem for skb\n");
1969 IPA_UT_TEST_FAIL_REPORT("no mem for skb");
1970 return -ENOMEM;
1971 }
1972 skb_put(skb, IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
1973 for (i = 0; i < IPA_MHI_TEST_MAX_DATA_BUF_SIZE; i++) {
1974 memset(skb->data + i, i & 0xFF, 1);
1975 memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
1976 }
1977
Skylar Changc01a7f42017-06-22 19:59:57 -07001978 rc = ipa_tx_dp(IPA_CLIENT_TEST_PROD, skb, NULL);
Amir Levy9659e592016-10-27 18:08:27 +03001979 if (rc) {
1980 IPA_UT_LOG("ipa_tx_dp failed %d\n", rc);
1981 IPA_UT_TEST_FAIL_REPORT("ipa tx dp fail");
1982 return rc;
1983 }
1984
1985 if (wait_for_completion_timeout(&mhi_test_wakeup_comp, HZ) == 0) {
1986 IPA_UT_LOG("timeout waiting for wakeup event\n");
1987 IPA_UT_TEST_FAIL_REPORT("timeout waiting for wakeup event");
1988 return -ETIME;
1989 }
1990
1991 IPA_UT_LOG("BEFORE resume\n");
1992 rc = ipa_test_mhi_resume();
1993 if (rc) {
1994 IPA_UT_LOG("resume failed %d\n", rc);
1995 IPA_UT_TEST_FAIL_REPORT("resume fail");
1996 return rc;
1997 }
1998 IPA_UT_LOG("AFTER resume\n");
1999
2000 /* check for MSI interrupt one channels */
2001 IPA_MHI_TEST_CHECK_MSI_INTR(false, timeout);
2002 if (timeout) {
2003 IPA_UT_LOG("fail: transfer timeout\n");
2004 IPA_UT_TEST_FAIL_REPORT("timeout on xfer");
2005 return -EFAULT;
2006 }
2007
2008 /* compare the two buffers */
2009 if (memcmp(test_mhi_ctx->in_buffer.base,
2010 test_mhi_ctx->out_buffer.base,
2011 IPA_MHI_TEST_MAX_DATA_BUF_SIZE)) {
2012 IPA_UT_LOG("fail: buffer are not equal\n");
2013 IPA_UT_TEST_FAIL_REPORT("non-equal buffers after xfer");
2014 return -EFAULT;
2015 }
2016
2017 return 0;
2018}
2019
2020/**
2021 * To be run during test
2022 * 1. queue OUT RE/buffer
2023 * 2. wait for MSI on OUT
2024 * 3. Do 1. and 2. till got MSI wait timeout (ch full / holb)
2025 */
2026static int ipa_mhi_test_create_full_channel(int *submitted_packets)
2027{
2028 int i;
2029 bool timeout = true;
2030 int rc;
2031
2032 if (!submitted_packets) {
2033 IPA_UT_LOG("Input error\n");
2034 return -EINVAL;
2035 }
2036
2037 *submitted_packets = 0;
2038
2039 for (i = 0; i < IPA_MHI_TEST_MAX_DATA_BUF_SIZE; i++)
2040 memset(test_mhi_ctx->out_buffer.base + i, i & 0xFF, 1);
2041
2042 do {
2043 /* invalidate spare register value (for msi) */
2044 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
2045
2046 IPA_UT_LOG("submitting OUT buffer\n");
2047 timeout = true;
2048 /* queue REs for OUT side and trigger doorbell */
2049 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
2050 test_mhi_ctx->xfer_ring_bufs,
2051 test_mhi_ctx->ev_ring_bufs,
2052 IPA_MHI_TEST_FIRST_CHANNEL_ID,
2053 &test_mhi_ctx->out_buffer,
2054 1,
2055 true,
2056 true,
2057 false,
2058 true);
2059 if (rc) {
2060 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n",
2061 rc);
2062 IPA_UT_TEST_FAIL_REPORT("fail OUT q re");
2063 return rc;
2064 }
2065 (*submitted_packets)++;
2066
2067 IPA_UT_LOG("waiting for MSI\n");
2068 for (i = 0; i < 10; i++) {
2069 if (*((u32 *)test_mhi_ctx->msi.base) ==
2070 (0x10000000 |
2071 (IPA_MHI_TEST_FIRST_EVENT_RING_ID))) {
2072 IPA_UT_LOG("got MSI\n");
2073 timeout = false;
2074 break;
2075 }
2076 msleep(20);
2077 }
2078 } while (!timeout);
2079
2080 return 0;
2081}
2082
2083/**
2084 * To be run during test
2085 * 1. queue OUT RE/buffer
2086 * 2. wait for MSI on OUT
2087 * 3. Do 1. and 2. till got MSI wait timeout (ch full)
2088 * 4. suspend - it should fail with -EAGAIN - M1 is rejected
2089 * 5. foreach submitted pkt, do the next steps
2090 * 6. queue IN RE/buffer
2091 * 7. wait for MSI
2092 * 8. compare IN and OUT buffers
2093 */
2094static int ipa_mhi_test_suspend_full_channel(bool force)
2095{
2096 int rc;
2097 bool timeout;
2098 int submitted_packets = 0;
2099
2100 rc = ipa_mhi_test_create_full_channel(&submitted_packets);
2101 if (rc) {
2102 IPA_UT_LOG("fail create full channel\n");
2103 IPA_UT_TEST_FAIL_REPORT("fail create full channel");
2104 return rc;
2105 }
2106
2107 IPA_UT_LOG("BEFORE suspend\n");
2108 rc = ipa_mhi_test_suspend(force, false);
2109 if (rc) {
2110 IPA_UT_LOG("ipa_mhi_suspend did not returned -EAGAIN. rc %d\n",
2111 rc);
2112 IPA_UT_TEST_FAIL_REPORT("test suspend fail");
2113 return -EFAULT;
2114 }
2115 IPA_UT_LOG("AFTER suspend\n");
2116
2117 while (submitted_packets) {
2118 memset(test_mhi_ctx->in_buffer.base, 0,
2119 IPA_MHI_TEST_MAX_DATA_BUF_SIZE);
2120
2121 /* invalidate spare register value (for msi) */
2122 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
2123
2124 timeout = true;
2125 /* queue RE for IN side and trigger doorbell */
2126 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
2127 test_mhi_ctx->xfer_ring_bufs,
2128 test_mhi_ctx->ev_ring_bufs,
2129 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
2130 &test_mhi_ctx->in_buffer,
2131 1,
2132 true,
2133 true,
2134 false,
2135 true);
2136 if (rc) {
2137 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n",
2138 rc);
2139 IPA_UT_TEST_FAIL_REPORT("fail IN q re");
2140 return rc;
2141 }
2142
2143 IPA_MHI_TEST_CHECK_MSI_INTR(true, timeout);
2144 if (timeout) {
2145 IPA_UT_LOG("transfer failed - timeout\n");
2146 IPA_UT_TEST_FAIL_REPORT("timeout on xfer");
2147 return -EFAULT;
2148 }
2149
2150 /* compare the two buffers */
2151 if (memcmp(test_mhi_ctx->in_buffer.base,
2152 test_mhi_ctx->out_buffer.base,
2153 IPA_MHI_TEST_MAX_DATA_BUF_SIZE)) {
2154 IPA_UT_LOG("buffer are not equal\n");
2155 IPA_UT_TEST_FAIL_REPORT("non-equal buffers after xfer");
2156 return -EFAULT;
2157 }
2158
2159 submitted_packets--;
2160 }
2161
2162 return 0;
2163}
2164
2165/**
2166 * To be called from test
2167 * 1. suspend
2168 * 2. reset to M0 state
2169 */
2170static int ipa_mhi_test_suspend_and_reset(struct ipa_test_mhi_context *ctx)
2171{
2172 int rc;
2173
2174 IPA_UT_LOG("BEFORE suspend\n");
2175 rc = ipa_mhi_test_suspend(false, true);
2176 if (rc) {
2177 IPA_UT_LOG("suspend failed %d\n", rc);
2178 IPA_UT_TEST_FAIL_REPORT("suspend fail");
2179 return rc;
2180 }
2181 IPA_UT_LOG("AFTER suspend\n");
2182
2183 rc = ipa_mhi_test_reset(ctx, false);
2184 if (rc) {
2185 IPA_UT_LOG("reset failed rc=%d", rc);
2186 IPA_UT_TEST_FAIL_REPORT("reset fail");
2187 return rc;
2188 }
2189
2190 return 0;
2191}
2192
2193/**
2194 * To be run during test
2195 * 1. manualy update wp
2196 * 2. suspend - should succeed
2197 * 3. restore wp value
2198 */
2199static int ipa_mhi_test_suspend_wp_update(void)
2200{
2201 int rc;
2202 struct ipa_mhi_mmio_register_set *p_mmio;
2203 struct ipa_mhi_channel_context_array *p_ch_ctx_array;
2204 u64 old_wp;
2205 u64 phys_addr;
2206
2207 /* simulate a write by updating the wp */
2208 p_mmio = test_mhi_ctx->mmio_buf.base;
2209 phys_addr = p_mmio->ccabap + ((IPA_MHI_TEST_FIRST_CHANNEL_ID) *
2210 sizeof(struct ipa_mhi_channel_context_array));
2211 p_ch_ctx_array = test_mhi_ctx->ch_ctx_array.base +
2212 (phys_addr - test_mhi_ctx->ch_ctx_array.phys_base);
2213 old_wp = p_ch_ctx_array->wp;
2214 p_ch_ctx_array->wp += 16;
2215
2216 IPA_UT_LOG("BEFORE suspend\n");
2217 rc = ipa_mhi_test_suspend(false, false);
2218 if (rc) {
2219 IPA_UT_LOG("suspend failed rc %d\n", rc);
2220 IPA_UT_TEST_FAIL_REPORT("suspend fail");
2221 p_ch_ctx_array->wp = old_wp;
2222 return rc;
2223 }
2224 IPA_UT_LOG("AFTER suspend\n");
2225
2226 p_ch_ctx_array->wp = old_wp;
2227
2228 return 0;
2229}
2230
2231/**
2232 * To be run during test
2233 * 1. create open aggr by sending data
2234 * 2. channel reset (disconnect/connet)
2235 * 3. validate no aggr. open after reset
2236 * 4. disable aggr.
2237 */
2238static int ipa_mhi_test_channel_reset_aggr_open(void)
2239{
2240 int rc;
2241 u32 aggr_state_active;
2242 struct ipa_ep_cfg_aggr ep_aggr;
2243
2244 IPA_UT_LOG("Entry\n");
2245
2246 rc = ipa_mhi_test_create_aggr_open_frame();
2247 if (rc) {
2248 IPA_UT_LOG("failed create open aggr rc=%d\n", rc);
2249 IPA_UT_TEST_FAIL_REPORT("fail creare open aggr frame");
2250 return rc;
2251 }
2252
2253 rc = ipa_mhi_test_channel_reset();
2254 if (rc) {
2255 IPA_UT_LOG("channel reset failed rc=%d\n", rc);
2256 IPA_UT_TEST_FAIL_REPORT("channel reset fail");
2257 return rc;
2258 }
2259
2260 aggr_state_active = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
2261 IPADBG("IPA_STATE_AGGR_ACTIVE 0x%x\n", aggr_state_active);
2262 if (aggr_state_active != 0) {
2263 IPA_UT_LOG("aggregation frame open after reset!\n");
2264 IPA_UT_LOG("IPA_STATE_AGGR_ACTIVE 0x%x\n", aggr_state_active);
2265 IPA_UT_TEST_FAIL_REPORT("open aggr after reset");
2266 return -EFAULT;
2267 }
2268
2269 memset(&ep_aggr, 0, sizeof(ep_aggr));
2270 rc = ipa3_cfg_ep_aggr(test_mhi_ctx->cons_hdl, &ep_aggr);
2271 if (rc) {
2272 IPA_UT_LOG("failed to configure aggr");
2273 IPA_UT_TEST_FAIL_REPORT("fail to disable aggr");
2274 return rc;
2275 }
2276
2277 return rc;
2278}
2279
2280/**
2281 * To be run during test
2282 * 1. queue OUT RE/buffer
2283 * 2. wait for MSI on OUT
2284 * 3. Do 1. and 2. till got MSI wait timeout (ch full)
2285 * 4. channel reset
2286 * disconnect and reconnect the prod and cons
2287 * 5. queue IN RE/buffer and ring DB
2288 * 6. wait for MSI - should get timeout as channels were reset
2289 * 7. reset again
2290 */
2291static int ipa_mhi_test_channel_reset_ipa_holb(void)
2292{
2293 int rc;
2294 int submitted_packets = 0;
2295 bool timeout;
2296
2297 IPA_UT_LOG("Entry\n");
2298
2299 rc = ipa_mhi_test_create_full_channel(&submitted_packets);
2300 if (rc) {
2301 IPA_UT_LOG("fail create full channel rc=%d\n", rc);
2302 IPA_UT_TEST_FAIL_REPORT("fail create full channel");
2303 return rc;
2304 }
2305
2306 rc = ipa_mhi_test_channel_reset();
2307 if (rc) {
2308 IPA_UT_LOG("channel reset failed rc=%d\n", rc);
2309 IPA_UT_TEST_FAIL_REPORT("channel reset fail");
2310 return rc;
2311 }
2312
2313 /* invalidate spare register value (for msi) */
2314 memset(test_mhi_ctx->msi.base, 0xFF, test_mhi_ctx->msi.size);
2315 timeout = true;
2316 /* queue RE for IN side and trigger doorbell */
2317 rc = ipa_mhi_test_q_transfer_re(&test_mhi_ctx->mmio_buf,
2318 test_mhi_ctx->xfer_ring_bufs,
2319 test_mhi_ctx->ev_ring_bufs,
2320 IPA_MHI_TEST_FIRST_CHANNEL_ID + 1,
2321 &test_mhi_ctx->in_buffer,
2322 1,
2323 true,
2324 true,
2325 false,
2326 true);
2327
2328 if (rc) {
2329 IPA_UT_LOG("ipa_mhi_test_q_transfer_re failed %d\n", rc);
2330 IPA_UT_TEST_FAIL_REPORT("fail IN q re");
2331 return rc;
2332 }
2333 submitted_packets--;
2334
2335 IPA_MHI_TEST_CHECK_MSI_INTR(true, timeout);
2336 if (!timeout) {
2337 IPA_UT_LOG("transfer succeed although we had reset\n");
2338 IPA_UT_TEST_FAIL_REPORT("xfer succeed although we had reset");
2339 return -EFAULT;
2340 }
2341
2342 rc = ipa_mhi_test_channel_reset();
2343 if (rc) {
2344 IPA_UT_LOG("channel reset failed rc=%d\n", rc);
2345 IPA_UT_TEST_FAIL_REPORT("channel reset fail");
2346 return rc;
2347 }
2348
2349 return rc;
2350}
2351
2352
2353/**
2354 * TEST: mhi reset in READY state
2355 * 1. init to ready state (without start and connect)
2356 * 2. reset (destroy and re-init)
2357 * 2. destroy
2358 */
2359static int ipa_mhi_test_reset_ready_state(void *priv)
2360{
2361 int rc;
2362 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2363
2364 IPA_UT_LOG("Test Start\n");
2365
2366 if (unlikely(!ctx)) {
2367 IPA_UT_LOG("No context");
2368 return -EFAULT;
2369 }
2370
2371 rc = ipa_mhi_test_initialize_driver(true);
2372 if (rc) {
2373 IPA_UT_LOG("init to Ready state failed rc=%d\n", rc);
2374 IPA_UT_TEST_FAIL_REPORT("fail to init to ready state");
2375 return rc;
2376 }
2377
2378 rc = ipa_mhi_test_reset(ctx, true);
2379 if (rc) {
2380 IPA_UT_LOG("reset failed rc=%d", rc);
2381 IPA_UT_TEST_FAIL_REPORT("reset (destroy/re-init) failed");
2382 return rc;
2383 }
2384
2385 rc = ipa_mhi_test_destroy(ctx);
2386 if (rc) {
2387 IPA_UT_LOG("destroy failed rc=%d", rc);
2388 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2389 return rc;
2390 }
2391
2392 return 0;
2393}
2394
2395/**
2396 * TEST: mhi reset in M0 state
2397 * 1. init to M0 state (with start and connect)
2398 * 2. reset (destroy and re-init)
2399 * 2. destroy
2400 */
2401static int ipa_mhi_test_reset_m0_state(void *priv)
2402{
2403 int rc;
2404 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2405
2406 IPA_UT_LOG("Test Start\n");
2407
2408 if (unlikely(!ctx)) {
2409 IPA_UT_LOG("No context");
2410 return -EFAULT;
2411 }
2412
2413 rc = ipa_mhi_test_initialize_driver(false);
2414 if (rc) {
2415 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2416 IPA_UT_TEST_FAIL_REPORT
2417 ("fail to init to M0 state (w/ start and connect)");
2418 return rc;
2419 }
2420
2421 rc = ipa_mhi_test_reset(ctx, false);
2422 if (rc) {
2423 IPA_UT_LOG("reset failed rc=%d", rc);
2424 IPA_UT_TEST_FAIL_REPORT("reset (destroy/re-init) failed");
2425 return rc;
2426 }
2427
2428 rc = ipa_mhi_test_destroy(ctx);
2429 if (rc) {
2430 IPA_UT_LOG("destroy failed rc=%d", rc);
2431 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2432 return rc;
2433 }
2434
2435 return 0;
2436}
2437
2438/**
2439 * TEST: mhi in-loop reset in M0 state
2440 * 1. init to M0 state (with start and connect)
2441 * 2. reset (destroy and re-init) in-loop
2442 * 3. destroy
2443 */
2444static int ipa_mhi_test_inloop_reset_m0_state(void *priv)
2445{
2446 int rc;
2447 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2448
2449 IPA_UT_LOG("Test Start\n");
2450
2451 if (unlikely(!ctx)) {
2452 IPA_UT_LOG("No context");
2453 return -EFAULT;
2454 }
2455
2456 rc = ipa_mhi_test_initialize_driver(false);
2457 if (rc) {
2458 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2459 IPA_UT_TEST_FAIL_REPORT
2460 ("fail to init to M0 state (w/ start and connect)");
2461 return rc;
2462 }
2463
2464 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_reset, rc, ctx, false);
2465 if (rc) {
2466 IPA_UT_LOG("in-loop reset failed rc=%d", rc);
2467 IPA_UT_TEST_FAIL_REPORT(
2468 "reset (destroy/re-init) in loop failed");
2469 return rc;
2470 }
2471
2472 rc = ipa_mhi_test_destroy(ctx);
2473 if (rc) {
2474 IPA_UT_LOG("destroy failed rc=%d", rc);
2475 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2476 return rc;
2477 }
2478
2479 return 0;
2480}
2481
2482/**
2483 * TEST: mhi loopback data with reset
2484 * 1. init to M0 state (with start and connect)
2485 * 2. reset (destroy and re-init)
2486 * 3. loopback data
2487 * 4. reset (destroy and re-init)
2488 * 5. loopback data again
2489 * 6. destroy
2490 */
2491static int ipa_mhi_test_loopback_data_with_reset(void *priv)
2492{
2493 int rc;
2494 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2495
2496 IPA_UT_LOG("Test Start\n");
2497
2498 if (unlikely(!ctx)) {
2499 IPA_UT_LOG("No context");
2500 return -EFAULT;
2501 }
2502
2503 rc = ipa_mhi_test_initialize_driver(false);
2504 if (rc) {
2505 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2506 IPA_UT_TEST_FAIL_REPORT(
2507 "fail to init to M0 state (w/ start and connect)");
2508 return rc;
2509 }
2510
2511 rc = ipa_mhi_test_reset(ctx, false);
2512 if (rc) {
2513 IPA_UT_LOG("reset failed rc=%d", rc);
2514 IPA_UT_TEST_FAIL_REPORT("reset (destroy/re-init) failed");
2515 return rc;
2516 }
2517
2518 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2519 if (rc) {
2520 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2521 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2522 return rc;
2523 }
2524
2525 rc = ipa_mhi_test_reset(ctx, false);
2526 if (rc) {
2527 IPA_UT_LOG("reset failed rc=%d", rc);
2528 IPA_UT_TEST_FAIL_REPORT("reset (destroy/re-init) failed");
2529 return rc;
2530 }
2531
2532 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2533 if (rc) {
2534 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2535 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2536 return rc;
2537 }
2538
2539 rc = ipa_mhi_test_destroy(ctx);
2540 if (rc) {
2541 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2542 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2543 return rc;
2544 }
2545
2546 return 0;
2547}
2548
2549/**
2550 * TEST: mhi reset in suspend state
2551 * 1. init to M0 state (with start and connect)
2552 * 2. suspend
2553 * 3. reset (destroy and re-init)
2554 * 4. destroy
2555 */
2556static int ipa_mhi_test_reset_on_suspend(void *priv)
2557{
2558 int rc;
2559 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2560
2561 IPA_UT_LOG("Test Start\n");
2562
2563 if (unlikely(!ctx)) {
2564 IPA_UT_LOG("No context");
2565 return -EFAULT;
2566 }
2567
2568 rc = ipa_mhi_test_initialize_driver(false);
2569 if (rc) {
2570 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2571 IPA_UT_TEST_FAIL_REPORT(
2572 "fail to init to M0 state (w/ start and connect)");
2573 return -EFAULT;
2574 }
2575
2576 rc = ipa_mhi_test_suspend_and_reset(ctx);
2577 if (rc) {
2578 IPA_UT_LOG("suspend and reset failed %d\n", rc);
2579 IPA_UT_TEST_FAIL_REPORT("suspend and then reset failed");
2580 return rc;
2581 }
2582
2583 rc = ipa_mhi_test_destroy(ctx);
2584 if (rc) {
2585 IPA_UT_LOG("destroy failed %d\n", rc);
2586 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2587 return -EFAULT;
2588 }
2589
2590 return 0;
2591}
2592
2593/**
2594 * TEST: mhi in-loop reset in suspend state
2595 * 1. init to M0 state (with start and connect)
2596 * 2. suspend
2597 * 3. reset (destroy and re-init)
2598 * 4. Do 2 and 3 in loop
2599 * 3. destroy
2600 */
2601static int ipa_mhi_test_inloop_reset_on_suspend(void *priv)
2602{
2603 int rc;
2604 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2605
2606 IPA_UT_LOG("Test Start\n");
2607
2608 if (unlikely(!ctx)) {
2609 IPA_UT_LOG("No context");
2610 return -EFAULT;
2611 }
2612
2613 rc = ipa_mhi_test_initialize_driver(false);
2614 if (rc) {
2615 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2616 IPA_UT_TEST_FAIL_REPORT(
2617 "fail to init to M0 state (w/ start and connect)");
2618 return rc;
2619 }
2620
2621 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_and_reset, rc, ctx);
2622 if (rc) {
2623 IPA_UT_LOG("in-loop reset in suspend failed rc=%d", rc);
2624 IPA_UT_TEST_FAIL_REPORT("fail to in-loop reset while suspend");
2625 return rc;
2626 }
2627
2628 rc = ipa_mhi_test_destroy(ctx);
2629 if (rc) {
2630 IPA_UT_LOG("destroy failed rc=%d", rc);
2631 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2632 return rc;
2633 }
2634
2635 return 0;
2636}
2637
2638/**
2639 * TEST: mhi loopback data with reset
2640 * 1. init to M0 state (with start and connect)
2641 * 2. suspend
2642 * 3. reset (destroy and re-init)
2643 * 4. loopback data
2644 * 5. suspend
2645 * 5. reset (destroy and re-init)
2646 * 6. destroy
2647 */
2648static int ipa_mhi_test_loopback_data_with_reset_on_suspend(void *priv)
2649{
2650 int rc;
2651 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2652
2653 IPA_UT_LOG("Test Start\n");
2654
2655 if (unlikely(!ctx)) {
2656 IPA_UT_LOG("No context");
2657 return -EFAULT;
2658 }
2659
2660 rc = ipa_mhi_test_initialize_driver(false);
2661 if (rc) {
2662 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2663 IPA_UT_TEST_FAIL_REPORT(
2664 "fail to init to M0 state (w/ start and connect)");
2665 return rc;
2666 }
2667
2668 rc = ipa_mhi_test_suspend_and_reset(ctx);
2669 if (rc) {
2670 IPA_UT_LOG("suspend and reset failed rc=%d", rc);
2671 IPA_UT_TEST_FAIL_REPORT("fail to suspend and then reset");
2672 return rc;
2673 }
2674
2675 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2676 if (rc) {
2677 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2678 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2679 return rc;
2680 }
2681
2682 rc = ipa_mhi_test_suspend_and_reset(ctx);
2683 if (rc) {
2684 IPA_UT_LOG("suspend and reset failed rc=%d", rc);
2685 IPA_UT_TEST_FAIL_REPORT("fail to suspend and then reset");
2686 return rc;
2687 }
2688
2689 rc = ipa_mhi_test_destroy(ctx);
2690 if (rc) {
2691 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2692 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2693 return rc;
2694 }
2695
2696 return 0;
2697}
2698
2699/**
2700 * TEST: mhi loopback data after in loop suspend/resume
2701 * 1. init to M0 state (with start and connect)
2702 * 2. in loop suspend/resume
2703 * 3. loopback data
2704 * 4. destroy
2705 */
2706static int ipa_mhi_test_in_loop_suspend_resume(void *priv)
2707{
2708 int rc;
2709 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2710
2711 IPA_UT_LOG("Test Start\n");
2712
2713 if (unlikely(!ctx)) {
2714 IPA_UT_LOG("No context");
2715 return -EFAULT;
2716 }
2717
2718 rc = ipa_mhi_test_initialize_driver(false);
2719 if (rc) {
2720 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2721 IPA_UT_TEST_FAIL_REPORT(
2722 "fail to init to M0 state (w/ start and connect)");
2723 return rc;
2724 }
2725
2726 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_resume, rc);
2727 if (rc) {
2728 IPA_UT_LOG("suspend resume failed rc=%d", rc);
2729 IPA_UT_TEST_FAIL_REPORT("in loop suspend/resume failed");
2730 return rc;
2731 }
2732
2733 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2734 if (rc) {
2735 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2736 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2737 return rc;
2738 }
2739
2740 rc = ipa_mhi_test_destroy(ctx);
2741 if (rc) {
2742 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2743 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2744 return rc;
2745 }
2746
2747 return 0;
2748}
2749
2750/**
2751 * TEST: mhi loopback data after in loop suspend/resume with aggr open
2752 * 1. init to M0 state (with start and connect)
2753 * 2. in loop suspend/resume with open aggr.
2754 * 3. loopback data
2755 * 4. destroy
2756 */
2757static int ipa_mhi_test_in_loop_suspend_resume_aggr_open(void *priv)
2758{
2759 int rc;
2760 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2761
2762 IPA_UT_LOG("Test Start\n");
2763
2764 if (unlikely(!ctx)) {
2765 IPA_UT_LOG("No context");
2766 return -EFAULT;
2767 }
2768
2769 rc = ipa_mhi_test_initialize_driver(false);
2770 if (rc) {
2771 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2772 IPA_UT_TEST_FAIL_REPORT(
2773 "fail to init to M0 state (w/ start and connect)");
2774 return rc;
2775 }
2776
2777 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_aggr_open,
2778 rc, false);
2779 if (rc) {
2780 IPA_UT_LOG("suspend resume with aggr open failed rc=%d", rc);
2781 IPA_UT_TEST_FAIL_REPORT(
2782 "in loop suspend/resume with open aggr failed");
2783 return rc;
2784 }
2785
2786 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2787 if (rc) {
2788 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2789 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2790 return rc;
2791 }
2792
2793 rc = ipa_mhi_test_destroy(ctx);
2794 if (rc) {
2795 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2796 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2797 return rc;
2798 }
2799
2800 return 0;
2801}
2802
2803/**
2804 * TEST: mhi loopback data after in loop force suspend/resume with aggr open
2805 * 1. init to M0 state (with start and connect)
2806 * 2. in loop force suspend/resume with open aggr.
2807 * 3. loopback data
2808 * 4. destroy
2809 */
2810static int ipa_mhi_test_in_loop_force_suspend_resume_aggr_open(void *priv)
2811{
2812 int rc;
2813 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2814
2815 IPA_UT_LOG("Test Start\n");
2816
2817 if (unlikely(!ctx)) {
2818 IPA_UT_LOG("No context");
2819 return -EFAULT;
2820 }
2821
2822 rc = ipa_mhi_test_initialize_driver(false);
2823 if (rc) {
2824 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2825 IPA_UT_TEST_FAIL_REPORT(
2826 "fail to init to M0 state (w/ start and connect)");
2827 return rc;
2828 }
2829
2830 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_aggr_open,
2831 rc, true);
2832 if (rc) {
2833 IPA_UT_LOG("force suspend resume with aggr open failed rc=%d",
2834 rc);
2835 IPA_UT_TEST_FAIL_REPORT(
2836 "in loop force suspend/resume with open aggr failed");
2837 return rc;
2838 }
2839
2840 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2841 if (rc) {
2842 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2843 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2844 return rc;
2845 }
2846
2847 rc = ipa_mhi_test_destroy(ctx);
2848 if (rc) {
2849 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2850 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2851 return rc;
2852 }
2853
2854 return 0;
2855}
2856
2857/**
2858 * TEST: mhi loopback data after in loop suspend/host wakeup resume
2859 * 1. init to M0 state (with start and connect)
2860 * 2. in loop suspend/resume with host wakeup
2861 * 3. loopback data
2862 * 4. destroy
2863 */
2864static int ipa_mhi_test_in_loop_suspend_host_wakeup(void *priv)
2865{
2866 int rc;
2867 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2868
2869 IPA_UT_LOG("Test Start\n");
2870
2871 if (unlikely(!ctx)) {
2872 IPA_UT_LOG("No context");
2873 return -EFAULT;
2874 }
2875
2876 rc = ipa_mhi_test_initialize_driver(false);
2877 if (rc) {
2878 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2879 IPA_UT_TEST_FAIL_REPORT(
2880 "fail to init to M0 state (w/ start and connect)");
2881 return rc;
2882 }
2883
2884 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_host_wakeup, rc);
2885 if (rc) {
2886 IPA_UT_LOG("suspend host wakeup resume failed rc=%d", rc);
2887 IPA_UT_TEST_FAIL_REPORT(
2888 "in loop suspend/resume with hsot wakeup failed");
2889 return rc;
2890 }
2891
2892 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2893 if (rc) {
2894 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2895 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2896 return rc;
2897 }
2898
2899 rc = ipa_mhi_test_destroy(ctx);
2900 if (rc) {
2901 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2902 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2903 return rc;
2904 }
2905
2906 return 0;
2907}
2908
2909/**
2910 * TEST: mhi loopback data after in loop rejected suspend as full channel
2911 * 1. init to M0 state (with start and connect)
2912 * 2. in loop rejrected suspend
2913 * 3. loopback data
2914 * 4. destroy
2915 */
2916static int ipa_mhi_test_in_loop_reject_suspend_full_channel(void *priv)
2917{
2918 int rc;
2919 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2920
2921 IPA_UT_LOG("Test Start\n");
2922
2923 if (unlikely(!ctx)) {
2924 IPA_UT_LOG("No context");
2925 return -EFAULT;
2926 }
2927
2928 rc = ipa_mhi_test_initialize_driver(false);
2929 if (rc) {
2930 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2931 IPA_UT_TEST_FAIL_REPORT(
2932 "fail to init to M0 state (w/ start and connect)");
2933 return rc;
2934 }
2935
2936 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_full_channel,
2937 rc, false);
2938 if (rc) {
2939 IPA_UT_LOG("full channel rejected suspend failed rc=%d", rc);
2940 IPA_UT_TEST_FAIL_REPORT(
2941 "in loop rejected suspend due to full channel failed");
2942 return rc;
2943 }
2944
2945 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
2946 if (rc) {
2947 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
2948 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
2949 return rc;
2950 }
2951
2952 rc = ipa_mhi_test_destroy(ctx);
2953 if (rc) {
2954 IPA_UT_LOG("destroy failed rc=%d\n", rc);
2955 IPA_UT_TEST_FAIL_REPORT("destroy failed");
2956 return rc;
2957 }
2958
2959 return 0;
2960}
2961
2962/**
2963 * TEST: mhi loopback data after in loop rejected force suspend as full channel
2964 * 1. init to M0 state (with start and connect)
2965 * 2. in loop force rejected suspend
2966 * 3. loopback data
2967 * 4. destroy
2968 */
2969static int ipa_mhi_test_in_loop_reject_force_suspend_full_channel(void *priv)
2970{
2971 int rc;
2972 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
2973
2974 IPA_UT_LOG("Test Start\n");
2975
2976 if (unlikely(!ctx)) {
2977 IPA_UT_LOG("No context");
2978 return -EFAULT;
2979 }
2980
2981 rc = ipa_mhi_test_initialize_driver(false);
2982 if (rc) {
2983 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
2984 IPA_UT_TEST_FAIL_REPORT(
2985 "fail to init to M0 state (w/ start and connect)");
2986 return rc;
2987 }
2988
2989 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_full_channel,
2990 rc, true);
2991 if (rc) {
2992 IPA_UT_LOG("full channel rejected force suspend failed rc=%d",
2993 rc);
2994 IPA_UT_TEST_FAIL_REPORT(
2995 "in loop force rejected suspend as full ch failed");
2996 return rc;
2997 }
2998
2999 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
3000 if (rc) {
3001 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
3002 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
3003 return rc;
3004 }
3005
3006 rc = ipa_mhi_test_destroy(ctx);
3007 if (rc) {
3008 IPA_UT_LOG("destroy failed rc=%d\n", rc);
3009 IPA_UT_TEST_FAIL_REPORT("destroy failed");
3010 return rc;
3011 }
3012
3013 return 0;
3014}
3015
3016/**
3017 * TEST: mhi loopback data after in loop suspend after wp manual update
3018 * 1. init to M0 state (with start and connect)
3019 * 2. in loop suspend after wp update
3020 * 3. loopback data
3021 * 4. destroy
3022 */
3023static int ipa_mhi_test_in_loop_suspend_resume_wp_update(void *priv)
3024{
3025 int rc;
3026 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
3027
3028 IPA_UT_LOG("Test Start\n");
3029
3030 if (unlikely(!ctx)) {
3031 IPA_UT_LOG("No context");
3032 return -EFAULT;
3033 }
3034
3035 rc = ipa_mhi_test_initialize_driver(false);
3036 if (rc) {
3037 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
3038 IPA_UT_TEST_FAIL_REPORT(
3039 "fail to init to M0 state (w/ start and connect)");
3040 return rc;
3041 }
3042
3043 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_suspend_wp_update, rc);
3044 if (rc) {
3045 IPA_UT_LOG("suspend after wp update failed rc=%d", rc);
3046 IPA_UT_TEST_FAIL_REPORT(
3047 "in loop suspend after wp update failed");
3048 return rc;
3049 }
3050
3051 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
3052 if (rc) {
3053 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
3054 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
3055 return rc;
3056 }
3057
3058 rc = ipa_mhi_test_destroy(ctx);
3059 if (rc) {
3060 IPA_UT_LOG("destroy failed rc=%d\n", rc);
3061 IPA_UT_TEST_FAIL_REPORT("destroy failed");
3062 return rc;
3063 }
3064
3065 return 0;
3066}
3067
3068/**
3069 * TEST: mhi loopback data after in loop channel reset (disconnect/connect)
3070 * 1. init to M0 state (with start and connect)
3071 * 2. in loop channel reset (disconnect/connect)
3072 * 3. loopback data
3073 * 4. destroy
3074 */
3075static int ipa_mhi_test_in_loop_channel_reset(void *priv)
3076{
3077 int rc;
3078 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
3079
3080 IPA_UT_LOG("Test Start\n");
3081
3082 if (unlikely(!ctx)) {
3083 IPA_UT_LOG("No context");
3084 return -EFAULT;
3085 }
3086
3087 rc = ipa_mhi_test_initialize_driver(false);
3088 if (rc) {
3089 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
3090 IPA_UT_TEST_FAIL_REPORT(
3091 "fail to init to M0 state (w/ start and connect)");
3092 return rc;
3093 }
3094
3095 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_channel_reset, rc);
3096 if (rc) {
3097 IPA_UT_LOG("channel reset (disconnect/connect) failed rc=%d",
3098 rc);
3099 IPA_UT_TEST_FAIL_REPORT("in loop channel reset failed");
3100 return rc;
3101 }
3102
3103 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
3104 if (rc) {
3105 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
3106 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
3107 return rc;
3108 }
3109
3110 rc = ipa_mhi_test_destroy(ctx);
3111 if (rc) {
3112 IPA_UT_LOG("destroy failed rc=%d\n", rc);
3113 IPA_UT_TEST_FAIL_REPORT("destroy failed");
3114 return rc;
3115 }
3116
3117 return 0;
3118}
3119
3120/**
3121 * TEST: mhi loopback data after in loop channel reset (disconnect/connect)
3122 * 1. init to M0 state (with start and connect)
3123 * 2. in loop channel reset (disconnect/connect) with open aggr
3124 * 3. loopback data
3125 * 4. destroy
3126 */
3127static int ipa_mhi_test_in_loop_channel_reset_aggr_open(void *priv)
3128{
3129 int rc;
3130 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
3131
3132 IPA_UT_LOG("Test Start\n");
3133
3134 if (unlikely(!ctx)) {
3135 IPA_UT_LOG("No context");
3136 return -EFAULT;
3137 }
3138
3139 rc = ipa_mhi_test_initialize_driver(false);
3140 if (rc) {
3141 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
3142 IPA_UT_TEST_FAIL_REPORT(
3143 "fail to init to M0 state (w/ start and connect)");
3144 return rc;
3145 }
3146
3147 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_channel_reset_aggr_open, rc);
3148 if (rc) {
3149 IPA_UT_LOG("channel reset (disconnect/connect) failed rc=%d",
3150 rc);
3151 IPA_UT_TEST_FAIL_REPORT(
3152 "in loop channel reset with open aggr failed");
3153 return rc;
3154 }
3155
3156 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
3157 if (rc) {
3158 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
3159 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
3160 return rc;
3161 }
3162
3163 rc = ipa_mhi_test_destroy(ctx);
3164 if (rc) {
3165 IPA_UT_LOG("destroy failed rc=%d\n", rc);
3166 IPA_UT_TEST_FAIL_REPORT("destroy failed");
3167 return rc;
3168 }
3169
3170 return 0;
3171}
3172
3173/**
3174 * TEST: mhi loopback data after in loop channel reset (disconnect/connect)
3175 * 1. init to M0 state (with start and connect)
3176 * 2. in loop channel reset (disconnect/connect) with channel in HOLB
3177 * 3. loopback data
3178 * 4. destroy
3179 */
3180static int ipa_mhi_test_in_loop_channel_reset_ipa_holb(void *priv)
3181{
3182 int rc;
3183 struct ipa_test_mhi_context *ctx = (struct ipa_test_mhi_context *)priv;
3184
3185 IPA_UT_LOG("Test Start\n");
3186
3187 if (unlikely(!ctx)) {
3188 IPA_UT_LOG("No context");
3189 return -EFAULT;
3190 }
3191
3192 rc = ipa_mhi_test_initialize_driver(false);
3193 if (rc) {
3194 IPA_UT_LOG("init to M0 state failed rc=%d\n", rc);
3195 IPA_UT_TEST_FAIL_REPORT(
3196 "fail to init to M0 state (w/ start and connect)");
3197 return rc;
3198 }
3199
3200 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_channel_reset_ipa_holb, rc);
3201 if (rc) {
3202 IPA_UT_LOG("channel reset (disconnect/connect) failed rc=%d",
3203 rc);
3204 IPA_UT_TEST_FAIL_REPORT(
3205 "in loop channel reset with channel HOLB failed");
3206 return rc;
3207 }
3208
3209 IPA_MHI_RUN_TEST_UNIT_IN_LOOP(ipa_mhi_test_loopback_data_transfer, rc);
3210 if (rc) {
3211 IPA_UT_LOG("data loopback failed rc=%d\n", rc);
3212 IPA_UT_TEST_FAIL_REPORT("loopback data in loop failed");
3213 return rc;
3214 }
3215
3216 rc = ipa_mhi_test_destroy(ctx);
3217 if (rc) {
3218 IPA_UT_LOG("destroy failed rc=%d\n", rc);
3219 IPA_UT_TEST_FAIL_REPORT("destroy failed");
3220 return rc;
3221 }
3222
3223 return 0;
3224}
3225
3226/* Suite definition block */
3227IPA_UT_DEFINE_SUITE_START(mhi, "MHI for GSI",
3228 ipa_test_mhi_suite_setup, ipa_test_mhi_suite_teardown)
3229{
3230 IPA_UT_ADD_TEST(reset_ready_state,
3231 "reset test in Ready state",
3232 ipa_mhi_test_reset_ready_state,
3233 true, IPA_HW_v3_0, IPA_HW_MAX),
3234 IPA_UT_ADD_TEST(reset_m0_state,
3235 "reset test in M0 state",
3236 ipa_mhi_test_reset_m0_state,
3237 true, IPA_HW_v3_0, IPA_HW_MAX),
3238 IPA_UT_ADD_TEST(inloop_reset_m0_state,
3239 "several reset iterations in M0 state",
3240 ipa_mhi_test_inloop_reset_m0_state,
3241 true, IPA_HW_v3_0, IPA_HW_MAX),
3242 IPA_UT_ADD_TEST(loopback_data_with_reset_on_m0,
3243 "reset before and after loopback data in M0 state",
3244 ipa_mhi_test_loopback_data_with_reset,
3245 true, IPA_HW_v3_0, IPA_HW_MAX),
3246 IPA_UT_ADD_TEST(reset_on_suspend,
3247 "reset test in suspend state",
3248 ipa_mhi_test_reset_on_suspend,
3249 true, IPA_HW_v3_0, IPA_HW_MAX),
3250 IPA_UT_ADD_TEST(inloop_reset_on_suspend,
3251 "several reset iterations in suspend state",
3252 ipa_mhi_test_inloop_reset_on_suspend,
3253 true, IPA_HW_v3_0, IPA_HW_MAX),
3254 IPA_UT_ADD_TEST(loopback_data_with_reset_on_suspend,
3255 "reset before and after loopback data in suspend state",
3256 ipa_mhi_test_loopback_data_with_reset_on_suspend,
3257 true, IPA_HW_v3_0, IPA_HW_MAX),
3258 IPA_UT_ADD_TEST(suspend_resume,
3259 "several suspend/resume iterations",
3260 ipa_mhi_test_in_loop_suspend_resume,
3261 true, IPA_HW_v3_0, IPA_HW_MAX),
3262 IPA_UT_ADD_TEST(suspend_resume_with_open_aggr,
3263 "several suspend/resume iterations with open aggregation frame",
3264 ipa_mhi_test_in_loop_suspend_resume_aggr_open,
Michael Adisumarta6f78ef42017-12-13 17:22:13 -08003265 true, IPA_HW_v3_0, IPA_HW_v3_5_1),
Amir Levy9659e592016-10-27 18:08:27 +03003266 IPA_UT_ADD_TEST(force_suspend_resume_with_open_aggr,
3267 "several force suspend/resume iterations with open aggregation frame",
3268 ipa_mhi_test_in_loop_force_suspend_resume_aggr_open,
Michael Adisumarta6f78ef42017-12-13 17:22:13 -08003269 true, IPA_HW_v3_0, IPA_HW_v3_5_1),
Amir Levy9659e592016-10-27 18:08:27 +03003270 IPA_UT_ADD_TEST(suspend_resume_with_host_wakeup,
3271 "several suspend and host wakeup resume iterations",
3272 ipa_mhi_test_in_loop_suspend_host_wakeup,
3273 true, IPA_HW_v3_0, IPA_HW_MAX),
3274 IPA_UT_ADD_TEST(reject_suspend_channel_full,
3275 "several rejected suspend iterations due to full channel",
3276 ipa_mhi_test_in_loop_reject_suspend_full_channel,
3277 true, IPA_HW_v3_0, IPA_HW_MAX),
3278 IPA_UT_ADD_TEST(reject_force_suspend_channel_full,
3279 "several rejected force suspend iterations due to full channel",
3280 ipa_mhi_test_in_loop_reject_force_suspend_full_channel,
3281 true, IPA_HW_v3_0, IPA_HW_MAX),
3282 IPA_UT_ADD_TEST(suspend_resume_manual_wp_update,
3283 "several suspend/resume iterations with after simulating writing by wp manual update",
3284 ipa_mhi_test_in_loop_suspend_resume_wp_update,
3285 true, IPA_HW_v3_0, IPA_HW_MAX),
3286 IPA_UT_ADD_TEST(channel_reset,
3287 "several channel reset (disconnect/connect) iterations",
3288 ipa_mhi_test_in_loop_channel_reset,
3289 true, IPA_HW_v3_0, IPA_HW_MAX),
3290 IPA_UT_ADD_TEST(channel_reset_aggr_open,
3291 "several channel reset (disconnect/connect) iterations with open aggregation frame",
3292 ipa_mhi_test_in_loop_channel_reset_aggr_open,
3293 true, IPA_HW_v3_0, IPA_HW_MAX),
3294 IPA_UT_ADD_TEST(channel_reset_ipa_holb,
3295 "several channel reset (disconnect/connect) iterations with channel in HOLB state",
3296 ipa_mhi_test_in_loop_channel_reset_ipa_holb,
3297 true, IPA_HW_v3_0, IPA_HW_MAX),
3298} IPA_UT_DEFINE_SUITE_END(mhi);
3299