blob: 591440ddf59a79d793bd16192e02b119e209f3c2 [file] [log] [blame]
Vamsi Krishna5b944712012-06-29 18:36:23 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/* add additional information to our printk's */
15#define pr_fmt(fmt) "%s: " fmt "\n", __func__
16
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/kref.h>
23#include <linux/platform_device.h>
24#include <linux/ratelimit.h>
25#include <linux/uaccess.h>
26#include <linux/usb.h>
27#include <linux/debugfs.h>
28#include <linux/seq_file.h>
29#include <linux/miscdevice.h>
30#include <linux/list.h>
31#include <linux/wait.h>
32
33#define DRIVER_DESC "USB host ks bridge driver"
34#define DRIVER_VERSION "1.0"
35
36struct data_pkt {
37 int n_read;
38 char *buf;
39 size_t len;
40 struct list_head list;
41 void *ctxt;
42};
43
44#define FILE_OPENED BIT(0)
45#define USB_DEV_CONNECTED BIT(1)
46#define NO_RX_REQS 10
47#define NO_BRIDGE_INSTANCES 2
48#define BOOT_BRIDGE_INDEX 0
49#define EFS_BRIDGE_INDEX 1
50#define MAX_DATA_PKT_SIZE 16384
51
52struct ks_bridge {
53 char *name;
54 spinlock_t lock;
55 struct workqueue_struct *wq;
56 struct work_struct to_mdm_work;
57 struct work_struct start_rx_work;
58 struct list_head to_mdm_list;
59 struct list_head to_ks_list;
60 wait_queue_head_t ks_wait_q;
61
62 /* usb specific */
63 struct usb_device *udev;
64 struct usb_interface *ifc;
65 __u8 in_epAddr;
66 __u8 out_epAddr;
67 unsigned int in_pipe;
68 unsigned int out_pipe;
69 struct usb_anchor submitted;
70
71 unsigned long flags;
Vamsi Krishna5b944712012-06-29 18:36:23 -070072
73#define DBG_MSG_LEN 40
74#define DBG_MAX_MSG 500
75 unsigned int dbg_idx;
76 rwlock_t dbg_lock;
77 char (dbgbuf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
78};
79struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES];
80
81/* by default debugging is enabled */
82static unsigned int enable_dbg = 1;
83module_param(enable_dbg, uint, S_IRUGO | S_IWUSR);
84
85static void
86dbg_log_event(struct ks_bridge *ksb, char *event, int d1, int d2)
87{
88 unsigned long flags;
89 unsigned long long t;
90 unsigned long nanosec;
91
92 if (!enable_dbg)
93 return;
94
95 write_lock_irqsave(&ksb->dbg_lock, flags);
96 t = cpu_clock(smp_processor_id());
97 nanosec = do_div(t, 1000000000)/1000;
98 scnprintf(ksb->dbgbuf[ksb->dbg_idx], DBG_MSG_LEN, "%5lu.%06lu:%s:%x:%x",
99 (unsigned long)t, nanosec, event, d1, d2);
100
101 ksb->dbg_idx++;
102 ksb->dbg_idx = ksb->dbg_idx % DBG_MAX_MSG;
103 write_unlock_irqrestore(&ksb->dbg_lock, flags);
104}
105
106static
107struct data_pkt *ksb_alloc_data_pkt(size_t count, gfp_t flags, void *ctxt)
108{
109 struct data_pkt *pkt;
110
111 pkt = kzalloc(sizeof(struct data_pkt), flags);
112 if (!pkt) {
113 pr_err("failed to allocate data packet\n");
114 return ERR_PTR(-ENOMEM);
115 }
116
117 pkt->buf = kmalloc(count, flags);
118 if (!pkt->buf) {
119 pr_err("failed to allocate data buffer\n");
120 kfree(pkt);
121 return ERR_PTR(-ENOMEM);
122 }
123
124 pkt->len = count;
125 INIT_LIST_HEAD(&pkt->list);
126 pkt->ctxt = ctxt;
127
128 return pkt;
129}
130
131static void ksb_free_data_pkt(struct data_pkt *pkt)
132{
133 kfree(pkt->buf);
134 kfree(pkt);
135}
136
137
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530138static void
139submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700140static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
141 size_t count, loff_t *pos)
142{
143 int ret;
144 unsigned long flags;
145 struct ks_bridge *ksb = fp->private_data;
146 struct data_pkt *pkt;
147 size_t space, copied;
148
149read_start:
150 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
151 return -ENODEV;
152
153 spin_lock_irqsave(&ksb->lock, flags);
154 if (list_empty(&ksb->to_ks_list)) {
155 spin_unlock_irqrestore(&ksb->lock, flags);
156 ret = wait_event_interruptible(ksb->ks_wait_q,
157 !list_empty(&ksb->to_ks_list) ||
158 !test_bit(USB_DEV_CONNECTED, &ksb->flags));
159 if (ret < 0)
160 return ret;
161
162 goto read_start;
163 }
164
165 space = count;
166 copied = 0;
167 while (!list_empty(&ksb->to_ks_list) && space) {
168 size_t len;
169
170 pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
Hemant Kumard45f96c2012-09-24 12:32:32 -0700171 len = min_t(size_t, space, pkt->len - pkt->n_read);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700172 spin_unlock_irqrestore(&ksb->lock, flags);
173
Hemant Kumard45f96c2012-09-24 12:32:32 -0700174 ret = copy_to_user(buf + copied, pkt->buf + pkt->n_read, len);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700175 if (ret) {
176 pr_err("copy_to_user failed err:%d\n", ret);
177 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700178 return ret;
179 }
180
Hemant Kumard45f96c2012-09-24 12:32:32 -0700181 pkt->n_read += len;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700182 space -= len;
183 copied += len;
184
185 spin_lock_irqsave(&ksb->lock, flags);
186 if (pkt->n_read == pkt->len) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530187 /*
188 * re-init the packet and queue it
189 * for more data.
190 */
Vamsi Krishna5b944712012-06-29 18:36:23 -0700191 list_del_init(&pkt->list);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530192 pkt->n_read = 0;
193 pkt->len = MAX_DATA_PKT_SIZE;
194 spin_unlock_irqrestore(&ksb->lock, flags);
195 submit_one_urb(ksb, GFP_KERNEL, pkt);
196 spin_lock_irqsave(&ksb->lock, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700197 }
198 }
199 spin_unlock_irqrestore(&ksb->lock, flags);
200
201 dbg_log_event(ksb, "KS_READ", copied, 0);
202
203 pr_debug("count:%d space:%d copied:%d", count, space, copied);
204
205 return copied;
206}
207
208static void ksb_tx_cb(struct urb *urb)
209{
210 struct data_pkt *pkt = urb->context;
211 struct ks_bridge *ksb = pkt->ctxt;
212
213 dbg_log_event(ksb, "C TX_URB", urb->status, 0);
214 pr_debug("status:%d", urb->status);
215
216 if (ksb->ifc)
217 usb_autopm_put_interface_async(ksb->ifc);
218
219 if (urb->status < 0)
220 pr_err_ratelimited("urb failed with err:%d", urb->status);
221
222 ksb_free_data_pkt(pkt);
223}
224
225static void ksb_tomdm_work(struct work_struct *w)
226{
227 struct ks_bridge *ksb = container_of(w, struct ks_bridge, to_mdm_work);
228 struct data_pkt *pkt;
229 unsigned long flags;
230 struct urb *urb;
231 int ret;
232
233 spin_lock_irqsave(&ksb->lock, flags);
234 while (!list_empty(&ksb->to_mdm_list)
235 && test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
236 pkt = list_first_entry(&ksb->to_mdm_list,
237 struct data_pkt, list);
238 list_del_init(&pkt->list);
239 spin_unlock_irqrestore(&ksb->lock, flags);
240
241 urb = usb_alloc_urb(0, GFP_KERNEL);
242 if (!urb) {
243 pr_err_ratelimited("unable to allocate urb");
244 ksb_free_data_pkt(pkt);
245 return;
246 }
247
248 ret = usb_autopm_get_interface(ksb->ifc);
249 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
250 pr_err_ratelimited("autopm_get failed:%d", ret);
251 usb_free_urb(urb);
252 ksb_free_data_pkt(pkt);
253 return;
254 }
255 usb_fill_bulk_urb(urb, ksb->udev, ksb->out_pipe,
256 pkt->buf, pkt->len, ksb_tx_cb, pkt);
257 usb_anchor_urb(urb, &ksb->submitted);
258
259 dbg_log_event(ksb, "S TX_URB", pkt->len, 0);
260
261 ret = usb_submit_urb(urb, GFP_KERNEL);
262 if (ret) {
263 pr_err("out urb submission failed");
264 usb_unanchor_urb(urb);
265 usb_free_urb(urb);
266 ksb_free_data_pkt(pkt);
267 usb_autopm_put_interface(ksb->ifc);
268 return;
269 }
270
Hemant Kumar9b230b52012-09-19 12:40:11 -0700271 usb_free_urb(urb);
272
Vamsi Krishna5b944712012-06-29 18:36:23 -0700273 spin_lock_irqsave(&ksb->lock, flags);
274 }
275 spin_unlock_irqrestore(&ksb->lock, flags);
276}
277
278static ssize_t ksb_fs_write(struct file *fp, const char __user *buf,
279 size_t count, loff_t *pos)
280{
281 int ret;
282 struct data_pkt *pkt;
283 unsigned long flags;
284 struct ks_bridge *ksb = fp->private_data;
285
286 pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
287 if (IS_ERR(pkt)) {
288 pr_err("unable to allocate data packet");
289 return PTR_ERR(pkt);
290 }
291
292 ret = copy_from_user(pkt->buf, buf, count);
293 if (ret) {
294 pr_err("copy_from_user failed: err:%d", ret);
295 ksb_free_data_pkt(pkt);
296 return ret;
297 }
298
299 spin_lock_irqsave(&ksb->lock, flags);
300 list_add_tail(&pkt->list, &ksb->to_mdm_list);
301 spin_unlock_irqrestore(&ksb->lock, flags);
302
303 queue_work(ksb->wq, &ksb->to_mdm_work);
304
305 return count;
306}
307
308static int efs_fs_open(struct inode *ip, struct file *fp)
309{
310 struct ks_bridge *ksb = __ksb[EFS_BRIDGE_INDEX];
311
312 pr_debug(":%s", ksb->name);
313 dbg_log_event(ksb, "EFS-FS-OPEN", 0, 0);
314
315 if (!ksb) {
316 pr_err("ksb is being removed");
317 return -ENODEV;
318 }
319
320 fp->private_data = ksb;
321 set_bit(FILE_OPENED, &ksb->flags);
322
323 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
324 queue_work(ksb->wq, &ksb->start_rx_work);
325
326 return 0;
327}
328
329static int ksb_fs_open(struct inode *ip, struct file *fp)
330{
331 struct ks_bridge *ksb = __ksb[BOOT_BRIDGE_INDEX];
332
333 pr_debug(":%s", ksb->name);
334 dbg_log_event(ksb, "KS-FS-OPEN", 0, 0);
335
336 if (!ksb) {
337 pr_err("ksb is being removed");
338 return -ENODEV;
339 }
340
341 fp->private_data = ksb;
342 set_bit(FILE_OPENED, &ksb->flags);
343
344 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
345 queue_work(ksb->wq, &ksb->start_rx_work);
346
347 return 0;
348}
349
350static int ksb_fs_release(struct inode *ip, struct file *fp)
351{
352 struct ks_bridge *ksb = fp->private_data;
353
354 pr_debug(":%s", ksb->name);
355 dbg_log_event(ksb, "FS-RELEASE", 0, 0);
356
357 clear_bit(FILE_OPENED, &ksb->flags);
358 fp->private_data = NULL;
359
360 return 0;
361}
362
363static const struct file_operations ksb_fops = {
364 .owner = THIS_MODULE,
365 .read = ksb_fs_read,
366 .write = ksb_fs_write,
367 .open = ksb_fs_open,
368 .release = ksb_fs_release,
369};
370
371static struct miscdevice ksb_fboot_dev = {
372 .minor = MISC_DYNAMIC_MINOR,
373 .name = "ks_bridge",
374 .fops = &ksb_fops,
375};
376
377static const struct file_operations efs_fops = {
378 .owner = THIS_MODULE,
379 .read = ksb_fs_read,
380 .write = ksb_fs_write,
381 .open = efs_fs_open,
382 .release = ksb_fs_release,
383};
384
385static struct miscdevice ksb_efs_dev = {
386 .minor = MISC_DYNAMIC_MINOR,
387 .name = "efs_bridge",
388 .fops = &efs_fops,
389};
390
391static const struct usb_device_id ksb_usb_ids[] = {
392 { USB_DEVICE(0x5c6, 0x9008),
393 .driver_info = (unsigned long)&ksb_fboot_dev, },
394 { USB_DEVICE(0x5c6, 0x9048),
395 .driver_info = (unsigned long)&ksb_efs_dev, },
396 { USB_DEVICE(0x5c6, 0x904C),
397 .driver_info = (unsigned long)&ksb_efs_dev, },
398
399 {} /* terminating entry */
400};
401MODULE_DEVICE_TABLE(usb, ksb_usb_ids);
402
403static void ksb_rx_cb(struct urb *urb);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530404static void
405submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700406{
Vamsi Krishna5b944712012-06-29 18:36:23 -0700407 struct urb *urb;
408 int ret;
409
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530410 urb = usb_alloc_urb(0, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700411 if (!urb) {
412 pr_err("unable to allocate urb");
413 ksb_free_data_pkt(pkt);
414 return;
415 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700416
417 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
418 pkt->buf, pkt->len,
419 ksb_rx_cb, pkt);
420 usb_anchor_urb(urb, &ksb->submitted);
421
422 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
423
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530424 ret = usb_submit_urb(urb, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700425 if (ret) {
426 pr_err("in urb submission failed");
427 usb_unanchor_urb(urb);
428 usb_free_urb(urb);
429 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700430 return;
431 }
432
433 usb_free_urb(urb);
434}
435static void ksb_rx_cb(struct urb *urb)
436{
437 struct data_pkt *pkt = urb->context;
438 struct ks_bridge *ksb = pkt->ctxt;
439
440 dbg_log_event(ksb, "C RX_URB", urb->status, urb->actual_length);
441
442 pr_debug("status:%d actual:%d", urb->status, urb->actual_length);
443
Hemant Kumara6194c12012-08-31 18:38:32 -0700444 /*non zero len of data received while unlinking urb*/
445 if (urb->status == -ENOENT && urb->actual_length > 0)
446 goto add_to_list;
447
Vamsi Krishna5b944712012-06-29 18:36:23 -0700448 if (urb->status < 0) {
Hemant Kumara6194c12012-08-31 18:38:32 -0700449 if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
450 && urb->status != -EPROTO)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700451 pr_err_ratelimited("urb failed with err:%d",
452 urb->status);
453 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700454 return;
455 }
456
457 if (urb->actual_length == 0) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530458 submit_one_urb(ksb, GFP_ATOMIC, pkt);
459 return;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700460 }
461
Hemant Kumara6194c12012-08-31 18:38:32 -0700462add_to_list:
Vamsi Krishna5b944712012-06-29 18:36:23 -0700463 spin_lock(&ksb->lock);
464 pkt->len = urb->actual_length;
465 list_add_tail(&pkt->list, &ksb->to_ks_list);
466 spin_unlock(&ksb->lock);
467
468 /* wake up read thread */
469 wake_up(&ksb->ks_wait_q);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700470}
471
472static void ksb_start_rx_work(struct work_struct *w)
473{
474 struct ks_bridge *ksb =
475 container_of(w, struct ks_bridge, start_rx_work);
476 struct data_pkt *pkt;
477 struct urb *urb;
478 int i = 0;
479 int ret;
480
481 for (i = 0; i < NO_RX_REQS; i++) {
482 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb);
483 if (IS_ERR(pkt)) {
484 pr_err("unable to allocate data pkt");
485 return;
486 }
487
488 urb = usb_alloc_urb(0, GFP_KERNEL);
489 if (!urb) {
490 pr_err("unable to allocate urb");
491 ksb_free_data_pkt(pkt);
492 return;
493 }
494
495 ret = usb_autopm_get_interface(ksb->ifc);
496 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
497 pr_err_ratelimited("autopm_get failed:%d", ret);
498 usb_free_urb(urb);
499 ksb_free_data_pkt(pkt);
500 return;
501 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700502
503 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
504 pkt->buf, pkt->len,
505 ksb_rx_cb, pkt);
506 usb_anchor_urb(urb, &ksb->submitted);
507
508 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
509
510 ret = usb_submit_urb(urb, GFP_KERNEL);
511 if (ret) {
512 pr_err("in urb submission failed");
513 usb_unanchor_urb(urb);
514 usb_free_urb(urb);
515 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700516 usb_autopm_put_interface(ksb->ifc);
517 return;
518 }
519
520 usb_autopm_put_interface_async(ksb->ifc);
521 usb_free_urb(urb);
522 }
523}
524
525static int
526ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
527{
528 __u8 ifc_num;
529 struct usb_host_interface *ifc_desc;
530 struct usb_endpoint_descriptor *ep_desc;
531 int i;
532 struct ks_bridge *ksb;
533 struct miscdevice *fs_dev;
534
535 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
536
537 switch (id->idProduct) {
538 case 0x9008:
539 if (ifc_num != 0)
540 return -ENODEV;
541 ksb = __ksb[BOOT_BRIDGE_INDEX];
542 break;
543 case 0x9048:
544 case 0x904C:
545 if (ifc_num != 2)
546 return -ENODEV;
547 ksb = __ksb[EFS_BRIDGE_INDEX];
548 break;
549 default:
550 return -ENODEV;
551 }
552
553 if (!ksb) {
554 pr_err("ksb is not initialized");
555 return -ENODEV;
556 }
557
558 ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
559 ksb->ifc = ifc;
560 ifc_desc = ifc->cur_altsetting;
561
562 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
563 ep_desc = &ifc_desc->endpoint[i].desc;
564
565 if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
566 ksb->in_epAddr = ep_desc->bEndpointAddress;
567
568 if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
569 ksb->out_epAddr = ep_desc->bEndpointAddress;
570 }
571
572 if (!(ksb->in_epAddr && ksb->out_epAddr)) {
573 pr_err("could not find bulk in and bulk out endpoints");
574 usb_put_dev(ksb->udev);
575 ksb->ifc = NULL;
576 return -ENODEV;
577 }
578
579 ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
580 ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);
581
582 usb_set_intfdata(ifc, ksb);
583 set_bit(USB_DEV_CONNECTED, &ksb->flags);
584
585 dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
586
587 fs_dev = (struct miscdevice *)id->driver_info;
588 misc_register(fs_dev);
589
Hemant Kumarf292a322012-09-07 19:00:21 -0700590 ifc->needs_remote_wakeup = 1;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700591 usb_enable_autosuspend(ksb->udev);
592
593 pr_debug("usb dev connected");
594
595 return 0;
596}
597
598static int ksb_usb_suspend(struct usb_interface *ifc, pm_message_t message)
599{
600 struct ks_bridge *ksb = usb_get_intfdata(ifc);
601
602 dbg_log_event(ksb, "SUSPEND", 0, 0);
603
Vamsi Krishna5b944712012-06-29 18:36:23 -0700604 usb_kill_anchored_urbs(&ksb->submitted);
605
606 return 0;
607}
608
609static int ksb_usb_resume(struct usb_interface *ifc)
610{
611 struct ks_bridge *ksb = usb_get_intfdata(ifc);
612
613 dbg_log_event(ksb, "RESUME", 0, 0);
614
615 if (test_bit(FILE_OPENED, &ksb->flags))
616 queue_work(ksb->wq, &ksb->start_rx_work);
617
618 return 0;
619}
620
621static void ksb_usb_disconnect(struct usb_interface *ifc)
622{
623 struct ks_bridge *ksb = usb_get_intfdata(ifc);
624 unsigned long flags;
625 struct data_pkt *pkt;
626
627 dbg_log_event(ksb, "PID-DETACH", 0, 0);
628
629 clear_bit(USB_DEV_CONNECTED, &ksb->flags);
630 wake_up(&ksb->ks_wait_q);
631 cancel_work_sync(&ksb->to_mdm_work);
632
633 usb_kill_anchored_urbs(&ksb->submitted);
634
635 spin_lock_irqsave(&ksb->lock, flags);
636 while (!list_empty(&ksb->to_ks_list)) {
637 pkt = list_first_entry(&ksb->to_ks_list,
638 struct data_pkt, list);
639 list_del_init(&pkt->list);
640 ksb_free_data_pkt(pkt);
641 }
642 while (!list_empty(&ksb->to_mdm_list)) {
643 pkt = list_first_entry(&ksb->to_mdm_list,
644 struct data_pkt, list);
645 list_del_init(&pkt->list);
646 ksb_free_data_pkt(pkt);
647 }
648 spin_unlock_irqrestore(&ksb->lock, flags);
649
Hemant Kumarf292a322012-09-07 19:00:21 -0700650 ifc->needs_remote_wakeup = 0;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700651 usb_put_dev(ksb->udev);
652 ksb->ifc = NULL;
653 usb_set_intfdata(ifc, NULL);
654
655 return;
656}
657
658static struct usb_driver ksb_usb_driver = {
659 .name = "ks_bridge",
660 .probe = ksb_usb_probe,
661 .disconnect = ksb_usb_disconnect,
662 .suspend = ksb_usb_suspend,
663 .resume = ksb_usb_resume,
664 .id_table = ksb_usb_ids,
665 .supports_autosuspend = 1,
666};
667
668static ssize_t ksb_debug_show(struct seq_file *s, void *unused)
669{
670 unsigned long flags;
671 struct ks_bridge *ksb = s->private;
672 int i;
673
674 read_lock_irqsave(&ksb->dbg_lock, flags);
675 for (i = 0; i < DBG_MAX_MSG; i++) {
676 if (i == (ksb->dbg_idx - 1))
677 seq_printf(s, "-->%s\n", ksb->dbgbuf[i]);
678 else
679 seq_printf(s, "%s\n", ksb->dbgbuf[i]);
680 }
681 read_unlock_irqrestore(&ksb->dbg_lock, flags);
682
683 return 0;
684}
685
686static int ksb_debug_open(struct inode *ip, struct file *fp)
687{
688 return single_open(fp, ksb_debug_show, ip->i_private);
689
690 return 0;
691}
692
693static const struct file_operations dbg_fops = {
694 .open = ksb_debug_open,
695 .read = seq_read,
696 .llseek = seq_lseek,
697 .release = single_release,
698};
699static struct dentry *dbg_dir;
700static int __init ksb_init(void)
701{
702 struct ks_bridge *ksb;
703 int num_instances = 0;
704 int ret = 0;
705 int i;
706
707 dbg_dir = debugfs_create_dir("ks_bridge", NULL);
708 if (IS_ERR(dbg_dir))
709 pr_err("unable to create debug dir");
710
711 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
712 ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
713 if (!ksb) {
714 pr_err("unable to allocat mem for ks_bridge");
715 return -ENOMEM;
716 }
717 __ksb[i] = ksb;
718
719 ksb->name = kasprintf(GFP_KERNEL, "ks_bridge:%i", i + 1);
720 if (!ksb->name) {
721 pr_info("unable to allocate name");
722 kfree(ksb);
723 ret = -ENOMEM;
724 goto dev_free;
725 }
726
727 spin_lock_init(&ksb->lock);
728 INIT_LIST_HEAD(&ksb->to_mdm_list);
729 INIT_LIST_HEAD(&ksb->to_ks_list);
730 init_waitqueue_head(&ksb->ks_wait_q);
731 ksb->wq = create_singlethread_workqueue(ksb->name);
732 if (!ksb->wq) {
733 pr_err("unable to allocate workqueue");
734 kfree(ksb->name);
735 kfree(ksb);
736 ret = -ENOMEM;
737 goto dev_free;
738 }
739
740 INIT_WORK(&ksb->to_mdm_work, ksb_tomdm_work);
741 INIT_WORK(&ksb->start_rx_work, ksb_start_rx_work);
742 init_usb_anchor(&ksb->submitted);
743
744 ksb->dbg_idx = 0;
745 ksb->dbg_lock = __RW_LOCK_UNLOCKED(lck);
746
747 if (!IS_ERR(dbg_dir))
748 debugfs_create_file(ksb->name, S_IRUGO, dbg_dir,
749 ksb, &dbg_fops);
750
751 num_instances++;
752 }
753
754 ret = usb_register(&ksb_usb_driver);
755 if (ret) {
756 pr_err("unable to register ks bridge driver");
757 goto dev_free;
758 }
759
760 pr_info("init done");
761
762 return 0;
763
764dev_free:
765 if (!IS_ERR(dbg_dir))
766 debugfs_remove_recursive(dbg_dir);
767
768 for (i = 0; i < num_instances; i++) {
769 ksb = __ksb[i];
770
771 destroy_workqueue(ksb->wq);
772 kfree(ksb->name);
773 kfree(ksb);
774 }
775
776 return ret;
777
778}
779
780static void __exit ksb_exit(void)
781{
782 struct ks_bridge *ksb;
783 int i;
784
785 if (!IS_ERR(dbg_dir))
786 debugfs_remove_recursive(dbg_dir);
787
788 usb_deregister(&ksb_usb_driver);
789
790 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
791 ksb = __ksb[i];
792
793 destroy_workqueue(ksb->wq);
794 kfree(ksb->name);
795 kfree(ksb);
796 }
797}
798
799module_init(ksb_init);
800module_exit(ksb_exit);
801
802MODULE_DESCRIPTION(DRIVER_DESC);
803MODULE_VERSION(DRIVER_VERSION);
804MODULE_LICENSE("GPL v2");