]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/usb/serial/usb_wwan.c
USB: usb_wwan: remove unimplemented set_termios
[mirror_ubuntu-bionic-kernel.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
0d456194
MG
44 intfdata = port->serial->private;
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);
85 intfdata = port->serial->private;
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
181/* Write */
182int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
183 const unsigned char *buf, int count)
184{
185 struct usb_wwan_port_private *portdata;
186 struct usb_wwan_intf_private *intfdata;
187 int i;
188 int left, todo;
189 struct urb *this_urb = NULL; /* spurious */
190 int err;
191 unsigned long flags;
192
193 portdata = usb_get_serial_port_data(port);
194 intfdata = port->serial->private;
195
a80be97d 196 dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count);
0d456194
MG
197
198 i = 0;
199 left = count;
200 for (i = 0; left > 0 && i < N_OUT_URB; i++) {
201 todo = left;
202 if (todo > OUT_BUFLEN)
203 todo = OUT_BUFLEN;
204
205 this_urb = portdata->out_urbs[i];
206 if (test_and_set_bit(i, &portdata->out_busy)) {
207 if (time_before(jiffies,
208 portdata->tx_start_time[i] + 10 * HZ))
209 continue;
210 usb_unlink_urb(this_urb);
211 continue;
212 }
a80be97d
GKH
213 dev_dbg(&port->dev, "%s: endpoint %d buf %d\n", __func__,
214 usb_pipeendpoint(this_urb->pipe), i);
0d456194
MG
215
216 err = usb_autopm_get_interface_async(port->serial->interface);
db090473 217 if (err < 0) {
218 clear_bit(i, &portdata->out_busy);
0d456194 219 break;
db090473 220 }
0d456194
MG
221
222 /* send the data */
223 memcpy(this_urb->transfer_buffer, buf, todo);
224 this_urb->transfer_buffer_length = todo;
225
226 spin_lock_irqsave(&intfdata->susp_lock, flags);
227 if (intfdata->suspended) {
228 usb_anchor_urb(this_urb, &portdata->delayed);
229 spin_unlock_irqrestore(&intfdata->susp_lock, flags);
230 } else {
231 intfdata->in_flight++;
232 spin_unlock_irqrestore(&intfdata->susp_lock, flags);
233 err = usb_submit_urb(this_urb, GFP_ATOMIC);
234 if (err) {
a80be97d
GKH
235 dev_dbg(&port->dev,
236 "usb_submit_urb %p (write bulk) failed (%d)\n",
237 this_urb, err);
0d456194
MG
238 clear_bit(i, &portdata->out_busy);
239 spin_lock_irqsave(&intfdata->susp_lock, flags);
240 intfdata->in_flight--;
241 spin_unlock_irqrestore(&intfdata->susp_lock,
242 flags);
3d06bf15 243 usb_autopm_put_interface_async(port->serial->interface);
433508ae 244 break;
0d456194
MG
245 }
246 }
247
248 portdata->tx_start_time[i] = jiffies;
249 buf += todo;
250 left -= todo;
251 }
252
253 count -= left;
a80be97d 254 dev_dbg(&port->dev, "%s: wrote (did %d)\n", __func__, count);
0d456194
MG
255 return count;
256}
257EXPORT_SYMBOL(usb_wwan_write);
258
259static void usb_wwan_indat_callback(struct urb *urb)
260{
261 int err;
262 int endpoint;
263 struct usb_serial_port *port;
a80be97d 264 struct device *dev;
0d456194
MG
265 unsigned char *data = urb->transfer_buffer;
266 int status = urb->status;
267
0d456194
MG
268 endpoint = usb_pipeendpoint(urb->pipe);
269 port = urb->context;
a80be97d 270 dev = &port->dev;
0d456194
MG
271
272 if (status) {
a80be97d
GKH
273 dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
274 __func__, status, endpoint);
0d456194 275 } else {
2e124b4a
JS
276 if (urb->actual_length) {
277 tty_insert_flip_string(&port->port, data,
278 urb->actual_length);
279 tty_flip_buffer_push(&port->port);
280 } else
281 dev_dbg(dev, "%s: empty read urb received\n", __func__);
6c1ee66a
MB
282 }
283 /* Resubmit urb so we continue receiving */
284 err = usb_submit_urb(urb, GFP_ATOMIC);
285 if (err) {
286 if (err != -EPERM) {
287 dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
288 __func__, err);
289 /* busy also in error unless we are killed */
ec42899c 290 usb_mark_last_busy(port->serial->dev);
0d456194 291 }
6c1ee66a
MB
292 } else {
293 usb_mark_last_busy(port->serial->dev);
0d456194 294 }
0d456194
MG
295}
296
297static void usb_wwan_outdat_callback(struct urb *urb)
298{
299 struct usb_serial_port *port;
300 struct usb_wwan_port_private *portdata;
301 struct usb_wwan_intf_private *intfdata;
302 int i;
303
0d456194
MG
304 port = urb->context;
305 intfdata = port->serial->private;
306
307 usb_serial_port_softint(port);
308 usb_autopm_put_interface_async(port->serial->interface);
309 portdata = usb_get_serial_port_data(port);
310 spin_lock(&intfdata->susp_lock);
311 intfdata->in_flight--;
312 spin_unlock(&intfdata->susp_lock);
313
314 for (i = 0; i < N_OUT_URB; ++i) {
315 if (portdata->out_urbs[i] == urb) {
316 smp_mb__before_clear_bit();
317 clear_bit(i, &portdata->out_busy);
318 break;
319 }
320 }
321}
322
323int usb_wwan_write_room(struct tty_struct *tty)
324{
325 struct usb_serial_port *port = tty->driver_data;
326 struct usb_wwan_port_private *portdata;
327 int i;
328 int data_len = 0;
329 struct urb *this_urb;
330
331 portdata = usb_get_serial_port_data(port);
332
333 for (i = 0; i < N_OUT_URB; i++) {
334 this_urb = portdata->out_urbs[i];
335 if (this_urb && !test_bit(i, &portdata->out_busy))
336 data_len += OUT_BUFLEN;
337 }
338
a80be97d 339 dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
0d456194
MG
340 return data_len;
341}
342EXPORT_SYMBOL(usb_wwan_write_room);
343
344int usb_wwan_chars_in_buffer(struct tty_struct *tty)
345{
346 struct usb_serial_port *port = tty->driver_data;
347 struct usb_wwan_port_private *portdata;
348 int i;
349 int data_len = 0;
350 struct urb *this_urb;
351
352 portdata = usb_get_serial_port_data(port);
353
354 for (i = 0; i < N_OUT_URB; i++) {
355 this_urb = portdata->out_urbs[i];
356 /* FIXME: This locking is insufficient as this_urb may
357 go unused during the test */
358 if (this_urb && test_bit(i, &portdata->out_busy))
359 data_len += this_urb->transfer_buffer_length;
360 }
a80be97d 361 dev_dbg(&port->dev, "%s: %d\n", __func__, data_len);
0d456194
MG
362 return data_len;
363}
364EXPORT_SYMBOL(usb_wwan_chars_in_buffer);
365
366int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
367{
368 struct usb_wwan_port_private *portdata;
369 struct usb_wwan_intf_private *intfdata;
370 struct usb_serial *serial = port->serial;
371 int i, err;
372 struct urb *urb;
373
374 portdata = usb_get_serial_port_data(port);
375 intfdata = serial->private;
376
9096f1fb
JH
377 if (port->interrupt_in_urb) {
378 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
379 if (err) {
380 dev_dbg(&port->dev, "%s: submit int urb failed: %d\n",
381 __func__, err);
382 }
383 }
384
0d456194
MG
385 /* Start reading from the IN endpoint */
386 for (i = 0; i < N_IN_URB; i++) {
387 urb = portdata->in_urbs[i];
388 if (!urb)
389 continue;
390 err = usb_submit_urb(urb, GFP_KERNEL);
391 if (err) {
a80be97d
GKH
392 dev_dbg(&port->dev, "%s: submit urb %d failed (%d) %d\n",
393 __func__, i, err, urb->transfer_buffer_length);
0d456194
MG
394 }
395 }
396
0d456194
MG
397 spin_lock_irq(&intfdata->susp_lock);
398 portdata->opened = 1;
c1c01803
JH
399 if (++intfdata->open_ports == 1)
400 serial->interface->needs_remote_wakeup = 1;
0d456194 401 spin_unlock_irq(&intfdata->susp_lock);
9a91aedc 402 /* this balances a get in the generic USB serial code */
0d456194
MG
403 usb_autopm_put_interface(serial->interface);
404
405 return 0;
406}
407EXPORT_SYMBOL(usb_wwan_open);
408
79eed03e
JH
409static void unbusy_queued_urb(struct urb *urb,
410 struct usb_wwan_port_private *portdata)
411{
412 int i;
413
414 for (i = 0; i < N_OUT_URB; i++) {
415 if (urb == portdata->out_urbs[i]) {
416 clear_bit(i, &portdata->out_busy);
417 break;
418 }
419 }
420}
421
0d456194
MG
422void usb_wwan_close(struct usb_serial_port *port)
423{
424 int i;
425 struct usb_serial *serial = port->serial;
426 struct usb_wwan_port_private *portdata;
427 struct usb_wwan_intf_private *intfdata = port->serial->private;
79eed03e 428 struct urb *urb;
0d456194 429
0d456194
MG
430 portdata = usb_get_serial_port_data(port);
431
e6d144bc
JH
432 /* Stop reading/writing urbs */
433 spin_lock_irq(&intfdata->susp_lock);
434 portdata->opened = 0;
c1c01803
JH
435 if (--intfdata->open_ports == 0)
436 serial->interface->needs_remote_wakeup = 0;
e6d144bc
JH
437 spin_unlock_irq(&intfdata->susp_lock);
438
79eed03e
JH
439 for (;;) {
440 urb = usb_get_from_anchor(&portdata->delayed);
441 if (!urb)
442 break;
443 unbusy_queued_urb(urb, portdata);
444 usb_autopm_put_interface_async(serial->interface);
445 }
446
e6d144bc
JH
447 for (i = 0; i < N_IN_URB; i++)
448 usb_kill_urb(portdata->in_urbs[i]);
449 for (i = 0; i < N_OUT_URB; i++)
450 usb_kill_urb(portdata->out_urbs[i]);
9096f1fb 451 usb_kill_urb(port->interrupt_in_urb);
e6d144bc
JH
452
453 /* balancing - important as an error cannot be handled*/
454 usb_autopm_get_interface_no_resume(serial->interface);
0d456194
MG
455}
456EXPORT_SYMBOL(usb_wwan_close);
457
458/* Helper functions used by usb_wwan_setup_urbs */
b8f0e820
JH
459static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
460 int endpoint,
0d456194
MG
461 int dir, void *ctx, char *buf, int len,
462 void (*callback) (struct urb *))
463{
b8f0e820 464 struct usb_serial *serial = port->serial;
0d456194
MG
465 struct urb *urb;
466
0d456194 467 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
10c642d0 468 if (!urb)
0d456194 469 return NULL;
0d456194
MG
470
471 /* Fill URB using supplied data. */
472 usb_fill_bulk_urb(urb, serial->dev,
473 usb_sndbulkpipe(serial->dev, endpoint) | dir,
474 buf, len, callback, ctx);
475
476 return urb;
477}
478
b8f0e820 479int usb_wwan_port_probe(struct usb_serial_port *port)
0d456194 480{
0d456194 481 struct usb_wwan_port_private *portdata;
b8f0e820
JH
482 struct urb *urb;
483 u8 *buffer;
b8f0e820 484 int i;
0d456194 485
bd73bd88
JH
486 if (!port->bulk_in_size || !port->bulk_out_size)
487 return -ENODEV;
488
b8f0e820
JH
489 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
490 if (!portdata)
491 return -ENOMEM;
0d456194 492
b8f0e820 493 init_usb_anchor(&portdata->delayed);
0d456194 494
b8f0e820
JH
495 for (i = 0; i < N_IN_URB; i++) {
496 buffer = (u8 *)__get_free_page(GFP_KERNEL);
497 if (!buffer)
498 goto bail_out_error;
499 portdata->in_buffer[i] = buffer;
500
501 urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
502 USB_DIR_IN, port,
503 buffer, IN_BUFLEN,
504 usb_wwan_indat_callback);
505 portdata->in_urbs[i] = urb;
506 }
0d456194 507
b8f0e820 508 for (i = 0; i < N_OUT_URB; i++) {
b8f0e820
JH
509 buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
510 if (!buffer)
511 goto bail_out_error2;
512 portdata->out_buffer[i] = buffer;
0d456194 513
b8f0e820
JH
514 urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
515 USB_DIR_OUT, port,
516 buffer, OUT_BUFLEN,
517 usb_wwan_outdat_callback);
518 portdata->out_urbs[i] = urb;
519 }
0d456194 520
b8f0e820 521 usb_set_serial_port_data(port, portdata);
0d456194 522
0d456194
MG
523 return 0;
524
525bail_out_error2:
b8f0e820
JH
526 for (i = 0; i < N_OUT_URB; i++) {
527 usb_free_urb(portdata->out_urbs[i]);
528 kfree(portdata->out_buffer[i]);
529 }
0d456194 530bail_out_error:
b8f0e820
JH
531 for (i = 0; i < N_IN_URB; i++) {
532 usb_free_urb(portdata->in_urbs[i]);
533 free_page((unsigned long)portdata->in_buffer[i]);
534 }
0d456194 535 kfree(portdata);
b8f0e820
JH
536
537 return -ENOMEM;
0d456194 538}
b8f0e820 539EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
0d456194 540
a1028f0a 541int usb_wwan_port_remove(struct usb_serial_port *port)
0d456194 542{
a1028f0a 543 int i;
0d456194
MG
544 struct usb_wwan_port_private *portdata;
545
a1028f0a
BM
546 portdata = usb_get_serial_port_data(port);
547 usb_set_serial_port_data(port, NULL);
548
549 /* Stop reading/writing urbs and free them */
550 for (i = 0; i < N_IN_URB; i++) {
551 usb_kill_urb(portdata->in_urbs[i]);
552 usb_free_urb(portdata->in_urbs[i]);
553 free_page((unsigned long)portdata->in_buffer[i]);
554 }
555 for (i = 0; i < N_OUT_URB; i++) {
556 usb_kill_urb(portdata->out_urbs[i]);
557 usb_free_urb(portdata->out_urbs[i]);
558 kfree(portdata->out_buffer[i]);
0d456194 559 }
0d456194 560
a1028f0a
BM
561 /* Now free port private data */
562 kfree(portdata);
563 return 0;
0d456194 564}
a1028f0a 565EXPORT_SYMBOL(usb_wwan_port_remove);
0d456194 566
a1028f0a
BM
567#ifdef CONFIG_PM
568static void stop_read_write_urbs(struct usb_serial *serial)
0d456194
MG
569{
570 int i, j;
571 struct usb_serial_port *port;
572 struct usb_wwan_port_private *portdata;
573
a1028f0a 574 /* Stop reading/writing urbs */
0d456194
MG
575 for (i = 0; i < serial->num_ports; ++i) {
576 port = serial->port[i];
577 portdata = usb_get_serial_port_data(port);
032129cb
BM
578 if (!portdata)
579 continue;
a1028f0a
BM
580 for (j = 0; j < N_IN_URB; j++)
581 usb_kill_urb(portdata->in_urbs[j]);
582 for (j = 0; j < N_OUT_URB; j++)
583 usb_kill_urb(portdata->out_urbs[j]);
0d456194
MG
584 }
585}
0d456194 586
0d456194
MG
587int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
588{
589 struct usb_wwan_intf_private *intfdata = serial->private;
0d456194 590
170fad9e 591 spin_lock_irq(&intfdata->susp_lock);
5b1b0b81 592 if (PMSG_IS_AUTO(message)) {
170fad9e
JH
593 if (intfdata->in_flight) {
594 spin_unlock_irq(&intfdata->susp_lock);
0d456194 595 return -EBUSY;
170fad9e 596 }
0d456194 597 }
0d456194
MG
598 intfdata->suspended = 1;
599 spin_unlock_irq(&intfdata->susp_lock);
170fad9e 600
0d456194
MG
601 stop_read_write_urbs(serial);
602
603 return 0;
604}
605EXPORT_SYMBOL(usb_wwan_suspend);
606
fb7ad4f9 607static int play_delayed(struct usb_serial_port *port)
0d456194 608{
7436f412 609 struct usb_serial *serial = port->serial;
0d456194
MG
610 struct usb_wwan_intf_private *data;
611 struct usb_wwan_port_private *portdata;
612 struct urb *urb;
7436f412
JH
613 int err_count = 0;
614 int err;
0d456194
MG
615
616 portdata = usb_get_serial_port_data(port);
617 data = port->serial->private;
618 while ((urb = usb_get_from_anchor(&portdata->delayed))) {
619 err = usb_submit_urb(urb, GFP_ATOMIC);
7436f412
JH
620 if (err) {
621 dev_err(&port->dev,
622 "%s: submit write urb failed: %d\n",
623 __func__, err);
624 err_count++;
625 unbusy_queued_urb(urb, portdata);
626 usb_autopm_put_interface_async(serial->interface);
627 continue;
16871dca 628 }
7436f412 629 data->in_flight++;
0d456194 630 }
fb7ad4f9 631
7436f412
JH
632 if (err_count)
633 return -EIO;
634
635 return 0;
0d456194
MG
636}
637
638int usb_wwan_resume(struct usb_serial *serial)
639{
640 int i, j;
641 struct usb_serial_port *port;
642 struct usb_wwan_intf_private *intfdata = serial->private;
643 struct usb_wwan_port_private *portdata;
644 struct urb *urb;
fb7ad4f9
JH
645 int err;
646 int err_count = 0;
0d456194 647
d9e93c08 648 spin_lock_irq(&intfdata->susp_lock);
0d456194
MG
649 for (i = 0; i < serial->num_ports; i++) {
650 /* walk all ports */
651 port = serial->port[i];
652 portdata = usb_get_serial_port_data(port);
653
654 /* skip closed ports */
d9e93c08 655 if (!portdata || !portdata->opened)
0d456194 656 continue;
0d456194 657
9096f1fb
JH
658 if (port->interrupt_in_urb) {
659 err = usb_submit_urb(port->interrupt_in_urb,
660 GFP_ATOMIC);
661 if (err) {
662 dev_err(&port->dev,
663 "%s: submit int urb failed: %d\n",
664 __func__, err);
fb7ad4f9 665 err_count++;
9096f1fb
JH
666 }
667 }
668
fb7ad4f9
JH
669 err = play_delayed(port);
670 if (err)
671 err_count++;
672
0d456194
MG
673 for (j = 0; j < N_IN_URB; j++) {
674 urb = portdata->in_urbs[j];
675 err = usb_submit_urb(urb, GFP_ATOMIC);
676 if (err < 0) {
3a1c2a82
GKH
677 dev_err(&port->dev, "%s: Error %d for bulk URB %d\n",
678 __func__, err, i);
fb7ad4f9 679 err_count++;
0d456194
MG
680 }
681 }
0d456194 682 }
0d456194
MG
683 intfdata->suspended = 0;
684 spin_unlock_irq(&intfdata->susp_lock);
fb7ad4f9
JH
685
686 if (err_count)
687 return -EIO;
688
689 return 0;
0d456194
MG
690}
691EXPORT_SYMBOL(usb_wwan_resume);
692#endif
693
694MODULE_AUTHOR(DRIVER_AUTHOR);
695MODULE_DESCRIPTION(DRIVER_DESC);
0d456194 696MODULE_LICENSE("GPL");