USB: option: revert introduction of struct option_private
[deliverable/linux.git] / drivers / usb / serial / usb_wwan.c
CommitLineData
0d456194
MG
1/*
2 USB Driver layer for GSM modems
3
4 Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de>
5
6 This driver is free software; you can redistribute it and/or modify
7 it under the terms of Version 2 of the GNU General Public License as
8 published by the Free Software Foundation.
9
10 Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
11
12 History: see the git log.
13
14 Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
15
16 This driver exists because the "normal" serial driver doesn't work too well
17 with GSM modems. Issues:
18 - data loss -- one single Receive URB is not nearly enough
19 - controlling the baud rate doesn't make sense
20*/
21
0d456194
MG
22#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
23#define DRIVER_DESC "USB Driver for GSM modems"
24
25#include <linux/kernel.h>
26#include <linux/jiffies.h>
27#include <linux/errno.h>
28#include <linux/slab.h>
29#include <linux/tty.h>
30#include <linux/tty_flip.h>
31#include <linux/module.h>
32#include <linux/bitops.h>
66921edd 33#include <linux/uaccess.h>
0d456194
MG
34#include <linux/usb.h>
35#include <linux/usb/serial.h>
02303f73 36#include <linux/serial.h>
0d456194
MG
37#include "usb-wwan.h"
38
0d456194
MG
39void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
40{
0d456194 41 struct usb_wwan_port_private *portdata;
0d456194
MG
42 struct usb_wwan_intf_private *intfdata;
43
37357ca5 44 intfdata = usb_get_serial_data(port->serial);
0d456194
MG
45
46 if (!intfdata->send_setup)
47 return;
48
49 portdata = usb_get_serial_port_data(port);
b2ca6990 50 /* FIXME: locking */
0d456194
MG
51 portdata->rts_state = on;
52 portdata->dtr_state = on;
b2ca6990
JH
53
54 intfdata->send_setup(port);
0d456194
MG
55}
56EXPORT_SYMBOL(usb_wwan_dtr_rts);
57
60b33c13 58int usb_wwan_tiocmget(struct tty_struct *tty)
0d456194
MG
59{
60 struct usb_serial_port *port = tty->driver_data;
61 unsigned int value;
62 struct usb_wwan_port_private *portdata;
63
64 portdata = usb_get_serial_port_data(port);
65
66 value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
67 ((portdata->dtr_state) ? TIOCM_DTR : 0) |
68 ((portdata->cts_state) ? TIOCM_CTS : 0) |
69 ((portdata->dsr_state) ? TIOCM_DSR : 0) |
70 ((portdata->dcd_state) ? TIOCM_CAR : 0) |
71 ((portdata->ri_state) ? TIOCM_RNG : 0);
72
73 return value;
74}
75EXPORT_SYMBOL(usb_wwan_tiocmget);
76
20b9d177 77int usb_wwan_tiocmset(struct tty_struct *tty,
0d456194
MG
78 unsigned int set, unsigned int clear)
79{
80 struct usb_serial_port *port = tty->driver_data;
81 struct usb_wwan_port_private *portdata;
82 struct usb_wwan_intf_private *intfdata;
83
84 portdata = usb_get_serial_port_data(port);
37357ca5 85 intfdata = usb_get_serial_data(port->serial);
0d456194
MG
86
87 if (!intfdata->send_setup)
88 return -EINVAL;
89
90 /* FIXME: what locks portdata fields ? */
91 if (set & TIOCM_RTS)
92 portdata->rts_state = 1;
93 if (set & TIOCM_DTR)
94 portdata->dtr_state = 1;
95
96 if (clear & TIOCM_RTS)
97 portdata->rts_state = 0;
98 if (clear & TIOCM_DTR)
99 portdata->dtr_state = 0;
100 return intfdata->send_setup(port);
101}
102EXPORT_SYMBOL(usb_wwan_tiocmset);
103
02303f73
DW
104static int get_serial_info(struct usb_serial_port *port,
105 struct serial_struct __user *retinfo)
106{
107 struct serial_struct tmp;
108
109 if (!retinfo)
110 return -EFAULT;
111
112 memset(&tmp, 0, sizeof(tmp));
e5b1e206 113 tmp.line = port->minor;
1143832e 114 tmp.port = port->port_number;
02303f73
DW
115 tmp.baud_base = tty_get_baud_rate(port->port.tty);
116 tmp.close_delay = port->port.close_delay / 10;
117 tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
118 ASYNC_CLOSING_WAIT_NONE :
119 port->port.closing_wait / 10;
120
121 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
122 return -EFAULT;
123 return 0;
124}
125
126static int set_serial_info(struct usb_serial_port *port,
127 struct serial_struct __user *newinfo)
128{
129 struct serial_struct new_serial;
130 unsigned int closing_wait, close_delay;
131 int retval = 0;
132
133 if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
134 return -EFAULT;
135
136 close_delay = new_serial.close_delay * 10;
137 closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
138 ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
139
140 mutex_lock(&port->port.mutex);
141
142 if (!capable(CAP_SYS_ADMIN)) {
143 if ((close_delay != port->port.close_delay) ||
144 (closing_wait != port->port.closing_wait))
145 retval = -EPERM;
146 else
147 retval = -EOPNOTSUPP;
148 } else {
149 port->port.close_delay = close_delay;
150 port->port.closing_wait = closing_wait;
151 }
152
153 mutex_unlock(&port->port.mutex);
154 return retval;
155}
156
00a0d0d6 157int usb_wwan_ioctl(struct tty_struct *tty,
02303f73
DW
158 unsigned int cmd, unsigned long arg)
159{
160 struct usb_serial_port *port = tty->driver_data;
161
a80be97d 162 dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
02303f73
DW
163
164 switch (cmd) {
165 case TIOCGSERIAL:
166 return get_serial_info(port,
167 (struct serial_struct __user *) arg);
168 case TIOCSSERIAL:
169 return set_serial_info(port,
170 (struct serial_struct __user *) arg);
171 default:
172 break;
173 }
174
a80be97d 175 dev_dbg(&port->dev, "%s arg not supported\n", __func__);
02303f73
DW
176
177 return -ENOIOCTLCMD;
178}
179EXPORT_SYMBOL(usb_wwan_ioctl);
180
0d456194
MG
181int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
182 const unsigned char *buf, int count)
183{
184 struct usb_wwan_port_private *portdata;
185 struct usb_wwan_intf_private *intfdata;
186 int i;
187 int left, todo;
188 struct urb *this_urb = NULL; /* spurious */
189 int err;
190 unsigned long flags;
191
192 portdata = usb_get_serial_port_data(port);
37357ca5 193 intfdata = usb_get_serial_data(port->serial);
0d456194 194
a80be97d 195 dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count);
0d456194
MG
196
197 i = 0;
198 left = count;
199 for (i = 0; left > 0 && i < N_OUT_URB; i++) {
200 todo = left;
201 if (todo > OUT_BUFLEN)
202 todo = OUT_BUFLEN;
203
204 this_urb = portdata->out_urbs[i];
205 if (test_and_set_bit(i, &portdata->out_busy)) {
206 if (time_before(jiffies,
207 portdata->tx_start_time[i] + 10 * HZ))
208 continue;
209 usb_unlink_urb(this_urb);
210 continue;
211 }
a80be97d
GKH
212 dev_dbg(&port->dev, "%s: endpoint %d buf %d\n", __func__,
213 usb_pipeendpoint(this_urb->pipe), i);
0d456194
MG
214
215 err = usb_autopm_get_interface_async(port->serial->interface);
db090473 216 if (err < 0) {
217 clear_bit(i, &portdata->out_busy);
0d456194 218 break;
db090473 219 }
0d456194
MG
220
221 /* send the data */
222 memcpy(this_urb->transfer_buffer, buf, todo);
223 this_urb->transfer_buffer_length = todo;
224
225 spin_lock_irqsave(&intfdata->susp_lock, flags);
226 if (intfdata->suspended) {
227 usb_anchor_urb(this_urb, &portdata->delayed);
228 spin_unlock_irqrestore(&intfdata->susp_lock, flags);
229 } else {
230 intfdata->in_flight++;
231 spin_unlock_irqrestore(&intfdata->susp_lock, flags);
232 err = usb_submit_urb(this_urb, GFP_ATOMIC);
233 if (err) {
8bb7ec65
JH
234 dev_err(&port->dev,
235 "%s: submit urb %d failed: %d\n",
236 __func__, i, err);
0d456194
MG
237 clear_bit(i, &portdata->out_busy);
238 spin_lock_irqsave(&intfdata->susp_lock, flags);
239 intfdata->in_flight--;
240 spin_unlock_irqrestore(&intfdata->susp_lock,
241 flags);
3d06bf15 242 usb_autopm_put_interface_async(port->serial->interface);
433508ae 243 break;
0d456194
MG
244 }
245 }
246
247 portdata->tx_start_time[i] = jiffies;
248 buf += todo;
249 left -= todo;
250 }
251
252 count -= left;
a80be97d 253 dev_dbg(&port->dev, "%s: wrote (did %d)\n", __func__, count);
0d456194
MG
254 return count;
255}
256EXPORT_SYMBOL(usb_wwan_write);
257
258static void usb_wwan_indat_callback(struct urb *urb)
259{
260 int err;
261 int endpoint;
262 struct usb_serial_port *port;
a80be97d 263 struct device *dev;
0d456194
MG
264 unsigned char *data = urb->transfer_buffer;
265 int status = urb->status;
266
0d456194
MG
267 endpoint = usb_pipeendpoint(urb->pipe);
268 port = urb->context;
a80be97d 269 dev = &port->dev;
0d456194
MG
270
271 if (status) {
a80be97d
GKH
272 dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
273 __func__, status, endpoint);
0d456194 274 } else {
2e124b4a
JS
275 if (urb->actual_length) {
276 tty_insert_flip_string(&port->port, data,
277 urb->actual_length);
278 tty_flip_buffer_push(&port->port);
279 } else
280 dev_dbg(dev, "%s: empty read urb received\n", __func__);
6c1ee66a
MB
281 }
282 /* Resubmit urb so we continue receiving */
283 err = usb_submit_urb(urb, GFP_ATOMIC);
284 if (err) {
d2958d1b 285 if (err != -EPERM && err != -ENODEV) {
6c1ee66a
MB
286 dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
287 __func__, err);
288 /* busy also in error unless we are killed */
ec42899c 289 usb_mark_last_busy(port->serial->dev);
0d456194 290 }
6c1ee66a
MB
291 } else {
292 usb_mark_last_busy(port->serial->dev);
0d456194 293 }
0d456194
MG
294}
295
296static void usb_wwan_outdat_callback(struct urb *urb)
297{
298 struct usb_serial_port *port;
299 struct usb_wwan_port_private *portdata;
300 struct usb_wwan_intf_private *intfdata;
301 int i;
302
0d456194 303 port = urb->context;
37357ca5 304 intfdata = usb_get_serial_data(port->serial);
0d456194
MG
305
306 usb_serial_port_softint(port);
307 usb_autopm_put_interface_async(port->serial->interface);
308 portdata = usb_get_serial_port_data(port);
309 spin_lock(&intfdata->susp_lock);
310 intfdata->in_flight--;
311 spin_unlock(&intfdata->susp_lock);
312
313 for (i = 0; i < N_OUT_URB; ++i) {
314 if (portdata->out_urbs[i] == urb) {
4e857c58 315 smp_mb__before_atomic();
0d456194
MG
316 clear_bit(i, &portdata->out_busy);
317 break;
318 }
319 }
320}
321
322int usb_wwan_write_room(struct tty_struct *tty)
323{
324 struct usb_serial_port *port = tty->driver_data;
325 struct usb_wwan_port_private *portdata;
326 int i;
327 int data_len = 0;
328 struct urb *this_urb;
329
330 portdata = usb_get_serial_port_data(port);
331
332 for (i = 0; i < N_OUT_URB; i++) {
333 this_urb = portdata->out_urbs[i];
334 if (this_urb && !test_bit(i, &portdata->out_busy))
335 data_len += OUT_BUFLEN;
336 }
337
a80be97d 338 dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
0d456194
MG
339 return data_len;
340}
341EXPORT_SYMBOL(usb_wwan_write_room);
342
343int usb_wwan_chars_in_buffer(struct tty_struct *tty)
344{
345 struct usb_serial_port *port = tty->driver_data;
346 struct usb_wwan_port_private *portdata;
347 int i;
348 int data_len = 0;
349 struct urb *this_urb;
350
351 portdata = usb_get_serial_port_data(port);
352
353 for (i = 0; i < N_OUT_URB; i++) {
354 this_urb = portdata->out_urbs[i];
355 /* FIXME: This locking is insufficient as this_urb may
356 go unused during the test */
357 if (this_urb && test_bit(i, &portdata->out_busy))
358 data_len += this_urb->transfer_buffer_length;
359 }
a80be97d 360 dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
0d456194
MG
361 return data_len;
362}
363EXPORT_SYMBOL(usb_wwan_chars_in_buffer);
364
365int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
366{
367 struct usb_wwan_port_private *portdata;
368 struct usb_wwan_intf_private *intfdata;
369 struct usb_serial *serial = port->serial;
370 int i, err;
371 struct urb *urb;
372
373 portdata = usb_get_serial_port_data(port);
37357ca5 374 intfdata = usb_get_serial_data(serial);
0d456194 375
9096f1fb
JH
376 if (port->interrupt_in_urb) {
377 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
378 if (err) {
8bb7ec65 379 dev_err(&port->dev, "%s: submit int urb failed: %d\n",
9096f1fb
JH
380 __func__, err);
381 }
382 }
383
0d456194
MG
384 /* Start reading from the IN endpoint */
385 for (i = 0; i < N_IN_URB; i++) {
386 urb = portdata->in_urbs[i];
387 if (!urb)
388 continue;
389 err = usb_submit_urb(urb, GFP_KERNEL);
390 if (err) {
8bb7ec65
JH
391 dev_err(&port->dev,
392 "%s: submit read urb %d failed: %d\n",
393 __func__, i, err);
0d456194
MG
394 }
395 }
396
0d456194 397 spin_lock_irq(&intfdata->susp_lock);
c1c01803
JH
398 if (++intfdata->open_ports == 1)
399 serial->interface->needs_remote_wakeup = 1;
0d456194 400 spin_unlock_irq(&intfdata->susp_lock);
9a91aedc 401 /* this balances a get in the generic USB serial code */
0d456194
MG
402 usb_autopm_put_interface(serial->interface);
403
404 return 0;
405}
406EXPORT_SYMBOL(usb_wwan_open);
407
79eed03e
JH
408static void unbusy_queued_urb(struct urb *urb,
409 struct usb_wwan_port_private *portdata)
410{
411 int i;
412
413 for (i = 0; i < N_OUT_URB; i++) {
414 if (urb == portdata->out_urbs[i]) {
415 clear_bit(i, &portdata->out_busy);
416 break;
417 }
418 }
419}
420
0d456194
MG
421void usb_wwan_close(struct usb_serial_port *port)
422{
423 int i;
424 struct usb_serial *serial = port->serial;
425 struct usb_wwan_port_private *portdata;
37357ca5 426 struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
79eed03e 427 struct urb *urb;
0d456194 428
0d456194
MG
429 portdata = usb_get_serial_port_data(port);
430
b0a9aa6d
JH
431 /*
432 * Need to take susp_lock to make sure port is not already being
433 * resumed, but no need to hold it due to ASYNC_INITIALIZED.
434 */
e6d144bc 435 spin_lock_irq(&intfdata->susp_lock);
c1c01803
JH
436 if (--intfdata->open_ports == 0)
437 serial->interface->needs_remote_wakeup = 0;
e6d144bc
JH
438 spin_unlock_irq(&intfdata->susp_lock);
439
79eed03e
JH
440 for (;;) {
441 urb = usb_get_from_anchor(&portdata->delayed);
442 if (!urb)
443 break;
444 unbusy_queued_urb(urb, portdata);
445 usb_autopm_put_interface_async(serial->interface);
446 }
447
e6d144bc
JH
448 for (i = 0; i < N_IN_URB; i++)
449 usb_kill_urb(portdata->in_urbs[i]);
450 for (i = 0; i < N_OUT_URB; i++)
451 usb_kill_urb(portdata->out_urbs[i]);
9096f1fb 452 usb_kill_urb(port->interrupt_in_urb);
e6d144bc 453
e6d144bc 454 usb_autopm_get_interface_no_resume(serial->interface);
0d456194
MG
455}
456EXPORT_SYMBOL(usb_wwan_close);
457
b8f0e820
JH
458static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
459 int endpoint,
0d456194
MG
460 int dir, void *ctx, char *buf, int len,
461 void (*callback) (struct urb *))
462{
b8f0e820 463 struct usb_serial *serial = port->serial;
0d456194
MG
464 struct urb *urb;
465
0d456194 466 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
10c642d0 467 if (!urb)
0d456194 468 return NULL;
0d456194 469
0d456194
MG
470 usb_fill_bulk_urb(urb, serial->dev,
471 usb_sndbulkpipe(serial->dev, endpoint) | dir,
472 buf, len, callback, ctx);
473
474 return urb;
475}
476
b8f0e820 477int usb_wwan_port_probe(struct usb_serial_port *port)
0d456194 478{
0d456194 479 struct usb_wwan_port_private *portdata;
b8f0e820
JH
480 struct urb *urb;
481 u8 *buffer;
b8f0e820 482 int i;
0d456194 483
bd73bd88
JH
484 if (!port->bulk_in_size || !port->bulk_out_size)
485 return -ENODEV;
486
b8f0e820
JH
487 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
488 if (!portdata)
489 return -ENOMEM;
0d456194 490
b8f0e820 491 init_usb_anchor(&portdata->delayed);
0d456194 492
b8f0e820
JH
493 for (i = 0; i < N_IN_URB; i++) {
494 buffer = (u8 *)__get_free_page(GFP_KERNEL);
495 if (!buffer)
496 goto bail_out_error;
497 portdata->in_buffer[i] = buffer;
498
499 urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
500 USB_DIR_IN, port,
501 buffer, IN_BUFLEN,
502 usb_wwan_indat_callback);
503 portdata->in_urbs[i] = urb;
504 }
0d456194 505
b8f0e820 506 for (i = 0; i < N_OUT_URB; i++) {
b8f0e820
JH
507 buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
508 if (!buffer)
509 goto bail_out_error2;
510 portdata->out_buffer[i] = buffer;
0d456194 511
b8f0e820
JH
512 urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
513 USB_DIR_OUT, port,
514 buffer, OUT_BUFLEN,
515 usb_wwan_outdat_callback);
516 portdata->out_urbs[i] = urb;
517 }
0d456194 518
b8f0e820 519 usb_set_serial_port_data(port, portdata);
0d456194 520
0d456194
MG
521 return 0;
522
523bail_out_error2:
b8f0e820
JH
524 for (i = 0; i < N_OUT_URB; i++) {
525 usb_free_urb(portdata->out_urbs[i]);
526 kfree(portdata->out_buffer[i]);
527 }
0d456194 528bail_out_error:
b8f0e820
JH
529 for (i = 0; i < N_IN_URB; i++) {
530 usb_free_urb(portdata->in_urbs[i]);
531 free_page((unsigned long)portdata->in_buffer[i]);
532 }
0d456194 533 kfree(portdata);
b8f0e820
JH
534
535 return -ENOMEM;
0d456194 536}
b8f0e820 537EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
0d456194 538
a1028f0a 539int usb_wwan_port_remove(struct usb_serial_port *port)
0d456194 540{
a1028f0a 541 int i;
0d456194
MG
542 struct usb_wwan_port_private *portdata;
543
a1028f0a
BM
544 portdata = usb_get_serial_port_data(port);
545 usb_set_serial_port_data(port, NULL);
546
a1028f0a 547 for (i = 0; i < N_IN_URB; i++) {
a1028f0a
BM
548 usb_free_urb(portdata->in_urbs[i]);
549 free_page((unsigned long)portdata->in_buffer[i]);
550 }
551 for (i = 0; i < N_OUT_URB; i++) {
a1028f0a
BM
552 usb_free_urb(portdata->out_urbs[i]);
553 kfree(portdata->out_buffer[i]);
0d456194 554 }
0d456194 555
a1028f0a 556 kfree(portdata);
2b4aceab 557
a1028f0a 558 return 0;
0d456194 559}
a1028f0a 560EXPORT_SYMBOL(usb_wwan_port_remove);
0d456194 561
a1028f0a 562#ifdef CONFIG_PM
ae75c940 563static void stop_urbs(struct usb_serial *serial)
0d456194
MG
564{
565 int i, j;
566 struct usb_serial_port *port;
567 struct usb_wwan_port_private *portdata;
568
0d456194
MG
569 for (i = 0; i < serial->num_ports; ++i) {
570 port = serial->port[i];
571 portdata = usb_get_serial_port_data(port);
032129cb
BM
572 if (!portdata)
573 continue;
a1028f0a
BM
574 for (j = 0; j < N_IN_URB; j++)
575 usb_kill_urb(portdata->in_urbs[j]);
576 for (j = 0; j < N_OUT_URB; j++)
577 usb_kill_urb(portdata->out_urbs[j]);
ae75c940 578 usb_kill_urb(port->interrupt_in_urb);
0d456194
MG
579 }
580}
0d456194 581
0d456194
MG
582int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
583{
37357ca5 584 struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
0d456194 585
170fad9e 586 spin_lock_irq(&intfdata->susp_lock);
5b1b0b81 587 if (PMSG_IS_AUTO(message)) {
170fad9e
JH
588 if (intfdata->in_flight) {
589 spin_unlock_irq(&intfdata->susp_lock);
0d456194 590 return -EBUSY;
170fad9e 591 }
0d456194 592 }
0d456194
MG
593 intfdata->suspended = 1;
594 spin_unlock_irq(&intfdata->susp_lock);
170fad9e 595
ae75c940 596 stop_urbs(serial);
0d456194
MG
597
598 return 0;
599}
600EXPORT_SYMBOL(usb_wwan_suspend);
601
3362c91c
JH
602/* Caller must hold susp_lock. */
603static int usb_wwan_submit_delayed_urbs(struct usb_serial_port *port)
0d456194 604{
7436f412 605 struct usb_serial *serial = port->serial;
37357ca5 606 struct usb_wwan_intf_private *data = usb_get_serial_data(serial);
0d456194
MG
607 struct usb_wwan_port_private *portdata;
608 struct urb *urb;
7436f412
JH
609 int err_count = 0;
610 int err;
0d456194
MG
611
612 portdata = usb_get_serial_port_data(port);
37357ca5 613
3362c91c
JH
614 for (;;) {
615 urb = usb_get_from_anchor(&portdata->delayed);
616 if (!urb)
617 break;
618
0d456194 619 err = usb_submit_urb(urb, GFP_ATOMIC);
7436f412 620 if (err) {
3362c91c 621 dev_err(&port->dev, "%s: submit urb failed: %d\n",
7436f412
JH
622 __func__, err);
623 err_count++;
624 unbusy_queued_urb(urb, portdata);
625 usb_autopm_put_interface_async(serial->interface);
626 continue;
16871dca 627 }
7436f412 628 data->in_flight++;
0d456194 629 }
fb7ad4f9 630
7436f412
JH
631 if (err_count)
632 return -EIO;
633
634 return 0;
0d456194
MG
635}
636
637int usb_wwan_resume(struct usb_serial *serial)
638{
639 int i, j;
640 struct usb_serial_port *port;
37357ca5 641 struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
0d456194
MG
642 struct usb_wwan_port_private *portdata;
643 struct urb *urb;
fb7ad4f9
JH
644 int err;
645 int err_count = 0;
0d456194 646
d9e93c08 647 spin_lock_irq(&intfdata->susp_lock);
0d456194 648 for (i = 0; i < serial->num_ports; i++) {
0d456194 649 port = serial->port[i];
0d456194 650
b0a9aa6d 651 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
0d456194 652 continue;
0d456194 653
b0a9aa6d
JH
654 portdata = usb_get_serial_port_data(port);
655
9096f1fb
JH
656 if (port->interrupt_in_urb) {
657 err = usb_submit_urb(port->interrupt_in_urb,
658 GFP_ATOMIC);
659 if (err) {
660 dev_err(&port->dev,
661 "%s: submit int urb failed: %d\n",
662 __func__, err);
fb7ad4f9 663 err_count++;
9096f1fb
JH
664 }
665 }
666
3362c91c 667 err = usb_wwan_submit_delayed_urbs(port);
fb7ad4f9
JH
668 if (err)
669 err_count++;
670
0d456194
MG
671 for (j = 0; j < N_IN_URB; j++) {
672 urb = portdata->in_urbs[j];
673 err = usb_submit_urb(urb, GFP_ATOMIC);
674 if (err < 0) {
b0f9d003
JH
675 dev_err(&port->dev,
676 "%s: submit read urb %d failed: %d\n",
677 __func__, i, err);
fb7ad4f9 678 err_count++;
0d456194
MG
679 }
680 }
0d456194 681 }
0d456194
MG
682 intfdata->suspended = 0;
683 spin_unlock_irq(&intfdata->susp_lock);
fb7ad4f9
JH
684
685 if (err_count)
686 return -EIO;
687
688 return 0;
0d456194
MG
689}
690EXPORT_SYMBOL(usb_wwan_resume);
691#endif
692
693MODULE_AUTHOR(DRIVER_AUTHOR);
694MODULE_DESCRIPTION(DRIVER_DESC);
0d456194 695MODULE_LICENSE("GPL");
This page took 0.347553 seconds and 5 git commands to generate.