blob: 2804e4f4fd3117ca56203d072fdfd908820e6a5e [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
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/*
14 * SDIO-Abstraction-Layer Test Module.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/workqueue.h>
21#include <linux/fs.h>
22#include <linux/cdev.h>
23#include <linux/sched.h>
24#include <linux/wait.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <linux/random.h>
28#include <linux/platform_device.h>
29#include <mach/sdio_smem.h>
30#include <linux/wakelock.h>
31
32#include <sdio_al_private.h>
33#include <linux/debugfs.h>
34
35#include <linux/kthread.h>
36enum lpm_test_msg_type {
Yaniv Gardi3e327762011-07-27 11:11:04 +030037 LPM_NO_MSG, /* 0 */
38 LPM_MSG_SEND, /* 1 */
39 LPM_MSG_REC, /* 2 */
40 LPM_SLEEP, /* 3 */
41 LPM_WAKEUP, /* 4 */
42 LPM_NOTIFY /* 5 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043};
44
45#define LPM_NO_MSG_NAME "LPM No Event"
46#define LPM_MSG_SEND_NAME "LPM Send Msg Event"
47#define LPM_MSG_REC_NAME "LPM Receive Msg Event"
48#define LPM_SLEEP_NAME "LPM Sleep Event"
49#define LPM_WAKEUP_NAME "LPM Wakeup Event"
50
51/** Module name string */
52#define TEST_MODULE_NAME "sdio_al_test"
53
54#define TEST_SIGNATURE 0x12345678
55#define TEST_CONFIG_SIGNATURE 0xBEEFCAFE
56
57#define MAX_XFER_SIZE (16*1024)
58#define SMEM_MAX_XFER_SIZE 0xBC000
59#define A2_MIN_PACKET_SIZE 5
60
61#define TEST_DBG(x...) if (test_ctx->runtime_debug) pr_info(x)
62
63#define LPM_TEST_NUM_OF_PACKETS 100
Yaniv Gardi3e327762011-07-27 11:11:04 +030064#define LPM_MAX_OPEN_CHAN_PER_DEV 4
65#define LPM_ARRAY_SIZE (7*LPM_TEST_NUM_OF_PACKETS*LPM_MAX_OPEN_CHAN_PER_DEV)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070066#define SDIO_LPM_TEST "sdio_lpm_test_reading_task"
67#define LPM_TEST_CONFIG_SIGNATURE 0xDEADBABE
Yaniv Gardi3e327762011-07-27 11:11:04 +030068#define LPM_MSG_NAME_SIZE 20
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070069
70enum sdio_test_case_type {
71 SDIO_TEST_LOOPBACK_HOST,
72 SDIO_TEST_LOOPBACK_CLIENT,
73 SDIO_TEST_LPM_HOST_WAKER,
74 SDIO_TEST_LPM_CLIENT_WAKER,
75 SDIO_TEST_LPM_RANDOM,
76 SDIO_TEST_HOST_SENDER_NO_LP,
77 SDIO_TEST_PERF, /* must be last since is not part of the 9k tests */
78};
79
80struct lpm_task {
81 struct task_struct *lpm_task;
82 const char *task_name;
83};
84
85struct lpm_entry_type {
86 enum lpm_test_msg_type msg_type;
Yaniv Gardi3e327762011-07-27 11:11:04 +030087 char msg_name[LPM_MSG_NAME_SIZE];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070088 u32 counter;
89 u32 current_ms;
Yaniv Gardi3e327762011-07-27 11:11:04 +030090 u32 read_avail_mask;
91 char chan_name[CHANNEL_NAME_SIZE];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092};
93
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094struct lpm_msg {
95 u32 signature;
96 u32 counter;
97 u32 reserve1;
98 u32 reserve2;
99};
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101struct test_config_msg {
102 u32 signature;
103 u32 test_case;
104 u32 test_param;
105 u32 num_packets;
106 u32 num_iterations;
107};
108
109struct test_result_msg {
110 u32 signature;
111 u32 is_successful;
112};
113
114struct test_work {
115 struct work_struct work;
116 struct test_channel *test_ch;
117};
118
119enum sdio_channels_ids {
120 SDIO_RPC,
121 SDIO_QMI,
122 SDIO_RMNT,
123 SDIO_DIAG,
124 SDIO_DUN,
125 SDIO_SMEM,
126 SDIO_CIQ,
127 SDIO_MAX_CHANNELS
128};
129
130enum sdio_test_results {
131 TEST_NO_RESULT,
132 TEST_FAILED,
133 TEST_PASSED
134};
135
136enum sdio_lpm_vote_state {
137 SDIO_NO_VOTE,
138 SDIO_VOTE_FOR_SLEEP,
139 SDIO_VOTE_AGAINST_SLEEP
140};
141
Yaniv Gardi3e327762011-07-27 11:11:04 +0300142struct sdio_test_device {
143 int open_channels_counter_to_recv;
144 int open_channels_counter_to_send;
145 struct lpm_entry_type *lpm_arr;
146 int array_size;
147 void *sdio_al_device;
148 spinlock_t lpm_array_lock;
149 unsigned long lpm_array_lock_flags;
150 u32 next_avail_entry_in_array;
151 struct lpm_task lpm_test_task;
152 u32 next_mask_id;
153 u32 read_avail_mask;
154 int modem_result_per_dev;
155 int final_result_per_dev;
156};
157
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158struct test_channel {
159 struct sdio_channel *ch;
160
161 char name[CHANNEL_NAME_SIZE];
162 int ch_id;
163
Yaniv Gardi3e327762011-07-27 11:11:04 +0300164 struct sdio_test_device *test_device;
165
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 u32 *buf;
167 u32 buf_size;
168
169 struct workqueue_struct *workqueue;
170 struct test_work test_work;
171
172 u32 rx_bytes;
173 u32 tx_bytes;
174
175 wait_queue_head_t wait_q;
176 atomic_t rx_notify_count;
177 atomic_t tx_notify_count;
178 atomic_t any_notify_count;
179 atomic_t wakeup_client;
180
181 int wait_counter;
182
183 int is_used;
184 int test_type;
185 int ch_ready;
186
187 struct test_config_msg config_msg;
188
189 int test_completed;
190 int test_result;
191 struct timer_list timer;
192 int timer_interval_ms;
193
194 struct timer_list timeout_timer;
195 int timeout_ms;
196 void *sdio_al_device;
197 int is_ok_to_sleep;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700198 unsigned int packet_length;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199 int random_packet_size;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300200 int next_index_in_sent_msg_per_chan;
201 int channel_mask_id;
202 int modem_result_per_chan;
203 int notify_counter_per_chan;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204};
205
206struct sdio_al_test_debug {
207 u32 dun_throughput;
208 u32 rmnt_throughput;
209 struct dentry *debug_root;
210 struct dentry *debug_test_result;
211 struct dentry *debug_dun_throughput;
212 struct dentry *debug_rmnt_throughput;
213};
214
215struct test_context {
216 dev_t dev_num;
217 struct device *dev;
218 struct cdev *cdev;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300219 int number_of_active_devices;
220 int max_number_of_devices;
221
222 struct sdio_test_device test_dev_arr[MAX_NUM_OF_SDIO_DEVICES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700223
224 struct test_channel *test_ch;
225
226 struct test_channel *test_ch_arr[SDIO_MAX_CHANNELS];
227
228 long testcase;
229
230 const char *name;
231
232 int exit_flag;
233
234 u32 signature;
235
236 int runtime_debug;
237
238 struct platform_device smem_pdev;
239 struct sdio_smem_client *sdio_smem;
240 int smem_was_init;
241 u8 *smem_buf;
242
243 wait_queue_head_t wait_q;
244 int test_completed;
245 int test_result;
246 struct sdio_al_test_debug debug;
247
248 struct wake_lock wake_lock;
249};
250
251/*
252 * Seed for pseudo random time sleeping in Random LPM test.
253 * If not set, current time in jiffies is used.
254 */
255static unsigned int seed;
256module_param(seed, int, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700257static struct test_context *test_ctx;
258
259#ifdef CONFIG_DEBUG_FS
260/*
261*
262* Trigger on/off for debug messages
263* for trigger off the data messages debug level use:
264* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
265* for trigger on the data messages debug level use:
266* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
267* for trigger off the lpm messages debug level use:
268* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
269* for trigger on the lpm messages debug level use:
270* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
271*/
272static int sdio_al_test_debugfs_init(void)
273{
274 test_ctx->debug.debug_root = debugfs_create_dir("sdio_al_test",
275 NULL);
276 if (!test_ctx->debug.debug_root)
277 return -ENOENT;
278
279 test_ctx->debug.debug_test_result = debugfs_create_u32(
280 "test_result",
281 S_IRUGO | S_IWUGO,
282 test_ctx->debug.debug_root,
283 &test_ctx->test_result);
284
285 test_ctx->debug.debug_dun_throughput = debugfs_create_u32(
286 "dun_throughput",
287 S_IRUGO | S_IWUGO,
288 test_ctx->debug.debug_root,
289 &test_ctx->debug.dun_throughput);
290
291 test_ctx->debug.debug_rmnt_throughput = debugfs_create_u32(
292 "rmnt_throughput",
293 S_IRUGO | S_IWUGO,
294 test_ctx->debug.debug_root,
295 &test_ctx->debug.rmnt_throughput);
296
297 if ((!test_ctx->debug.debug_dun_throughput) &&
298 (!test_ctx->debug.debug_rmnt_throughput)) {
299 debugfs_remove_recursive(test_ctx->debug.debug_root);
300 test_ctx->debug.debug_root = NULL;
301 return -ENOENT;
302 }
303 return 0;
304}
305
306static void sdio_al_test_debugfs_cleanup(void)
307{
308 debugfs_remove(test_ctx->debug.debug_dun_throughput);
309 debugfs_remove(test_ctx->debug.debug_rmnt_throughput);
310 debugfs_remove(test_ctx->debug.debug_root);
311}
312#endif
313
314static int channel_name_to_id(char *name)
315{
316 pr_info(TEST_MODULE_NAME "%s: channel name %s\n",
317 __func__, name);
318
319 if (!strncmp(name, "SDIO_RPC", strnlen("SDIO_RPC", CHANNEL_NAME_SIZE)))
320 return SDIO_RPC;
321 else if (!strncmp(name, "SDIO_QMI",
322 strnlen("SDIO_QMI", CHANNEL_NAME_SIZE)))
323 return SDIO_QMI;
324 else if (!strncmp(name, "SDIO_RMNT",
325 strnlen("SDIO_RMNT", CHANNEL_NAME_SIZE)))
326 return SDIO_RMNT;
327 else if (!strncmp(name, "SDIO_DIAG",
328 strnlen("SDIO_DIAG", CHANNEL_NAME_SIZE)))
329 return SDIO_DIAG;
330 else if (!strncmp(name, "SDIO_DUN",
331 strnlen("SDIO_DUN", CHANNEL_NAME_SIZE)))
332 return SDIO_DUN;
333 else if (!strncmp(name, "SDIO_SMEM",
334 strnlen("SDIO_SMEM", CHANNEL_NAME_SIZE)))
335 return SDIO_SMEM;
336 else if (!strncmp(name, "SDIO_CIQ",
337 strnlen("SDIO_CIQ", CHANNEL_NAME_SIZE)))
338 return SDIO_CIQ;
339 else
340 return SDIO_MAX_CHANNELS;
341
342 return SDIO_MAX_CHANNELS;
343}
344
345/**
346 * Config message
347 */
348
349static void send_config_msg(struct test_channel *test_ch)
350{
351 int ret = 0 ;
352 u32 write_avail = 0;
353 int size = sizeof(test_ch->config_msg);
354
355 pr_debug(TEST_MODULE_NAME "%s\n", __func__);
356
357 memcpy(test_ch->buf, (void *)&test_ch->config_msg, size);
358
359 if (test_ctx->exit_flag) {
360 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
361 return;
362 }
363
364 pr_info(TEST_MODULE_NAME ":Sending the config message.\n");
365
366 /* wait for data ready event */
367 write_avail = sdio_write_avail(test_ch->ch);
368 pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
369 if (write_avail < size) {
370 wait_event(test_ch->wait_q,
371 atomic_read(&test_ch->tx_notify_count));
372 atomic_dec(&test_ch->tx_notify_count);
373 }
374
375 write_avail = sdio_write_avail(test_ch->ch);
376 pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
377 if (write_avail < size) {
378 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
379 return;
380 }
381
382 ret = sdio_write(test_ch->ch, test_ch->buf, size);
383 if (ret)
384 pr_err(TEST_MODULE_NAME ":%s sdio_write err=%d.\n",
385 __func__, -ret);
386 else
387 pr_info(TEST_MODULE_NAME ":%s sent config_msg successfully.\n",
388 __func__);
389}
390
391/**
392 * Loopback Test
393 */
394static void loopback_test(struct test_channel *test_ch)
395{
396 int ret = 0 ;
397 u32 read_avail = 0;
398 u32 write_avail = 0;
399
400 while (1) {
401
402 if (test_ctx->exit_flag) {
403 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
404 return;
405 }
406
407 TEST_DBG(TEST_MODULE_NAME "--LOOPBACK WAIT FOR EVENT--.\n");
408 /* wait for data ready event */
409 wait_event(test_ch->wait_q,
410 atomic_read(&test_ch->rx_notify_count));
411 atomic_dec(&test_ch->rx_notify_count);
412
413 read_avail = sdio_read_avail(test_ch->ch);
414 if (read_avail == 0)
415 continue;
416
417
418 write_avail = sdio_write_avail(test_ch->ch);
419 if (write_avail < read_avail) {
420 pr_info(TEST_MODULE_NAME
421 ":not enough write avail.\n");
422 continue;
423 }
424
425 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
426 if (ret) {
427 pr_info(TEST_MODULE_NAME
428 ":worker, sdio_read err=%d.\n", -ret);
429 continue;
430 }
431 test_ch->rx_bytes += read_avail;
432
433 TEST_DBG(TEST_MODULE_NAME ":worker total rx bytes = 0x%x.\n",
434 test_ch->rx_bytes);
435
436
437 ret = sdio_write(test_ch->ch,
438 test_ch->buf, read_avail);
439 if (ret) {
440 pr_info(TEST_MODULE_NAME
441 ":loopback sdio_write err=%d.\n",
442 -ret);
443 continue;
444 }
445 test_ch->tx_bytes += read_avail;
446
447 TEST_DBG(TEST_MODULE_NAME
448 ":loopback total tx bytes = 0x%x.\n",
449 test_ch->tx_bytes);
450 } /* end of while */
451}
452
453/**
454 * Check if all tests completed
455 */
456static void check_test_completion(void)
457{
458 int i;
459
460 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
461 struct test_channel *tch = test_ctx->test_ch_arr[i];
462
463 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
464 continue;
465 if (!tch->test_completed) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300466 pr_info(TEST_MODULE_NAME ": %s - Channel %s test is "
467 "not completed", __func__, tch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468 return;
469 }
470 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300471 pr_info(TEST_MODULE_NAME ": %s - Test is completed", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700472 test_ctx->test_completed = 1;
473 wake_up(&test_ctx->wait_q);
474}
475
476static int pseudo_random_seed(unsigned int *seed_number)
477{
478 if (!seed_number)
479 return 0;
480
481 *seed_number = (unsigned int)(((unsigned long)*seed_number *
482 (unsigned long)1103515367) + 35757);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300483 return (int)(*seed_number / (64*1024) % 500);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484}
485
Yaniv Gardi3e327762011-07-27 11:11:04 +0300486/* this function must be locked before accessing it */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700487static void lpm_test_update_entry(struct test_channel *tch,
488 enum lpm_test_msg_type msg_type,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300489 char *msg_name,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490 int counter)
491{
492 u32 index = 0;
493 static int print_full = 1;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300494 struct sdio_test_device *test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495
496 if (!tch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300497 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 return;
499 }
500
Yaniv Gardi3e327762011-07-27 11:11:04 +0300501 test_device = tch->test_device;
502
503 if (!test_device) {
504 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
505 return;
506 }
507
508 if (test_device->next_avail_entry_in_array >=
509 test_device->array_size) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700510 pr_err(TEST_MODULE_NAME ": %s - lpm array is full",
511 __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513 if (print_full) {
514 print_hex_dump(KERN_INFO, TEST_MODULE_NAME ": lpm_arr:",
515 0, 32, 2,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300516 (void *)test_device->lpm_arr,
517 sizeof(test_device->lpm_arr), false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 print_full = 0;
519 }
520 return;
521 }
522
Yaniv Gardi3e327762011-07-27 11:11:04 +0300523 index = test_device->next_avail_entry_in_array;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524 if ((msg_type == LPM_MSG_SEND) || (msg_type == LPM_MSG_REC))
Yaniv Gardi3e327762011-07-27 11:11:04 +0300525 test_device->lpm_arr[index].counter = counter;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 else
Yaniv Gardi3e327762011-07-27 11:11:04 +0300527 test_device->lpm_arr[index].counter = 0;
528
529 test_device->lpm_arr[index].msg_type = msg_type;
530 memcpy(test_device->lpm_arr[index].msg_name, msg_name,
531 LPM_MSG_NAME_SIZE);
532 test_device->lpm_arr[index].current_ms =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 jiffies_to_msecs(get_jiffies_64());
534
Yaniv Gardi3e327762011-07-27 11:11:04 +0300535 test_device->lpm_arr[index].read_avail_mask =
536 test_device->read_avail_mask;
537
538 if ((msg_type == LPM_SLEEP) || (msg_type == LPM_WAKEUP))
539 memcpy(test_device->lpm_arr[index].chan_name, "DEVICE ",
540 CHANNEL_NAME_SIZE);
541 else
542 memcpy(test_device->lpm_arr[index].chan_name, tch->name,
543 CHANNEL_NAME_SIZE);
544
545 test_device->next_avail_entry_in_array++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700546}
547
548static int wait_for_result_msg(struct test_channel *test_ch)
549{
550 u32 read_avail = 0;
551 int ret = 0;
552
Yaniv Gardi3e327762011-07-27 11:11:04 +0300553 pr_info(TEST_MODULE_NAME ": %s - START, channel %s\n",
554 __func__, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555
556 while (1) {
557 read_avail = sdio_read_avail(test_ch->ch);
558
559 if (read_avail == 0) {
560 pr_info(TEST_MODULE_NAME
561 ": read_avail is 0 for chan %s\n",
562 test_ch->name);
563 wait_event(test_ch->wait_q,
564 atomic_read(&test_ch->rx_notify_count));
565 atomic_dec(&test_ch->rx_notify_count);
566 continue;
567 }
568
569 memset(test_ch->buf, 0x00, test_ch->buf_size);
570
571 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
572 if (ret) {
573 pr_info(TEST_MODULE_NAME ": sdio_read for chan"
574 "%s failed, err=%d.\n",
575 test_ch->name, -ret);
576 goto exit_err;
577 }
578
579 if (test_ch->buf[0] != TEST_CONFIG_SIGNATURE) {
580 pr_info(TEST_MODULE_NAME ": Not a test_result "
581 "signature. expected 0x%x. received 0x%x "
582 "for chan %s\n",
583 TEST_CONFIG_SIGNATURE,
584 test_ch->buf[0],
585 test_ch->name);
586 continue;
587 } else {
588 pr_info(TEST_MODULE_NAME ": Signature is "
589 "TEST_CONFIG_SIGNATURE as expected\n");
590 break;
591 }
592 }
593
594 return test_ch->buf[1];
595
596exit_err:
597 return 0;
598}
599
Yaniv Gardi3e327762011-07-27 11:11:04 +0300600static int check_random_lpm_test_array(struct sdio_test_device *test_dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700601{
602 int i = 0, j = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 unsigned int delta_ms = 0;
604 int arr_ind = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300605 int ret = 1;
606 int notify_counter = 0;
607 int sleep_counter = 0;
608 int wakeup_counter = 0;
609 int lpm_activity_counter = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610
Yaniv Gardi3e327762011-07-27 11:11:04 +0300611 if (!test_dev) {
612 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 return -ENODEV;
614 }
615
Yaniv Gardi3e327762011-07-27 11:11:04 +0300616 for (i = 0 ; i < test_dev->next_avail_entry_in_array ; ++i) {
617 if (i == 0)
618 pr_err(TEST_MODULE_NAME ": index %4d, chan=%2s, "
619 "code=%1d=%4s, msg#%1d, ms from before=-1, "
620 "read_mask=0x%d, ms=%2u",
621 i,
622 test_dev->lpm_arr[i].chan_name,
623 test_dev->lpm_arr[i].msg_type,
624 test_dev->lpm_arr[i].msg_name,
625 test_dev->lpm_arr[i].counter,
626 test_dev->lpm_arr[i].read_avail_mask,
627 test_dev->lpm_arr[i].current_ms);
628 else
629 pr_err(TEST_MODULE_NAME ": index "
630 "%4d, %2s, code=%1d=%4s, msg#%1d, ms from "
631 "before=%2u, read_mask=0x%d, ms=%2u",
632 i,
633 test_dev->lpm_arr[i].chan_name,
634 test_dev->lpm_arr[i].msg_type,
635 test_dev->lpm_arr[i].msg_name,
636 test_dev->lpm_arr[i].counter,
637 test_dev->lpm_arr[i].current_ms -
638 test_dev->lpm_arr[i-1].current_ms,
639 test_dev->lpm_arr[i].read_avail_mask,
640 test_dev->lpm_arr[i].current_ms);
641 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642
Yaniv Gardi3e327762011-07-27 11:11:04 +0300643 for (i = 0; i < test_dev->next_avail_entry_in_array; i++) {
644 notify_counter = 0;
645 sleep_counter = 0;
646 wakeup_counter = 0;
647
648 if ((test_dev->lpm_arr[i].msg_type == LPM_MSG_SEND) ||
649 (test_dev->lpm_arr[i].msg_type == LPM_MSG_REC)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700650 /* find the next message in the array */
Yaniv Gardi3e327762011-07-27 11:11:04 +0300651 arr_ind = test_dev->next_avail_entry_in_array;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652 for (j = i+1; j < arr_ind; j++) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300653 if ((test_dev->lpm_arr[j].msg_type ==
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700654 LPM_MSG_SEND) ||
Yaniv Gardi3e327762011-07-27 11:11:04 +0300655 (test_dev->lpm_arr[j].msg_type ==
656 LPM_MSG_REC) ||
657 (test_dev->lpm_arr[j].msg_type ==
658 LPM_NOTIFY))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 break;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300660 if (test_dev->lpm_arr[j].msg_type ==
661 LPM_SLEEP)
662 sleep_counter++;
663 if (test_dev->lpm_arr[j].msg_type ==
664 LPM_WAKEUP)
665 wakeup_counter++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700666 }
667 if (j == arr_ind) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300668 ret = 1;
669 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700670 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300671
672 delta_ms = test_dev->lpm_arr[j].current_ms -
673 test_dev->lpm_arr[i].current_ms;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674 if (delta_ms < 30) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300675 if ((sleep_counter == 0)
676 && (wakeup_counter == 0)) {
677 continue;
678 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 pr_err(TEST_MODULE_NAME "%s: lpm "
680 "activity while delta is less "
Yaniv Gardi3e327762011-07-27 11:11:04 +0300681 "than 30, i=%d, j=%d, "
682 "sleep_counter=%d, "
683 "wakeup_counter=%d",
684 __func__, i, j,
685 sleep_counter, wakeup_counter);
686 ret = 0;
687 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 }
689 } else {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300690 if ((delta_ms > 90) &&
691 (test_dev->lpm_arr[i].
692 read_avail_mask == 0)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 if (j != i+3) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300694 pr_err(TEST_MODULE_NAME
695 "%s: unexpected "
696 "lpm activity "
697 "while delta is "
698 "bigger than "
699 "90, i=%d, "
700 "j=%d, "
701 "notify_counter"
702 "=%d",
703 __func__, i, j,
704 notify_counter);
705 ret = 0;
706 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300708 lpm_activity_counter++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709 }
710 }
711 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300713
714 pr_info(TEST_MODULE_NAME ": %s - lpm_activity_counter=%d",
715 __func__, lpm_activity_counter);
716
717 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700718}
719
720static int lpm_test_main_task(void *ptr)
721{
722 u32 read_avail = 0;
723 int last_msg_index = 0;
724 struct test_channel *test_ch = (struct test_channel *)ptr;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300725 struct sdio_test_device *test_dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726 struct lpm_msg lpm_msg;
727 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700728 int host_result = 0;
729
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 if (!test_ch) {
731 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
732 return -ENODEV;
733 }
734
Yaniv Gardi3e327762011-07-27 11:11:04 +0300735 pr_err(TEST_MODULE_NAME ": %s - STARTED. channel %s\n",
736 __func__, test_ch->name);
737
738 test_dev = test_ch->test_device;
739
740 if (!test_dev) {
741 pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
742 return -ENODEV;
743 }
744
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700745 while (last_msg_index < test_ch->config_msg.num_packets - 1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300746
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700747 TEST_DBG(TEST_MODULE_NAME ": %s - "
748 "IN LOOP last_msg_index=%d\n",
749 __func__, last_msg_index);
750
751 read_avail = sdio_read_avail(test_ch->ch);
752 if (read_avail == 0) {
753 TEST_DBG(TEST_MODULE_NAME
754 ":read_avail 0 for chan %s, "
755 "wait for event\n",
756 test_ch->name);
757 wait_event(test_ch->wait_q,
758 atomic_read(&test_ch->rx_notify_count));
759 atomic_dec(&test_ch->rx_notify_count);
760
761 read_avail = sdio_read_avail(test_ch->ch);
762 if (read_avail == 0) {
763 pr_err(TEST_MODULE_NAME
764 ":read_avail size %d for chan %s not as"
765 " expected\n",
766 read_avail, test_ch->name);
767 continue;
768 }
769 }
770
771 memset(test_ch->buf, 0x00, sizeof(test_ch->buf));
772
773 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
774 if (ret) {
775 pr_info(TEST_MODULE_NAME ":sdio_read for chan %s"
Yaniv Gardi3e327762011-07-27 11:11:04 +0300776 " err=%d.\n", test_ch->name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 goto exit_err;
778 }
779
780 memcpy((void *)&lpm_msg, test_ch->buf, sizeof(lpm_msg));
781
Yaniv Gardi3e327762011-07-27 11:11:04 +0300782 /*
783 * when reading from channel, we want to turn off the bit
784 * mask that implies that there is pending data on that channel
785 */
786 if (test_ch->test_device != NULL) {
787 spin_lock_irqsave(&test_dev->lpm_array_lock,
788 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789
Yaniv Gardi3e327762011-07-27 11:11:04 +0300790 test_ch->notify_counter_per_chan--;
791
792 /*
793 * if the channel has no pending data, turn off the
794 * pending data bit mask of the channel
795 */
796 if (test_ch->notify_counter_per_chan == 0) {
797 test_ch->test_device->read_avail_mask =
798 test_ch->test_device->read_avail_mask &
799 ~test_ch->channel_mask_id;
800 }
801
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700802 last_msg_index = lpm_msg.counter;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300803 lpm_test_update_entry(test_ch,
804 LPM_MSG_REC,
805 "RECEIVE",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 last_msg_index);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300807
808 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
809 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 }
811 }
812
Yaniv Gardi3e327762011-07-27 11:11:04 +0300813 pr_info(TEST_MODULE_NAME ":%s: Finished to recieve all (%d) "
814 "packets from the modem %s. Waiting for result_msg",
815 __func__, test_ch->config_msg.num_packets, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816
817 /* Wait for the resault message from the modem */
Yaniv Gardi3e327762011-07-27 11:11:04 +0300818 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819
Yaniv Gardi3e327762011-07-27 11:11:04 +0300820 /*
821 * the DEVICE modem result is a failure if one of the channels on
822 * that device, got modem_result = 0. this is why we bitwise "AND" each
823 * time another channel completes its task
824 */
825 test_dev->modem_result_per_dev &= test_ch->modem_result_per_chan;
826
827 /*
828 * when reading from channel, we want to turn off the bit
829 * mask that implies that there is pending data on that channel
830 */
831 spin_lock_irqsave(&test_dev->lpm_array_lock,
832 test_dev->lpm_array_lock_flags);
833
834 test_dev->open_channels_counter_to_recv--;
835
836 /* turning off the read_avail bit of the channel */
837 test_ch->test_device->read_avail_mask =
838 test_ch->test_device->read_avail_mask &
839 ~test_ch->channel_mask_id;
840
841 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
842 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843
844 /* Wait for all the packets to be sent to the modem */
845 while (1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300846 spin_lock_irqsave(&test_dev->lpm_array_lock,
847 test_dev->lpm_array_lock_flags);
848
849 if (test_ch->next_index_in_sent_msg_per_chan >=
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700850 test_ch->config_msg.num_packets - 1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300851
852 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
853 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 break;
855 } else {
856 pr_info(TEST_MODULE_NAME ":%s: Didn't finished to send "
Yaniv Gardi3e327762011-07-27 11:11:04 +0300857 "all packets, "
858 "next_index_in_sent_msg_per_chan = %d ",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 __func__,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300860 test_ch->next_index_in_sent_msg_per_chan);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300862 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
863 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700864 msleep(60);
865 }
866
Yaniv Gardi3e327762011-07-27 11:11:04 +0300867 if (test_dev->open_channels_counter_to_recv != 0 ||
868 test_dev->open_channels_counter_to_send != 0) {
869 test_ch->test_completed = 1;
870 test_ch->next_index_in_sent_msg_per_chan = 0;
871 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 } else {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300873 test_ctx->number_of_active_devices--;
874 sdio_al_unregister_lpm_cb(test_ch->sdio_al_device);
875
876 if (test_ch->test_type == SDIO_TEST_LPM_RANDOM)
877 host_result = check_random_lpm_test_array(test_dev);
878
879 pr_info(TEST_MODULE_NAME ": %s - host_result=%d. "
880 "device_modem_result=%d",
881 __func__, host_result, test_dev->modem_result_per_dev);
882
883 test_ch->test_completed = 1;
884 if (test_dev->modem_result_per_dev && host_result) {
885 pr_info(TEST_MODULE_NAME ": %s - Random LPM "
886 "TEST_PASSED for device %d of %d\n",
887 __func__,
888 (test_ctx->max_number_of_devices-
889 test_ctx->number_of_active_devices),
890 test_ctx->max_number_of_devices);
891 test_dev->final_result_per_dev = 1; /* PASSED */
892 } else {
893 pr_info(TEST_MODULE_NAME ": %s - Random LPM "
894 "TEST_FAILED for device %d of %d\n",
895 __func__,
896 (test_ctx->max_number_of_devices-
897 test_ctx->number_of_active_devices),
898 test_ctx->max_number_of_devices);
899 test_dev->final_result_per_dev = 0; /* FAILED */
900 }
901
902 test_dev->next_avail_entry_in_array = 0;
903 test_ch->next_index_in_sent_msg_per_chan = 0;
904
905 check_test_completion();
906
907 kfree(test_ch->test_device->lpm_arr);
908
909 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910 }
911
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912exit_err:
913 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
914 test_ch->name);
915 test_ch->test_completed = 1;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300916 test_dev->open_channels_counter_to_recv--;
917 test_dev->next_avail_entry_in_array = 0;
918 test_ch->next_index_in_sent_msg_per_chan = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 test_ch->test_result = TEST_FAILED;
920 check_test_completion();
921 return -ENODEV;
922}
923
924static int lpm_test_create_read_thread(struct test_channel *test_ch)
925{
Yaniv Gardi3e327762011-07-27 11:11:04 +0300926 struct sdio_test_device *test_dev;
927
928 pr_info(TEST_MODULE_NAME ": %s - STARTED channel %s\n",
929 __func__, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930
931 if (!test_ch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300932 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933 return -ENODEV;
934 }
935
Yaniv Gardi3e327762011-07-27 11:11:04 +0300936 test_dev = test_ch->test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700937
Yaniv Gardi3e327762011-07-27 11:11:04 +0300938 if (!test_dev) {
939 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
940 return -ENODEV;
941 }
942
943 test_dev->lpm_test_task.task_name = SDIO_LPM_TEST;
944
945 test_dev->lpm_test_task.lpm_task =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700946 kthread_create(lpm_test_main_task,
947 (void *)(test_ch),
Yaniv Gardi3e327762011-07-27 11:11:04 +0300948 test_dev->lpm_test_task.task_name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700949
Yaniv Gardi3e327762011-07-27 11:11:04 +0300950 if (IS_ERR(test_dev->lpm_test_task.lpm_task)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700951 pr_err(TEST_MODULE_NAME ": %s - kthread_create() failed\n",
952 __func__);
953 return -ENOMEM;
954 }
955
Yaniv Gardi3e327762011-07-27 11:11:04 +0300956 wake_up_process(test_dev->lpm_test_task.lpm_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700957
958 return 0;
959}
960
961static void lpm_continuous_rand_test(struct test_channel *test_ch)
962{
963 unsigned int local_ms = 0;
964 int ret = 0;
965 unsigned int write_avail = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300966 struct sdio_test_device *test_dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700967
968 pr_info(MODULE_NAME ": %s - STARTED\n", __func__);
969
970 if (!test_ch) {
971 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
972 return;
973 }
974
Yaniv Gardi3e327762011-07-27 11:11:04 +0300975 test_dev = test_ch->test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976
Yaniv Gardi3e327762011-07-27 11:11:04 +0300977 if (!test_dev) {
978 pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
979 return;
980 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981
982 ret = lpm_test_create_read_thread(test_ch);
983 if (ret != 0) {
984 pr_err(TEST_MODULE_NAME ": %s - failed to create lpm reading "
985 "thread", __func__);
986 }
987
Yaniv Gardi3e327762011-07-27 11:11:04 +0300988 while (test_ch->next_index_in_sent_msg_per_chan <=
989 test_ch->config_msg.num_packets - 1) {
990
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700991 struct lpm_msg msg;
992 u32 ret = 0;
993
Yaniv Gardi3e327762011-07-27 11:11:04 +0300994 /* sleeping period is dependent on number of open channels */
995
996 local_ms = test_dev->open_channels_counter_to_send *
997 pseudo_random_seed(&test_ch->config_msg.test_param);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700998 TEST_DBG(TEST_MODULE_NAME ":%s: SLEEPING for %d ms",
999 __func__, local_ms);
1000 msleep(local_ms);
1001
Yaniv Gardi3e327762011-07-27 11:11:04 +03001002 msg.counter = test_ch->next_index_in_sent_msg_per_chan;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001003 msg.signature = LPM_TEST_CONFIG_SIGNATURE;
1004 msg.reserve1 = 0;
1005 msg.reserve2 = 0;
1006
1007 /* wait for data ready event */
1008 write_avail = sdio_write_avail(test_ch->ch);
1009 pr_debug(TEST_MODULE_NAME ": %s: write_avail=%d\n",
1010 __func__, write_avail);
1011 if (write_avail < sizeof(msg)) {
1012 wait_event(test_ch->wait_q,
1013 atomic_read(&test_ch->tx_notify_count));
1014 atomic_dec(&test_ch->tx_notify_count);
1015 }
1016
1017 write_avail = sdio_write_avail(test_ch->ch);
1018 if (write_avail < sizeof(msg)) {
1019 pr_info(TEST_MODULE_NAME ": %s: not enough write "
1020 "avail.\n", __func__);
1021 break;
1022 }
1023
1024 ret = sdio_write(test_ch->ch, (u32 *)&msg, sizeof(msg));
1025 if (ret)
1026 pr_err(TEST_MODULE_NAME ":%s: sdio_write err=%d.\n",
1027 __func__, -ret);
1028
Yaniv Gardi3e327762011-07-27 11:11:04 +03001029 TEST_DBG(TEST_MODULE_NAME ": %s: for chan %s, write, "
1030 "msg # %d\n",
1031 __func__,
1032 test_ch->name,
1033 test_ch->next_index_in_sent_msg_per_chan);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034
Yaniv Gardi3e327762011-07-27 11:11:04 +03001035 if (test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
1036 spin_lock_irqsave(&test_dev->lpm_array_lock,
1037 test_dev->lpm_array_lock_flags);
1038 lpm_test_update_entry(test_ch, LPM_MSG_SEND,
1039 "SEND ",
1040 test_ch->
1041 next_index_in_sent_msg_per_chan);
1042
1043 test_ch->next_index_in_sent_msg_per_chan++;
1044
1045 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
1046 test_dev->lpm_array_lock_flags);
1047 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048 }
1049
Yaniv Gardi3e327762011-07-27 11:11:04 +03001050 spin_lock_irqsave(&test_dev->lpm_array_lock,
1051 test_dev->lpm_array_lock_flags);
1052 test_dev->open_channels_counter_to_send--;
1053 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
1054 test_dev->lpm_array_lock_flags);
1055
1056 pr_info(TEST_MODULE_NAME ": %s: - Finished to send all (%d) "
1057 "packets to the modem on channel %s",
1058 __func__, test_ch->config_msg.num_packets, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059
1060 return;
1061}
1062
1063static void lpm_test(struct test_channel *test_ch)
1064{
Yaniv Gardi3e327762011-07-27 11:11:04 +03001065 pr_info(TEST_MODULE_NAME ": %s - START channel %s\n", __func__,
1066 test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001067
1068 if (!test_ch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +03001069 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070 return;
1071 }
1072
Yaniv Gardi3e327762011-07-27 11:11:04 +03001073 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074 pr_debug(TEST_MODULE_NAME ": %s - delete the timeout timer\n",
1075 __func__);
1076 del_timer_sync(&test_ch->timeout_timer);
1077
Yaniv Gardi3e327762011-07-27 11:11:04 +03001078 if (test_ch->modem_result_per_chan == 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001079 pr_err(TEST_MODULE_NAME ": LPM TEST - Client didn't sleep. "
1080 "Result Msg - is_successful=%d\n", test_ch->buf[1]);
1081 goto exit_err;
1082 } else {
1083 pr_info(TEST_MODULE_NAME ": %s -"
1084 "LPM 9K WAS SLEEPING - PASS\n", __func__);
1085 if (test_ch->test_result == TEST_PASSED) {
1086 pr_info(TEST_MODULE_NAME ": LPM TEST_PASSED\n");
1087 test_ch->test_completed = 1;
1088 check_test_completion();
1089 } else {
1090 pr_err(TEST_MODULE_NAME ": LPM TEST - Host didn't "
1091 "sleep. Client slept\n");
1092 goto exit_err;
1093 }
1094 }
1095
1096 return;
1097
1098exit_err:
1099 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1100 test_ch->name);
1101 test_ch->test_completed = 1;
1102 test_ch->test_result = TEST_FAILED;
1103 check_test_completion();
1104 return;
1105}
1106
1107
1108/**
1109 * LPM Test while the host wakes up the modem
1110 */
1111static void lpm_test_host_waker(struct test_channel *test_ch)
1112{
1113 pr_info(TEST_MODULE_NAME ": %s - START\n", __func__);
1114 wait_event(test_ch->wait_q, atomic_read(&test_ch->wakeup_client));
1115 atomic_set(&test_ch->wakeup_client, 0);
1116
1117 pr_info(TEST_MODULE_NAME ": %s - Sending the config_msg to wakeup "
1118 " the client\n", __func__);
1119 send_config_msg(test_ch);
1120
1121 lpm_test(test_ch);
1122}
1123
1124/**
1125 * sender Test
1126 */
1127static void sender_test(struct test_channel *test_ch)
1128{
1129 int ret = 0 ;
1130 u32 read_avail = 0;
1131 u32 write_avail = 0;
1132 int packet_count = 0;
1133 int size = 512;
1134 u16 *buf16 = (u16 *) test_ch->buf;
1135 int i;
1136 int max_packet_count = 10000;
1137 int random_num = 0;
1138
1139 max_packet_count = test_ch->config_msg.num_packets;
1140
1141 for (i = 0 ; i < size / 2 ; i++)
1142 buf16[i] = (u16) (i & 0xFFFF);
1143
1144
1145 pr_info(TEST_MODULE_NAME
1146 ":SENDER TEST START for chan %s\n", test_ch->name);
1147
1148 while (packet_count < max_packet_count) {
1149
1150 if (test_ctx->exit_flag) {
1151 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1152 return;
1153 }
1154
1155 random_num = get_random_int();
1156 size = (random_num % test_ch->packet_length) + 1;
1157
1158 TEST_DBG(TEST_MODULE_NAME "SENDER WAIT FOR EVENT for chan %s\n",
1159 test_ch->name);
1160
1161 /* wait for data ready event */
1162 write_avail = sdio_write_avail(test_ch->ch);
1163 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1164 if (write_avail < size) {
1165 wait_event(test_ch->wait_q,
1166 atomic_read(&test_ch->tx_notify_count));
1167 atomic_dec(&test_ch->tx_notify_count);
1168 }
1169
1170 write_avail = sdio_write_avail(test_ch->ch);
1171 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1172 if (write_avail < size) {
1173 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
1174 continue;
1175 }
1176
1177 test_ch->buf[0] = packet_count;
1178
1179 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1180 if (ret) {
1181 pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
1182 -ret);
1183 goto exit_err;
1184 }
1185
1186 /* wait for read data ready event */
1187 TEST_DBG(TEST_MODULE_NAME ":sender wait for rx data for "
1188 "chan %s\n",
1189 test_ch->name);
1190 read_avail = sdio_read_avail(test_ch->ch);
1191 wait_event(test_ch->wait_q,
1192 atomic_read(&test_ch->rx_notify_count));
1193 atomic_dec(&test_ch->rx_notify_count);
1194
1195 read_avail = sdio_read_avail(test_ch->ch);
1196
1197 if (read_avail != size) {
1198 pr_info(TEST_MODULE_NAME
1199 ":read_avail size %d for chan %s not as "
1200 "expected size %d.\n",
1201 read_avail, test_ch->name, size);
1202 goto exit_err;
1203 }
1204
1205 memset(test_ch->buf, 0x00, size);
1206
1207 ret = sdio_read(test_ch->ch, test_ch->buf, size);
1208 if (ret) {
1209 pr_info(TEST_MODULE_NAME ":sender sdio_read for chan %s"
1210 " err=%d.\n",
1211 test_ch->name, -ret);
1212 goto exit_err;
1213 }
1214
1215
1216 if ((test_ch->buf[0] != packet_count) && (size != 1)) {
1217 pr_info(TEST_MODULE_NAME ":sender sdio_read WRONG DATA"
1218 " for chan %s, size=%d\n",
1219 test_ch->name, size);
1220 goto exit_err;
1221 }
1222
1223 test_ch->tx_bytes += size;
1224 test_ch->rx_bytes += size;
1225 packet_count++;
1226
1227 TEST_DBG(TEST_MODULE_NAME
1228 ":sender total rx bytes = 0x%x , packet#=%d, size=%d"
1229 " for chan %s\n",
1230 test_ch->rx_bytes, packet_count, size, test_ch->name);
1231 TEST_DBG(TEST_MODULE_NAME
1232 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
1233 " for chan %s\n",
1234 test_ch->tx_bytes, packet_count, size, test_ch->name);
1235
1236 } /* end of while */
1237
1238 pr_info(TEST_MODULE_NAME
1239 ":SENDER TEST END: total rx bytes = 0x%x, "
1240 " total tx bytes = 0x%x for chan %s\n",
1241 test_ch->rx_bytes, test_ch->tx_bytes, test_ch->name);
1242
1243 pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
1244 test_ch->name);
1245 test_ch->test_completed = 1;
1246 test_ch->test_result = TEST_PASSED;
1247 check_test_completion();
1248 return;
1249
1250exit_err:
1251 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1252 test_ch->name);
1253 test_ch->test_completed = 1;
1254 test_ch->test_result = TEST_FAILED;
1255 check_test_completion();
1256 return;
1257}
1258
1259/**
1260 * A2 Perf Test
1261 */
1262static void a2_performance_test(struct test_channel *test_ch)
1263{
1264 int ret = 0 ;
1265 u32 read_avail = 0;
1266 u32 write_avail = 0;
1267 int tx_packet_count = 0;
1268 int rx_packet_count = 0;
1269 int size = 0;
1270 u16 *buf16 = (u16 *) test_ch->buf;
1271 int i;
1272 int total_bytes = 0;
1273 int max_packets = 10000;
1274 u32 packet_size = test_ch->buf_size;
1275 int rand_size = 0;
1276
1277 u64 start_jiffy, end_jiffy, delta_jiffies;
1278 unsigned int time_msec = 0;
1279 u32 throughput = 0;
1280
1281 max_packets = test_ch->config_msg.num_packets;
1282 packet_size = test_ch->packet_length;
1283
1284 for (i = 0; i < packet_size / 2; i++)
1285 buf16[i] = (u16) (i & 0xFFFF);
1286
1287 pr_info(TEST_MODULE_NAME ": A2 PERFORMANCE TEST START for chan %s\n",
1288 test_ch->name);
1289
1290 start_jiffy = get_jiffies_64(); /* read the current time */
1291
1292 while (tx_packet_count < max_packets) {
1293
1294 if (test_ctx->exit_flag) {
1295 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1296 return;
1297 }
1298
1299 if (test_ch->random_packet_size) {
1300 rand_size = get_random_int();
1301 packet_size = (rand_size % test_ch->packet_length) + 1;
1302 if (packet_size < A2_MIN_PACKET_SIZE)
1303 packet_size = A2_MIN_PACKET_SIZE;
1304 }
1305
1306 /* wait for data ready event */
1307 /* use a func to avoid compiler optimizations */
1308 write_avail = sdio_write_avail(test_ch->ch);
1309 read_avail = sdio_read_avail(test_ch->ch);
1310 TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d, "
1311 "read_avail=%d for chan %s\n",
1312 test_ch->name, write_avail, read_avail,
1313 test_ch->name);
1314 if ((write_avail == 0) && (read_avail == 0)) {
1315 wait_event(test_ch->wait_q,
1316 atomic_read(&test_ch->any_notify_count));
1317 atomic_set(&test_ch->any_notify_count, 0);
1318 }
1319
1320 write_avail = sdio_write_avail(test_ch->ch);
1321 TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
1322 test_ch->name, write_avail);
1323 if (write_avail > 0) {
1324 size = min(packet_size, write_avail) ;
1325 TEST_DBG(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
1326 size, test_ch->name);
1327 test_ch->buf[0] = tx_packet_count;
1328 test_ch->buf[(size/4)-1] = tx_packet_count;
1329
1330 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1331 if (ret) {
1332 pr_info(TEST_MODULE_NAME ":sdio_write err=%d"
1333 " for chan %s\n",
1334 -ret, test_ch->name);
1335 goto exit_err;
1336 }
1337 tx_packet_count++;
1338 test_ch->tx_bytes += size;
1339 }
1340
1341 read_avail = sdio_read_avail(test_ch->ch);
1342 TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
1343 test_ch->name, read_avail);
1344 if (read_avail > 0) {
1345 size = min(packet_size, read_avail);
1346 pr_debug(TEST_MODULE_NAME ":rx size = %d.\n", size);
1347 ret = sdio_read(test_ch->ch, test_ch->buf, size);
1348 if (ret) {
1349 pr_info(TEST_MODULE_NAME ": sdio_read size %d "
1350 " err=%d"
1351 " for chan %s\n",
1352 size, -ret, test_ch->name);
1353 goto exit_err;
1354 }
1355 rx_packet_count++;
1356 test_ch->rx_bytes += size;
1357 }
1358
1359 TEST_DBG(TEST_MODULE_NAME
1360 ":total rx bytes = %d , rx_packet#=%d"
1361 " for chan %s\n",
1362 test_ch->rx_bytes, rx_packet_count, test_ch->name);
1363 TEST_DBG(TEST_MODULE_NAME
1364 ":total tx bytes = %d , tx_packet#=%d"
1365 " for chan %s\n",
1366 test_ch->tx_bytes, tx_packet_count, test_ch->name);
1367
1368 } /* while (tx_packet_count < max_packets ) */
1369
1370 end_jiffy = get_jiffies_64(); /* read the current time */
1371
1372 delta_jiffies = end_jiffy - start_jiffy;
1373 time_msec = jiffies_to_msecs(delta_jiffies);
1374
1375 pr_info(TEST_MODULE_NAME ":total rx bytes = 0x%x , rx_packet#=%d for"
1376 " chan %s.\n",
1377 test_ch->rx_bytes, rx_packet_count, test_ch->name);
1378 pr_info(TEST_MODULE_NAME ":total tx bytes = 0x%x , tx_packet#=%d"
1379 " for chan %s.\n",
1380 test_ch->tx_bytes, tx_packet_count, test_ch->name);
1381
1382 total_bytes = (test_ch->tx_bytes + test_ch->rx_bytes);
1383 pr_err(TEST_MODULE_NAME ":total bytes = %d, time msec = %d"
1384 " for chan %s\n",
1385 total_bytes , (int) time_msec, test_ch->name);
1386
1387 if (!test_ch->random_packet_size) {
1388 throughput = (total_bytes / time_msec) * 8 / 1000;
1389 pr_err(TEST_MODULE_NAME ":Performance = %d Mbit/sec for "
1390 "chan %s\n",
1391 throughput, test_ch->name);
1392 }
1393
1394#ifdef CONFIG_DEBUG_FS
1395 switch (test_ch->ch_id) {
1396 case SDIO_DUN:
1397 test_ctx->debug.dun_throughput = throughput;
1398 break;
1399 case SDIO_RMNT:
1400 test_ctx->debug.rmnt_throughput = throughput;
1401 break;
1402 default:
1403 pr_err(TEST_MODULE_NAME "No debugfs for this channel "
1404 "throughput");
1405 }
1406#endif
1407
1408 pr_err(TEST_MODULE_NAME ": A2 PERFORMANCE TEST END for chan %s.\n",
1409 test_ch->name);
1410
1411 pr_err(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
1412 test_ch->test_completed = 1;
1413 test_ch->test_result = TEST_PASSED;
1414 check_test_completion();
1415 return;
1416
1417exit_err:
1418 pr_err(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
1419 test_ch->test_completed = 1;
1420 test_ch->test_result = TEST_FAILED;
1421 check_test_completion();
1422 return;
1423}
1424
1425/**
1426 * sender No loopback Test
1427 */
1428static void sender_no_loopback_test(struct test_channel *test_ch)
1429{
1430 int ret = 0 ;
1431 u32 write_avail = 0;
1432 int packet_count = 0;
1433 int size = 512;
1434 u16 *buf16 = (u16 *) test_ch->buf;
1435 int i;
1436 int max_packet_count = 10000;
1437 int random_num = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001438
1439 max_packet_count = test_ch->config_msg.num_packets;
1440
1441 for (i = 0 ; i < size / 2 ; i++)
1442 buf16[i] = (u16) (i & 0xFFFF);
1443
1444 pr_info(TEST_MODULE_NAME
1445 ":SENDER NO LP TEST START for chan %s\n", test_ch->name);
1446
1447 while (packet_count < max_packet_count) {
1448
1449 if (test_ctx->exit_flag) {
1450 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1451 return;
1452 }
1453
1454 random_num = get_random_int();
1455 size = (random_num % test_ch->packet_length) + 1;
1456
1457 TEST_DBG(TEST_MODULE_NAME ":SENDER WAIT FOR EVENT "
1458 "for chan %s\n",
1459 test_ch->name);
1460
1461 /* wait for data ready event */
1462 write_avail = sdio_write_avail(test_ch->ch);
1463 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1464 if (write_avail < size) {
1465 wait_event(test_ch->wait_q,
1466 atomic_read(&test_ch->tx_notify_count));
1467 atomic_dec(&test_ch->tx_notify_count);
1468 }
1469
1470 write_avail = sdio_write_avail(test_ch->ch);
1471 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1472 if (write_avail < size) {
1473 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
1474 continue;
1475 }
1476
1477 test_ch->buf[0] = packet_count;
1478
1479 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1480 if (ret) {
1481 pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
1482 -ret);
1483 goto exit_err;
1484 }
1485
1486 test_ch->tx_bytes += size;
1487 packet_count++;
1488
1489 TEST_DBG(TEST_MODULE_NAME
1490 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
1491 " for chan %s\n",
1492 test_ch->tx_bytes, packet_count, size, test_ch->name);
1493
1494 } /* end of while */
1495
1496 pr_info(TEST_MODULE_NAME
1497 ":SENDER TEST END: total tx bytes = 0x%x, "
1498 " for chan %s\n",
1499 test_ch->tx_bytes, test_ch->name);
1500
Yaniv Gardi3e327762011-07-27 11:11:04 +03001501 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001502
Yaniv Gardi3e327762011-07-27 11:11:04 +03001503 if (test_ch->modem_result_per_chan) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001504 pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
1505 test_ch->name);
1506 test_ch->test_result = TEST_PASSED;
1507 } else {
1508 pr_info(TEST_MODULE_NAME ": TEST FAILURE for chan %s.\n",
1509 test_ch->name);
1510 test_ch->test_result = TEST_FAILED;
1511 }
1512 test_ch->test_completed = 1;
1513 check_test_completion();
1514 return;
1515
1516exit_err:
1517 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1518 test_ch->name);
1519 test_ch->test_completed = 1;
1520 test_ch->test_result = TEST_FAILED;
1521 check_test_completion();
1522 return;
1523}
1524
1525/**
1526 * Worker thread to handle the tests types
1527 */
1528static void worker(struct work_struct *work)
1529{
1530 struct test_channel *test_ch = NULL;
1531 struct test_work *test_work = container_of(work,
1532 struct test_work,
1533 work);
1534 int test_type = 0;
1535
1536 test_ch = test_work->test_ch;
1537
1538 if (test_ch == NULL) {
1539 pr_err(TEST_MODULE_NAME ":NULL test_ch\n");
1540 return;
1541 }
1542
1543 test_type = test_ch->test_type;
1544
1545 switch (test_type) {
1546 case SDIO_TEST_LOOPBACK_HOST:
1547 loopback_test(test_ch);
1548 break;
1549 case SDIO_TEST_LOOPBACK_CLIENT:
1550 sender_test(test_ch);
1551 break;
1552 case SDIO_TEST_PERF:
1553 a2_performance_test(test_ch);
1554 break;
1555 case SDIO_TEST_LPM_CLIENT_WAKER:
1556 lpm_test(test_ch);
1557 break;
1558 case SDIO_TEST_LPM_HOST_WAKER:
1559 lpm_test_host_waker(test_ch);
1560 break;
1561 case SDIO_TEST_HOST_SENDER_NO_LP:
1562 sender_no_loopback_test(test_ch);
1563 break;
1564 case SDIO_TEST_LPM_RANDOM:
1565 lpm_continuous_rand_test(test_ch);
1566 break;
1567 default:
1568 pr_err(TEST_MODULE_NAME ":Bad Test type = %d.\n",
1569 (int) test_type);
1570 }
1571}
1572
1573
1574/**
1575 * Notification Callback
1576 *
1577 * Notify the worker
1578 *
1579 */
1580static void notify(void *priv, unsigned channel_event)
1581{
1582 struct test_channel *test_ch = (struct test_channel *) priv;
1583
Yaniv Gardi3e327762011-07-27 11:11:04 +03001584 pr_debug(TEST_MODULE_NAME ": %s - notify event=%d.\n",
1585 __func__, channel_event);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001586
1587 if (test_ch->ch == NULL) {
Yaniv Gardi3e327762011-07-27 11:11:04 +03001588 pr_info(TEST_MODULE_NAME ": %s - notify before ch ready.\n",
1589 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001590 return;
1591 }
1592
1593 switch (channel_event) {
1594 case SDIO_EVENT_DATA_READ_AVAIL:
1595 atomic_inc(&test_ch->rx_notify_count);
1596 atomic_set(&test_ch->any_notify_count, 1);
Yaniv Gardi3e327762011-07-27 11:11:04 +03001597 TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_READ_AVAIL, "
1598 "any_notify_count=%d, rx_notify_count=%d\n",
1599 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001600 atomic_read(&test_ch->any_notify_count),
1601 atomic_read(&test_ch->rx_notify_count));
Yaniv Gardi3e327762011-07-27 11:11:04 +03001602 /*
1603 * when there is pending data on a channel we would like to
1604 * turn on the bit mask that implies that there is pending
1605 * data for that channel on that deivce
1606 */
1607 if (test_ch->test_device != NULL &&
1608 test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
1609 spin_lock_irqsave(&test_ch->test_device->lpm_array_lock,
1610 test_ch->test_device->
1611 lpm_array_lock_flags);
1612 test_ch->test_device->read_avail_mask |=
1613 test_ch->channel_mask_id;
1614 test_ch->notify_counter_per_chan++;
1615
1616 lpm_test_update_entry(test_ch, LPM_NOTIFY, "NOTIFY", 0);
1617 spin_unlock_irqrestore(&test_ch->test_device->
1618 lpm_array_lock,
1619 test_ch->test_device->
1620 lpm_array_lock_flags);
1621 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001622 break;
1623
1624 case SDIO_EVENT_DATA_WRITE_AVAIL:
1625 atomic_inc(&test_ch->tx_notify_count);
1626 atomic_set(&test_ch->any_notify_count, 1);
Yaniv Gardi3e327762011-07-27 11:11:04 +03001627 TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_WRITE_AVAIL, "
1628 "any_notify_count=%d, tx_notify_count=%d\n",
1629 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001630 atomic_read(&test_ch->any_notify_count),
1631 atomic_read(&test_ch->tx_notify_count));
1632 break;
1633
1634 default:
1635 BUG();
1636 }
1637 wake_up(&test_ch->wait_q);
1638
1639}
1640
1641#ifdef CONFIG_MSM_SDIO_SMEM
1642static int sdio_smem_test_cb(int event)
1643{
1644 struct test_channel *tch = test_ctx->test_ch_arr[SDIO_SMEM];
1645 pr_debug(TEST_MODULE_NAME ":%s: Received event %d\n", __func__, event);
1646
1647 switch (event) {
1648 case SDIO_SMEM_EVENT_READ_DONE:
1649 tch->rx_bytes += SMEM_MAX_XFER_SIZE;
1650 if (tch->rx_bytes >= 40000000) {
1651 if (!tch->test_completed) {
1652 pr_info(TEST_MODULE_NAME ":SMEM test PASSED\n");
1653 tch->test_completed = 1;
1654 tch->test_result = TEST_PASSED;
1655 check_test_completion();
1656 }
1657
1658 }
1659 break;
1660 case SDIO_SMEM_EVENT_READ_ERR:
1661 pr_err(TEST_MODULE_NAME ":Read overflow, SMEM test FAILED\n");
1662 tch->test_completed = 1;
1663 tch->test_result = TEST_FAILED;
1664 check_test_completion();
1665 return -EIO;
1666 default:
1667 pr_err(TEST_MODULE_NAME ":Unhandled event\n");
1668 return -EINVAL;
1669 }
1670 return 0;
1671}
1672
1673static int sdio_smem_test_probe(struct platform_device *pdev)
1674{
1675 int ret = 0;
1676
1677 test_ctx->sdio_smem = container_of(pdev, struct sdio_smem_client,
1678 plat_dev);
1679
1680 test_ctx->sdio_smem->buf = test_ctx->smem_buf;
1681 test_ctx->sdio_smem->size = SMEM_MAX_XFER_SIZE;
1682 test_ctx->sdio_smem->cb_func = sdio_smem_test_cb;
1683 ret = sdio_smem_register_client();
1684 if (ret)
1685 pr_info(TEST_MODULE_NAME "%s: Error (%d) registering sdio_smem "
1686 "test client\n",
1687 __func__, ret);
1688 return ret;
1689}
1690
1691static struct platform_driver sdio_smem_drv = {
1692 .probe = sdio_smem_test_probe,
1693 .driver = {
1694 .name = "SDIO_SMEM_CLIENT",
1695 .owner = THIS_MODULE,
1696 },
1697};
1698#endif
1699
1700
1701static void default_sdio_al_test_release(struct device *dev)
1702{
1703 pr_info(MODULE_NAME ":platform device released.\n");
1704}
1705
1706static void sdio_test_lpm_timeout_handler(unsigned long data)
1707{
1708 struct test_channel *tch = (struct test_channel *)data;
1709
1710 pr_info(TEST_MODULE_NAME ": %s - LPM TEST TIMEOUT Expired after "
1711 "%d ms\n", __func__, tch->timeout_ms);
1712 tch->test_completed = 1;
1713 pr_info(TEST_MODULE_NAME ": %s - tch->test_result = TEST_FAILED\n",
1714 __func__);
1715 tch->test_completed = 1;
1716 tch->test_result = TEST_FAILED;
1717 check_test_completion();
1718 return;
1719}
1720
1721static void sdio_test_lpm_timer_handler(unsigned long data)
1722{
1723 struct test_channel *tch = (struct test_channel *)data;
1724
1725 pr_info(TEST_MODULE_NAME ": %s - LPM TEST Timer Expired after "
1726 "%d ms\n", __func__, tch->timer_interval_ms);
1727
1728 if (!tch) {
1729 pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. "
1730 "tch is NULL\n", __func__);
1731 return;
1732 }
1733
1734 if (!tch->ch) {
1735 pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. tch->ch "
1736 "is NULL\n", __func__);
1737 tch->test_result = TEST_FAILED;
1738 return;
1739 }
1740
1741 /* Verfiy that we voted for sleep */
1742 if (tch->is_ok_to_sleep) {
1743 tch->test_result = TEST_PASSED;
1744 pr_info(TEST_MODULE_NAME ": %s - 8K voted for sleep\n",
1745 __func__);
1746 } else {
1747 tch->test_result = TEST_FAILED;
1748 pr_info(TEST_MODULE_NAME ": %s - 8K voted against sleep\n",
1749 __func__);
1750
1751 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03001752
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001753 sdio_al_unregister_lpm_cb(tch->sdio_al_device);
1754
1755 if (tch->test_type == SDIO_TEST_LPM_HOST_WAKER) {
1756 atomic_set(&tch->wakeup_client, 1);
1757 wake_up(&tch->wait_q);
1758 }
1759}
1760
1761int sdio_test_wakeup_callback(void *device_handle, int is_vote_for_sleep)
1762{
1763 int i = 0;
1764
1765 TEST_DBG(TEST_MODULE_NAME ": %s is_vote_for_sleep=%d!!!",
1766 __func__, is_vote_for_sleep);
1767
1768 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
1769 struct test_channel *tch = test_ctx->test_ch_arr[i];
1770
1771 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
1772 continue;
1773 if (tch->sdio_al_device == device_handle) {
1774 tch->is_ok_to_sleep = is_vote_for_sleep;
1775
Yaniv Gardi3e327762011-07-27 11:11:04 +03001776 if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
1777 spin_lock_irqsave(&tch->test_device->
1778 lpm_array_lock,
1779 tch->test_device->
1780 lpm_array_lock_flags);
1781
1782 if (is_vote_for_sleep == 1)
1783 lpm_test_update_entry(tch,
1784 LPM_SLEEP,
1785 "SLEEP ", 0);
1786 else
1787 lpm_test_update_entry(tch,
1788 LPM_WAKEUP,
1789 "WAKEUP", 0);
1790
1791 spin_unlock_irqrestore(&tch->test_device->
1792 lpm_array_lock,
1793 tch->test_device->
1794 lpm_array_lock_flags);
1795 break;
1796 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001797 }
1798 }
1799
Yaniv Gardi3e327762011-07-27 11:11:04 +03001800 return 0;
1801}
1802
1803static int sdio_test_find_dev(struct test_channel *tch)
1804{
1805 int j;
1806 int null_index = -1;
1807
1808 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
1809
1810 struct sdio_test_device *test_dev =
1811 &test_ctx->test_dev_arr[j];
1812
1813 if (test_dev->sdio_al_device == NULL) {
1814 if (null_index == -1)
1815 null_index = j;
1816 continue;
1817 }
1818
1819 if (test_dev->sdio_al_device ==
1820 tch->ch->sdio_al_dev) {
1821 test_dev->open_channels_counter_to_recv++;
1822 test_dev->open_channels_counter_to_send++;
1823 tch->test_device = test_dev;
1824 /* setting mask id for pending data for
1825 this channel */
1826 tch->channel_mask_id = test_dev->next_mask_id;
1827 test_dev->next_mask_id *= 2;
1828 pr_info(TEST_MODULE_NAME ": %s - channel %s "
1829 "got read_mask_id = 0x%x. device "
1830 "next_mask_id=0x%x",
1831 __func__, tch->name, tch->channel_mask_id,
1832 test_dev->next_mask_id);
1833 break;
1834 }
1835 }
1836
1837 /*
1838 * happens ones a new device is "discovered" while testing. i.e
1839 * if testing a few channels, a new deivce will be "discovered" once
1840 * the first channel of a device is being tested
1841 */
1842 if (j == MAX_NUM_OF_SDIO_DEVICES) {
1843
1844 struct sdio_test_device *test_dev =
1845 &test_ctx->
1846 test_dev_arr[null_index];
1847 test_dev->sdio_al_device =
1848 tch->ch->sdio_al_dev;
1849
1850 test_ctx->number_of_active_devices++;
1851 test_ctx->max_number_of_devices++;
1852 test_dev->open_channels_counter_to_recv++;
1853 test_dev->open_channels_counter_to_send++;
1854 test_dev->next_avail_entry_in_array = 0;
1855 tch->test_device = test_dev;
1856 tch->test_device->array_size =
1857 LPM_ARRAY_SIZE;
1858 test_dev->modem_result_per_dev = 1;
1859 tch->modem_result_per_chan = 0;
1860
1861 spin_lock_init(&test_dev->
1862 lpm_array_lock);
1863 pr_err(MODULE_NAME ": %s - "
1864 "Allocating Msg Array for "
1865 "Maximum open channels for device (%d) "
1866 "Channels. Array has %d entries",
1867 __func__,
1868 LPM_MAX_OPEN_CHAN_PER_DEV,
1869 test_dev->array_size);
1870
1871
1872 if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
1873 pr_err(TEST_MODULE_NAME ": %s - initializing the "
1874 "lpm_array", __func__);
1875
1876 test_dev->lpm_arr =
1877 kzalloc(sizeof(
1878 struct lpm_entry_type) *
1879 tch->
1880 test_device->array_size,
1881 GFP_KERNEL);
1882
1883 if (!test_dev->lpm_arr) {
1884 pr_err(MODULE_NAME ": %s - "
1885 "lpm_arr is NULL",
1886 __func__);
1887 return -ENOMEM;
1888 }
1889 }
1890
1891 /*
1892 * in new device, initialize next_mask_id, and setting
1893 * mask_id to the channel
1894 */
1895 test_dev->next_mask_id = 0x1;
1896 tch->channel_mask_id = test_dev->next_mask_id;
1897 test_dev->next_mask_id *= 2;
1898 pr_info(TEST_MODULE_NAME ": %s - channel %s got "
1899 "read_mask_id = 0x%x. device next_mask_id=0x%x",
1900 __func__,
1901 tch->name,
1902 tch->channel_mask_id,
1903 test_dev->next_mask_id);
1904 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001905
1906 return 0;
1907}
1908
Yaniv Gardi3e327762011-07-27 11:11:04 +03001909static void check_test_result(void)
1910{
1911 int result = 1;
1912 int i = 0;
1913
1914 test_ctx->max_number_of_devices = 0;
1915
1916 pr_info(TEST_MODULE_NAME ": %s - Woke Up\n", __func__);
1917
1918 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
1919 struct test_channel *tch = test_ctx->test_ch_arr[i];
1920
1921 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
1922 continue;
1923
1924 if (tch->test_type == SDIO_TEST_LPM_RANDOM)
1925 result &= tch->test_device->final_result_per_dev;
1926 else
1927 if (tch->test_result == TEST_FAILED) {
1928 pr_info(TEST_MODULE_NAME ": %s - "
1929 "Test FAILED\n", __func__);
1930 test_ctx->test_result = TEST_FAILED;
1931 pr_err(TEST_MODULE_NAME ": %s - "
1932 "test_result %d",
1933 __func__, test_ctx->test_result);
1934 return;
1935 }
1936 }
1937
1938 if (result == 0) {
1939 pr_info(TEST_MODULE_NAME ": %s - Test FAILED\n", __func__);
1940 test_ctx->test_result = TEST_FAILED;
1941 pr_err(TEST_MODULE_NAME ": %s - "
1942 "test_result %d",
1943 __func__, test_ctx->test_result);
1944 return;
1945 }
1946
1947 pr_info(TEST_MODULE_NAME ": %s - Test PASSED", __func__);
1948 test_ctx->test_result = TEST_PASSED;
1949 pr_err(TEST_MODULE_NAME ": %s - "
1950 "test_result %d",
1951 __func__, test_ctx->test_result);
1952 return;
1953}
1954
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001955/**
1956 * Test Main
1957 */
1958static int test_start(void)
1959{
1960 int ret = -ENOMEM;
1961 int i;
1962
1963 pr_debug(TEST_MODULE_NAME ":Starting Test ....\n");
1964
1965 test_ctx->test_completed = 0;
1966 test_ctx->test_result = TEST_NO_RESULT;
1967 test_ctx->debug.dun_throughput = 0;
1968 test_ctx->debug.rmnt_throughput = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +03001969 test_ctx->number_of_active_devices = 0;
1970
1971 pr_err(TEST_MODULE_NAME ": %s - test_result %d",
1972 __func__, test_ctx->test_result);
1973
1974 memset(test_ctx->test_dev_arr, 0,
1975 sizeof(struct sdio_test_device)*MAX_NUM_OF_SDIO_DEVICES);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001976
1977 /* Open The Channels */
1978 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
1979 struct test_channel *tch = test_ctx->test_ch_arr[i];
1980
1981 if ((!tch) || (!tch->is_used))
1982 continue;
1983
1984 tch->rx_bytes = 0;
1985 tch->tx_bytes = 0;
1986
1987 atomic_set(&tch->tx_notify_count, 0);
1988 atomic_set(&tch->rx_notify_count, 0);
1989 atomic_set(&tch->any_notify_count, 0);
1990 atomic_set(&tch->wakeup_client, 0);
1991
Yaniv Gardi3e327762011-07-27 11:11:04 +03001992 /* in case there are values left from previous tests */
1993 tch->notify_counter_per_chan = 0;
1994
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001995 memset(tch->buf, 0x00, tch->buf_size);
1996 tch->test_result = TEST_NO_RESULT;
1997
1998 tch->test_completed = 0;
1999
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002000 if (!tch->ch_ready) {
2001 pr_info(TEST_MODULE_NAME ":openning channel %s\n",
2002 tch->name);
2003 tch->ch_ready = true;
2004 if (tch->ch_id == SDIO_SMEM) {
2005 test_ctx->smem_pdev.name = "SDIO_SMEM";
2006 test_ctx->smem_pdev.dev.release =
2007 default_sdio_al_test_release;
2008 platform_device_register(&test_ctx->smem_pdev);
2009 } else {
2010 ret = sdio_open(tch->name , &tch->ch, tch,
2011 notify);
2012 if (ret) {
2013 pr_info(TEST_MODULE_NAME
2014 ":openning channel %s failed\n",
2015 tch->name);
2016 tch->ch_ready = false;
2017 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002018 }
2019 }
2020
Yaniv Gardi3e327762011-07-27 11:11:04 +03002021 if (tch->ch_id != SDIO_SMEM) {
2022 ret = sdio_test_find_dev(tch);
2023
2024 if (ret) {
2025 pr_err(TEST_MODULE_NAME ": %s - "
2026 "sdio_test_find_dev() returned with "
2027 "error", __func__);
2028 return -ENODEV;
2029 }
2030
2031 tch->sdio_al_device = tch->ch->sdio_al_dev;
2032 }
2033
2034 if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
2035 (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
2036 (tch->test_type == SDIO_TEST_LPM_RANDOM))
2037 sdio_al_register_lpm_cb(tch->sdio_al_device,
2038 sdio_test_wakeup_callback);
2039 }
2040
2041 /*
2042 * make some space between opening the channels and sending the
2043 * config messages
2044 */
2045 msleep(100);
2046
2047 /*
2048 * try to delay send_config_msg of all channels to after the point
2049 * when we open them all
2050 */
2051 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2052 struct test_channel *tch = test_ctx->test_ch_arr[i];
2053
2054 if ((!tch) || (!tch->is_used))
2055 continue;
2056
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002057 if ((tch->ch_ready) && (tch->ch_id != SDIO_SMEM))
2058 send_config_msg(tch);
2059
2060 if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
2061 (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
2062 (tch->test_type == SDIO_TEST_LPM_RANDOM)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002063 if (tch->timer_interval_ms > 0) {
2064 pr_info(TEST_MODULE_NAME ": %s - init timer, "
Yaniv Gardi3e327762011-07-27 11:11:04 +03002065 "ms=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002066 __func__, tch->timer_interval_ms);
2067 init_timer(&tch->timer);
2068 tch->timer.data = (unsigned long)tch;
2069 tch->timer.function =
2070 sdio_test_lpm_timer_handler;
2071 tch->timer.expires = jiffies +
2072 msecs_to_jiffies(tch->timer_interval_ms);
2073 add_timer(&tch->timer);
2074 }
2075 }
2076 }
2077
2078 pr_debug(TEST_MODULE_NAME ":queue_work..\n");
2079 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2080 struct test_channel *tch = test_ctx->test_ch_arr[i];
2081
2082 if ((!tch) || (!tch->is_used) || (!tch->ch_ready) ||
2083 (tch->ch_id == SDIO_SMEM))
2084 continue;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002085
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002086 queue_work(tch->workqueue, &tch->test_work.work);
2087 }
2088
Yaniv Gardi3e327762011-07-27 11:11:04 +03002089 pr_info(TEST_MODULE_NAME ": %s - Waiting for the test completion\n",
2090 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002091
Yaniv Gardi3e327762011-07-27 11:11:04 +03002092 wait_event(test_ctx->wait_q, test_ctx->test_completed);
2093 check_test_result();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002094
2095 return 0;
2096}
2097
2098static int set_params_loopback_9k(struct test_channel *tch)
2099{
2100 if (!tch) {
2101 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2102 return -EINVAL;
2103 }
2104 tch->is_used = 1;
2105 tch->test_type = SDIO_TEST_LOOPBACK_CLIENT;
2106 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2107 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2108 tch->config_msg.num_packets = 10000;
2109 tch->config_msg.num_iterations = 1;
2110
2111 tch->packet_length = 512;
2112 if (tch->ch_id == SDIO_RPC)
2113 tch->packet_length = 128;
2114 tch->timer_interval_ms = 0;
2115
2116 return 0;
2117}
2118
2119static int set_params_a2_perf(struct test_channel *tch)
2120{
2121 if (!tch) {
2122 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2123 return -EINVAL;
2124 }
2125 tch->is_used = 1;
2126 tch->test_type = SDIO_TEST_PERF;
2127 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2128 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2129 if (tch->ch_id == SDIO_DIAG)
2130 tch->packet_length = 512;
2131 else
2132 tch->packet_length = MAX_XFER_SIZE;
2133
2134 tch->config_msg.num_packets = 10000;
2135 tch->config_msg.num_iterations = 1;
2136 tch->random_packet_size = 0;
2137
2138 tch->timer_interval_ms = 0;
2139
2140 return 0;
2141}
2142
2143static int set_params_a2_small_pkts(struct test_channel *tch)
2144{
2145 if (!tch) {
2146 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2147 return -EINVAL;
2148 }
2149 tch->is_used = 1;
2150 tch->test_type = SDIO_TEST_PERF;
2151 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2152 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2153 tch->packet_length = 128;
2154
2155 tch->config_msg.num_packets = 1000000;
2156 tch->config_msg.num_iterations = 1;
2157 tch->random_packet_size = 1;
2158
2159 tch->timer_interval_ms = 0;
2160
2161 return 0;
2162}
2163
2164static int set_params_smem_test(struct test_channel *tch)
2165{
2166 if (!tch) {
2167 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2168 return -EINVAL;
2169 }
2170 tch->is_used = 1;
2171 tch->timer_interval_ms = 0;
2172
2173 return 0;
2174}
2175
2176static int set_params_lpm_test(struct test_channel *tch,
2177 enum sdio_test_case_type test,
2178 int timer_interval_ms)
2179{
2180 static int first_time = 1;
2181 if (!tch) {
2182 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
2183 return -EINVAL;
2184 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002185
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002186 tch->is_used = 1;
2187 tch->test_type = test;
2188 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2189 tch->config_msg.test_case = test;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002190 tch->config_msg.num_packets = LPM_TEST_NUM_OF_PACKETS;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002191 tch->config_msg.num_iterations = 1;
2192 if (seed != 0)
2193 tch->config_msg.test_param = seed;
2194 else
2195 tch->config_msg.test_param =
2196 (unsigned int)(get_jiffies_64() & 0xFFFF);
2197 pr_info(TEST_MODULE_NAME ":%s: seed is %d",
2198 __func__, tch->config_msg.test_param);
2199
2200 tch->timer_interval_ms = timer_interval_ms;
2201 tch->timeout_ms = 10000;
2202
2203 tch->packet_length = 0;
2204 if (test != SDIO_TEST_LPM_RANDOM) {
2205 init_timer(&tch->timeout_timer);
2206 tch->timeout_timer.data = (unsigned long)tch;
2207 tch->timeout_timer.function = sdio_test_lpm_timeout_handler;
2208 tch->timeout_timer.expires = jiffies +
2209 msecs_to_jiffies(tch->timeout_ms);
2210 add_timer(&tch->timeout_timer);
2211 pr_info(TEST_MODULE_NAME ": %s - Initiated LPM TIMEOUT TIMER."
2212 "set to %d ms\n",
2213 __func__, tch->timeout_ms);
2214 }
2215
2216 if (first_time) {
2217 pr_info(TEST_MODULE_NAME ": %s - wake_lock_init() called\n",
2218 __func__);
2219 wake_lock_init(&test_ctx->wake_lock,
2220 WAKE_LOCK_SUSPEND, TEST_MODULE_NAME);
2221 first_time = 0;
2222 }
2223
2224 pr_info(TEST_MODULE_NAME ": %s - wake_lock() for the TEST is "
Yaniv Gardi3e327762011-07-27 11:11:04 +03002225 "called channel %s. to prevent real sleeping\n",
2226 __func__, tch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002227 wake_lock(&test_ctx->wake_lock);
2228
2229 return 0;
2230}
2231
2232static int set_params_8k_sender_no_lp(struct test_channel *tch)
2233{
2234 if (!tch) {
2235 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2236 return -EINVAL;
2237 }
2238 tch->is_used = 1;
2239 tch->test_type = SDIO_TEST_HOST_SENDER_NO_LP;
2240 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2241 tch->config_msg.test_case = SDIO_TEST_HOST_SENDER_NO_LP;
2242 tch->config_msg.num_packets = 1000;
2243 tch->config_msg.num_iterations = 1;
2244
2245 tch->packet_length = 512;
2246 if (tch->ch_id == SDIO_RPC)
2247 tch->packet_length = 128;
2248 tch->timer_interval_ms = 0;
2249
2250 return 0;
2251}
2252
2253/**
2254 * Write File.
2255 *
2256 * @note Trigger the test from user space by:
2257 * echo 1 > /dev/sdio_al_test
2258 *
2259 */
2260ssize_t test_write(struct file *filp, const char __user *buf, size_t size,
2261 loff_t *f_pos)
2262{
2263 int ret = 0;
2264 int i;
2265
Yaniv Gardi3e327762011-07-27 11:11:04 +03002266 for (i = 0 ; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
2267 test_ctx->test_dev_arr[i].sdio_al_device = NULL;
2268
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002269 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2270 struct test_channel *tch = test_ctx->test_ch_arr[i];
2271 if (!tch)
2272 continue;
2273 tch->is_used = 0;
2274 }
2275
2276 ret = strict_strtol(buf, 10, &test_ctx->testcase);
2277
2278 switch (test_ctx->testcase) {
2279 case 1:
2280 /* RPC */
2281 pr_debug(TEST_MODULE_NAME " --RPC sender--.\n");
2282 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]))
2283 return size;
2284 break;
2285 case 2:
2286 /* RPC, QMI and DIAG */
2287 pr_debug(TEST_MODULE_NAME " --RPC, QMI and DIAG sender--.\n");
2288 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2289 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]) ||
2290 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]))
2291 return size;
2292 break;
2293 case 4:
2294 pr_debug(TEST_MODULE_NAME " --SMEM--.\n");
2295 if (set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]))
2296 return size;
2297 break;
2298
2299 case 5:
2300 pr_debug(TEST_MODULE_NAME " --SMEM and RPC--.\n");
2301 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2302 set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]))
2303 return size;
2304 break;
2305 case 6:
2306 pr_debug(TEST_MODULE_NAME " --RmNet A2 Performance--.\n");
2307 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]))
2308 return size;
2309 break;
2310
2311 case 7:
2312 pr_debug(TEST_MODULE_NAME " --DUN A2 Performance--.\n");
2313 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]))
2314 return size;
2315 break;
2316 case 8:
2317 pr_debug(TEST_MODULE_NAME " --RmNet and DUN A2 Performance--."
2318 "\n");
2319 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]) ||
2320 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]))
2321 return size;
2322 break;
2323 case 9:
2324 pr_debug(TEST_MODULE_NAME " --RPC sender and RmNet A2 "
2325 "Performance--.\n");
2326 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2327 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]))
2328 return size;
2329 break;
2330 case 10:
2331 pr_debug(TEST_MODULE_NAME " --All the channels--.\n");
2332 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2333 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]) ||
2334 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]) ||
2335 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]) ||
2336 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]) ||
2337 set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]) ||
2338 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_CIQ]))
2339 return size;
2340 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002341 case 16:
2342 pr_info(TEST_MODULE_NAME " -- host sender no LP for Diag --");
2343 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
2344 break;
2345 case 17:
2346 pr_info(TEST_MODULE_NAME " -- host sender no LP for Diag, RPC, "
2347 "CIQ --");
2348 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
2349 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_CIQ]);
2350 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_RPC]);
2351 break;
2352 case 18:
2353 pr_info(TEST_MODULE_NAME " -- rmnet small packets (5-128) --");
2354 if (set_params_a2_small_pkts(test_ctx->test_ch_arr[SDIO_RMNT]))
2355 return size;
2356 break;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002357 case 111:
2358 pr_info(TEST_MODULE_NAME " --LPM Test For Device 1. Client "
2359 "wakes the Host --.\n");
2360 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2361 SDIO_TEST_LPM_CLIENT_WAKER, 90))
2362 return size;
2363 break;
2364 case 113:
2365 pr_info(TEST_MODULE_NAME " --LPM Test For Device 1. Host "
2366 "wakes the Client --.\n");
2367 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2368 SDIO_TEST_LPM_HOST_WAKER, 120))
2369 return size;
2370 break;
2371 case 114:
2372 pr_info(TEST_MODULE_NAME " --LPM Test RANDOM SINGLE "
2373 "CHANNEL--.\n");
2374 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2375 SDIO_TEST_LPM_RANDOM, 0))
2376 return size;
2377 break;
2378 case 115:
2379 pr_info(TEST_MODULE_NAME " --LPM Test RANDOM MULTI "
2380 "CHANNEL--.\n");
2381 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2382 SDIO_TEST_LPM_RANDOM, 0) ||
2383 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_CIQ],
2384 SDIO_TEST_LPM_RANDOM, 0) ||
2385 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_DIAG],
2386 SDIO_TEST_LPM_RANDOM, 0) ||
2387 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_QMI],
2388 SDIO_TEST_LPM_RANDOM, 0))
2389 return size;
2390 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002391 case 98:
2392 pr_info(TEST_MODULE_NAME " set runtime debug on");
2393 test_ctx->runtime_debug = 1;
2394 return size;
2395 case 99:
2396 pr_info(TEST_MODULE_NAME " set runtime debug off");
2397 test_ctx->runtime_debug = 0;
2398 return size;
2399 default:
2400 pr_info(TEST_MODULE_NAME ":Bad Test number = %d.\n",
2401 (int)test_ctx->testcase);
2402 return 0;
2403 }
2404 ret = test_start();
2405 if (ret) {
2406 pr_err(TEST_MODULE_NAME ":test_start failed, ret = %d.\n",
2407 ret);
2408
2409 }
2410 return size;
2411}
2412
2413/**
2414 * Test Channel Init.
2415 */
2416int test_channel_init(char *name)
2417{
2418 struct test_channel *test_ch;
2419 int ch_id = 0;
2420#ifdef CONFIG_MSM_SDIO_SMEM
2421 int ret;
2422#endif
2423
2424 pr_debug(TEST_MODULE_NAME ":%s.\n", __func__);
2425 pr_info(TEST_MODULE_NAME ": init test cahnnel %s.\n", name);
2426
2427 ch_id = channel_name_to_id(name);
2428 pr_debug(TEST_MODULE_NAME ":id = %d.\n", ch_id);
2429 if (test_ctx->test_ch_arr[ch_id] == NULL) {
2430 test_ch = kzalloc(sizeof(*test_ch), GFP_KERNEL);
2431 if (test_ch == NULL) {
2432 pr_err(TEST_MODULE_NAME ":kzalloc err for allocating "
2433 "test_ch %s.\n",
2434 name);
2435 return -ENOMEM;
2436 }
2437 test_ctx->test_ch_arr[ch_id] = test_ch;
2438
2439 test_ch->ch_id = ch_id;
2440
2441 memcpy(test_ch->name, name, CHANNEL_NAME_SIZE);
2442
2443 test_ch->buf_size = MAX_XFER_SIZE;
2444
2445 test_ch->buf = kzalloc(test_ch->buf_size, GFP_KERNEL);
2446 if (test_ch->buf == NULL) {
2447 kfree(test_ch);
2448 test_ctx->test_ch = NULL;
2449 return -ENOMEM;
2450 }
2451
2452 if (test_ch->ch_id == SDIO_SMEM) {
2453 test_ctx->smem_buf = kzalloc(SMEM_MAX_XFER_SIZE,
2454 GFP_KERNEL);
2455 if (test_ctx->smem_buf == NULL) {
2456 pr_err(TEST_MODULE_NAME ":%s: Unable to "
2457 "allocate smem buf\n",
2458 __func__);
2459 kfree(test_ch);
2460 test_ctx->test_ch = NULL;
2461 return -ENOMEM;
2462 }
2463
2464#ifdef CONFIG_MSM_SDIO_SMEM
2465 ret = platform_driver_register(&sdio_smem_drv);
2466 if (ret) {
2467 pr_err(TEST_MODULE_NAME ":%s: Unable to "
2468 "register sdio smem "
2469 "test client\n",
2470 __func__);
2471 return ret;
2472 }
2473#endif
2474 } else {
2475 test_ch->workqueue =
2476 create_singlethread_workqueue(test_ch->name);
2477 test_ch->test_work.test_ch = test_ch;
2478 INIT_WORK(&test_ch->test_work.work, worker);
2479
2480 init_waitqueue_head(&test_ch->wait_q);
2481 }
2482 } else {
2483 pr_err(TEST_MODULE_NAME ":trying to call test_channel_init "
2484 "twice for chan %d\n",
2485 ch_id);
2486 }
2487
2488 return 0;
2489}
2490
2491static struct class *test_class;
2492
2493const struct file_operations test_fops = {
2494 .owner = THIS_MODULE,
2495 .write = test_write,
2496};
2497
2498/**
2499 * Module Init.
2500 */
2501static int __init test_init(void)
2502{
2503 int ret;
2504
2505 pr_debug(TEST_MODULE_NAME ":test_init.\n");
2506
Yaniv Gardi3e327762011-07-27 11:11:04 +03002507 test_ctx = kzalloc(sizeof(struct test_context), GFP_KERNEL);
2508
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002509 if (test_ctx == NULL) {
2510 pr_err(TEST_MODULE_NAME ":kzalloc err.\n");
2511 return -ENOMEM;
2512 }
2513 test_ctx->test_ch = NULL;
2514 test_ctx->signature = TEST_SIGNATURE;
2515
2516 test_ctx->name = "UNKNOWN";
2517
2518 init_waitqueue_head(&test_ctx->wait_q);
2519
2520#ifdef CONFIG_DEBUG_FS
2521 sdio_al_test_debugfs_init();
2522#endif
2523
2524 test_class = class_create(THIS_MODULE, TEST_MODULE_NAME);
2525
2526 ret = alloc_chrdev_region(&test_ctx->dev_num, 0, 1, TEST_MODULE_NAME);
2527 if (ret) {
2528 pr_err(TEST_MODULE_NAME "alloc_chrdev_region err.\n");
2529 return -ENODEV;
2530 }
2531
2532 test_ctx->dev = device_create(test_class, NULL, test_ctx->dev_num,
2533 test_ctx, TEST_MODULE_NAME);
2534 if (IS_ERR(test_ctx->dev)) {
2535 pr_err(TEST_MODULE_NAME ":device_create err.\n");
2536 return -ENODEV;
2537 }
2538
2539 test_ctx->cdev = cdev_alloc();
2540 if (test_ctx->cdev == NULL) {
2541 pr_err(TEST_MODULE_NAME ":cdev_alloc err.\n");
2542 return -ENODEV;
2543 }
2544 cdev_init(test_ctx->cdev, &test_fops);
2545 test_ctx->cdev->owner = THIS_MODULE;
2546
2547 ret = cdev_add(test_ctx->cdev, test_ctx->dev_num, 1);
2548 if (ret)
2549 pr_err(TEST_MODULE_NAME ":cdev_add err=%d\n", -ret);
2550 else
2551 pr_debug(TEST_MODULE_NAME ":SDIO-AL-Test init OK..\n");
2552
2553 return ret;
2554}
2555
2556/**
2557 * Module Exit.
2558 */
2559static void __exit test_exit(void)
2560{
2561 int i;
2562
2563 pr_debug(TEST_MODULE_NAME ":test_exit.\n");
2564
2565 test_ctx->exit_flag = true;
2566
2567 msleep(100); /* allow gracefully exit of the worker thread */
2568
2569 cdev_del(test_ctx->cdev);
2570 device_destroy(test_class, test_ctx->dev_num);
2571 unregister_chrdev_region(test_ctx->dev_num, 1);
2572
2573 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2574 struct test_channel *tch = test_ctx->test_ch_arr[i];
2575 if (!tch)
2576 continue;
2577 kfree(tch->buf);
2578 kfree(tch);
2579 }
2580
2581#ifdef CONFIG_DEBUG_FS
2582 sdio_al_test_debugfs_cleanup();
2583#endif
2584
2585 kfree(test_ctx);
2586
2587 pr_debug(TEST_MODULE_NAME ":test_exit complete.\n");
2588}
2589
2590module_init(test_init);
2591module_exit(test_exit);
2592
2593MODULE_LICENSE("GPL v2");
2594MODULE_DESCRIPTION("SDIO_AL Test");
2595MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
2596
2597