blob: 060f03f07ff4a5e6f1498aecc36fc081941c44f4 [file] [log] [blame]
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/slab.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
Manoj Prabhu B95427a22016-11-04 11:58:11 +053017#include <linux/kernel.h>
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070018#include <linux/err.h>
19#include <linux/sched.h>
20#include <linux/ratelimit.h>
21#include <linux/workqueue.h>
22#include <linux/diagchar.h>
23#include <linux/delay.h>
24#include <linux/kmemleak.h>
25#include <linux/list.h>
26#ifdef CONFIG_DIAG_OVER_USB
27#include <linux/usb/usbdiag.h>
28#endif
29#include "diag_usb.h"
30#include "diag_mux.h"
31#include "diagmem.h"
32#include "diag_ipc_logging.h"
33
34#define DIAG_USB_STRING_SZ 10
35#define DIAG_USB_MAX_SIZE 16384
36
37struct diag_usb_info diag_usb[NUM_DIAG_USB_DEV] = {
38 {
39 .id = DIAG_USB_LOCAL,
40 .name = DIAG_LEGACY,
41 .enabled = 0,
42 .mempool = POOL_TYPE_MUX_APPS,
43 .hdl = NULL,
44 .ops = NULL,
45 .read_buf = NULL,
46 .read_ptr = NULL,
47 .usb_wq = NULL,
48 .read_cnt = 0,
49 .write_cnt = 0,
50 .max_size = DIAG_USB_MAX_SIZE,
51 },
52#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
53 {
54 .id = DIAG_USB_MDM,
55 .name = DIAG_MDM,
56 .enabled = 0,
57 .mempool = POOL_TYPE_MDM_MUX,
58 .hdl = NULL,
59 .ops = NULL,
60 .read_buf = NULL,
61 .read_ptr = NULL,
62 .usb_wq = NULL,
63 .read_cnt = 0,
64 .write_cnt = 0,
65 .max_size = DIAG_USB_MAX_SIZE,
66 },
67 {
68 .id = DIAG_USB_MDM2,
69 .name = DIAG_MDM2,
70 .enabled = 0,
71 .mempool = POOL_TYPE_MDM2_MUX,
72 .hdl = NULL,
73 .ops = NULL,
74 .read_buf = NULL,
75 .read_ptr = NULL,
76 .usb_wq = NULL,
77 .read_cnt = 0,
78 .write_cnt = 0,
79 .max_size = DIAG_USB_MAX_SIZE,
80 },
81 {
82 .id = DIAG_USB_QSC,
83 .name = DIAG_QSC,
84 .enabled = 0,
85 .mempool = POOL_TYPE_QSC_MUX,
86 .hdl = NULL,
87 .ops = NULL,
88 .read_buf = NULL,
89 .read_ptr = NULL,
90 .usb_wq = NULL,
91 .read_cnt = 0,
92 .write_cnt = 0,
93 .max_size = DIAG_USB_MAX_SIZE,
94 }
95#endif
96};
97
98static int diag_usb_buf_tbl_add(struct diag_usb_info *usb_info,
99 unsigned char *buf, uint32_t len, int ctxt)
100{
101 struct list_head *start, *temp;
102 struct diag_usb_buf_tbl_t *entry = NULL;
103
104 list_for_each_safe(start, temp, &usb_info->buf_tbl) {
105 entry = list_entry(start, struct diag_usb_buf_tbl_t, track);
106 if (entry->buf == buf) {
107 atomic_inc(&entry->ref_count);
108 return 0;
109 }
110 }
111
112 /* New buffer, not found in the list */
113 entry = kzalloc(sizeof(struct diag_usb_buf_tbl_t), GFP_ATOMIC);
114 if (!entry)
115 return -ENOMEM;
116
117 entry->buf = buf;
118 entry->ctxt = ctxt;
119 entry->len = len;
120 atomic_set(&entry->ref_count, 1);
121 INIT_LIST_HEAD(&entry->track);
122 list_add_tail(&entry->track, &usb_info->buf_tbl);
123
124 return 0;
125}
126
127static void diag_usb_buf_tbl_remove(struct diag_usb_info *usb_info,
128 unsigned char *buf)
129{
130 struct list_head *start, *temp;
131 struct diag_usb_buf_tbl_t *entry = NULL;
132
133 list_for_each_safe(start, temp, &usb_info->buf_tbl) {
134 entry = list_entry(start, struct diag_usb_buf_tbl_t, track);
135 if (entry->buf == buf) {
136 DIAG_LOG(DIAG_DEBUG_MUX, "ref_count-- for %pK\n", buf);
137 atomic_dec(&entry->ref_count);
138 /*
139 * Remove reference from the table if it is the
140 * only instance of the buffer
141 */
142 if (atomic_read(&entry->ref_count) == 0)
143 list_del(&entry->track);
144 break;
145 }
146 }
147}
148
149static struct diag_usb_buf_tbl_t *diag_usb_buf_tbl_get(
150 struct diag_usb_info *usb_info,
151 unsigned char *buf)
152{
153 struct list_head *start, *temp;
154 struct diag_usb_buf_tbl_t *entry = NULL;
155
156 list_for_each_safe(start, temp, &usb_info->buf_tbl) {
157 entry = list_entry(start, struct diag_usb_buf_tbl_t, track);
158 if (entry->buf == buf) {
159 DIAG_LOG(DIAG_DEBUG_MUX, "ref_count-- for %pK\n", buf);
160 atomic_dec(&entry->ref_count);
161 return entry;
162 }
163 }
164
165 return NULL;
166}
167
168/*
169 * This function is called asynchronously when USB is connected and
170 * synchronously when Diag wants to connect to USB explicitly.
171 */
172static void usb_connect(struct diag_usb_info *ch)
173{
174 int err = 0;
175 int num_write = 0;
176 int num_read = 1; /* Only one read buffer for any USB channel */
177
178 if (!ch || !atomic_read(&ch->connected))
179 return;
180
181 num_write = diag_mempools[ch->mempool].poolsize;
182 err = usb_diag_alloc_req(ch->hdl, num_write, num_read);
183 if (err) {
184 pr_err("diag: Unable to allocate usb requests for %s, write: %d read: %d, err: %d\n",
185 ch->name, num_write, num_read, err);
186 return;
187 }
188
189 if (ch->ops && ch->ops->open) {
190 if (atomic_read(&ch->diag_state)) {
191 ch->ops->open(ch->ctxt, DIAG_USB_MODE);
192 } else {
193 /*
194 * This case indicates that the USB is connected
195 * but the logging is still happening in MEMORY
196 * DEVICE MODE. Continue the logging without
197 * resetting the buffers.
198 */
199 }
200 }
201 /* As soon as we open the channel, queue a read */
202 queue_work(ch->usb_wq, &(ch->read_work));
203}
204
205static void usb_connect_work_fn(struct work_struct *work)
206{
207 struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
208 connect_work);
209 usb_connect(ch);
210}
211
212/*
213 * This function is called asynchronously when USB is disconnected
214 * and synchronously when Diag wants to disconnect from USB
215 * explicitly.
216 */
217static void usb_disconnect(struct diag_usb_info *ch)
218{
219 if (!ch)
220 return;
221
Manoj Prabhu B95427a22016-11-04 11:58:11 +0530222 if (!atomic_read(&ch->connected) &&
223 driver->usb_connected && diag_mask_param())
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530224 diag_clear_masks(0);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700225
226 if (ch && ch->ops && ch->ops->close)
227 ch->ops->close(ch->ctxt, DIAG_USB_MODE);
228}
229
230static void usb_disconnect_work_fn(struct work_struct *work)
231{
232 struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
233 disconnect_work);
234 usb_disconnect(ch);
235}
236
237static void usb_read_work_fn(struct work_struct *work)
238{
239 int err = 0;
240 unsigned long flags;
241 struct diag_request *req = NULL;
242 struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
243 read_work);
244 if (!ch)
245 return;
246
247 if (!atomic_read(&ch->connected) || !ch->enabled ||
248 atomic_read(&ch->read_pending) || !atomic_read(&ch->diag_state)) {
249 pr_debug_ratelimited("diag: Discarding USB read, ch: %s e: %d, c: %d, p: %d, d: %d\n",
250 ch->name, ch->enabled,
251 atomic_read(&ch->connected),
252 atomic_read(&ch->read_pending),
253 atomic_read(&ch->diag_state));
254 return;
255 }
256
257 spin_lock_irqsave(&ch->lock, flags);
258 req = ch->read_ptr;
259 if (req) {
260 atomic_set(&ch->read_pending, 1);
261 req->buf = ch->read_buf;
262 req->length = USB_MAX_OUT_BUF;
263 err = usb_diag_read(ch->hdl, req);
264 if (err) {
265 pr_debug("diag: In %s, error in reading from USB %s, err: %d\n",
266 __func__, ch->name, err);
267 atomic_set(&ch->read_pending, 0);
268 queue_work(ch->usb_wq, &(ch->read_work));
269 }
270 } else {
271 pr_err_ratelimited("diag: In %s invalid read req\n", __func__);
272 }
273 spin_unlock_irqrestore(&ch->lock, flags);
274}
275
276static void usb_read_done_work_fn(struct work_struct *work)
277{
278 struct diag_request *req = NULL;
279 struct diag_usb_info *ch = container_of(work, struct diag_usb_info,
280 read_done_work);
281 if (!ch)
282 return;
283
284 /*
285 * USB is disconnected/Disabled before the previous read completed.
286 * Discard the packet and don't do any further processing.
287 */
288 if (!atomic_read(&ch->connected) || !ch->enabled ||
289 !atomic_read(&ch->diag_state))
290 return;
291
292 req = ch->read_ptr;
293 ch->read_cnt++;
294
295 if (ch->ops && ch->ops->read_done && req->status >= 0)
296 ch->ops->read_done(req->buf, req->actual, ch->ctxt);
297}
298
299static void diag_usb_write_done(struct diag_usb_info *ch,
300 struct diag_request *req)
301{
302 int ctxt = 0;
303 int len = 0;
304 struct diag_usb_buf_tbl_t *entry = NULL;
305 unsigned char *buf = NULL;
306 unsigned long flags;
307
308 if (!ch || !req)
309 return;
310
311 ch->write_cnt++;
312 entry = diag_usb_buf_tbl_get(ch, req->context);
313 if (!entry) {
314 pr_err_ratelimited("diag: In %s, unable to find entry %pK in the table\n",
315 __func__, req->context);
316 return;
317 }
318 if (atomic_read(&entry->ref_count) != 0) {
319 DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
320 atomic_read(&entry->ref_count));
321 diag_ws_on_copy_complete(DIAG_WS_MUX);
322 diagmem_free(driver, req, ch->mempool);
323 return;
324 }
325 DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
326 ctxt);
327 spin_lock_irqsave(&ch->write_lock, flags);
328 list_del(&entry->track);
329 ctxt = entry->ctxt;
330 buf = entry->buf;
331 len = entry->len;
332 kfree(entry);
333 diag_ws_on_copy_complete(DIAG_WS_MUX);
334
335 if (ch->ops && ch->ops->write_done)
336 ch->ops->write_done(buf, len, ctxt, DIAG_USB_MODE);
337 buf = NULL;
338 len = 0;
339 ctxt = 0;
340 spin_unlock_irqrestore(&ch->write_lock, flags);
341 diagmem_free(driver, req, ch->mempool);
342}
343
344static void diag_usb_notifier(void *priv, unsigned int event,
345 struct diag_request *d_req)
346{
347 int id = 0;
348 unsigned long flags;
349 struct diag_usb_info *usb_info = NULL;
350
351 id = (int)(uintptr_t)priv;
352 if (id < 0 || id >= NUM_DIAG_USB_DEV)
353 return;
354 usb_info = &diag_usb[id];
355
356 switch (event) {
357 case USB_DIAG_CONNECT:
358 usb_info->max_size = usb_diag_request_size(usb_info->hdl);
359 atomic_set(&usb_info->connected, 1);
360 pr_info("diag: USB channel %s connected\n", usb_info->name);
361 queue_work(usb_info->usb_wq,
362 &usb_info->connect_work);
363 break;
364 case USB_DIAG_DISCONNECT:
365 atomic_set(&usb_info->connected, 0);
366 pr_info("diag: USB channel %s disconnected\n", usb_info->name);
367 queue_work(usb_info->usb_wq,
368 &usb_info->disconnect_work);
369 break;
370 case USB_DIAG_READ_DONE:
371 spin_lock_irqsave(&usb_info->lock, flags);
372 usb_info->read_ptr = d_req;
373 spin_unlock_irqrestore(&usb_info->lock, flags);
374 atomic_set(&usb_info->read_pending, 0);
375 queue_work(usb_info->usb_wq,
376 &usb_info->read_done_work);
377 break;
378 case USB_DIAG_WRITE_DONE:
379 diag_usb_write_done(usb_info, d_req);
380 break;
381 default:
382 pr_err_ratelimited("diag: Unknown event from USB diag\n");
383 break;
384 }
385}
386
387int diag_usb_queue_read(int id)
388{
389 if (id < 0 || id >= NUM_DIAG_USB_DEV) {
390 pr_err_ratelimited("diag: In %s, Incorrect id %d\n",
391 __func__, id);
392 return -EINVAL;
393 }
394 queue_work(diag_usb[id].usb_wq, &(diag_usb[id].read_work));
395 return 0;
396}
397
398static int diag_usb_write_ext(struct diag_usb_info *usb_info,
399 unsigned char *buf, int len, int ctxt)
400{
401 int err = 0;
402 int write_len = 0;
403 int bytes_remaining = len;
404 int offset = 0;
405 unsigned long flags;
406 struct diag_request *req = NULL;
407
408 if (!usb_info || !buf || len <= 0) {
409 pr_err_ratelimited("diag: In %s, usb_info: %pK buf: %pK, len: %d\n",
410 __func__, usb_info, buf, len);
411 return -EINVAL;
412 }
413
414 spin_lock_irqsave(&usb_info->write_lock, flags);
415 while (bytes_remaining > 0) {
416 req = diagmem_alloc(driver, sizeof(struct diag_request),
417 usb_info->mempool);
418 if (!req) {
419 /*
420 * This should never happen. It either means that we are
421 * trying to write more buffers than the max supported
422 * by this particualar diag USB channel at any given
423 * instance, or the previous write ptrs are stuck in
424 * the USB layer.
425 */
426 pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n",
427 __func__, usb_info->name);
428 spin_unlock_irqrestore(&usb_info->write_lock, flags);
429 return -ENOMEM;
430 }
431
432 write_len = (bytes_remaining > usb_info->max_size) ?
433 usb_info->max_size : (bytes_remaining);
434
435 req->buf = buf + offset;
436 req->length = write_len;
437 req->context = (void *)buf;
438
439 if (!usb_info->hdl || !atomic_read(&usb_info->connected) ||
440 !atomic_read(&usb_info->diag_state)) {
441 pr_debug_ratelimited("diag: USB ch %s is not connected\n",
442 usb_info->name);
443 diagmem_free(driver, req, usb_info->mempool);
444 spin_unlock_irqrestore(&usb_info->write_lock, flags);
445 return -ENODEV;
446 }
447
448 if (diag_usb_buf_tbl_add(usb_info, buf, len, ctxt)) {
449 diagmem_free(driver, req, usb_info->mempool);
450 spin_unlock_irqrestore(&usb_info->write_lock, flags);
451 return -ENOMEM;
452 }
453
454 diag_ws_on_read(DIAG_WS_MUX, len);
455 err = usb_diag_write(usb_info->hdl, req);
456 diag_ws_on_copy(DIAG_WS_MUX);
457 if (err) {
458 pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n",
459 __func__, usb_info->name, err);
460 DIAG_LOG(DIAG_DEBUG_MUX,
461 "ERR! unable to write t usb, err: %d\n", err);
462 diag_ws_on_copy_fail(DIAG_WS_MUX);
463 diag_usb_buf_tbl_remove(usb_info, buf);
464 diagmem_free(driver, req, usb_info->mempool);
465 spin_unlock_irqrestore(&usb_info->write_lock, flags);
466 return err;
467 }
468 offset += write_len;
469 bytes_remaining -= write_len;
470 DIAG_LOG(DIAG_DEBUG_MUX,
471 "bytes_remaining: %d write_len: %d, len: %d\n",
472 bytes_remaining, write_len, len);
473 }
474 DIAG_LOG(DIAG_DEBUG_MUX, "done writing!");
475 spin_unlock_irqrestore(&usb_info->write_lock, flags);
476
477 return 0;
478}
479
480int diag_usb_write(int id, unsigned char *buf, int len, int ctxt)
481{
482 int err = 0;
483 struct diag_request *req = NULL;
484 struct diag_usb_info *usb_info = NULL;
485 unsigned long flags;
486
487 if (id < 0 || id >= NUM_DIAG_USB_DEV) {
488 pr_err_ratelimited("diag: In %s, Incorrect id %d\n",
489 __func__, id);
490 return -EINVAL;
491 }
492
493 usb_info = &diag_usb[id];
494
495 if (len > usb_info->max_size) {
496 DIAG_LOG(DIAG_DEBUG_MUX, "len: %d, max_size: %d\n",
497 len, usb_info->max_size);
498 return diag_usb_write_ext(usb_info, buf, len, ctxt);
499 }
500
501 req = diagmem_alloc(driver, sizeof(struct diag_request),
502 usb_info->mempool);
503 if (!req) {
504 /*
505 * This should never happen. It either means that we are
506 * trying to write more buffers than the max supported by
507 * this particualar diag USB channel at any given instance,
508 * or the previous write ptrs are stuck in the USB layer.
509 */
510 pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n",
511 __func__, usb_info->name);
512 return -ENOMEM;
513 }
514
515 req->buf = buf;
516 req->length = len;
517 req->context = (void *)buf;
518
519 if (!usb_info->hdl || !atomic_read(&usb_info->connected) ||
520 !atomic_read(&usb_info->diag_state)) {
521 pr_debug_ratelimited("diag: USB ch %s is not connected\n",
522 usb_info->name);
523 diagmem_free(driver, req, usb_info->mempool);
524 return -ENODEV;
525 }
526
527 spin_lock_irqsave(&usb_info->write_lock, flags);
528 if (diag_usb_buf_tbl_add(usb_info, buf, len, ctxt)) {
529 DIAG_LOG(DIAG_DEBUG_MUX,
530 "ERR! unable to add buf %pK to table\n",
531 buf);
532 diagmem_free(driver, req, usb_info->mempool);
533 spin_unlock_irqrestore(&usb_info->write_lock, flags);
534 return -ENOMEM;
535 }
536
537 diag_ws_on_read(DIAG_WS_MUX, len);
538 err = usb_diag_write(usb_info->hdl, req);
539 diag_ws_on_copy(DIAG_WS_MUX);
540 if (err) {
541 pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n",
542 __func__, usb_info->name, err);
543 diag_ws_on_copy_fail(DIAG_WS_MUX);
544 DIAG_LOG(DIAG_DEBUG_MUX,
545 "ERR! unable to write t usb, err: %d\n", err);
546 diag_usb_buf_tbl_remove(usb_info, buf);
547 diagmem_free(driver, req, usb_info->mempool);
548 }
549 spin_unlock_irqrestore(&usb_info->write_lock, flags);
550
551 return err;
552}
553
554/*
555 * This functions performs USB connect operations wrt Diag synchronously. It
556 * doesn't translate to actual USB connect. This is used when Diag switches
557 * logging to USB mode and wants to mimic USB connection.
558 */
559void diag_usb_connect_all(void)
560{
561 int i = 0;
562 struct diag_usb_info *usb_info = NULL;
563
564 for (i = 0; i < NUM_DIAG_USB_DEV; i++) {
565 usb_info = &diag_usb[i];
566 if (!usb_info->enabled)
567 continue;
568 atomic_set(&usb_info->diag_state, 1);
569 usb_connect(usb_info);
570 }
571}
572
573/*
574 * This functions performs USB disconnect operations wrt Diag synchronously.
575 * It doesn't translate to actual USB disconnect. This is used when Diag
576 * switches logging from USB mode and want to mimic USB disconnect.
577 */
578void diag_usb_disconnect_all(void)
579{
580 int i = 0;
581 struct diag_usb_info *usb_info = NULL;
582
583 for (i = 0; i < NUM_DIAG_USB_DEV; i++) {
584 usb_info = &diag_usb[i];
585 if (!usb_info->enabled)
586 continue;
587 atomic_set(&usb_info->diag_state, 0);
588 usb_disconnect(usb_info);
589 }
590}
591
592int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops)
593{
594 struct diag_usb_info *ch = NULL;
595 unsigned char wq_name[DIAG_USB_NAME_SZ + DIAG_USB_STRING_SZ];
596
597 if (id < 0 || id >= NUM_DIAG_USB_DEV) {
598 pr_err("diag: Unable to register with USB, id: %d\n", id);
599 return -EIO;
600 }
601
602 if (!ops) {
603 pr_err("diag: Invalid operations for USB\n");
604 return -EIO;
605 }
606
607 ch = &diag_usb[id];
608 ch->ops = ops;
609 ch->ctxt = ctxt;
610 spin_lock_init(&ch->lock);
611 spin_lock_init(&ch->write_lock);
612 ch->read_buf = kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
613 if (!ch->read_buf)
614 goto err;
615 ch->read_ptr = kzalloc(sizeof(struct diag_request), GFP_KERNEL);
616 if (!ch->read_ptr)
617 goto err;
618 atomic_set(&ch->connected, 0);
619 atomic_set(&ch->read_pending, 0);
620 /*
621 * This function is called when the mux registers with Diag-USB.
622 * The registration happens during boot up and Diag always starts
623 * in USB mode. Set the state to 1.
624 */
625 atomic_set(&ch->diag_state, 1);
626 INIT_LIST_HEAD(&ch->buf_tbl);
627 diagmem_init(driver, ch->mempool);
628 INIT_WORK(&(ch->read_work), usb_read_work_fn);
629 INIT_WORK(&(ch->read_done_work), usb_read_done_work_fn);
630 INIT_WORK(&(ch->connect_work), usb_connect_work_fn);
631 INIT_WORK(&(ch->disconnect_work), usb_disconnect_work_fn);
632 strlcpy(wq_name, "DIAG_USB_", DIAG_USB_STRING_SZ);
633 strlcat(wq_name, ch->name, sizeof(ch->name));
634 ch->usb_wq = create_singlethread_workqueue(wq_name);
635 if (!ch->usb_wq)
636 goto err;
637 ch->hdl = usb_diag_open(ch->name, (void *)(uintptr_t)id,
638 diag_usb_notifier);
639 if (IS_ERR(ch->hdl)) {
640 pr_err("diag: Unable to open USB channel %s\n", ch->name);
641 goto err;
642 }
643 ch->enabled = 1;
644 pr_debug("diag: Successfully registered USB %s\n", ch->name);
645 return 0;
646
647err:
648 if (ch->usb_wq)
649 destroy_workqueue(ch->usb_wq);
650 kfree(ch->read_ptr);
651 kfree(ch->read_buf);
652 return -ENOMEM;
653}
654
655void diag_usb_exit(int id)
656{
657 struct diag_usb_info *ch = NULL;
658
659 if (id < 0 || id >= NUM_DIAG_USB_DEV) {
660 pr_err("diag: In %s, incorrect id %d\n", __func__, id);
661 return;
662 }
663
664 ch = &diag_usb[id];
665 ch->ops = NULL;
666 atomic_set(&ch->connected, 0);
667 atomic_set(&ch->read_pending, 0);
668 atomic_set(&ch->diag_state, 0);
669 ch->enabled = 0;
670 ch->ctxt = 0;
671 ch->read_cnt = 0;
672 ch->write_cnt = 0;
673 diagmem_exit(driver, ch->mempool);
674 ch->mempool = 0;
675 if (ch->hdl) {
676 usb_diag_close(ch->hdl);
677 ch->hdl = NULL;
678 }
679 if (ch->usb_wq)
680 destroy_workqueue(ch->usb_wq);
681 kfree(ch->read_ptr);
682 ch->read_ptr = NULL;
683 kfree(ch->read_buf);
684 ch->read_buf = NULL;
685}
686