blob: e5062fb02c2e063da346d0fffc9db7102483e983 [file] [log] [blame]
Vamsi Krishna5b944712012-06-29 18:36:23 -07001/*
Pavankumar Kondeti4fde7d42012-12-28 17:15:41 +05302 * Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
Vamsi Krishna5b944712012-06-29 18:36:23 -07003 *
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
Hemant Kumar54aeb822013-01-16 18:55:14 -080036enum bus_id {
37 BUS_HSIC,
38 BUS_USB,
39 BUS_UNDEF,
40};
41
42#define BUSNAME_LEN 20
43
44static enum bus_id str_to_busid(const char *name)
45{
46 if (!strncasecmp("msm_hsic_host", name, BUSNAME_LEN))
47 return BUS_HSIC;
48 if (!strncasecmp("msm_ehci_host.0", name, BUSNAME_LEN))
49 return BUS_USB;
50
51 return BUS_UNDEF;
52}
53
Vamsi Krishna5b944712012-06-29 18:36:23 -070054struct data_pkt {
55 int n_read;
56 char *buf;
57 size_t len;
58 struct list_head list;
59 void *ctxt;
60};
61
62#define FILE_OPENED BIT(0)
63#define USB_DEV_CONNECTED BIT(1)
64#define NO_RX_REQS 10
Hemant Kumar54aeb822013-01-16 18:55:14 -080065#define NO_BRIDGE_INSTANCES 4
66#define EFS_HSIC_BRIDGE_INDEX 2
67#define EFS_USB_BRIDGE_INDEX 3
Vamsi Krishna5b944712012-06-29 18:36:23 -070068#define MAX_DATA_PKT_SIZE 16384
69
70struct ks_bridge {
71 char *name;
72 spinlock_t lock;
73 struct workqueue_struct *wq;
74 struct work_struct to_mdm_work;
75 struct work_struct start_rx_work;
76 struct list_head to_mdm_list;
77 struct list_head to_ks_list;
78 wait_queue_head_t ks_wait_q;
Hemant Kumar54aeb822013-01-16 18:55:14 -080079 struct miscdevice fs_dev;
Vamsi Krishna5b944712012-06-29 18:36:23 -070080
81 /* usb specific */
82 struct usb_device *udev;
83 struct usb_interface *ifc;
84 __u8 in_epAddr;
85 __u8 out_epAddr;
86 unsigned int in_pipe;
87 unsigned int out_pipe;
88 struct usb_anchor submitted;
89
90 unsigned long flags;
Vamsi Krishna5b944712012-06-29 18:36:23 -070091
92#define DBG_MSG_LEN 40
93#define DBG_MAX_MSG 500
94 unsigned int dbg_idx;
95 rwlock_t dbg_lock;
96 char (dbgbuf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
97};
98struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES];
99
100/* by default debugging is enabled */
101static unsigned int enable_dbg = 1;
102module_param(enable_dbg, uint, S_IRUGO | S_IWUSR);
103
104static void
105dbg_log_event(struct ks_bridge *ksb, char *event, int d1, int d2)
106{
107 unsigned long flags;
108 unsigned long long t;
109 unsigned long nanosec;
110
111 if (!enable_dbg)
112 return;
113
114 write_lock_irqsave(&ksb->dbg_lock, flags);
115 t = cpu_clock(smp_processor_id());
116 nanosec = do_div(t, 1000000000)/1000;
117 scnprintf(ksb->dbgbuf[ksb->dbg_idx], DBG_MSG_LEN, "%5lu.%06lu:%s:%x:%x",
118 (unsigned long)t, nanosec, event, d1, d2);
119
120 ksb->dbg_idx++;
121 ksb->dbg_idx = ksb->dbg_idx % DBG_MAX_MSG;
122 write_unlock_irqrestore(&ksb->dbg_lock, flags);
123}
124
125static
126struct data_pkt *ksb_alloc_data_pkt(size_t count, gfp_t flags, void *ctxt)
127{
128 struct data_pkt *pkt;
129
130 pkt = kzalloc(sizeof(struct data_pkt), flags);
131 if (!pkt) {
132 pr_err("failed to allocate data packet\n");
133 return ERR_PTR(-ENOMEM);
134 }
135
136 pkt->buf = kmalloc(count, flags);
137 if (!pkt->buf) {
138 pr_err("failed to allocate data buffer\n");
139 kfree(pkt);
140 return ERR_PTR(-ENOMEM);
141 }
142
143 pkt->len = count;
144 INIT_LIST_HEAD(&pkt->list);
145 pkt->ctxt = ctxt;
146
147 return pkt;
148}
149
150static void ksb_free_data_pkt(struct data_pkt *pkt)
151{
152 kfree(pkt->buf);
153 kfree(pkt);
154}
155
156
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530157static void
158submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700159static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
160 size_t count, loff_t *pos)
161{
162 int ret;
163 unsigned long flags;
164 struct ks_bridge *ksb = fp->private_data;
165 struct data_pkt *pkt;
166 size_t space, copied;
167
168read_start:
169 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
170 return -ENODEV;
171
172 spin_lock_irqsave(&ksb->lock, flags);
173 if (list_empty(&ksb->to_ks_list)) {
174 spin_unlock_irqrestore(&ksb->lock, flags);
175 ret = wait_event_interruptible(ksb->ks_wait_q,
176 !list_empty(&ksb->to_ks_list) ||
177 !test_bit(USB_DEV_CONNECTED, &ksb->flags));
178 if (ret < 0)
179 return ret;
180
181 goto read_start;
182 }
183
184 space = count;
185 copied = 0;
186 while (!list_empty(&ksb->to_ks_list) && space) {
187 size_t len;
188
189 pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
Hemant Kumard45f96c2012-09-24 12:32:32 -0700190 len = min_t(size_t, space, pkt->len - pkt->n_read);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700191 spin_unlock_irqrestore(&ksb->lock, flags);
192
Hemant Kumard45f96c2012-09-24 12:32:32 -0700193 ret = copy_to_user(buf + copied, pkt->buf + pkt->n_read, len);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700194 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800195 dev_err(ksb->fs_dev.this_device,
196 "copy_to_user failed err:%d\n", ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700197 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700198 return ret;
199 }
200
Hemant Kumard45f96c2012-09-24 12:32:32 -0700201 pkt->n_read += len;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700202 space -= len;
203 copied += len;
204
205 spin_lock_irqsave(&ksb->lock, flags);
206 if (pkt->n_read == pkt->len) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530207 /*
208 * re-init the packet and queue it
209 * for more data.
210 */
Vamsi Krishna5b944712012-06-29 18:36:23 -0700211 list_del_init(&pkt->list);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530212 pkt->n_read = 0;
213 pkt->len = MAX_DATA_PKT_SIZE;
214 spin_unlock_irqrestore(&ksb->lock, flags);
215 submit_one_urb(ksb, GFP_KERNEL, pkt);
216 spin_lock_irqsave(&ksb->lock, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700217 }
218 }
219 spin_unlock_irqrestore(&ksb->lock, flags);
220
221 dbg_log_event(ksb, "KS_READ", copied, 0);
222
Hemant Kumar54aeb822013-01-16 18:55:14 -0800223 dev_dbg(ksb->fs_dev.this_device, "count:%d space:%d copied:%d", count,
224 space, copied);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700225
226 return copied;
227}
228
229static void ksb_tx_cb(struct urb *urb)
230{
231 struct data_pkt *pkt = urb->context;
232 struct ks_bridge *ksb = pkt->ctxt;
233
234 dbg_log_event(ksb, "C TX_URB", urb->status, 0);
Hemant Kumar54aeb822013-01-16 18:55:14 -0800235 dev_dbg(&ksb->udev->dev, "status:%d", urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700236
237 if (ksb->ifc)
238 usb_autopm_put_interface_async(ksb->ifc);
239
240 if (urb->status < 0)
Hemant Kumar54aeb822013-01-16 18:55:14 -0800241 pr_err_ratelimited("%s: urb failed with err:%d",
242 ksb->fs_dev.name, urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700243
244 ksb_free_data_pkt(pkt);
245}
246
247static void ksb_tomdm_work(struct work_struct *w)
248{
249 struct ks_bridge *ksb = container_of(w, struct ks_bridge, to_mdm_work);
250 struct data_pkt *pkt;
251 unsigned long flags;
252 struct urb *urb;
253 int ret;
254
255 spin_lock_irqsave(&ksb->lock, flags);
256 while (!list_empty(&ksb->to_mdm_list)
257 && test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
258 pkt = list_first_entry(&ksb->to_mdm_list,
259 struct data_pkt, list);
260 list_del_init(&pkt->list);
261 spin_unlock_irqrestore(&ksb->lock, flags);
262
263 urb = usb_alloc_urb(0, GFP_KERNEL);
264 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800265 pr_err_ratelimited("%s: unable to allocate urb",
266 ksb->fs_dev.name);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700267 ksb_free_data_pkt(pkt);
268 return;
269 }
270
271 ret = usb_autopm_get_interface(ksb->ifc);
272 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800273 pr_err_ratelimited("%s: autopm_get failed:%d",
274 ksb->fs_dev.name, ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700275 usb_free_urb(urb);
276 ksb_free_data_pkt(pkt);
277 return;
278 }
279 usb_fill_bulk_urb(urb, ksb->udev, ksb->out_pipe,
280 pkt->buf, pkt->len, ksb_tx_cb, pkt);
281 usb_anchor_urb(urb, &ksb->submitted);
282
283 dbg_log_event(ksb, "S TX_URB", pkt->len, 0);
284
285 ret = usb_submit_urb(urb, GFP_KERNEL);
286 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800287 dev_err(&ksb->udev->dev, "out urb submission failed");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700288 usb_unanchor_urb(urb);
289 usb_free_urb(urb);
290 ksb_free_data_pkt(pkt);
291 usb_autopm_put_interface(ksb->ifc);
292 return;
293 }
294
Hemant Kumar9b230b52012-09-19 12:40:11 -0700295 usb_free_urb(urb);
296
Vamsi Krishna5b944712012-06-29 18:36:23 -0700297 spin_lock_irqsave(&ksb->lock, flags);
298 }
299 spin_unlock_irqrestore(&ksb->lock, flags);
300}
301
302static ssize_t ksb_fs_write(struct file *fp, const char __user *buf,
303 size_t count, loff_t *pos)
304{
305 int ret;
306 struct data_pkt *pkt;
307 unsigned long flags;
308 struct ks_bridge *ksb = fp->private_data;
309
Pavankumar Kondeti4fde7d42012-12-28 17:15:41 +0530310
311 if (count > MAX_DATA_PKT_SIZE)
312 count = MAX_DATA_PKT_SIZE;
313
Vamsi Krishna5b944712012-06-29 18:36:23 -0700314 pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
315 if (IS_ERR(pkt)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800316 dev_err(ksb->fs_dev.this_device,
317 "unable to allocate data packet");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700318 return PTR_ERR(pkt);
319 }
320
321 ret = copy_from_user(pkt->buf, buf, count);
322 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800323 dev_err(ksb->fs_dev.this_device,
324 "copy_from_user failed: err:%d", ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700325 ksb_free_data_pkt(pkt);
326 return ret;
327 }
328
329 spin_lock_irqsave(&ksb->lock, flags);
330 list_add_tail(&pkt->list, &ksb->to_mdm_list);
331 spin_unlock_irqrestore(&ksb->lock, flags);
332
333 queue_work(ksb->wq, &ksb->to_mdm_work);
334
335 return count;
336}
337
Vamsi Krishna5b944712012-06-29 18:36:23 -0700338static int ksb_fs_open(struct inode *ip, struct file *fp)
339{
Hemant Kumar54aeb822013-01-16 18:55:14 -0800340 struct miscdevice *mdev = fp->private_data;
341 struct ks_bridge *ksb = container_of(mdev, struct ks_bridge, fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700342
Hemant Kumar54aeb822013-01-16 18:55:14 -0800343 if (IS_ERR(ksb)) {
344 pr_err("ksb device not found");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700345 return -ENODEV;
346 }
347
Hemant Kumar54aeb822013-01-16 18:55:14 -0800348 dev_dbg(ksb->fs_dev.this_device, ":%s", ksb->fs_dev.name);
349 dbg_log_event(ksb, "FS-OPEN", 0, 0);
350
Vamsi Krishna5b944712012-06-29 18:36:23 -0700351 fp->private_data = ksb;
352 set_bit(FILE_OPENED, &ksb->flags);
353
354 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
355 queue_work(ksb->wq, &ksb->start_rx_work);
356
357 return 0;
358}
359
360static int ksb_fs_release(struct inode *ip, struct file *fp)
361{
362 struct ks_bridge *ksb = fp->private_data;
363
Hemant Kumar54aeb822013-01-16 18:55:14 -0800364 dev_dbg(ksb->fs_dev.this_device, ":%s", ksb->fs_dev.name);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700365 dbg_log_event(ksb, "FS-RELEASE", 0, 0);
366
367 clear_bit(FILE_OPENED, &ksb->flags);
368 fp->private_data = NULL;
369
370 return 0;
371}
372
373static const struct file_operations ksb_fops = {
374 .owner = THIS_MODULE,
375 .read = ksb_fs_read,
376 .write = ksb_fs_write,
377 .open = ksb_fs_open,
378 .release = ksb_fs_release,
379};
380
Hemant Kumar54aeb822013-01-16 18:55:14 -0800381static struct miscdevice ksb_fboot_dev[] = {
382 {
383 .minor = MISC_DYNAMIC_MINOR,
384 .name = "ks_hsic_bridge",
385 .fops = &ksb_fops,
386 },
387 {
388 .minor = MISC_DYNAMIC_MINOR,
389 .name = "ks_usb_bridge",
390 .fops = &ksb_fops,
391 },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700392};
393
394static const struct file_operations efs_fops = {
395 .owner = THIS_MODULE,
396 .read = ksb_fs_read,
397 .write = ksb_fs_write,
Hemant Kumar54aeb822013-01-16 18:55:14 -0800398 .open = ksb_fs_open,
Vamsi Krishna5b944712012-06-29 18:36:23 -0700399 .release = ksb_fs_release,
400};
401
Hemant Kumar54aeb822013-01-16 18:55:14 -0800402static struct miscdevice ksb_efs_hsic_dev = {
Vamsi Krishna5b944712012-06-29 18:36:23 -0700403 .minor = MISC_DYNAMIC_MINOR,
Hemant Kumar54aeb822013-01-16 18:55:14 -0800404 .name = "efs_hsic_bridge",
Vamsi Krishna5b944712012-06-29 18:36:23 -0700405 .fops = &efs_fops,
406};
407
Hemant Kumar54aeb822013-01-16 18:55:14 -0800408static struct miscdevice ksb_efs_usb_dev = {
409 .minor = MISC_DYNAMIC_MINOR,
410 .name = "efs_usb_bridge",
411 .fops = &efs_fops,
412};
Vamsi Krishna5b944712012-06-29 18:36:23 -0700413static const struct usb_device_id ksb_usb_ids[] = {
414 { USB_DEVICE(0x5c6, 0x9008),
415 .driver_info = (unsigned long)&ksb_fboot_dev, },
416 { USB_DEVICE(0x5c6, 0x9048),
Hemant Kumar54aeb822013-01-16 18:55:14 -0800417 .driver_info = (unsigned long)&ksb_efs_hsic_dev, },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700418 { USB_DEVICE(0x5c6, 0x904C),
Hemant Kumar54aeb822013-01-16 18:55:14 -0800419 .driver_info = (unsigned long)&ksb_efs_hsic_dev, },
420 { USB_DEVICE(0x5c6, 0x9079),
421 .driver_info = (unsigned long)&ksb_efs_usb_dev, },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700422
423 {} /* terminating entry */
424};
425MODULE_DEVICE_TABLE(usb, ksb_usb_ids);
426
427static void ksb_rx_cb(struct urb *urb);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530428static void
429submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700430{
Vamsi Krishna5b944712012-06-29 18:36:23 -0700431 struct urb *urb;
432 int ret;
433
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530434 urb = usb_alloc_urb(0, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700435 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800436 dev_err(&ksb->udev->dev, "unable to allocate urb");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700437 ksb_free_data_pkt(pkt);
438 return;
439 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700440
441 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
442 pkt->buf, pkt->len,
443 ksb_rx_cb, pkt);
444 usb_anchor_urb(urb, &ksb->submitted);
445
446 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
447
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530448 ret = usb_submit_urb(urb, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700449 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800450 dev_err(&ksb->udev->dev, "in urb submission failed");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700451 usb_unanchor_urb(urb);
452 usb_free_urb(urb);
453 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700454 return;
455 }
456
457 usb_free_urb(urb);
458}
459static void ksb_rx_cb(struct urb *urb)
460{
461 struct data_pkt *pkt = urb->context;
462 struct ks_bridge *ksb = pkt->ctxt;
463
464 dbg_log_event(ksb, "C RX_URB", urb->status, urb->actual_length);
465
Hemant Kumar54aeb822013-01-16 18:55:14 -0800466 dev_dbg(&ksb->udev->dev, "status:%d actual:%d", urb->status,
467 urb->actual_length);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700468
Hemant Kumara6194c12012-08-31 18:38:32 -0700469 /*non zero len of data received while unlinking urb*/
470 if (urb->status == -ENOENT && urb->actual_length > 0)
471 goto add_to_list;
472
Vamsi Krishna5b944712012-06-29 18:36:23 -0700473 if (urb->status < 0) {
Hemant Kumara6194c12012-08-31 18:38:32 -0700474 if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
475 && urb->status != -EPROTO)
Hemant Kumar54aeb822013-01-16 18:55:14 -0800476 pr_err_ratelimited("%s: urb failed with err:%d",
477 ksb->fs_dev.name, urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700478 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700479 return;
480 }
481
482 if (urb->actual_length == 0) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530483 submit_one_urb(ksb, GFP_ATOMIC, pkt);
484 return;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700485 }
486
Hemant Kumara6194c12012-08-31 18:38:32 -0700487add_to_list:
Vamsi Krishna5b944712012-06-29 18:36:23 -0700488 spin_lock(&ksb->lock);
489 pkt->len = urb->actual_length;
490 list_add_tail(&pkt->list, &ksb->to_ks_list);
491 spin_unlock(&ksb->lock);
492
493 /* wake up read thread */
494 wake_up(&ksb->ks_wait_q);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700495}
496
497static void ksb_start_rx_work(struct work_struct *w)
498{
499 struct ks_bridge *ksb =
500 container_of(w, struct ks_bridge, start_rx_work);
501 struct data_pkt *pkt;
502 struct urb *urb;
503 int i = 0;
504 int ret;
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530505 bool put = true;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700506
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530507 ret = usb_autopm_get_interface(ksb->ifc);
508 if (ret < 0) {
509 if (ret != -EAGAIN && ret != -EACCES) {
510 pr_err_ratelimited("autopm_get failed:%d", ret);
511 return;
512 }
513 put = false;
514 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700515 for (i = 0; i < NO_RX_REQS; i++) {
516 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb);
517 if (IS_ERR(pkt)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800518 dev_err(&ksb->udev->dev, "unable to allocate data pkt");
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530519 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700520 }
521
522 urb = usb_alloc_urb(0, GFP_KERNEL);
523 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800524 dev_err(&ksb->udev->dev, "unable to allocate urb");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700525 ksb_free_data_pkt(pkt);
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530526 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700527 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700528
529 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
530 pkt->buf, pkt->len,
531 ksb_rx_cb, pkt);
532 usb_anchor_urb(urb, &ksb->submitted);
533
534 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
535
536 ret = usb_submit_urb(urb, GFP_KERNEL);
537 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800538 dev_err(&ksb->udev->dev, "in urb submission failed");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700539 usb_unanchor_urb(urb);
540 usb_free_urb(urb);
541 ksb_free_data_pkt(pkt);
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530542 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700543 }
544
Vamsi Krishna5b944712012-06-29 18:36:23 -0700545 usb_free_urb(urb);
546 }
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530547 if (put)
548 usb_autopm_put_interface_async(ksb->ifc);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700549}
550
551static int
552ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
553{
554 __u8 ifc_num;
555 struct usb_host_interface *ifc_desc;
556 struct usb_endpoint_descriptor *ep_desc;
557 int i;
558 struct ks_bridge *ksb;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800559 struct miscdevice *mdev, *fbdev;
560 struct usb_device *udev;
561 unsigned int bus_id;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700562
563 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
564
Hemant Kumar54aeb822013-01-16 18:55:14 -0800565 udev = interface_to_usbdev(ifc);
566 fbdev = mdev = (struct miscdevice *)id->driver_info;
567
568 bus_id = str_to_busid(udev->bus->bus_name);
569 if (bus_id == BUS_UNDEF) {
570 dev_err(&udev->dev, "unknown usb bus %s, probe failed\n",
571 udev->bus->bus_name);
572 return -ENODEV;
573 }
574
Vamsi Krishna5b944712012-06-29 18:36:23 -0700575 switch (id->idProduct) {
576 case 0x9008:
577 if (ifc_num != 0)
578 return -ENODEV;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800579 ksb = __ksb[bus_id];
580 mdev = &fbdev[bus_id];
Vamsi Krishna5b944712012-06-29 18:36:23 -0700581 break;
582 case 0x9048:
583 case 0x904C:
584 if (ifc_num != 2)
585 return -ENODEV;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800586 ksb = __ksb[EFS_HSIC_BRIDGE_INDEX];
587 break;
588 case 0x9079:
589 if (ifc_num != 2)
590 return -ENODEV;
591 ksb = __ksb[EFS_USB_BRIDGE_INDEX];
Vamsi Krishna5b944712012-06-29 18:36:23 -0700592 break;
593 default:
594 return -ENODEV;
595 }
596
597 if (!ksb) {
598 pr_err("ksb is not initialized");
599 return -ENODEV;
600 }
601
602 ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
603 ksb->ifc = ifc;
604 ifc_desc = ifc->cur_altsetting;
605
606 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
607 ep_desc = &ifc_desc->endpoint[i].desc;
608
609 if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
610 ksb->in_epAddr = ep_desc->bEndpointAddress;
611
612 if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
613 ksb->out_epAddr = ep_desc->bEndpointAddress;
614 }
615
616 if (!(ksb->in_epAddr && ksb->out_epAddr)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800617 dev_err(&udev->dev,
618 "could not find bulk in and bulk out endpoints");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700619 usb_put_dev(ksb->udev);
620 ksb->ifc = NULL;
621 return -ENODEV;
622 }
623
624 ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
625 ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);
626
627 usb_set_intfdata(ifc, ksb);
628 set_bit(USB_DEV_CONNECTED, &ksb->flags);
629
630 dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
631
Hemant Kumar54aeb822013-01-16 18:55:14 -0800632 ksb->fs_dev = *mdev;
633 misc_register(&ksb->fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700634
Hemant Kumarf292a322012-09-07 19:00:21 -0700635 ifc->needs_remote_wakeup = 1;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700636 usb_enable_autosuspend(ksb->udev);
637
Hemant Kumar54aeb822013-01-16 18:55:14 -0800638 dev_dbg(&udev->dev, "usb dev connected");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700639
640 return 0;
641}
642
643static int ksb_usb_suspend(struct usb_interface *ifc, pm_message_t message)
644{
645 struct ks_bridge *ksb = usb_get_intfdata(ifc);
646
647 dbg_log_event(ksb, "SUSPEND", 0, 0);
648
Vamsi Krishna5b944712012-06-29 18:36:23 -0700649 usb_kill_anchored_urbs(&ksb->submitted);
650
651 return 0;
652}
653
654static int ksb_usb_resume(struct usb_interface *ifc)
655{
656 struct ks_bridge *ksb = usb_get_intfdata(ifc);
657
658 dbg_log_event(ksb, "RESUME", 0, 0);
659
660 if (test_bit(FILE_OPENED, &ksb->flags))
661 queue_work(ksb->wq, &ksb->start_rx_work);
662
663 return 0;
664}
665
666static void ksb_usb_disconnect(struct usb_interface *ifc)
667{
668 struct ks_bridge *ksb = usb_get_intfdata(ifc);
669 unsigned long flags;
670 struct data_pkt *pkt;
671
672 dbg_log_event(ksb, "PID-DETACH", 0, 0);
673
674 clear_bit(USB_DEV_CONNECTED, &ksb->flags);
675 wake_up(&ksb->ks_wait_q);
676 cancel_work_sync(&ksb->to_mdm_work);
677
Hemant Kumar54aeb822013-01-16 18:55:14 -0800678 misc_deregister(&ksb->fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700679
Hemant Kumar38980ec42012-08-24 19:42:31 -0700680 usb_kill_anchored_urbs(&ksb->submitted);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700681 spin_lock_irqsave(&ksb->lock, flags);
682 while (!list_empty(&ksb->to_ks_list)) {
683 pkt = list_first_entry(&ksb->to_ks_list,
684 struct data_pkt, list);
685 list_del_init(&pkt->list);
686 ksb_free_data_pkt(pkt);
687 }
688 while (!list_empty(&ksb->to_mdm_list)) {
689 pkt = list_first_entry(&ksb->to_mdm_list,
690 struct data_pkt, list);
691 list_del_init(&pkt->list);
692 ksb_free_data_pkt(pkt);
693 }
694 spin_unlock_irqrestore(&ksb->lock, flags);
695
Hemant Kumarf292a322012-09-07 19:00:21 -0700696 ifc->needs_remote_wakeup = 0;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700697 usb_put_dev(ksb->udev);
698 ksb->ifc = NULL;
699 usb_set_intfdata(ifc, NULL);
700
701 return;
702}
703
704static struct usb_driver ksb_usb_driver = {
705 .name = "ks_bridge",
706 .probe = ksb_usb_probe,
707 .disconnect = ksb_usb_disconnect,
708 .suspend = ksb_usb_suspend,
709 .resume = ksb_usb_resume,
710 .id_table = ksb_usb_ids,
711 .supports_autosuspend = 1,
712};
713
714static ssize_t ksb_debug_show(struct seq_file *s, void *unused)
715{
716 unsigned long flags;
717 struct ks_bridge *ksb = s->private;
718 int i;
719
720 read_lock_irqsave(&ksb->dbg_lock, flags);
721 for (i = 0; i < DBG_MAX_MSG; i++) {
722 if (i == (ksb->dbg_idx - 1))
723 seq_printf(s, "-->%s\n", ksb->dbgbuf[i]);
724 else
725 seq_printf(s, "%s\n", ksb->dbgbuf[i]);
726 }
727 read_unlock_irqrestore(&ksb->dbg_lock, flags);
728
729 return 0;
730}
731
732static int ksb_debug_open(struct inode *ip, struct file *fp)
733{
734 return single_open(fp, ksb_debug_show, ip->i_private);
735
736 return 0;
737}
738
739static const struct file_operations dbg_fops = {
740 .open = ksb_debug_open,
741 .read = seq_read,
742 .llseek = seq_lseek,
743 .release = single_release,
744};
745static struct dentry *dbg_dir;
746static int __init ksb_init(void)
747{
748 struct ks_bridge *ksb;
749 int num_instances = 0;
750 int ret = 0;
751 int i;
752
753 dbg_dir = debugfs_create_dir("ks_bridge", NULL);
754 if (IS_ERR(dbg_dir))
755 pr_err("unable to create debug dir");
756
757 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
758 ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
759 if (!ksb) {
760 pr_err("unable to allocat mem for ks_bridge");
Hemant Kumar38980ec42012-08-24 19:42:31 -0700761 ret = -ENOMEM;
762 goto dev_free;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700763 }
764 __ksb[i] = ksb;
765
766 ksb->name = kasprintf(GFP_KERNEL, "ks_bridge:%i", i + 1);
767 if (!ksb->name) {
768 pr_info("unable to allocate name");
769 kfree(ksb);
770 ret = -ENOMEM;
771 goto dev_free;
772 }
773
774 spin_lock_init(&ksb->lock);
775 INIT_LIST_HEAD(&ksb->to_mdm_list);
776 INIT_LIST_HEAD(&ksb->to_ks_list);
777 init_waitqueue_head(&ksb->ks_wait_q);
778 ksb->wq = create_singlethread_workqueue(ksb->name);
779 if (!ksb->wq) {
780 pr_err("unable to allocate workqueue");
781 kfree(ksb->name);
782 kfree(ksb);
783 ret = -ENOMEM;
784 goto dev_free;
785 }
786
787 INIT_WORK(&ksb->to_mdm_work, ksb_tomdm_work);
788 INIT_WORK(&ksb->start_rx_work, ksb_start_rx_work);
789 init_usb_anchor(&ksb->submitted);
790
791 ksb->dbg_idx = 0;
792 ksb->dbg_lock = __RW_LOCK_UNLOCKED(lck);
793
794 if (!IS_ERR(dbg_dir))
795 debugfs_create_file(ksb->name, S_IRUGO, dbg_dir,
796 ksb, &dbg_fops);
797
798 num_instances++;
799 }
800
801 ret = usb_register(&ksb_usb_driver);
802 if (ret) {
803 pr_err("unable to register ks bridge driver");
804 goto dev_free;
805 }
806
807 pr_info("init done");
808
809 return 0;
810
811dev_free:
812 if (!IS_ERR(dbg_dir))
813 debugfs_remove_recursive(dbg_dir);
814
815 for (i = 0; i < num_instances; i++) {
816 ksb = __ksb[i];
817
818 destroy_workqueue(ksb->wq);
819 kfree(ksb->name);
820 kfree(ksb);
821 }
822
823 return ret;
824
825}
826
827static void __exit ksb_exit(void)
828{
829 struct ks_bridge *ksb;
830 int i;
831
832 if (!IS_ERR(dbg_dir))
833 debugfs_remove_recursive(dbg_dir);
834
835 usb_deregister(&ksb_usb_driver);
836
837 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
838 ksb = __ksb[i];
839
840 destroy_workqueue(ksb->wq);
841 kfree(ksb->name);
842 kfree(ksb);
843 }
844}
845
846module_init(ksb_init);
847module_exit(ksb_exit);
848
849MODULE_DESCRIPTION(DRIVER_DESC);
850MODULE_VERSION(DRIVER_VERSION);
851MODULE_LICENSE("GPL v2");