blob: 2a9536a8e95e466aa85e9109b923c3831a130516 [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
Hemant Kumarea4b0b02012-09-16 20:28:56 -070069#define PENDING_URB_TIMEOUT 10
Vamsi Krishna5b944712012-06-29 18:36:23 -070070
71struct ks_bridge {
72 char *name;
73 spinlock_t lock;
74 struct workqueue_struct *wq;
75 struct work_struct to_mdm_work;
76 struct work_struct start_rx_work;
77 struct list_head to_mdm_list;
78 struct list_head to_ks_list;
79 wait_queue_head_t ks_wait_q;
Hemant Kumar54aeb822013-01-16 18:55:14 -080080 struct miscdevice fs_dev;
Hemant Kumarea4b0b02012-09-16 20:28:56 -070081 wait_queue_head_t pending_urb_wait;
82 atomic_t tx_pending_cnt;
83 atomic_t rx_pending_cnt;
Vamsi Krishna5b944712012-06-29 18:36:23 -070084
85 /* usb specific */
86 struct usb_device *udev;
87 struct usb_interface *ifc;
88 __u8 in_epAddr;
89 __u8 out_epAddr;
90 unsigned int in_pipe;
91 unsigned int out_pipe;
92 struct usb_anchor submitted;
93
94 unsigned long flags;
Vamsi Krishna5b944712012-06-29 18:36:23 -070095
96#define DBG_MSG_LEN 40
97#define DBG_MAX_MSG 500
98 unsigned int dbg_idx;
99 rwlock_t dbg_lock;
100 char (dbgbuf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
101};
102struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES];
103
104/* by default debugging is enabled */
105static unsigned int enable_dbg = 1;
106module_param(enable_dbg, uint, S_IRUGO | S_IWUSR);
107
108static void
109dbg_log_event(struct ks_bridge *ksb, char *event, int d1, int d2)
110{
111 unsigned long flags;
112 unsigned long long t;
113 unsigned long nanosec;
114
115 if (!enable_dbg)
116 return;
117
118 write_lock_irqsave(&ksb->dbg_lock, flags);
119 t = cpu_clock(smp_processor_id());
120 nanosec = do_div(t, 1000000000)/1000;
121 scnprintf(ksb->dbgbuf[ksb->dbg_idx], DBG_MSG_LEN, "%5lu.%06lu:%s:%x:%x",
122 (unsigned long)t, nanosec, event, d1, d2);
123
124 ksb->dbg_idx++;
125 ksb->dbg_idx = ksb->dbg_idx % DBG_MAX_MSG;
126 write_unlock_irqrestore(&ksb->dbg_lock, flags);
127}
128
129static
130struct data_pkt *ksb_alloc_data_pkt(size_t count, gfp_t flags, void *ctxt)
131{
132 struct data_pkt *pkt;
133
134 pkt = kzalloc(sizeof(struct data_pkt), flags);
135 if (!pkt) {
136 pr_err("failed to allocate data packet\n");
137 return ERR_PTR(-ENOMEM);
138 }
139
140 pkt->buf = kmalloc(count, flags);
141 if (!pkt->buf) {
142 pr_err("failed to allocate data buffer\n");
143 kfree(pkt);
144 return ERR_PTR(-ENOMEM);
145 }
146
147 pkt->len = count;
148 INIT_LIST_HEAD(&pkt->list);
149 pkt->ctxt = ctxt;
150
151 return pkt;
152}
153
154static void ksb_free_data_pkt(struct data_pkt *pkt)
155{
156 kfree(pkt->buf);
157 kfree(pkt);
158}
159
160
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530161static void
162submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700163static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
164 size_t count, loff_t *pos)
165{
166 int ret;
167 unsigned long flags;
168 struct ks_bridge *ksb = fp->private_data;
169 struct data_pkt *pkt;
170 size_t space, copied;
171
172read_start:
173 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
174 return -ENODEV;
175
176 spin_lock_irqsave(&ksb->lock, flags);
177 if (list_empty(&ksb->to_ks_list)) {
178 spin_unlock_irqrestore(&ksb->lock, flags);
179 ret = wait_event_interruptible(ksb->ks_wait_q,
180 !list_empty(&ksb->to_ks_list) ||
181 !test_bit(USB_DEV_CONNECTED, &ksb->flags));
182 if (ret < 0)
183 return ret;
184
185 goto read_start;
186 }
187
188 space = count;
189 copied = 0;
190 while (!list_empty(&ksb->to_ks_list) && space) {
191 size_t len;
192
193 pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
Hemant Kumard45f96c2012-09-24 12:32:32 -0700194 len = min_t(size_t, space, pkt->len - pkt->n_read);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700195 spin_unlock_irqrestore(&ksb->lock, flags);
196
Hemant Kumard45f96c2012-09-24 12:32:32 -0700197 ret = copy_to_user(buf + copied, pkt->buf + pkt->n_read, len);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700198 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800199 dev_err(ksb->fs_dev.this_device,
200 "copy_to_user failed err:%d\n", ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700201 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700202 return ret;
203 }
204
Hemant Kumard45f96c2012-09-24 12:32:32 -0700205 pkt->n_read += len;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700206 space -= len;
207 copied += len;
208
209 spin_lock_irqsave(&ksb->lock, flags);
210 if (pkt->n_read == pkt->len) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530211 /*
212 * re-init the packet and queue it
213 * for more data.
214 */
Vamsi Krishna5b944712012-06-29 18:36:23 -0700215 list_del_init(&pkt->list);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530216 pkt->n_read = 0;
217 pkt->len = MAX_DATA_PKT_SIZE;
218 spin_unlock_irqrestore(&ksb->lock, flags);
219 submit_one_urb(ksb, GFP_KERNEL, pkt);
220 spin_lock_irqsave(&ksb->lock, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700221 }
222 }
223 spin_unlock_irqrestore(&ksb->lock, flags);
224
225 dbg_log_event(ksb, "KS_READ", copied, 0);
226
Hemant Kumar54aeb822013-01-16 18:55:14 -0800227 dev_dbg(ksb->fs_dev.this_device, "count:%d space:%d copied:%d", count,
228 space, copied);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700229
230 return copied;
231}
232
233static void ksb_tx_cb(struct urb *urb)
234{
235 struct data_pkt *pkt = urb->context;
236 struct ks_bridge *ksb = pkt->ctxt;
237
238 dbg_log_event(ksb, "C TX_URB", urb->status, 0);
Hemant Kumar54aeb822013-01-16 18:55:14 -0800239 dev_dbg(&ksb->udev->dev, "status:%d", urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700240
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700241 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
Vamsi Krishna5b944712012-06-29 18:36:23 -0700242 usb_autopm_put_interface_async(ksb->ifc);
243
244 if (urb->status < 0)
Hemant Kumar54aeb822013-01-16 18:55:14 -0800245 pr_err_ratelimited("%s: urb failed with err:%d",
246 ksb->fs_dev.name, urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700247
248 ksb_free_data_pkt(pkt);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700249
250 atomic_dec(&ksb->tx_pending_cnt);
251 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700252}
253
254static void ksb_tomdm_work(struct work_struct *w)
255{
256 struct ks_bridge *ksb = container_of(w, struct ks_bridge, to_mdm_work);
257 struct data_pkt *pkt;
258 unsigned long flags;
259 struct urb *urb;
260 int ret;
261
262 spin_lock_irqsave(&ksb->lock, flags);
263 while (!list_empty(&ksb->to_mdm_list)
264 && test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
265 pkt = list_first_entry(&ksb->to_mdm_list,
266 struct data_pkt, list);
267 list_del_init(&pkt->list);
268 spin_unlock_irqrestore(&ksb->lock, flags);
269
270 urb = usb_alloc_urb(0, GFP_KERNEL);
271 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800272 pr_err_ratelimited("%s: unable to allocate urb",
273 ksb->fs_dev.name);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700274 ksb_free_data_pkt(pkt);
275 return;
276 }
277
278 ret = usb_autopm_get_interface(ksb->ifc);
279 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800280 pr_err_ratelimited("%s: autopm_get failed:%d",
281 ksb->fs_dev.name, ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700282 usb_free_urb(urb);
283 ksb_free_data_pkt(pkt);
284 return;
285 }
286 usb_fill_bulk_urb(urb, ksb->udev, ksb->out_pipe,
287 pkt->buf, pkt->len, ksb_tx_cb, pkt);
288 usb_anchor_urb(urb, &ksb->submitted);
289
290 dbg_log_event(ksb, "S TX_URB", pkt->len, 0);
291
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700292 atomic_inc(&ksb->tx_pending_cnt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700293 ret = usb_submit_urb(urb, GFP_KERNEL);
294 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800295 dev_err(&ksb->udev->dev, "out urb submission failed");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700296 usb_unanchor_urb(urb);
297 usb_free_urb(urb);
298 ksb_free_data_pkt(pkt);
299 usb_autopm_put_interface(ksb->ifc);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700300 atomic_dec(&ksb->tx_pending_cnt);
301 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700302 return;
303 }
304
Hemant Kumar9b230b52012-09-19 12:40:11 -0700305 usb_free_urb(urb);
306
Vamsi Krishna5b944712012-06-29 18:36:23 -0700307 spin_lock_irqsave(&ksb->lock, flags);
308 }
309 spin_unlock_irqrestore(&ksb->lock, flags);
310}
311
312static ssize_t ksb_fs_write(struct file *fp, const char __user *buf,
313 size_t count, loff_t *pos)
314{
315 int ret;
316 struct data_pkt *pkt;
317 unsigned long flags;
318 struct ks_bridge *ksb = fp->private_data;
319
Hemant Kumarc999d432012-09-17 14:05:54 -0700320 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
321 return -ENODEV;
Pavankumar Kondeti4fde7d42012-12-28 17:15:41 +0530322
323 if (count > MAX_DATA_PKT_SIZE)
324 count = MAX_DATA_PKT_SIZE;
325
Vamsi Krishna5b944712012-06-29 18:36:23 -0700326 pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
327 if (IS_ERR(pkt)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800328 dev_err(ksb->fs_dev.this_device,
329 "unable to allocate data packet");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700330 return PTR_ERR(pkt);
331 }
332
333 ret = copy_from_user(pkt->buf, buf, count);
334 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800335 dev_err(ksb->fs_dev.this_device,
336 "copy_from_user failed: err:%d", ret);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700337 ksb_free_data_pkt(pkt);
338 return ret;
339 }
340
341 spin_lock_irqsave(&ksb->lock, flags);
342 list_add_tail(&pkt->list, &ksb->to_mdm_list);
343 spin_unlock_irqrestore(&ksb->lock, flags);
344
345 queue_work(ksb->wq, &ksb->to_mdm_work);
346
347 return count;
348}
349
Vamsi Krishna5b944712012-06-29 18:36:23 -0700350static int ksb_fs_open(struct inode *ip, struct file *fp)
351{
Hemant Kumar54aeb822013-01-16 18:55:14 -0800352 struct miscdevice *mdev = fp->private_data;
353 struct ks_bridge *ksb = container_of(mdev, struct ks_bridge, fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700354
Hemant Kumar54aeb822013-01-16 18:55:14 -0800355 if (IS_ERR(ksb)) {
356 pr_err("ksb device not found");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700357 return -ENODEV;
358 }
359
Hemant Kumar54aeb822013-01-16 18:55:14 -0800360 dev_dbg(ksb->fs_dev.this_device, ":%s", ksb->fs_dev.name);
361 dbg_log_event(ksb, "FS-OPEN", 0, 0);
362
Vamsi Krishna5b944712012-06-29 18:36:23 -0700363 fp->private_data = ksb;
364 set_bit(FILE_OPENED, &ksb->flags);
365
366 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
367 queue_work(ksb->wq, &ksb->start_rx_work);
368
369 return 0;
370}
371
372static int ksb_fs_release(struct inode *ip, struct file *fp)
373{
374 struct ks_bridge *ksb = fp->private_data;
375
Hemant Kumar54aeb822013-01-16 18:55:14 -0800376 dev_dbg(ksb->fs_dev.this_device, ":%s", ksb->fs_dev.name);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700377 dbg_log_event(ksb, "FS-RELEASE", 0, 0);
378
379 clear_bit(FILE_OPENED, &ksb->flags);
380 fp->private_data = NULL;
381
382 return 0;
383}
384
385static const struct file_operations ksb_fops = {
386 .owner = THIS_MODULE,
387 .read = ksb_fs_read,
388 .write = ksb_fs_write,
389 .open = ksb_fs_open,
390 .release = ksb_fs_release,
391};
392
Hemant Kumar54aeb822013-01-16 18:55:14 -0800393static struct miscdevice ksb_fboot_dev[] = {
394 {
395 .minor = MISC_DYNAMIC_MINOR,
396 .name = "ks_hsic_bridge",
397 .fops = &ksb_fops,
398 },
399 {
400 .minor = MISC_DYNAMIC_MINOR,
401 .name = "ks_usb_bridge",
402 .fops = &ksb_fops,
403 },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700404};
405
406static const struct file_operations efs_fops = {
407 .owner = THIS_MODULE,
408 .read = ksb_fs_read,
409 .write = ksb_fs_write,
Hemant Kumar54aeb822013-01-16 18:55:14 -0800410 .open = ksb_fs_open,
Vamsi Krishna5b944712012-06-29 18:36:23 -0700411 .release = ksb_fs_release,
412};
413
Hemant Kumar54aeb822013-01-16 18:55:14 -0800414static struct miscdevice ksb_efs_hsic_dev = {
Vamsi Krishna5b944712012-06-29 18:36:23 -0700415 .minor = MISC_DYNAMIC_MINOR,
Hemant Kumar54aeb822013-01-16 18:55:14 -0800416 .name = "efs_hsic_bridge",
Vamsi Krishna5b944712012-06-29 18:36:23 -0700417 .fops = &efs_fops,
418};
419
Hemant Kumar54aeb822013-01-16 18:55:14 -0800420static struct miscdevice ksb_efs_usb_dev = {
421 .minor = MISC_DYNAMIC_MINOR,
422 .name = "efs_usb_bridge",
423 .fops = &efs_fops,
424};
Vamsi Krishna5b944712012-06-29 18:36:23 -0700425static const struct usb_device_id ksb_usb_ids[] = {
426 { USB_DEVICE(0x5c6, 0x9008),
427 .driver_info = (unsigned long)&ksb_fboot_dev, },
428 { USB_DEVICE(0x5c6, 0x9048),
Hemant Kumar54aeb822013-01-16 18:55:14 -0800429 .driver_info = (unsigned long)&ksb_efs_hsic_dev, },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700430 { USB_DEVICE(0x5c6, 0x904C),
Hemant Kumar54aeb822013-01-16 18:55:14 -0800431 .driver_info = (unsigned long)&ksb_efs_hsic_dev, },
432 { USB_DEVICE(0x5c6, 0x9079),
433 .driver_info = (unsigned long)&ksb_efs_usb_dev, },
Vamsi Krishna5b944712012-06-29 18:36:23 -0700434
435 {} /* terminating entry */
436};
437MODULE_DEVICE_TABLE(usb, ksb_usb_ids);
438
439static void ksb_rx_cb(struct urb *urb);
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530440static void
441submit_one_urb(struct ks_bridge *ksb, gfp_t flags, struct data_pkt *pkt)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700442{
Vamsi Krishna5b944712012-06-29 18:36:23 -0700443 struct urb *urb;
444 int ret;
445
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530446 urb = usb_alloc_urb(0, flags);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700447 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800448 dev_err(&ksb->udev->dev, "unable to allocate urb");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700449 ksb_free_data_pkt(pkt);
450 return;
451 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700452
453 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
454 pkt->buf, pkt->len,
455 ksb_rx_cb, pkt);
456 usb_anchor_urb(urb, &ksb->submitted);
457
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700458 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
Vamsi Krishna5b944712012-06-29 18:36:23 -0700459 usb_unanchor_urb(urb);
460 usb_free_urb(urb);
461 ksb_free_data_pkt(pkt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700462 return;
463 }
464
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700465 atomic_inc(&ksb->rx_pending_cnt);
466 ret = usb_submit_urb(urb, GFP_ATOMIC);
467 if (ret) {
468 dev_err(&ksb->udev->dev, "in urb submission failed");
469 usb_unanchor_urb(urb);
470 usb_free_urb(urb);
471 ksb_free_data_pkt(pkt);
472 atomic_dec(&ksb->rx_pending_cnt);
473 wake_up(&ksb->pending_urb_wait);
474 return;
475 }
476
477 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
478
Vamsi Krishna5b944712012-06-29 18:36:23 -0700479 usb_free_urb(urb);
480}
481static void ksb_rx_cb(struct urb *urb)
482{
483 struct data_pkt *pkt = urb->context;
484 struct ks_bridge *ksb = pkt->ctxt;
485
486 dbg_log_event(ksb, "C RX_URB", urb->status, urb->actual_length);
487
Hemant Kumar54aeb822013-01-16 18:55:14 -0800488 dev_dbg(&ksb->udev->dev, "status:%d actual:%d", urb->status,
489 urb->actual_length);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700490
Hemant Kumara6194c12012-08-31 18:38:32 -0700491 /*non zero len of data received while unlinking urb*/
492 if (urb->status == -ENOENT && urb->actual_length > 0)
493 goto add_to_list;
494
Vamsi Krishna5b944712012-06-29 18:36:23 -0700495 if (urb->status < 0) {
Hemant Kumara6194c12012-08-31 18:38:32 -0700496 if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
497 && urb->status != -EPROTO)
Hemant Kumar54aeb822013-01-16 18:55:14 -0800498 pr_err_ratelimited("%s: urb failed with err:%d",
499 ksb->fs_dev.name, urb->status);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700500 ksb_free_data_pkt(pkt);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700501 goto done;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700502 }
503
504 if (urb->actual_length == 0) {
Pavankumar Kondeti009bbd62012-12-14 15:12:46 +0530505 submit_one_urb(ksb, GFP_ATOMIC, pkt);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700506 goto done;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700507 }
508
Hemant Kumara6194c12012-08-31 18:38:32 -0700509add_to_list:
Vamsi Krishna5b944712012-06-29 18:36:23 -0700510 spin_lock(&ksb->lock);
511 pkt->len = urb->actual_length;
512 list_add_tail(&pkt->list, &ksb->to_ks_list);
513 spin_unlock(&ksb->lock);
514
515 /* wake up read thread */
516 wake_up(&ksb->ks_wait_q);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700517done:
518 atomic_dec(&ksb->rx_pending_cnt);
519 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700520}
521
522static void ksb_start_rx_work(struct work_struct *w)
523{
524 struct ks_bridge *ksb =
525 container_of(w, struct ks_bridge, start_rx_work);
526 struct data_pkt *pkt;
527 struct urb *urb;
528 int i = 0;
529 int ret;
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530530 bool put = true;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700531
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530532 ret = usb_autopm_get_interface(ksb->ifc);
533 if (ret < 0) {
534 if (ret != -EAGAIN && ret != -EACCES) {
535 pr_err_ratelimited("autopm_get failed:%d", ret);
536 return;
537 }
538 put = false;
539 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700540 for (i = 0; i < NO_RX_REQS; i++) {
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700541
542 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
543 return;
544
Vamsi Krishna5b944712012-06-29 18:36:23 -0700545 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb);
546 if (IS_ERR(pkt)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800547 dev_err(&ksb->udev->dev, "unable to allocate data pkt");
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530548 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700549 }
550
551 urb = usb_alloc_urb(0, GFP_KERNEL);
552 if (!urb) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800553 dev_err(&ksb->udev->dev, "unable to allocate urb");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700554 ksb_free_data_pkt(pkt);
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530555 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700556 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700557
558 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
559 pkt->buf, pkt->len,
560 ksb_rx_cb, pkt);
561 usb_anchor_urb(urb, &ksb->submitted);
562
563 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
564
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700565 atomic_inc(&ksb->rx_pending_cnt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700566 ret = usb_submit_urb(urb, GFP_KERNEL);
567 if (ret) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800568 dev_err(&ksb->udev->dev, "in urb submission failed");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700569 usb_unanchor_urb(urb);
570 usb_free_urb(urb);
571 ksb_free_data_pkt(pkt);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700572 atomic_dec(&ksb->rx_pending_cnt);
573 wake_up(&ksb->pending_urb_wait);
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530574 break;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700575 }
576
Vamsi Krishna5b944712012-06-29 18:36:23 -0700577 usb_free_urb(urb);
578 }
Pavankumar Kondeti76fe5292013-01-21 21:14:26 +0530579 if (put)
580 usb_autopm_put_interface_async(ksb->ifc);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700581}
582
583static int
584ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
585{
586 __u8 ifc_num;
587 struct usb_host_interface *ifc_desc;
588 struct usb_endpoint_descriptor *ep_desc;
589 int i;
590 struct ks_bridge *ksb;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800591 struct miscdevice *mdev, *fbdev;
592 struct usb_device *udev;
593 unsigned int bus_id;
Hemant Kumarc999d432012-09-17 14:05:54 -0700594 unsigned long flags;
595 struct data_pkt *pkt;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700596
597 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
598
Hemant Kumar54aeb822013-01-16 18:55:14 -0800599 udev = interface_to_usbdev(ifc);
600 fbdev = mdev = (struct miscdevice *)id->driver_info;
601
602 bus_id = str_to_busid(udev->bus->bus_name);
603 if (bus_id == BUS_UNDEF) {
604 dev_err(&udev->dev, "unknown usb bus %s, probe failed\n",
605 udev->bus->bus_name);
606 return -ENODEV;
607 }
608
Vamsi Krishna5b944712012-06-29 18:36:23 -0700609 switch (id->idProduct) {
610 case 0x9008:
611 if (ifc_num != 0)
612 return -ENODEV;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800613 ksb = __ksb[bus_id];
614 mdev = &fbdev[bus_id];
Vamsi Krishna5b944712012-06-29 18:36:23 -0700615 break;
616 case 0x9048:
617 case 0x904C:
618 if (ifc_num != 2)
619 return -ENODEV;
Hemant Kumar54aeb822013-01-16 18:55:14 -0800620 ksb = __ksb[EFS_HSIC_BRIDGE_INDEX];
621 break;
622 case 0x9079:
623 if (ifc_num != 2)
624 return -ENODEV;
625 ksb = __ksb[EFS_USB_BRIDGE_INDEX];
Vamsi Krishna5b944712012-06-29 18:36:23 -0700626 break;
627 default:
628 return -ENODEV;
629 }
630
631 if (!ksb) {
632 pr_err("ksb is not initialized");
633 return -ENODEV;
634 }
635
636 ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
637 ksb->ifc = ifc;
638 ifc_desc = ifc->cur_altsetting;
639
640 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
641 ep_desc = &ifc_desc->endpoint[i].desc;
642
643 if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
644 ksb->in_epAddr = ep_desc->bEndpointAddress;
645
646 if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
647 ksb->out_epAddr = ep_desc->bEndpointAddress;
648 }
649
650 if (!(ksb->in_epAddr && ksb->out_epAddr)) {
Hemant Kumar54aeb822013-01-16 18:55:14 -0800651 dev_err(&udev->dev,
652 "could not find bulk in and bulk out endpoints");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700653 usb_put_dev(ksb->udev);
654 ksb->ifc = NULL;
655 return -ENODEV;
656 }
657
658 ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
659 ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);
660
661 usb_set_intfdata(ifc, ksb);
662 set_bit(USB_DEV_CONNECTED, &ksb->flags);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700663 atomic_set(&ksb->tx_pending_cnt, 0);
664 atomic_set(&ksb->rx_pending_cnt, 0);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700665
666 dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
667
Hemant Kumarc999d432012-09-17 14:05:54 -0700668 /*free up stale buffers if any from previous disconnect*/
669 spin_lock_irqsave(&ksb->lock, flags);
670 while (!list_empty(&ksb->to_ks_list)) {
671 pkt = list_first_entry(&ksb->to_ks_list,
672 struct data_pkt, list);
673 list_del_init(&pkt->list);
674 ksb_free_data_pkt(pkt);
675 }
676 while (!list_empty(&ksb->to_mdm_list)) {
677 pkt = list_first_entry(&ksb->to_mdm_list,
678 struct data_pkt, list);
679 list_del_init(&pkt->list);
680 ksb_free_data_pkt(pkt);
681 }
682 spin_unlock_irqrestore(&ksb->lock, flags);
683
Hemant Kumar54aeb822013-01-16 18:55:14 -0800684 ksb->fs_dev = *mdev;
685 misc_register(&ksb->fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700686
Hemant Kumarf292a322012-09-07 19:00:21 -0700687 ifc->needs_remote_wakeup = 1;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700688 usb_enable_autosuspend(ksb->udev);
689
Hemant Kumar54aeb822013-01-16 18:55:14 -0800690 dev_dbg(&udev->dev, "usb dev connected");
Vamsi Krishna5b944712012-06-29 18:36:23 -0700691
692 return 0;
693}
694
695static int ksb_usb_suspend(struct usb_interface *ifc, pm_message_t message)
696{
697 struct ks_bridge *ksb = usb_get_intfdata(ifc);
698
699 dbg_log_event(ksb, "SUSPEND", 0, 0);
700
Vamsi Krishna5b944712012-06-29 18:36:23 -0700701 usb_kill_anchored_urbs(&ksb->submitted);
702
703 return 0;
704}
705
706static int ksb_usb_resume(struct usb_interface *ifc)
707{
708 struct ks_bridge *ksb = usb_get_intfdata(ifc);
709
710 dbg_log_event(ksb, "RESUME", 0, 0);
711
712 if (test_bit(FILE_OPENED, &ksb->flags))
713 queue_work(ksb->wq, &ksb->start_rx_work);
714
715 return 0;
716}
717
718static void ksb_usb_disconnect(struct usb_interface *ifc)
719{
720 struct ks_bridge *ksb = usb_get_intfdata(ifc);
721 unsigned long flags;
722 struct data_pkt *pkt;
723
724 dbg_log_event(ksb, "PID-DETACH", 0, 0);
725
726 clear_bit(USB_DEV_CONNECTED, &ksb->flags);
727 wake_up(&ksb->ks_wait_q);
728 cancel_work_sync(&ksb->to_mdm_work);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700729 cancel_work_sync(&ksb->start_rx_work);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700730
Hemant Kumar54aeb822013-01-16 18:55:14 -0800731 misc_deregister(&ksb->fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700732
Hemant Kumar38980ec42012-08-24 19:42:31 -0700733 usb_kill_anchored_urbs(&ksb->submitted);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700734
735 wait_event_interruptible_timeout(
736 ksb->pending_urb_wait,
737 !atomic_read(&ksb->tx_pending_cnt) &&
738 !atomic_read(&ksb->rx_pending_cnt),
739 msecs_to_jiffies(PENDING_URB_TIMEOUT));
740
Vamsi Krishna5b944712012-06-29 18:36:23 -0700741 spin_lock_irqsave(&ksb->lock, flags);
742 while (!list_empty(&ksb->to_ks_list)) {
743 pkt = list_first_entry(&ksb->to_ks_list,
744 struct data_pkt, list);
745 list_del_init(&pkt->list);
746 ksb_free_data_pkt(pkt);
747 }
748 while (!list_empty(&ksb->to_mdm_list)) {
749 pkt = list_first_entry(&ksb->to_mdm_list,
750 struct data_pkt, list);
751 list_del_init(&pkt->list);
752 ksb_free_data_pkt(pkt);
753 }
754 spin_unlock_irqrestore(&ksb->lock, flags);
755
Hemant Kumarf292a322012-09-07 19:00:21 -0700756 ifc->needs_remote_wakeup = 0;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700757 usb_put_dev(ksb->udev);
758 ksb->ifc = NULL;
759 usb_set_intfdata(ifc, NULL);
760
761 return;
762}
763
764static struct usb_driver ksb_usb_driver = {
765 .name = "ks_bridge",
766 .probe = ksb_usb_probe,
767 .disconnect = ksb_usb_disconnect,
768 .suspend = ksb_usb_suspend,
769 .resume = ksb_usb_resume,
770 .id_table = ksb_usb_ids,
771 .supports_autosuspend = 1,
772};
773
774static ssize_t ksb_debug_show(struct seq_file *s, void *unused)
775{
776 unsigned long flags;
777 struct ks_bridge *ksb = s->private;
778 int i;
779
780 read_lock_irqsave(&ksb->dbg_lock, flags);
781 for (i = 0; i < DBG_MAX_MSG; i++) {
782 if (i == (ksb->dbg_idx - 1))
783 seq_printf(s, "-->%s\n", ksb->dbgbuf[i]);
784 else
785 seq_printf(s, "%s\n", ksb->dbgbuf[i]);
786 }
787 read_unlock_irqrestore(&ksb->dbg_lock, flags);
788
789 return 0;
790}
791
792static int ksb_debug_open(struct inode *ip, struct file *fp)
793{
794 return single_open(fp, ksb_debug_show, ip->i_private);
795
796 return 0;
797}
798
799static const struct file_operations dbg_fops = {
800 .open = ksb_debug_open,
801 .read = seq_read,
802 .llseek = seq_lseek,
803 .release = single_release,
804};
805static struct dentry *dbg_dir;
806static int __init ksb_init(void)
807{
808 struct ks_bridge *ksb;
809 int num_instances = 0;
810 int ret = 0;
811 int i;
812
813 dbg_dir = debugfs_create_dir("ks_bridge", NULL);
814 if (IS_ERR(dbg_dir))
815 pr_err("unable to create debug dir");
816
817 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
818 ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
819 if (!ksb) {
820 pr_err("unable to allocat mem for ks_bridge");
Hemant Kumar38980ec42012-08-24 19:42:31 -0700821 ret = -ENOMEM;
822 goto dev_free;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700823 }
824 __ksb[i] = ksb;
825
826 ksb->name = kasprintf(GFP_KERNEL, "ks_bridge:%i", i + 1);
827 if (!ksb->name) {
828 pr_info("unable to allocate name");
829 kfree(ksb);
830 ret = -ENOMEM;
831 goto dev_free;
832 }
833
834 spin_lock_init(&ksb->lock);
835 INIT_LIST_HEAD(&ksb->to_mdm_list);
836 INIT_LIST_HEAD(&ksb->to_ks_list);
837 init_waitqueue_head(&ksb->ks_wait_q);
Hemant Kumarea4b0b02012-09-16 20:28:56 -0700838 init_waitqueue_head(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700839 ksb->wq = create_singlethread_workqueue(ksb->name);
840 if (!ksb->wq) {
841 pr_err("unable to allocate workqueue");
842 kfree(ksb->name);
843 kfree(ksb);
844 ret = -ENOMEM;
845 goto dev_free;
846 }
847
848 INIT_WORK(&ksb->to_mdm_work, ksb_tomdm_work);
849 INIT_WORK(&ksb->start_rx_work, ksb_start_rx_work);
850 init_usb_anchor(&ksb->submitted);
851
852 ksb->dbg_idx = 0;
853 ksb->dbg_lock = __RW_LOCK_UNLOCKED(lck);
854
855 if (!IS_ERR(dbg_dir))
856 debugfs_create_file(ksb->name, S_IRUGO, dbg_dir,
857 ksb, &dbg_fops);
858
859 num_instances++;
860 }
861
862 ret = usb_register(&ksb_usb_driver);
863 if (ret) {
864 pr_err("unable to register ks bridge driver");
865 goto dev_free;
866 }
867
868 pr_info("init done");
869
870 return 0;
871
872dev_free:
873 if (!IS_ERR(dbg_dir))
874 debugfs_remove_recursive(dbg_dir);
875
876 for (i = 0; i < num_instances; i++) {
877 ksb = __ksb[i];
878
879 destroy_workqueue(ksb->wq);
880 kfree(ksb->name);
881 kfree(ksb);
882 }
883
884 return ret;
885
886}
887
888static void __exit ksb_exit(void)
889{
890 struct ks_bridge *ksb;
891 int i;
892
893 if (!IS_ERR(dbg_dir))
894 debugfs_remove_recursive(dbg_dir);
895
896 usb_deregister(&ksb_usb_driver);
897
898 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
899 ksb = __ksb[i];
900
901 destroy_workqueue(ksb->wq);
902 kfree(ksb->name);
903 kfree(ksb);
904 }
905}
906
907module_init(ksb_init);
908module_exit(ksb_exit);
909
910MODULE_DESCRIPTION(DRIVER_DESC);
911MODULE_VERSION(DRIVER_VERSION);
912MODULE_LICENSE("GPL v2");