blob: c91cd684d2bf754088caf628004a7ff8e30b4518 [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;
72 unsigned int alloced_read_pkts;
73
74#define DBG_MSG_LEN 40
75#define DBG_MAX_MSG 500
76 unsigned int dbg_idx;
77 rwlock_t dbg_lock;
78 char (dbgbuf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
79};
80struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES];
81
82/* by default debugging is enabled */
83static unsigned int enable_dbg = 1;
84module_param(enable_dbg, uint, S_IRUGO | S_IWUSR);
85
86static void
87dbg_log_event(struct ks_bridge *ksb, char *event, int d1, int d2)
88{
89 unsigned long flags;
90 unsigned long long t;
91 unsigned long nanosec;
92
93 if (!enable_dbg)
94 return;
95
96 write_lock_irqsave(&ksb->dbg_lock, flags);
97 t = cpu_clock(smp_processor_id());
98 nanosec = do_div(t, 1000000000)/1000;
99 scnprintf(ksb->dbgbuf[ksb->dbg_idx], DBG_MSG_LEN, "%5lu.%06lu:%s:%x:%x",
100 (unsigned long)t, nanosec, event, d1, d2);
101
102 ksb->dbg_idx++;
103 ksb->dbg_idx = ksb->dbg_idx % DBG_MAX_MSG;
104 write_unlock_irqrestore(&ksb->dbg_lock, flags);
105}
106
107static
108struct data_pkt *ksb_alloc_data_pkt(size_t count, gfp_t flags, void *ctxt)
109{
110 struct data_pkt *pkt;
111
112 pkt = kzalloc(sizeof(struct data_pkt), flags);
113 if (!pkt) {
114 pr_err("failed to allocate data packet\n");
115 return ERR_PTR(-ENOMEM);
116 }
117
118 pkt->buf = kmalloc(count, flags);
119 if (!pkt->buf) {
120 pr_err("failed to allocate data buffer\n");
121 kfree(pkt);
122 return ERR_PTR(-ENOMEM);
123 }
124
125 pkt->len = count;
126 INIT_LIST_HEAD(&pkt->list);
127 pkt->ctxt = ctxt;
128
129 return pkt;
130}
131
132static void ksb_free_data_pkt(struct data_pkt *pkt)
133{
134 kfree(pkt->buf);
135 kfree(pkt);
136}
137
138
139static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
140 size_t count, loff_t *pos)
141{
142 int ret;
143 unsigned long flags;
144 struct ks_bridge *ksb = fp->private_data;
145 struct data_pkt *pkt;
146 size_t space, copied;
147
148read_start:
149 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
150 return -ENODEV;
151
152 spin_lock_irqsave(&ksb->lock, flags);
153 if (list_empty(&ksb->to_ks_list)) {
154 spin_unlock_irqrestore(&ksb->lock, flags);
155 ret = wait_event_interruptible(ksb->ks_wait_q,
156 !list_empty(&ksb->to_ks_list) ||
157 !test_bit(USB_DEV_CONNECTED, &ksb->flags));
158 if (ret < 0)
159 return ret;
160
161 goto read_start;
162 }
163
164 space = count;
165 copied = 0;
166 while (!list_empty(&ksb->to_ks_list) && space) {
167 size_t len;
168
169 pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
Hemant Kumard45f96c2012-09-24 12:32:32 -0700170 len = min_t(size_t, space, pkt->len - pkt->n_read);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700171 spin_unlock_irqrestore(&ksb->lock, flags);
172
Hemant Kumard45f96c2012-09-24 12:32:32 -0700173 ret = copy_to_user(buf + copied, pkt->buf + pkt->n_read, len);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700174 if (ret) {
175 pr_err("copy_to_user failed err:%d\n", ret);
176 ksb_free_data_pkt(pkt);
177 ksb->alloced_read_pkts--;
178 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) {
187 list_del_init(&pkt->list);
188 ksb_free_data_pkt(pkt);
189 ksb->alloced_read_pkts--;
190 }
191 }
192 spin_unlock_irqrestore(&ksb->lock, flags);
193
194 dbg_log_event(ksb, "KS_READ", copied, 0);
195
196 pr_debug("count:%d space:%d copied:%d", count, space, copied);
197
198 return copied;
199}
200
201static void ksb_tx_cb(struct urb *urb)
202{
203 struct data_pkt *pkt = urb->context;
204 struct ks_bridge *ksb = pkt->ctxt;
205
206 dbg_log_event(ksb, "C TX_URB", urb->status, 0);
207 pr_debug("status:%d", urb->status);
208
209 if (ksb->ifc)
210 usb_autopm_put_interface_async(ksb->ifc);
211
212 if (urb->status < 0)
213 pr_err_ratelimited("urb failed with err:%d", urb->status);
214
215 ksb_free_data_pkt(pkt);
216}
217
218static void ksb_tomdm_work(struct work_struct *w)
219{
220 struct ks_bridge *ksb = container_of(w, struct ks_bridge, to_mdm_work);
221 struct data_pkt *pkt;
222 unsigned long flags;
223 struct urb *urb;
224 int ret;
225
226 spin_lock_irqsave(&ksb->lock, flags);
227 while (!list_empty(&ksb->to_mdm_list)
228 && test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
229 pkt = list_first_entry(&ksb->to_mdm_list,
230 struct data_pkt, list);
231 list_del_init(&pkt->list);
232 spin_unlock_irqrestore(&ksb->lock, flags);
233
234 urb = usb_alloc_urb(0, GFP_KERNEL);
235 if (!urb) {
236 pr_err_ratelimited("unable to allocate urb");
237 ksb_free_data_pkt(pkt);
238 return;
239 }
240
241 ret = usb_autopm_get_interface(ksb->ifc);
242 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
243 pr_err_ratelimited("autopm_get failed:%d", ret);
244 usb_free_urb(urb);
245 ksb_free_data_pkt(pkt);
246 return;
247 }
248 usb_fill_bulk_urb(urb, ksb->udev, ksb->out_pipe,
249 pkt->buf, pkt->len, ksb_tx_cb, pkt);
250 usb_anchor_urb(urb, &ksb->submitted);
251
252 dbg_log_event(ksb, "S TX_URB", pkt->len, 0);
253
254 ret = usb_submit_urb(urb, GFP_KERNEL);
255 if (ret) {
256 pr_err("out urb submission failed");
257 usb_unanchor_urb(urb);
258 usb_free_urb(urb);
259 ksb_free_data_pkt(pkt);
260 usb_autopm_put_interface(ksb->ifc);
261 return;
262 }
263
Hemant Kumar9b230b52012-09-19 12:40:11 -0700264 usb_free_urb(urb);
265
Vamsi Krishna5b944712012-06-29 18:36:23 -0700266 spin_lock_irqsave(&ksb->lock, flags);
267 }
268 spin_unlock_irqrestore(&ksb->lock, flags);
269}
270
271static ssize_t ksb_fs_write(struct file *fp, const char __user *buf,
272 size_t count, loff_t *pos)
273{
274 int ret;
275 struct data_pkt *pkt;
276 unsigned long flags;
277 struct ks_bridge *ksb = fp->private_data;
278
279 pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
280 if (IS_ERR(pkt)) {
281 pr_err("unable to allocate data packet");
282 return PTR_ERR(pkt);
283 }
284
285 ret = copy_from_user(pkt->buf, buf, count);
286 if (ret) {
287 pr_err("copy_from_user failed: err:%d", ret);
288 ksb_free_data_pkt(pkt);
289 return ret;
290 }
291
292 spin_lock_irqsave(&ksb->lock, flags);
293 list_add_tail(&pkt->list, &ksb->to_mdm_list);
294 spin_unlock_irqrestore(&ksb->lock, flags);
295
296 queue_work(ksb->wq, &ksb->to_mdm_work);
297
298 return count;
299}
300
301static int efs_fs_open(struct inode *ip, struct file *fp)
302{
303 struct ks_bridge *ksb = __ksb[EFS_BRIDGE_INDEX];
304
305 pr_debug(":%s", ksb->name);
306 dbg_log_event(ksb, "EFS-FS-OPEN", 0, 0);
307
308 if (!ksb) {
309 pr_err("ksb is being removed");
310 return -ENODEV;
311 }
312
313 fp->private_data = ksb;
314 set_bit(FILE_OPENED, &ksb->flags);
315
316 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
317 queue_work(ksb->wq, &ksb->start_rx_work);
318
319 return 0;
320}
321
322static int ksb_fs_open(struct inode *ip, struct file *fp)
323{
324 struct ks_bridge *ksb = __ksb[BOOT_BRIDGE_INDEX];
325
326 pr_debug(":%s", ksb->name);
327 dbg_log_event(ksb, "KS-FS-OPEN", 0, 0);
328
329 if (!ksb) {
330 pr_err("ksb is being removed");
331 return -ENODEV;
332 }
333
334 fp->private_data = ksb;
335 set_bit(FILE_OPENED, &ksb->flags);
336
337 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
338 queue_work(ksb->wq, &ksb->start_rx_work);
339
340 return 0;
341}
342
343static int ksb_fs_release(struct inode *ip, struct file *fp)
344{
345 struct ks_bridge *ksb = fp->private_data;
346
347 pr_debug(":%s", ksb->name);
348 dbg_log_event(ksb, "FS-RELEASE", 0, 0);
349
350 clear_bit(FILE_OPENED, &ksb->flags);
351 fp->private_data = NULL;
352
353 return 0;
354}
355
356static const struct file_operations ksb_fops = {
357 .owner = THIS_MODULE,
358 .read = ksb_fs_read,
359 .write = ksb_fs_write,
360 .open = ksb_fs_open,
361 .release = ksb_fs_release,
362};
363
364static struct miscdevice ksb_fboot_dev = {
365 .minor = MISC_DYNAMIC_MINOR,
366 .name = "ks_bridge",
367 .fops = &ksb_fops,
368};
369
370static const struct file_operations efs_fops = {
371 .owner = THIS_MODULE,
372 .read = ksb_fs_read,
373 .write = ksb_fs_write,
374 .open = efs_fs_open,
375 .release = ksb_fs_release,
376};
377
378static struct miscdevice ksb_efs_dev = {
379 .minor = MISC_DYNAMIC_MINOR,
380 .name = "efs_bridge",
381 .fops = &efs_fops,
382};
383
384static const struct usb_device_id ksb_usb_ids[] = {
385 { USB_DEVICE(0x5c6, 0x9008),
386 .driver_info = (unsigned long)&ksb_fboot_dev, },
387 { USB_DEVICE(0x5c6, 0x9048),
388 .driver_info = (unsigned long)&ksb_efs_dev, },
389 { USB_DEVICE(0x5c6, 0x904C),
390 .driver_info = (unsigned long)&ksb_efs_dev, },
391
392 {} /* terminating entry */
393};
394MODULE_DEVICE_TABLE(usb, ksb_usb_ids);
395
396static void ksb_rx_cb(struct urb *urb);
397static void submit_one_urb(struct ks_bridge *ksb)
398{
399 struct data_pkt *pkt;
400 struct urb *urb;
401 int ret;
402
403 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_ATOMIC, ksb);
404 if (IS_ERR(pkt)) {
405 pr_err("unable to allocate data pkt");
406 return;
407 }
408
409 urb = usb_alloc_urb(0, GFP_ATOMIC);
410 if (!urb) {
411 pr_err("unable to allocate urb");
412 ksb_free_data_pkt(pkt);
413 return;
414 }
415 ksb->alloced_read_pkts++;
416
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
424 ret = usb_submit_urb(urb, GFP_ATOMIC);
425 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);
430 ksb->alloced_read_pkts--;
431 return;
432 }
433
434 usb_free_urb(urb);
435}
436static void ksb_rx_cb(struct urb *urb)
437{
438 struct data_pkt *pkt = urb->context;
439 struct ks_bridge *ksb = pkt->ctxt;
440
441 dbg_log_event(ksb, "C RX_URB", urb->status, urb->actual_length);
442
443 pr_debug("status:%d actual:%d", urb->status, urb->actual_length);
444
Hemant Kumara6194c12012-08-31 18:38:32 -0700445 /*non zero len of data received while unlinking urb*/
446 if (urb->status == -ENOENT && urb->actual_length > 0)
447 goto add_to_list;
448
Vamsi Krishna5b944712012-06-29 18:36:23 -0700449 if (urb->status < 0) {
Hemant Kumara6194c12012-08-31 18:38:32 -0700450 if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
451 && urb->status != -EPROTO)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700452 pr_err_ratelimited("urb failed with err:%d",
453 urb->status);
454 ksb_free_data_pkt(pkt);
455 ksb->alloced_read_pkts--;
456 return;
457 }
458
459 if (urb->actual_length == 0) {
460 ksb_free_data_pkt(pkt);
461 ksb->alloced_read_pkts--;
462 goto resubmit_urb;
463 }
464
Hemant Kumara6194c12012-08-31 18:38:32 -0700465add_to_list:
Vamsi Krishna5b944712012-06-29 18:36:23 -0700466 spin_lock(&ksb->lock);
467 pkt->len = urb->actual_length;
468 list_add_tail(&pkt->list, &ksb->to_ks_list);
469 spin_unlock(&ksb->lock);
470
471 /* wake up read thread */
472 wake_up(&ksb->ks_wait_q);
473
474resubmit_urb:
475 submit_one_urb(ksb);
476
477}
478
479static void ksb_start_rx_work(struct work_struct *w)
480{
481 struct ks_bridge *ksb =
482 container_of(w, struct ks_bridge, start_rx_work);
483 struct data_pkt *pkt;
484 struct urb *urb;
485 int i = 0;
486 int ret;
487
488 for (i = 0; i < NO_RX_REQS; i++) {
489 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb);
490 if (IS_ERR(pkt)) {
491 pr_err("unable to allocate data pkt");
492 return;
493 }
494
495 urb = usb_alloc_urb(0, GFP_KERNEL);
496 if (!urb) {
497 pr_err("unable to allocate urb");
498 ksb_free_data_pkt(pkt);
499 return;
500 }
501
502 ret = usb_autopm_get_interface(ksb->ifc);
503 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
504 pr_err_ratelimited("autopm_get failed:%d", ret);
505 usb_free_urb(urb);
506 ksb_free_data_pkt(pkt);
507 return;
508 }
509 ksb->alloced_read_pkts++;
510
511 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
512 pkt->buf, pkt->len,
513 ksb_rx_cb, pkt);
514 usb_anchor_urb(urb, &ksb->submitted);
515
516 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
517
518 ret = usb_submit_urb(urb, GFP_KERNEL);
519 if (ret) {
520 pr_err("in urb submission failed");
521 usb_unanchor_urb(urb);
522 usb_free_urb(urb);
523 ksb_free_data_pkt(pkt);
524 ksb->alloced_read_pkts--;
525 usb_autopm_put_interface(ksb->ifc);
526 return;
527 }
528
529 usb_autopm_put_interface_async(ksb->ifc);
530 usb_free_urb(urb);
531 }
532}
533
534static int
535ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
536{
537 __u8 ifc_num;
538 struct usb_host_interface *ifc_desc;
539 struct usb_endpoint_descriptor *ep_desc;
540 int i;
541 struct ks_bridge *ksb;
542 struct miscdevice *fs_dev;
543
544 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
545
546 switch (id->idProduct) {
547 case 0x9008:
548 if (ifc_num != 0)
549 return -ENODEV;
550 ksb = __ksb[BOOT_BRIDGE_INDEX];
551 break;
552 case 0x9048:
553 case 0x904C:
554 if (ifc_num != 2)
555 return -ENODEV;
556 ksb = __ksb[EFS_BRIDGE_INDEX];
557 break;
558 default:
559 return -ENODEV;
560 }
561
562 if (!ksb) {
563 pr_err("ksb is not initialized");
564 return -ENODEV;
565 }
566
567 ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
568 ksb->ifc = ifc;
569 ifc_desc = ifc->cur_altsetting;
570
571 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
572 ep_desc = &ifc_desc->endpoint[i].desc;
573
574 if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
575 ksb->in_epAddr = ep_desc->bEndpointAddress;
576
577 if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
578 ksb->out_epAddr = ep_desc->bEndpointAddress;
579 }
580
581 if (!(ksb->in_epAddr && ksb->out_epAddr)) {
582 pr_err("could not find bulk in and bulk out endpoints");
583 usb_put_dev(ksb->udev);
584 ksb->ifc = NULL;
585 return -ENODEV;
586 }
587
588 ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
589 ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);
590
591 usb_set_intfdata(ifc, ksb);
592 set_bit(USB_DEV_CONNECTED, &ksb->flags);
593
594 dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
595
596 fs_dev = (struct miscdevice *)id->driver_info;
597 misc_register(fs_dev);
598
Hemant Kumarf292a322012-09-07 19:00:21 -0700599 ifc->needs_remote_wakeup = 1;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700600 usb_enable_autosuspend(ksb->udev);
601
602 pr_debug("usb dev connected");
603
604 return 0;
605}
606
607static int ksb_usb_suspend(struct usb_interface *ifc, pm_message_t message)
608{
609 struct ks_bridge *ksb = usb_get_intfdata(ifc);
610
611 dbg_log_event(ksb, "SUSPEND", 0, 0);
612
Hemant Kumara6194c12012-08-31 18:38:32 -0700613 pr_debug("read cnt: %d", ksb->alloced_read_pkts);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700614
615 usb_kill_anchored_urbs(&ksb->submitted);
616
617 return 0;
618}
619
620static int ksb_usb_resume(struct usb_interface *ifc)
621{
622 struct ks_bridge *ksb = usb_get_intfdata(ifc);
623
624 dbg_log_event(ksb, "RESUME", 0, 0);
625
626 if (test_bit(FILE_OPENED, &ksb->flags))
627 queue_work(ksb->wq, &ksb->start_rx_work);
628
629 return 0;
630}
631
632static void ksb_usb_disconnect(struct usb_interface *ifc)
633{
634 struct ks_bridge *ksb = usb_get_intfdata(ifc);
635 unsigned long flags;
636 struct data_pkt *pkt;
637
638 dbg_log_event(ksb, "PID-DETACH", 0, 0);
639
640 clear_bit(USB_DEV_CONNECTED, &ksb->flags);
641 wake_up(&ksb->ks_wait_q);
642 cancel_work_sync(&ksb->to_mdm_work);
643
644 usb_kill_anchored_urbs(&ksb->submitted);
645
646 spin_lock_irqsave(&ksb->lock, flags);
647 while (!list_empty(&ksb->to_ks_list)) {
648 pkt = list_first_entry(&ksb->to_ks_list,
649 struct data_pkt, list);
650 list_del_init(&pkt->list);
651 ksb_free_data_pkt(pkt);
652 }
653 while (!list_empty(&ksb->to_mdm_list)) {
654 pkt = list_first_entry(&ksb->to_mdm_list,
655 struct data_pkt, list);
656 list_del_init(&pkt->list);
657 ksb_free_data_pkt(pkt);
658 }
659 spin_unlock_irqrestore(&ksb->lock, flags);
660
Hemant Kumarf292a322012-09-07 19:00:21 -0700661 ifc->needs_remote_wakeup = 0;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700662 usb_put_dev(ksb->udev);
663 ksb->ifc = NULL;
664 usb_set_intfdata(ifc, NULL);
665
666 return;
667}
668
669static struct usb_driver ksb_usb_driver = {
670 .name = "ks_bridge",
671 .probe = ksb_usb_probe,
672 .disconnect = ksb_usb_disconnect,
673 .suspend = ksb_usb_suspend,
674 .resume = ksb_usb_resume,
675 .id_table = ksb_usb_ids,
676 .supports_autosuspend = 1,
677};
678
679static ssize_t ksb_debug_show(struct seq_file *s, void *unused)
680{
681 unsigned long flags;
682 struct ks_bridge *ksb = s->private;
683 int i;
684
685 read_lock_irqsave(&ksb->dbg_lock, flags);
686 for (i = 0; i < DBG_MAX_MSG; i++) {
687 if (i == (ksb->dbg_idx - 1))
688 seq_printf(s, "-->%s\n", ksb->dbgbuf[i]);
689 else
690 seq_printf(s, "%s\n", ksb->dbgbuf[i]);
691 }
692 read_unlock_irqrestore(&ksb->dbg_lock, flags);
693
694 return 0;
695}
696
697static int ksb_debug_open(struct inode *ip, struct file *fp)
698{
699 return single_open(fp, ksb_debug_show, ip->i_private);
700
701 return 0;
702}
703
704static const struct file_operations dbg_fops = {
705 .open = ksb_debug_open,
706 .read = seq_read,
707 .llseek = seq_lseek,
708 .release = single_release,
709};
710static struct dentry *dbg_dir;
711static int __init ksb_init(void)
712{
713 struct ks_bridge *ksb;
714 int num_instances = 0;
715 int ret = 0;
716 int i;
717
718 dbg_dir = debugfs_create_dir("ks_bridge", NULL);
719 if (IS_ERR(dbg_dir))
720 pr_err("unable to create debug dir");
721
722 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
723 ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
724 if (!ksb) {
725 pr_err("unable to allocat mem for ks_bridge");
726 return -ENOMEM;
727 }
728 __ksb[i] = ksb;
729
730 ksb->name = kasprintf(GFP_KERNEL, "ks_bridge:%i", i + 1);
731 if (!ksb->name) {
732 pr_info("unable to allocate name");
733 kfree(ksb);
734 ret = -ENOMEM;
735 goto dev_free;
736 }
737
738 spin_lock_init(&ksb->lock);
739 INIT_LIST_HEAD(&ksb->to_mdm_list);
740 INIT_LIST_HEAD(&ksb->to_ks_list);
741 init_waitqueue_head(&ksb->ks_wait_q);
742 ksb->wq = create_singlethread_workqueue(ksb->name);
743 if (!ksb->wq) {
744 pr_err("unable to allocate workqueue");
745 kfree(ksb->name);
746 kfree(ksb);
747 ret = -ENOMEM;
748 goto dev_free;
749 }
750
751 INIT_WORK(&ksb->to_mdm_work, ksb_tomdm_work);
752 INIT_WORK(&ksb->start_rx_work, ksb_start_rx_work);
753 init_usb_anchor(&ksb->submitted);
754
755 ksb->dbg_idx = 0;
756 ksb->dbg_lock = __RW_LOCK_UNLOCKED(lck);
757
758 if (!IS_ERR(dbg_dir))
759 debugfs_create_file(ksb->name, S_IRUGO, dbg_dir,
760 ksb, &dbg_fops);
761
762 num_instances++;
763 }
764
765 ret = usb_register(&ksb_usb_driver);
766 if (ret) {
767 pr_err("unable to register ks bridge driver");
768 goto dev_free;
769 }
770
771 pr_info("init done");
772
773 return 0;
774
775dev_free:
776 if (!IS_ERR(dbg_dir))
777 debugfs_remove_recursive(dbg_dir);
778
779 for (i = 0; i < num_instances; i++) {
780 ksb = __ksb[i];
781
782 destroy_workqueue(ksb->wq);
783 kfree(ksb->name);
784 kfree(ksb);
785 }
786
787 return ret;
788
789}
790
791static void __exit ksb_exit(void)
792{
793 struct ks_bridge *ksb;
794 int i;
795
796 if (!IS_ERR(dbg_dir))
797 debugfs_remove_recursive(dbg_dir);
798
799 usb_deregister(&ksb_usb_driver);
800
801 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
802 ksb = __ksb[i];
803
804 destroy_workqueue(ksb->wq);
805 kfree(ksb->name);
806 kfree(ksb);
807 }
808}
809
810module_init(ksb_init);
811module_exit(ksb_exit);
812
813MODULE_DESCRIPTION(DRIVER_DESC);
814MODULE_VERSION(DRIVER_VERSION);
815MODULE_LICENSE("GPL v2");