blob: 10f75758fa69271bb8aa2e3b11b658dc0a4a20c2 [file] [log] [blame]
Eric Holmberg6275b602012-11-19 13:05:04 -07001/* arch/arm/mach-msm/smp2p_test.c
2 *
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include <linux/debugfs.h>
15#include <linux/ctype.h>
16#include <linux/jiffies.h>
17#include <linux/delay.h>
18#include <linux/completion.h>
19#include "smp2p_private.h"
20#include "smp2p_test_common.h"
21
22/**
23 * smp2p_ut_local_basic - Basic sanity test using local loopback.
24 *
25 * @s: pointer to output file
26 *
27 * This test simulates a simple write and read
28 * when remote processor does not exist.
29 */
30static void smp2p_ut_local_basic(struct seq_file *s)
31{
32 int failed = 0;
33 struct msm_smp2p_out *smp2p_obj;
34 struct msm_smp2p_remote_mock *rmp = NULL;
35 int ret;
36 uint32_t test_request;
37 uint32_t test_response = 0;
38 static struct mock_cb_data cb_data;
39
40 seq_printf(s, "Running %s\n", __func__);
41 mock_cb_data_init(&cb_data);
42 do {
43 /* initialize mock edge and start opening */
44 ret = smp2p_reset_mock_edge();
45 UT_ASSERT_INT(ret, ==, 0);
46
47 rmp = msm_smp2p_get_remote_mock();
48 UT_ASSERT_PTR(rmp, !=, NULL);
49
50 rmp->rx_interrupt_count = 0;
51 memset(&rmp->remote_item, 0,
52 sizeof(struct smp2p_smem_item));
53
54 msm_smp2p_set_remote_mock_exists(false);
55
56 ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p",
57 &cb_data.nb, &smp2p_obj);
58 UT_ASSERT_INT(ret, ==, 0);
59
60 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
61 UT_ASSERT_INT(cb_data.cb_count, ==, 0);
62 rmp->rx_interrupt_count = 0;
63
64 /* simulate response from remote side */
65 rmp->remote_item.header.magic = SMP2P_MAGIC;
66 SMP2P_SET_LOCAL_PID(
67 rmp->remote_item.header.rem_loc_proc_id,
68 SMP2P_REMOTE_MOCK_PROC);
69 SMP2P_SET_REMOTE_PID(
70 rmp->remote_item.header.rem_loc_proc_id,
71 SMP2P_APPS_PROC);
72 SMP2P_SET_VERSION(
73 rmp->remote_item.header.feature_version, 1);
74 SMP2P_SET_FEATURES(
75 rmp->remote_item.header.feature_version, 0);
76 SMP2P_SET_ENT_TOTAL(
77 rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
78 SMP2P_SET_ENT_VALID(
79 rmp->remote_item.header.valid_total_ent, 0);
80 rmp->remote_item.header.reserved = 0x0;
81 msm_smp2p_set_remote_mock_exists(true);
82 rmp->tx_interrupt();
83
84 /* verify port was opened */
85 UT_ASSERT_INT(
86 (int)wait_for_completion_timeout(
87 &cb_data.cb_completion, HZ / 2), >, 0);
88 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
89 UT_ASSERT_INT(cb_data.event_open, ==, 1);
90 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2);
91
92 /* do write (test outbound entries) */
93 rmp->rx_interrupt_count = 0;
94 test_request = 0xC0DE;
95 ret = msm_smp2p_out_write(smp2p_obj, test_request);
96 UT_ASSERT_INT(ret, ==, 0);
97 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
98
99 /* do read (test inbound entries) */
100 ret = msm_smp2p_out_read(smp2p_obj, &test_response);
101 UT_ASSERT_INT(ret, ==, 0);
102 UT_ASSERT_INT(test_request, ==, test_response);
103
104 ret = msm_smp2p_out_close(&smp2p_obj);
105 UT_ASSERT_INT(ret, ==, 0);
106 UT_ASSERT_PTR(smp2p_obj, ==, 0);
107
108 seq_printf(s, "\tOK\n");
109 } while (0);
110
111 if (failed) {
112 pr_err("%s: Failed\n", __func__);
113 seq_printf(s, "\tFailed\n");
114 (void)msm_smp2p_out_close(&smp2p_obj);
115 }
116}
117
118/**
119 * smp2p_ut_local_late_open - Verify post-negotiation opening.
120 *
121 * @s: pointer to output file
122 *
123 * Verify entry creation for opening entries after negotiation is complete.
124 */
125static void smp2p_ut_local_late_open(struct seq_file *s)
126{
127 int failed = 0;
128 struct msm_smp2p_out *smp2p_obj;
129 struct msm_smp2p_remote_mock *rmp = NULL;
130 int ret;
131 uint32_t test_request;
132 uint32_t test_response = 0;
133 static struct mock_cb_data cb_data;
134
135 seq_printf(s, "Running %s\n", __func__);
136 mock_cb_data_init(&cb_data);
137 do {
138 /* initialize mock edge */
139 ret = smp2p_reset_mock_edge();
140 UT_ASSERT_INT(ret, ==, 0);
141
142 rmp = msm_smp2p_get_remote_mock();
143 UT_ASSERT_PTR(rmp, !=, NULL);
144
145 rmp->rx_interrupt_count = 0;
146 memset(&rmp->remote_item, 0,
147 sizeof(struct smp2p_smem_item));
148 rmp->remote_item.header.magic = SMP2P_MAGIC;
149 SMP2P_SET_LOCAL_PID(
150 rmp->remote_item.header.rem_loc_proc_id,
151 SMP2P_REMOTE_MOCK_PROC);
152 SMP2P_SET_REMOTE_PID(
153 rmp->remote_item.header.rem_loc_proc_id,
154 SMP2P_APPS_PROC);
155 SMP2P_SET_VERSION(
156 rmp->remote_item.header.feature_version, 1);
157 SMP2P_SET_FEATURES(
158 rmp->remote_item.header.feature_version, 0);
159 SMP2P_SET_ENT_TOTAL(
160 rmp->remote_item.header.valid_total_ent,
161 SMP2P_MAX_ENTRY);
162 SMP2P_SET_ENT_VALID(
163 rmp->remote_item.header.valid_total_ent, 0);
164 rmp->remote_item.header.reserved = 0x0;
165
166 msm_smp2p_set_remote_mock_exists(true);
167
168 ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p",
169 &cb_data.nb, &smp2p_obj);
170 UT_ASSERT_INT(ret, ==, 0);
171
172 /* verify port was opened */
173 UT_ASSERT_INT(
174 (int)wait_for_completion_timeout(
175 &cb_data.cb_completion, HZ / 2),
176 >, 0);
177 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
178 UT_ASSERT_INT(cb_data.event_open, ==, 1);
179 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2);
180
181 /* do write (test outbound entries) */
182 rmp->rx_interrupt_count = 0;
183 test_request = 0xC0DE;
184 ret = msm_smp2p_out_write(smp2p_obj, test_request);
185 UT_ASSERT_INT(ret, ==, 0);
186 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
187
188 /* do read (test inbound entries) */
189 ret = msm_smp2p_out_read(smp2p_obj, &test_response);
190 UT_ASSERT_INT(ret, ==, 0);
191 UT_ASSERT_INT(test_request, ==, test_response);
192
193 ret = msm_smp2p_out_close(&smp2p_obj);
194 UT_ASSERT_INT(ret, ==, 0);
195 UT_ASSERT_PTR(smp2p_obj, ==, 0);
196
197 seq_printf(s, "\tOK\n");
198 } while (0);
199
200 if (failed) {
201 pr_err("%s: Failed\n", __func__);
202 seq_printf(s, "\tFailed\n");
203 (void)msm_smp2p_out_close(&smp2p_obj);
204 }
205}
206
207/**
208 * smp2p_ut_local_early_open - Verify pre-negotiation opening.
209 *
210 * @s: pointer to output file
211 *
212 * Verify entry creation for opening entries before negotiation is complete.
213 */
214static void smp2p_ut_local_early_open(struct seq_file *s)
215{
216 int failed = 0;
217 struct msm_smp2p_out *smp2p_obj;
218 struct msm_smp2p_remote_mock *rmp = NULL;
219 struct smp2p_smem *outbound_item;
220 int negotiation_state;
221 int ret;
222 uint32_t test_request;
223 uint32_t test_response = 0;
224 static struct mock_cb_data cb_data;
225
226 seq_printf(s, "Running %s\n", __func__);
227 mock_cb_data_init(&cb_data);
228 do {
229 /* initialize mock edge, but don't enable, yet */
230 ret = smp2p_reset_mock_edge();
231 UT_ASSERT_INT(ret, ==, 0);
232
233 rmp = msm_smp2p_get_remote_mock();
234 UT_ASSERT_PTR(rmp, !=, NULL);
235
236 rmp->rx_interrupt_count = 0;
237 memset(&rmp->remote_item, 0,
238 sizeof(struct smp2p_smem_item));
239 rmp->remote_item.header.magic = SMP2P_MAGIC;
240 SMP2P_SET_LOCAL_PID(
241 rmp->remote_item.header.rem_loc_proc_id,
242 SMP2P_REMOTE_MOCK_PROC);
243 SMP2P_SET_REMOTE_PID(
244 rmp->remote_item.header.rem_loc_proc_id,
245 SMP2P_APPS_PROC);
246 SMP2P_SET_VERSION(
247 rmp->remote_item.header.feature_version, 1);
248 SMP2P_SET_FEATURES(
249 rmp->remote_item.header.feature_version, 0);
250 SMP2P_SET_ENT_TOTAL(
251 rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
252 SMP2P_SET_ENT_VALID(
253 rmp->remote_item.header.valid_total_ent, 0);
254 rmp->remote_item.header.reserved = 0x0;
255
256 msm_smp2p_set_remote_mock_exists(false);
257 UT_ASSERT_PTR(NULL, ==,
258 smp2p_get_in_item(SMP2P_REMOTE_MOCK_PROC));
259
260 /* initiate open, but verify it doesn't complete */
261 ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p",
262 &cb_data.nb, &smp2p_obj);
263 UT_ASSERT_INT(ret, ==, 0);
264
265 UT_ASSERT_INT(
266 (int)wait_for_completion_timeout(
267 &cb_data.cb_completion, HZ / 8),
268 ==, 0);
269 UT_ASSERT_INT(cb_data.cb_count, ==, 0);
270 UT_ASSERT_INT(cb_data.event_open, ==, 0);
271 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
272
273 outbound_item = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
274 &negotiation_state);
275 UT_ASSERT_PTR(outbound_item, !=, NULL);
276 UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENING);
277 UT_ASSERT_INT(0, ==,
278 SMP2P_GET_ENT_VALID(outbound_item->valid_total_ent));
279
280 /* verify that read/write don't work yet */
281 rmp->rx_interrupt_count = 0;
282 test_request = 0x0;
283 ret = msm_smp2p_out_write(smp2p_obj, test_request);
284 UT_ASSERT_INT(ret, ==, -ENODEV);
285 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0);
286
287 ret = msm_smp2p_out_read(smp2p_obj, &test_response);
288 UT_ASSERT_INT(ret, ==, -ENODEV);
289
290 /* allocate remote entry and verify open */
291 msm_smp2p_set_remote_mock_exists(true);
292 rmp->tx_interrupt();
293
294 UT_ASSERT_INT(
295 (int)wait_for_completion_timeout(
296 &cb_data.cb_completion, HZ / 2),
297 >, 0);
298 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
299 UT_ASSERT_INT(cb_data.event_open, ==, 1);
300 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2);
301
302 /* do write (test outbound entries) */
303 rmp->rx_interrupt_count = 0;
304 test_request = 0xC0DE;
305 ret = msm_smp2p_out_write(smp2p_obj, test_request);
306 UT_ASSERT_INT(ret, ==, 0);
307 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
308
309 /* do read (test inbound entries) */
310 ret = msm_smp2p_out_read(smp2p_obj, &test_response);
311 UT_ASSERT_INT(ret, ==, 0);
312 UT_ASSERT_INT(test_request, ==, test_response);
313
314 ret = msm_smp2p_out_close(&smp2p_obj);
315 UT_ASSERT_INT(ret, ==, 0);
316 UT_ASSERT_PTR(smp2p_obj, ==, 0);
317
318 seq_printf(s, "\tOK\n");
319 } while (0);
320
321 if (failed) {
322 pr_err("%s: Failed\n", __func__);
323 seq_printf(s, "\tFailed\n");
324 (void)msm_smp2p_out_close(&smp2p_obj);
325 }
326}
327
328/**
329 * smp2p_ut_mock_loopback - Exercise the remote loopback using remote mock.
330 *
331 * @s: pointer to output file
332 *
333 * This test exercises the remote loopback code using
334 * remote mock object. The remote mock object simulates the remote
335 * processor sending remote loopback commands to the local processor.
336 */
337static void smp2p_ut_mock_loopback(struct seq_file *s)
338{
339 int failed = 0;
340 struct msm_smp2p_remote_mock *rmp = NULL;
341 int ret;
342 uint32_t test_request = 0;
343 uint32_t test_response = 0;
344 struct msm_smp2p_out *local;
345
346 seq_printf(s, "Running %s\n", __func__);
347 do {
348 /* Initialize the mock edge */
349 ret = smp2p_reset_mock_edge();
350 UT_ASSERT_INT(ret, ==, 0);
351
352 rmp = msm_smp2p_get_remote_mock();
353 UT_ASSERT_PTR(rmp, !=, NULL);
354
355 memset(&rmp->remote_item, 0,
356 sizeof(struct smp2p_smem_item));
357 rmp->remote_item.header.magic = SMP2P_MAGIC;
358 SMP2P_SET_LOCAL_PID(
359 rmp->remote_item.header.rem_loc_proc_id,
360 SMP2P_REMOTE_MOCK_PROC);
361 SMP2P_SET_REMOTE_PID(
362 rmp->remote_item.header.rem_loc_proc_id,
363 SMP2P_APPS_PROC);
364 SMP2P_SET_VERSION(
365 rmp->remote_item.header.feature_version, 1);
366 SMP2P_SET_FEATURES(
367 rmp->remote_item.header.feature_version, 0);
368 SMP2P_SET_ENT_TOTAL(
369 rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
370 SMP2P_SET_ENT_VALID(
371 rmp->remote_item.header.valid_total_ent, 1);
372 rmp->remote_item.header.reserved = 0x0;
373 msm_smp2p_set_remote_mock_exists(true);
374
375 /* Create test entry and attach loopback server */
376 rmp->rx_interrupt_count = 0;
377 INIT_COMPLETION(rmp->cb_completion);
378 strlcpy(rmp->remote_item.entries[0].name, "smp2p",
379 SMP2P_MAX_ENTRY_NAME);
380 rmp->remote_item.entries[0].entry = 0;
381 rmp->tx_interrupt();
382
383 local = msm_smp2p_init_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC);
384 UT_ASSERT_INT(
385 (int)wait_for_completion_timeout(
386 &rmp->cb_completion, HZ / 2),
387 >, 0);
388 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2);
389
390 /* Send Echo Command */
391 rmp->rx_interrupt_count = 0;
392 INIT_COMPLETION(rmp->cb_completion);
393 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
394 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO);
395 SMP2P_SET_RMT_DATA(test_request, 10);
396 rmp->remote_item.entries[0].entry = test_request;
397 rmp->tx_interrupt();
398 UT_ASSERT_INT(
399 (int)wait_for_completion_timeout(
400 &rmp->cb_completion, HZ / 2),
401 >, 0);
402
403 /* Verify Echo Response */
404 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
405 ret = msm_smp2p_out_read(local,
406 &test_response);
407 UT_ASSERT_INT(ret, ==, 0);
408 test_response = SMP2P_GET_RMT_DATA(test_response);
409 UT_ASSERT_INT(test_response, ==, 10);
410
411 /* Send PINGPONG command */
412 test_request = 0;
413 test_response = 0;
414 rmp->rx_interrupt_count = 0;
415 INIT_COMPLETION(rmp->cb_completion);
416 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
417 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG);
418 SMP2P_SET_RMT_DATA(test_request, 10);
419 rmp->remote_item.entries[0].entry = test_request;
420 rmp->tx_interrupt();
421 UT_ASSERT_INT(
422 (int)wait_for_completion_timeout(
423 &rmp->cb_completion, HZ / 2),
424 >, 0);
425
426 /* Verify PINGPONG Response */
427 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
428 ret = msm_smp2p_out_read(local, &test_response);
429 UT_ASSERT_INT(ret, ==, 0);
430 test_response = SMP2P_GET_RMT_DATA(test_response);
431 UT_ASSERT_INT(test_response, ==, 9);
432
433 /* Send CLEARALL command */
434 test_request = 0;
435 test_response = 0;
436 rmp->rx_interrupt_count = 0;
437 INIT_COMPLETION(rmp->cb_completion);
438 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
439 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL);
440 SMP2P_SET_RMT_DATA(test_request, 10);
441 rmp->remote_item.entries[0].entry = test_request;
442 rmp->tx_interrupt();
443 UT_ASSERT_INT(
444 (int)wait_for_completion_timeout(
445 &rmp->cb_completion, HZ / 2),
446 >, 0);
447
448 /* Verify CLEARALL response */
449 UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
450 ret = msm_smp2p_out_read(local, &test_response);
451 UT_ASSERT_INT(ret, ==, 0);
452 test_response = SMP2P_GET_RMT_DATA(test_response);
453 UT_ASSERT_INT(test_response, ==, 0);
454
455 ret = msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC);
456 UT_ASSERT_INT(ret, ==, 0);
457 seq_printf(s, "\tOK\n");
458 } while (0);
459
460 if (failed) {
461 pr_err("%s: Failed\n", __func__);
462 seq_printf(s, "\tFailed\n");
463 msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC);
464 }
465}
466
467/**
468 * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality.
469 *
470 * @s: pointer to output file
471 * @remote_pid: Remote processor to test
472 *
473 * This test verifies inbound/outbound functionality for the remote processor.
474 */
475static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid)
476{
477 int failed = 0;
478 struct msm_smp2p_out *handle;
479 int ret;
480 uint32_t test_request;
481 uint32_t test_response = 0;
482 static struct mock_cb_data cb_out;
483 static struct mock_cb_data cb_in;
484
485 seq_printf(s, "Running %s for '%s' remote pid %d\n",
486 __func__, smp2p_pid_to_name(remote_pid), remote_pid);
487 mock_cb_data_init(&cb_out);
488 mock_cb_data_init(&cb_in);
489 do {
490 /* Open output entry */
491 ret = msm_smp2p_out_open(remote_pid, "smp2p",
492 &cb_out.nb, &handle);
493 UT_ASSERT_INT(ret, ==, 0);
494 UT_ASSERT_INT(
495 (int)wait_for_completion_timeout(
496 &cb_out.cb_completion, HZ / 2),
497 >, 0);
498 UT_ASSERT_INT(cb_out.cb_count, ==, 1);
499 UT_ASSERT_INT(cb_out.event_open, ==, 1);
500
501 /* Open inbound entry */
502 ret = msm_smp2p_in_register(remote_pid, "smp2p",
503 &cb_in.nb);
504 UT_ASSERT_INT(ret, ==, 0);
505 UT_ASSERT_INT(
506 (int)wait_for_completion_timeout(
507 &cb_in.cb_completion, HZ / 2),
508 >, 0);
509 UT_ASSERT_INT(cb_in.cb_count, ==, 1);
510 UT_ASSERT_INT(cb_in.event_open, ==, 1);
511
512 /* Write an echo request */
513 mock_cb_data_reset(&cb_out);
514 mock_cb_data_reset(&cb_in);
515 test_request = 0x0;
516 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
517 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO);
518 SMP2P_SET_RMT_DATA(test_request, 0xAA55);
519 ret = msm_smp2p_out_write(handle, test_request);
520 UT_ASSERT_INT(ret, ==, 0);
521
522 /* Verify inbound reply */
523 UT_ASSERT_INT(
524 (int)wait_for_completion_timeout(
525 &cb_in.cb_completion, HZ / 2),
526 >, 0);
527 UT_ASSERT_INT(cb_in.cb_count, ==, 1);
528 UT_ASSERT_INT(cb_in.event_entry_update, ==, 1);
529 UT_ASSERT_INT(SMP2P_GET_RMT_DATA(
530 cb_in.entry_data.current_value), ==, 0xAA55);
531
532 ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response);
533 UT_ASSERT_INT(ret, ==, 0);
534 UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response));
535 UT_ASSERT_INT(SMP2P_LB_CMD_ECHO, ==,
536 SMP2P_GET_RMT_CMD(test_response));
537 UT_ASSERT_INT(0xAA55, ==, SMP2P_GET_RMT_DATA(test_response));
538
539 /* Write a clear all request */
540 mock_cb_data_reset(&cb_in);
541 test_request = 0x0;
542 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
543 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL);
544 SMP2P_SET_RMT_DATA(test_request, 0xAA55);
545 ret = msm_smp2p_out_write(handle, test_request);
546 UT_ASSERT_INT(ret, ==, 0);
547
548 /* Verify inbound reply */
549 UT_ASSERT_INT(
550 (int)wait_for_completion_timeout(
551 &cb_in.cb_completion, HZ / 2),
552 >, 0);
553 UT_ASSERT_INT(cb_in.cb_count, ==, 1);
554 UT_ASSERT_INT(cb_in.event_entry_update, ==, 1);
555 UT_ASSERT_INT(SMP2P_GET_RMT_DATA(
556 cb_in.entry_data.current_value), ==, 0x0000);
557
558 ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response);
559 UT_ASSERT_INT(ret, ==, 0);
560 UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response));
561 UT_ASSERT_INT(0x0000, ==, SMP2P_GET_RMT_DATA(test_response));
562
563 /* Write a decrement request */
564 mock_cb_data_reset(&cb_in);
565 test_request = 0x0;
566 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
567 SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG);
568 SMP2P_SET_RMT_DATA(test_request, 0xAA55);
569 ret = msm_smp2p_out_write(handle, test_request);
570 UT_ASSERT_INT(ret, ==, 0);
571
572 /* Verify inbound reply */
573 UT_ASSERT_INT(
574 (int)wait_for_completion_timeout(
575 &cb_in.cb_completion, HZ / 2),
576 >, 0);
577 UT_ASSERT_INT(cb_in.cb_count, ==, 1);
578 UT_ASSERT_INT(cb_in.event_entry_update, ==, 1);
579 UT_ASSERT_INT(SMP2P_GET_RMT_DATA(
580 cb_in.entry_data.current_value), ==, 0xAA54);
581
582 ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response);
583 UT_ASSERT_INT(ret, ==, 0);
584 UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response));
585 UT_ASSERT_INT(SMP2P_LB_CMD_PINGPONG, ==,
586 SMP2P_GET_RMT_CMD(test_response));
587 UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response));
588
589 /* Test the ignore flag */
590 mock_cb_data_reset(&cb_in);
591 test_request = 0x0;
592 SMP2P_SET_RMT_CMD_TYPE(test_request, 1);
593 SMP2P_SET_RMT_CMD(test_request, SMP2P_RLPB_IGNORE);
594 SMP2P_SET_RMT_DATA(test_request, 0xAA55);
595 ret = msm_smp2p_out_write(handle, test_request);
596 UT_ASSERT_INT(ret, ==, 0);
597
598 UT_ASSERT_INT(
599 (int)wait_for_completion_timeout(
600 &cb_in.cb_completion, HZ / 2),
601 ==, 0);
602 UT_ASSERT_INT(cb_in.cb_count, ==, 0);
603 UT_ASSERT_INT(cb_in.event_entry_update, ==, 0);
604 ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response);
605 UT_ASSERT_INT(ret, ==, 0);
606 UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response));
607
608 /* Cleanup */
609 ret = msm_smp2p_out_close(&handle);
610 UT_ASSERT_INT(ret, ==, 0);
611 UT_ASSERT_PTR(handle, ==, 0);
612 ret = msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb);
613 UT_ASSERT_INT(ret, ==, 0);
614
615 seq_printf(s, "\tOK\n");
616 } while (0);
617
618 if (failed) {
619 if (handle)
620 (void)msm_smp2p_out_close(&handle);
621 (void)msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb);
622
623 pr_err("%s: Failed\n", __func__);
624 seq_printf(s, "\tFailed\n");
625 }
626}
627
628/**
629 * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all.
630 *
631 * @s: pointer to output file
632 *
633 * This test verifies inbound and outbound functionality for all
634 * configured remote processor.
635 */
636static void smp2p_ut_remote_inout(struct seq_file *s)
637{
638 struct smp2p_interrupt_config *int_cfg;
639 int pid;
640
641 int_cfg = smp2p_get_interrupt_config();
642 if (!int_cfg) {
643 seq_printf(s,
644 "Remote processor config unavailable\n");
645 return;
646 }
647
648 for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
649 if (!int_cfg[pid].is_configured)
650 continue;
651
652 msm_smp2p_deinit_rmt_lpb_proc(pid);
653 smp2p_ut_remote_inout_core(s, pid);
654 msm_smp2p_init_rmt_lpb_proc(pid);
655 }
656}
657
658/**
659 * smp2p_ut_remote_out_max_entries_core - Verify open functionality.
660 *
661 * @s: pointer to output file
662 * @remote_pid: Remote processor for which the test is executed.
663 *
664 * This test verifies open functionality by creating maximum outbound entries.
665 */
666static void smp2p_ut_remote_out_max_entries_core(struct seq_file *s,
667 int remote_pid)
668{
669 int j = 0;
670 int failed = 0;
671 struct msm_smp2p_out *handle[SMP2P_MAX_ENTRY];
672 int ret;
673 static struct mock_cb_data cb_out[SMP2P_MAX_ENTRY];
674 char entry_name[SMP2P_MAX_ENTRY_NAME];
675 int num_created;
676
677 seq_printf(s, "Running %s for '%s' remote pid %d\n",
678 __func__, smp2p_pid_to_name(remote_pid), remote_pid);
679
680 for (j = 0; j < SMP2P_MAX_ENTRY; j++) {
681 handle[j] = NULL;
682 mock_cb_data_init(&cb_out[j]);
683 }
684
685 do {
686 num_created = 0;
687 for (j = 0; j < SMP2P_MAX_ENTRY; j++) {
688 /* Open as many output entries as possible */
689 scnprintf((char *)entry_name, SMP2P_MAX_ENTRY_NAME,
690 "smp2p%d", j);
691 ret = msm_smp2p_out_open(remote_pid, entry_name,
692 &cb_out[j].nb, &handle[j]);
693 if (ret == -ENOMEM)
694 /* hit max number */
695 break;
696 UT_ASSERT_INT(ret, ==, 0);
697 ++num_created;
698 }
699 if (failed)
700 break;
701
702 /* verify we created more than 1 entry */
703 UT_ASSERT_INT(num_created, <=, SMP2P_MAX_ENTRY);
704 UT_ASSERT_INT(num_created, >, 0);
705
706 seq_printf(s, "\tOK\n");
707 } while (0);
708
709 if (failed) {
710 pr_err("%s: Failed\n", __func__);
711 seq_printf(s, "\tFailed\n");
712 }
713
714 /* cleanup */
715 for (j = 0; j < SMP2P_MAX_ENTRY; j++)
716 ret = msm_smp2p_out_close(&handle[j]);
717}
718
719/**
720 * smp2p_ut_remote_out_max_entries - Verify open for all configured processors.
721 *
722 * @s: pointer to output file
723 *
724 * This test verifies creating max number of entries for
725 * all configured remote processor.
726 */
727static void smp2p_ut_remote_out_max_entries(struct seq_file *s)
728{
729 struct smp2p_interrupt_config *int_cfg;
730 int pid;
731
732 int_cfg = smp2p_get_interrupt_config();
733 if (!int_cfg) {
734 seq_printf(s,
735 "Remote processor config unavailable\n");
736 return;
737 }
738
739 for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
740 if (!int_cfg[pid].is_configured)
741 continue;
742
743 smp2p_ut_remote_out_max_entries_core(s, pid);
744 }
745}
746
747/**
748 * smp2p_ut_local_in_max_entries - Verify registering and unregistering.
749 *
750 * @s: pointer to output file
751 *
752 * This test verifies registering and unregistering for inbound entries using
753 * the remote mock processor.
754 */
755static void smp2p_ut_local_in_max_entries(struct seq_file *s)
756{
757 int j = 0;
758 int failed = 0;
759 struct msm_smp2p_remote_mock *rmp = NULL;
760 int ret;
761 static struct mock_cb_data cb_in[SMP2P_MAX_ENTRY];
762 static struct mock_cb_data cb_out;
763
764 seq_printf(s, "Running %s\n", __func__);
765
766 for (j = 0; j < SMP2P_MAX_ENTRY; j++)
767 mock_cb_data_init(&cb_in[j]);
768
769 mock_cb_data_init(&cb_out);
770
771 do {
772 /* Initialize mock edge */
773 ret = smp2p_reset_mock_edge();
774 UT_ASSERT_INT(ret, ==, 0);
775
776 rmp = msm_smp2p_get_remote_mock();
777 UT_ASSERT_PTR(rmp, !=, NULL);
778
779 rmp->rx_interrupt_count = 0;
780 memset(&rmp->remote_item, 0,
781 sizeof(struct smp2p_smem_item));
782 rmp->remote_item.header.magic = SMP2P_MAGIC;
783 SMP2P_SET_LOCAL_PID(
784 rmp->remote_item.header.rem_loc_proc_id,
785 SMP2P_REMOTE_MOCK_PROC);
786 SMP2P_SET_REMOTE_PID(
787 rmp->remote_item.header.rem_loc_proc_id,
788 SMP2P_APPS_PROC);
789 SMP2P_SET_VERSION(
790 rmp->remote_item.header.feature_version, 1);
791 SMP2P_SET_FEATURES(
792 rmp->remote_item.header.feature_version, 0);
793 SMP2P_SET_ENT_TOTAL(
794 rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
795 SMP2P_SET_ENT_VALID(
796 rmp->remote_item.header.valid_total_ent, 0);
797 rmp->remote_item.header.reserved = 0x0;
798 msm_smp2p_set_remote_mock_exists(true);
799
800 /* Create Max Entries in the remote mock object */
801 for (j = 0; j < SMP2P_MAX_ENTRY; j++) {
802 scnprintf(rmp->remote_item.entries[j].name,
803 SMP2P_MAX_ENTRY_NAME, "smp2p%d", j);
804 rmp->remote_item.entries[j].entry = 0;
805 rmp->tx_interrupt();
806 }
807
808 /* Register for in entries */
809 for (j = 0; j < SMP2P_MAX_ENTRY; j++) {
810 ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC,
811 rmp->remote_item.entries[j].name,
812 &(cb_in[j].nb));
813 UT_ASSERT_INT(ret, ==, 0);
814 UT_ASSERT_INT(
815 (int)wait_for_completion_timeout(
816 &(cb_in[j].cb_completion), HZ / 2),
817 >, 0);
818 UT_ASSERT_INT(cb_in[j].cb_count, ==, 1);
819 UT_ASSERT_INT(cb_in[j].event_entry_update, ==, 0);
820 }
821 UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY);
822
823 /* Unregister */
824 for (j = 0; j < SMP2P_MAX_ENTRY; j++) {
825 ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC,
826 rmp->remote_item.entries[j].name,
827 &(cb_in[j].nb));
828 UT_ASSERT_INT(ret, ==, 0);
829 }
830 UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY);
831
832 seq_printf(s, "\tOK\n");
833 } while (0);
834
835 if (failed) {
836 pr_err("%s: Failed\n", __func__);
837 seq_printf(s, "\tFailed\n");
838
839 for (j = 0; j < SMP2P_MAX_ENTRY; j++)
840 ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC,
841 rmp->remote_item.entries[j].name,
842 &(cb_in[j].nb));
843 }
844}
845
846static struct dentry *dent;
847
848static int debugfs_show(struct seq_file *s, void *data)
849{
850 void (*show)(struct seq_file *) = s->private;
851
852 show(s);
853
854 return 0;
855}
856
857static int debug_open(struct inode *inode, struct file *file)
858{
859 return single_open(file, debugfs_show, inode->i_private);
860}
861
862static const struct file_operations debug_ops = {
863 .open = debug_open,
864 .release = single_release,
865 .read = seq_read,
866 .llseek = seq_lseek,
867};
868
869void smp2p_debug_create(const char *name,
870 void (*show)(struct seq_file *))
871{
872 struct dentry *file;
873
874 file = debugfs_create_file(name, 0444, dent, show, &debug_ops);
875 if (!file)
876 pr_err("%s: unable to create file '%s'\n", __func__, name);
877}
878
879static int __init smp2p_debugfs_init(void)
880{
881 dent = debugfs_create_dir("smp2p_test", 0);
882 if (IS_ERR(dent))
883 return PTR_ERR(dent);
884
885 /*
886 * Add Unit Test entries.
887 *
888 * The idea with unit tests is that you can run all of them
889 * from ADB shell by doing:
890 * adb shell
891 * cat ut*
892 *
893 * And if particular tests fail, you can then repeatedly run the
894 * failing tests as you debug and resolve the failing test.
895 */
896 smp2p_debug_create("ut_local_basic",
897 smp2p_ut_local_basic);
898 smp2p_debug_create("ut_local_late_open",
899 smp2p_ut_local_late_open);
900 smp2p_debug_create("ut_local_early_open",
901 smp2p_ut_local_early_open);
902 smp2p_debug_create("ut_mock_loopback",
903 smp2p_ut_mock_loopback);
904 smp2p_debug_create("ut_remote_inout",
905 smp2p_ut_remote_inout);
906 smp2p_debug_create("ut_local_in_max_entries",
907 smp2p_ut_local_in_max_entries);
908 smp2p_debug_create("ut_remote_out_max_entries",
909 smp2p_ut_remote_out_max_entries);
910
911 return 0;
912}
913module_init(smp2p_debugfs_init);