blob: db2f40ab4ad38d0f3a68c1addf667065e0e8bde8 [file] [log] [blame]
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. 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
24#define MAX_RX_URBS 50
25#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
32static const char *data_bridge_names[] = {
33 "dun_data_hsic0",
34 "rmnet_data_hsic0"
35};
36
37static struct workqueue_struct *bridge_wq;
38
39static unsigned int fctrl_support = FLOW_CTRL_SUPPORT;
40module_param(fctrl_support, uint, S_IRUGO | S_IWUSR);
41
42static unsigned int fctrl_en_thld = FLOW_CTRL_EN_THRESHOLD;
43module_param(fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
44
45static unsigned int fctrl_dis_thld = FLOW_CTRL_DISABLE;
46module_param(fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
47
48unsigned int max_rx_urbs = MAX_RX_URBS;
49module_param(max_rx_urbs, uint, S_IRUGO | S_IWUSR);
50
51unsigned int stop_submit_urb_limit = STOP_SUBMIT_URB_LIMIT;
52module_param(stop_submit_urb_limit, uint, S_IRUGO | S_IWUSR);
53
Hemant Kumar73eff1c2012-01-09 18:49:11 -080054static unsigned tx_urb_mult = 20;
55module_param(tx_urb_mult, uint, S_IRUGO|S_IWUSR);
56
Hemant Kumar14401d52011-11-03 16:40:32 -070057#define TX_HALT BIT(0)
58#define RX_HALT BIT(1)
59#define SUSPENDED BIT(2)
60
61struct data_bridge {
62 struct usb_interface *intf;
63 struct usb_device *udev;
Jack Pham9b0a0e52012-02-28 18:05:14 -080064 int id;
65
Hemant Kumar14401d52011-11-03 16:40:32 -070066 unsigned int bulk_in;
67 unsigned int bulk_out;
Hemant Kumar06b7e432012-01-19 22:13:50 -080068 int err;
Hemant Kumar14401d52011-11-03 16:40:32 -070069
70 /* keep track of in-flight URBs */
71 struct usb_anchor tx_active;
72 struct usb_anchor rx_active;
73
74 /* keep track of outgoing URBs during suspend */
75 struct usb_anchor delayed;
76
77 struct list_head rx_idle;
78 struct sk_buff_head rx_done;
79
80 struct workqueue_struct *wq;
81 struct work_struct process_rx_w;
82
83 struct bridge *brdg;
84
85 /* work queue function for handling halt conditions */
86 struct work_struct kevent;
87
88 unsigned long flags;
89
90 struct platform_device *pdev;
91
92 /* counters */
93 atomic_t pending_txurbs;
94 unsigned int txurb_drp_cnt;
95 unsigned long to_host;
96 unsigned long to_modem;
97 unsigned int tx_throttled_cnt;
98 unsigned int tx_unthrottled_cnt;
99 unsigned int rx_throttled_cnt;
100 unsigned int rx_unthrottled_cnt;
101};
102
103static struct data_bridge *__dev[MAX_BRIDGE_DEVICES];
104
105/* counter used for indexing data bridge devices */
106static int ch_id;
107
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800108static unsigned int get_timestamp(void);
109static void dbg_timestamp(char *, struct sk_buff *);
Hemant Kumar14401d52011-11-03 16:40:32 -0700110static int submit_rx_urb(struct data_bridge *dev, struct urb *urb,
111 gfp_t flags);
112
113static inline bool rx_halted(struct data_bridge *dev)
114{
115 return test_bit(RX_HALT, &dev->flags);
116}
117
118static inline bool rx_throttled(struct bridge *brdg)
119{
120 return test_bit(RX_THROTTLED, &brdg->flags);
121}
122
123int data_bridge_unthrottle_rx(unsigned int id)
124{
125 struct data_bridge *dev;
126
127 if (id >= MAX_BRIDGE_DEVICES)
128 return -EINVAL;
129
130 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800131 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700132 return -ENODEV;
133
134 dev->rx_unthrottled_cnt++;
135 queue_work(dev->wq, &dev->process_rx_w);
136
137 return 0;
138}
139EXPORT_SYMBOL(data_bridge_unthrottle_rx);
140
141static void data_bridge_process_rx(struct work_struct *work)
142{
143 int retval;
144 unsigned long flags;
145 struct urb *rx_idle;
146 struct sk_buff *skb;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800147 struct timestamp_info *info;
Hemant Kumar14401d52011-11-03 16:40:32 -0700148 struct data_bridge *dev =
149 container_of(work, struct data_bridge, process_rx_w);
150
151 struct bridge *brdg = dev->brdg;
152
153 if (!brdg || !brdg->ops.send_pkt || rx_halted(dev))
154 return;
155
156 while (!rx_throttled(brdg) && (skb = skb_dequeue(&dev->rx_done))) {
157 dev->to_host++;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800158 info = (struct timestamp_info *)skb->cb;
159 info->rx_done_sent = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700160 /* hand off sk_buff to client,they'll need to free it */
161 retval = brdg->ops.send_pkt(brdg->ctx, skb, skb->len);
162 if (retval == -ENOTCONN || retval == -EINVAL) {
163 return;
164 } else if (retval == -EBUSY) {
165 dev->rx_throttled_cnt++;
166 break;
167 }
168 }
169
170 spin_lock_irqsave(&dev->rx_done.lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700171 while (!list_empty(&dev->rx_idle)) {
Hemant Kumarfd2d5e52011-12-22 17:51:53 -0800172 if (dev->rx_done.qlen > stop_submit_urb_limit)
173 break;
Hemant Kumar14401d52011-11-03 16:40:32 -0700174
175 rx_idle = list_first_entry(&dev->rx_idle, struct urb, urb_list);
176 list_del(&rx_idle->urb_list);
177 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
178 retval = submit_rx_urb(dev, rx_idle, GFP_KERNEL);
179 spin_lock_irqsave(&dev->rx_done.lock, flags);
Hemant Kumar184765b2011-12-27 13:20:45 -0800180 if (retval) {
181 list_add_tail(&rx_idle->urb_list, &dev->rx_idle);
Hemant Kumar14401d52011-11-03 16:40:32 -0700182 break;
Hemant Kumar184765b2011-12-27 13:20:45 -0800183 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700184 }
185 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
186}
187
188static void data_bridge_read_cb(struct urb *urb)
189{
190 struct bridge *brdg;
191 struct sk_buff *skb = urb->context;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800192 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
193 struct data_bridge *dev = info->dev;
Hemant Kumar14401d52011-11-03 16:40:32 -0700194 bool queue = 0;
195
196 brdg = dev->brdg;
Hemant Kumar14401d52011-11-03 16:40:32 -0700197 skb_put(skb, urb->actual_length);
198
199 switch (urb->status) {
200 case 0: /* success */
201 queue = 1;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800202 info->rx_done = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700203 spin_lock(&dev->rx_done.lock);
204 __skb_queue_tail(&dev->rx_done, skb);
205 spin_unlock(&dev->rx_done.lock);
206 break;
207
208 /*do not resubmit*/
209 case -EPIPE:
210 set_bit(RX_HALT, &dev->flags);
Jack Phame8741502012-06-13 17:34:07 -0700211 dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700212 schedule_work(&dev->kevent);
213 /* FALLTHROUGH */
214 case -ESHUTDOWN:
215 case -ENOENT: /* suspended */
216 case -ECONNRESET: /* unplug */
217 case -EPROTO:
218 dev_kfree_skb_any(skb);
219 break;
220
221 /*resubmit */
222 case -EOVERFLOW: /*babble error*/
223 default:
224 queue = 1;
225 dev_kfree_skb_any(skb);
226 pr_debug_ratelimited("%s: non zero urb status = %d\n",
227 __func__, urb->status);
228 break;
229 }
230
231 spin_lock(&dev->rx_done.lock);
232 list_add_tail(&urb->urb_list, &dev->rx_idle);
233 spin_unlock(&dev->rx_done.lock);
234
235 if (queue)
236 queue_work(dev->wq, &dev->process_rx_w);
237}
238
239static int submit_rx_urb(struct data_bridge *dev, struct urb *rx_urb,
240 gfp_t flags)
241{
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800242 struct sk_buff *skb;
243 struct timestamp_info *info;
244 int retval = -EINVAL;
245 unsigned int created;
Hemant Kumar14401d52011-11-03 16:40:32 -0700246
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800247 created = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700248 skb = alloc_skb(RMNET_RX_BUFSIZE, flags);
Hemant Kumar184765b2011-12-27 13:20:45 -0800249 if (!skb)
Hemant Kumar14401d52011-11-03 16:40:32 -0700250 return -ENOMEM;
Hemant Kumar14401d52011-11-03 16:40:32 -0700251
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800252 info = (struct timestamp_info *)skb->cb;
253 info->dev = dev;
254 info->created = created;
Hemant Kumar14401d52011-11-03 16:40:32 -0700255
256 usb_fill_bulk_urb(rx_urb, dev->udev, dev->bulk_in,
257 skb->data, RMNET_RX_BUFSIZE,
258 data_bridge_read_cb, skb);
259
260 if (test_bit(SUSPENDED, &dev->flags))
261 goto suspended;
262
263 usb_anchor_urb(rx_urb, &dev->rx_active);
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800264 info->rx_queued = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700265 retval = usb_submit_urb(rx_urb, flags);
266 if (retval)
267 goto fail;
268
Hemant Kumarb72233f2012-04-04 13:21:44 -0700269 usb_mark_last_busy(dev->udev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700270 return 0;
271fail:
272 usb_unanchor_urb(rx_urb);
273suspended:
274 dev_kfree_skb_any(skb);
Hemant Kumar184765b2011-12-27 13:20:45 -0800275
Hemant Kumar14401d52011-11-03 16:40:32 -0700276 return retval;
277}
278
279static int data_bridge_prepare_rx(struct data_bridge *dev)
280{
281 int i;
282 struct urb *rx_urb;
283
284 for (i = 0; i < max_rx_urbs; i++) {
285 rx_urb = usb_alloc_urb(0, GFP_KERNEL);
286 if (!rx_urb)
287 return -ENOMEM;
288
289 list_add_tail(&rx_urb->urb_list, &dev->rx_idle);
290 }
291 return 0;
292}
293
294int data_bridge_open(struct bridge *brdg)
295{
296 struct data_bridge *dev;
297
298 if (!brdg) {
299 err("bridge is null\n");
300 return -EINVAL;
301 }
302
303 if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
304 return -EINVAL;
305
306 dev = __dev[brdg->ch_id];
307 if (!dev) {
308 err("dev is null\n");
309 return -ENODEV;
310 }
311
Jack Phame8741502012-06-13 17:34:07 -0700312 dev_dbg(&dev->intf->dev, "%s: dev:%p\n", __func__, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700313
314 dev->brdg = brdg;
Hemant Kumar06b7e432012-01-19 22:13:50 -0800315 dev->err = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700316 atomic_set(&dev->pending_txurbs, 0);
317 dev->to_host = 0;
318 dev->to_modem = 0;
319 dev->txurb_drp_cnt = 0;
320 dev->tx_throttled_cnt = 0;
321 dev->tx_unthrottled_cnt = 0;
322 dev->rx_throttled_cnt = 0;
323 dev->rx_unthrottled_cnt = 0;
324
325 queue_work(dev->wq, &dev->process_rx_w);
326
327 return 0;
328}
329EXPORT_SYMBOL(data_bridge_open);
330
331void data_bridge_close(unsigned int id)
332{
333 struct data_bridge *dev;
334 struct sk_buff *skb;
335 unsigned long flags;
336
337 if (id >= MAX_BRIDGE_DEVICES)
338 return;
339
340 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800341 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700342 return;
343
Jack Phame8741502012-06-13 17:34:07 -0700344 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700345
346 usb_unlink_anchored_urbs(&dev->tx_active);
347 usb_unlink_anchored_urbs(&dev->rx_active);
348 usb_unlink_anchored_urbs(&dev->delayed);
349
350 spin_lock_irqsave(&dev->rx_done.lock, flags);
351 while ((skb = __skb_dequeue(&dev->rx_done)))
352 dev_kfree_skb_any(skb);
353 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
354
355 dev->brdg = NULL;
356}
357EXPORT_SYMBOL(data_bridge_close);
358
359static void defer_kevent(struct work_struct *work)
360{
361 int status;
362 struct data_bridge *dev =
363 container_of(work, struct data_bridge, kevent);
364
365 if (!dev)
366 return;
367
368 if (test_bit(TX_HALT, &dev->flags)) {
369 usb_unlink_anchored_urbs(&dev->tx_active);
370
371 status = usb_autopm_get_interface(dev->intf);
372 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700373 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700374 "can't acquire interface, status %d\n", status);
375 return;
376 }
377
378 status = usb_clear_halt(dev->udev, dev->bulk_out);
379 usb_autopm_put_interface(dev->intf);
380 if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
Jack Phame8741502012-06-13 17:34:07 -0700381 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700382 "can't clear tx halt, status %d\n", status);
383 else
384 clear_bit(TX_HALT, &dev->flags);
385 }
386
387 if (test_bit(RX_HALT, &dev->flags)) {
388 usb_unlink_anchored_urbs(&dev->rx_active);
389
390 status = usb_autopm_get_interface(dev->intf);
391 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700392 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700393 "can't acquire interface, status %d\n", status);
394 return;
395 }
396
397 status = usb_clear_halt(dev->udev, dev->bulk_in);
398 usb_autopm_put_interface(dev->intf);
399 if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
Jack Phame8741502012-06-13 17:34:07 -0700400 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700401 "can't clear rx halt, status %d\n", status);
402 else {
403 clear_bit(RX_HALT, &dev->flags);
404 if (dev->brdg)
405 queue_work(dev->wq, &dev->process_rx_w);
406 }
407 }
408}
409
410static void data_bridge_write_cb(struct urb *urb)
411{
412 struct sk_buff *skb = urb->context;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800413 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
414 struct data_bridge *dev = info->dev;
Hemant Kumar14401d52011-11-03 16:40:32 -0700415 struct bridge *brdg = dev->brdg;
416 int pending;
417
418 pr_debug("%s: dev:%p\n", __func__, dev);
419
420 switch (urb->status) {
421 case 0: /*success*/
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800422 dbg_timestamp("UL", skb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700423 break;
Hemant Kumar06b7e432012-01-19 22:13:50 -0800424 case -EPROTO:
425 dev->err = -EPROTO;
426 break;
Hemant Kumar14401d52011-11-03 16:40:32 -0700427 case -EPIPE:
428 set_bit(TX_HALT, &dev->flags);
Jack Phame8741502012-06-13 17:34:07 -0700429 dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700430 schedule_work(&dev->kevent);
431 /* FALLTHROUGH */
432 case -ESHUTDOWN:
433 case -ENOENT: /* suspended */
434 case -ECONNRESET: /* unplug */
435 case -EOVERFLOW: /*babble error*/
436 /* FALLTHROUGH */
437 default:
438 pr_debug_ratelimited("%s: non zero urb status = %d\n",
439 __func__, urb->status);
440 }
441
442 usb_free_urb(urb);
443 dev_kfree_skb_any(skb);
444
445 pending = atomic_dec_return(&dev->pending_txurbs);
446
447 /*flow ctrl*/
448 if (brdg && fctrl_support && pending <= fctrl_dis_thld &&
449 test_and_clear_bit(TX_THROTTLED, &brdg->flags)) {
450 pr_debug_ratelimited("%s: disable flow ctrl: pend urbs:%u\n",
451 __func__, pending);
452 dev->tx_unthrottled_cnt++;
453 if (brdg->ops.unthrottle_tx)
454 brdg->ops.unthrottle_tx(brdg->ctx);
455 }
456
457 usb_autopm_put_interface_async(dev->intf);
458}
459
460int data_bridge_write(unsigned int id, struct sk_buff *skb)
461{
462 int result;
463 int size = skb->len;
464 int pending;
465 struct urb *txurb;
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800466 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
Hemant Kumar14401d52011-11-03 16:40:32 -0700467 struct data_bridge *dev = __dev[id];
468 struct bridge *brdg;
469
Hemant Kumar06b7e432012-01-19 22:13:50 -0800470 if (!dev || !dev->brdg || dev->err || !usb_get_intfdata(dev->intf))
Hemant Kumar14401d52011-11-03 16:40:32 -0700471 return -ENODEV;
472
473 brdg = dev->brdg;
Hemant Kumarc8a3d312011-12-27 15:41:32 -0800474 if (!brdg)
475 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700476
Jack Phame8741502012-06-13 17:34:07 -0700477 dev_dbg(&dev->intf->dev, "%s: write (%d bytes)\n", __func__, skb->len);
Hemant Kumar14401d52011-11-03 16:40:32 -0700478
479 result = usb_autopm_get_interface(dev->intf);
480 if (result < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700481 dev_err(&dev->intf->dev, "%s: resume failure\n", __func__);
Hemant Kumar93387bd2012-06-08 15:55:26 -0700482 goto pm_error;
Hemant Kumar14401d52011-11-03 16:40:32 -0700483 }
484
485 txurb = usb_alloc_urb(0, GFP_KERNEL);
486 if (!txurb) {
Jack Phame8741502012-06-13 17:34:07 -0700487 dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700488 __func__);
489 result = -ENOMEM;
490 goto error;
491 }
492
493 /* store dev pointer in skb */
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800494 info->dev = dev;
495 info->tx_queued = get_timestamp();
Hemant Kumar14401d52011-11-03 16:40:32 -0700496
497 usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out,
498 skb->data, skb->len, data_bridge_write_cb, skb);
499
500 if (test_bit(SUSPENDED, &dev->flags)) {
501 usb_anchor_urb(txurb, &dev->delayed);
502 goto free_urb;
503 }
504
505 pending = atomic_inc_return(&dev->pending_txurbs);
506 usb_anchor_urb(txurb, &dev->tx_active);
507
Hemant Kumar73eff1c2012-01-09 18:49:11 -0800508 if (atomic_read(&dev->pending_txurbs) % tx_urb_mult)
509 txurb->transfer_flags |= URB_NO_INTERRUPT;
510
Hemant Kumar14401d52011-11-03 16:40:32 -0700511 result = usb_submit_urb(txurb, GFP_KERNEL);
512 if (result < 0) {
513 usb_unanchor_urb(txurb);
514 atomic_dec(&dev->pending_txurbs);
Jack Phame8741502012-06-13 17:34:07 -0700515 dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700516 __func__, result);
517 goto free_urb;
518 }
519
520 dev->to_modem++;
Jack Phame8741502012-06-13 17:34:07 -0700521 dev_dbg(&dev->intf->dev, "%s: pending_txurbs: %u\n", __func__, pending);
Hemant Kumar14401d52011-11-03 16:40:32 -0700522
523 /* flow control: last urb submitted but return -EBUSY */
524 if (fctrl_support && pending > fctrl_en_thld) {
525 set_bit(TX_THROTTLED, &brdg->flags);
526 dev->tx_throttled_cnt++;
527 pr_debug_ratelimited("%s: enable flow ctrl pend txurbs:%u\n",
528 __func__, pending);
529 return -EBUSY;
530 }
531
532 return size;
533
534free_urb:
535 usb_free_urb(txurb);
536error:
537 dev->txurb_drp_cnt++;
538 usb_autopm_put_interface(dev->intf);
Hemant Kumar93387bd2012-06-08 15:55:26 -0700539pm_error:
Hemant Kumar14401d52011-11-03 16:40:32 -0700540 return result;
541}
542EXPORT_SYMBOL(data_bridge_write);
543
544static int data_bridge_resume(struct data_bridge *dev)
545{
546 struct urb *urb;
547 int retval;
548
Jack Pham9b0a0e52012-02-28 18:05:14 -0800549 if (!test_and_clear_bit(SUSPENDED, &dev->flags))
550 return 0;
551
Hemant Kumar14401d52011-11-03 16:40:32 -0700552 while ((urb = usb_get_from_anchor(&dev->delayed))) {
553 usb_anchor_urb(urb, &dev->tx_active);
554 atomic_inc(&dev->pending_txurbs);
555 retval = usb_submit_urb(urb, GFP_ATOMIC);
556 if (retval < 0) {
557 atomic_dec(&dev->pending_txurbs);
558 usb_unanchor_urb(urb);
559
560 /* TODO: need to free urb data */
561 usb_scuttle_anchored_urbs(&dev->delayed);
562 break;
563 }
564 dev->to_modem++;
565 dev->txurb_drp_cnt--;
566 }
567
Hemant Kumar14401d52011-11-03 16:40:32 -0700568 if (dev->brdg)
569 queue_work(dev->wq, &dev->process_rx_w);
570
571 return 0;
572}
573
574static int bridge_resume(struct usb_interface *iface)
575{
576 int retval = 0;
577 int oldstate;
578 struct data_bridge *dev = usb_get_intfdata(iface);
Hemant Kumar14401d52011-11-03 16:40:32 -0700579
580 oldstate = iface->dev.power.power_state.event;
581 iface->dev.power.power_state.event = PM_EVENT_ON;
582
Jack Pham9b0a0e52012-02-28 18:05:14 -0800583 if (oldstate & PM_EVENT_SUSPEND) {
584 retval = data_bridge_resume(dev);
585 if (!retval)
586 retval = ctrl_bridge_resume(dev->id);
Hemant Kumar14401d52011-11-03 16:40:32 -0700587 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800588
Hemant Kumar14401d52011-11-03 16:40:32 -0700589 return retval;
590}
591
592static int data_bridge_suspend(struct data_bridge *dev, pm_message_t message)
593{
594 if (atomic_read(&dev->pending_txurbs) &&
595 (message.event & PM_EVENT_AUTO))
596 return -EBUSY;
597
598 set_bit(SUSPENDED, &dev->flags);
599
600 usb_kill_anchored_urbs(&dev->tx_active);
601 usb_kill_anchored_urbs(&dev->rx_active);
602
603 return 0;
604}
605
606static int bridge_suspend(struct usb_interface *intf, pm_message_t message)
607{
608 int retval;
609 struct data_bridge *dev = usb_get_intfdata(intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700610
611 retval = data_bridge_suspend(dev, message);
612 if (!retval) {
Jack Pham9b0a0e52012-02-28 18:05:14 -0800613 retval = ctrl_bridge_suspend(dev->id);
614 intf->dev.power.power_state.event = message.event;
Hemant Kumar14401d52011-11-03 16:40:32 -0700615 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800616
Hemant Kumar14401d52011-11-03 16:40:32 -0700617 return retval;
618}
619
620static int data_bridge_probe(struct usb_interface *iface,
621 struct usb_host_endpoint *bulk_in,
622 struct usb_host_endpoint *bulk_out, int id)
623{
624 struct data_bridge *dev;
625
626 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
627 if (!dev) {
628 err("%s: unable to allocate dev\n", __func__);
629 return -ENOMEM;
630 }
631
632 dev->pdev = platform_device_alloc(data_bridge_names[id], id);
633 if (!dev->pdev) {
634 err("%s: unable to allocate platform device\n", __func__);
635 kfree(dev);
636 return -ENOMEM;
637 }
638
639 init_usb_anchor(&dev->tx_active);
640 init_usb_anchor(&dev->rx_active);
641 init_usb_anchor(&dev->delayed);
642
643 INIT_LIST_HEAD(&dev->rx_idle);
644 skb_queue_head_init(&dev->rx_done);
645
646 dev->wq = bridge_wq;
Jack Pham9b0a0e52012-02-28 18:05:14 -0800647 dev->id = id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700648 dev->udev = interface_to_usbdev(iface);
649 dev->intf = iface;
650
651 dev->bulk_in = usb_rcvbulkpipe(dev->udev,
652 bulk_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
653
654 dev->bulk_out = usb_sndbulkpipe(dev->udev,
655 bulk_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
656
657 usb_set_intfdata(iface, dev);
658
659 INIT_WORK(&dev->kevent, defer_kevent);
660 INIT_WORK(&dev->process_rx_w, data_bridge_process_rx);
661
662 __dev[id] = dev;
663
664 /*allocate list of rx urbs*/
665 data_bridge_prepare_rx(dev);
666
667 platform_device_add(dev->pdev);
668
669 return 0;
670}
671
672#if defined(CONFIG_DEBUG_FS)
673#define DEBUG_BUF_SIZE 1024
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800674
675static unsigned int record_timestamp;
676module_param(record_timestamp, uint, S_IRUGO | S_IWUSR);
677
678static struct timestamp_buf dbg_data = {
679 .idx = 0,
680 .lck = __RW_LOCK_UNLOCKED(lck)
681};
682
683/*get_timestamp - returns time of day in us */
684static unsigned int get_timestamp(void)
685{
686 struct timeval tval;
687 unsigned int stamp;
688
689 if (!record_timestamp)
690 return 0;
691
692 do_gettimeofday(&tval);
693 /* 2^32 = 4294967296. Limit to 4096s. */
694 stamp = tval.tv_sec & 0xFFF;
695 stamp = stamp * 1000000 + tval.tv_usec;
696 return stamp;
697}
698
699static void dbg_inc(unsigned *idx)
700{
701 *idx = (*idx + 1) & (DBG_DATA_MAX-1);
702}
703
704/**
705* dbg_timestamp - Stores timestamp values of a SKB life cycle
706* to debug buffer
707* @event: "UL": Uplink Data
708* @skb: SKB used to store timestamp values to debug buffer
709*/
710static void dbg_timestamp(char *event, struct sk_buff * skb)
711{
712 unsigned long flags;
713 struct timestamp_info *info = (struct timestamp_info *)skb->cb;
714
715 if (!record_timestamp)
716 return;
717
718 write_lock_irqsave(&dbg_data.lck, flags);
719
720 scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
721 "%p %u[%s] %u %u %u %u %u %u\n",
722 skb, skb->len, event, info->created, info->rx_queued,
723 info->rx_done, info->rx_done_sent, info->tx_queued,
724 get_timestamp());
725
726 dbg_inc(&dbg_data.idx);
727
728 write_unlock_irqrestore(&dbg_data.lck, flags);
729}
730
731/* show_timestamp: displays the timestamp buffer */
732static ssize_t show_timestamp(struct file *file, char __user *ubuf,
733 size_t count, loff_t *ppos)
734{
735 unsigned long flags;
736 unsigned i;
737 unsigned j = 0;
738 char *buf;
739 int ret = 0;
740
741 if (!record_timestamp)
742 return 0;
743
744 buf = kzalloc(sizeof(char) * 4 * DEBUG_BUF_SIZE, GFP_KERNEL);
745 if (!buf)
746 return -ENOMEM;
747
748 read_lock_irqsave(&dbg_data.lck, flags);
749
750 i = dbg_data.idx;
751 for (dbg_inc(&i); i != dbg_data.idx; dbg_inc(&i)) {
752 if (!strnlen(dbg_data.buf[i], DBG_DATA_MSG))
753 continue;
754 j += scnprintf(buf + j, (4 * DEBUG_BUF_SIZE) - j,
755 "%s\n", dbg_data.buf[i]);
756 }
757
758 read_unlock_irqrestore(&dbg_data.lck, flags);
759
760 ret = simple_read_from_buffer(ubuf, count, ppos, buf, j);
761
762 kfree(buf);
763
764 return ret;
765}
766
767const struct file_operations data_timestamp_ops = {
768 .read = show_timestamp,
769};
770
Hemant Kumar14401d52011-11-03 16:40:32 -0700771static ssize_t data_bridge_read_stats(struct file *file, char __user *ubuf,
772 size_t count, loff_t *ppos)
773{
774 struct data_bridge *dev;
775 char *buf;
776 int ret;
777 int i;
778 int temp = 0;
779
780 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
781 if (!buf)
782 return -ENOMEM;
783
784 for (i = 0; i < ch_id; i++) {
785 dev = __dev[i];
786 if (!dev)
787 continue;
788
789 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
790 "\nName#%s dev %p\n"
791 "pending tx urbs: %u\n"
792 "tx urb drp cnt: %u\n"
793 "to host: %lu\n"
794 "to mdm: %lu\n"
795 "tx throttled cnt: %u\n"
796 "tx unthrottled cnt: %u\n"
797 "rx throttled cnt: %u\n"
798 "rx unthrottled cnt: %u\n"
799 "rx done skb qlen: %u\n"
Hemant Kumar06b7e432012-01-19 22:13:50 -0800800 "dev err: %d\n"
Hemant Kumar14401d52011-11-03 16:40:32 -0700801 "suspended: %d\n"
802 "TX_HALT: %d\n"
803 "RX_HALT: %d\n",
804 dev->pdev->name, dev,
805 atomic_read(&dev->pending_txurbs),
806 dev->txurb_drp_cnt,
807 dev->to_host,
808 dev->to_modem,
809 dev->tx_throttled_cnt,
810 dev->tx_unthrottled_cnt,
811 dev->rx_throttled_cnt,
812 dev->rx_unthrottled_cnt,
813 dev->rx_done.qlen,
Hemant Kumar06b7e432012-01-19 22:13:50 -0800814 dev->err,
Hemant Kumar14401d52011-11-03 16:40:32 -0700815 test_bit(SUSPENDED, &dev->flags),
816 test_bit(TX_HALT, &dev->flags),
817 test_bit(RX_HALT, &dev->flags));
818
819 }
820
821 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
822
823 kfree(buf);
824
825 return ret;
826}
827
828static ssize_t data_bridge_reset_stats(struct file *file,
829 const char __user *buf, size_t count, loff_t *ppos)
830{
831 struct data_bridge *dev;
832 int i;
833
834 for (i = 0; i < ch_id; i++) {
835 dev = __dev[i];
836 if (!dev)
837 continue;
838
839 dev->to_host = 0;
840 dev->to_modem = 0;
841 dev->txurb_drp_cnt = 0;
842 dev->tx_throttled_cnt = 0;
843 dev->tx_unthrottled_cnt = 0;
844 dev->rx_throttled_cnt = 0;
845 dev->rx_unthrottled_cnt = 0;
846 }
847 return count;
848}
849
850const struct file_operations data_stats_ops = {
851 .read = data_bridge_read_stats,
852 .write = data_bridge_reset_stats,
853};
854
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800855static struct dentry *data_dent;
856static struct dentry *data_dfile_stats;
857static struct dentry *data_dfile_tstamp;
858
Hemant Kumar14401d52011-11-03 16:40:32 -0700859static void data_bridge_debugfs_init(void)
860{
861 data_dent = debugfs_create_dir("data_hsic_bridge", 0);
862 if (IS_ERR(data_dent))
863 return;
864
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800865 data_dfile_stats = debugfs_create_file("status", 0644, data_dent, 0,
866 &data_stats_ops);
867 if (!data_dfile_stats || IS_ERR(data_dfile_stats)) {
868 debugfs_remove(data_dent);
869 return;
870 }
871
872 data_dfile_tstamp = debugfs_create_file("timestamp", 0644, data_dent,
873 0, &data_timestamp_ops);
874 if (!data_dfile_tstamp || IS_ERR(data_dfile_tstamp))
Hemant Kumar14401d52011-11-03 16:40:32 -0700875 debugfs_remove(data_dent);
876}
877
878static void data_bridge_debugfs_exit(void)
879{
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800880 debugfs_remove(data_dfile_stats);
881 debugfs_remove(data_dfile_tstamp);
Hemant Kumar14401d52011-11-03 16:40:32 -0700882 debugfs_remove(data_dent);
883}
884
885#else
886static void data_bridge_debugfs_init(void) { }
887static void data_bridge_debugfs_exit(void) { }
Hemant Kumarc72ab2b2012-01-10 12:33:49 -0800888static void dbg_timestamp(char *event, struct sk_buff * skb)
889{
890 return;
891}
892
893static unsigned int get_timestamp(void)
894{
895 return 0;
896}
897
Hemant Kumar14401d52011-11-03 16:40:32 -0700898#endif
899
900static int __devinit
901bridge_probe(struct usb_interface *iface, const struct usb_device_id *id)
902{
903 struct usb_host_endpoint *endpoint = NULL;
904 struct usb_host_endpoint *bulk_in = NULL;
905 struct usb_host_endpoint *bulk_out = NULL;
906 struct usb_host_endpoint *int_in = NULL;
907 struct usb_device *udev;
908 int i;
909 int status = 0;
910 int numends;
Hemant Kumar67a4fd02012-01-05 15:44:36 -0800911 unsigned int iface_num;
Hemant Kumar14401d52011-11-03 16:40:32 -0700912
913 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
914
915 if (iface->num_altsetting != 1) {
916 err("%s invalid num_altsetting %u\n",
917 __func__, iface->num_altsetting);
918 return -EINVAL;
919 }
920
Hemant Kumar67a4fd02012-01-05 15:44:36 -0800921 if (!test_bit(iface_num, &id->driver_info))
Hemant Kumar46f9f242011-12-15 20:20:58 -0800922 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700923
Jack Pham1b1ba472012-06-13 16:40:15 -0700924 udev = interface_to_usbdev(iface);
925 usb_get_dev(udev);
926
Hemant Kumar14401d52011-11-03 16:40:32 -0700927 numends = iface->cur_altsetting->desc.bNumEndpoints;
928 for (i = 0; i < numends; i++) {
929 endpoint = iface->cur_altsetting->endpoint + i;
930 if (!endpoint) {
Jack Phame8741502012-06-13 17:34:07 -0700931 dev_err(&iface->dev, "%s: invalid endpoint %u\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700932 __func__, i);
933 status = -EINVAL;
934 goto out;
935 }
936
937 if (usb_endpoint_is_bulk_in(&endpoint->desc))
938 bulk_in = endpoint;
939 else if (usb_endpoint_is_bulk_out(&endpoint->desc))
940 bulk_out = endpoint;
941 else if (usb_endpoint_is_int_in(&endpoint->desc))
942 int_in = endpoint;
943 }
944
945 if (!bulk_in || !bulk_out || !int_in) {
Jack Phame8741502012-06-13 17:34:07 -0700946 dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700947 status = -EINVAL;
948 goto out;
949 }
950
951 status = data_bridge_probe(iface, bulk_in, bulk_out, ch_id);
952 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700953 dev_err(&iface->dev, "data_bridge_probe failed %d\n", status);
Hemant Kumar14401d52011-11-03 16:40:32 -0700954 goto out;
955 }
956
957 status = ctrl_bridge_probe(iface, int_in, ch_id);
958 if (status < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700959 dev_err(&iface->dev, "ctrl_bridge_probe failed %d\n", status);
Hemant Kumar14401d52011-11-03 16:40:32 -0700960 goto free_data_bridge;
961 }
Hemant Kumar67a4fd02012-01-05 15:44:36 -0800962
Hemant Kumar14401d52011-11-03 16:40:32 -0700963 ch_id++;
964
965 return 0;
966
967free_data_bridge:
Jack Pham1b1ba472012-06-13 16:40:15 -0700968 platform_device_unregister(__dev[ch_id]->pdev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700969 usb_set_intfdata(iface, NULL);
970 kfree(__dev[ch_id]);
971 __dev[ch_id] = NULL;
972out:
973 usb_put_dev(udev);
974
975 return status;
976}
977
978static void bridge_disconnect(struct usb_interface *intf)
979{
980 struct data_bridge *dev = usb_get_intfdata(intf);
981 struct list_head *head;
982 struct urb *rx_urb;
983 unsigned long flags;
Hemant Kumar14401d52011-11-03 16:40:32 -0700984
985 if (!dev) {
986 err("%s: data device not found\n", __func__);
987 return;
988 }
989
Hemant Kumar14401d52011-11-03 16:40:32 -0700990 ch_id--;
991 ctrl_bridge_disconnect(ch_id);
Jack Pham1b1ba472012-06-13 16:40:15 -0700992 platform_device_unregister(dev->pdev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700993 usb_set_intfdata(intf, NULL);
994 __dev[ch_id] = NULL;
995
996 cancel_work_sync(&dev->process_rx_w);
997 cancel_work_sync(&dev->kevent);
998
999 /*free rx urbs*/
1000 head = &dev->rx_idle;
1001 spin_lock_irqsave(&dev->rx_done.lock, flags);
1002 while (!list_empty(head)) {
1003 rx_urb = list_entry(head->next, struct urb, urb_list);
1004 list_del(&rx_urb->urb_list);
1005 usb_free_urb(rx_urb);
1006 }
1007 spin_unlock_irqrestore(&dev->rx_done.lock, flags);
1008
1009 usb_put_dev(dev->udev);
1010 kfree(dev);
1011}
1012
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001013/*bit position represents interface number*/
1014#define PID9001_IFACE_MASK 0xC
1015#define PID9034_IFACE_MASK 0xC
1016#define PID9048_IFACE_MASK 0x18
Hemant Kumare97cbb32012-02-24 13:00:57 -08001017#define PID904C_IFACE_MASK 0x28
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001018
Hemant Kumar14401d52011-11-03 16:40:32 -07001019static const struct usb_device_id bridge_ids[] = {
Hemant Kumar67a4fd02012-01-05 15:44:36 -08001020 { USB_DEVICE(0x5c6, 0x9001),
1021 .driver_info = PID9001_IFACE_MASK,
1022 },
1023 { USB_DEVICE(0x5c6, 0x9034),
1024 .driver_info = PID9034_IFACE_MASK,
1025 },
1026 { USB_DEVICE(0x5c6, 0x9048),
1027 .driver_info = PID9048_IFACE_MASK,
1028 },
Hemant Kumare97cbb32012-02-24 13:00:57 -08001029 { USB_DEVICE(0x5c6, 0x904c),
1030 .driver_info = PID904C_IFACE_MASK,
1031 },
Jack Phamb1ad7152011-12-07 10:58:11 -08001032
1033 { } /* Terminating entry */
Hemant Kumar14401d52011-11-03 16:40:32 -07001034};
Hemant Kumar14401d52011-11-03 16:40:32 -07001035MODULE_DEVICE_TABLE(usb, bridge_ids);
1036
1037static struct usb_driver bridge_driver = {
1038 .name = "mdm_bridge",
1039 .probe = bridge_probe,
1040 .disconnect = bridge_disconnect,
1041 .id_table = bridge_ids,
1042 .suspend = bridge_suspend,
1043 .resume = bridge_resume,
1044 .supports_autosuspend = 1,
1045};
1046
1047static int __init bridge_init(void)
1048{
1049 int ret;
1050
1051 ret = usb_register(&bridge_driver);
1052 if (ret) {
1053 err("%s: unable to register mdm_bridge driver", __func__);
1054 return ret;
1055 }
1056
1057 bridge_wq = create_singlethread_workqueue("mdm_bridge");
1058 if (!bridge_wq) {
1059 usb_deregister(&bridge_driver);
1060 pr_err("%s: Unable to create workqueue:bridge\n", __func__);
1061 return -ENOMEM;
1062 }
1063
1064 data_bridge_debugfs_init();
1065
1066 return 0;
1067}
1068
1069static void __exit bridge_exit(void)
1070{
1071 data_bridge_debugfs_exit();
1072 destroy_workqueue(bridge_wq);
1073 usb_deregister(&bridge_driver);
1074}
1075
1076module_init(bridge_init);
1077module_exit(bridge_exit);
1078
1079MODULE_DESCRIPTION("Qualcomm modem data bridge driver");
1080MODULE_LICENSE("GPL v2");