blob: ca57d4343b434e17304d0b129a71e07a5df924e1 [file] [log] [blame]
Pavankumar Kondeti50f38152013-01-17 16:04:53 +05301/* Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
Hemant Kumar14401d52011-11-03 16:40:32 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/debugfs.h>
19#include <linux/platform_device.h>
20#include <linux/uaccess.h>
21#include <linux/ratelimit.h>
22#include <mach/usb_bridge.h>
23
Hemant Kumare8f691f2012-10-03 17:15:28 -070024#define MAX_RX_URBS 100
Hemant Kumar14401d52011-11-03 16:40:32 -070025#define RMNET_RX_BUFSIZE 2048
26
Hemant Kumarfd2d5e52011-12-22 17:51:53 -080027#define STOP_SUBMIT_URB_LIMIT 500
Hemant Kumar14401d52011-11-03 16:40:32 -070028#define FLOW_CTRL_EN_THRESHOLD 500
29#define FLOW_CTRL_DISABLE 300
30#define FLOW_CTRL_SUPPORT 1
31
Hemant Kumarc2b17782013-02-03 15:56:29 -080032#define BRIDGE_DATA_IDX 0
33#define BRIDGE_CTRL_IDX 1
34
35/*for xport : HSIC*/
36static const char * const serial_hsic_bridge_names[] = {
37 "serial_hsic_data",
38 "serial_hsic_ctrl",
39};
40
41static const char * const rmnet_hsic_bridge_names[] = {
42 "rmnet_hsic_data",
43 "rmnet_hsic_ctrl",
Hemant Kumar14401d52011-11-03 16:40:32 -070044};
45
Hemant Kumar67107002013-02-11 13:24:08 -080046/*for xport : HSUSB*/
47static const char * const serial_hsusb_bridge_names[] = {
48 "serial_hsusb_data",
49 "serial_hsusb_ctrl",
50};
51
52static const char * const rmnet_hsusb_bridge_names[] = {
53 "rmnet_hsusb_data",
54 "rmnet_hsusb_ctrl",
55};
56
57/* since driver supports multiple instances, on smp systems
58 * probe might get called from multiple cores, hence use lock
59 * to identify unclaimed bridge device instance
60 */
61static DEFINE_MUTEX(brdg_claim_lock);
62
Hemant Kumar14401d52011-11-03 16:40:32 -070063static struct workqueue_struct *bridge_wq;
64
65static unsigned int fctrl_support = FLOW_CTRL_SUPPORT;
66module_param(fctrl_support, uint, S_IRUGO | S_IWUSR);
67
68static unsigned int fctrl_en_thld = FLOW_CTRL_EN_THRESHOLD;
69module_param(fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
70
71static unsigned int fctrl_dis_thld = FLOW_CTRL_DISABLE;
72module_param(fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
73
74unsigned int max_rx_urbs = MAX_RX_URBS;
75module_param(max_rx_urbs, uint, S_IRUGO | S_IWUSR);
76
77unsigned int stop_submit_urb_limit = STOP_SUBMIT_URB_LIMIT;
78module_param(stop_submit_urb_limit, uint, S_IRUGO | S_IWUSR);
79
Hemant Kumar73eff1c2012-01-09 18:49:11 -080080static unsigned tx_urb_mult = 20;
81module_param(tx_urb_mult, uint, S_IRUGO|S_IWUSR);
82
Hemant Kumar67107002013-02-11 13:24:08 -080083#define TX_HALT 0
84#define RX_HALT 1
85#define SUSPENDED 2
86#define CLAIMED 3
Hemant Kumar14401d52011-11-03 16:40:32 -070087
88struct data_bridge {
89 struct usb_interface *intf;
90 struct usb_device *udev;
Jack Pham9b0a0e52012-02-28 18:05:14 -080091 int id;
Hemant Kumarc2b17782013-02-03 15:56:29 -080092 char *name;
Jack Pham9b0a0e52012-02-28 18:05:14 -080093
Hemant Kumar14401d52011-11-03 16:40:32 -070094 unsigned int bulk_in;
95 unsigned int bulk_out;
Hemant Kumar06b7e432012-01-19 22:13:50 -080096 int err;
Hemant Kumar14401d52011-11-03 16:40:32 -070097
98 /* keep track of in-flight URBs */
99 struct usb_anchor tx_active;
100 struct usb_anchor rx_active;
101
102 /* keep track of outgoing URBs during suspend */
103 struct usb_anchor delayed;
104
105 struct list_head rx_idle;
106 struct sk_buff_head rx_done;
107
108 struct workqueue_struct *wq;
109 struct work_struct process_rx_w;
110
111 struct bridge *brdg;
112
113 /* work queue function for handling halt conditions */
114 struct work_struct kevent;
115
116 unsigned long flags;
117
118 struct platform_device *pdev;
119
120 /* counters */
121 atomic_t pending_txurbs;
122 unsigned int txurb_drp_cnt;
123 unsigned long to_host;
124 unsigned long to_modem;
125 unsigned int tx_throttled_cnt;
126 unsigned int tx_unthrottled_cnt;
127 unsigned int rx_throttled_cnt;
128 unsigned int rx_unthrottled_cnt;
129};
130
131static struct data_bridge *__dev[MAX_BRIDGE_DEVICES];
132
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800133static unsigned int get_timestamp(void);
134static void dbg_timestamp(char *, struct sk_buff *);
Hemant Kumar14401d52011-11-03 16:40:32 -0700135static int submit_rx_urb(struct data_bridge *dev, struct urb *urb,
136 gfp_t flags);
137
Hemant Kumar67107002013-02-11 13:24:08 -0800138/* Find an unclaimed bridge device instance */
139static int get_bridge_dev_idx(void)
140{
141 struct data_bridge *dev;
142 int i;
143
144 mutex_lock(&brdg_claim_lock);
145 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
146 dev = __dev[i];
147 if (!test_bit(CLAIMED, &dev->flags)) {
148 set_bit(CLAIMED, &dev->flags);
149 mutex_unlock(&brdg_claim_lock);
150 return i;
151 }
152 }
153 mutex_unlock(&brdg_claim_lock);
154
155 return -ENODEV;
156}
157
Hemant Kumarc2b17782013-02-03 15:56:29 -0800158static int get_data_bridge_chid(char *xport_name)
159{
160 struct data_bridge *dev;
161 int i;
162
163 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
164 dev = __dev[i];
165 if (!strncmp(dev->name, xport_name, BRIDGE_NAME_MAX_LEN))
166 return i;
167 }
168
169 return -ENODEV;
170}
171
Hemant Kumar14401d52011-11-03 16:40:32 -0700172static inline bool rx_halted(struct data_bridge *dev)
173{
174 return test_bit(RX_HALT, &dev->flags);
175}
176
177static inline bool rx_throttled(struct bridge *brdg)
178{
179 return test_bit(RX_THROTTLED, &brdg->flags);
180}
181
Hemant Kumar262682a2013-02-01 09:46:45 -0800182static void free_rx_urbs(struct data_bridge *dev)
183{
184 struct list_head *head;
185 struct urb *rx_urb;
186 unsigned long flags;
187
188 head = &dev->rx_idle;
189 spin_lock_irqsave(&dev->rx_done.lock, flags);
190 while (!list_empty(head)) {
191 rx_urb = list_entry(head->next, struct urb, urb_list);
192 list_del(&rx_urb->urb_list);
193 usb_free_urb(rx_urb);
194 }
195 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
196}
197
Hemant Kumar14401d52011-11-03 16:40:32 -0700198int data_bridge_unthrottle_rx(unsigned int id)
199{
200 struct data_bridge *dev;
201
202 if (id >= MAX_BRIDGE_DEVICES)
203 return -EINVAL;
204
205 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800206 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700207 return -ENODEV;
208
209 dev->rx_unthrottled_cnt++;
210 queue_work(dev->wq, &dev->process_rx_w);
211
212 return 0;
213}
214EXPORT_SYMBOL(data_bridge_unthrottle_rx);
215
216static void data_bridge_process_rx(struct work_struct *work)
217{
218 int retval;
219 unsigned long flags;
220 struct urb *rx_idle;
221 struct sk_buff *skb;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800222 struct timestamp_info *info;
Hemant Kumar14401d52011-11-03 16:40:32 -0700223 struct data_bridge *dev =
224 container_of(work, struct data_bridge, process_rx_w);
225
226 struct bridge *brdg = dev->brdg;
227
228 if (!brdg || !brdg->ops.send_pkt || rx_halted(dev))
229 return;
230
231 while (!rx_throttled(brdg) && (skb = skb_dequeue(&dev->rx_done))) {
232 dev->to_host++;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800233 info = (struct timestamp_info *)skb->cb;
234 info->rx_done_sent = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700235 /* hand off sk_buff to client,they'll need to free it */
236 retval = brdg->ops.send_pkt(brdg->ctx, skb, skb->len);
237 if (retval == -ENOTCONN || retval == -EINVAL) {
238 return;
239 } else if (retval == -EBUSY) {
240 dev->rx_throttled_cnt++;
241 break;
242 }
243 }
244
245 spin_lock_irqsave(&dev->rx_done.lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700246 while (!list_empty(&dev->rx_idle)) {
Hemant Kumarfd2d5e52011-12-22 17:51:53 -0800247 if (dev->rx_done.qlen > stop_submit_urb_limit)
248 break;
Hemant Kumar14401d52011-11-03 16:40:32 -0700249
250 rx_idle = list_first_entry(&dev->rx_idle, struct urb, urb_list);
251 list_del(&rx_idle->urb_list);
252 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
253 retval = submit_rx_urb(dev, rx_idle, GFP_KERNEL);
254 spin_lock_irqsave(&dev->rx_done.lock, flags);
Hemant Kumar184765b2011-12-27 13:20:45 -0800255 if (retval) {
256 list_add_tail(&rx_idle->urb_list, &dev->rx_idle);
Hemant Kumar14401d52011-11-03 16:40:32 -0700257 break;
Hemant Kumar184765b2011-12-27 13:20:45 -0800258 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700259 }
260 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
261}
262
263static void data_bridge_read_cb(struct urb *urb)
264{
265 struct bridge *brdg;
266 struct sk_buff *skb = urb->context;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800267 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
268 struct data_bridge *dev = info->dev;
Hemant Kumar14401d52011-11-03 16:40:32 -0700269 bool queue = 0;
270
Hemant Kumar262682a2013-02-01 09:46:45 -0800271 /*usb device disconnect*/
272 if (urb->dev->state == USB_STATE_NOTATTACHED)
273 urb->status = -ECONNRESET;
274
Hemant Kumar14401d52011-11-03 16:40:32 -0700275 brdg = dev->brdg;
Hemant Kumar14401d52011-11-03 16:40:32 -0700276 skb_put(skb, urb->actual_length);
277
278 switch (urb->status) {
279 case 0: /* success */
280 queue = 1;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800281 info->rx_done = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700282 spin_lock(&dev->rx_done.lock);
283 __skb_queue_tail(&dev->rx_done, skb);
284 spin_unlock(&dev->rx_done.lock);
285 break;
286
287 /*do not resubmit*/
288 case -EPIPE:
289 set_bit(RX_HALT, &dev->flags);
Jack Phame8741502012-06-13 17:34:07 -0700290 dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700291 schedule_work(&dev->kevent);
292 /* FALLTHROUGH */
293 case -ESHUTDOWN:
294 case -ENOENT: /* suspended */
295 case -ECONNRESET: /* unplug */
296 case -EPROTO:
297 dev_kfree_skb_any(skb);
298 break;
299
300 /*resubmit */
301 case -EOVERFLOW: /*babble error*/
302 default:
303 queue = 1;
304 dev_kfree_skb_any(skb);
305 pr_debug_ratelimited("%s: non zero urb status = %d\n",
306 __func__, urb->status);
307 break;
308 }
309
310 spin_lock(&dev->rx_done.lock);
311 list_add_tail(&urb->urb_list, &dev->rx_idle);
312 spin_unlock(&dev->rx_done.lock);
313
314 if (queue)
315 queue_work(dev->wq, &dev->process_rx_w);
316}
317
318static int submit_rx_urb(struct data_bridge *dev, struct urb *rx_urb,
319 gfp_t flags)
320{
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800321 struct sk_buff *skb;
322 struct timestamp_info *info;
323 int retval = -EINVAL;
324 unsigned int created;
Hemant Kumar14401d52011-11-03 16:40:32 -0700325
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800326 created = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700327 skb = alloc_skb(RMNET_RX_BUFSIZE, flags);
Hemant Kumar184765b2011-12-27 13:20:45 -0800328 if (!skb)
Hemant Kumar14401d52011-11-03 16:40:32 -0700329 return -ENOMEM;
Hemant Kumar14401d52011-11-03 16:40:32 -0700330
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800331 info = (struct timestamp_info *)skb->cb;
332 info->dev = dev;
333 info->created = created;
Hemant Kumar14401d52011-11-03 16:40:32 -0700334
335 usb_fill_bulk_urb(rx_urb, dev->udev, dev->bulk_in,
336 skb->data, RMNET_RX_BUFSIZE,
337 data_bridge_read_cb, skb);
338
339 if (test_bit(SUSPENDED, &dev->flags))
340 goto suspended;
341
342 usb_anchor_urb(rx_urb, &dev->rx_active);
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800343 info->rx_queued = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700344 retval = usb_submit_urb(rx_urb, flags);
345 if (retval)
346 goto fail;
347
Hemant Kumarb72233f2012-04-04 13:21:44 -0700348 usb_mark_last_busy(dev->udev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700349 return 0;
350fail:
351 usb_unanchor_urb(rx_urb);
352suspended:
353 dev_kfree_skb_any(skb);
Hemant Kumar184765b2011-12-27 13:20:45 -0800354
Hemant Kumar14401d52011-11-03 16:40:32 -0700355 return retval;
356}
357
358static int data_bridge_prepare_rx(struct data_bridge *dev)
359{
360 int i;
361 struct urb *rx_urb;
Hemant Kumar262682a2013-02-01 09:46:45 -0800362 int retval = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700363
364 for (i = 0; i < max_rx_urbs; i++) {
365 rx_urb = usb_alloc_urb(0, GFP_KERNEL);
Hemant Kumar262682a2013-02-01 09:46:45 -0800366 if (!rx_urb) {
367 retval = -ENOMEM;
368 goto free_urbs;
369 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700370
371 list_add_tail(&rx_urb->urb_list, &dev->rx_idle);
372 }
Hemant Kumar262682a2013-02-01 09:46:45 -0800373
374 return 0;
375
376free_urbs:
377 free_rx_urbs(dev);
378 return retval;
Hemant Kumar14401d52011-11-03 16:40:32 -0700379}
380
381int data_bridge_open(struct bridge *brdg)
382{
383 struct data_bridge *dev;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800384 int ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700385
386 if (!brdg) {
387 err("bridge is null\n");
388 return -EINVAL;
389 }
390
Hemant Kumarc2b17782013-02-03 15:56:29 -0800391 ch_id = get_data_bridge_chid(brdg->name);
392 if (ch_id < 0 || ch_id >= MAX_BRIDGE_DEVICES) {
393 err("%s: %s dev not found\n", __func__, brdg->name);
394 return ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700395 }
396
Hemant Kumarc2b17782013-02-03 15:56:29 -0800397 brdg->ch_id = ch_id;
398
399 dev = __dev[ch_id];
400
Jack Phame8741502012-06-13 17:34:07 -0700401 dev_dbg(&dev->intf->dev, "%s: dev:%p\n", __func__, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700402
403 dev->brdg = brdg;
Hemant Kumar06b7e432012-01-19 22:13:50 -0800404 dev->err = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700405 atomic_set(&dev->pending_txurbs, 0);
406 dev->to_host = 0;
407 dev->to_modem = 0;
408 dev->txurb_drp_cnt = 0;
409 dev->tx_throttled_cnt = 0;
410 dev->tx_unthrottled_cnt = 0;
411 dev->rx_throttled_cnt = 0;
412 dev->rx_unthrottled_cnt = 0;
413
414 queue_work(dev->wq, &dev->process_rx_w);
415
416 return 0;
417}
418EXPORT_SYMBOL(data_bridge_open);
419
420void data_bridge_close(unsigned int id)
421{
422 struct data_bridge *dev;
423 struct sk_buff *skb;
424 unsigned long flags;
425
426 if (id >= MAX_BRIDGE_DEVICES)
427 return;
428
429 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800430 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700431 return;
432
Jack Phame8741502012-06-13 17:34:07 -0700433 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700434
Pavankumar Kondeti50f38152013-01-17 16:04:53 +0530435 cancel_work_sync(&dev->kevent);
436 cancel_work_sync(&dev->process_rx_w);
437
Hemant Kumar262682a2013-02-01 09:46:45 -0800438 usb_kill_anchored_urbs(&dev->tx_active);
439 usb_kill_anchored_urbs(&dev->rx_active);
440 usb_kill_anchored_urbs(&dev->delayed);
Hemant Kumar14401d52011-11-03 16:40:32 -0700441
442 spin_lock_irqsave(&dev->rx_done.lock, flags);
443 while ((skb = __skb_dequeue(&dev->rx_done)))
444 dev_kfree_skb_any(skb);
445 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
446
447 dev->brdg = NULL;
448}
449EXPORT_SYMBOL(data_bridge_close);
450
451static void defer_kevent(struct work_struct *work)
452{
453 int status;
454 struct data_bridge *dev =
455 container_of(work, struct data_bridge, kevent);
456
457 if (!dev)
458 return;
459
460 if (test_bit(TX_HALT, &dev->flags)) {
461 usb_unlink_anchored_urbs(&dev->tx_active);
462
463 status = usb_autopm_get_interface(dev->intf);
464 if (status < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700465 dev_dbg(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700466 "can't acquire interface, status %d\n", status);
467 return;
468 }
469
470 status = usb_clear_halt(dev->udev, dev->bulk_out);
471 usb_autopm_put_interface(dev->intf);
472 if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
Jack Phame8741502012-06-13 17:34:07 -0700473 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700474 "can't clear tx halt, status %d\n", status);
475 else
476 clear_bit(TX_HALT, &dev->flags);
477 }
478
479 if (test_bit(RX_HALT, &dev->flags)) {
480 usb_unlink_anchored_urbs(&dev->rx_active);
481
482 status = usb_autopm_get_interface(dev->intf);
483 if (status < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700484 dev_dbg(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700485 "can't acquire interface, status %d\n", status);
486 return;
487 }
488
489 status = usb_clear_halt(dev->udev, dev->bulk_in);
490 usb_autopm_put_interface(dev->intf);
491 if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
Jack Phame8741502012-06-13 17:34:07 -0700492 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700493 "can't clear rx halt, status %d\n", status);
494 else {
495 clear_bit(RX_HALT, &dev->flags);
496 if (dev->brdg)
497 queue_work(dev->wq, &dev->process_rx_w);
498 }
499 }
500}
501
502static void data_bridge_write_cb(struct urb *urb)
503{
504 struct sk_buff *skb = urb->context;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800505 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
506 struct data_bridge *dev = info->dev;
Hemant Kumar14401d52011-11-03 16:40:32 -0700507 struct bridge *brdg = dev->brdg;
508 int pending;
509
510 pr_debug("%s: dev:%p\n", __func__, dev);
511
512 switch (urb->status) {
513 case 0: /*success*/
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800514 dbg_timestamp("UL", skb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700515 break;
Hemant Kumar06b7e432012-01-19 22:13:50 -0800516 case -EPROTO:
517 dev->err = -EPROTO;
518 break;
Hemant Kumar14401d52011-11-03 16:40:32 -0700519 case -EPIPE:
520 set_bit(TX_HALT, &dev->flags);
Jack Phame8741502012-06-13 17:34:07 -0700521 dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700522 schedule_work(&dev->kevent);
523 /* FALLTHROUGH */
524 case -ESHUTDOWN:
525 case -ENOENT: /* suspended */
526 case -ECONNRESET: /* unplug */
527 case -EOVERFLOW: /*babble error*/
528 /* FALLTHROUGH */
529 default:
530 pr_debug_ratelimited("%s: non zero urb status = %d\n",
531 __func__, urb->status);
532 }
533
534 usb_free_urb(urb);
535 dev_kfree_skb_any(skb);
536
537 pending = atomic_dec_return(&dev->pending_txurbs);
538
539 /*flow ctrl*/
540 if (brdg && fctrl_support && pending <= fctrl_dis_thld &&
541 test_and_clear_bit(TX_THROTTLED, &brdg->flags)) {
542 pr_debug_ratelimited("%s: disable flow ctrl: pend urbs:%u\n",
543 __func__, pending);
544 dev->tx_unthrottled_cnt++;
545 if (brdg->ops.unthrottle_tx)
546 brdg->ops.unthrottle_tx(brdg->ctx);
547 }
548
Hemant Kumar262682a2013-02-01 09:46:45 -0800549 /* if we are here after device disconnect
550 * usb_unbind_interface() takes care of
551 * residual pm_autopm_get_interface_* calls
552 */
553 if (urb->dev->state != USB_STATE_NOTATTACHED)
554 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700555}
556
557int data_bridge_write(unsigned int id, struct sk_buff *skb)
558{
559 int result;
560 int size = skb->len;
561 int pending;
562 struct urb *txurb;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800563 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
Hemant Kumar14401d52011-11-03 16:40:32 -0700564 struct data_bridge *dev = __dev[id];
565 struct bridge *brdg;
566
Hemant Kumar06b7e432012-01-19 22:13:50 -0800567 if (!dev || !dev->brdg || dev->err || !usb_get_intfdata(dev->intf))
Hemant Kumar14401d52011-11-03 16:40:32 -0700568 return -ENODEV;
569
570 brdg = dev->brdg;
Hemant Kumarc8a3d312011-12-27 15:41:32 -0800571 if (!brdg)
572 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700573
Jack Phame8741502012-06-13 17:34:07 -0700574 dev_dbg(&dev->intf->dev, "%s: write (%d bytes)\n", __func__, skb->len);
Hemant Kumar14401d52011-11-03 16:40:32 -0700575
576 result = usb_autopm_get_interface(dev->intf);
577 if (result < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700578 dev_dbg(&dev->intf->dev, "%s: resume failure\n", __func__);
Hemant Kumar93387bd2012-06-08 15:55:26 -0700579 goto pm_error;
Hemant Kumar14401d52011-11-03 16:40:32 -0700580 }
581
582 txurb = usb_alloc_urb(0, GFP_KERNEL);
583 if (!txurb) {
Jack Phame8741502012-06-13 17:34:07 -0700584 dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700585 __func__);
586 result = -ENOMEM;
587 goto error;
588 }
589
590 /* store dev pointer in skb */
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800591 info->dev = dev;
592 info->tx_queued = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700593
594 usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out,
595 skb->data, skb->len, data_bridge_write_cb, skb);
596
Jack Pham5a10c6f2012-06-26 11:41:28 -0700597 txurb->transfer_flags |= URB_ZERO_PACKET;
598
Hemant Kumar14401d52011-11-03 16:40:32 -0700599 if (test_bit(SUSPENDED, &dev->flags)) {
600 usb_anchor_urb(txurb, &dev->delayed);
601 goto free_urb;
602 }
603
604 pending = atomic_inc_return(&dev->pending_txurbs);
605 usb_anchor_urb(txurb, &dev->tx_active);
606
Hemant Kumar73eff1c2012-01-09 18:49:11 -0800607 if (atomic_read(&dev->pending_txurbs) % tx_urb_mult)
608 txurb->transfer_flags |= URB_NO_INTERRUPT;
609
Hemant Kumar14401d52011-11-03 16:40:32 -0700610 result = usb_submit_urb(txurb, GFP_KERNEL);
611 if (result < 0) {
612 usb_unanchor_urb(txurb);
613 atomic_dec(&dev->pending_txurbs);
Jack Phame8741502012-06-13 17:34:07 -0700614 dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700615 __func__, result);
616 goto free_urb;
617 }
618
619 dev->to_modem++;
Jack Phame8741502012-06-13 17:34:07 -0700620 dev_dbg(&dev->intf->dev, "%s: pending_txurbs: %u\n", __func__, pending);
Hemant Kumar14401d52011-11-03 16:40:32 -0700621
622 /* flow control: last urb submitted but return -EBUSY */
623 if (fctrl_support && pending > fctrl_en_thld) {
624 set_bit(TX_THROTTLED, &brdg->flags);
625 dev->tx_throttled_cnt++;
626 pr_debug_ratelimited("%s: enable flow ctrl pend txurbs:%u\n",
627 __func__, pending);
628 return -EBUSY;
629 }
630
631 return size;
632
633free_urb:
634 usb_free_urb(txurb);
635error:
636 dev->txurb_drp_cnt++;
637 usb_autopm_put_interface(dev->intf);
Hemant Kumar93387bd2012-06-08 15:55:26 -0700638pm_error:
Hemant Kumar14401d52011-11-03 16:40:32 -0700639 return result;
640}
641EXPORT_SYMBOL(data_bridge_write);
642
643static int data_bridge_resume(struct data_bridge *dev)
644{
645 struct urb *urb;
646 int retval;
647
Jack Pham9b0a0e52012-02-28 18:05:14 -0800648 if (!test_and_clear_bit(SUSPENDED, &dev->flags))
649 return 0;
650
Hemant Kumar14401d52011-11-03 16:40:32 -0700651 while ((urb = usb_get_from_anchor(&dev->delayed))) {
652 usb_anchor_urb(urb, &dev->tx_active);
653 atomic_inc(&dev->pending_txurbs);
654 retval = usb_submit_urb(urb, GFP_ATOMIC);
655 if (retval < 0) {
656 atomic_dec(&dev->pending_txurbs);
657 usb_unanchor_urb(urb);
658
659 /* TODO: need to free urb data */
660 usb_scuttle_anchored_urbs(&dev->delayed);
661 break;
662 }
663 dev->to_modem++;
664 dev->txurb_drp_cnt--;
665 }
666
Hemant Kumar14401d52011-11-03 16:40:32 -0700667 if (dev->brdg)
668 queue_work(dev->wq, &dev->process_rx_w);
669
670 return 0;
671}
672
673static int bridge_resume(struct usb_interface *iface)
674{
675 int retval = 0;
676 int oldstate;
677 struct data_bridge *dev = usb_get_intfdata(iface);
Hemant Kumar14401d52011-11-03 16:40:32 -0700678
679 oldstate = iface->dev.power.power_state.event;
680 iface->dev.power.power_state.event = PM_EVENT_ON;
681
Jack Pham9b0a0e52012-02-28 18:05:14 -0800682 if (oldstate & PM_EVENT_SUSPEND) {
683 retval = data_bridge_resume(dev);
684 if (!retval)
685 retval = ctrl_bridge_resume(dev->id);
Hemant Kumar14401d52011-11-03 16:40:32 -0700686 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800687
Hemant Kumar14401d52011-11-03 16:40:32 -0700688 return retval;
689}
690
691static int data_bridge_suspend(struct data_bridge *dev, pm_message_t message)
692{
693 if (atomic_read(&dev->pending_txurbs) &&
694 (message.event & PM_EVENT_AUTO))
695 return -EBUSY;
696
697 set_bit(SUSPENDED, &dev->flags);
698
699 usb_kill_anchored_urbs(&dev->tx_active);
700 usb_kill_anchored_urbs(&dev->rx_active);
701
702 return 0;
703}
704
705static int bridge_suspend(struct usb_interface *intf, pm_message_t message)
706{
707 int retval;
708 struct data_bridge *dev = usb_get_intfdata(intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700709
710 retval = data_bridge_suspend(dev, message);
711 if (!retval) {
Jack Pham9b0a0e52012-02-28 18:05:14 -0800712 retval = ctrl_bridge_suspend(dev->id);
713 intf->dev.power.power_state.event = message.event;
Hemant Kumar14401d52011-11-03 16:40:32 -0700714 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800715
Hemant Kumar14401d52011-11-03 16:40:32 -0700716 return retval;
717}
718
719static int data_bridge_probe(struct usb_interface *iface,
720 struct usb_host_endpoint *bulk_in,
Hemant Kumarc2b17782013-02-03 15:56:29 -0800721 struct usb_host_endpoint *bulk_out, char *name, int id)
Hemant Kumar14401d52011-11-03 16:40:32 -0700722{
723 struct data_bridge *dev;
Hemant Kumar262682a2013-02-01 09:46:45 -0800724 int retval;
Hemant Kumar14401d52011-11-03 16:40:32 -0700725
Hemant Kumar262682a2013-02-01 09:46:45 -0800726 dev = __dev[id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700727 if (!dev) {
Hemant Kumar262682a2013-02-01 09:46:45 -0800728 err("%s: device not found\n", __func__);
729 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700730 }
731
Hemant Kumarc2b17782013-02-03 15:56:29 -0800732 dev->pdev = platform_device_alloc(name, -1);
Hemant Kumar14401d52011-11-03 16:40:32 -0700733 if (!dev->pdev) {
734 err("%s: unable to allocate platform device\n", __func__);
735 kfree(dev);
736 return -ENOMEM;
737 }
738
Hemant Kumar67107002013-02-11 13:24:08 -0800739 /*clear all bits except claimed bit*/
740 clear_bit(RX_HALT, &dev->flags);
741 clear_bit(TX_HALT, &dev->flags);
742 clear_bit(SUSPENDED, &dev->flags);
743
Jack Pham9b0a0e52012-02-28 18:05:14 -0800744 dev->id = id;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800745 dev->name = name;
Hemant Kumar14401d52011-11-03 16:40:32 -0700746 dev->udev = interface_to_usbdev(iface);
747 dev->intf = iface;
748
749 dev->bulk_in = usb_rcvbulkpipe(dev->udev,
750 bulk_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
751
752 dev->bulk_out = usb_sndbulkpipe(dev->udev,
753 bulk_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
754
755 usb_set_intfdata(iface, dev);
756
Hemant Kumar14401d52011-11-03 16:40:32 -0700757 /*allocate list of rx urbs*/
Hemant Kumar262682a2013-02-01 09:46:45 -0800758 retval = data_bridge_prepare_rx(dev);
759 if (retval) {
760 platform_device_put(dev->pdev);
761 return retval;
762 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700763
764 platform_device_add(dev->pdev);
765
766 return 0;
767}
768
769#if defined(CONFIG_DEBUG_FS)
Hemant Kumar67107002013-02-11 13:24:08 -0800770#define DEBUG_BUF_SIZE 4096
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800771
772static unsigned int record_timestamp;
773module_param(record_timestamp, uint, S_IRUGO | S_IWUSR);
774
775static struct timestamp_buf dbg_data = {
776 .idx = 0,
777 .lck = __RW_LOCK_UNLOCKED(lck)
778};
779
780/*get_timestamp - returns time of day in us */
781static unsigned int get_timestamp(void)
782{
783 struct timeval tval;
784 unsigned int stamp;
785
786 if (!record_timestamp)
787 return 0;
788
789 do_gettimeofday(&tval);
790 /* 2^32 = 4294967296. Limit to 4096s. */
791 stamp = tval.tv_sec & 0xFFF;
792 stamp = stamp * 1000000 + tval.tv_usec;
793 return stamp;
794}
795
796static void dbg_inc(unsigned *idx)
797{
798 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
799}
800
801/**
802* dbg_timestamp - Stores timestamp values of a SKB life cycle
803* to debug buffer
804* @event: "UL": Uplink Data
805* @skb: SKB used to store timestamp values to debug buffer
806*/
807static void dbg_timestamp(char *event, struct sk_buff * skb)
808{
809 unsigned long flags;
810 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
811
812 if (!record_timestamp)
813 return;
814
815 write_lock_irqsave(&dbg_data.lck, flags);
816
817 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
818 "%p %u[%s] %u %u %u %u %u %u\n",
819 skb, skb->len, event, info->created, info->rx_queued,
820 info->rx_done, info->rx_done_sent, info->tx_queued,
821 get_timestamp());
822
823 dbg_inc(&dbg_data.idx);
824
825 write_unlock_irqrestore(&dbg_data.lck, flags);
826}
827
828/* show_timestamp: displays the timestamp buffer */
829static ssize_t show_timestamp(struct file *file, char __user *ubuf,
830 size_t count, loff_t *ppos)
831{
832 unsigned long flags;
833 unsigned i;
834 unsigned j = 0;
835 char *buf;
836 int ret = 0;
837
838 if (!record_timestamp)
839 return 0;
840
Hemant Kumar67107002013-02-11 13:24:08 -0800841 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800842 if (!buf)
843 return -ENOMEM;
844
845 read_lock_irqsave(&dbg_data.lck, flags);
846
847 i = dbg_data.idx;
848 for (dbg_inc(&i); i != dbg_data.idx; dbg_inc(&i)) {
849 if (!strnlen(dbg_data.buf[i], DBG_DATA_MSG))
850 continue;
Hemant Kumar67107002013-02-11 13:24:08 -0800851 j += scnprintf(buf + j, DEBUG_BUF_SIZE - j,
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800852 "%s\n", dbg_data.buf[i]);
853 }
854
855 read_unlock_irqrestore(&dbg_data.lck, flags);
856
857 ret = simple_read_from_buffer(ubuf, count, ppos, buf, j);
858
859 kfree(buf);
860
861 return ret;
862}
863
864const struct file_operations data_timestamp_ops = {
865 .read = show_timestamp,
866};
867
Hemant Kumar14401d52011-11-03 16:40:32 -0700868static ssize_t data_bridge_read_stats(struct file *file, char __user *ubuf,
869 size_t count, loff_t *ppos)
870{
871 struct data_bridge *dev;
872 char *buf;
873 int ret;
874 int i;
875 int temp = 0;
876
877 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
878 if (!buf)
879 return -ENOMEM;
880
Hemant Kumar67107002013-02-11 13:24:08 -0800881 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700882 dev = __dev[i];
883 if (!dev)
884 continue;
885
886 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
887 "\nName#%s dev %p\n"
888 "pending tx urbs: %u\n"
889 "tx urb drp cnt: %u\n"
890 "to host: %lu\n"
891 "to mdm: %lu\n"
892 "tx throttled cnt: %u\n"
893 "tx unthrottled cnt: %u\n"
894 "rx throttled cnt: %u\n"
895 "rx unthrottled cnt: %u\n"
896 "rx done skb qlen: %u\n"
Hemant Kumar06b7e432012-01-19 22:13:50 -0800897 "dev err: %d\n"
Hemant Kumar14401d52011-11-03 16:40:32 -0700898 "suspended: %d\n"
899 "TX_HALT: %d\n"
900 "RX_HALT: %d\n",
Hemant Kumar67107002013-02-11 13:24:08 -0800901 dev->name, dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700902 atomic_read(&dev->pending_txurbs),
903 dev->txurb_drp_cnt,
904 dev->to_host,
905 dev->to_modem,
906 dev->tx_throttled_cnt,
907 dev->tx_unthrottled_cnt,
908 dev->rx_throttled_cnt,
909 dev->rx_unthrottled_cnt,
910 dev->rx_done.qlen,
Hemant Kumar06b7e432012-01-19 22:13:50 -0800911 dev->err,
Hemant Kumar14401d52011-11-03 16:40:32 -0700912 test_bit(SUSPENDED, &dev->flags),
913 test_bit(TX_HALT, &dev->flags),
914 test_bit(RX_HALT, &dev->flags));
915
916 }
917
918 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
919
920 kfree(buf);
921
922 return ret;
923}
924
925static ssize_t data_bridge_reset_stats(struct file *file,
926 const char __user *buf, size_t count, loff_t *ppos)
927{
928 struct data_bridge *dev;
929 int i;
930
Hemant Kumar67107002013-02-11 13:24:08 -0800931 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700932 dev = __dev[i];
933 if (!dev)
934 continue;
935
936 dev->to_host = 0;
937 dev->to_modem = 0;
938 dev->txurb_drp_cnt = 0;
939 dev->tx_throttled_cnt = 0;
940 dev->tx_unthrottled_cnt = 0;
941 dev->rx_throttled_cnt = 0;
942 dev->rx_unthrottled_cnt = 0;
943 }
944 return count;
945}
946
947const struct file_operations data_stats_ops = {
948 .read = data_bridge_read_stats,
949 .write = data_bridge_reset_stats,
950};
951
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800952static struct dentry *data_dent;
953static struct dentry *data_dfile_stats;
954static struct dentry *data_dfile_tstamp;
955
Hemant Kumar14401d52011-11-03 16:40:32 -0700956static void data_bridge_debugfs_init(void)
957{
958 data_dent = debugfs_create_dir("data_hsic_bridge", 0);
959 if (IS_ERR(data_dent))
960 return;
961
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800962 data_dfile_stats = debugfs_create_file("status", 0644, data_dent, 0,
963 &data_stats_ops);
964 if (!data_dfile_stats || IS_ERR(data_dfile_stats)) {
965 debugfs_remove(data_dent);
966 return;
967 }
968
969 data_dfile_tstamp = debugfs_create_file("timestamp", 0644, data_dent,
970 0, &data_timestamp_ops);
971 if (!data_dfile_tstamp || IS_ERR(data_dfile_tstamp))
Hemant Kumar14401d52011-11-03 16:40:32 -0700972 debugfs_remove(data_dent);
973}
974
975static void data_bridge_debugfs_exit(void)
976{
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800977 debugfs_remove(data_dfile_stats);
978 debugfs_remove(data_dfile_tstamp);
Hemant Kumar14401d52011-11-03 16:40:32 -0700979 debugfs_remove(data_dent);
980}
981
982#else
983static void data_bridge_debugfs_init(void) { }
984static void data_bridge_debugfs_exit(void) { }
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800985static void dbg_timestamp(char *event, struct sk_buff * skb)
986{
987 return;
988}
989
990static unsigned int get_timestamp(void)
991{
992 return 0;
993}
994
Hemant Kumar14401d52011-11-03 16:40:32 -0700995#endif
996
997static int __devinit
998bridge_probe(struct usb_interface *iface, const struct usb_device_id *id)
999{
1000 struct usb_host_endpoint *endpoint = NULL;
1001 struct usb_host_endpoint *bulk_in = NULL;
1002 struct usb_host_endpoint *bulk_out = NULL;
1003 struct usb_host_endpoint *int_in = NULL;
1004 struct usb_device *udev;
1005 int i;
1006 int status = 0;
1007 int numends;
Hemant Kumar67107002013-02-11 13:24:08 -08001008 int ch_id;
Hemant Kumarc2b17782013-02-03 15:56:29 -08001009 char **bname = (char **)id->driver_info;
Hemant Kumar14401d52011-11-03 16:40:32 -07001010
1011 if (iface->num_altsetting != 1) {
1012 err("%s invalid num_altsetting %u\n",
1013 __func__, iface->num_altsetting);
1014 return -EINVAL;
1015 }
1016
Jack Pham1b1ba472012-06-13 16:40:15 -07001017 udev = interface_to_usbdev(iface);
1018 usb_get_dev(udev);
1019
Hemant Kumar14401d52011-11-03 16:40:32 -07001020 numends = iface->cur_altsetting->desc.bNumEndpoints;
1021 for (i = 0; i < numends; i++) {
1022 endpoint = iface->cur_altsetting->endpoint + i;
1023 if (!endpoint) {
Jack Phame8741502012-06-13 17:34:07 -07001024 dev_err(&iface->dev, "%s: invalid endpoint %u\n",
Hemant Kumar14401d52011-11-03 16:40:32 -07001025 __func__, i);
1026 status = -EINVAL;
1027 goto out;
1028 }
1029
1030 if (usb_endpoint_is_bulk_in(&endpoint->desc))
1031 bulk_in = endpoint;
1032 else if (usb_endpoint_is_bulk_out(&endpoint->desc))
1033 bulk_out = endpoint;
1034 else if (usb_endpoint_is_int_in(&endpoint->desc))
1035 int_in = endpoint;
1036 }
1037
1038 if (!bulk_in || !bulk_out || !int_in) {
Jack Phame8741502012-06-13 17:34:07 -07001039 dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -07001040 status = -EINVAL;
1041 goto out;
1042 }
1043
Hemant Kumar67107002013-02-11 13:24:08 -08001044 ch_id = get_bridge_dev_idx();
1045 if (ch_id < 0) {
1046 err("%s all bridge channels claimed. Probe failed\n", __func__);
1047 return -ENODEV;
1048 }
1049
Hemant Kumarc2b17782013-02-03 15:56:29 -08001050 status = data_bridge_probe(iface, bulk_in, bulk_out,
1051 bname[BRIDGE_DATA_IDX], ch_id);
Hemant Kumar14401d52011-11-03 16:40:32 -07001052 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -07001053 dev_err(&iface->dev, "data_bridge_probe failed %d\n", status);
Hemant Kumar14401d52011-11-03 16:40:32 -07001054 goto out;
1055 }
1056
Hemant Kumarc2b17782013-02-03 15:56:29 -08001057 status = ctrl_bridge_probe(iface, int_in, bname[BRIDGE_CTRL_IDX],
1058 ch_id);
Hemant Kumar14401d52011-11-03 16:40:32 -07001059 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -07001060 dev_err(&iface->dev, "ctrl_bridge_probe failed %d\n", status);
Hemant Kumar262682a2013-02-01 09:46:45 -08001061 goto error;
Hemant Kumar14401d52011-11-03 16:40:32 -07001062 }
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001063
Hemant Kumar14401d52011-11-03 16:40:32 -07001064 return 0;
1065
Hemant Kumar262682a2013-02-01 09:46:45 -08001066error:
1067 platform_device_put(__dev[ch_id]->pdev);
1068 free_rx_urbs(__dev[ch_id]);
Hemant Kumar14401d52011-11-03 16:40:32 -07001069 usb_set_intfdata(iface, NULL);
Hemant Kumar14401d52011-11-03 16:40:32 -07001070out:
1071 usb_put_dev(udev);
1072
1073 return status;
1074}
1075
1076static void bridge_disconnect(struct usb_interface *intf)
1077{
1078 struct data_bridge *dev = usb_get_intfdata(intf);
Hemant Kumar14401d52011-11-03 16:40:32 -07001079
1080 if (!dev) {
1081 err("%s: data device not found\n", __func__);
1082 return;
1083 }
1084
Hemant Kumar67107002013-02-11 13:24:08 -08001085 /*set device name to none to get correct channel id
1086 * at the time of bridge open
1087 */
1088 dev->name = "none";
1089
Hemant Kumar45bdca82012-09-02 11:10:35 -07001090 ctrl_bridge_disconnect(dev->id);
Jack Pham1b1ba472012-06-13 16:40:15 -07001091 platform_device_unregister(dev->pdev);
Hemant Kumar14401d52011-11-03 16:40:32 -07001092 usb_set_intfdata(intf, NULL);
Hemant Kumar14401d52011-11-03 16:40:32 -07001093
Hemant Kumar262682a2013-02-01 09:46:45 -08001094 free_rx_urbs(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -07001095
1096 usb_put_dev(dev->udev);
Hemant Kumar67107002013-02-11 13:24:08 -08001097
1098 clear_bit(CLAIMED, &dev->flags);
Hemant Kumar14401d52011-11-03 16:40:32 -07001099}
1100
Hemant Kumarc2b17782013-02-03 15:56:29 -08001101/*driver info stores data/ctrl bridge name used to match bridge xport name*/
Hemant Kumar14401d52011-11-03 16:40:32 -07001102static const struct usb_device_id bridge_ids[] = {
Hemant Kumarc2b17782013-02-03 15:56:29 -08001103 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 2),
1104 .driver_info = (unsigned long)serial_hsic_bridge_names,
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001105 },
Hemant Kumarc2b17782013-02-03 15:56:29 -08001106 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9001, 3),
1107 .driver_info = (unsigned long)rmnet_hsic_bridge_names,
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001108 },
Hemant Kumarc2b17782013-02-03 15:56:29 -08001109 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 2),
1110 .driver_info = (unsigned long)serial_hsic_bridge_names,
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001111 },
Hemant Kumarc2b17782013-02-03 15:56:29 -08001112 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 3),
1113 .driver_info = (unsigned long)rmnet_hsic_bridge_names,
Hemant Kumare97cbb32012-02-24 13:00:57 -08001114 },
Hemant Kumarc2b17782013-02-03 15:56:29 -08001115 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 3),
1116 .driver_info = (unsigned long)serial_hsic_bridge_names,
1117 },
1118 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 4),
1119 .driver_info = (unsigned long)rmnet_hsic_bridge_names,
1120 },
1121 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904c, 3),
1122 .driver_info = (unsigned long)serial_hsic_bridge_names,
1123 },
1124 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x904c, 5),
1125 .driver_info = (unsigned long)rmnet_hsic_bridge_names,
1126 },
1127 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 3),
1128 .driver_info = (unsigned long)serial_hsic_bridge_names,
1129 },
1130 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9075, 5),
1131 .driver_info = (unsigned long)rmnet_hsic_bridge_names,
Hemant Kumarce3c5bf2012-12-06 15:52:02 -08001132 },
Hemant Kumar67107002013-02-11 13:24:08 -08001133 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 3),
1134 .driver_info = (unsigned long)serial_hsusb_bridge_names,
1135 },
1136 { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9079, 4),
1137 .driver_info = (unsigned long)rmnet_hsusb_bridge_names,
1138 },
Jack Phamb1ad7152011-12-07 10:58:11 -08001139
1140 { } /* Terminating entry */
Hemant Kumar14401d52011-11-03 16:40:32 -07001141};
Hemant Kumar14401d52011-11-03 16:40:32 -07001142MODULE_DEVICE_TABLE(usb, bridge_ids);
1143
1144static struct usb_driver bridge_driver = {
1145 .name = "mdm_bridge",
1146 .probe = bridge_probe,
1147 .disconnect = bridge_disconnect,
1148 .id_table = bridge_ids,
1149 .suspend = bridge_suspend,
1150 .resume = bridge_resume,
1151 .supports_autosuspend = 1,
1152};
1153
1154static int __init bridge_init(void)
1155{
Hemant Kumar262682a2013-02-01 09:46:45 -08001156 struct data_bridge *dev;
1157 int ret;
1158 int i = 0;
1159
1160 ret = ctrl_bridge_init();
1161 if (ret)
1162 return ret;
1163
1164 bridge_wq = create_singlethread_workqueue("mdm_bridge");
1165 if (!bridge_wq) {
1166 pr_err("%s: Unable to create workqueue:bridge\n", __func__);
1167 ret = -ENOMEM;
1168 goto free_ctrl;
1169 }
1170
1171 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
1172
1173 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1174 if (!dev) {
1175 err("%s: unable to allocate dev\n", __func__);
1176 ret = -ENOMEM;
1177 goto error;
1178 }
1179
1180 dev->wq = bridge_wq;
1181
Hemant Kumarc2b17782013-02-03 15:56:29 -08001182 /*transport name will be set during probe*/
Hemant Kumar67107002013-02-11 13:24:08 -08001183 dev->name = "none";
Hemant Kumarc2b17782013-02-03 15:56:29 -08001184
Hemant Kumar262682a2013-02-01 09:46:45 -08001185 init_usb_anchor(&dev->tx_active);
1186 init_usb_anchor(&dev->rx_active);
1187 init_usb_anchor(&dev->delayed);
1188
1189 INIT_LIST_HEAD(&dev->rx_idle);
1190
1191 skb_queue_head_init(&dev->rx_done);
1192
1193 INIT_WORK(&dev->kevent, defer_kevent);
1194 INIT_WORK(&dev->process_rx_w, data_bridge_process_rx);
1195
1196 __dev[i] = dev;
1197 }
Hemant Kumar14401d52011-11-03 16:40:32 -07001198
1199 ret = usb_register(&bridge_driver);
1200 if (ret) {
1201 err("%s: unable to register mdm_bridge driver", __func__);
Hemant Kumar262682a2013-02-01 09:46:45 -08001202 goto error;
Hemant Kumar14401d52011-11-03 16:40:32 -07001203 }
1204
1205 data_bridge_debugfs_init();
1206
1207 return 0;
Hemant Kumar262682a2013-02-01 09:46:45 -08001208
1209error:
1210 while (--i >= 0) {
1211 kfree(__dev[i]);
1212 __dev[i] = NULL;
1213 }
1214 destroy_workqueue(bridge_wq);
1215free_ctrl:
1216 ctrl_bridge_exit();
1217 return ret;
Hemant Kumar14401d52011-11-03 16:40:32 -07001218}
1219
1220static void __exit bridge_exit(void)
1221{
Hemant Kumar262682a2013-02-01 09:46:45 -08001222 int i;
1223
1224 usb_deregister(&bridge_driver);
Hemant Kumar14401d52011-11-03 16:40:32 -07001225 data_bridge_debugfs_exit();
1226 destroy_workqueue(bridge_wq);
Hemant Kumar262682a2013-02-01 09:46:45 -08001227
1228 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
1229 kfree(__dev[i]);
1230 __dev[i] = NULL;
1231 }
1232
1233 ctrl_bridge_exit();
Hemant Kumar14401d52011-11-03 16:40:32 -07001234}
1235
1236module_init(bridge_init);
1237module_exit(bridge_exit);
1238
1239MODULE_DESCRIPTION("Qualcomm modem data bridge driver");
1240MODULE_LICENSE("GPL v2");