blob: 75fce2f92a4effaf446e0c4f1f428f2987cfb7aa [file] [log] [blame]
Hemant Kumar262682a2013-02-01 09:46:45 -08001/* Copyright (c) 2011-2013, The 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/kref.h>
19#include <linux/debugfs.h>
20#include <linux/platform_device.h>
21#include <linux/uaccess.h>
22#include <linux/ratelimit.h>
23#include <linux/usb/ch9.h>
24#include <linux/usb/cdc.h>
25#include <linux/termios.h>
26#include <asm/unaligned.h>
27#include <mach/usb_bridge.h>
28
Hemant Kumar14401d52011-11-03 16:40:32 -070029/* polling interval for Interrupt ep */
30#define HS_INTERVAL 7
31#define FS_LS_INTERVAL 3
32
33#define ACM_CTRL_DTR (1 << 0)
34#define DEFAULT_READ_URB_LENGTH 4096
35
Jack Pham9b0a0e52012-02-28 18:05:14 -080036#define SUSPENDED BIT(0)
Hemant Kumar14401d52011-11-03 16:40:32 -070037
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +053038enum ctrl_bridge_rx_state {
39 RX_IDLE, /* inturb is not queued */
40 RX_WAIT, /* inturb is queued and waiting for data */
41 RX_BUSY, /* inturb is completed. processing RX */
42};
43
Jack Pham9b0a0e52012-02-28 18:05:14 -080044struct ctrl_bridge {
Hemant Kumar14401d52011-11-03 16:40:32 -070045 struct usb_device *udev;
46 struct usb_interface *intf;
47
Hemant Kumarc2b17782013-02-03 15:56:29 -080048 char *name;
49
Hemant Kumar14401d52011-11-03 16:40:32 -070050 unsigned int int_pipe;
51 struct urb *inturb;
52 void *intbuf;
53
54 struct urb *readurb;
55 void *readbuf;
56
57 struct usb_anchor tx_submitted;
Jack Pham9b0a0e52012-02-28 18:05:14 -080058 struct usb_anchor tx_deferred;
Hemant Kumar14401d52011-11-03 16:40:32 -070059 struct usb_ctrlrequest *in_ctlreq;
60
61 struct bridge *brdg;
62 struct platform_device *pdev;
63
Jack Pham9b0a0e52012-02-28 18:05:14 -080064 unsigned long flags;
65
Hemant Kumar14401d52011-11-03 16:40:32 -070066 /* input control lines (DSR, CTS, CD, RI) */
67 unsigned int cbits_tohost;
68
69 /* output control lines (DTR, RTS) */
70 unsigned int cbits_tomdm;
71
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +053072 spinlock_t lock;
73 enum ctrl_bridge_rx_state rx_state;
74
Hemant Kumar14401d52011-11-03 16:40:32 -070075 /* counters */
76 unsigned int snd_encap_cmd;
77 unsigned int get_encap_res;
78 unsigned int resp_avail;
79 unsigned int set_ctrl_line_sts;
80 unsigned int notify_ser_state;
Hemant Kumar14401d52011-11-03 16:40:32 -070081};
82
83static struct ctrl_bridge *__dev[MAX_BRIDGE_DEVICES];
84
Hemant Kumarc2b17782013-02-03 15:56:29 -080085static int get_ctrl_bridge_chid(char *xport_name)
86{
87 struct ctrl_bridge *dev;
88 int i;
89
90 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
91 dev = __dev[i];
92 if (!strncmp(dev->name, xport_name, BRIDGE_NAME_MAX_LEN))
93 return i;
94 }
95
96 return -ENODEV;
97}
98
Hemant Kumar14401d52011-11-03 16:40:32 -070099unsigned int ctrl_bridge_get_cbits_tohost(unsigned int id)
100{
101 struct ctrl_bridge *dev;
102
103 if (id >= MAX_BRIDGE_DEVICES)
104 return -EINVAL;
105
106 dev = __dev[id];
107 if (!dev)
108 return -ENODEV;
109
110 return dev->cbits_tohost;
111}
112EXPORT_SYMBOL(ctrl_bridge_get_cbits_tohost);
113
114int ctrl_bridge_set_cbits(unsigned int id, unsigned int cbits)
115{
116 struct ctrl_bridge *dev;
117 struct bridge *brdg;
118 int retval;
119
120 if (id >= MAX_BRIDGE_DEVICES)
121 return -EINVAL;
122
123 dev = __dev[id];
124 if (!dev)
125 return -ENODEV;
126
127 pr_debug("%s: dev[id] =%u cbits : %u\n", __func__, id, cbits);
128
129 brdg = dev->brdg;
130 if (!brdg)
131 return -ENODEV;
132
133 dev->cbits_tomdm = cbits;
134
135 retval = ctrl_bridge_write(id, NULL, 0);
136
137 /* if DTR is high, update latest modem info to host */
138 if (brdg && (cbits & ACM_CTRL_DTR) && brdg->ops.send_cbits)
139 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
140
141 return retval;
142}
143EXPORT_SYMBOL(ctrl_bridge_set_cbits);
144
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530145static int ctrl_bridge_start_read(struct ctrl_bridge *dev, gfp_t gfp_flags)
146{
147 int retval = 0;
148 unsigned long flags;
149
150 if (!dev->inturb) {
151 dev_err(&dev->intf->dev, "%s: inturb is NULL\n", __func__);
152 return -ENODEV;
153 }
154
155 retval = usb_submit_urb(dev->inturb, gfp_flags);
156 if (retval < 0 && retval != -EPERM) {
157 dev_err(&dev->intf->dev,
158 "%s error submitting int urb %d\n",
159 __func__, retval);
160 }
161
162 spin_lock_irqsave(&dev->lock, flags);
163 if (retval)
164 dev->rx_state = RX_IDLE;
165 else
166 dev->rx_state = RX_WAIT;
167 spin_unlock_irqrestore(&dev->lock, flags);
168
169 return retval;
170}
171
Hemant Kumar14401d52011-11-03 16:40:32 -0700172static void resp_avail_cb(struct urb *urb)
173{
174 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700175 int resubmit_urb = 1;
176 struct bridge *brdg = dev->brdg;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530177 unsigned long flags;
Hemant Kumar14401d52011-11-03 16:40:32 -0700178
Hemant Kumar262682a2013-02-01 09:46:45 -0800179 /*usb device disconnect*/
180 if (urb->dev->state == USB_STATE_NOTATTACHED)
181 return;
182
Hemant Kumar14401d52011-11-03 16:40:32 -0700183 switch (urb->status) {
184 case 0:
185 /*success*/
186 dev->get_encap_res++;
187 if (brdg && brdg->ops.send_pkt)
188 brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
189 urb->actual_length);
190 break;
191
192 /*do not resubmit*/
193 case -ESHUTDOWN:
194 case -ENOENT:
195 case -ECONNRESET:
196 /* unplug */
197 case -EPROTO:
198 /*babble error*/
199 resubmit_urb = 0;
200 /*resubmit*/
201 case -EOVERFLOW:
202 default:
Jack Phame8741502012-06-13 17:34:07 -0700203 dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700204 __func__, urb->status);
205 }
206
207 if (resubmit_urb) {
208 /*re- submit int urb to check response available*/
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530209 ctrl_bridge_start_read(dev, GFP_ATOMIC);
210 } else {
211 spin_lock_irqsave(&dev->lock, flags);
212 dev->rx_state = RX_IDLE;
213 spin_unlock_irqrestore(&dev->lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700214 }
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530215
216 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700217}
218
219static void notification_available_cb(struct urb *urb)
220{
221 int status;
222 struct usb_cdc_notification *ctrl;
Hemant Kumar14401d52011-11-03 16:40:32 -0700223 struct ctrl_bridge *dev = urb->context;
224 struct bridge *brdg = dev->brdg;
225 unsigned int ctrl_bits;
226 unsigned char *data;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530227 unsigned long flags;
Hemant Kumar14401d52011-11-03 16:40:32 -0700228
Hemant Kumar262682a2013-02-01 09:46:45 -0800229 /*usb device disconnect*/
230 if (urb->dev->state == USB_STATE_NOTATTACHED)
231 return;
232
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530233 spin_lock_irqsave(&dev->lock, flags);
234 dev->rx_state = RX_IDLE;
235 spin_unlock_irqrestore(&dev->lock, flags);
236
Hemant Kumar14401d52011-11-03 16:40:32 -0700237 switch (urb->status) {
238 case 0:
239 /*success*/
240 break;
241 case -ESHUTDOWN:
242 case -ENOENT:
243 case -ECONNRESET:
244 case -EPROTO:
245 /* unplug */
246 return;
247 case -EPIPE:
Jack Phame8741502012-06-13 17:34:07 -0700248 dev_err(&dev->intf->dev,
249 "%s: stall on int endpoint\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700250 /* TBD : halt to be cleared in work */
251 case -EOVERFLOW:
252 default:
253 pr_debug_ratelimited("%s: non zero urb status = %d\n",
254 __func__, urb->status);
255 goto resubmit_int_urb;
256 }
257
258 ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
259 data = (unsigned char *)(ctrl + 1);
260
261 switch (ctrl->bNotificationType) {
262 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530263 spin_lock_irqsave(&dev->lock, flags);
264 dev->rx_state = RX_BUSY;
265 spin_unlock_irqrestore(&dev->lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700266 dev->resp_avail++;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530267 usb_autopm_get_interface_no_resume(dev->intf);
Jack Phame8741502012-06-13 17:34:07 -0700268 usb_fill_control_urb(dev->readurb, dev->udev,
269 usb_rcvctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700270 (unsigned char *)dev->in_ctlreq,
271 dev->readbuf,
272 DEFAULT_READ_URB_LENGTH,
273 resp_avail_cb, dev);
274
275 status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
276 if (status) {
Jack Phame8741502012-06-13 17:34:07 -0700277 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700278 "%s: Error submitting Read URB %d\n",
279 __func__, status);
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530280 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700281 goto resubmit_int_urb;
282 }
283 return;
284 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
Jack Phame8741502012-06-13 17:34:07 -0700285 dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
Hemant Kumar14401d52011-11-03 16:40:32 -0700286 "connected to" : "disconnected from");
287 break;
288 case USB_CDC_NOTIFY_SERIAL_STATE:
289 dev->notify_ser_state++;
290 ctrl_bits = get_unaligned_le16(data);
Jack Phame8741502012-06-13 17:34:07 -0700291 dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
Hemant Kumar14401d52011-11-03 16:40:32 -0700292 dev->cbits_tohost = ctrl_bits;
293 if (brdg && brdg->ops.send_cbits)
294 brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
295 break;
296 default:
Jack Phame8741502012-06-13 17:34:07 -0700297 dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
Hemant Kumar14401d52011-11-03 16:40:32 -0700298 "index %d len %d data0 %d data1 %d",
299 __func__, ctrl->bNotificationType, ctrl->wIndex,
300 ctrl->wLength, data[0], data[1]);
301 }
302
303resubmit_int_urb:
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530304 ctrl_bridge_start_read(dev, GFP_ATOMIC);
Hemant Kumar14401d52011-11-03 16:40:32 -0700305}
306
Hemant Kumar14401d52011-11-03 16:40:32 -0700307int ctrl_bridge_open(struct bridge *brdg)
308{
309 struct ctrl_bridge *dev;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800310 int ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700311
312 if (!brdg) {
313 err("bridge is null\n");
314 return -EINVAL;
315 }
316
Hemant Kumarc2b17782013-02-03 15:56:29 -0800317 ch_id = get_ctrl_bridge_chid(brdg->name);
318 if (ch_id < 0 || ch_id >= MAX_BRIDGE_DEVICES) {
319 err("%s: %s dev not found\n", __func__, brdg->name);
320 return ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700321 }
322
Hemant Kumarc2b17782013-02-03 15:56:29 -0800323 brdg->ch_id = ch_id;
324
325 dev = __dev[ch_id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700326 dev->brdg = brdg;
327 dev->snd_encap_cmd = 0;
328 dev->get_encap_res = 0;
329 dev->resp_avail = 0;
330 dev->set_ctrl_line_sts = 0;
331 dev->notify_ser_state = 0;
332
Jack Phamb9d67c62012-05-22 18:38:53 -0700333 if (brdg->ops.send_cbits)
334 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800335
Jack Phamb9d67c62012-05-22 18:38:53 -0700336 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700337}
338EXPORT_SYMBOL(ctrl_bridge_open);
339
340void ctrl_bridge_close(unsigned int id)
341{
342 struct ctrl_bridge *dev;
343
344 if (id >= MAX_BRIDGE_DEVICES)
345 return;
346
347 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800348 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700349 return;
350
Jack Phame8741502012-06-13 17:34:07 -0700351 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700352
353 ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
Hemant Kumar14401d52011-11-03 16:40:32 -0700354
355 dev->brdg = NULL;
356}
357EXPORT_SYMBOL(ctrl_bridge_close);
358
359static void ctrl_write_callback(struct urb *urb)
360{
Hemant Kumarf13358e2012-01-19 12:07:20 -0800361 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700362
363 if (urb->status) {
364 pr_debug("Write status/size %d/%d\n",
365 urb->status, urb->actual_length);
366 }
367
368 kfree(urb->transfer_buffer);
369 kfree(urb->setup_packet);
370 usb_free_urb(urb);
Hemant Kumar262682a2013-02-01 09:46:45 -0800371
372 /* if we are here after device disconnect
373 * usb_unbind_interface() takes care of
374 * residual pm_autopm_get_interface_* calls
375 */
376 if (urb->dev->state != USB_STATE_NOTATTACHED)
377 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700378}
379
380int ctrl_bridge_write(unsigned int id, char *data, size_t size)
381{
382 int result;
383 struct urb *writeurb;
384 struct usb_ctrlrequest *out_ctlreq;
Hemant Kumar14401d52011-11-03 16:40:32 -0700385 struct ctrl_bridge *dev;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530386 unsigned long flags;
Hemant Kumar14401d52011-11-03 16:40:32 -0700387
388 if (id >= MAX_BRIDGE_DEVICES) {
389 result = -EINVAL;
390 goto free_data;
391 }
392
393 dev = __dev[id];
394
395 if (!dev) {
396 result = -ENODEV;
397 goto free_data;
398 }
399
Jack Phame8741502012-06-13 17:34:07 -0700400 dev_dbg(&dev->intf->dev, "%s:[id]:%u: write (%d bytes)\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700401 __func__, id, size);
402
403 writeurb = usb_alloc_urb(0, GFP_ATOMIC);
404 if (!writeurb) {
Jack Phame8741502012-06-13 17:34:07 -0700405 dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700406 __func__);
407 result = -ENOMEM;
408 goto free_data;
409 }
410
411 out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
412 if (!out_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700413 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700414 "%s: error allocating setup packet buffer\n",
415 __func__);
416 result = -ENOMEM;
417 goto free_urb;
418 }
419
420 /* CDC Send Encapsulated Request packet */
421 out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
422 USB_RECIP_INTERFACE);
423 if (!data && !size) {
424 out_ctlreq->bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
425 out_ctlreq->wValue = dev->cbits_tomdm;
426 dev->set_ctrl_line_sts++;
427 } else {
428 out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
429 out_ctlreq->wValue = 0;
430 dev->snd_encap_cmd++;
431 }
432 out_ctlreq->wIndex =
433 dev->intf->cur_altsetting->desc.bInterfaceNumber;
434 out_ctlreq->wLength = cpu_to_le16(size);
435
Jack Phame8741502012-06-13 17:34:07 -0700436 usb_fill_control_urb(writeurb, dev->udev,
437 usb_sndctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700438 (unsigned char *)out_ctlreq,
439 (void *)data, size,
Hemant Kumarf13358e2012-01-19 12:07:20 -0800440 ctrl_write_callback, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700441
442 result = usb_autopm_get_interface_async(dev->intf);
443 if (result < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700444 dev_dbg(&dev->intf->dev, "%s: unable to resume interface: %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700445 __func__, result);
446
447 /*
448 * Revisit: if (result == -EPERM)
449 * bridge_suspend(dev->intf, PMSG_SUSPEND);
450 */
451
452 goto free_ctrlreq;
453 }
454
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530455 spin_lock_irqsave(&dev->lock, flags);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800456 if (test_bit(SUSPENDED, &dev->flags)) {
457 usb_anchor_urb(writeurb, &dev->tx_deferred);
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530458 spin_unlock_irqrestore(&dev->lock, flags);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800459 goto deferred;
460 }
461
Hemant Kumar14401d52011-11-03 16:40:32 -0700462 usb_anchor_urb(writeurb, &dev->tx_submitted);
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530463 spin_unlock_irqrestore(&dev->lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700464 result = usb_submit_urb(writeurb, GFP_ATOMIC);
465 if (result < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700466 dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700467 __func__, result);
468 usb_autopm_put_interface_async(dev->intf);
469 goto unanchor_urb;
470 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800471deferred:
Hemant Kumar14401d52011-11-03 16:40:32 -0700472 return size;
473
474unanchor_urb:
475 usb_unanchor_urb(writeurb);
476free_ctrlreq:
477 kfree(out_ctlreq);
478free_urb:
479 usb_free_urb(writeurb);
480free_data:
481 kfree(data);
482
483 return result;
484}
485EXPORT_SYMBOL(ctrl_bridge_write);
486
487int ctrl_bridge_suspend(unsigned int id)
488{
489 struct ctrl_bridge *dev;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530490 unsigned long flags;
Hemant Kumar14401d52011-11-03 16:40:32 -0700491
492 if (id >= MAX_BRIDGE_DEVICES)
493 return -EINVAL;
494
495 dev = __dev[id];
496 if (!dev)
497 return -ENODEV;
498
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530499 spin_lock_irqsave(&dev->lock, flags);
500 if (!usb_anchor_empty(&dev->tx_submitted) || dev->rx_state == RX_BUSY) {
501 spin_unlock_irqrestore(&dev->lock, flags);
502 return -EBUSY;
503 }
504 spin_unlock_irqrestore(&dev->lock, flags);
505
Hemant Kumar262682a2013-02-01 09:46:45 -0800506 usb_kill_urb(dev->inturb);
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530507
508 spin_lock_irqsave(&dev->lock, flags);
509 if (dev->rx_state != RX_IDLE) {
510 spin_unlock_irqrestore(&dev->lock, flags);
511 return -EBUSY;
512 }
513 if (!usb_anchor_empty(&dev->tx_submitted)) {
514 spin_unlock_irqrestore(&dev->lock, flags);
515 ctrl_bridge_start_read(dev, GFP_KERNEL);
516 return -EBUSY;
517 }
518 set_bit(SUSPENDED, &dev->flags);
519 spin_unlock_irqrestore(&dev->lock, flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700520
Jack Pham9b0a0e52012-02-28 18:05:14 -0800521 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700522}
523
524int ctrl_bridge_resume(unsigned int id)
525{
526 struct ctrl_bridge *dev;
Jack Pham9b0a0e52012-02-28 18:05:14 -0800527 struct urb *urb;
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530528 unsigned long flags;
529 int ret;
Hemant Kumar14401d52011-11-03 16:40:32 -0700530
531 if (id >= MAX_BRIDGE_DEVICES)
532 return -EINVAL;
533
534 dev = __dev[id];
535 if (!dev)
536 return -ENODEV;
537
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530538 if (!test_bit(SUSPENDED, &dev->flags))
Jack Pham9b0a0e52012-02-28 18:05:14 -0800539 return 0;
540
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530541 spin_lock_irqsave(&dev->lock, flags);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800542 /* submit pending write requests */
543 while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530544 spin_unlock_irqrestore(&dev->lock, flags);
545 /*
546 * usb_get_from_anchor() does not drop the
547 * ref count incremented by the usb_anchro_urb()
548 * called in Tx submission path. Let us do it.
549 */
550 usb_put_urb(urb);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800551 usb_anchor_urb(urb, &dev->tx_submitted);
552 ret = usb_submit_urb(urb, GFP_ATOMIC);
553 if (ret < 0) {
554 usb_unanchor_urb(urb);
555 kfree(urb->setup_packet);
556 kfree(urb->transfer_buffer);
557 usb_free_urb(urb);
558 usb_autopm_put_interface_async(dev->intf);
559 }
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530560 spin_lock_irqsave(&dev->lock, flags);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800561 }
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530562 clear_bit(SUSPENDED, &dev->flags);
563 spin_unlock_irqrestore(&dev->lock, flags);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800564
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530565 return ctrl_bridge_start_read(dev, GFP_KERNEL);
Hemant Kumar14401d52011-11-03 16:40:32 -0700566}
567
568#if defined(CONFIG_DEBUG_FS)
569#define DEBUG_BUF_SIZE 1024
570static ssize_t ctrl_bridge_read_stats(struct file *file, char __user *ubuf,
571 size_t count, loff_t *ppos)
572{
573 struct ctrl_bridge *dev;
574 char *buf;
575 int ret;
576 int i;
577 int temp = 0;
578
579 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
580 if (!buf)
581 return -ENOMEM;
582
Hemant Kumar67107002013-02-11 13:24:08 -0800583 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700584 dev = __dev[i];
585 if (!dev)
586 continue;
587
588 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
589 "\nName#%s dev %p\n"
590 "snd encap cmd cnt: %u\n"
591 "get encap res cnt: %u\n"
592 "res available cnt: %u\n"
593 "set ctrlline sts cnt: %u\n"
594 "notify ser state cnt: %u\n"
595 "cbits_tomdm: %d\n"
Jack Pham9b0a0e52012-02-28 18:05:14 -0800596 "cbits_tohost: %d\n"
597 "suspended: %d\n",
Hemant Kumar67107002013-02-11 13:24:08 -0800598 dev->name, dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700599 dev->snd_encap_cmd,
600 dev->get_encap_res,
601 dev->resp_avail,
602 dev->set_ctrl_line_sts,
603 dev->notify_ser_state,
604 dev->cbits_tomdm,
Jack Pham9b0a0e52012-02-28 18:05:14 -0800605 dev->cbits_tohost,
606 test_bit(SUSPENDED, &dev->flags));
Hemant Kumar14401d52011-11-03 16:40:32 -0700607 }
608
609 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
610
611 kfree(buf);
612
613 return ret;
614}
615
616static ssize_t ctrl_bridge_reset_stats(struct file *file,
617 const char __user *buf, size_t count, loff_t *ppos)
618{
619 struct ctrl_bridge *dev;
620 int i;
621
Hemant Kumar67107002013-02-11 13:24:08 -0800622 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700623 dev = __dev[i];
624 if (!dev)
625 continue;
626
627 dev->snd_encap_cmd = 0;
628 dev->get_encap_res = 0;
629 dev->resp_avail = 0;
630 dev->set_ctrl_line_sts = 0;
631 dev->notify_ser_state = 0;
632 }
633 return count;
634}
635
636const struct file_operations ctrl_stats_ops = {
637 .read = ctrl_bridge_read_stats,
638 .write = ctrl_bridge_reset_stats,
639};
640
641struct dentry *ctrl_dent;
642struct dentry *ctrl_dfile;
643static void ctrl_bridge_debugfs_init(void)
644{
645 ctrl_dent = debugfs_create_dir("ctrl_hsic_bridge", 0);
646 if (IS_ERR(ctrl_dent))
647 return;
648
649 ctrl_dfile =
650 debugfs_create_file("status", 0644, ctrl_dent, 0,
651 &ctrl_stats_ops);
652 if (!ctrl_dfile || IS_ERR(ctrl_dfile))
653 debugfs_remove(ctrl_dent);
654}
655
656static void ctrl_bridge_debugfs_exit(void)
657{
658 debugfs_remove(ctrl_dfile);
659 debugfs_remove(ctrl_dent);
660}
661
662#else
663static void ctrl_bridge_debugfs_init(void) { }
664static void ctrl_bridge_debugfs_exit(void) { }
665#endif
666
667int
668ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
Hemant Kumarc2b17782013-02-03 15:56:29 -0800669 char *name, int id)
Hemant Kumar14401d52011-11-03 16:40:32 -0700670{
671 struct ctrl_bridge *dev;
672 struct usb_device *udev;
673 struct usb_endpoint_descriptor *ep;
674 u16 wMaxPacketSize;
675 int retval = 0;
676 int interval;
677
678 udev = interface_to_usbdev(ifc);
679
Hemant Kumar262682a2013-02-01 09:46:45 -0800680 dev = __dev[id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700681 if (!dev) {
Hemant Kumar262682a2013-02-01 09:46:45 -0800682 pr_err("%s:device not found\n", __func__);
683 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700684 }
Hemant Kumar262682a2013-02-01 09:46:45 -0800685
Hemant Kumarc2b17782013-02-03 15:56:29 -0800686 dev->name = name;
687
688 dev->pdev = platform_device_alloc(name, -1);
Hemant Kumar14401d52011-11-03 16:40:32 -0700689 if (!dev->pdev) {
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530690 retval = -ENOMEM;
Jack Phame8741502012-06-13 17:34:07 -0700691 dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
692 __func__);
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530693 goto free_name;
Hemant Kumar14401d52011-11-03 16:40:32 -0700694 }
695
Hemant Kumar262682a2013-02-01 09:46:45 -0800696 dev->flags = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700697 dev->udev = udev;
698 dev->int_pipe = usb_rcvintpipe(udev,
699 int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
700 dev->intf = ifc;
701
Hemant Kumar14401d52011-11-03 16:40:32 -0700702 /*use max pkt size from ep desc*/
703 ep = &dev->intf->cur_altsetting->endpoint[0].desc;
704
705 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
706 if (!dev->inturb) {
Jack Phame8741502012-06-13 17:34:07 -0700707 dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700708 retval = -ENOMEM;
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530709 goto pdev_put;
Hemant Kumar14401d52011-11-03 16:40:32 -0700710 }
711
712 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
713
714 dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
715 if (!dev->intbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700716 dev_err(&ifc->dev, "%s: error allocating int buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700717 __func__);
718 retval = -ENOMEM;
719 goto free_inturb;
720 }
721
722 interval =
723 (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;
724
725 usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
726 dev->intbuf, wMaxPacketSize,
727 notification_available_cb, dev, interval);
728
729 dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
730 if (!dev->readurb) {
Jack Phame8741502012-06-13 17:34:07 -0700731 dev_err(&ifc->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700732 __func__);
733 retval = -ENOMEM;
734 goto free_intbuf;
735 }
736
737 dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
738 if (!dev->readbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700739 dev_err(&ifc->dev, "%s: error allocating read buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700740 __func__);
741 retval = -ENOMEM;
742 goto free_rurb;
743 }
744
745 dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
746 if (!dev->in_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700747 dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700748 __func__);
749 retval = -ENOMEM;
750 goto free_rbuf;
751 }
752
753 dev->in_ctlreq->bRequestType =
754 (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
755 dev->in_ctlreq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
756 dev->in_ctlreq->wValue = 0;
757 dev->in_ctlreq->wIndex =
758 dev->intf->cur_altsetting->desc.bInterfaceNumber;
759 dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
760
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530761 retval = platform_device_add(dev->pdev);
762 if (retval) {
763 dev_err(&ifc->dev, "%s:fail to add pdev\n", __func__);
764 goto free_ctrlreq;
765 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700766
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530767 retval = ctrl_bridge_start_read(dev, GFP_KERNEL);
768 if (retval) {
769 dev_err(&ifc->dev, "%s:fail to start reading\n", __func__);
770 goto pdev_del;
771 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700772
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530773 return 0;
774
775pdev_del:
776 platform_device_del(dev->pdev);
777free_ctrlreq:
778 kfree(dev->in_ctlreq);
Hemant Kumar14401d52011-11-03 16:40:32 -0700779free_rbuf:
780 kfree(dev->readbuf);
781free_rurb:
782 usb_free_urb(dev->readurb);
783free_intbuf:
784 kfree(dev->intbuf);
785free_inturb:
786 usb_free_urb(dev->inturb);
Pavankumar Kondeti90851542013-03-22 13:26:00 +0530787pdev_put:
788 platform_device_put(dev->pdev);
789free_name:
790 dev->name = "none";
Hemant Kumar14401d52011-11-03 16:40:32 -0700791
792 return retval;
793}
794
795void ctrl_bridge_disconnect(unsigned int id)
796{
797 struct ctrl_bridge *dev = __dev[id];
798
Jack Phame8741502012-06-13 17:34:07 -0700799 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700800
Hemant Kumar67107002013-02-11 13:24:08 -0800801 /*set device name to none to get correct channel id
802 * at the time of bridge open
803 */
804 dev->name = "none";
805
Jack Pham1b1ba472012-06-13 16:40:15 -0700806 platform_device_unregister(dev->pdev);
Jack Pham452c6922011-12-14 18:15:26 -0800807
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530808 usb_scuttle_anchored_urbs(&dev->tx_deferred);
Hemant Kumar262682a2013-02-01 09:46:45 -0800809 usb_kill_anchored_urbs(&dev->tx_submitted);
810
811 usb_kill_urb(dev->inturb);
812 usb_kill_urb(dev->readurb);
Hemant Kumar77f79572012-11-08 12:19:26 -0800813
Hemant Kumar14401d52011-11-03 16:40:32 -0700814 kfree(dev->in_ctlreq);
815 kfree(dev->readbuf);
816 kfree(dev->intbuf);
817
818 usb_free_urb(dev->readurb);
819 usb_free_urb(dev->inturb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700820}
821
Hemant Kumar262682a2013-02-01 09:46:45 -0800822int ctrl_bridge_init(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700823{
Hemant Kumar262682a2013-02-01 09:46:45 -0800824 struct ctrl_bridge *dev;
825 int i;
826 int retval = 0;
827
828 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
829
830 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
831 if (!dev) {
832 pr_err("%s: unable to allocate dev\n", __func__);
833 retval = -ENOMEM;
834 goto error;
835 }
836
Hemant Kumarc2b17782013-02-03 15:56:29 -0800837 /*transport name will be set during probe*/
Hemant Kumar67107002013-02-11 13:24:08 -0800838 dev->name = "none";
Hemant Kumarc2b17782013-02-03 15:56:29 -0800839
Pavankumar Kondeti01b23a12013-02-25 21:57:54 +0530840 spin_lock_init(&dev->lock);
Hemant Kumar262682a2013-02-01 09:46:45 -0800841 init_usb_anchor(&dev->tx_submitted);
842 init_usb_anchor(&dev->tx_deferred);
843
844 __dev[i] = dev;
845 }
846
Hemant Kumar14401d52011-11-03 16:40:32 -0700847 ctrl_bridge_debugfs_init();
848
849 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700850
Hemant Kumar262682a2013-02-01 09:46:45 -0800851error:
852 while (--i >= 0) {
853 kfree(__dev[i]);
854 __dev[i] = NULL;
855 }
856
857 return retval;
858}
859
860void ctrl_bridge_exit(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700861{
Hemant Kumar262682a2013-02-01 09:46:45 -0800862 int i;
Hemant Kumar14401d52011-11-03 16:40:32 -0700863
Hemant Kumar262682a2013-02-01 09:46:45 -0800864 ctrl_bridge_debugfs_exit();
865
866 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
867 kfree(__dev[i]);
868 __dev[i] = NULL;
869 }
870}