blob: 4c255a4ba50f2f433ea8086e948c69776136dec8 [file] [log] [blame]
Eric Holmberg8ed30f22012-05-10 19:16:51 -06001/* drivers/tty/smux_test.c
2 *
3 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#include <linux/debugfs.h>
16#include <linux/list.h>
17#include <linux/ctype.h>
18#include <linux/jiffies.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/completion.h>
22#include <linux/termios.h>
23#include <linux/smux.h>
Eric Holmberg06011322012-07-06 18:17:03 -060024#include <mach/subsystem_restart.h>
Eric Holmberg8ed30f22012-05-10 19:16:51 -060025#include "smux_private.h"
26
27#define DEBUG_BUFMAX 4096
28
29/**
30 * Unit test assertion for logging test cases.
31 *
32 * @a lval
33 * @b rval
34 * @cmp comparison operator
35 *
36 * Assertion fails if (@a cmp @b) is not true which then
37 * logs the function and line number where the error occurred
38 * along with the values of @a and @b.
39 *
40 * Assumes that the following local variables exist:
41 * @buf - buffer to write failure message to
42 * @i - number of bytes written to buffer
43 * @max - maximum size of the buffer
44 * @failed - set to true if test fails
45 */
46#define UT_ASSERT_INT(a, cmp, b) \
Eric Holmberg527b66f2012-07-02 16:01:16 -060047 { \
48 int a_tmp = (a); \
49 int b_tmp = (b); \
50 if (!((a_tmp)cmp(b_tmp))) { \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060051 i += scnprintf(buf + i, max - i, \
52 "%s:%d Fail: " #a "(%d) " #cmp " " #b "(%d)\n", \
53 __func__, __LINE__, \
Eric Holmberg527b66f2012-07-02 16:01:16 -060054 a_tmp, b_tmp); \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060055 failed = 1; \
56 break; \
57 } \
Eric Holmberg527b66f2012-07-02 16:01:16 -060058 }
Eric Holmberg8ed30f22012-05-10 19:16:51 -060059
60#define UT_ASSERT_PTR(a, cmp, b) \
Eric Holmberg527b66f2012-07-02 16:01:16 -060061 { \
62 void *a_tmp = (a); \
63 void *b_tmp = (b); \
64 if (!((a_tmp)cmp(b_tmp))) { \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060065 i += scnprintf(buf + i, max - i, \
66 "%s:%d Fail: " #a "(%p) " #cmp " " #b "(%p)\n", \
67 __func__, __LINE__, \
Eric Holmberg527b66f2012-07-02 16:01:16 -060068 a_tmp, b_tmp); \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060069 failed = 1; \
70 break; \
71 } \
Eric Holmberg527b66f2012-07-02 16:01:16 -060072 }
Eric Holmberg8ed30f22012-05-10 19:16:51 -060073
74#define UT_ASSERT_UINT(a, cmp, b) \
Eric Holmberg527b66f2012-07-02 16:01:16 -060075 { \
76 unsigned a_tmp = (a); \
77 unsigned b_tmp = (b); \
78 if (!((a_tmp)cmp(b_tmp))) { \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060079 i += scnprintf(buf + i, max - i, \
80 "%s:%d Fail: " #a "(%u) " #cmp " " #b "(%u)\n", \
81 __func__, __LINE__, \
Eric Holmberg527b66f2012-07-02 16:01:16 -060082 a_tmp, b_tmp); \
Eric Holmberg8ed30f22012-05-10 19:16:51 -060083 failed = 1; \
84 break; \
85 } \
Eric Holmberg527b66f2012-07-02 16:01:16 -060086 }
Eric Holmberg8ed30f22012-05-10 19:16:51 -060087
Eric Holmbergb8435c82012-06-05 14:51:29 -060088/**
89 * In-range unit test assertion for test cases.
90 *
91 * @a lval
92 * @minv Minimum value
93 * @maxv Maximum value
94 *
95 * Assertion fails if @a is not on the exclusive range minv, maxv
96 * ((@a < @minv) or (@a > @maxv)). In the failure case, the macro
97 * logs the function and line number where the error occurred along
98 * with the values of @a and @minv, @maxv.
99 *
100 * Assumes that the following local variables exist:
101 * @buf - buffer to write failure message to
102 * @i - number of bytes written to buffer
103 * @max - maximum size of the buffer
104 * @failed - set to true if test fails
105 */
106#define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \
Eric Holmberg527b66f2012-07-02 16:01:16 -0600107 { \
108 int a_tmp = (a); \
109 int minv_tmp = (minv); \
110 int maxv_tmp = (maxv); \
111 if (((a_tmp) < (minv_tmp)) || ((a_tmp) > (maxv_tmp))) { \
Eric Holmbergb8435c82012-06-05 14:51:29 -0600112 i += scnprintf(buf + i, max - i, \
113 "%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \
114 #a "(%d) > " #maxv "(%d)\n", \
115 __func__, __LINE__, \
Eric Holmberg527b66f2012-07-02 16:01:16 -0600116 a_tmp, minv_tmp, a_tmp, maxv_tmp); \
Eric Holmbergb8435c82012-06-05 14:51:29 -0600117 failed = 1; \
118 break; \
119 } \
Eric Holmberg527b66f2012-07-02 16:01:16 -0600120 }
Eric Holmbergb8435c82012-06-05 14:51:29 -0600121
122
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600123static unsigned char test_array[] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55,
124 89, 144, 233};
125
Eric Holmbergb8435c82012-06-05 14:51:29 -0600126/* when 1, forces failure of get_rx_buffer_mock function */
127static int get_rx_buffer_mock_fail;
128
129
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600130/* Used for mapping local to remote TIOCM signals */
131struct tiocm_test_vector {
132 uint32_t input;
133 uint32_t set_old;
134 uint32_t set_new;
135 uint32_t clr_old;
136};
137
138/**
139 * Allocates a new buffer for SMUX for every call.
140 */
141int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
142{
143 void *rx_buf;
144
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600145 rx_buf = kmalloc(size, GFP_KERNEL);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600146 *pkt_priv = (void *)0x1234;
147 *buffer = rx_buf;
148
149 return 0;
150}
151
152/* Test vector for packet tests. */
153struct test_vector {
154 const char *data;
155 const unsigned len;
156};
157
158/* Mock object metadata for SMUX_READ_DONE event */
159struct mock_read_event {
160 struct list_head list;
161 struct smux_meta_read meta;
162};
163
164/* Mock object metadata for SMUX_WRITE_DONE event */
165struct mock_write_event {
166 struct list_head list;
167 struct smux_meta_write meta;
168};
169
Eric Holmbergb8435c82012-06-05 14:51:29 -0600170/* Mock object metadata for get_rx_buffer failure event */
171struct mock_get_rx_buff_event {
172 struct list_head list;
173 int size;
174 unsigned long jiffies;
175};
176
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600177/* Mock object for all SMUX callback events */
178struct smux_mock_callback {
179 int cb_count;
180 struct completion cb_completion;
181 spinlock_t lock;
182
183 /* status changes */
184 int event_connected;
185 int event_disconnected;
186 int event_disconnected_ssr;
187 int event_low_wm;
188 int event_high_wm;
Eric Holmberg2e0906f2012-06-26 13:29:14 -0600189 int event_rx_retry_high_wm;
190 int event_rx_retry_low_wm;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600191
192 /* TIOCM changes */
193 int event_tiocm;
194 struct smux_meta_tiocm tiocm_meta;
195
196 /* read event data */
197 int event_read_done;
198 int event_read_failed;
199 struct list_head read_events;
200
Eric Holmbergb8435c82012-06-05 14:51:29 -0600201 /* read retry data */
202 int get_rx_buff_retry_count;
203 struct list_head get_rx_buff_retry_events;
204
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600205 /* write event data */
206 int event_write_done;
207 int event_write_failed;
208 struct list_head write_events;
209};
210
Eric Holmberg06011322012-07-06 18:17:03 -0600211static int get_rx_buffer_mock(void *priv, void **pkt_priv,
212 void **buffer, int size);
213
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600214/**
215 * Initialize mock callback data. Only call once.
216 *
217 * @cb Mock callback data
218 */
219void mock_cb_data_init(struct smux_mock_callback *cb)
220{
221 init_completion(&cb->cb_completion);
222 spin_lock_init(&cb->lock);
223 INIT_LIST_HEAD(&cb->read_events);
Eric Holmbergb8435c82012-06-05 14:51:29 -0600224 INIT_LIST_HEAD(&cb->get_rx_buff_retry_events);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600225 INIT_LIST_HEAD(&cb->write_events);
226}
227
228/**
229 * Reset mock callback data to default values.
230 *
231 * @cb Mock callback data
232 *
233 * All packets are freed and counters reset to zero.
234 */
235void mock_cb_data_reset(struct smux_mock_callback *cb)
236{
237 cb->cb_count = 0;
238 INIT_COMPLETION(cb->cb_completion);
239 cb->event_connected = 0;
240 cb->event_disconnected = 0;
241 cb->event_disconnected_ssr = 0;
242 cb->event_low_wm = 0;
243 cb->event_high_wm = 0;
Eric Holmberg2e0906f2012-06-26 13:29:14 -0600244 cb->event_rx_retry_high_wm = 0;
245 cb->event_rx_retry_low_wm = 0;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600246 cb->event_tiocm = 0;
247 cb->tiocm_meta.tiocm_old = 0;
248 cb->tiocm_meta.tiocm_new = 0;
249
250 cb->event_read_done = 0;
251 cb->event_read_failed = 0;
252 while (!list_empty(&cb->read_events)) {
253 struct mock_read_event *meta;
254 meta = list_first_entry(&cb->read_events,
255 struct mock_read_event,
256 list);
257 kfree(meta->meta.buffer);
258 list_del(&meta->list);
259 kfree(meta);
260 }
261
Eric Holmbergb8435c82012-06-05 14:51:29 -0600262 cb->get_rx_buff_retry_count = 0;
263 while (!list_empty(&cb->get_rx_buff_retry_events)) {
264 struct mock_get_rx_buff_event *meta;
265 meta = list_first_entry(&cb->get_rx_buff_retry_events,
266 struct mock_get_rx_buff_event,
267 list);
268 list_del(&meta->list);
269 kfree(meta);
270 }
271
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600272 cb->event_write_done = 0;
273 cb->event_write_failed = 0;
274 while (!list_empty(&cb->write_events)) {
275 struct mock_write_event *meta;
276 meta = list_first_entry(&cb->write_events,
277 struct mock_write_event,
278 list);
279 list_del(&meta->list);
280 kfree(meta);
281 }
282}
283
284/**
285 * Dump the values of the mock callback data for debug purposes.
286 *
287 * @cb Mock callback data
288 * @buf Print buffer
289 * @max Maximum number of characters to print
290 *
291 * @returns Number of characters added to buffer
292 */
293static int mock_cb_data_print(const struct smux_mock_callback *cb,
294 char *buf, int max)
295{
296 int i = 0;
297
298 i += scnprintf(buf + i, max - i,
299 "\tcb_count=%d\n"
300 "\tcb_completion.done=%d\n"
301 "\tevent_connected=%d\n"
302 "\tevent_disconnected=%d\n"
303 "\tevent_disconnected_ssr=%d\n"
304 "\tevent_low_wm=%d\n"
305 "\tevent_high_wm=%d\n"
Eric Holmberg2e0906f2012-06-26 13:29:14 -0600306 "\tevent_rx_retry_high_wm=%d\n"
307 "\tevent_rx_retry_low_wm=%d\n"
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600308 "\tevent_tiocm=%d\n"
309 "\tevent_read_done=%d\n"
310 "\tevent_read_failed=%d\n"
Eric Holmberg88373642012-07-02 14:16:08 -0600311 "\tread_events empty=%d\n"
Eric Holmbergb8435c82012-06-05 14:51:29 -0600312 "\tget_rx_retry=%d\n"
Eric Holmberg88373642012-07-02 14:16:08 -0600313 "\tget_rx_retry_events empty=%d\n"
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600314 "\tevent_write_done=%d\n"
315 "\tevent_write_failed=%d\n"
Eric Holmberg88373642012-07-02 14:16:08 -0600316 "\twrite_events empty=%d\n",
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600317 cb->cb_count,
318 cb->cb_completion.done,
319 cb->event_connected,
320 cb->event_disconnected,
321 cb->event_disconnected_ssr,
322 cb->event_low_wm,
323 cb->event_high_wm,
Eric Holmberg2e0906f2012-06-26 13:29:14 -0600324 cb->event_rx_retry_high_wm,
325 cb->event_rx_retry_low_wm,
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600326 cb->event_tiocm,
327 cb->event_read_done,
328 cb->event_read_failed,
Eric Holmberg88373642012-07-02 14:16:08 -0600329 list_empty(&cb->read_events),
Eric Holmbergb8435c82012-06-05 14:51:29 -0600330 cb->get_rx_buff_retry_count,
Eric Holmberg88373642012-07-02 14:16:08 -0600331 list_empty(&cb->get_rx_buff_retry_events),
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600332 cb->event_write_done,
333 cb->event_write_failed,
334 list_empty(&cb->write_events)
335 );
336
337 return i;
338}
339
340/**
341 * Mock object event callback. Used to logs events for analysis in the unit
342 * tests.
343 */
344void smux_mock_cb(void *priv, int event, const void *metadata)
345{
346 struct smux_mock_callback *cb_data_ptr;
347 struct mock_write_event *write_event_meta;
348 struct mock_read_event *read_event_meta;
349 unsigned long flags;
350
351 cb_data_ptr = (struct smux_mock_callback *)priv;
352 if (cb_data_ptr == NULL) {
353 pr_err("%s: invalid private data\n", __func__);
354 return;
355 }
356
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600357 switch (event) {
358 case SMUX_CONNECTED:
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600359 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600360 ++cb_data_ptr->event_connected;
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600361 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600362 break;
363
364 case SMUX_DISCONNECTED:
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600365 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600366 ++cb_data_ptr->event_disconnected;
367 cb_data_ptr->event_disconnected_ssr =
368 ((struct smux_meta_disconnected *)metadata)->is_ssr;
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600369 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600370 break;
371
372 case SMUX_READ_DONE:
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600373 read_event_meta = kmalloc(sizeof(struct mock_read_event),
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600374 GFP_KERNEL);
375 spin_lock_irqsave(&cb_data_ptr->lock, flags);
376 ++cb_data_ptr->event_read_done;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600377 if (read_event_meta) {
378 read_event_meta->meta =
379 *(struct smux_meta_read *)metadata;
380 list_add_tail(&read_event_meta->list,
381 &cb_data_ptr->read_events);
382 }
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600383 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600384 break;
385
386 case SMUX_READ_FAIL:
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600387 read_event_meta = kmalloc(sizeof(struct mock_read_event),
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600388 GFP_KERNEL);
389 spin_lock_irqsave(&cb_data_ptr->lock, flags);
390 ++cb_data_ptr->event_read_failed;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600391 if (read_event_meta) {
Eric Holmbergb8435c82012-06-05 14:51:29 -0600392 if (metadata)
393 read_event_meta->meta =
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600394 *(struct smux_meta_read *)metadata;
Eric Holmbergb8435c82012-06-05 14:51:29 -0600395 else
396 memset(&read_event_meta->meta, 0x0,
397 sizeof(struct smux_meta_read));
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600398 list_add_tail(&read_event_meta->list,
399 &cb_data_ptr->read_events);
400 }
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600401 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600402 break;
403
404 case SMUX_WRITE_DONE:
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600405 write_event_meta = kmalloc(sizeof(struct mock_write_event),
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600406 GFP_KERNEL);
407 spin_lock_irqsave(&cb_data_ptr->lock, flags);
408 ++cb_data_ptr->event_write_done;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600409 if (write_event_meta) {
410 write_event_meta->meta =
411 *(struct smux_meta_write *)metadata;
412 list_add_tail(&write_event_meta->list,
413 &cb_data_ptr->write_events);
414 }
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600415 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600416 break;
417
418 case SMUX_WRITE_FAIL:
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600419 write_event_meta = kmalloc(sizeof(struct mock_write_event),
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600420 GFP_KERNEL);
421 spin_lock_irqsave(&cb_data_ptr->lock, flags);
422 ++cb_data_ptr->event_write_failed;
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600423 if (write_event_meta) {
424 write_event_meta->meta =
425 *(struct smux_meta_write *)metadata;
426 list_add_tail(&write_event_meta->list,
427 &cb_data_ptr->write_events);
428 }
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600429 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600430 break;
431
432 case SMUX_LOW_WM_HIT:
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600433 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600434 ++cb_data_ptr->event_low_wm;
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600435 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600436 break;
437
438 case SMUX_HIGH_WM_HIT:
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600439 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600440 ++cb_data_ptr->event_high_wm;
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600441 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600442 break;
443
Eric Holmberg2e0906f2012-06-26 13:29:14 -0600444 case SMUX_RX_RETRY_HIGH_WM_HIT:
445 spin_lock_irqsave(&cb_data_ptr->lock, flags);
446 ++cb_data_ptr->event_rx_retry_high_wm;
447 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
448 break;
449
450 case SMUX_RX_RETRY_LOW_WM_HIT:
451 spin_lock_irqsave(&cb_data_ptr->lock, flags);
452 ++cb_data_ptr->event_rx_retry_low_wm;
453 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
454 break;
455
456
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600457 case SMUX_TIOCM_UPDATE:
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600458 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600459 ++cb_data_ptr->event_tiocm;
460 cb_data_ptr->tiocm_meta = *(struct smux_meta_tiocm *)metadata;
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600461 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600462 break;
463
464 default:
465 pr_err("%s: unknown event %d\n", __func__, event);
466 };
467
Eric Holmberg0560f7a2012-05-31 15:50:26 -0600468 spin_lock_irqsave(&cb_data_ptr->lock, flags);
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600469 ++cb_data_ptr->cb_count;
470 complete(&cb_data_ptr->cb_completion);
471 spin_unlock_irqrestore(&cb_data_ptr->lock, flags);
472}
473
474/**
475 * Test Read/write usage.
476 *
477 * @buf Output buffer for failure/status messages
478 * @max Size of @buf
479 * @vectors Test vector data (must end with NULL item)
480 * @name Name of the test case for failure messages
481 *
482 * Perform a sanity test consisting of opening a port, writing test packet(s),
483 * reading the response(s), and closing the port.
484 *
485 * The port should already be configured to use either local or remote
486 * loopback.
487 */
488static int smux_ut_basic_core(char *buf, int max,
489 const struct test_vector *vectors,
490 const char *name)
491{
492 int i = 0;
493 int failed = 0;
494 static struct smux_mock_callback cb_data;
495 static int cb_initialized;
496 int ret;
497
498 if (!cb_initialized)
499 mock_cb_data_init(&cb_data);
500
501 mock_cb_data_reset(&cb_data);
502 while (!failed) {
503 struct mock_write_event *write_event;
504 struct mock_read_event *read_event;
505
506 /* open port */
507 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
508 get_rx_buffer);
509 UT_ASSERT_INT(ret, ==, 0);
510 UT_ASSERT_INT(
511 (int)wait_for_completion_timeout(
512 &cb_data.cb_completion, HZ), >, 0);
513 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
514 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
515 mock_cb_data_reset(&cb_data);
516
517 /* write, read, and verify the test vector data */
518 for (; vectors->data != NULL; ++vectors) {
519 const char *test_data = vectors->data;
520 const unsigned test_len = vectors->len;
521
522 i += scnprintf(buf + i, max - i,
523 "Writing vector %p len %d\n",
524 test_data, test_len);
525
526 /* write data */
527 msm_smux_write(SMUX_TEST_LCID, (void *)0xCAFEFACE,
528 test_data, test_len);
529 UT_ASSERT_INT(ret, ==, 0);
530 UT_ASSERT_INT(
531 (int)wait_for_completion_timeout(
532 &cb_data.cb_completion, HZ), >, 0);
533
534 /* wait for write and echo'd read to complete */
535 INIT_COMPLETION(cb_data.cb_completion);
536 if (cb_data.cb_count < 2)
537 UT_ASSERT_INT(
538 (int)wait_for_completion_timeout(
539 &cb_data.cb_completion, HZ),
540 >, 0);
541
542 UT_ASSERT_INT(cb_data.cb_count, >=, 1);
543 UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
544 UT_ASSERT_INT(list_empty(&cb_data.write_events), ==, 0);
545
546 write_event = list_first_entry(&cb_data.write_events,
547 struct mock_write_event, list);
548 UT_ASSERT_PTR(write_event->meta.pkt_priv, ==,
549 (void *)0xCAFEFACE);
550 UT_ASSERT_PTR(write_event->meta.buffer, ==,
551 (void *)test_data);
552 UT_ASSERT_INT(write_event->meta.len, ==, test_len);
553
554 /* verify read event */
555 UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
556 UT_ASSERT_INT(list_empty(&cb_data.read_events), ==, 0);
557 read_event = list_first_entry(&cb_data.read_events,
558 struct mock_read_event, list);
559 UT_ASSERT_PTR(read_event->meta.pkt_priv, ==,
560 (void *)0x1234);
561 UT_ASSERT_PTR(read_event->meta.buffer, !=, NULL);
562
563 if (read_event->meta.len != test_len ||
564 memcmp(read_event->meta.buffer,
565 test_data, test_len)) {
566 /* data mismatch */
567 char linebuff[80];
568
569 hex_dump_to_buffer(test_data, test_len,
570 16, 1, linebuff, sizeof(linebuff), 1);
571 i += scnprintf(buf + i, max - i,
572 "Expected:\n%s\n\n", linebuff);
573
574 hex_dump_to_buffer(read_event->meta.buffer,
575 read_event->meta.len,
576 16, 1, linebuff, sizeof(linebuff), 1);
577 i += scnprintf(buf + i, max - i,
578 "Actual:\n%s\n", linebuff);
579 failed = 1;
580 break;
581 }
582 mock_cb_data_reset(&cb_data);
583 }
584
585 /* close port */
586 ret = msm_smux_close(SMUX_TEST_LCID);
587 UT_ASSERT_INT(ret, ==, 0);
588 UT_ASSERT_INT(
589 (int)wait_for_completion_timeout(
590 &cb_data.cb_completion, HZ),
591 >, 0);
592 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
593 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
594 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
595 break;
596 }
597
598 if (!failed) {
599 i += scnprintf(buf + i, max - i, "\tOK\n");
600 } else {
601 pr_err("%s: Failed\n", name);
602 i += scnprintf(buf + i, max - i, "\tFailed\n");
603 i += mock_cb_data_print(&cb_data, buf + i, max - i);
604 msm_smux_close(SMUX_TEST_LCID);
605 }
606
607 mock_cb_data_reset(&cb_data);
608 return i;
609}
610
611/**
612 * Verify Basic Local Loopback Support
613 *
614 * Perform a sanity test consisting of opening a port in local loopback
615 * mode and writing a packet and reading the echo'd packet back.
616 */
617static int smux_ut_basic(char *buf, int max)
618{
619 const struct test_vector test_data[] = {
620 {"hello\0world\n", sizeof("hello\0world\n")},
621 {0, 0},
622 };
623 int i = 0;
624 int failed = 0;
625 int ret;
626
627 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
628 while (!failed) {
629 /* enable loopback mode */
630 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
631 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
632 UT_ASSERT_INT(ret, ==, 0);
633
634 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
635 break;
636 }
637
638 if (failed) {
639 pr_err("%s: Failed\n", __func__);
640 i += scnprintf(buf + i, max - i, "\tFailed\n");
641 }
642 return i;
643}
644
645/**
646 * Verify Basic Remote Loopback Support
647 *
648 * Perform a sanity test consisting of opening a port in remote loopback
649 * mode and writing a packet and reading the echo'd packet back.
650 */
651static int smux_ut_remote_basic(char *buf, int max)
652{
653 const struct test_vector test_data[] = {
654 {"hello\0world\n", sizeof("hello\0world\n")},
655 {0, 0},
656 };
657 int i = 0;
658 int failed = 0;
659 int ret;
660
661 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
662 while (!failed) {
663 /* enable remote mode */
664 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
665 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
666 UT_ASSERT_INT(ret, ==, 0);
667
668 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
669 break;
670 }
671
672 if (failed) {
673 pr_err("%s: Failed\n", __func__);
674 i += scnprintf(buf + i, max - i, "\tFailed\n");
675 }
676 return i;
677}
678
679/**
Eric Holmberg06011322012-07-06 18:17:03 -0600680 * Verify Basic Subsystem Restart Support
681 *
682 * Run a basic loopback test followed by a subsystem restart and then another
683 * loopback test.
684 */
685static int smux_ut_remote_ssr_basic(char *buf, int max)
686{
687 const struct test_vector test_data[] = {
688 {"hello\0world\n", sizeof("hello\0world\n")},
689 {0, 0},
690 };
691 int i = 0;
692 int failed = 0;
693 int ret;
694
695 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
696 while (!failed) {
697 /* enable remote mode */
698 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
699 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
700 UT_ASSERT_INT(ret, ==, 0);
701
702 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
703 subsystem_restart("external_modem");
704 msleep(5000);
705 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
706 break;
707 }
708
709 if (failed) {
710 pr_err("%s: Failed\n", __func__);
711 i += scnprintf(buf + i, max - i, "\tFailed\n");
712 }
713 return i;
714}
715
716/**
717 * Verify Subsystem Restart Support During Port Open
718 */
719static int smux_ut_remote_ssr_open(char *buf, int max)
720{
721 static struct smux_mock_callback cb_data;
722 static int cb_initialized;
723 int ret;
724 int i = 0;
725 int failed = 0;
726
727 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
728
729 if (!cb_initialized)
730 mock_cb_data_init(&cb_data);
731
732 mock_cb_data_reset(&cb_data);
733 while (!failed) {
734 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
735 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
736 UT_ASSERT_INT(ret, ==, 0);
737
738 /* open port */
739 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
740 get_rx_buffer);
741 UT_ASSERT_INT(ret, ==, 0);
742 UT_ASSERT_INT(
743 (int)wait_for_completion_timeout(
744 &cb_data.cb_completion, HZ), >, 0);
745 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
746 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
747 mock_cb_data_reset(&cb_data);
748
749 /* restart modem */
750 subsystem_restart("external_modem");
751
752 /* verify SSR events */
753 UT_ASSERT_INT(ret, ==, 0);
754 UT_ASSERT_INT(
755 (int)wait_for_completion_timeout(
756 &cb_data.cb_completion, 5*HZ),
757 >, 0);
758 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
759 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
760 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
761 mock_cb_data_reset(&cb_data);
762
763 /* close port */
764 ret = msm_smux_close(SMUX_TEST_LCID);
765 UT_ASSERT_INT(ret, ==, 0);
766 break;
767 }
768
769 if (!failed) {
770 i += scnprintf(buf + i, max - i, "\tOK\n");
771 } else {
772 pr_err("%s: Failed\n", __func__);
773 i += scnprintf(buf + i, max - i, "\tFailed\n");
774 i += mock_cb_data_print(&cb_data, buf + i, max - i);
775 msm_smux_close(SMUX_TEST_LCID);
776 }
777
778 mock_cb_data_reset(&cb_data);
779
780 return i;
781}
782
783/**
784 * Verify get_rx_buffer callback retry doesn't livelock SSR
785 * until all RX Bufffer Retries have timed out.
786 *
787 * @buf Buffer for status message
788 * @max Size of buffer
789 *
790 * @returns Number of bytes written to @buf
791 */
792static int smux_ut_remote_ssr_rx_buff_retry(char *buf, int max)
793{
794 static struct smux_mock_callback cb_data;
795 static int cb_initialized;
796 int i = 0;
797 int failed = 0;
798 int ret;
799
800 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
801 pr_err("%s", buf);
802
803 if (!cb_initialized)
804 mock_cb_data_init(&cb_data);
805
806 mock_cb_data_reset(&cb_data);
807 while (!failed) {
808 /* open port for loopback */
809 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
810 SMUX_CH_OPTION_REMOTE_LOOPBACK,
811 0);
812 UT_ASSERT_INT(ret, ==, 0);
813
814 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
815 smux_mock_cb, get_rx_buffer_mock);
816 UT_ASSERT_INT(ret, ==, 0);
817 UT_ASSERT_INT(
818 (int)wait_for_completion_timeout(
819 &cb_data.cb_completion, HZ), >, 0);
820 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
821 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
822 mock_cb_data_reset(&cb_data);
823
824 /* Queue up an RX buffer retry */
825 get_rx_buffer_mock_fail = 1;
826 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
827 test_array, sizeof(test_array));
828 UT_ASSERT_INT(ret, ==, 0);
829 while (!cb_data.get_rx_buff_retry_count) {
830 UT_ASSERT_INT(
831 (int)wait_for_completion_timeout(
832 &cb_data.cb_completion, HZ),
833 >, 0);
834 INIT_COMPLETION(cb_data.cb_completion);
835 }
836 if (failed)
837 break;
838 mock_cb_data_reset(&cb_data);
839
840 /* trigger SSR */
841 subsystem_restart("external_modem");
842
843 /* verify SSR completed */
844 UT_ASSERT_INT(ret, ==, 0);
845 UT_ASSERT_INT(
846 (int)wait_for_completion_timeout(
847 &cb_data.cb_completion, 5*HZ),
848 >, 0);
849 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
850 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
851 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
852 mock_cb_data_reset(&cb_data);
853
854 /* close port */
855 ret = msm_smux_close(SMUX_TEST_LCID);
856 UT_ASSERT_INT(ret, ==, 0);
857 break;
858 }
859
860 if (!failed) {
861 i += scnprintf(buf + i, max - i, "\tOK\n");
862 } else {
863 pr_err("%s: Failed\n", __func__);
864 i += scnprintf(buf + i, max - i, "\tFailed\n");
865 i += mock_cb_data_print(&cb_data, buf + i, max - i);
866 msm_smux_close(SMUX_TEST_LCID);
867 }
868 mock_cb_data_reset(&cb_data);
869 return i;
870}
871/**
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600872 * Fill test pattern into provided buffer including an optional
873 * redzone 16 bytes before and 16 bytes after the buffer.
874 *
875 * buf ---------
876 * redzone
877 * --------- <- returned pointer
878 * data
879 * --------- <- returned pointer + len
880 * redzone
881 * ---------
882 *
883 * @buf Pointer to the buffer of size len or len+32 (redzone)
884 * @len Length of the *data* buffer (excluding 32-byte redzone)
885 * @redzone If true, adds redzone data
886 *
887 * @returns pointer to buffer (buf + 16 if redzone enabled)
888 */
889uint8_t *test_pattern_fill(char *buf, int len, int redzone)
890{
891 void *ret;
892 uint8_t ch;
893
894 ret = buf;
895 if (redzone) {
896 memset((char *)buf, 0xAB, 16);
897 memset((char *)buf + len, 0xBA, 16);
898 ret += 16;
899 }
900
901 /* fill with test pattern */
902 for (ch = 0; len > 0; --len, ++ch)
903 *buf++ = (char)ch;
904
905 return ret;
906}
907
908/**
909 * Verify test pattern generated by test_pattern_fill.
910 *
911 * @buf_ptr Pointer to buffer pointer
912 * @len Length of the *data* buffer (excluding 32-byte redzone)
913 * @redzone If true, verifies redzone and adjusts *buf_ptr
914 * @errmsg Buffer for error message
915 * @errmsg_max Size of error message buffer
916 *
917 * @returns 0 for success; length of error message otherwise
918 */
919unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
920 char *errmsg, int errmsg_max)
921{
922 int n;
923 int i = 0;
924 char linebuff[80];
925
926 if (redzone) {
927 *buf_ptr -= 16;
928
929 /* verify prefix redzone */
930 for (n = 0; n < 16; ++n) {
931 if (*buf_ptr[n] != 0xAB) {
932 hex_dump_to_buffer(*buf_ptr, 16,
933 16, 1, linebuff, sizeof(linebuff), 1);
934 i += scnprintf(errmsg + i, errmsg_max - i,
935 "Redzone violation: %s\n", linebuff);
936 break;
937 }
938 }
939
940 /* verify postfix redzone */
941 for (n = 0; n < 16; ++n) {
942 if (*buf_ptr[len + n] != 0xBA) {
943 hex_dump_to_buffer(&(*buf_ptr)[len], 16,
944 16, 1, linebuff, sizeof(linebuff), 1);
945 i += scnprintf(errmsg + i, errmsg_max - i,
946 "Redzone violation: %s\n", linebuff);
947 break;
948 }
949 }
950 }
951 return i;
952}
953
954/**
955 * Write a multiple packets in ascending size and verify packet is received
956 * correctly.
957 *
958 * @buf Buffer for status message
959 * @max Size of buffer
960 * @name Name of the test for error reporting
961 *
962 * @returns Number of bytes written to @buf
963 *
964 * Requires that the port already be opened and loopback mode is
965 * configured correctly (if required).
966 */
967static int smux_ut_loopback_big_pkt(char *buf, int max, const char *name)
968{
969 struct test_vector test_data[] = {
970 {0, 64},
971 {0, 128},
972 {0, 256},
973 {0, 512},
974 {0, 1024},
975 {0, 2048},
976 {0, 4096},
977 {0, 0},
978 };
979 int i = 0;
980 int failed = 0;
981 struct test_vector *tv;
982
983 /* generate test data */
984 for (tv = test_data; tv->len > 0; ++tv) {
985 tv->data = kmalloc(tv->len + 32, GFP_KERNEL);
986 pr_err("%s: allocating %p len %d\n",
987 __func__, tv->data, tv->len);
988 if (!tv->data) {
989 i += scnprintf(buf + i, max - i,
990 "%s: Unable to allocate %d bytes\n",
991 __func__, tv->len);
992 failed = 1;
993 goto out;
994 }
995 test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
996 }
997
998 /* run test */
999 i += scnprintf(buf + i, max - i, "Running %s\n", name);
1000 while (!failed) {
1001 i += smux_ut_basic_core(buf + i, max - i, test_data, name);
1002 break;
1003 }
1004
1005out:
1006 if (failed) {
1007 pr_err("%s: Failed\n", name);
1008 i += scnprintf(buf + i, max - i, "\tFailed\n");
1009 }
1010
1011 for (tv = test_data; tv->len > 0; ++tv) {
1012 if (!tv->data) {
1013 i += test_pattern_verify((char **)&tv->data,
1014 tv->len, 1, buf + i, max - i);
1015 pr_err("%s: freeing %p len %d\n", __func__,
1016 tv->data, tv->len);
1017 kfree(tv->data);
1018 }
1019 }
1020
1021 return i;
1022}
1023
1024/**
1025 * Verify Large-packet Local Loopback Support.
1026 *
1027 * @buf Buffer for status message
1028 * @max Size of buffer
1029 *
1030 * @returns Number of bytes written to @buf
1031 *
1032 * Open port in local loopback mode and write a multiple packets in ascending
1033 * size and verify packet is received correctly.
1034 */
1035static int smux_ut_local_big_pkt(char *buf, int max)
1036{
1037 int i = 0;
1038 int ret;
1039
1040 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1041 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
1042
1043 if (ret == 0) {
1044 smux_byte_loopback = SMUX_TEST_LCID;
1045 i += smux_ut_loopback_big_pkt(buf, max, __func__);
1046 smux_byte_loopback = 0;
1047 } else {
1048 i += scnprintf(buf + i, max - i,
1049 "%s: Unable to set loopback mode\n",
1050 __func__);
1051 }
1052
1053 return i;
1054}
1055
1056/**
1057 * Verify Large-packet Remote Loopback Support.
1058 *
1059 * @buf Buffer for status message
1060 * @max Size of buffer
1061 *
1062 * @returns Number of bytes written to @buf
1063 *
1064 * Open port in remote loopback mode and write a multiple packets in ascending
1065 * size and verify packet is received correctly.
1066 */
1067static int smux_ut_remote_big_pkt(char *buf, int max)
1068{
1069 int i = 0;
1070 int ret;
1071
1072 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1073 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
1074 if (ret == 0) {
1075 i += smux_ut_loopback_big_pkt(buf, max, __func__);
1076 } else {
1077 i += scnprintf(buf + i, max - i,
1078 "%s: Unable to set loopback mode\n",
1079 __func__);
1080 }
1081
1082 return i;
1083}
1084
1085/**
1086 * Verify set and get operations for each TIOCM bit.
1087 *
1088 * @buf Buffer for status message
1089 * @max Size of buffer
1090 * @name Name of the test for error reporting
1091 *
1092 * @returns Number of bytes written to @buf
1093 */
1094static int smux_ut_tiocm(char *buf, int max, const char *name)
1095{
1096 static struct smux_mock_callback cb_data;
1097 static int cb_initialized;
1098 static const struct tiocm_test_vector tiocm_vectors[] = {
1099 /* bit to set, set old, set new, clear old */
1100 {TIOCM_DTR, TIOCM_DTR, TIOCM_DTR | TIOCM_DSR, TIOCM_DSR},
1101 {TIOCM_RTS, TIOCM_RTS, TIOCM_RTS | TIOCM_CTS, TIOCM_CTS},
1102 {TIOCM_RI, 0x0, TIOCM_RI, TIOCM_RI},
1103 {TIOCM_CD, 0x0, TIOCM_CD, TIOCM_CD},
1104 };
1105 int i = 0;
1106 int failed = 0;
1107 int n;
1108 int ret;
1109
1110 i += scnprintf(buf + i, max - i, "Running %s\n", name);
1111
1112 if (!cb_initialized)
1113 mock_cb_data_init(&cb_data);
1114
1115 mock_cb_data_reset(&cb_data);
1116 while (!failed) {
1117 /* open port */
1118 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1119 get_rx_buffer);
1120 UT_ASSERT_INT(ret, ==, 0);
1121 UT_ASSERT_INT(
1122 (int)wait_for_completion_timeout(
1123 &cb_data.cb_completion, HZ), >, 0);
1124 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1125 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1126 mock_cb_data_reset(&cb_data);
1127
1128 /* set and clear each TIOCM bit */
1129 for (n = 0; n < ARRAY_SIZE(tiocm_vectors) && !failed; ++n) {
1130 /* set signal and verify */
1131 ret = msm_smux_tiocm_set(SMUX_TEST_LCID,
1132 tiocm_vectors[n].input, 0x0);
1133 UT_ASSERT_INT(ret, ==, 0);
1134 UT_ASSERT_INT(
1135 (int)wait_for_completion_timeout(
1136 &cb_data.cb_completion, HZ), >, 0);
1137 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1138 UT_ASSERT_INT(cb_data.event_tiocm, ==, 1);
1139 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_old, ==,
1140 tiocm_vectors[n].set_old);
1141 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_new, ==,
1142 tiocm_vectors[n].set_new);
1143 mock_cb_data_reset(&cb_data);
1144
1145 /* clear signal and verify */
1146 ret = msm_smux_tiocm_set(SMUX_TEST_LCID, 0x0,
1147 tiocm_vectors[n].input);
1148 UT_ASSERT_INT(ret, ==, 0);
1149 UT_ASSERT_INT(
1150 (int)wait_for_completion_timeout(
1151 &cb_data.cb_completion, HZ),
1152 >, 0);
1153 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1154 UT_ASSERT_INT(cb_data.event_tiocm, ==, 1);
1155 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_old, ==,
1156 tiocm_vectors[n].clr_old);
1157 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_new, ==, 0x0);
1158 mock_cb_data_reset(&cb_data);
1159 }
1160 if (failed)
1161 break;
1162
1163 /* close port */
1164 ret = msm_smux_close(SMUX_TEST_LCID);
1165 UT_ASSERT_INT(ret, ==, 0);
1166 UT_ASSERT_INT(
1167 (int)wait_for_completion_timeout(
1168 &cb_data.cb_completion, HZ),
1169 >, 0);
1170 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1171 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1172 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1173 break;
1174 }
1175
1176 if (!failed) {
1177 i += scnprintf(buf + i, max - i, "\tOK\n");
1178 } else {
1179 pr_err("%s: Failed\n", name);
1180 i += scnprintf(buf + i, max - i, "\tFailed\n");
1181 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1182 msm_smux_close(SMUX_TEST_LCID);
1183 }
1184
1185 mock_cb_data_reset(&cb_data);
1186 return i;
1187}
1188
1189/**
1190 * Verify TIOCM Status Bits for local loopback.
1191 *
1192 * @buf Buffer for status message
1193 * @max Size of buffer
1194 *
1195 * @returns Number of bytes written to @buf
1196 */
1197static int smux_ut_local_tiocm(char *buf, int max)
1198{
1199 int i = 0;
1200 int ret;
1201
1202 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1203 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
1204
1205 if (ret == 0) {
1206 smux_byte_loopback = SMUX_TEST_LCID;
1207 i += smux_ut_tiocm(buf, max, __func__);
1208 smux_byte_loopback = 0;
1209 } else {
1210 i += scnprintf(buf + i, max - i,
1211 "%s: Unable to set loopback mode\n",
1212 __func__);
1213 }
1214
1215 return i;
1216}
1217
1218/**
1219 * Verify TIOCM Status Bits for remote loopback.
1220 *
1221 * @buf Buffer for status message
1222 * @max Size of buffer
1223 *
1224 * @returns Number of bytes written to @buf
1225 */
1226static int smux_ut_remote_tiocm(char *buf, int max)
1227{
1228 int i = 0;
1229 int ret;
1230
1231 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1232 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
1233 if (ret == 0) {
1234 i += smux_ut_tiocm(buf, max, __func__);
1235 } else {
1236 i += scnprintf(buf + i, max - i,
1237 "%s: Unable to set loopback mode\n",
1238 __func__);
1239 }
1240
1241 return i;
1242}
1243
1244/**
1245 * Verify High/Low Watermark notifications.
1246 *
1247 * @buf Buffer for status message
1248 * @max Size of buffer
1249 *
1250 * @returns Number of bytes written to @buf
1251 */
1252static int smux_ut_local_wm(char *buf, int max)
1253{
1254 static struct smux_mock_callback cb_data;
1255 static int cb_initialized;
1256 int i = 0;
1257 int failed = 0;
1258 int ret;
1259
1260 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1261 pr_err("%s", buf);
1262
1263 if (!cb_initialized)
1264 mock_cb_data_init(&cb_data);
1265
1266 mock_cb_data_reset(&cb_data);
1267 smux_byte_loopback = SMUX_TEST_LCID;
1268 while (!failed) {
1269 /* open port for loopback with TX disabled */
1270 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1271 SMUX_CH_OPTION_LOCAL_LOOPBACK
1272 | SMUX_CH_OPTION_REMOTE_TX_STOP,
1273 0);
1274 UT_ASSERT_INT(ret, ==, 0);
1275
1276 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1277 get_rx_buffer);
1278 UT_ASSERT_INT(ret, ==, 0);
1279 UT_ASSERT_INT(
1280 (int)wait_for_completion_timeout(
1281 &cb_data.cb_completion, HZ), >, 0);
1282 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1283 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1284 mock_cb_data_reset(&cb_data);
1285
1286 /* transmit 4 packets and verify high-watermark notification */
1287 ret = 0;
1288 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)1,
1289 test_array, sizeof(test_array));
1290 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)2,
1291 test_array, sizeof(test_array));
1292 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)3,
1293 test_array, sizeof(test_array));
1294 UT_ASSERT_INT(ret, ==, 0);
1295 UT_ASSERT_INT(cb_data.cb_count, ==, 0);
1296 UT_ASSERT_INT(cb_data.event_high_wm, ==, 0);
1297
1298 ret = msm_smux_write(SMUX_TEST_LCID, (void *)4,
1299 test_array, sizeof(test_array));
1300 UT_ASSERT_INT(ret, ==, 0);
1301 UT_ASSERT_INT(
1302 (int)wait_for_completion_timeout(
1303 &cb_data.cb_completion, HZ),
1304 >, 0);
1305 UT_ASSERT_INT(cb_data.event_high_wm, ==, 1);
1306 UT_ASSERT_INT(cb_data.event_low_wm, ==, 0);
1307 mock_cb_data_reset(&cb_data);
1308
1309 /* exceed watermark and verify failure return value */
1310 ret = msm_smux_write(SMUX_TEST_LCID, (void *)5,
1311 test_array, sizeof(test_array));
1312 UT_ASSERT_INT(ret, ==, -EAGAIN);
1313
1314 /* re-enable TX and verify low-watermark notification */
1315 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1316 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
1317 UT_ASSERT_INT(ret, ==, 0);
1318 while (cb_data.cb_count < 9) {
1319 UT_ASSERT_INT(
1320 (int)wait_for_completion_timeout(
1321 &cb_data.cb_completion, HZ),
1322 >, 0);
1323 INIT_COMPLETION(cb_data.cb_completion);
1324 }
1325 if (failed)
1326 break;
1327
1328 UT_ASSERT_INT(cb_data.event_high_wm, ==, 0);
1329 UT_ASSERT_INT(cb_data.event_low_wm, ==, 1);
1330 UT_ASSERT_INT(cb_data.event_write_done, ==, 4);
1331 mock_cb_data_reset(&cb_data);
1332
1333 /* close port */
1334 ret = msm_smux_close(SMUX_TEST_LCID);
1335 UT_ASSERT_INT(ret, ==, 0);
1336 UT_ASSERT_INT(
1337 (int)wait_for_completion_timeout(
1338 &cb_data.cb_completion, HZ),
1339 >, 0);
1340 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1341 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1342 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1343 break;
1344 }
1345
1346 if (!failed) {
1347 i += scnprintf(buf + i, max - i, "\tOK\n");
1348 } else {
1349 pr_err("%s: Failed\n", __func__);
1350 i += scnprintf(buf + i, max - i, "\tFailed\n");
1351 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1352 msm_smux_close(SMUX_TEST_LCID);
1353 }
1354 smux_byte_loopback = 0;
1355 mock_cb_data_reset(&cb_data);
1356 return i;
1357}
1358
1359/**
1360 * Verify smuxld_receive_buf regular and error processing.
1361 *
1362 * @buf Buffer for status message
1363 * @max Size of buffer
1364 *
1365 * @returns Number of bytes written to @buf
1366 */
1367static int smux_ut_local_smuxld_receive_buf(char *buf, int max)
1368{
1369 static struct smux_mock_callback cb_data;
1370 static int cb_initialized;
1371 struct mock_read_event *meta;
1372 int i = 0;
1373 int failed = 0;
1374 int ret;
1375 char data[] = {SMUX_UT_ECHO_REQ,
1376 SMUX_UT_ECHO_REQ, SMUX_UT_ECHO_REQ,
1377 };
1378 char flags[] = {0x0, 0x1, 0x0,};
1379
1380
1381 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1382
1383 if (!cb_initialized)
1384 mock_cb_data_init(&cb_data);
1385
1386 mock_cb_data_reset(&cb_data);
1387 smux_byte_loopback = SMUX_TEST_LCID;
1388 while (!failed) {
1389 /* open port for loopback */
1390 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1391 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
1392 UT_ASSERT_INT(ret, ==, 0);
1393
1394 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1395 get_rx_buffer);
1396 UT_ASSERT_INT(ret, ==, 0);
1397 UT_ASSERT_INT(
1398 (int)wait_for_completion_timeout(
1399 &cb_data.cb_completion, HZ), >, 0);
1400 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1401 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1402 mock_cb_data_reset(&cb_data);
1403
1404 /*
1405 * Verify RX error processing by sending 3 echo requests:
1406 * one OK, one fail, and a final OK
1407 *
1408 * The parsing framework should process the requests
1409 * and send us three BYTE command packets with
1410 * ECHO ACK FAIL and ECHO ACK OK characters.
1411 */
1412 smuxld_receive_buf(0, data, flags, sizeof(data));
1413
1414 /* verify response characters */
1415 do {
1416 UT_ASSERT_INT(
1417 (int)wait_for_completion_timeout(
1418 &cb_data.cb_completion, HZ), >, 0);
1419 INIT_COMPLETION(cb_data.cb_completion);
1420 } while (cb_data.cb_count < 3);
1421 UT_ASSERT_INT(cb_data.cb_count, ==, 3);
1422 UT_ASSERT_INT(cb_data.event_read_done, ==, 3);
1423
1424 meta = list_first_entry(&cb_data.read_events,
1425 struct mock_read_event, list);
1426 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1427 SMUX_UT_ECHO_ACK_OK);
1428 list_del(&meta->list);
1429
1430 meta = list_first_entry(&cb_data.read_events,
1431 struct mock_read_event, list);
1432 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1433 SMUX_UT_ECHO_ACK_FAIL);
1434 list_del(&meta->list);
1435
1436 meta = list_first_entry(&cb_data.read_events,
1437 struct mock_read_event, list);
1438 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1439 SMUX_UT_ECHO_ACK_OK);
1440 list_del(&meta->list);
1441 mock_cb_data_reset(&cb_data);
1442
1443 /* close port */
1444 ret = msm_smux_close(SMUX_TEST_LCID);
1445 UT_ASSERT_INT(ret, ==, 0);
1446 UT_ASSERT_INT(
1447 (int)wait_for_completion_timeout(
1448 &cb_data.cb_completion, HZ),
1449 >, 0);
1450 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1451 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1452 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1453 break;
1454 }
1455
1456 if (!failed) {
1457 i += scnprintf(buf + i, max - i, "\tOK\n");
1458 } else {
1459 pr_err("%s: Failed\n", __func__);
1460 i += scnprintf(buf + i, max - i, "\tFailed\n");
1461 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1462 msm_smux_close(SMUX_TEST_LCID);
1463 }
1464 smux_byte_loopback = 0;
1465 mock_cb_data_reset(&cb_data);
1466 return i;
1467}
1468
Eric Holmbergb8435c82012-06-05 14:51:29 -06001469/**
1470 * Allocates a new buffer or returns a failure based upon the
1471 * global @get_rx_buffer_mock_fail.
1472 */
1473static int get_rx_buffer_mock(void *priv, void **pkt_priv,
1474 void **buffer, int size)
1475{
1476 void *rx_buf;
1477 unsigned long flags;
1478 struct smux_mock_callback *cb_ptr;
1479
1480 cb_ptr = (struct smux_mock_callback *)priv;
1481 if (!cb_ptr) {
1482 pr_err("%s: no callback data\n", __func__);
1483 return -ENXIO;
1484 }
1485
1486 if (get_rx_buffer_mock_fail) {
1487 /* force failure and log failure event */
1488 struct mock_get_rx_buff_event *meta;
1489 meta = kmalloc(sizeof(struct mock_get_rx_buff_event),
1490 GFP_KERNEL);
1491 if (!meta) {
1492 pr_err("%s: unable to allocate metadata\n", __func__);
1493 return -ENOMEM;
1494 }
1495 INIT_LIST_HEAD(&meta->list);
1496 meta->size = size;
1497 meta->jiffies = jiffies;
1498
1499 spin_lock_irqsave(&cb_ptr->lock, flags);
1500 ++cb_ptr->get_rx_buff_retry_count;
1501 list_add_tail(&meta->list, &cb_ptr->get_rx_buff_retry_events);
1502 ++cb_ptr->cb_count;
1503 complete(&cb_ptr->cb_completion);
1504 spin_unlock_irqrestore(&cb_ptr->lock, flags);
1505 return -EAGAIN;
1506 } else {
1507 rx_buf = kmalloc(size, GFP_KERNEL);
1508 *pkt_priv = (void *)0x1234;
1509 *buffer = rx_buf;
1510 return 0;
1511 }
1512 return 0;
1513}
1514
1515/**
1516 * Verify get_rx_buffer callback retry.
1517 *
1518 * @buf Buffer for status message
1519 * @max Size of buffer
1520 *
1521 * @returns Number of bytes written to @buf
1522 */
1523static int smux_ut_local_get_rx_buff_retry(char *buf, int max)
1524{
1525 static struct smux_mock_callback cb_data;
1526 static int cb_initialized;
1527 int i = 0;
1528 int failed = 0;
1529 char try_two[] = "try 2";
1530 int ret;
1531 unsigned long start_j;
1532 struct mock_get_rx_buff_event *event;
1533 struct mock_read_event *read_event;
1534 int try;
1535
1536 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1537 pr_err("%s", buf);
1538
1539 if (!cb_initialized)
1540 mock_cb_data_init(&cb_data);
1541
1542 mock_cb_data_reset(&cb_data);
1543 smux_byte_loopback = SMUX_TEST_LCID;
1544 while (!failed) {
1545 /* open port for loopback */
1546 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1547 SMUX_CH_OPTION_LOCAL_LOOPBACK,
Eric Holmberg2e0906f2012-06-26 13:29:14 -06001548 SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP);
Eric Holmbergb8435c82012-06-05 14:51:29 -06001549 UT_ASSERT_INT(ret, ==, 0);
1550
1551 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
1552 smux_mock_cb, get_rx_buffer_mock);
1553 UT_ASSERT_INT(ret, ==, 0);
1554 UT_ASSERT_INT(
1555 (int)wait_for_completion_timeout(
1556 &cb_data.cb_completion, HZ), >, 0);
1557 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1558 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1559 mock_cb_data_reset(&cb_data);
1560
1561 /*
1562 * Force get_rx_buffer failure for a single RX packet
1563 *
1564 * The get_rx_buffer calls should follow an exponential
1565 * back-off with a maximum timeout of 1024 ms after which we
1566 * will get a failure notification.
1567 *
1568 * Try Post Delay (ms)
1569 * 0 -
1570 * 1 1
1571 * 2 2
1572 * 3 4
1573 * 4 8
1574 * 5 16
1575 * 6 32
1576 * 7 64
1577 * 8 128
1578 * 9 256
1579 * 10 512
1580 * 11 1024
1581 * 12 Fail
1582 *
1583 * All times are limited by the precision of the timer
1584 * framework, so ranges are used in the test
1585 * verification.
1586 */
1587 get_rx_buffer_mock_fail = 1;
1588 start_j = jiffies;
1589 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1590 test_array, sizeof(test_array));
1591 UT_ASSERT_INT(ret, ==, 0);
1592 ret = msm_smux_write(SMUX_TEST_LCID, (void *)2,
1593 try_two, sizeof(try_two));
1594 UT_ASSERT_INT(ret, ==, 0);
1595
1596 /* wait for RX failure event */
1597 while (cb_data.event_read_failed == 0) {
1598 UT_ASSERT_INT(
1599 (int)wait_for_completion_timeout(
1600 &cb_data.cb_completion, 2*HZ),
1601 >, 0);
1602 INIT_COMPLETION(cb_data.cb_completion);
1603 }
1604 if (failed)
1605 break;
1606
1607 /* verify retry attempts */
1608 UT_ASSERT_INT(cb_data.get_rx_buff_retry_count, ==, 12);
1609 event = list_first_entry(&cb_data.get_rx_buff_retry_events,
1610 struct mock_get_rx_buff_event, list);
1611 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1612 jiffies_to_msecs(event->jiffies - start_j));
1613 UT_ASSERT_INT_IN_RANGE(
1614 jiffies_to_msecs(event->jiffies - start_j),
1615 0, 0 + 20);
1616 start_j = event->jiffies;
1617
1618 event = list_first_entry(&event->list,
1619 struct mock_get_rx_buff_event, list);
1620 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1621 jiffies_to_msecs(event->jiffies - start_j));
1622 UT_ASSERT_INT_IN_RANGE(
1623 jiffies_to_msecs(event->jiffies - start_j),
1624 1, 1 + 20);
1625 start_j = event->jiffies;
1626
1627 event = list_first_entry(&event->list,
1628 struct mock_get_rx_buff_event, list);
1629 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1630 jiffies_to_msecs(event->jiffies - start_j));
1631 UT_ASSERT_INT_IN_RANGE(
1632 jiffies_to_msecs(event->jiffies - start_j),
1633 2, 2 + 20);
1634 start_j = event->jiffies;
1635
1636 event = list_first_entry(&event->list,
1637 struct mock_get_rx_buff_event, list);
1638 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1639 jiffies_to_msecs(event->jiffies - start_j));
1640 UT_ASSERT_INT_IN_RANGE(
1641 jiffies_to_msecs(event->jiffies - start_j),
1642 4, 4 + 20);
1643 start_j = event->jiffies;
1644
1645 event = list_first_entry(&event->list,
1646 struct mock_get_rx_buff_event, list);
1647 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1648 jiffies_to_msecs(event->jiffies - start_j));
1649 UT_ASSERT_INT_IN_RANGE(
1650 jiffies_to_msecs(event->jiffies - start_j),
1651 8, 8 + 20);
1652 start_j = event->jiffies;
1653
1654 event = list_first_entry(&event->list,
1655 struct mock_get_rx_buff_event, list);
1656 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1657 jiffies_to_msecs(event->jiffies - start_j));
1658 UT_ASSERT_INT_IN_RANGE(
1659 jiffies_to_msecs(event->jiffies - start_j),
1660 16, 16 + 20);
1661 start_j = event->jiffies;
1662
1663 event = list_first_entry(&event->list,
1664 struct mock_get_rx_buff_event, list);
1665 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1666 jiffies_to_msecs(event->jiffies - start_j));
1667 UT_ASSERT_INT_IN_RANGE(
1668 jiffies_to_msecs(event->jiffies - start_j),
1669 32 - 20, 32 + 20);
1670 start_j = event->jiffies;
1671
1672 event = list_first_entry(&event->list,
1673 struct mock_get_rx_buff_event, list);
1674 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1675 jiffies_to_msecs(event->jiffies - start_j));
1676 UT_ASSERT_INT_IN_RANGE(
1677 jiffies_to_msecs(event->jiffies - start_j),
1678 64 - 20, 64 + 20);
1679 start_j = event->jiffies;
1680
1681 event = list_first_entry(&event->list,
1682 struct mock_get_rx_buff_event, list);
1683 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1684 jiffies_to_msecs(event->jiffies - start_j));
1685 UT_ASSERT_INT_IN_RANGE(
1686 jiffies_to_msecs(event->jiffies - start_j),
1687 128 - 20, 128 + 20);
1688 start_j = event->jiffies;
1689
1690 event = list_first_entry(&event->list,
1691 struct mock_get_rx_buff_event, list);
1692 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1693 jiffies_to_msecs(event->jiffies - start_j));
1694 UT_ASSERT_INT_IN_RANGE(
1695 jiffies_to_msecs(event->jiffies - start_j),
1696 256 - 20, 256 + 20);
1697 start_j = event->jiffies;
1698
1699 event = list_first_entry(&event->list,
1700 struct mock_get_rx_buff_event, list);
1701 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1702 jiffies_to_msecs(event->jiffies - start_j));
1703 UT_ASSERT_INT_IN_RANGE(
1704 jiffies_to_msecs(event->jiffies - start_j),
1705 512 - 20, 512 + 20);
1706 start_j = event->jiffies;
1707
1708 event = list_first_entry(&event->list,
1709 struct mock_get_rx_buff_event, list);
1710 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1711 jiffies_to_msecs(event->jiffies - start_j));
1712 UT_ASSERT_INT_IN_RANGE(
1713 jiffies_to_msecs(event->jiffies - start_j),
1714 1024 - 20, 1024 + 20);
1715 mock_cb_data_reset(&cb_data);
1716
1717 /* verify 2nd pending RX packet goes through */
1718 get_rx_buffer_mock_fail = 0;
1719 INIT_COMPLETION(cb_data.cb_completion);
1720 if (cb_data.event_read_done == 0)
1721 UT_ASSERT_INT(
1722 (int)wait_for_completion_timeout(
1723 &cb_data.cb_completion, HZ),
1724 >, 0);
1725 UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
1726 UT_ASSERT_INT(list_empty(&cb_data.read_events), ==, 0);
1727 read_event = list_first_entry(&cb_data.read_events,
1728 struct mock_read_event, list);
1729 UT_ASSERT_PTR(read_event->meta.pkt_priv, ==, (void *)0x1234);
1730 UT_ASSERT_PTR(read_event->meta.buffer, !=, NULL);
1731 UT_ASSERT_INT(0, ==, memcmp(read_event->meta.buffer, try_two,
1732 sizeof(try_two)));
1733 mock_cb_data_reset(&cb_data);
1734
1735 /* Test maximum retry queue size */
1736 get_rx_buffer_mock_fail = 1;
1737 for (try = 0; try < (SMUX_RX_RETRY_MAX_PKTS + 1); ++try) {
1738 mock_cb_data_reset(&cb_data);
1739 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1740 test_array, sizeof(test_array));
1741 UT_ASSERT_INT(ret, ==, 0);
1742 UT_ASSERT_INT(
1743 (int)wait_for_completion_timeout(
1744 &cb_data.cb_completion, HZ),
1745 >, 0);
1746 }
1747
1748 /* should have 32 successful rx packets and 1 failed */
1749 while (cb_data.event_read_failed == 0) {
1750 UT_ASSERT_INT(
1751 (int)wait_for_completion_timeout(
1752 &cb_data.cb_completion, 2*HZ),
1753 >, 0);
1754 INIT_COMPLETION(cb_data.cb_completion);
1755 }
1756 if (failed)
1757 break;
1758
1759 get_rx_buffer_mock_fail = 0;
1760 while (cb_data.event_read_done < SMUX_RX_RETRY_MAX_PKTS) {
1761 UT_ASSERT_INT(
1762 (int)wait_for_completion_timeout(
1763 &cb_data.cb_completion, 2*HZ),
1764 >, 0);
1765 INIT_COMPLETION(cb_data.cb_completion);
1766 }
1767 if (failed)
1768 break;
1769
1770 UT_ASSERT_INT(1, ==, cb_data.event_read_failed);
1771 UT_ASSERT_INT(SMUX_RX_RETRY_MAX_PKTS, ==,
1772 cb_data.event_read_done);
1773 mock_cb_data_reset(&cb_data);
1774
1775 /* close port */
1776 ret = msm_smux_close(SMUX_TEST_LCID);
1777 UT_ASSERT_INT(ret, ==, 0);
1778 UT_ASSERT_INT(
1779 (int)wait_for_completion_timeout(
1780 &cb_data.cb_completion, HZ),
1781 >, 0);
1782 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1783 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1784 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1785 break;
1786 }
1787
1788 if (!failed) {
1789 i += scnprintf(buf + i, max - i, "\tOK\n");
1790 } else {
1791 pr_err("%s: Failed\n", __func__);
1792 i += scnprintf(buf + i, max - i, "\tFailed\n");
1793 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1794 msm_smux_close(SMUX_TEST_LCID);
1795 }
1796 smux_byte_loopback = 0;
1797 mock_cb_data_reset(&cb_data);
1798 return i;
1799}
1800
Eric Holmberg2e0906f2012-06-26 13:29:14 -06001801/**
1802 * Verify get_rx_buffer callback retry for auto-rx flow control.
1803 *
1804 * @buf Buffer for status message
1805 * @max Size of buffer
1806 *
1807 * @returns Number of bytes written to @buf
1808 */
1809static int smux_ut_local_get_rx_buff_retry_auto(char *buf, int max)
1810{
1811 static struct smux_mock_callback cb_data;
1812 static int cb_initialized;
1813 int i = 0;
1814 int failed = 0;
1815 int ret;
1816 int try;
1817 int try_rx_retry_wm;
1818
1819 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1820 pr_err("%s", buf);
1821
1822 if (!cb_initialized)
1823 mock_cb_data_init(&cb_data);
1824
1825 mock_cb_data_reset(&cb_data);
1826 smux_byte_loopback = SMUX_TEST_LCID;
1827 while (!failed) {
1828 /* open port for loopback */
1829 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1830 SMUX_CH_OPTION_LOCAL_LOOPBACK
1831 | SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP,
1832 0);
1833 UT_ASSERT_INT(ret, ==, 0);
1834
1835 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
1836 smux_mock_cb, get_rx_buffer_mock);
1837 UT_ASSERT_INT(ret, ==, 0);
1838 UT_ASSERT_INT(
1839 (int)wait_for_completion_timeout(
1840 &cb_data.cb_completion, HZ), >, 0);
1841 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1842 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1843 mock_cb_data_reset(&cb_data);
1844
1845 /* Test high rx-retry watermark */
1846 get_rx_buffer_mock_fail = 1;
1847 try_rx_retry_wm = 0;
1848 for (try = 0; try < SMUX_RX_RETRY_MAX_PKTS; ++try) {
1849 pr_err("%s: try %d\n", __func__, try);
1850 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1851 test_array, sizeof(test_array));
1852 UT_ASSERT_INT(ret, ==, 0);
1853 if (failed)
1854 break;
1855
1856 if (!try_rx_retry_wm &&
1857 cb_data.event_rx_retry_high_wm) {
1858 /* RX high watermark hit */
1859 try_rx_retry_wm = try + 1;
1860 break;
1861 }
1862
1863 while (cb_data.event_write_done <= try) {
1864 UT_ASSERT_INT(
1865 (int)wait_for_completion_timeout(
1866 &cb_data.cb_completion, HZ),
1867 >, 0);
1868 INIT_COMPLETION(cb_data.cb_completion);
1869 }
1870 if (failed)
1871 break;
1872 }
1873 if (failed)
1874 break;
1875
1876 /* RX retry high watermark should have been set */
1877 UT_ASSERT_INT(cb_data.event_rx_retry_high_wm, ==, 1);
1878 UT_ASSERT_INT(try_rx_retry_wm, ==, SMUX_RX_WM_HIGH);
1879
1880 /*
1881 * Disabled RX buffer allocation failure and wait for
1882 * the SMUX_RX_WM_HIGH count successful packets.
1883 */
1884 get_rx_buffer_mock_fail = 0;
1885 while (cb_data.event_read_done < SMUX_RX_WM_HIGH) {
1886 UT_ASSERT_INT(
1887 (int)wait_for_completion_timeout(
1888 &cb_data.cb_completion, 2*HZ),
1889 >, 0);
1890 INIT_COMPLETION(cb_data.cb_completion);
1891 }
1892 if (failed)
1893 break;
1894
1895 UT_ASSERT_INT(0, ==, cb_data.event_read_failed);
1896 UT_ASSERT_INT(SMUX_RX_WM_HIGH, ==,
1897 cb_data.event_read_done);
1898 UT_ASSERT_INT(cb_data.event_rx_retry_low_wm, ==, 1);
1899 mock_cb_data_reset(&cb_data);
1900
1901 /* close port */
1902 ret = msm_smux_close(SMUX_TEST_LCID);
1903 UT_ASSERT_INT(ret, ==, 0);
1904 UT_ASSERT_INT(
1905 (int)wait_for_completion_timeout(
1906 &cb_data.cb_completion, HZ),
1907 >, 0);
1908 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1909 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1910 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1911 break;
1912 }
1913
1914 if (!failed) {
1915 i += scnprintf(buf + i, max - i, "\tOK\n");
1916 } else {
1917 pr_err("%s: Failed\n", __func__);
1918 i += scnprintf(buf + i, max - i, "\tFailed\n");
1919 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1920 msm_smux_close(SMUX_TEST_LCID);
1921 }
1922 smux_byte_loopback = 0;
1923 mock_cb_data_reset(&cb_data);
1924 return i;
1925}
1926
Eric Holmberg8ed30f22012-05-10 19:16:51 -06001927static char debug_buffer[DEBUG_BUFMAX];
1928
1929static ssize_t debug_read(struct file *file, char __user *buf,
1930 size_t count, loff_t *ppos)
1931{
1932 int (*fill)(char *buf, int max) = file->private_data;
1933 int bsize;
1934
1935 if (*ppos != 0)
1936 return 0;
1937
1938 bsize = fill(debug_buffer, DEBUG_BUFMAX);
1939 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
1940}
1941
1942static int debug_open(struct inode *inode, struct file *file)
1943{
1944 file->private_data = inode->i_private;
1945 return 0;
1946}
1947
1948static const struct file_operations debug_ops = {
1949 .read = debug_read,
1950 .open = debug_open,
1951};
1952
1953static void debug_create(const char *name, mode_t mode,
1954 struct dentry *dent,
1955 int (*fill)(char *buf, int max))
1956{
1957 debugfs_create_file(name, mode, dent, fill, &debug_ops);
1958}
1959
1960static int __init smux_debugfs_init(void)
1961{
1962 struct dentry *dent;
1963
1964 dent = debugfs_create_dir("n_smux", 0);
1965 if (IS_ERR(dent))
1966 return PTR_ERR(dent);
1967
1968 /*
1969 * Add Unit Test entries.
1970 *
1971 * The idea with unit tests is that you can run all of them
1972 * from ADB shell by doing:
1973 * adb shell
1974 * cat ut*
1975 *
1976 * And if particular tests fail, you can then repeatedly run the failing
1977 * tests as you debug and resolve the failing test.
1978 */
1979 debug_create("ut_local_basic", 0444, dent, smux_ut_basic);
1980 debug_create("ut_remote_basic", 0444, dent, smux_ut_remote_basic);
1981 debug_create("ut_local_big_pkt", 0444, dent, smux_ut_local_big_pkt);
1982 debug_create("ut_remote_big_pkt", 0444, dent, smux_ut_remote_big_pkt);
1983 debug_create("ut_local_tiocm", 0444, dent, smux_ut_local_tiocm);
1984 debug_create("ut_remote_tiocm", 0444, dent, smux_ut_remote_tiocm);
1985 debug_create("ut_local_wm", 0444, dent, smux_ut_local_wm);
1986 debug_create("ut_local_smuxld_receive_buf", 0444, dent,
1987 smux_ut_local_smuxld_receive_buf);
Eric Holmbergb8435c82012-06-05 14:51:29 -06001988 debug_create("ut_local_get_rx_buff_retry", 0444, dent,
1989 smux_ut_local_get_rx_buff_retry);
Eric Holmberg2e0906f2012-06-26 13:29:14 -06001990 debug_create("ut_local_get_rx_buff_retry_auto", 0444, dent,
1991 smux_ut_local_get_rx_buff_retry_auto);
Eric Holmberg06011322012-07-06 18:17:03 -06001992 debug_create("ut_remote_ssr_basic", 0444, dent,
1993 smux_ut_remote_ssr_basic);
1994 debug_create("ut_remote_ssr_open", 0444, dent,
1995 smux_ut_remote_ssr_open);
1996 debug_create("ut_remote_ssr_rx_buff_retry", 0444, dent,
1997 smux_ut_remote_ssr_rx_buff_retry);
Eric Holmberg8ed30f22012-05-10 19:16:51 -06001998
1999 return 0;
2000}
2001
2002late_initcall(smux_debugfs_init);
2003