blob: 74e90ce8e5a72947fa5dfc3eb0e318722c589bc1 [file] [log] [blame]
Eric Holmberg8ed30f22012-05-10 19:16:51 -06001/* drivers/tty/smux_test.c
2 *
Eric Holmberg837a9342012-10-29 14:12:34 -06003 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Eric Holmberg8ed30f22012-05-10 19:16:51 -06004 *
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 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600141static int get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600142{
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 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600219static void mock_cb_data_init(struct smux_mock_callback *cb)
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600220{
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 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600235static void mock_cb_data_reset(struct smux_mock_callback *cb)
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600236{
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 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600344static void smux_mock_cb(void *priv, int event, const void *metadata)
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600345{
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;
Eric Holmberga43404f2012-08-28 15:31:01 -0600693 int retry_count = 0;
Eric Holmberg06011322012-07-06 18:17:03 -0600694 int ret;
695
696 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
697 while (!failed) {
698 /* enable remote mode */
699 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
700 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
701 UT_ASSERT_INT(ret, ==, 0);
702
703 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
704 subsystem_restart("external_modem");
Eric Holmberga43404f2012-08-28 15:31:01 -0600705
706 do {
707 msleep(500);
708 ++retry_count;
709 UT_ASSERT_INT(retry_count, <, 20);
710 } while (!smux_remote_is_active() && !failed);
711
Eric Holmberg06011322012-07-06 18:17:03 -0600712 i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
713 break;
714 }
715
716 if (failed) {
717 pr_err("%s: Failed\n", __func__);
718 i += scnprintf(buf + i, max - i, "\tFailed\n");
719 }
720 return i;
721}
722
723/**
724 * Verify Subsystem Restart Support During Port Open
725 */
726static int smux_ut_remote_ssr_open(char *buf, int max)
727{
728 static struct smux_mock_callback cb_data;
729 static int cb_initialized;
730 int ret;
Eric Holmberga43404f2012-08-28 15:31:01 -0600731 int retry_count;
Eric Holmberg06011322012-07-06 18:17:03 -0600732 int i = 0;
733 int failed = 0;
734
735 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
736
737 if (!cb_initialized)
738 mock_cb_data_init(&cb_data);
739
740 mock_cb_data_reset(&cb_data);
741 while (!failed) {
742 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
743 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
744 UT_ASSERT_INT(ret, ==, 0);
745
746 /* open port */
747 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
748 get_rx_buffer);
749 UT_ASSERT_INT(ret, ==, 0);
750 UT_ASSERT_INT(
751 (int)wait_for_completion_timeout(
752 &cb_data.cb_completion, HZ), >, 0);
753 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
754 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
755 mock_cb_data_reset(&cb_data);
756
757 /* restart modem */
758 subsystem_restart("external_modem");
759
760 /* verify SSR events */
761 UT_ASSERT_INT(ret, ==, 0);
762 UT_ASSERT_INT(
763 (int)wait_for_completion_timeout(
764 &cb_data.cb_completion, 5*HZ),
765 >, 0);
766 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
767 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
768 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
769 mock_cb_data_reset(&cb_data);
770
771 /* close port */
772 ret = msm_smux_close(SMUX_TEST_LCID);
773 UT_ASSERT_INT(ret, ==, 0);
Eric Holmberga43404f2012-08-28 15:31:01 -0600774
775 /* wait for remote side to finish booting */
776 retry_count = 0;
777 do {
778 msleep(500);
779 ++retry_count;
780 UT_ASSERT_INT(retry_count, <, 20);
781 } while (!smux_remote_is_active() && !failed);
Eric Holmberg06011322012-07-06 18:17:03 -0600782 break;
783 }
784
785 if (!failed) {
786 i += scnprintf(buf + i, max - i, "\tOK\n");
787 } else {
788 pr_err("%s: Failed\n", __func__);
789 i += scnprintf(buf + i, max - i, "\tFailed\n");
790 i += mock_cb_data_print(&cb_data, buf + i, max - i);
791 msm_smux_close(SMUX_TEST_LCID);
792 }
793
794 mock_cb_data_reset(&cb_data);
795
796 return i;
797}
798
799/**
800 * Verify get_rx_buffer callback retry doesn't livelock SSR
801 * until all RX Bufffer Retries have timed out.
802 *
803 * @buf Buffer for status message
804 * @max Size of buffer
805 *
806 * @returns Number of bytes written to @buf
807 */
808static int smux_ut_remote_ssr_rx_buff_retry(char *buf, int max)
809{
810 static struct smux_mock_callback cb_data;
811 static int cb_initialized;
812 int i = 0;
813 int failed = 0;
Eric Holmberga43404f2012-08-28 15:31:01 -0600814 int retry_count;
Eric Holmberg06011322012-07-06 18:17:03 -0600815 int ret;
816
817 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
818 pr_err("%s", buf);
819
820 if (!cb_initialized)
821 mock_cb_data_init(&cb_data);
822
823 mock_cb_data_reset(&cb_data);
824 while (!failed) {
825 /* open port for loopback */
826 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
827 SMUX_CH_OPTION_REMOTE_LOOPBACK,
828 0);
829 UT_ASSERT_INT(ret, ==, 0);
830
831 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
832 smux_mock_cb, get_rx_buffer_mock);
833 UT_ASSERT_INT(ret, ==, 0);
834 UT_ASSERT_INT(
835 (int)wait_for_completion_timeout(
836 &cb_data.cb_completion, HZ), >, 0);
837 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
838 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
839 mock_cb_data_reset(&cb_data);
840
841 /* Queue up an RX buffer retry */
842 get_rx_buffer_mock_fail = 1;
843 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
844 test_array, sizeof(test_array));
845 UT_ASSERT_INT(ret, ==, 0);
846 while (!cb_data.get_rx_buff_retry_count) {
847 UT_ASSERT_INT(
848 (int)wait_for_completion_timeout(
849 &cb_data.cb_completion, HZ),
850 >, 0);
851 INIT_COMPLETION(cb_data.cb_completion);
852 }
853 if (failed)
854 break;
855 mock_cb_data_reset(&cb_data);
856
857 /* trigger SSR */
858 subsystem_restart("external_modem");
859
860 /* verify SSR completed */
Eric Holmberga43404f2012-08-28 15:31:01 -0600861 retry_count = 0;
862 while (cb_data.event_disconnected_ssr == 0) {
863 (void)wait_for_completion_timeout(
864 &cb_data.cb_completion, HZ);
865 INIT_COMPLETION(cb_data.cb_completion);
866 ++retry_count;
867 UT_ASSERT_INT(retry_count, <, 10);
868 }
869 if (failed)
870 break;
Eric Holmberg06011322012-07-06 18:17:03 -0600871 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
872 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
873 mock_cb_data_reset(&cb_data);
874
875 /* close port */
876 ret = msm_smux_close(SMUX_TEST_LCID);
877 UT_ASSERT_INT(ret, ==, 0);
Eric Holmberga43404f2012-08-28 15:31:01 -0600878
879 /* wait for remote side to finish booting */
880 retry_count = 0;
881 do {
882 msleep(500);
883 ++retry_count;
884 UT_ASSERT_INT(retry_count, <, 20);
885 } while (!smux_remote_is_active() && !failed);
Eric Holmberg06011322012-07-06 18:17:03 -0600886 break;
887 }
888
889 if (!failed) {
890 i += scnprintf(buf + i, max - i, "\tOK\n");
891 } else {
892 pr_err("%s: Failed\n", __func__);
893 i += scnprintf(buf + i, max - i, "\tFailed\n");
894 i += mock_cb_data_print(&cb_data, buf + i, max - i);
895 msm_smux_close(SMUX_TEST_LCID);
896 }
897 mock_cb_data_reset(&cb_data);
898 return i;
899}
900/**
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600901 * Fill test pattern into provided buffer including an optional
902 * redzone 16 bytes before and 16 bytes after the buffer.
903 *
904 * buf ---------
905 * redzone
906 * --------- <- returned pointer
907 * data
908 * --------- <- returned pointer + len
909 * redzone
910 * ---------
911 *
912 * @buf Pointer to the buffer of size len or len+32 (redzone)
913 * @len Length of the *data* buffer (excluding 32-byte redzone)
914 * @redzone If true, adds redzone data
915 *
916 * @returns pointer to buffer (buf + 16 if redzone enabled)
917 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600918static uint8_t *test_pattern_fill(char *buf, int len, int redzone)
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600919{
920 void *ret;
921 uint8_t ch;
922
923 ret = buf;
924 if (redzone) {
925 memset((char *)buf, 0xAB, 16);
926 memset((char *)buf + len, 0xBA, 16);
927 ret += 16;
928 }
929
930 /* fill with test pattern */
931 for (ch = 0; len > 0; --len, ++ch)
932 *buf++ = (char)ch;
933
934 return ret;
935}
936
937/**
938 * Verify test pattern generated by test_pattern_fill.
939 *
940 * @buf_ptr Pointer to buffer pointer
941 * @len Length of the *data* buffer (excluding 32-byte redzone)
942 * @redzone If true, verifies redzone and adjusts *buf_ptr
943 * @errmsg Buffer for error message
944 * @errmsg_max Size of error message buffer
945 *
946 * @returns 0 for success; length of error message otherwise
947 */
Eric Holmberg837a9342012-10-29 14:12:34 -0600948static unsigned test_pattern_verify(char **buf_ptr, int len, int redzone,
Eric Holmberg8ed30f22012-05-10 19:16:51 -0600949 char *errmsg, int errmsg_max)
950{
951 int n;
952 int i = 0;
953 char linebuff[80];
954
955 if (redzone) {
956 *buf_ptr -= 16;
957
958 /* verify prefix redzone */
959 for (n = 0; n < 16; ++n) {
960 if (*buf_ptr[n] != 0xAB) {
961 hex_dump_to_buffer(*buf_ptr, 16,
962 16, 1, linebuff, sizeof(linebuff), 1);
963 i += scnprintf(errmsg + i, errmsg_max - i,
964 "Redzone violation: %s\n", linebuff);
965 break;
966 }
967 }
968
969 /* verify postfix redzone */
970 for (n = 0; n < 16; ++n) {
971 if (*buf_ptr[len + n] != 0xBA) {
972 hex_dump_to_buffer(&(*buf_ptr)[len], 16,
973 16, 1, linebuff, sizeof(linebuff), 1);
974 i += scnprintf(errmsg + i, errmsg_max - i,
975 "Redzone violation: %s\n", linebuff);
976 break;
977 }
978 }
979 }
980 return i;
981}
982
983/**
984 * Write a multiple packets in ascending size and verify packet is received
985 * correctly.
986 *
987 * @buf Buffer for status message
988 * @max Size of buffer
989 * @name Name of the test for error reporting
990 *
991 * @returns Number of bytes written to @buf
992 *
993 * Requires that the port already be opened and loopback mode is
994 * configured correctly (if required).
995 */
996static int smux_ut_loopback_big_pkt(char *buf, int max, const char *name)
997{
998 struct test_vector test_data[] = {
999 {0, 64},
1000 {0, 128},
1001 {0, 256},
1002 {0, 512},
1003 {0, 1024},
1004 {0, 2048},
1005 {0, 4096},
1006 {0, 0},
1007 };
1008 int i = 0;
1009 int failed = 0;
1010 struct test_vector *tv;
1011
1012 /* generate test data */
1013 for (tv = test_data; tv->len > 0; ++tv) {
1014 tv->data = kmalloc(tv->len + 32, GFP_KERNEL);
1015 pr_err("%s: allocating %p len %d\n",
1016 __func__, tv->data, tv->len);
1017 if (!tv->data) {
1018 i += scnprintf(buf + i, max - i,
1019 "%s: Unable to allocate %d bytes\n",
1020 __func__, tv->len);
1021 failed = 1;
1022 goto out;
1023 }
1024 test_pattern_fill((uint8_t *)tv->data, tv->len, 1);
1025 }
1026
1027 /* run test */
1028 i += scnprintf(buf + i, max - i, "Running %s\n", name);
1029 while (!failed) {
1030 i += smux_ut_basic_core(buf + i, max - i, test_data, name);
1031 break;
1032 }
1033
1034out:
1035 if (failed) {
1036 pr_err("%s: Failed\n", name);
1037 i += scnprintf(buf + i, max - i, "\tFailed\n");
1038 }
1039
1040 for (tv = test_data; tv->len > 0; ++tv) {
1041 if (!tv->data) {
1042 i += test_pattern_verify((char **)&tv->data,
1043 tv->len, 1, buf + i, max - i);
1044 pr_err("%s: freeing %p len %d\n", __func__,
1045 tv->data, tv->len);
1046 kfree(tv->data);
1047 }
1048 }
1049
1050 return i;
1051}
1052
1053/**
1054 * Verify Large-packet Local Loopback Support.
1055 *
1056 * @buf Buffer for status message
1057 * @max Size of buffer
1058 *
1059 * @returns Number of bytes written to @buf
1060 *
1061 * Open port in local loopback mode and write a multiple packets in ascending
1062 * size and verify packet is received correctly.
1063 */
1064static int smux_ut_local_big_pkt(char *buf, int max)
1065{
1066 int i = 0;
1067 int ret;
1068
1069 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1070 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
1071
1072 if (ret == 0) {
1073 smux_byte_loopback = SMUX_TEST_LCID;
1074 i += smux_ut_loopback_big_pkt(buf, max, __func__);
1075 smux_byte_loopback = 0;
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 Large-packet Remote Loopback Support.
1087 *
1088 * @buf Buffer for status message
1089 * @max Size of buffer
1090 *
1091 * @returns Number of bytes written to @buf
1092 *
1093 * Open port in remote loopback mode and write a multiple packets in ascending
1094 * size and verify packet is received correctly.
1095 */
1096static int smux_ut_remote_big_pkt(char *buf, int max)
1097{
1098 int i = 0;
1099 int ret;
1100
1101 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1102 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
1103 if (ret == 0) {
1104 i += smux_ut_loopback_big_pkt(buf, max, __func__);
1105 } else {
1106 i += scnprintf(buf + i, max - i,
1107 "%s: Unable to set loopback mode\n",
1108 __func__);
1109 }
1110
1111 return i;
1112}
1113
1114/**
1115 * Verify set and get operations for each TIOCM bit.
1116 *
1117 * @buf Buffer for status message
1118 * @max Size of buffer
1119 * @name Name of the test for error reporting
1120 *
1121 * @returns Number of bytes written to @buf
1122 */
1123static int smux_ut_tiocm(char *buf, int max, const char *name)
1124{
1125 static struct smux_mock_callback cb_data;
1126 static int cb_initialized;
1127 static const struct tiocm_test_vector tiocm_vectors[] = {
1128 /* bit to set, set old, set new, clear old */
1129 {TIOCM_DTR, TIOCM_DTR, TIOCM_DTR | TIOCM_DSR, TIOCM_DSR},
1130 {TIOCM_RTS, TIOCM_RTS, TIOCM_RTS | TIOCM_CTS, TIOCM_CTS},
1131 {TIOCM_RI, 0x0, TIOCM_RI, TIOCM_RI},
1132 {TIOCM_CD, 0x0, TIOCM_CD, TIOCM_CD},
1133 };
1134 int i = 0;
1135 int failed = 0;
1136 int n;
1137 int ret;
1138
1139 i += scnprintf(buf + i, max - i, "Running %s\n", name);
1140
1141 if (!cb_initialized)
1142 mock_cb_data_init(&cb_data);
1143
1144 mock_cb_data_reset(&cb_data);
1145 while (!failed) {
1146 /* open port */
1147 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1148 get_rx_buffer);
1149 UT_ASSERT_INT(ret, ==, 0);
1150 UT_ASSERT_INT(
1151 (int)wait_for_completion_timeout(
1152 &cb_data.cb_completion, HZ), >, 0);
1153 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1154 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1155 mock_cb_data_reset(&cb_data);
1156
1157 /* set and clear each TIOCM bit */
1158 for (n = 0; n < ARRAY_SIZE(tiocm_vectors) && !failed; ++n) {
1159 /* set signal and verify */
1160 ret = msm_smux_tiocm_set(SMUX_TEST_LCID,
1161 tiocm_vectors[n].input, 0x0);
1162 UT_ASSERT_INT(ret, ==, 0);
1163 UT_ASSERT_INT(
1164 (int)wait_for_completion_timeout(
1165 &cb_data.cb_completion, HZ), >, 0);
1166 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1167 UT_ASSERT_INT(cb_data.event_tiocm, ==, 1);
1168 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_old, ==,
1169 tiocm_vectors[n].set_old);
1170 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_new, ==,
1171 tiocm_vectors[n].set_new);
1172 mock_cb_data_reset(&cb_data);
1173
1174 /* clear signal and verify */
1175 ret = msm_smux_tiocm_set(SMUX_TEST_LCID, 0x0,
1176 tiocm_vectors[n].input);
1177 UT_ASSERT_INT(ret, ==, 0);
1178 UT_ASSERT_INT(
1179 (int)wait_for_completion_timeout(
1180 &cb_data.cb_completion, HZ),
1181 >, 0);
1182 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1183 UT_ASSERT_INT(cb_data.event_tiocm, ==, 1);
1184 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_old, ==,
1185 tiocm_vectors[n].clr_old);
1186 UT_ASSERT_INT(cb_data.tiocm_meta.tiocm_new, ==, 0x0);
1187 mock_cb_data_reset(&cb_data);
1188 }
1189 if (failed)
1190 break;
1191
1192 /* close port */
1193 ret = msm_smux_close(SMUX_TEST_LCID);
1194 UT_ASSERT_INT(ret, ==, 0);
1195 UT_ASSERT_INT(
1196 (int)wait_for_completion_timeout(
1197 &cb_data.cb_completion, HZ),
1198 >, 0);
1199 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1200 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1201 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1202 break;
1203 }
1204
1205 if (!failed) {
1206 i += scnprintf(buf + i, max - i, "\tOK\n");
1207 } else {
1208 pr_err("%s: Failed\n", name);
1209 i += scnprintf(buf + i, max - i, "\tFailed\n");
1210 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1211 msm_smux_close(SMUX_TEST_LCID);
1212 }
1213
1214 mock_cb_data_reset(&cb_data);
1215 return i;
1216}
1217
1218/**
1219 * Verify TIOCM Status Bits for local 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_local_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_LOCAL_LOOPBACK, 0);
1233
1234 if (ret == 0) {
1235 smux_byte_loopback = SMUX_TEST_LCID;
1236 i += smux_ut_tiocm(buf, max, __func__);
1237 smux_byte_loopback = 0;
1238 } else {
1239 i += scnprintf(buf + i, max - i,
1240 "%s: Unable to set loopback mode\n",
1241 __func__);
1242 }
1243
1244 return i;
1245}
1246
1247/**
1248 * Verify TIOCM Status Bits for remote loopback.
1249 *
1250 * @buf Buffer for status message
1251 * @max Size of buffer
1252 *
1253 * @returns Number of bytes written to @buf
1254 */
1255static int smux_ut_remote_tiocm(char *buf, int max)
1256{
1257 int i = 0;
1258 int ret;
1259
1260 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1261 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
1262 if (ret == 0) {
1263 i += smux_ut_tiocm(buf, max, __func__);
1264 } else {
1265 i += scnprintf(buf + i, max - i,
1266 "%s: Unable to set loopback mode\n",
1267 __func__);
1268 }
1269
1270 return i;
1271}
1272
1273/**
1274 * Verify High/Low Watermark notifications.
1275 *
1276 * @buf Buffer for status message
1277 * @max Size of buffer
1278 *
1279 * @returns Number of bytes written to @buf
1280 */
1281static int smux_ut_local_wm(char *buf, int max)
1282{
1283 static struct smux_mock_callback cb_data;
1284 static int cb_initialized;
1285 int i = 0;
1286 int failed = 0;
1287 int ret;
1288
1289 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1290 pr_err("%s", buf);
1291
1292 if (!cb_initialized)
1293 mock_cb_data_init(&cb_data);
1294
1295 mock_cb_data_reset(&cb_data);
1296 smux_byte_loopback = SMUX_TEST_LCID;
1297 while (!failed) {
1298 /* open port for loopback with TX disabled */
1299 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1300 SMUX_CH_OPTION_LOCAL_LOOPBACK
1301 | SMUX_CH_OPTION_REMOTE_TX_STOP,
1302 0);
1303 UT_ASSERT_INT(ret, ==, 0);
1304
1305 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1306 get_rx_buffer);
1307 UT_ASSERT_INT(ret, ==, 0);
1308 UT_ASSERT_INT(
1309 (int)wait_for_completion_timeout(
1310 &cb_data.cb_completion, HZ), >, 0);
1311 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1312 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1313 mock_cb_data_reset(&cb_data);
1314
1315 /* transmit 4 packets and verify high-watermark notification */
1316 ret = 0;
1317 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)1,
1318 test_array, sizeof(test_array));
1319 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)2,
1320 test_array, sizeof(test_array));
1321 ret |= msm_smux_write(SMUX_TEST_LCID, (void *)3,
1322 test_array, sizeof(test_array));
1323 UT_ASSERT_INT(ret, ==, 0);
1324 UT_ASSERT_INT(cb_data.cb_count, ==, 0);
1325 UT_ASSERT_INT(cb_data.event_high_wm, ==, 0);
1326
1327 ret = msm_smux_write(SMUX_TEST_LCID, (void *)4,
1328 test_array, sizeof(test_array));
1329 UT_ASSERT_INT(ret, ==, 0);
1330 UT_ASSERT_INT(
1331 (int)wait_for_completion_timeout(
1332 &cb_data.cb_completion, HZ),
1333 >, 0);
1334 UT_ASSERT_INT(cb_data.event_high_wm, ==, 1);
1335 UT_ASSERT_INT(cb_data.event_low_wm, ==, 0);
1336 mock_cb_data_reset(&cb_data);
1337
1338 /* exceed watermark and verify failure return value */
1339 ret = msm_smux_write(SMUX_TEST_LCID, (void *)5,
1340 test_array, sizeof(test_array));
1341 UT_ASSERT_INT(ret, ==, -EAGAIN);
1342
1343 /* re-enable TX and verify low-watermark notification */
1344 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1345 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
1346 UT_ASSERT_INT(ret, ==, 0);
1347 while (cb_data.cb_count < 9) {
1348 UT_ASSERT_INT(
1349 (int)wait_for_completion_timeout(
1350 &cb_data.cb_completion, HZ),
1351 >, 0);
1352 INIT_COMPLETION(cb_data.cb_completion);
1353 }
1354 if (failed)
1355 break;
1356
1357 UT_ASSERT_INT(cb_data.event_high_wm, ==, 0);
1358 UT_ASSERT_INT(cb_data.event_low_wm, ==, 1);
1359 UT_ASSERT_INT(cb_data.event_write_done, ==, 4);
1360 mock_cb_data_reset(&cb_data);
1361
1362 /* close port */
1363 ret = msm_smux_close(SMUX_TEST_LCID);
1364 UT_ASSERT_INT(ret, ==, 0);
1365 UT_ASSERT_INT(
1366 (int)wait_for_completion_timeout(
1367 &cb_data.cb_completion, HZ),
1368 >, 0);
1369 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1370 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1371 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1372 break;
1373 }
1374
1375 if (!failed) {
1376 i += scnprintf(buf + i, max - i, "\tOK\n");
1377 } else {
1378 pr_err("%s: Failed\n", __func__);
1379 i += scnprintf(buf + i, max - i, "\tFailed\n");
1380 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1381 msm_smux_close(SMUX_TEST_LCID);
1382 }
1383 smux_byte_loopback = 0;
1384 mock_cb_data_reset(&cb_data);
1385 return i;
1386}
1387
1388/**
1389 * Verify smuxld_receive_buf regular and error processing.
1390 *
1391 * @buf Buffer for status message
1392 * @max Size of buffer
1393 *
1394 * @returns Number of bytes written to @buf
1395 */
1396static int smux_ut_local_smuxld_receive_buf(char *buf, int max)
1397{
1398 static struct smux_mock_callback cb_data;
1399 static int cb_initialized;
1400 struct mock_read_event *meta;
1401 int i = 0;
1402 int failed = 0;
1403 int ret;
1404 char data[] = {SMUX_UT_ECHO_REQ,
1405 SMUX_UT_ECHO_REQ, SMUX_UT_ECHO_REQ,
1406 };
1407 char flags[] = {0x0, 0x1, 0x0,};
1408
1409
1410 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1411
1412 if (!cb_initialized)
1413 mock_cb_data_init(&cb_data);
1414
1415 mock_cb_data_reset(&cb_data);
1416 smux_byte_loopback = SMUX_TEST_LCID;
1417 while (!failed) {
1418 /* open port for loopback */
1419 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1420 SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
1421 UT_ASSERT_INT(ret, ==, 0);
1422
1423 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1424 get_rx_buffer);
1425 UT_ASSERT_INT(ret, ==, 0);
1426 UT_ASSERT_INT(
1427 (int)wait_for_completion_timeout(
1428 &cb_data.cb_completion, HZ), >, 0);
1429 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1430 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1431 mock_cb_data_reset(&cb_data);
1432
1433 /*
1434 * Verify RX error processing by sending 3 echo requests:
1435 * one OK, one fail, and a final OK
1436 *
1437 * The parsing framework should process the requests
1438 * and send us three BYTE command packets with
1439 * ECHO ACK FAIL and ECHO ACK OK characters.
1440 */
1441 smuxld_receive_buf(0, data, flags, sizeof(data));
1442
1443 /* verify response characters */
1444 do {
1445 UT_ASSERT_INT(
1446 (int)wait_for_completion_timeout(
1447 &cb_data.cb_completion, HZ), >, 0);
1448 INIT_COMPLETION(cb_data.cb_completion);
1449 } while (cb_data.cb_count < 3);
1450 UT_ASSERT_INT(cb_data.cb_count, ==, 3);
1451 UT_ASSERT_INT(cb_data.event_read_done, ==, 3);
1452
1453 meta = list_first_entry(&cb_data.read_events,
1454 struct mock_read_event, list);
1455 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1456 SMUX_UT_ECHO_ACK_OK);
1457 list_del(&meta->list);
1458
1459 meta = list_first_entry(&cb_data.read_events,
1460 struct mock_read_event, list);
1461 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1462 SMUX_UT_ECHO_ACK_FAIL);
1463 list_del(&meta->list);
1464
1465 meta = list_first_entry(&cb_data.read_events,
1466 struct mock_read_event, list);
1467 UT_ASSERT_INT((int)meta->meta.pkt_priv, ==,
1468 SMUX_UT_ECHO_ACK_OK);
1469 list_del(&meta->list);
1470 mock_cb_data_reset(&cb_data);
1471
1472 /* close port */
1473 ret = msm_smux_close(SMUX_TEST_LCID);
1474 UT_ASSERT_INT(ret, ==, 0);
1475 UT_ASSERT_INT(
1476 (int)wait_for_completion_timeout(
1477 &cb_data.cb_completion, HZ),
1478 >, 0);
1479 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1480 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1481 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1482 break;
1483 }
1484
1485 if (!failed) {
1486 i += scnprintf(buf + i, max - i, "\tOK\n");
1487 } else {
1488 pr_err("%s: Failed\n", __func__);
1489 i += scnprintf(buf + i, max - i, "\tFailed\n");
1490 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1491 msm_smux_close(SMUX_TEST_LCID);
1492 }
1493 smux_byte_loopback = 0;
1494 mock_cb_data_reset(&cb_data);
1495 return i;
1496}
1497
Eric Holmbergb8435c82012-06-05 14:51:29 -06001498/**
1499 * Allocates a new buffer or returns a failure based upon the
1500 * global @get_rx_buffer_mock_fail.
1501 */
1502static int get_rx_buffer_mock(void *priv, void **pkt_priv,
1503 void **buffer, int size)
1504{
1505 void *rx_buf;
1506 unsigned long flags;
1507 struct smux_mock_callback *cb_ptr;
1508
1509 cb_ptr = (struct smux_mock_callback *)priv;
1510 if (!cb_ptr) {
1511 pr_err("%s: no callback data\n", __func__);
1512 return -ENXIO;
1513 }
1514
1515 if (get_rx_buffer_mock_fail) {
1516 /* force failure and log failure event */
1517 struct mock_get_rx_buff_event *meta;
1518 meta = kmalloc(sizeof(struct mock_get_rx_buff_event),
1519 GFP_KERNEL);
1520 if (!meta) {
1521 pr_err("%s: unable to allocate metadata\n", __func__);
1522 return -ENOMEM;
1523 }
1524 INIT_LIST_HEAD(&meta->list);
1525 meta->size = size;
1526 meta->jiffies = jiffies;
1527
1528 spin_lock_irqsave(&cb_ptr->lock, flags);
1529 ++cb_ptr->get_rx_buff_retry_count;
1530 list_add_tail(&meta->list, &cb_ptr->get_rx_buff_retry_events);
1531 ++cb_ptr->cb_count;
1532 complete(&cb_ptr->cb_completion);
1533 spin_unlock_irqrestore(&cb_ptr->lock, flags);
1534 return -EAGAIN;
1535 } else {
1536 rx_buf = kmalloc(size, GFP_KERNEL);
1537 *pkt_priv = (void *)0x1234;
1538 *buffer = rx_buf;
1539 return 0;
1540 }
1541 return 0;
1542}
1543
1544/**
1545 * Verify get_rx_buffer callback retry.
1546 *
1547 * @buf Buffer for status message
1548 * @max Size of buffer
1549 *
1550 * @returns Number of bytes written to @buf
1551 */
1552static int smux_ut_local_get_rx_buff_retry(char *buf, int max)
1553{
1554 static struct smux_mock_callback cb_data;
1555 static int cb_initialized;
1556 int i = 0;
1557 int failed = 0;
1558 char try_two[] = "try 2";
1559 int ret;
1560 unsigned long start_j;
1561 struct mock_get_rx_buff_event *event;
1562 struct mock_read_event *read_event;
1563 int try;
1564
1565 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1566 pr_err("%s", buf);
1567
1568 if (!cb_initialized)
1569 mock_cb_data_init(&cb_data);
1570
1571 mock_cb_data_reset(&cb_data);
1572 smux_byte_loopback = SMUX_TEST_LCID;
1573 while (!failed) {
1574 /* open port for loopback */
1575 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1576 SMUX_CH_OPTION_LOCAL_LOOPBACK,
Eric Holmberg2e0906f2012-06-26 13:29:14 -06001577 SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP);
Eric Holmbergb8435c82012-06-05 14:51:29 -06001578 UT_ASSERT_INT(ret, ==, 0);
1579
1580 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
1581 smux_mock_cb, get_rx_buffer_mock);
1582 UT_ASSERT_INT(ret, ==, 0);
1583 UT_ASSERT_INT(
1584 (int)wait_for_completion_timeout(
1585 &cb_data.cb_completion, HZ), >, 0);
1586 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1587 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1588 mock_cb_data_reset(&cb_data);
1589
1590 /*
1591 * Force get_rx_buffer failure for a single RX packet
1592 *
1593 * The get_rx_buffer calls should follow an exponential
1594 * back-off with a maximum timeout of 1024 ms after which we
1595 * will get a failure notification.
1596 *
1597 * Try Post Delay (ms)
1598 * 0 -
1599 * 1 1
1600 * 2 2
1601 * 3 4
1602 * 4 8
1603 * 5 16
1604 * 6 32
1605 * 7 64
1606 * 8 128
1607 * 9 256
1608 * 10 512
1609 * 11 1024
1610 * 12 Fail
1611 *
1612 * All times are limited by the precision of the timer
1613 * framework, so ranges are used in the test
1614 * verification.
1615 */
1616 get_rx_buffer_mock_fail = 1;
1617 start_j = jiffies;
1618 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1619 test_array, sizeof(test_array));
1620 UT_ASSERT_INT(ret, ==, 0);
1621 ret = msm_smux_write(SMUX_TEST_LCID, (void *)2,
1622 try_two, sizeof(try_two));
1623 UT_ASSERT_INT(ret, ==, 0);
1624
1625 /* wait for RX failure event */
1626 while (cb_data.event_read_failed == 0) {
1627 UT_ASSERT_INT(
1628 (int)wait_for_completion_timeout(
1629 &cb_data.cb_completion, 2*HZ),
1630 >, 0);
1631 INIT_COMPLETION(cb_data.cb_completion);
1632 }
1633 if (failed)
1634 break;
1635
1636 /* verify retry attempts */
1637 UT_ASSERT_INT(cb_data.get_rx_buff_retry_count, ==, 12);
1638 event = list_first_entry(&cb_data.get_rx_buff_retry_events,
1639 struct mock_get_rx_buff_event, list);
1640 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1641 jiffies_to_msecs(event->jiffies - start_j));
1642 UT_ASSERT_INT_IN_RANGE(
1643 jiffies_to_msecs(event->jiffies - start_j),
1644 0, 0 + 20);
1645 start_j = event->jiffies;
1646
1647 event = list_first_entry(&event->list,
1648 struct mock_get_rx_buff_event, list);
1649 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1650 jiffies_to_msecs(event->jiffies - start_j));
1651 UT_ASSERT_INT_IN_RANGE(
1652 jiffies_to_msecs(event->jiffies - start_j),
1653 1, 1 + 20);
1654 start_j = event->jiffies;
1655
1656 event = list_first_entry(&event->list,
1657 struct mock_get_rx_buff_event, list);
1658 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1659 jiffies_to_msecs(event->jiffies - start_j));
1660 UT_ASSERT_INT_IN_RANGE(
1661 jiffies_to_msecs(event->jiffies - start_j),
1662 2, 2 + 20);
1663 start_j = event->jiffies;
1664
1665 event = list_first_entry(&event->list,
1666 struct mock_get_rx_buff_event, list);
1667 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1668 jiffies_to_msecs(event->jiffies - start_j));
1669 UT_ASSERT_INT_IN_RANGE(
1670 jiffies_to_msecs(event->jiffies - start_j),
1671 4, 4 + 20);
1672 start_j = event->jiffies;
1673
1674 event = list_first_entry(&event->list,
1675 struct mock_get_rx_buff_event, list);
1676 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1677 jiffies_to_msecs(event->jiffies - start_j));
1678 UT_ASSERT_INT_IN_RANGE(
1679 jiffies_to_msecs(event->jiffies - start_j),
1680 8, 8 + 20);
1681 start_j = event->jiffies;
1682
1683 event = list_first_entry(&event->list,
1684 struct mock_get_rx_buff_event, list);
1685 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1686 jiffies_to_msecs(event->jiffies - start_j));
1687 UT_ASSERT_INT_IN_RANGE(
1688 jiffies_to_msecs(event->jiffies - start_j),
1689 16, 16 + 20);
1690 start_j = event->jiffies;
1691
1692 event = list_first_entry(&event->list,
1693 struct mock_get_rx_buff_event, list);
1694 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1695 jiffies_to_msecs(event->jiffies - start_j));
1696 UT_ASSERT_INT_IN_RANGE(
1697 jiffies_to_msecs(event->jiffies - start_j),
1698 32 - 20, 32 + 20);
1699 start_j = event->jiffies;
1700
1701 event = list_first_entry(&event->list,
1702 struct mock_get_rx_buff_event, list);
1703 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1704 jiffies_to_msecs(event->jiffies - start_j));
1705 UT_ASSERT_INT_IN_RANGE(
1706 jiffies_to_msecs(event->jiffies - start_j),
1707 64 - 20, 64 + 20);
1708 start_j = event->jiffies;
1709
1710 event = list_first_entry(&event->list,
1711 struct mock_get_rx_buff_event, list);
1712 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1713 jiffies_to_msecs(event->jiffies - start_j));
1714 UT_ASSERT_INT_IN_RANGE(
1715 jiffies_to_msecs(event->jiffies - start_j),
1716 128 - 20, 128 + 20);
1717 start_j = event->jiffies;
1718
1719 event = list_first_entry(&event->list,
1720 struct mock_get_rx_buff_event, list);
1721 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1722 jiffies_to_msecs(event->jiffies - start_j));
1723 UT_ASSERT_INT_IN_RANGE(
1724 jiffies_to_msecs(event->jiffies - start_j),
1725 256 - 20, 256 + 20);
1726 start_j = event->jiffies;
1727
1728 event = list_first_entry(&event->list,
1729 struct mock_get_rx_buff_event, list);
1730 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1731 jiffies_to_msecs(event->jiffies - start_j));
1732 UT_ASSERT_INT_IN_RANGE(
1733 jiffies_to_msecs(event->jiffies - start_j),
1734 512 - 20, 512 + 20);
1735 start_j = event->jiffies;
1736
1737 event = list_first_entry(&event->list,
1738 struct mock_get_rx_buff_event, list);
1739 pr_err("%s: event->jiffies = %d (ms)\n", __func__,
1740 jiffies_to_msecs(event->jiffies - start_j));
1741 UT_ASSERT_INT_IN_RANGE(
1742 jiffies_to_msecs(event->jiffies - start_j),
1743 1024 - 20, 1024 + 20);
1744 mock_cb_data_reset(&cb_data);
1745
1746 /* verify 2nd pending RX packet goes through */
1747 get_rx_buffer_mock_fail = 0;
1748 INIT_COMPLETION(cb_data.cb_completion);
1749 if (cb_data.event_read_done == 0)
1750 UT_ASSERT_INT(
1751 (int)wait_for_completion_timeout(
1752 &cb_data.cb_completion, HZ),
1753 >, 0);
1754 UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
1755 UT_ASSERT_INT(list_empty(&cb_data.read_events), ==, 0);
1756 read_event = list_first_entry(&cb_data.read_events,
1757 struct mock_read_event, list);
1758 UT_ASSERT_PTR(read_event->meta.pkt_priv, ==, (void *)0x1234);
1759 UT_ASSERT_PTR(read_event->meta.buffer, !=, NULL);
1760 UT_ASSERT_INT(0, ==, memcmp(read_event->meta.buffer, try_two,
1761 sizeof(try_two)));
1762 mock_cb_data_reset(&cb_data);
1763
1764 /* Test maximum retry queue size */
1765 get_rx_buffer_mock_fail = 1;
1766 for (try = 0; try < (SMUX_RX_RETRY_MAX_PKTS + 1); ++try) {
1767 mock_cb_data_reset(&cb_data);
1768 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1769 test_array, sizeof(test_array));
1770 UT_ASSERT_INT(ret, ==, 0);
1771 UT_ASSERT_INT(
1772 (int)wait_for_completion_timeout(
1773 &cb_data.cb_completion, HZ),
1774 >, 0);
1775 }
1776
1777 /* should have 32 successful rx packets and 1 failed */
1778 while (cb_data.event_read_failed == 0) {
1779 UT_ASSERT_INT(
1780 (int)wait_for_completion_timeout(
1781 &cb_data.cb_completion, 2*HZ),
1782 >, 0);
1783 INIT_COMPLETION(cb_data.cb_completion);
1784 }
1785 if (failed)
1786 break;
1787
1788 get_rx_buffer_mock_fail = 0;
1789 while (cb_data.event_read_done < SMUX_RX_RETRY_MAX_PKTS) {
1790 UT_ASSERT_INT(
1791 (int)wait_for_completion_timeout(
1792 &cb_data.cb_completion, 2*HZ),
1793 >, 0);
1794 INIT_COMPLETION(cb_data.cb_completion);
1795 }
1796 if (failed)
1797 break;
1798
1799 UT_ASSERT_INT(1, ==, cb_data.event_read_failed);
1800 UT_ASSERT_INT(SMUX_RX_RETRY_MAX_PKTS, ==,
1801 cb_data.event_read_done);
1802 mock_cb_data_reset(&cb_data);
1803
1804 /* close port */
1805 ret = msm_smux_close(SMUX_TEST_LCID);
1806 UT_ASSERT_INT(ret, ==, 0);
1807 UT_ASSERT_INT(
1808 (int)wait_for_completion_timeout(
1809 &cb_data.cb_completion, HZ),
1810 >, 0);
1811 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1812 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1813 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1814 break;
1815 }
1816
1817 if (!failed) {
1818 i += scnprintf(buf + i, max - i, "\tOK\n");
1819 } else {
1820 pr_err("%s: Failed\n", __func__);
1821 i += scnprintf(buf + i, max - i, "\tFailed\n");
1822 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1823 msm_smux_close(SMUX_TEST_LCID);
1824 }
1825 smux_byte_loopback = 0;
1826 mock_cb_data_reset(&cb_data);
1827 return i;
1828}
1829
Eric Holmberg2e0906f2012-06-26 13:29:14 -06001830/**
1831 * Verify get_rx_buffer callback retry for auto-rx flow control.
1832 *
1833 * @buf Buffer for status message
1834 * @max Size of buffer
1835 *
1836 * @returns Number of bytes written to @buf
1837 */
1838static int smux_ut_local_get_rx_buff_retry_auto(char *buf, int max)
1839{
1840 static struct smux_mock_callback cb_data;
1841 static int cb_initialized;
1842 int i = 0;
1843 int failed = 0;
1844 int ret;
1845 int try;
1846 int try_rx_retry_wm;
1847
1848 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1849 pr_err("%s", buf);
1850
1851 if (!cb_initialized)
1852 mock_cb_data_init(&cb_data);
1853
1854 mock_cb_data_reset(&cb_data);
1855 smux_byte_loopback = SMUX_TEST_LCID;
1856 while (!failed) {
1857 /* open port for loopback */
1858 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1859 SMUX_CH_OPTION_LOCAL_LOOPBACK
1860 | SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP,
1861 0);
1862 UT_ASSERT_INT(ret, ==, 0);
1863
1864 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data,
1865 smux_mock_cb, get_rx_buffer_mock);
1866 UT_ASSERT_INT(ret, ==, 0);
1867 UT_ASSERT_INT(
1868 (int)wait_for_completion_timeout(
1869 &cb_data.cb_completion, HZ), >, 0);
1870 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1871 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1872 mock_cb_data_reset(&cb_data);
1873
1874 /* Test high rx-retry watermark */
1875 get_rx_buffer_mock_fail = 1;
1876 try_rx_retry_wm = 0;
1877 for (try = 0; try < SMUX_RX_RETRY_MAX_PKTS; ++try) {
1878 pr_err("%s: try %d\n", __func__, try);
1879 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1880 test_array, sizeof(test_array));
1881 UT_ASSERT_INT(ret, ==, 0);
1882 if (failed)
1883 break;
1884
1885 if (!try_rx_retry_wm &&
1886 cb_data.event_rx_retry_high_wm) {
1887 /* RX high watermark hit */
1888 try_rx_retry_wm = try + 1;
1889 break;
1890 }
1891
1892 while (cb_data.event_write_done <= try) {
1893 UT_ASSERT_INT(
1894 (int)wait_for_completion_timeout(
1895 &cb_data.cb_completion, HZ),
1896 >, 0);
1897 INIT_COMPLETION(cb_data.cb_completion);
1898 }
1899 if (failed)
1900 break;
1901 }
1902 if (failed)
1903 break;
1904
1905 /* RX retry high watermark should have been set */
1906 UT_ASSERT_INT(cb_data.event_rx_retry_high_wm, ==, 1);
1907 UT_ASSERT_INT(try_rx_retry_wm, ==, SMUX_RX_WM_HIGH);
1908
1909 /*
1910 * Disabled RX buffer allocation failure and wait for
1911 * the SMUX_RX_WM_HIGH count successful packets.
1912 */
1913 get_rx_buffer_mock_fail = 0;
1914 while (cb_data.event_read_done < SMUX_RX_WM_HIGH) {
1915 UT_ASSERT_INT(
1916 (int)wait_for_completion_timeout(
1917 &cb_data.cb_completion, 2*HZ),
1918 >, 0);
1919 INIT_COMPLETION(cb_data.cb_completion);
1920 }
1921 if (failed)
1922 break;
1923
1924 UT_ASSERT_INT(0, ==, cb_data.event_read_failed);
1925 UT_ASSERT_INT(SMUX_RX_WM_HIGH, ==,
1926 cb_data.event_read_done);
1927 UT_ASSERT_INT(cb_data.event_rx_retry_low_wm, ==, 1);
1928 mock_cb_data_reset(&cb_data);
1929
1930 /* close port */
1931 ret = msm_smux_close(SMUX_TEST_LCID);
1932 UT_ASSERT_INT(ret, ==, 0);
1933 UT_ASSERT_INT(
1934 (int)wait_for_completion_timeout(
1935 &cb_data.cb_completion, HZ),
1936 >, 0);
1937 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1938 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
1939 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
1940 break;
1941 }
1942
1943 if (!failed) {
1944 i += scnprintf(buf + i, max - i, "\tOK\n");
1945 } else {
1946 pr_err("%s: Failed\n", __func__);
1947 i += scnprintf(buf + i, max - i, "\tFailed\n");
1948 i += mock_cb_data_print(&cb_data, buf + i, max - i);
1949 msm_smux_close(SMUX_TEST_LCID);
1950 }
1951 smux_byte_loopback = 0;
1952 mock_cb_data_reset(&cb_data);
1953 return i;
1954}
1955
Eric Holmbergeee5d5a2012-08-13 14:45:27 -06001956/**
1957 * Verify remote flow control (remote TX stop).
1958 *
1959 * @buf Buffer for status message
1960 * @max Size of buffer
1961 *
1962 * @returns Number of bytes written to @buf
1963 */
1964static int smux_ut_remote_tx_stop(char *buf, int max)
1965{
1966 static struct smux_mock_callback cb_data;
1967 static int cb_initialized;
1968 int i = 0;
1969 int failed = 0;
1970 int ret;
1971
1972 i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
1973 pr_err("%s", buf);
1974
1975 if (!cb_initialized)
1976 mock_cb_data_init(&cb_data);
1977
1978 mock_cb_data_reset(&cb_data);
1979 while (!failed) {
1980 /* open port for remote loopback */
1981 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
1982 SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
1983 UT_ASSERT_INT(ret, ==, 0);
1984
1985 ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
1986 get_rx_buffer);
1987 UT_ASSERT_INT(ret, ==, 0);
1988 UT_ASSERT_INT(
1989 (int)wait_for_completion_timeout(
1990 &cb_data.cb_completion, HZ), >, 0);
1991 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
1992 UT_ASSERT_INT(cb_data.event_connected, ==, 1);
1993 mock_cb_data_reset(&cb_data);
1994
1995 /* send 1 packet and verify response */
1996 ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
1997 test_array, sizeof(test_array));
1998 UT_ASSERT_INT(ret, ==, 0);
1999 UT_ASSERT_INT(
2000 (int)wait_for_completion_timeout(
2001 &cb_data.cb_completion, HZ),
2002 >, 0);
2003 UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
2004
2005 INIT_COMPLETION(cb_data.cb_completion);
2006 if (!cb_data.event_read_done) {
2007 UT_ASSERT_INT(
2008 (int)wait_for_completion_timeout(
2009 &cb_data.cb_completion, HZ),
2010 >, 0);
2011 }
2012 UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
2013 mock_cb_data_reset(&cb_data);
2014
2015 /* enable flow control */
2016 UT_ASSERT_INT(smux_lch[SMUX_TEST_LCID].tx_flow_control, ==, 0);
2017 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
2018 SMUX_CH_OPTION_REMOTE_TX_STOP, 0);
2019 UT_ASSERT_INT(ret, ==, 0);
2020
2021 /* wait for remote echo and clear our tx_flow control */
2022 msleep(500);
2023 UT_ASSERT_INT(smux_lch[SMUX_TEST_LCID].tx_flow_control, ==, 1);
2024 smux_lch[SMUX_TEST_LCID].tx_flow_control = 0;
2025
2026 /* Send 1 packet and verify no response */
2027 ret = msm_smux_write(SMUX_TEST_LCID, (void *)2,
2028 test_array, sizeof(test_array));
2029 UT_ASSERT_INT(ret, ==, 0);
2030 UT_ASSERT_INT(
2031 (int)wait_for_completion_timeout(
2032 &cb_data.cb_completion, HZ),
2033 >, 0);
2034 INIT_COMPLETION(cb_data.cb_completion);
2035 UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
2036 UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
2037 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
2038
2039 UT_ASSERT_INT(
2040 (int)wait_for_completion_timeout(
2041 &cb_data.cb_completion, 1*HZ),
2042 ==, 0);
2043 UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
2044 mock_cb_data_reset(&cb_data);
2045
2046 /* disable flow control and verify response is received */
2047 UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
2048 ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
2049 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
2050 UT_ASSERT_INT(ret, ==, 0);
2051
2052 UT_ASSERT_INT(
2053 (int)wait_for_completion_timeout(
2054 &cb_data.cb_completion, HZ),
2055 >, 0);
2056 UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
2057 mock_cb_data_reset(&cb_data);
2058
2059 /* close port */
2060 ret = msm_smux_close(SMUX_TEST_LCID);
2061 UT_ASSERT_INT(ret, ==, 0);
2062 UT_ASSERT_INT(
2063 (int)wait_for_completion_timeout(
2064 &cb_data.cb_completion, HZ),
2065 >, 0);
2066 UT_ASSERT_INT(cb_data.cb_count, ==, 1);
2067 UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
2068 UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
2069 break;
2070 }
2071
2072 if (!failed) {
2073 i += scnprintf(buf + i, max - i, "\tOK\n");
2074 } else {
2075 pr_err("%s: Failed\n", __func__);
2076 i += scnprintf(buf + i, max - i, "\tFailed\n");
2077 i += mock_cb_data_print(&cb_data, buf + i, max - i);
2078 msm_smux_set_ch_option(SMUX_TEST_LCID,
2079 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
2080 msm_smux_close(SMUX_TEST_LCID);
2081 }
2082 mock_cb_data_reset(&cb_data);
2083 return i;
2084}
2085
Eric Holmberg8ed30f22012-05-10 19:16:51 -06002086static char debug_buffer[DEBUG_BUFMAX];
2087
2088static ssize_t debug_read(struct file *file, char __user *buf,
2089 size_t count, loff_t *ppos)
2090{
2091 int (*fill)(char *buf, int max) = file->private_data;
2092 int bsize;
2093
2094 if (*ppos != 0)
2095 return 0;
2096
2097 bsize = fill(debug_buffer, DEBUG_BUFMAX);
2098 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
2099}
2100
2101static int debug_open(struct inode *inode, struct file *file)
2102{
2103 file->private_data = inode->i_private;
2104 return 0;
2105}
2106
2107static const struct file_operations debug_ops = {
2108 .read = debug_read,
2109 .open = debug_open,
2110};
2111
2112static void debug_create(const char *name, mode_t mode,
2113 struct dentry *dent,
2114 int (*fill)(char *buf, int max))
2115{
2116 debugfs_create_file(name, mode, dent, fill, &debug_ops);
2117}
2118
2119static int __init smux_debugfs_init(void)
2120{
2121 struct dentry *dent;
2122
Eric Holmberg9d890672012-06-13 17:58:13 -06002123 dent = debugfs_create_dir("n_smux_test", 0);
Eric Holmberg8ed30f22012-05-10 19:16:51 -06002124 if (IS_ERR(dent))
2125 return PTR_ERR(dent);
2126
2127 /*
2128 * Add Unit Test entries.
2129 *
2130 * The idea with unit tests is that you can run all of them
2131 * from ADB shell by doing:
2132 * adb shell
2133 * cat ut*
2134 *
2135 * And if particular tests fail, you can then repeatedly run the failing
2136 * tests as you debug and resolve the failing test.
2137 */
2138 debug_create("ut_local_basic", 0444, dent, smux_ut_basic);
2139 debug_create("ut_remote_basic", 0444, dent, smux_ut_remote_basic);
2140 debug_create("ut_local_big_pkt", 0444, dent, smux_ut_local_big_pkt);
2141 debug_create("ut_remote_big_pkt", 0444, dent, smux_ut_remote_big_pkt);
2142 debug_create("ut_local_tiocm", 0444, dent, smux_ut_local_tiocm);
2143 debug_create("ut_remote_tiocm", 0444, dent, smux_ut_remote_tiocm);
2144 debug_create("ut_local_wm", 0444, dent, smux_ut_local_wm);
2145 debug_create("ut_local_smuxld_receive_buf", 0444, dent,
2146 smux_ut_local_smuxld_receive_buf);
Eric Holmbergb8435c82012-06-05 14:51:29 -06002147 debug_create("ut_local_get_rx_buff_retry", 0444, dent,
2148 smux_ut_local_get_rx_buff_retry);
Eric Holmberg2e0906f2012-06-26 13:29:14 -06002149 debug_create("ut_local_get_rx_buff_retry_auto", 0444, dent,
2150 smux_ut_local_get_rx_buff_retry_auto);
Eric Holmberg06011322012-07-06 18:17:03 -06002151 debug_create("ut_remote_ssr_basic", 0444, dent,
2152 smux_ut_remote_ssr_basic);
2153 debug_create("ut_remote_ssr_open", 0444, dent,
2154 smux_ut_remote_ssr_open);
2155 debug_create("ut_remote_ssr_rx_buff_retry", 0444, dent,
2156 smux_ut_remote_ssr_rx_buff_retry);
Eric Holmbergeee5d5a2012-08-13 14:45:27 -06002157 debug_create("ut_remote_tx_stop", 0444, dent,
2158 smux_ut_remote_tx_stop);
Eric Holmberg8ed30f22012-05-10 19:16:51 -06002159
2160 return 0;
2161}
2162
2163late_initcall(smux_debugfs_init);
2164