blob: c2425a065e33a1896c98d78a12ab400668ab66a8 [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
Maya Erezbde9df82011-08-02 14:40:00 +030060#define DUN_PACKET_SIZE (2*1024)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061
62#define TEST_DBG(x...) if (test_ctx->runtime_debug) pr_info(x)
63
64#define LPM_TEST_NUM_OF_PACKETS 100
Yaniv Gardi3e327762011-07-27 11:11:04 +030065#define LPM_MAX_OPEN_CHAN_PER_DEV 4
66#define LPM_ARRAY_SIZE (7*LPM_TEST_NUM_OF_PACKETS*LPM_MAX_OPEN_CHAN_PER_DEV)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070067#define SDIO_LPM_TEST "sdio_lpm_test_reading_task"
68#define LPM_TEST_CONFIG_SIGNATURE 0xDEADBABE
Yaniv Gardi3e327762011-07-27 11:11:04 +030069#define LPM_MSG_NAME_SIZE 20
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070
Maya Erez53508c12011-08-01 14:04:03 +030071#define A2_HEADER_OVERHEAD 8
72
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073enum sdio_test_case_type {
74 SDIO_TEST_LOOPBACK_HOST,
75 SDIO_TEST_LOOPBACK_CLIENT,
76 SDIO_TEST_LPM_HOST_WAKER,
77 SDIO_TEST_LPM_CLIENT_WAKER,
78 SDIO_TEST_LPM_RANDOM,
79 SDIO_TEST_HOST_SENDER_NO_LP,
Maya Erez53508c12011-08-01 14:04:03 +030080 /* The following tests are not part of the 9k tests and should be
81 * kept last in case new tests are added
82 */
83 SDIO_TEST_PERF,
84 SDIO_TEST_RTT,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085};
86
87struct lpm_task {
88 struct task_struct *lpm_task;
89 const char *task_name;
90};
91
92struct lpm_entry_type {
93 enum lpm_test_msg_type msg_type;
Yaniv Gardi3e327762011-07-27 11:11:04 +030094 char msg_name[LPM_MSG_NAME_SIZE];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095 u32 counter;
96 u32 current_ms;
Yaniv Gardi3e327762011-07-27 11:11:04 +030097 u32 read_avail_mask;
98 char chan_name[CHANNEL_NAME_SIZE];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099};
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101struct lpm_msg {
102 u32 signature;
103 u32 counter;
104 u32 reserve1;
105 u32 reserve2;
106};
107
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700108struct test_config_msg {
109 u32 signature;
110 u32 test_case;
111 u32 test_param;
112 u32 num_packets;
113 u32 num_iterations;
114};
115
116struct test_result_msg {
117 u32 signature;
118 u32 is_successful;
119};
120
121struct test_work {
122 struct work_struct work;
123 struct test_channel *test_ch;
124};
125
126enum sdio_channels_ids {
127 SDIO_RPC,
128 SDIO_QMI,
129 SDIO_RMNT,
130 SDIO_DIAG,
131 SDIO_DUN,
132 SDIO_SMEM,
133 SDIO_CIQ,
134 SDIO_MAX_CHANNELS
135};
136
137enum sdio_test_results {
138 TEST_NO_RESULT,
139 TEST_FAILED,
140 TEST_PASSED
141};
142
143enum sdio_lpm_vote_state {
144 SDIO_NO_VOTE,
145 SDIO_VOTE_FOR_SLEEP,
146 SDIO_VOTE_AGAINST_SLEEP
147};
148
Yaniv Gardi3e327762011-07-27 11:11:04 +0300149struct sdio_test_device {
150 int open_channels_counter_to_recv;
151 int open_channels_counter_to_send;
152 struct lpm_entry_type *lpm_arr;
153 int array_size;
154 void *sdio_al_device;
155 spinlock_t lpm_array_lock;
156 unsigned long lpm_array_lock_flags;
157 u32 next_avail_entry_in_array;
158 struct lpm_task lpm_test_task;
159 u32 next_mask_id;
160 u32 read_avail_mask;
161 int modem_result_per_dev;
162 int final_result_per_dev;
163};
164
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165struct test_channel {
166 struct sdio_channel *ch;
167
168 char name[CHANNEL_NAME_SIZE];
169 int ch_id;
170
Yaniv Gardi3e327762011-07-27 11:11:04 +0300171 struct sdio_test_device *test_device;
172
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173 u32 *buf;
174 u32 buf_size;
175
176 struct workqueue_struct *workqueue;
177 struct test_work test_work;
178
179 u32 rx_bytes;
180 u32 tx_bytes;
181
182 wait_queue_head_t wait_q;
183 atomic_t rx_notify_count;
184 atomic_t tx_notify_count;
185 atomic_t any_notify_count;
186 atomic_t wakeup_client;
187
188 int wait_counter;
189
190 int is_used;
191 int test_type;
192 int ch_ready;
193
194 struct test_config_msg config_msg;
195
196 int test_completed;
197 int test_result;
198 struct timer_list timer;
199 int timer_interval_ms;
200
201 struct timer_list timeout_timer;
202 int timeout_ms;
203 void *sdio_al_device;
204 int is_ok_to_sleep;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205 unsigned int packet_length;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206 int random_packet_size;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300207 int next_index_in_sent_msg_per_chan;
208 int channel_mask_id;
209 int modem_result_per_chan;
210 int notify_counter_per_chan;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700211};
212
213struct sdio_al_test_debug {
214 u32 dun_throughput;
215 u32 rmnt_throughput;
216 struct dentry *debug_root;
217 struct dentry *debug_test_result;
218 struct dentry *debug_dun_throughput;
219 struct dentry *debug_rmnt_throughput;
220};
221
222struct test_context {
223 dev_t dev_num;
224 struct device *dev;
225 struct cdev *cdev;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300226 int number_of_active_devices;
227 int max_number_of_devices;
228
229 struct sdio_test_device test_dev_arr[MAX_NUM_OF_SDIO_DEVICES];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230
231 struct test_channel *test_ch;
232
233 struct test_channel *test_ch_arr[SDIO_MAX_CHANNELS];
234
235 long testcase;
236
237 const char *name;
238
239 int exit_flag;
240
241 u32 signature;
242
243 int runtime_debug;
244
245 struct platform_device smem_pdev;
246 struct sdio_smem_client *sdio_smem;
247 int smem_was_init;
248 u8 *smem_buf;
249
250 wait_queue_head_t wait_q;
251 int test_completed;
252 int test_result;
253 struct sdio_al_test_debug debug;
254
255 struct wake_lock wake_lock;
Maya Erezf204e692011-08-12 22:00:13 +0300256
257 unsigned int lpm_pseudo_random_seed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258};
259
260/*
261 * Seed for pseudo random time sleeping in Random LPM test.
262 * If not set, current time in jiffies is used.
263 */
264static unsigned int seed;
265module_param(seed, int, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266static struct test_context *test_ctx;
267
268#ifdef CONFIG_DEBUG_FS
269/*
270*
271* Trigger on/off for debug messages
272* for trigger off the data messages debug level use:
273* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
274* for trigger on the data messages debug level use:
275* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
276* for trigger off the lpm messages debug level use:
277* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
278* for trigger on the lpm messages debug level use:
279* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
280*/
281static int sdio_al_test_debugfs_init(void)
282{
283 test_ctx->debug.debug_root = debugfs_create_dir("sdio_al_test",
284 NULL);
285 if (!test_ctx->debug.debug_root)
286 return -ENOENT;
287
288 test_ctx->debug.debug_test_result = debugfs_create_u32(
289 "test_result",
290 S_IRUGO | S_IWUGO,
291 test_ctx->debug.debug_root,
292 &test_ctx->test_result);
293
294 test_ctx->debug.debug_dun_throughput = debugfs_create_u32(
295 "dun_throughput",
296 S_IRUGO | S_IWUGO,
297 test_ctx->debug.debug_root,
298 &test_ctx->debug.dun_throughput);
299
300 test_ctx->debug.debug_rmnt_throughput = debugfs_create_u32(
301 "rmnt_throughput",
302 S_IRUGO | S_IWUGO,
303 test_ctx->debug.debug_root,
304 &test_ctx->debug.rmnt_throughput);
305
306 if ((!test_ctx->debug.debug_dun_throughput) &&
307 (!test_ctx->debug.debug_rmnt_throughput)) {
308 debugfs_remove_recursive(test_ctx->debug.debug_root);
309 test_ctx->debug.debug_root = NULL;
310 return -ENOENT;
311 }
312 return 0;
313}
314
315static void sdio_al_test_debugfs_cleanup(void)
316{
317 debugfs_remove(test_ctx->debug.debug_dun_throughput);
318 debugfs_remove(test_ctx->debug.debug_rmnt_throughput);
319 debugfs_remove(test_ctx->debug.debug_root);
320}
321#endif
322
323static int channel_name_to_id(char *name)
324{
325 pr_info(TEST_MODULE_NAME "%s: channel name %s\n",
326 __func__, name);
327
328 if (!strncmp(name, "SDIO_RPC", strnlen("SDIO_RPC", CHANNEL_NAME_SIZE)))
329 return SDIO_RPC;
330 else if (!strncmp(name, "SDIO_QMI",
331 strnlen("SDIO_QMI", CHANNEL_NAME_SIZE)))
332 return SDIO_QMI;
333 else if (!strncmp(name, "SDIO_RMNT",
334 strnlen("SDIO_RMNT", CHANNEL_NAME_SIZE)))
335 return SDIO_RMNT;
336 else if (!strncmp(name, "SDIO_DIAG",
337 strnlen("SDIO_DIAG", CHANNEL_NAME_SIZE)))
338 return SDIO_DIAG;
339 else if (!strncmp(name, "SDIO_DUN",
340 strnlen("SDIO_DUN", CHANNEL_NAME_SIZE)))
341 return SDIO_DUN;
342 else if (!strncmp(name, "SDIO_SMEM",
343 strnlen("SDIO_SMEM", CHANNEL_NAME_SIZE)))
344 return SDIO_SMEM;
345 else if (!strncmp(name, "SDIO_CIQ",
346 strnlen("SDIO_CIQ", CHANNEL_NAME_SIZE)))
347 return SDIO_CIQ;
348 else
349 return SDIO_MAX_CHANNELS;
350
351 return SDIO_MAX_CHANNELS;
352}
353
354/**
355 * Config message
356 */
357
358static void send_config_msg(struct test_channel *test_ch)
359{
360 int ret = 0 ;
361 u32 write_avail = 0;
362 int size = sizeof(test_ch->config_msg);
363
364 pr_debug(TEST_MODULE_NAME "%s\n", __func__);
365
366 memcpy(test_ch->buf, (void *)&test_ch->config_msg, size);
367
368 if (test_ctx->exit_flag) {
369 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
370 return;
371 }
372
373 pr_info(TEST_MODULE_NAME ":Sending the config message.\n");
374
375 /* wait for data ready event */
376 write_avail = sdio_write_avail(test_ch->ch);
377 pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
378 if (write_avail < size) {
379 wait_event(test_ch->wait_q,
380 atomic_read(&test_ch->tx_notify_count));
381 atomic_dec(&test_ch->tx_notify_count);
382 }
383
384 write_avail = sdio_write_avail(test_ch->ch);
385 pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
386 if (write_avail < size) {
387 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
388 return;
389 }
390
391 ret = sdio_write(test_ch->ch, test_ch->buf, size);
392 if (ret)
393 pr_err(TEST_MODULE_NAME ":%s sdio_write err=%d.\n",
394 __func__, -ret);
395 else
396 pr_info(TEST_MODULE_NAME ":%s sent config_msg successfully.\n",
397 __func__);
398}
399
400/**
401 * Loopback Test
402 */
403static void loopback_test(struct test_channel *test_ch)
404{
405 int ret = 0 ;
406 u32 read_avail = 0;
407 u32 write_avail = 0;
408
409 while (1) {
410
411 if (test_ctx->exit_flag) {
412 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
413 return;
414 }
415
416 TEST_DBG(TEST_MODULE_NAME "--LOOPBACK WAIT FOR EVENT--.\n");
417 /* wait for data ready event */
418 wait_event(test_ch->wait_q,
419 atomic_read(&test_ch->rx_notify_count));
420 atomic_dec(&test_ch->rx_notify_count);
421
422 read_avail = sdio_read_avail(test_ch->ch);
423 if (read_avail == 0)
424 continue;
425
426
427 write_avail = sdio_write_avail(test_ch->ch);
428 if (write_avail < read_avail) {
429 pr_info(TEST_MODULE_NAME
430 ":not enough write avail.\n");
431 continue;
432 }
433
434 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
435 if (ret) {
436 pr_info(TEST_MODULE_NAME
437 ":worker, sdio_read err=%d.\n", -ret);
438 continue;
439 }
440 test_ch->rx_bytes += read_avail;
441
442 TEST_DBG(TEST_MODULE_NAME ":worker total rx bytes = 0x%x.\n",
443 test_ch->rx_bytes);
444
445
446 ret = sdio_write(test_ch->ch,
447 test_ch->buf, read_avail);
448 if (ret) {
449 pr_info(TEST_MODULE_NAME
450 ":loopback sdio_write err=%d.\n",
451 -ret);
452 continue;
453 }
454 test_ch->tx_bytes += read_avail;
455
456 TEST_DBG(TEST_MODULE_NAME
457 ":loopback total tx bytes = 0x%x.\n",
458 test_ch->tx_bytes);
459 } /* end of while */
460}
461
462/**
463 * Check if all tests completed
464 */
465static void check_test_completion(void)
466{
467 int i;
468
469 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
470 struct test_channel *tch = test_ctx->test_ch_arr[i];
471
472 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
473 continue;
474 if (!tch->test_completed) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300475 pr_info(TEST_MODULE_NAME ": %s - Channel %s test is "
476 "not completed", __func__, tch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477 return;
478 }
479 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300480 pr_info(TEST_MODULE_NAME ": %s - Test is completed", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700481 test_ctx->test_completed = 1;
482 wake_up(&test_ctx->wait_q);
483}
484
485static int pseudo_random_seed(unsigned int *seed_number)
486{
487 if (!seed_number)
488 return 0;
489
490 *seed_number = (unsigned int)(((unsigned long)*seed_number *
491 (unsigned long)1103515367) + 35757);
Maya Erezf204e692011-08-12 22:00:13 +0300492 return (int)((*seed_number / (64*1024)) % 500);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493}
494
Yaniv Gardi3e327762011-07-27 11:11:04 +0300495/* this function must be locked before accessing it */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700496static void lpm_test_update_entry(struct test_channel *tch,
497 enum lpm_test_msg_type msg_type,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300498 char *msg_name,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499 int counter)
500{
501 u32 index = 0;
502 static int print_full = 1;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300503 struct sdio_test_device *test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700504
505 if (!tch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300506 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507 return;
508 }
509
Yaniv Gardi3e327762011-07-27 11:11:04 +0300510 test_device = tch->test_device;
511
512 if (!test_device) {
513 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
514 return;
515 }
516
517 if (test_device->next_avail_entry_in_array >=
518 test_device->array_size) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700519 pr_err(TEST_MODULE_NAME ": %s - lpm array is full",
520 __func__);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300521
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700522 if (print_full) {
523 print_hex_dump(KERN_INFO, TEST_MODULE_NAME ": lpm_arr:",
524 0, 32, 2,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300525 (void *)test_device->lpm_arr,
526 sizeof(test_device->lpm_arr), false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527 print_full = 0;
528 }
529 return;
530 }
531
Yaniv Gardi3e327762011-07-27 11:11:04 +0300532 index = test_device->next_avail_entry_in_array;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 if ((msg_type == LPM_MSG_SEND) || (msg_type == LPM_MSG_REC))
Yaniv Gardi3e327762011-07-27 11:11:04 +0300534 test_device->lpm_arr[index].counter = counter;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535 else
Yaniv Gardi3e327762011-07-27 11:11:04 +0300536 test_device->lpm_arr[index].counter = 0;
537
538 test_device->lpm_arr[index].msg_type = msg_type;
539 memcpy(test_device->lpm_arr[index].msg_name, msg_name,
540 LPM_MSG_NAME_SIZE);
541 test_device->lpm_arr[index].current_ms =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542 jiffies_to_msecs(get_jiffies_64());
543
Yaniv Gardi3e327762011-07-27 11:11:04 +0300544 test_device->lpm_arr[index].read_avail_mask =
545 test_device->read_avail_mask;
546
547 if ((msg_type == LPM_SLEEP) || (msg_type == LPM_WAKEUP))
548 memcpy(test_device->lpm_arr[index].chan_name, "DEVICE ",
549 CHANNEL_NAME_SIZE);
550 else
551 memcpy(test_device->lpm_arr[index].chan_name, tch->name,
552 CHANNEL_NAME_SIZE);
553
554 test_device->next_avail_entry_in_array++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555}
556
557static int wait_for_result_msg(struct test_channel *test_ch)
558{
559 u32 read_avail = 0;
560 int ret = 0;
561
Yaniv Gardi3e327762011-07-27 11:11:04 +0300562 pr_info(TEST_MODULE_NAME ": %s - START, channel %s\n",
563 __func__, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700564
565 while (1) {
566 read_avail = sdio_read_avail(test_ch->ch);
567
568 if (read_avail == 0) {
569 pr_info(TEST_MODULE_NAME
570 ": read_avail is 0 for chan %s\n",
571 test_ch->name);
572 wait_event(test_ch->wait_q,
573 atomic_read(&test_ch->rx_notify_count));
574 atomic_dec(&test_ch->rx_notify_count);
575 continue;
576 }
577
578 memset(test_ch->buf, 0x00, test_ch->buf_size);
579
580 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
581 if (ret) {
582 pr_info(TEST_MODULE_NAME ": sdio_read for chan"
583 "%s failed, err=%d.\n",
584 test_ch->name, -ret);
585 goto exit_err;
586 }
587
588 if (test_ch->buf[0] != TEST_CONFIG_SIGNATURE) {
589 pr_info(TEST_MODULE_NAME ": Not a test_result "
590 "signature. expected 0x%x. received 0x%x "
591 "for chan %s\n",
592 TEST_CONFIG_SIGNATURE,
593 test_ch->buf[0],
594 test_ch->name);
595 continue;
596 } else {
597 pr_info(TEST_MODULE_NAME ": Signature is "
598 "TEST_CONFIG_SIGNATURE as expected\n");
599 break;
600 }
601 }
602
603 return test_ch->buf[1];
604
605exit_err:
606 return 0;
607}
608
Yaniv Gardi3e327762011-07-27 11:11:04 +0300609static int check_random_lpm_test_array(struct sdio_test_device *test_dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610{
611 int i = 0, j = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612 unsigned int delta_ms = 0;
613 int arr_ind = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300614 int ret = 1;
615 int notify_counter = 0;
616 int sleep_counter = 0;
617 int wakeup_counter = 0;
618 int lpm_activity_counter = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619
Yaniv Gardi3e327762011-07-27 11:11:04 +0300620 if (!test_dev) {
621 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 return -ENODEV;
623 }
624
Yaniv Gardi3e327762011-07-27 11:11:04 +0300625 for (i = 0 ; i < test_dev->next_avail_entry_in_array ; ++i) {
626 if (i == 0)
627 pr_err(TEST_MODULE_NAME ": index %4d, chan=%2s, "
628 "code=%1d=%4s, msg#%1d, ms from before=-1, "
629 "read_mask=0x%d, ms=%2u",
630 i,
631 test_dev->lpm_arr[i].chan_name,
632 test_dev->lpm_arr[i].msg_type,
633 test_dev->lpm_arr[i].msg_name,
634 test_dev->lpm_arr[i].counter,
635 test_dev->lpm_arr[i].read_avail_mask,
636 test_dev->lpm_arr[i].current_ms);
637 else
638 pr_err(TEST_MODULE_NAME ": index "
639 "%4d, %2s, code=%1d=%4s, msg#%1d, ms from "
640 "before=%2u, read_mask=0x%d, ms=%2u",
641 i,
642 test_dev->lpm_arr[i].chan_name,
643 test_dev->lpm_arr[i].msg_type,
644 test_dev->lpm_arr[i].msg_name,
645 test_dev->lpm_arr[i].counter,
646 test_dev->lpm_arr[i].current_ms -
647 test_dev->lpm_arr[i-1].current_ms,
648 test_dev->lpm_arr[i].read_avail_mask,
649 test_dev->lpm_arr[i].current_ms);
650 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651
Yaniv Gardi3e327762011-07-27 11:11:04 +0300652 for (i = 0; i < test_dev->next_avail_entry_in_array; i++) {
653 notify_counter = 0;
654 sleep_counter = 0;
655 wakeup_counter = 0;
656
657 if ((test_dev->lpm_arr[i].msg_type == LPM_MSG_SEND) ||
658 (test_dev->lpm_arr[i].msg_type == LPM_MSG_REC)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 /* find the next message in the array */
Yaniv Gardi3e327762011-07-27 11:11:04 +0300660 arr_ind = test_dev->next_avail_entry_in_array;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 for (j = i+1; j < arr_ind; j++) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300662 if ((test_dev->lpm_arr[j].msg_type ==
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 LPM_MSG_SEND) ||
Yaniv Gardi3e327762011-07-27 11:11:04 +0300664 (test_dev->lpm_arr[j].msg_type ==
665 LPM_MSG_REC) ||
666 (test_dev->lpm_arr[j].msg_type ==
667 LPM_NOTIFY))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700668 break;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300669 if (test_dev->lpm_arr[j].msg_type ==
670 LPM_SLEEP)
671 sleep_counter++;
672 if (test_dev->lpm_arr[j].msg_type ==
673 LPM_WAKEUP)
674 wakeup_counter++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 }
676 if (j == arr_ind) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300677 ret = 1;
678 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300680
681 delta_ms = test_dev->lpm_arr[j].current_ms -
682 test_dev->lpm_arr[i].current_ms;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683 if (delta_ms < 30) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300684 if ((sleep_counter == 0)
685 && (wakeup_counter == 0)) {
686 continue;
687 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 pr_err(TEST_MODULE_NAME "%s: lpm "
689 "activity while delta is less "
Yaniv Gardi3e327762011-07-27 11:11:04 +0300690 "than 30, i=%d, j=%d, "
691 "sleep_counter=%d, "
692 "wakeup_counter=%d",
693 __func__, i, j,
694 sleep_counter, wakeup_counter);
695 ret = 0;
696 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697 }
698 } else {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300699 if ((delta_ms > 90) &&
700 (test_dev->lpm_arr[i].
701 read_avail_mask == 0)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702 if (j != i+3) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300703 pr_err(TEST_MODULE_NAME
704 "%s: unexpected "
705 "lpm activity "
706 "while delta is "
707 "bigger than "
708 "90, i=%d, "
709 "j=%d, "
710 "notify_counter"
711 "=%d",
712 __func__, i, j,
713 notify_counter);
714 ret = 0;
715 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700716 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300717 lpm_activity_counter++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700718 }
719 }
720 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300722
723 pr_info(TEST_MODULE_NAME ": %s - lpm_activity_counter=%d",
724 __func__, lpm_activity_counter);
725
726 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727}
728
729static int lpm_test_main_task(void *ptr)
730{
731 u32 read_avail = 0;
732 int last_msg_index = 0;
733 struct test_channel *test_ch = (struct test_channel *)ptr;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300734 struct sdio_test_device *test_dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735 struct lpm_msg lpm_msg;
736 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 int host_result = 0;
738
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700739 if (!test_ch) {
740 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
741 return -ENODEV;
742 }
743
Yaniv Gardi3e327762011-07-27 11:11:04 +0300744 pr_err(TEST_MODULE_NAME ": %s - STARTED. channel %s\n",
745 __func__, test_ch->name);
746
747 test_dev = test_ch->test_device;
748
749 if (!test_dev) {
750 pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
751 return -ENODEV;
752 }
753
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700754 while (last_msg_index < test_ch->config_msg.num_packets - 1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300755
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756 TEST_DBG(TEST_MODULE_NAME ": %s - "
757 "IN LOOP last_msg_index=%d\n",
758 __func__, last_msg_index);
759
760 read_avail = sdio_read_avail(test_ch->ch);
761 if (read_avail == 0) {
762 TEST_DBG(TEST_MODULE_NAME
763 ":read_avail 0 for chan %s, "
764 "wait for event\n",
765 test_ch->name);
766 wait_event(test_ch->wait_q,
767 atomic_read(&test_ch->rx_notify_count));
768 atomic_dec(&test_ch->rx_notify_count);
769
770 read_avail = sdio_read_avail(test_ch->ch);
771 if (read_avail == 0) {
772 pr_err(TEST_MODULE_NAME
773 ":read_avail size %d for chan %s not as"
774 " expected\n",
775 read_avail, test_ch->name);
776 continue;
777 }
778 }
779
780 memset(test_ch->buf, 0x00, sizeof(test_ch->buf));
781
782 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
783 if (ret) {
784 pr_info(TEST_MODULE_NAME ":sdio_read for chan %s"
Yaniv Gardi3e327762011-07-27 11:11:04 +0300785 " err=%d.\n", test_ch->name, -ret);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786 goto exit_err;
787 }
788
789 memcpy((void *)&lpm_msg, test_ch->buf, sizeof(lpm_msg));
790
Yaniv Gardi3e327762011-07-27 11:11:04 +0300791 /*
792 * when reading from channel, we want to turn off the bit
793 * mask that implies that there is pending data on that channel
794 */
795 if (test_ch->test_device != NULL) {
796 spin_lock_irqsave(&test_dev->lpm_array_lock,
797 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700798
Yaniv Gardi3e327762011-07-27 11:11:04 +0300799 test_ch->notify_counter_per_chan--;
800
801 /*
802 * if the channel has no pending data, turn off the
803 * pending data bit mask of the channel
804 */
805 if (test_ch->notify_counter_per_chan == 0) {
806 test_ch->test_device->read_avail_mask =
807 test_ch->test_device->read_avail_mask &
808 ~test_ch->channel_mask_id;
809 }
810
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811 last_msg_index = lpm_msg.counter;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300812 lpm_test_update_entry(test_ch,
813 LPM_MSG_REC,
814 "RECEIVE",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700815 last_msg_index);
Yaniv Gardi3e327762011-07-27 11:11:04 +0300816
817 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
818 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819 }
820 }
821
Yaniv Gardi3e327762011-07-27 11:11:04 +0300822 pr_info(TEST_MODULE_NAME ":%s: Finished to recieve all (%d) "
823 "packets from the modem %s. Waiting for result_msg",
824 __func__, test_ch->config_msg.num_packets, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700825
826 /* Wait for the resault message from the modem */
Yaniv Gardi3e327762011-07-27 11:11:04 +0300827 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828
Yaniv Gardi3e327762011-07-27 11:11:04 +0300829 /*
830 * the DEVICE modem result is a failure if one of the channels on
831 * that device, got modem_result = 0. this is why we bitwise "AND" each
832 * time another channel completes its task
833 */
834 test_dev->modem_result_per_dev &= test_ch->modem_result_per_chan;
835
836 /*
837 * when reading from channel, we want to turn off the bit
838 * mask that implies that there is pending data on that channel
839 */
840 spin_lock_irqsave(&test_dev->lpm_array_lock,
841 test_dev->lpm_array_lock_flags);
842
843 test_dev->open_channels_counter_to_recv--;
844
845 /* turning off the read_avail bit of the channel */
846 test_ch->test_device->read_avail_mask =
847 test_ch->test_device->read_avail_mask &
848 ~test_ch->channel_mask_id;
849
850 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
851 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852
853 /* Wait for all the packets to be sent to the modem */
854 while (1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300855 spin_lock_irqsave(&test_dev->lpm_array_lock,
856 test_dev->lpm_array_lock_flags);
857
858 if (test_ch->next_index_in_sent_msg_per_chan >=
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 test_ch->config_msg.num_packets - 1) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300860
861 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
862 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700863 break;
864 } else {
865 pr_info(TEST_MODULE_NAME ":%s: Didn't finished to send "
Yaniv Gardi3e327762011-07-27 11:11:04 +0300866 "all packets, "
867 "next_index_in_sent_msg_per_chan = %d ",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700868 __func__,
Yaniv Gardi3e327762011-07-27 11:11:04 +0300869 test_ch->next_index_in_sent_msg_per_chan);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 }
Yaniv Gardi3e327762011-07-27 11:11:04 +0300871 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
872 test_dev->lpm_array_lock_flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700873 msleep(60);
874 }
875
Yaniv Gardi3e327762011-07-27 11:11:04 +0300876 if (test_dev->open_channels_counter_to_recv != 0 ||
877 test_dev->open_channels_counter_to_send != 0) {
878 test_ch->test_completed = 1;
879 test_ch->next_index_in_sent_msg_per_chan = 0;
880 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881 } else {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300882 test_ctx->number_of_active_devices--;
883 sdio_al_unregister_lpm_cb(test_ch->sdio_al_device);
884
885 if (test_ch->test_type == SDIO_TEST_LPM_RANDOM)
886 host_result = check_random_lpm_test_array(test_dev);
887
888 pr_info(TEST_MODULE_NAME ": %s - host_result=%d. "
889 "device_modem_result=%d",
890 __func__, host_result, test_dev->modem_result_per_dev);
891
892 test_ch->test_completed = 1;
893 if (test_dev->modem_result_per_dev && host_result) {
894 pr_info(TEST_MODULE_NAME ": %s - Random LPM "
895 "TEST_PASSED for device %d of %d\n",
896 __func__,
897 (test_ctx->max_number_of_devices-
898 test_ctx->number_of_active_devices),
899 test_ctx->max_number_of_devices);
900 test_dev->final_result_per_dev = 1; /* PASSED */
901 } else {
902 pr_info(TEST_MODULE_NAME ": %s - Random LPM "
903 "TEST_FAILED for device %d of %d\n",
904 __func__,
905 (test_ctx->max_number_of_devices-
906 test_ctx->number_of_active_devices),
907 test_ctx->max_number_of_devices);
908 test_dev->final_result_per_dev = 0; /* FAILED */
909 }
910
911 test_dev->next_avail_entry_in_array = 0;
912 test_ch->next_index_in_sent_msg_per_chan = 0;
913
914 check_test_completion();
915
916 kfree(test_ch->test_device->lpm_arr);
917
918 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 }
920
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700921exit_err:
922 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
923 test_ch->name);
924 test_ch->test_completed = 1;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300925 test_dev->open_channels_counter_to_recv--;
926 test_dev->next_avail_entry_in_array = 0;
927 test_ch->next_index_in_sent_msg_per_chan = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 test_ch->test_result = TEST_FAILED;
929 check_test_completion();
930 return -ENODEV;
931}
932
933static int lpm_test_create_read_thread(struct test_channel *test_ch)
934{
Yaniv Gardi3e327762011-07-27 11:11:04 +0300935 struct sdio_test_device *test_dev;
936
937 pr_info(TEST_MODULE_NAME ": %s - STARTED channel %s\n",
938 __func__, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700939
940 if (!test_ch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +0300941 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 return -ENODEV;
943 }
944
Yaniv Gardi3e327762011-07-27 11:11:04 +0300945 test_dev = test_ch->test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700946
Yaniv Gardi3e327762011-07-27 11:11:04 +0300947 if (!test_dev) {
948 pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
949 return -ENODEV;
950 }
951
952 test_dev->lpm_test_task.task_name = SDIO_LPM_TEST;
953
954 test_dev->lpm_test_task.lpm_task =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955 kthread_create(lpm_test_main_task,
956 (void *)(test_ch),
Yaniv Gardi3e327762011-07-27 11:11:04 +0300957 test_dev->lpm_test_task.task_name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700958
Yaniv Gardi3e327762011-07-27 11:11:04 +0300959 if (IS_ERR(test_dev->lpm_test_task.lpm_task)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700960 pr_err(TEST_MODULE_NAME ": %s - kthread_create() failed\n",
961 __func__);
962 return -ENOMEM;
963 }
964
Yaniv Gardi3e327762011-07-27 11:11:04 +0300965 wake_up_process(test_dev->lpm_test_task.lpm_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700966
967 return 0;
968}
969
970static void lpm_continuous_rand_test(struct test_channel *test_ch)
971{
972 unsigned int local_ms = 0;
973 int ret = 0;
974 unsigned int write_avail = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +0300975 struct sdio_test_device *test_dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976
977 pr_info(MODULE_NAME ": %s - STARTED\n", __func__);
978
979 if (!test_ch) {
980 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
981 return;
982 }
983
Yaniv Gardi3e327762011-07-27 11:11:04 +0300984 test_dev = test_ch->test_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700985
Yaniv Gardi3e327762011-07-27 11:11:04 +0300986 if (!test_dev) {
987 pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
988 return;
989 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700990
991 ret = lpm_test_create_read_thread(test_ch);
992 if (ret != 0) {
993 pr_err(TEST_MODULE_NAME ": %s - failed to create lpm reading "
994 "thread", __func__);
995 }
996
Yaniv Gardi3e327762011-07-27 11:11:04 +0300997 while (test_ch->next_index_in_sent_msg_per_chan <=
998 test_ch->config_msg.num_packets - 1) {
999
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000 struct lpm_msg msg;
1001 u32 ret = 0;
1002
Yaniv Gardi3e327762011-07-27 11:11:04 +03001003 /* sleeping period is dependent on number of open channels */
Maya Erezf204e692011-08-12 22:00:13 +03001004 test_ch->config_msg.test_param =
1005 test_ctx->lpm_pseudo_random_seed;
Yaniv Gardi3e327762011-07-27 11:11:04 +03001006
1007 local_ms = test_dev->open_channels_counter_to_send *
Maya Erezf204e692011-08-12 22:00:13 +03001008 test_ctx->lpm_pseudo_random_seed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001009 TEST_DBG(TEST_MODULE_NAME ":%s: SLEEPING for %d ms",
1010 __func__, local_ms);
1011 msleep(local_ms);
1012
Yaniv Gardi3e327762011-07-27 11:11:04 +03001013 msg.counter = test_ch->next_index_in_sent_msg_per_chan;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001014 msg.signature = LPM_TEST_CONFIG_SIGNATURE;
1015 msg.reserve1 = 0;
1016 msg.reserve2 = 0;
1017
1018 /* wait for data ready event */
1019 write_avail = sdio_write_avail(test_ch->ch);
1020 pr_debug(TEST_MODULE_NAME ": %s: write_avail=%d\n",
1021 __func__, write_avail);
1022 if (write_avail < sizeof(msg)) {
1023 wait_event(test_ch->wait_q,
1024 atomic_read(&test_ch->tx_notify_count));
1025 atomic_dec(&test_ch->tx_notify_count);
1026 }
1027
1028 write_avail = sdio_write_avail(test_ch->ch);
1029 if (write_avail < sizeof(msg)) {
1030 pr_info(TEST_MODULE_NAME ": %s: not enough write "
1031 "avail.\n", __func__);
1032 break;
1033 }
1034
1035 ret = sdio_write(test_ch->ch, (u32 *)&msg, sizeof(msg));
1036 if (ret)
1037 pr_err(TEST_MODULE_NAME ":%s: sdio_write err=%d.\n",
1038 __func__, -ret);
1039
Yaniv Gardi3e327762011-07-27 11:11:04 +03001040 TEST_DBG(TEST_MODULE_NAME ": %s: for chan %s, write, "
1041 "msg # %d\n",
1042 __func__,
1043 test_ch->name,
1044 test_ch->next_index_in_sent_msg_per_chan);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001045
Yaniv Gardi3e327762011-07-27 11:11:04 +03001046 if (test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
1047 spin_lock_irqsave(&test_dev->lpm_array_lock,
1048 test_dev->lpm_array_lock_flags);
1049 lpm_test_update_entry(test_ch, LPM_MSG_SEND,
1050 "SEND ",
1051 test_ch->
1052 next_index_in_sent_msg_per_chan);
1053
1054 test_ch->next_index_in_sent_msg_per_chan++;
1055
1056 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
1057 test_dev->lpm_array_lock_flags);
1058 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059 }
1060
Yaniv Gardi3e327762011-07-27 11:11:04 +03001061 spin_lock_irqsave(&test_dev->lpm_array_lock,
1062 test_dev->lpm_array_lock_flags);
1063 test_dev->open_channels_counter_to_send--;
1064 spin_unlock_irqrestore(&test_dev->lpm_array_lock,
1065 test_dev->lpm_array_lock_flags);
1066
1067 pr_info(TEST_MODULE_NAME ": %s: - Finished to send all (%d) "
1068 "packets to the modem on channel %s",
1069 __func__, test_ch->config_msg.num_packets, test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070
1071 return;
1072}
1073
1074static void lpm_test(struct test_channel *test_ch)
1075{
Yaniv Gardi3e327762011-07-27 11:11:04 +03001076 pr_info(TEST_MODULE_NAME ": %s - START channel %s\n", __func__,
1077 test_ch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078
1079 if (!test_ch) {
Yaniv Gardi3e327762011-07-27 11:11:04 +03001080 pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001081 return;
1082 }
1083
Yaniv Gardi3e327762011-07-27 11:11:04 +03001084 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001085 pr_debug(TEST_MODULE_NAME ": %s - delete the timeout timer\n",
1086 __func__);
1087 del_timer_sync(&test_ch->timeout_timer);
1088
Yaniv Gardi3e327762011-07-27 11:11:04 +03001089 if (test_ch->modem_result_per_chan == 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090 pr_err(TEST_MODULE_NAME ": LPM TEST - Client didn't sleep. "
1091 "Result Msg - is_successful=%d\n", test_ch->buf[1]);
1092 goto exit_err;
1093 } else {
1094 pr_info(TEST_MODULE_NAME ": %s -"
1095 "LPM 9K WAS SLEEPING - PASS\n", __func__);
1096 if (test_ch->test_result == TEST_PASSED) {
1097 pr_info(TEST_MODULE_NAME ": LPM TEST_PASSED\n");
1098 test_ch->test_completed = 1;
1099 check_test_completion();
1100 } else {
1101 pr_err(TEST_MODULE_NAME ": LPM TEST - Host didn't "
1102 "sleep. Client slept\n");
1103 goto exit_err;
1104 }
1105 }
1106
1107 return;
1108
1109exit_err:
1110 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1111 test_ch->name);
1112 test_ch->test_completed = 1;
1113 test_ch->test_result = TEST_FAILED;
1114 check_test_completion();
1115 return;
1116}
1117
1118
1119/**
1120 * LPM Test while the host wakes up the modem
1121 */
1122static void lpm_test_host_waker(struct test_channel *test_ch)
1123{
1124 pr_info(TEST_MODULE_NAME ": %s - START\n", __func__);
1125 wait_event(test_ch->wait_q, atomic_read(&test_ch->wakeup_client));
1126 atomic_set(&test_ch->wakeup_client, 0);
1127
1128 pr_info(TEST_MODULE_NAME ": %s - Sending the config_msg to wakeup "
1129 " the client\n", __func__);
1130 send_config_msg(test_ch);
1131
1132 lpm_test(test_ch);
1133}
1134
1135/**
1136 * sender Test
1137 */
1138static void sender_test(struct test_channel *test_ch)
1139{
1140 int ret = 0 ;
1141 u32 read_avail = 0;
1142 u32 write_avail = 0;
1143 int packet_count = 0;
1144 int size = 512;
1145 u16 *buf16 = (u16 *) test_ch->buf;
1146 int i;
1147 int max_packet_count = 10000;
1148 int random_num = 0;
1149
1150 max_packet_count = test_ch->config_msg.num_packets;
1151
1152 for (i = 0 ; i < size / 2 ; i++)
1153 buf16[i] = (u16) (i & 0xFFFF);
1154
1155
1156 pr_info(TEST_MODULE_NAME
1157 ":SENDER TEST START for chan %s\n", test_ch->name);
1158
1159 while (packet_count < max_packet_count) {
1160
1161 if (test_ctx->exit_flag) {
1162 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1163 return;
1164 }
1165
1166 random_num = get_random_int();
1167 size = (random_num % test_ch->packet_length) + 1;
1168
1169 TEST_DBG(TEST_MODULE_NAME "SENDER WAIT FOR EVENT for chan %s\n",
1170 test_ch->name);
1171
1172 /* wait for data ready event */
1173 write_avail = sdio_write_avail(test_ch->ch);
1174 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1175 if (write_avail < size) {
1176 wait_event(test_ch->wait_q,
1177 atomic_read(&test_ch->tx_notify_count));
1178 atomic_dec(&test_ch->tx_notify_count);
1179 }
1180
1181 write_avail = sdio_write_avail(test_ch->ch);
1182 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1183 if (write_avail < size) {
1184 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
1185 continue;
1186 }
1187
1188 test_ch->buf[0] = packet_count;
1189
1190 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1191 if (ret) {
1192 pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
1193 -ret);
1194 goto exit_err;
1195 }
1196
1197 /* wait for read data ready event */
1198 TEST_DBG(TEST_MODULE_NAME ":sender wait for rx data for "
1199 "chan %s\n",
1200 test_ch->name);
1201 read_avail = sdio_read_avail(test_ch->ch);
1202 wait_event(test_ch->wait_q,
1203 atomic_read(&test_ch->rx_notify_count));
1204 atomic_dec(&test_ch->rx_notify_count);
1205
1206 read_avail = sdio_read_avail(test_ch->ch);
1207
1208 if (read_avail != size) {
1209 pr_info(TEST_MODULE_NAME
1210 ":read_avail size %d for chan %s not as "
1211 "expected size %d.\n",
1212 read_avail, test_ch->name, size);
1213 goto exit_err;
1214 }
1215
1216 memset(test_ch->buf, 0x00, size);
1217
1218 ret = sdio_read(test_ch->ch, test_ch->buf, size);
1219 if (ret) {
1220 pr_info(TEST_MODULE_NAME ":sender sdio_read for chan %s"
1221 " err=%d.\n",
1222 test_ch->name, -ret);
1223 goto exit_err;
1224 }
1225
1226
1227 if ((test_ch->buf[0] != packet_count) && (size != 1)) {
1228 pr_info(TEST_MODULE_NAME ":sender sdio_read WRONG DATA"
1229 " for chan %s, size=%d\n",
1230 test_ch->name, size);
1231 goto exit_err;
1232 }
1233
1234 test_ch->tx_bytes += size;
1235 test_ch->rx_bytes += size;
1236 packet_count++;
1237
1238 TEST_DBG(TEST_MODULE_NAME
1239 ":sender total rx bytes = 0x%x , packet#=%d, size=%d"
1240 " for chan %s\n",
1241 test_ch->rx_bytes, packet_count, size, test_ch->name);
1242 TEST_DBG(TEST_MODULE_NAME
1243 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
1244 " for chan %s\n",
1245 test_ch->tx_bytes, packet_count, size, test_ch->name);
1246
1247 } /* end of while */
1248
1249 pr_info(TEST_MODULE_NAME
1250 ":SENDER TEST END: total rx bytes = 0x%x, "
1251 " total tx bytes = 0x%x for chan %s\n",
1252 test_ch->rx_bytes, test_ch->tx_bytes, test_ch->name);
1253
1254 pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
1255 test_ch->name);
1256 test_ch->test_completed = 1;
1257 test_ch->test_result = TEST_PASSED;
1258 check_test_completion();
1259 return;
1260
1261exit_err:
1262 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1263 test_ch->name);
1264 test_ch->test_completed = 1;
1265 test_ch->test_result = TEST_FAILED;
1266 check_test_completion();
1267 return;
1268}
1269
1270/**
1271 * A2 Perf Test
1272 */
1273static void a2_performance_test(struct test_channel *test_ch)
1274{
1275 int ret = 0 ;
1276 u32 read_avail = 0;
1277 u32 write_avail = 0;
1278 int tx_packet_count = 0;
1279 int rx_packet_count = 0;
1280 int size = 0;
1281 u16 *buf16 = (u16 *) test_ch->buf;
1282 int i;
1283 int total_bytes = 0;
1284 int max_packets = 10000;
1285 u32 packet_size = test_ch->buf_size;
1286 int rand_size = 0;
1287
1288 u64 start_jiffy, end_jiffy, delta_jiffies;
1289 unsigned int time_msec = 0;
1290 u32 throughput = 0;
1291
1292 max_packets = test_ch->config_msg.num_packets;
1293 packet_size = test_ch->packet_length;
1294
1295 for (i = 0; i < packet_size / 2; i++)
1296 buf16[i] = (u16) (i & 0xFFFF);
1297
1298 pr_info(TEST_MODULE_NAME ": A2 PERFORMANCE TEST START for chan %s\n",
1299 test_ch->name);
1300
1301 start_jiffy = get_jiffies_64(); /* read the current time */
1302
1303 while (tx_packet_count < max_packets) {
1304
1305 if (test_ctx->exit_flag) {
1306 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1307 return;
1308 }
1309
1310 if (test_ch->random_packet_size) {
1311 rand_size = get_random_int();
1312 packet_size = (rand_size % test_ch->packet_length) + 1;
1313 if (packet_size < A2_MIN_PACKET_SIZE)
1314 packet_size = A2_MIN_PACKET_SIZE;
1315 }
1316
1317 /* wait for data ready event */
1318 /* use a func to avoid compiler optimizations */
1319 write_avail = sdio_write_avail(test_ch->ch);
1320 read_avail = sdio_read_avail(test_ch->ch);
1321 TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d, "
1322 "read_avail=%d for chan %s\n",
1323 test_ch->name, write_avail, read_avail,
1324 test_ch->name);
1325 if ((write_avail == 0) && (read_avail == 0)) {
1326 wait_event(test_ch->wait_q,
1327 atomic_read(&test_ch->any_notify_count));
1328 atomic_set(&test_ch->any_notify_count, 0);
1329 }
1330
1331 write_avail = sdio_write_avail(test_ch->ch);
1332 TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
1333 test_ch->name, write_avail);
1334 if (write_avail > 0) {
1335 size = min(packet_size, write_avail) ;
1336 TEST_DBG(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
1337 size, test_ch->name);
1338 test_ch->buf[0] = tx_packet_count;
1339 test_ch->buf[(size/4)-1] = tx_packet_count;
1340
1341 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1342 if (ret) {
1343 pr_info(TEST_MODULE_NAME ":sdio_write err=%d"
1344 " for chan %s\n",
1345 -ret, test_ch->name);
1346 goto exit_err;
1347 }
1348 tx_packet_count++;
1349 test_ch->tx_bytes += size;
1350 }
1351
1352 read_avail = sdio_read_avail(test_ch->ch);
1353 TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
1354 test_ch->name, read_avail);
1355 if (read_avail > 0) {
1356 size = min(packet_size, read_avail);
1357 pr_debug(TEST_MODULE_NAME ":rx size = %d.\n", size);
1358 ret = sdio_read(test_ch->ch, test_ch->buf, size);
1359 if (ret) {
1360 pr_info(TEST_MODULE_NAME ": sdio_read size %d "
1361 " err=%d"
1362 " for chan %s\n",
1363 size, -ret, test_ch->name);
1364 goto exit_err;
1365 }
1366 rx_packet_count++;
1367 test_ch->rx_bytes += size;
1368 }
1369
1370 TEST_DBG(TEST_MODULE_NAME
1371 ":total rx bytes = %d , rx_packet#=%d"
1372 " for chan %s\n",
1373 test_ch->rx_bytes, rx_packet_count, test_ch->name);
1374 TEST_DBG(TEST_MODULE_NAME
1375 ":total tx bytes = %d , tx_packet#=%d"
1376 " for chan %s\n",
1377 test_ch->tx_bytes, tx_packet_count, test_ch->name);
1378
1379 } /* while (tx_packet_count < max_packets ) */
1380
1381 end_jiffy = get_jiffies_64(); /* read the current time */
1382
1383 delta_jiffies = end_jiffy - start_jiffy;
1384 time_msec = jiffies_to_msecs(delta_jiffies);
1385
1386 pr_info(TEST_MODULE_NAME ":total rx bytes = 0x%x , rx_packet#=%d for"
1387 " chan %s.\n",
1388 test_ch->rx_bytes, rx_packet_count, test_ch->name);
1389 pr_info(TEST_MODULE_NAME ":total tx bytes = 0x%x , tx_packet#=%d"
1390 " for chan %s.\n",
1391 test_ch->tx_bytes, tx_packet_count, test_ch->name);
1392
1393 total_bytes = (test_ch->tx_bytes + test_ch->rx_bytes);
1394 pr_err(TEST_MODULE_NAME ":total bytes = %d, time msec = %d"
1395 " for chan %s\n",
1396 total_bytes , (int) time_msec, test_ch->name);
1397
1398 if (!test_ch->random_packet_size) {
1399 throughput = (total_bytes / time_msec) * 8 / 1000;
1400 pr_err(TEST_MODULE_NAME ":Performance = %d Mbit/sec for "
1401 "chan %s\n",
1402 throughput, test_ch->name);
1403 }
1404
1405#ifdef CONFIG_DEBUG_FS
1406 switch (test_ch->ch_id) {
1407 case SDIO_DUN:
1408 test_ctx->debug.dun_throughput = throughput;
1409 break;
1410 case SDIO_RMNT:
1411 test_ctx->debug.rmnt_throughput = throughput;
1412 break;
1413 default:
1414 pr_err(TEST_MODULE_NAME "No debugfs for this channel "
1415 "throughput");
1416 }
1417#endif
1418
1419 pr_err(TEST_MODULE_NAME ": A2 PERFORMANCE TEST END for chan %s.\n",
1420 test_ch->name);
1421
1422 pr_err(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
1423 test_ch->test_completed = 1;
1424 test_ch->test_result = TEST_PASSED;
1425 check_test_completion();
1426 return;
1427
1428exit_err:
1429 pr_err(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
1430 test_ch->test_completed = 1;
1431 test_ch->test_result = TEST_FAILED;
1432 check_test_completion();
1433 return;
1434}
1435
1436/**
Maya Erez53508c12011-08-01 14:04:03 +03001437 * rx_cleanup
1438 * This function reads all the messages sent by the modem until
1439 * the read_avail is 0 after 1 second of sleep.
1440 * The function returns the number of packets that was received.
1441 */
1442static void rx_cleanup(struct test_channel *test_ch, int *rx_packet_count)
1443{
1444 int read_avail = 0;
1445 int ret = 0;
1446
1447 read_avail = sdio_read_avail(test_ch->ch);
1448 TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
1449 test_ch->name, read_avail);
1450
1451 /* If no pending messages, wait to see if the modem sends data */
1452 if (read_avail == 0) {
1453 msleep(1000);
1454 read_avail = sdio_read_avail(test_ch->ch);
1455 }
1456
1457 while (read_avail > 0) {
1458 TEST_DBG(TEST_MODULE_NAME ": read_avail=%d for ch %s\n",
1459 read_avail, test_ch->name);
1460
1461 ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
1462 if (ret) {
1463 pr_info(TEST_MODULE_NAME ": sdio_read size %d "
1464 " err=%d for chan %s\n",
1465 read_avail, -ret, test_ch->name);
1466 break;
1467 }
1468 (*rx_packet_count)++;
1469 test_ch->rx_bytes += read_avail;
1470 read_avail = sdio_read_avail(test_ch->ch);
1471 if (read_avail == 0) {
1472 msleep(1000);
1473 read_avail = sdio_read_avail(test_ch->ch);
1474 }
1475 }
1476 pr_info(TEST_MODULE_NAME ": finished cleanup for ch %s, "
1477 "rx_packet_count=%d, total rx bytes=%d\n",
1478 test_ch->name, *rx_packet_count, test_ch->rx_bytes);
1479}
1480
1481
1482/**
1483 * A2 RTT Test
1484 * This function sends a packet and calculate the RTT time of
1485 * this packet.
1486 * The test also calculte Min, Max and Average RTT
1487 */
1488static void a2_rtt_test(struct test_channel *test_ch)
1489{
1490 int ret = 0 ;
1491 u32 read_avail = 0;
1492 u32 write_avail = 0;
1493 int tx_packet_count = 0;
1494 int rx_packet_count = 0;
1495 u16 *buf16 = (u16 *) test_ch->buf;
1496 int i;
1497 int max_packets = test_ch->config_msg.num_packets;
1498 u32 packet_size = test_ch->packet_length;
1499 s64 start_time, end_time;
1500 int delta_usec = 0;
1501 int time_average = 0;
1502 int min_delta_usec = 0xFFFF;
1503 int max_delta_usec = 0;
1504 int total_time = 0;
1505 int expected_read_size = 0;
1506
1507 for (i = 0; i < packet_size / 2; i++)
1508 buf16[i] = (u16) (i & 0xFFFF);
1509
1510 pr_info(TEST_MODULE_NAME ": A2 RTT TEST START for chan %s\n",
1511 test_ch->name);
1512
1513 rx_cleanup(test_ch, &rx_packet_count);
1514 rx_packet_count = 0;
1515
1516 while (tx_packet_count < max_packets) {
1517 if (test_ctx->exit_flag) {
1518 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1519 return;
1520 }
1521 start_time = 0;
1522 end_time = 0;
1523
1524 /* Allow sdio_al to go to sleep to change the read_threshold
1525 * to 1
1526 */
1527 msleep(100);
1528
1529 /* wait for data ready event */
1530 write_avail = sdio_write_avail(test_ch->ch);
1531 TEST_DBG(TEST_MODULE_NAME ":ch %s: write_avail=%d\n",
1532 test_ch->name, write_avail);
1533 if (write_avail == 0) {
1534 wait_event(test_ch->wait_q,
1535 atomic_read(&test_ch->tx_notify_count));
1536 atomic_dec(&test_ch->tx_notify_count);
1537 }
1538
1539 write_avail = sdio_write_avail(test_ch->ch);
1540 TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
1541 test_ch->name, write_avail);
1542 if (write_avail > 0) {
1543 TEST_DBG(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
1544 packet_size, test_ch->name);
1545 test_ch->buf[0] = tx_packet_count;
1546
1547 start_time = ktime_to_us(ktime_get());
1548 ret = sdio_write(test_ch->ch, test_ch->buf,
1549 packet_size);
1550 if (ret) {
1551 pr_err(TEST_MODULE_NAME ":sdio_write err=%d"
1552 " for chan %s\n",
1553 -ret, test_ch->name);
1554 goto exit_err;
1555 }
1556 tx_packet_count++;
1557 test_ch->tx_bytes += packet_size;
1558 } else {
1559 pr_err(TEST_MODULE_NAME ": Invalid write_avail"
1560 " %d for chan %s\n",
1561 write_avail, test_ch->name);
1562 goto exit_err;
1563 }
1564
1565 expected_read_size = packet_size + A2_HEADER_OVERHEAD;
1566
1567 read_avail = sdio_read_avail(test_ch->ch);
1568 TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
1569 test_ch->name, read_avail);
1570 while (read_avail < expected_read_size) {
1571 wait_event(test_ch->wait_q,
1572 atomic_read(&test_ch->rx_notify_count));
1573 atomic_dec(&test_ch->rx_notify_count);
1574 read_avail = sdio_read_avail(test_ch->ch);
1575 }
1576
1577 if (read_avail >= expected_read_size) {
1578 pr_debug(TEST_MODULE_NAME ":read_avail=%d for ch %s.\n",
1579 read_avail, test_ch->name);
1580 ret = sdio_read(test_ch->ch, test_ch->buf,
1581 expected_read_size);
1582 if (ret) {
1583 pr_info(TEST_MODULE_NAME ": sdio_read size %d "
1584 " err=%d for chan %s\n",
1585 expected_read_size, -ret,
1586 test_ch->name);
1587 goto exit_err;
1588 }
1589 end_time = ktime_to_us(ktime_get());
1590 rx_packet_count++;
1591 test_ch->rx_bytes += expected_read_size;
1592 } else {
1593 pr_info(TEST_MODULE_NAME ": Invalid read_avail "
1594 "%d for chan %s\n",
1595 read_avail, test_ch->name);
1596 goto exit_err;
1597 }
1598
1599 delta_usec = (int)(end_time - start_time);
1600 total_time += delta_usec;
1601 if (delta_usec < min_delta_usec)
1602 min_delta_usec = delta_usec;
1603 if (delta_usec > max_delta_usec)
1604 max_delta_usec = delta_usec;
1605
1606 TEST_DBG(TEST_MODULE_NAME
1607 ":RTT time=%d for packet #%d for chan %s\n",
1608 delta_usec, tx_packet_count, test_ch->name);
1609
1610 } /* while (tx_packet_count < max_packets ) */
1611
1612
1613 pr_info(TEST_MODULE_NAME ":total rx bytes = 0x%x , rx_packet#=%d for"
1614 " chan %s.\n",
1615 test_ch->rx_bytes, rx_packet_count, test_ch->name);
1616 pr_info(TEST_MODULE_NAME ":total tx bytes = 0x%x , tx_packet#=%d"
1617 " for chan %s.\n",
1618 test_ch->tx_bytes, tx_packet_count, test_ch->name);
1619
1620 time_average = total_time / tx_packet_count;
1621
1622 pr_info(TEST_MODULE_NAME ":Average RTT time = %d for chan %s\n",
1623 time_average, test_ch->name);
1624 pr_info(TEST_MODULE_NAME ":MIN RTT time = %d for chan %s\n",
1625 min_delta_usec, test_ch->name);
1626 pr_info(TEST_MODULE_NAME ":MAX RTT time = %d for chan %s\n",
1627 max_delta_usec, test_ch->name);
1628
1629 pr_info(TEST_MODULE_NAME ": A2 RTT TEST END for chan %s.\n",
1630 test_ch->name);
1631
1632 pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
1633 test_ch->test_completed = 1;
1634 test_ch->test_result = TEST_PASSED;
1635 check_test_completion();
1636 return;
1637
1638exit_err:
1639 pr_err(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
1640 test_ch->test_completed = 1;
1641 test_ch->test_result = TEST_FAILED;
1642 check_test_completion();
1643 return;
1644}
1645
1646
1647/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001648 * sender No loopback Test
1649 */
1650static void sender_no_loopback_test(struct test_channel *test_ch)
1651{
1652 int ret = 0 ;
1653 u32 write_avail = 0;
1654 int packet_count = 0;
1655 int size = 512;
1656 u16 *buf16 = (u16 *) test_ch->buf;
1657 int i;
1658 int max_packet_count = 10000;
1659 int random_num = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001660
1661 max_packet_count = test_ch->config_msg.num_packets;
1662
1663 for (i = 0 ; i < size / 2 ; i++)
1664 buf16[i] = (u16) (i & 0xFFFF);
1665
1666 pr_info(TEST_MODULE_NAME
1667 ":SENDER NO LP TEST START for chan %s\n", test_ch->name);
1668
1669 while (packet_count < max_packet_count) {
1670
1671 if (test_ctx->exit_flag) {
1672 pr_info(TEST_MODULE_NAME ":Exit Test.\n");
1673 return;
1674 }
1675
1676 random_num = get_random_int();
1677 size = (random_num % test_ch->packet_length) + 1;
1678
1679 TEST_DBG(TEST_MODULE_NAME ":SENDER WAIT FOR EVENT "
1680 "for chan %s\n",
1681 test_ch->name);
1682
1683 /* wait for data ready event */
1684 write_avail = sdio_write_avail(test_ch->ch);
1685 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1686 if (write_avail < size) {
1687 wait_event(test_ch->wait_q,
1688 atomic_read(&test_ch->tx_notify_count));
1689 atomic_dec(&test_ch->tx_notify_count);
1690 }
1691
1692 write_avail = sdio_write_avail(test_ch->ch);
1693 TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
1694 if (write_avail < size) {
1695 pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
1696 continue;
1697 }
1698
1699 test_ch->buf[0] = packet_count;
1700
1701 ret = sdio_write(test_ch->ch, test_ch->buf, size);
1702 if (ret) {
1703 pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
1704 -ret);
1705 goto exit_err;
1706 }
1707
1708 test_ch->tx_bytes += size;
1709 packet_count++;
1710
1711 TEST_DBG(TEST_MODULE_NAME
1712 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
1713 " for chan %s\n",
1714 test_ch->tx_bytes, packet_count, size, test_ch->name);
1715
1716 } /* end of while */
1717
1718 pr_info(TEST_MODULE_NAME
1719 ":SENDER TEST END: total tx bytes = 0x%x, "
1720 " for chan %s\n",
1721 test_ch->tx_bytes, test_ch->name);
1722
Yaniv Gardi3e327762011-07-27 11:11:04 +03001723 test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001724
Yaniv Gardi3e327762011-07-27 11:11:04 +03001725 if (test_ch->modem_result_per_chan) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001726 pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
1727 test_ch->name);
1728 test_ch->test_result = TEST_PASSED;
1729 } else {
1730 pr_info(TEST_MODULE_NAME ": TEST FAILURE for chan %s.\n",
1731 test_ch->name);
1732 test_ch->test_result = TEST_FAILED;
1733 }
1734 test_ch->test_completed = 1;
1735 check_test_completion();
1736 return;
1737
1738exit_err:
1739 pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
1740 test_ch->name);
1741 test_ch->test_completed = 1;
1742 test_ch->test_result = TEST_FAILED;
1743 check_test_completion();
1744 return;
1745}
1746
1747/**
1748 * Worker thread to handle the tests types
1749 */
1750static void worker(struct work_struct *work)
1751{
1752 struct test_channel *test_ch = NULL;
1753 struct test_work *test_work = container_of(work,
1754 struct test_work,
1755 work);
1756 int test_type = 0;
1757
1758 test_ch = test_work->test_ch;
1759
1760 if (test_ch == NULL) {
1761 pr_err(TEST_MODULE_NAME ":NULL test_ch\n");
1762 return;
1763 }
1764
1765 test_type = test_ch->test_type;
1766
1767 switch (test_type) {
1768 case SDIO_TEST_LOOPBACK_HOST:
1769 loopback_test(test_ch);
1770 break;
1771 case SDIO_TEST_LOOPBACK_CLIENT:
1772 sender_test(test_ch);
1773 break;
1774 case SDIO_TEST_PERF:
1775 a2_performance_test(test_ch);
1776 break;
1777 case SDIO_TEST_LPM_CLIENT_WAKER:
1778 lpm_test(test_ch);
1779 break;
1780 case SDIO_TEST_LPM_HOST_WAKER:
1781 lpm_test_host_waker(test_ch);
1782 break;
1783 case SDIO_TEST_HOST_SENDER_NO_LP:
1784 sender_no_loopback_test(test_ch);
1785 break;
1786 case SDIO_TEST_LPM_RANDOM:
1787 lpm_continuous_rand_test(test_ch);
Maya Erezf204e692011-08-12 22:00:13 +03001788 break;
Maya Erez53508c12011-08-01 14:04:03 +03001789 case SDIO_TEST_RTT:
1790 a2_rtt_test(test_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791 break;
1792 default:
1793 pr_err(TEST_MODULE_NAME ":Bad Test type = %d.\n",
1794 (int) test_type);
1795 }
1796}
1797
1798
1799/**
1800 * Notification Callback
1801 *
1802 * Notify the worker
1803 *
1804 */
1805static void notify(void *priv, unsigned channel_event)
1806{
1807 struct test_channel *test_ch = (struct test_channel *) priv;
1808
Yaniv Gardi3e327762011-07-27 11:11:04 +03001809 pr_debug(TEST_MODULE_NAME ": %s - notify event=%d.\n",
1810 __func__, channel_event);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001811
1812 if (test_ch->ch == NULL) {
Yaniv Gardi3e327762011-07-27 11:11:04 +03001813 pr_info(TEST_MODULE_NAME ": %s - notify before ch ready.\n",
1814 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001815 return;
1816 }
1817
1818 switch (channel_event) {
1819 case SDIO_EVENT_DATA_READ_AVAIL:
1820 atomic_inc(&test_ch->rx_notify_count);
1821 atomic_set(&test_ch->any_notify_count, 1);
Yaniv Gardi3e327762011-07-27 11:11:04 +03001822 TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_READ_AVAIL, "
1823 "any_notify_count=%d, rx_notify_count=%d\n",
1824 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825 atomic_read(&test_ch->any_notify_count),
1826 atomic_read(&test_ch->rx_notify_count));
Yaniv Gardi3e327762011-07-27 11:11:04 +03001827 /*
1828 * when there is pending data on a channel we would like to
1829 * turn on the bit mask that implies that there is pending
1830 * data for that channel on that deivce
1831 */
1832 if (test_ch->test_device != NULL &&
1833 test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
1834 spin_lock_irqsave(&test_ch->test_device->lpm_array_lock,
1835 test_ch->test_device->
1836 lpm_array_lock_flags);
1837 test_ch->test_device->read_avail_mask |=
1838 test_ch->channel_mask_id;
1839 test_ch->notify_counter_per_chan++;
1840
1841 lpm_test_update_entry(test_ch, LPM_NOTIFY, "NOTIFY", 0);
1842 spin_unlock_irqrestore(&test_ch->test_device->
1843 lpm_array_lock,
1844 test_ch->test_device->
1845 lpm_array_lock_flags);
1846 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001847 break;
1848
1849 case SDIO_EVENT_DATA_WRITE_AVAIL:
1850 atomic_inc(&test_ch->tx_notify_count);
1851 atomic_set(&test_ch->any_notify_count, 1);
Yaniv Gardi3e327762011-07-27 11:11:04 +03001852 TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_WRITE_AVAIL, "
1853 "any_notify_count=%d, tx_notify_count=%d\n",
1854 __func__,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001855 atomic_read(&test_ch->any_notify_count),
1856 atomic_read(&test_ch->tx_notify_count));
1857 break;
1858
1859 default:
1860 BUG();
1861 }
1862 wake_up(&test_ch->wait_q);
1863
1864}
1865
1866#ifdef CONFIG_MSM_SDIO_SMEM
1867static int sdio_smem_test_cb(int event)
1868{
1869 struct test_channel *tch = test_ctx->test_ch_arr[SDIO_SMEM];
1870 pr_debug(TEST_MODULE_NAME ":%s: Received event %d\n", __func__, event);
1871
1872 switch (event) {
1873 case SDIO_SMEM_EVENT_READ_DONE:
1874 tch->rx_bytes += SMEM_MAX_XFER_SIZE;
1875 if (tch->rx_bytes >= 40000000) {
1876 if (!tch->test_completed) {
1877 pr_info(TEST_MODULE_NAME ":SMEM test PASSED\n");
1878 tch->test_completed = 1;
1879 tch->test_result = TEST_PASSED;
1880 check_test_completion();
1881 }
1882
1883 }
1884 break;
1885 case SDIO_SMEM_EVENT_READ_ERR:
1886 pr_err(TEST_MODULE_NAME ":Read overflow, SMEM test FAILED\n");
1887 tch->test_completed = 1;
1888 tch->test_result = TEST_FAILED;
1889 check_test_completion();
1890 return -EIO;
1891 default:
1892 pr_err(TEST_MODULE_NAME ":Unhandled event\n");
1893 return -EINVAL;
1894 }
1895 return 0;
1896}
1897
1898static int sdio_smem_test_probe(struct platform_device *pdev)
1899{
1900 int ret = 0;
1901
1902 test_ctx->sdio_smem = container_of(pdev, struct sdio_smem_client,
1903 plat_dev);
1904
1905 test_ctx->sdio_smem->buf = test_ctx->smem_buf;
1906 test_ctx->sdio_smem->size = SMEM_MAX_XFER_SIZE;
1907 test_ctx->sdio_smem->cb_func = sdio_smem_test_cb;
1908 ret = sdio_smem_register_client();
1909 if (ret)
1910 pr_info(TEST_MODULE_NAME "%s: Error (%d) registering sdio_smem "
1911 "test client\n",
1912 __func__, ret);
1913 return ret;
1914}
1915
1916static struct platform_driver sdio_smem_drv = {
1917 .probe = sdio_smem_test_probe,
1918 .driver = {
1919 .name = "SDIO_SMEM_CLIENT",
1920 .owner = THIS_MODULE,
1921 },
1922};
1923#endif
1924
1925
1926static void default_sdio_al_test_release(struct device *dev)
1927{
1928 pr_info(MODULE_NAME ":platform device released.\n");
1929}
1930
1931static void sdio_test_lpm_timeout_handler(unsigned long data)
1932{
1933 struct test_channel *tch = (struct test_channel *)data;
1934
1935 pr_info(TEST_MODULE_NAME ": %s - LPM TEST TIMEOUT Expired after "
1936 "%d ms\n", __func__, tch->timeout_ms);
1937 tch->test_completed = 1;
1938 pr_info(TEST_MODULE_NAME ": %s - tch->test_result = TEST_FAILED\n",
1939 __func__);
1940 tch->test_completed = 1;
1941 tch->test_result = TEST_FAILED;
1942 check_test_completion();
1943 return;
1944}
1945
1946static void sdio_test_lpm_timer_handler(unsigned long data)
1947{
1948 struct test_channel *tch = (struct test_channel *)data;
1949
1950 pr_info(TEST_MODULE_NAME ": %s - LPM TEST Timer Expired after "
1951 "%d ms\n", __func__, tch->timer_interval_ms);
1952
1953 if (!tch) {
1954 pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. "
1955 "tch is NULL\n", __func__);
1956 return;
1957 }
1958
1959 if (!tch->ch) {
1960 pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. tch->ch "
1961 "is NULL\n", __func__);
1962 tch->test_result = TEST_FAILED;
1963 return;
1964 }
1965
1966 /* Verfiy that we voted for sleep */
1967 if (tch->is_ok_to_sleep) {
1968 tch->test_result = TEST_PASSED;
1969 pr_info(TEST_MODULE_NAME ": %s - 8K voted for sleep\n",
1970 __func__);
1971 } else {
1972 tch->test_result = TEST_FAILED;
1973 pr_info(TEST_MODULE_NAME ": %s - 8K voted against sleep\n",
1974 __func__);
1975
1976 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03001977
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001978 sdio_al_unregister_lpm_cb(tch->sdio_al_device);
1979
1980 if (tch->test_type == SDIO_TEST_LPM_HOST_WAKER) {
1981 atomic_set(&tch->wakeup_client, 1);
1982 wake_up(&tch->wait_q);
1983 }
1984}
1985
1986int sdio_test_wakeup_callback(void *device_handle, int is_vote_for_sleep)
1987{
1988 int i = 0;
1989
1990 TEST_DBG(TEST_MODULE_NAME ": %s is_vote_for_sleep=%d!!!",
1991 __func__, is_vote_for_sleep);
1992
1993 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
1994 struct test_channel *tch = test_ctx->test_ch_arr[i];
1995
1996 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
1997 continue;
1998 if (tch->sdio_al_device == device_handle) {
1999 tch->is_ok_to_sleep = is_vote_for_sleep;
2000
Yaniv Gardi3e327762011-07-27 11:11:04 +03002001 if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
2002 spin_lock_irqsave(&tch->test_device->
2003 lpm_array_lock,
2004 tch->test_device->
2005 lpm_array_lock_flags);
2006
2007 if (is_vote_for_sleep == 1)
2008 lpm_test_update_entry(tch,
2009 LPM_SLEEP,
2010 "SLEEP ", 0);
2011 else
2012 lpm_test_update_entry(tch,
2013 LPM_WAKEUP,
2014 "WAKEUP", 0);
2015
2016 spin_unlock_irqrestore(&tch->test_device->
2017 lpm_array_lock,
2018 tch->test_device->
2019 lpm_array_lock_flags);
2020 break;
2021 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022 }
2023 }
2024
Yaniv Gardi3e327762011-07-27 11:11:04 +03002025 return 0;
2026}
2027
2028static int sdio_test_find_dev(struct test_channel *tch)
2029{
2030 int j;
2031 int null_index = -1;
2032
2033 for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
2034
2035 struct sdio_test_device *test_dev =
2036 &test_ctx->test_dev_arr[j];
2037
2038 if (test_dev->sdio_al_device == NULL) {
2039 if (null_index == -1)
2040 null_index = j;
2041 continue;
2042 }
2043
2044 if (test_dev->sdio_al_device ==
2045 tch->ch->sdio_al_dev) {
2046 test_dev->open_channels_counter_to_recv++;
2047 test_dev->open_channels_counter_to_send++;
2048 tch->test_device = test_dev;
2049 /* setting mask id for pending data for
2050 this channel */
2051 tch->channel_mask_id = test_dev->next_mask_id;
2052 test_dev->next_mask_id *= 2;
2053 pr_info(TEST_MODULE_NAME ": %s - channel %s "
2054 "got read_mask_id = 0x%x. device "
2055 "next_mask_id=0x%x",
2056 __func__, tch->name, tch->channel_mask_id,
2057 test_dev->next_mask_id);
2058 break;
2059 }
2060 }
2061
2062 /*
2063 * happens ones a new device is "discovered" while testing. i.e
2064 * if testing a few channels, a new deivce will be "discovered" once
2065 * the first channel of a device is being tested
2066 */
2067 if (j == MAX_NUM_OF_SDIO_DEVICES) {
2068
2069 struct sdio_test_device *test_dev =
2070 &test_ctx->
2071 test_dev_arr[null_index];
2072 test_dev->sdio_al_device =
2073 tch->ch->sdio_al_dev;
2074
2075 test_ctx->number_of_active_devices++;
2076 test_ctx->max_number_of_devices++;
2077 test_dev->open_channels_counter_to_recv++;
2078 test_dev->open_channels_counter_to_send++;
2079 test_dev->next_avail_entry_in_array = 0;
2080 tch->test_device = test_dev;
2081 tch->test_device->array_size =
2082 LPM_ARRAY_SIZE;
2083 test_dev->modem_result_per_dev = 1;
2084 tch->modem_result_per_chan = 0;
2085
2086 spin_lock_init(&test_dev->
2087 lpm_array_lock);
2088 pr_err(MODULE_NAME ": %s - "
2089 "Allocating Msg Array for "
2090 "Maximum open channels for device (%d) "
2091 "Channels. Array has %d entries",
2092 __func__,
2093 LPM_MAX_OPEN_CHAN_PER_DEV,
2094 test_dev->array_size);
2095
2096
2097 if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
2098 pr_err(TEST_MODULE_NAME ": %s - initializing the "
2099 "lpm_array", __func__);
2100
2101 test_dev->lpm_arr =
2102 kzalloc(sizeof(
2103 struct lpm_entry_type) *
2104 tch->
2105 test_device->array_size,
2106 GFP_KERNEL);
2107
2108 if (!test_dev->lpm_arr) {
2109 pr_err(MODULE_NAME ": %s - "
2110 "lpm_arr is NULL",
2111 __func__);
2112 return -ENOMEM;
2113 }
2114 }
2115
2116 /*
2117 * in new device, initialize next_mask_id, and setting
2118 * mask_id to the channel
2119 */
2120 test_dev->next_mask_id = 0x1;
2121 tch->channel_mask_id = test_dev->next_mask_id;
2122 test_dev->next_mask_id *= 2;
2123 pr_info(TEST_MODULE_NAME ": %s - channel %s got "
2124 "read_mask_id = 0x%x. device next_mask_id=0x%x",
2125 __func__,
2126 tch->name,
2127 tch->channel_mask_id,
2128 test_dev->next_mask_id);
2129 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002130
2131 return 0;
2132}
2133
Yaniv Gardi3e327762011-07-27 11:11:04 +03002134static void check_test_result(void)
2135{
2136 int result = 1;
2137 int i = 0;
2138
2139 test_ctx->max_number_of_devices = 0;
2140
2141 pr_info(TEST_MODULE_NAME ": %s - Woke Up\n", __func__);
2142
2143 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2144 struct test_channel *tch = test_ctx->test_ch_arr[i];
2145
2146 if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
2147 continue;
2148
2149 if (tch->test_type == SDIO_TEST_LPM_RANDOM)
2150 result &= tch->test_device->final_result_per_dev;
2151 else
2152 if (tch->test_result == TEST_FAILED) {
2153 pr_info(TEST_MODULE_NAME ": %s - "
2154 "Test FAILED\n", __func__);
2155 test_ctx->test_result = TEST_FAILED;
2156 pr_err(TEST_MODULE_NAME ": %s - "
2157 "test_result %d",
2158 __func__, test_ctx->test_result);
2159 return;
2160 }
2161 }
2162
2163 if (result == 0) {
2164 pr_info(TEST_MODULE_NAME ": %s - Test FAILED\n", __func__);
2165 test_ctx->test_result = TEST_FAILED;
2166 pr_err(TEST_MODULE_NAME ": %s - "
2167 "test_result %d",
2168 __func__, test_ctx->test_result);
2169 return;
2170 }
2171
2172 pr_info(TEST_MODULE_NAME ": %s - Test PASSED", __func__);
2173 test_ctx->test_result = TEST_PASSED;
2174 pr_err(TEST_MODULE_NAME ": %s - "
2175 "test_result %d",
2176 __func__, test_ctx->test_result);
2177 return;
2178}
2179
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002180/**
2181 * Test Main
2182 */
2183static int test_start(void)
2184{
2185 int ret = -ENOMEM;
2186 int i;
2187
2188 pr_debug(TEST_MODULE_NAME ":Starting Test ....\n");
2189
2190 test_ctx->test_completed = 0;
2191 test_ctx->test_result = TEST_NO_RESULT;
2192 test_ctx->debug.dun_throughput = 0;
2193 test_ctx->debug.rmnt_throughput = 0;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002194 test_ctx->number_of_active_devices = 0;
2195
2196 pr_err(TEST_MODULE_NAME ": %s - test_result %d",
2197 __func__, test_ctx->test_result);
2198
2199 memset(test_ctx->test_dev_arr, 0,
2200 sizeof(struct sdio_test_device)*MAX_NUM_OF_SDIO_DEVICES);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002201
2202 /* Open The Channels */
2203 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2204 struct test_channel *tch = test_ctx->test_ch_arr[i];
2205
2206 if ((!tch) || (!tch->is_used))
2207 continue;
2208
2209 tch->rx_bytes = 0;
2210 tch->tx_bytes = 0;
2211
2212 atomic_set(&tch->tx_notify_count, 0);
2213 atomic_set(&tch->rx_notify_count, 0);
2214 atomic_set(&tch->any_notify_count, 0);
2215 atomic_set(&tch->wakeup_client, 0);
2216
Yaniv Gardi3e327762011-07-27 11:11:04 +03002217 /* in case there are values left from previous tests */
2218 tch->notify_counter_per_chan = 0;
2219
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002220 memset(tch->buf, 0x00, tch->buf_size);
2221 tch->test_result = TEST_NO_RESULT;
2222
2223 tch->test_completed = 0;
2224
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002225 if (!tch->ch_ready) {
2226 pr_info(TEST_MODULE_NAME ":openning channel %s\n",
2227 tch->name);
2228 tch->ch_ready = true;
2229 if (tch->ch_id == SDIO_SMEM) {
2230 test_ctx->smem_pdev.name = "SDIO_SMEM";
2231 test_ctx->smem_pdev.dev.release =
2232 default_sdio_al_test_release;
2233 platform_device_register(&test_ctx->smem_pdev);
2234 } else {
2235 ret = sdio_open(tch->name , &tch->ch, tch,
2236 notify);
2237 if (ret) {
2238 pr_info(TEST_MODULE_NAME
2239 ":openning channel %s failed\n",
2240 tch->name);
2241 tch->ch_ready = false;
2242 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002243 }
2244 }
2245
Yaniv Gardi3e327762011-07-27 11:11:04 +03002246 if (tch->ch_id != SDIO_SMEM) {
2247 ret = sdio_test_find_dev(tch);
2248
2249 if (ret) {
2250 pr_err(TEST_MODULE_NAME ": %s - "
2251 "sdio_test_find_dev() returned with "
2252 "error", __func__);
2253 return -ENODEV;
2254 }
2255
2256 tch->sdio_al_device = tch->ch->sdio_al_dev;
2257 }
2258
2259 if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
2260 (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
2261 (tch->test_type == SDIO_TEST_LPM_RANDOM))
2262 sdio_al_register_lpm_cb(tch->sdio_al_device,
2263 sdio_test_wakeup_callback);
2264 }
2265
2266 /*
2267 * make some space between opening the channels and sending the
2268 * config messages
2269 */
2270 msleep(100);
2271
2272 /*
2273 * try to delay send_config_msg of all channels to after the point
2274 * when we open them all
2275 */
2276 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2277 struct test_channel *tch = test_ctx->test_ch_arr[i];
2278
2279 if ((!tch) || (!tch->is_used))
2280 continue;
2281
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002282 if ((tch->ch_ready) && (tch->ch_id != SDIO_SMEM))
2283 send_config_msg(tch);
2284
2285 if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
2286 (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
2287 (tch->test_type == SDIO_TEST_LPM_RANDOM)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002288 if (tch->timer_interval_ms > 0) {
2289 pr_info(TEST_MODULE_NAME ": %s - init timer, "
Yaniv Gardi3e327762011-07-27 11:11:04 +03002290 "ms=%d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002291 __func__, tch->timer_interval_ms);
2292 init_timer(&tch->timer);
2293 tch->timer.data = (unsigned long)tch;
2294 tch->timer.function =
2295 sdio_test_lpm_timer_handler;
2296 tch->timer.expires = jiffies +
2297 msecs_to_jiffies(tch->timer_interval_ms);
2298 add_timer(&tch->timer);
2299 }
2300 }
2301 }
2302
2303 pr_debug(TEST_MODULE_NAME ":queue_work..\n");
2304 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2305 struct test_channel *tch = test_ctx->test_ch_arr[i];
2306
2307 if ((!tch) || (!tch->is_used) || (!tch->ch_ready) ||
2308 (tch->ch_id == SDIO_SMEM))
2309 continue;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002310
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002311 queue_work(tch->workqueue, &tch->test_work.work);
2312 }
2313
Yaniv Gardi3e327762011-07-27 11:11:04 +03002314 pr_info(TEST_MODULE_NAME ": %s - Waiting for the test completion\n",
2315 __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002316
Yaniv Gardi3e327762011-07-27 11:11:04 +03002317 wait_event(test_ctx->wait_q, test_ctx->test_completed);
2318 check_test_result();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002319
2320 return 0;
2321}
2322
2323static int set_params_loopback_9k(struct test_channel *tch)
2324{
2325 if (!tch) {
2326 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2327 return -EINVAL;
2328 }
2329 tch->is_used = 1;
2330 tch->test_type = SDIO_TEST_LOOPBACK_CLIENT;
2331 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2332 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2333 tch->config_msg.num_packets = 10000;
2334 tch->config_msg.num_iterations = 1;
2335
2336 tch->packet_length = 512;
2337 if (tch->ch_id == SDIO_RPC)
2338 tch->packet_length = 128;
2339 tch->timer_interval_ms = 0;
2340
2341 return 0;
2342}
2343
2344static int set_params_a2_perf(struct test_channel *tch)
2345{
2346 if (!tch) {
2347 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2348 return -EINVAL;
2349 }
2350 tch->is_used = 1;
2351 tch->test_type = SDIO_TEST_PERF;
2352 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2353 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
Maya Erezbde9df82011-08-02 14:40:00 +03002354 tch->packet_length = MAX_XFER_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002355 if (tch->ch_id == SDIO_DIAG)
2356 tch->packet_length = 512;
Maya Erezbde9df82011-08-02 14:40:00 +03002357 else if (tch->ch_id == SDIO_DUN)
2358 tch->packet_length = DUN_PACKET_SIZE;
2359 pr_info(TEST_MODULE_NAME ": %s: packet_length=%d", __func__,
2360 tch->packet_length);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002361
2362 tch->config_msg.num_packets = 10000;
2363 tch->config_msg.num_iterations = 1;
2364 tch->random_packet_size = 0;
2365
2366 tch->timer_interval_ms = 0;
2367
2368 return 0;
2369}
2370
Maya Erez53508c12011-08-01 14:04:03 +03002371static int set_params_rtt(struct test_channel *tch)
2372{
2373 if (!tch) {
2374 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2375 return -EINVAL;
2376 }
2377 tch->is_used = 1;
2378 tch->test_type = SDIO_TEST_RTT;
2379 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2380 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2381 tch->packet_length = 32;
2382
2383 tch->config_msg.num_packets = 200;
2384 tch->config_msg.num_iterations = 1;
2385 tch->random_packet_size = 0;
2386
2387 tch->timer_interval_ms = 0;
2388
2389 return 0;
2390}
2391
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002392static int set_params_a2_small_pkts(struct test_channel *tch)
2393{
2394 if (!tch) {
2395 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2396 return -EINVAL;
2397 }
2398 tch->is_used = 1;
2399 tch->test_type = SDIO_TEST_PERF;
2400 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2401 tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
2402 tch->packet_length = 128;
2403
2404 tch->config_msg.num_packets = 1000000;
2405 tch->config_msg.num_iterations = 1;
2406 tch->random_packet_size = 1;
2407
2408 tch->timer_interval_ms = 0;
2409
2410 return 0;
2411}
2412
2413static int set_params_smem_test(struct test_channel *tch)
2414{
2415 if (!tch) {
2416 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2417 return -EINVAL;
2418 }
2419 tch->is_used = 1;
2420 tch->timer_interval_ms = 0;
2421
2422 return 0;
2423}
2424
2425static int set_params_lpm_test(struct test_channel *tch,
2426 enum sdio_test_case_type test,
2427 int timer_interval_ms)
2428{
2429 static int first_time = 1;
2430 if (!tch) {
2431 pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
2432 return -EINVAL;
2433 }
Yaniv Gardi3e327762011-07-27 11:11:04 +03002434
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002435 tch->is_used = 1;
2436 tch->test_type = test;
2437 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2438 tch->config_msg.test_case = test;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002439 tch->config_msg.num_packets = LPM_TEST_NUM_OF_PACKETS;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002440 tch->config_msg.num_iterations = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002441 tch->timer_interval_ms = timer_interval_ms;
2442 tch->timeout_ms = 10000;
2443
2444 tch->packet_length = 0;
2445 if (test != SDIO_TEST_LPM_RANDOM) {
2446 init_timer(&tch->timeout_timer);
2447 tch->timeout_timer.data = (unsigned long)tch;
2448 tch->timeout_timer.function = sdio_test_lpm_timeout_handler;
2449 tch->timeout_timer.expires = jiffies +
2450 msecs_to_jiffies(tch->timeout_ms);
2451 add_timer(&tch->timeout_timer);
2452 pr_info(TEST_MODULE_NAME ": %s - Initiated LPM TIMEOUT TIMER."
2453 "set to %d ms\n",
2454 __func__, tch->timeout_ms);
2455 }
2456
2457 if (first_time) {
2458 pr_info(TEST_MODULE_NAME ": %s - wake_lock_init() called\n",
2459 __func__);
2460 wake_lock_init(&test_ctx->wake_lock,
2461 WAKE_LOCK_SUSPEND, TEST_MODULE_NAME);
2462 first_time = 0;
2463 }
2464
2465 pr_info(TEST_MODULE_NAME ": %s - wake_lock() for the TEST is "
Yaniv Gardi3e327762011-07-27 11:11:04 +03002466 "called channel %s. to prevent real sleeping\n",
2467 __func__, tch->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002468 wake_lock(&test_ctx->wake_lock);
2469
2470 return 0;
2471}
2472
2473static int set_params_8k_sender_no_lp(struct test_channel *tch)
2474{
2475 if (!tch) {
2476 pr_err(TEST_MODULE_NAME ":NULL channel\n");
2477 return -EINVAL;
2478 }
2479 tch->is_used = 1;
2480 tch->test_type = SDIO_TEST_HOST_SENDER_NO_LP;
2481 tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
2482 tch->config_msg.test_case = SDIO_TEST_HOST_SENDER_NO_LP;
2483 tch->config_msg.num_packets = 1000;
2484 tch->config_msg.num_iterations = 1;
2485
2486 tch->packet_length = 512;
2487 if (tch->ch_id == SDIO_RPC)
2488 tch->packet_length = 128;
2489 tch->timer_interval_ms = 0;
2490
2491 return 0;
2492}
2493
Maya Erezf204e692011-08-12 22:00:13 +03002494static void set_pseudo_random_seed(void)
2495{
2496 /* Set the seed accoring to the kernel command parameters if any or
2497 get a random value */
2498 if (seed != 0) {
2499 test_ctx->lpm_pseudo_random_seed = seed;
2500 } else {
2501 test_ctx->lpm_pseudo_random_seed =
2502 (unsigned int)(get_jiffies_64() & 0xFFFF);
2503 test_ctx->lpm_pseudo_random_seed =
2504 pseudo_random_seed(&test_ctx->lpm_pseudo_random_seed);
2505 }
2506
2507 pr_info(TEST_MODULE_NAME ":%s: seed is %u",
2508 __func__, test_ctx->lpm_pseudo_random_seed);
2509}
2510
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002511/**
2512 * Write File.
2513 *
2514 * @note Trigger the test from user space by:
2515 * echo 1 > /dev/sdio_al_test
2516 *
2517 */
2518ssize_t test_write(struct file *filp, const char __user *buf, size_t size,
2519 loff_t *f_pos)
2520{
2521 int ret = 0;
2522 int i;
2523
Yaniv Gardi3e327762011-07-27 11:11:04 +03002524 for (i = 0 ; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
2525 test_ctx->test_dev_arr[i].sdio_al_device = NULL;
2526
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002527 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2528 struct test_channel *tch = test_ctx->test_ch_arr[i];
2529 if (!tch)
2530 continue;
2531 tch->is_used = 0;
2532 }
2533
2534 ret = strict_strtol(buf, 10, &test_ctx->testcase);
2535
2536 switch (test_ctx->testcase) {
2537 case 1:
2538 /* RPC */
2539 pr_debug(TEST_MODULE_NAME " --RPC sender--.\n");
2540 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]))
2541 return size;
2542 break;
2543 case 2:
2544 /* RPC, QMI and DIAG */
2545 pr_debug(TEST_MODULE_NAME " --RPC, QMI and DIAG sender--.\n");
2546 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2547 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]) ||
2548 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]))
2549 return size;
2550 break;
2551 case 4:
2552 pr_debug(TEST_MODULE_NAME " --SMEM--.\n");
2553 if (set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]))
2554 return size;
2555 break;
2556
2557 case 5:
2558 pr_debug(TEST_MODULE_NAME " --SMEM and RPC--.\n");
2559 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2560 set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]))
2561 return size;
2562 break;
2563 case 6:
2564 pr_debug(TEST_MODULE_NAME " --RmNet A2 Performance--.\n");
2565 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]))
2566 return size;
2567 break;
2568
2569 case 7:
2570 pr_debug(TEST_MODULE_NAME " --DUN A2 Performance--.\n");
2571 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]))
2572 return size;
2573 break;
2574 case 8:
2575 pr_debug(TEST_MODULE_NAME " --RmNet and DUN A2 Performance--."
2576 "\n");
2577 if (set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]) ||
2578 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]))
2579 return size;
2580 break;
2581 case 9:
2582 pr_debug(TEST_MODULE_NAME " --RPC sender and RmNet A2 "
2583 "Performance--.\n");
2584 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2585 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]))
2586 return size;
2587 break;
2588 case 10:
2589 pr_debug(TEST_MODULE_NAME " --All the channels--.\n");
2590 if (set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]) ||
2591 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]) ||
2592 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]) ||
2593 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]) ||
2594 set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]) ||
2595 set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]) ||
2596 set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_CIQ]))
2597 return size;
2598 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002599 case 16:
2600 pr_info(TEST_MODULE_NAME " -- host sender no LP for Diag --");
2601 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
2602 break;
2603 case 17:
2604 pr_info(TEST_MODULE_NAME " -- host sender no LP for Diag, RPC, "
2605 "CIQ --");
2606 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
2607 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_CIQ]);
2608 set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_RPC]);
2609 break;
2610 case 18:
2611 pr_info(TEST_MODULE_NAME " -- rmnet small packets (5-128) --");
2612 if (set_params_a2_small_pkts(test_ctx->test_ch_arr[SDIO_RMNT]))
2613 return size;
2614 break;
Maya Erez53508c12011-08-01 14:04:03 +03002615 case 19:
2616 pr_info(TEST_MODULE_NAME " -- rmnet RTT --");
2617 if (set_params_rtt(test_ctx->test_ch_arr[SDIO_RMNT]))
2618 return size;
2619 break;
Yaniv Gardi3e327762011-07-27 11:11:04 +03002620 case 111:
2621 pr_info(TEST_MODULE_NAME " --LPM Test For Device 1. Client "
2622 "wakes the Host --.\n");
2623 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2624 SDIO_TEST_LPM_CLIENT_WAKER, 90))
2625 return size;
2626 break;
2627 case 113:
2628 pr_info(TEST_MODULE_NAME " --LPM Test For Device 1. Host "
2629 "wakes the Client --.\n");
2630 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2631 SDIO_TEST_LPM_HOST_WAKER, 120))
2632 return size;
2633 break;
2634 case 114:
2635 pr_info(TEST_MODULE_NAME " --LPM Test RANDOM SINGLE "
2636 "CHANNEL--.\n");
Maya Erezf204e692011-08-12 22:00:13 +03002637 set_pseudo_random_seed();
Yaniv Gardi3e327762011-07-27 11:11:04 +03002638 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2639 SDIO_TEST_LPM_RANDOM, 0))
2640 return size;
2641 break;
2642 case 115:
2643 pr_info(TEST_MODULE_NAME " --LPM Test RANDOM MULTI "
2644 "CHANNEL--.\n");
Maya Erezf204e692011-08-12 22:00:13 +03002645 set_pseudo_random_seed();
Yaniv Gardi3e327762011-07-27 11:11:04 +03002646 if (set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
2647 SDIO_TEST_LPM_RANDOM, 0) ||
2648 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_CIQ],
2649 SDIO_TEST_LPM_RANDOM, 0) ||
2650 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_DIAG],
2651 SDIO_TEST_LPM_RANDOM, 0) ||
2652 set_params_lpm_test(test_ctx->test_ch_arr[SDIO_QMI],
2653 SDIO_TEST_LPM_RANDOM, 0))
2654 return size;
2655 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002656 case 98:
2657 pr_info(TEST_MODULE_NAME " set runtime debug on");
2658 test_ctx->runtime_debug = 1;
2659 return size;
2660 case 99:
2661 pr_info(TEST_MODULE_NAME " set runtime debug off");
2662 test_ctx->runtime_debug = 0;
2663 return size;
2664 default:
2665 pr_info(TEST_MODULE_NAME ":Bad Test number = %d.\n",
2666 (int)test_ctx->testcase);
2667 return 0;
2668 }
2669 ret = test_start();
2670 if (ret) {
2671 pr_err(TEST_MODULE_NAME ":test_start failed, ret = %d.\n",
2672 ret);
2673
2674 }
2675 return size;
2676}
2677
2678/**
2679 * Test Channel Init.
2680 */
2681int test_channel_init(char *name)
2682{
2683 struct test_channel *test_ch;
2684 int ch_id = 0;
2685#ifdef CONFIG_MSM_SDIO_SMEM
2686 int ret;
2687#endif
2688
2689 pr_debug(TEST_MODULE_NAME ":%s.\n", __func__);
2690 pr_info(TEST_MODULE_NAME ": init test cahnnel %s.\n", name);
2691
2692 ch_id = channel_name_to_id(name);
2693 pr_debug(TEST_MODULE_NAME ":id = %d.\n", ch_id);
2694 if (test_ctx->test_ch_arr[ch_id] == NULL) {
2695 test_ch = kzalloc(sizeof(*test_ch), GFP_KERNEL);
2696 if (test_ch == NULL) {
2697 pr_err(TEST_MODULE_NAME ":kzalloc err for allocating "
2698 "test_ch %s.\n",
2699 name);
2700 return -ENOMEM;
2701 }
2702 test_ctx->test_ch_arr[ch_id] = test_ch;
2703
2704 test_ch->ch_id = ch_id;
2705
2706 memcpy(test_ch->name, name, CHANNEL_NAME_SIZE);
2707
2708 test_ch->buf_size = MAX_XFER_SIZE;
2709
2710 test_ch->buf = kzalloc(test_ch->buf_size, GFP_KERNEL);
2711 if (test_ch->buf == NULL) {
2712 kfree(test_ch);
2713 test_ctx->test_ch = NULL;
2714 return -ENOMEM;
2715 }
2716
2717 if (test_ch->ch_id == SDIO_SMEM) {
2718 test_ctx->smem_buf = kzalloc(SMEM_MAX_XFER_SIZE,
2719 GFP_KERNEL);
2720 if (test_ctx->smem_buf == NULL) {
2721 pr_err(TEST_MODULE_NAME ":%s: Unable to "
2722 "allocate smem buf\n",
2723 __func__);
2724 kfree(test_ch);
2725 test_ctx->test_ch = NULL;
2726 return -ENOMEM;
2727 }
2728
2729#ifdef CONFIG_MSM_SDIO_SMEM
2730 ret = platform_driver_register(&sdio_smem_drv);
2731 if (ret) {
2732 pr_err(TEST_MODULE_NAME ":%s: Unable to "
2733 "register sdio smem "
2734 "test client\n",
2735 __func__);
2736 return ret;
2737 }
2738#endif
2739 } else {
2740 test_ch->workqueue =
2741 create_singlethread_workqueue(test_ch->name);
2742 test_ch->test_work.test_ch = test_ch;
2743 INIT_WORK(&test_ch->test_work.work, worker);
2744
2745 init_waitqueue_head(&test_ch->wait_q);
2746 }
2747 } else {
2748 pr_err(TEST_MODULE_NAME ":trying to call test_channel_init "
2749 "twice for chan %d\n",
2750 ch_id);
2751 }
2752
2753 return 0;
2754}
2755
2756static struct class *test_class;
2757
2758const struct file_operations test_fops = {
2759 .owner = THIS_MODULE,
2760 .write = test_write,
2761};
2762
2763/**
2764 * Module Init.
2765 */
2766static int __init test_init(void)
2767{
2768 int ret;
2769
2770 pr_debug(TEST_MODULE_NAME ":test_init.\n");
2771
Yaniv Gardi3e327762011-07-27 11:11:04 +03002772 test_ctx = kzalloc(sizeof(struct test_context), GFP_KERNEL);
2773
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002774 if (test_ctx == NULL) {
2775 pr_err(TEST_MODULE_NAME ":kzalloc err.\n");
2776 return -ENOMEM;
2777 }
2778 test_ctx->test_ch = NULL;
2779 test_ctx->signature = TEST_SIGNATURE;
2780
2781 test_ctx->name = "UNKNOWN";
2782
2783 init_waitqueue_head(&test_ctx->wait_q);
2784
2785#ifdef CONFIG_DEBUG_FS
2786 sdio_al_test_debugfs_init();
2787#endif
2788
2789 test_class = class_create(THIS_MODULE, TEST_MODULE_NAME);
2790
2791 ret = alloc_chrdev_region(&test_ctx->dev_num, 0, 1, TEST_MODULE_NAME);
2792 if (ret) {
2793 pr_err(TEST_MODULE_NAME "alloc_chrdev_region err.\n");
2794 return -ENODEV;
2795 }
2796
2797 test_ctx->dev = device_create(test_class, NULL, test_ctx->dev_num,
2798 test_ctx, TEST_MODULE_NAME);
2799 if (IS_ERR(test_ctx->dev)) {
2800 pr_err(TEST_MODULE_NAME ":device_create err.\n");
2801 return -ENODEV;
2802 }
2803
2804 test_ctx->cdev = cdev_alloc();
2805 if (test_ctx->cdev == NULL) {
2806 pr_err(TEST_MODULE_NAME ":cdev_alloc err.\n");
2807 return -ENODEV;
2808 }
2809 cdev_init(test_ctx->cdev, &test_fops);
2810 test_ctx->cdev->owner = THIS_MODULE;
2811
2812 ret = cdev_add(test_ctx->cdev, test_ctx->dev_num, 1);
2813 if (ret)
2814 pr_err(TEST_MODULE_NAME ":cdev_add err=%d\n", -ret);
2815 else
2816 pr_debug(TEST_MODULE_NAME ":SDIO-AL-Test init OK..\n");
2817
2818 return ret;
2819}
2820
2821/**
2822 * Module Exit.
2823 */
2824static void __exit test_exit(void)
2825{
2826 int i;
2827
2828 pr_debug(TEST_MODULE_NAME ":test_exit.\n");
2829
2830 test_ctx->exit_flag = true;
2831
2832 msleep(100); /* allow gracefully exit of the worker thread */
2833
2834 cdev_del(test_ctx->cdev);
2835 device_destroy(test_class, test_ctx->dev_num);
2836 unregister_chrdev_region(test_ctx->dev_num, 1);
2837
2838 for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
2839 struct test_channel *tch = test_ctx->test_ch_arr[i];
2840 if (!tch)
2841 continue;
2842 kfree(tch->buf);
2843 kfree(tch);
2844 }
2845
2846#ifdef CONFIG_DEBUG_FS
2847 sdio_al_test_debugfs_cleanup();
2848#endif
2849
2850 kfree(test_ctx);
2851
2852 pr_debug(TEST_MODULE_NAME ":test_exit complete.\n");
2853}
2854
2855module_init(test_init);
2856module_exit(test_exit);
2857
2858MODULE_LICENSE("GPL v2");
2859MODULE_DESCRIPTION("SDIO_AL Test");
2860MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
2861
2862