aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb_wwan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/usb_wwan.c')
-rw-r--r--drivers/usb/serial/usb_wwan.c124
1 files changed, 50 insertions, 74 deletions
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index e42aa398ed3..61a73ad1a18 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port)
447EXPORT_SYMBOL(usb_wwan_close); 447EXPORT_SYMBOL(usb_wwan_close);
448 448
449/* Helper functions used by usb_wwan_setup_urbs */ 449/* Helper functions used by usb_wwan_setup_urbs */
450static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, 450static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
451 int endpoint,
451 int dir, void *ctx, char *buf, int len, 452 int dir, void *ctx, char *buf, int len,
452 void (*callback) (struct urb *)) 453 void (*callback) (struct urb *))
453{ 454{
455 struct usb_serial *serial = port->serial;
454 struct urb *urb; 456 struct urb *urb;
455 457
456 if (endpoint == -1) 458 if (endpoint == -1)
@@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
472 return urb; 474 return urb;
473} 475}
474 476
475/* Setup urbs */ 477int usb_wwan_port_probe(struct usb_serial_port *port)
476static void usb_wwan_setup_urbs(struct usb_serial *serial)
477{ 478{
478 int i, j;
479 struct usb_serial_port *port;
480 struct usb_wwan_port_private *portdata; 479 struct usb_wwan_port_private *portdata;
480 struct urb *urb;
481 u8 *buffer;
482 int err;
483 int i;
481 484
482 for (i = 0; i < serial->num_ports; i++) { 485 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
483 port = serial->port[i]; 486 if (!portdata)
484 portdata = usb_get_serial_port_data(port); 487 return -ENOMEM;
485 488
486 /* Do indat endpoints first */ 489 init_usb_anchor(&portdata->delayed);
487 for (j = 0; j < N_IN_URB; ++j) {
488 portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
489 port->
490 bulk_in_endpointAddress,
491 USB_DIR_IN,
492 port,
493 portdata->
494 in_buffer[j],
495 IN_BUFLEN,
496 usb_wwan_indat_callback);
497 }
498 490
499 /* outdat endpoints */ 491 for (i = 0; i < N_IN_URB; i++) {
500 for (j = 0; j < N_OUT_URB; ++j) { 492 buffer = (u8 *)__get_free_page(GFP_KERNEL);
501 portdata->out_urbs[j] = usb_wwan_setup_urb(serial, 493 if (!buffer)
502 port-> 494 goto bail_out_error;
503 bulk_out_endpointAddress, 495 portdata->in_buffer[i] = buffer;
504 USB_DIR_OUT, 496
505 port, 497 urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
506 portdata-> 498 USB_DIR_IN, port,
507 out_buffer 499 buffer, IN_BUFLEN,
508 [j], 500 usb_wwan_indat_callback);
509 OUT_BUFLEN, 501 portdata->in_urbs[i] = urb;
510 usb_wwan_outdat_callback);
511 }
512 } 502 }
513}
514
515int usb_wwan_startup(struct usb_serial *serial)
516{
517 int i, j, err;
518 struct usb_serial_port *port;
519 struct usb_wwan_port_private *portdata;
520 u8 *buffer;
521 503
522 /* Now setup per port private data */ 504 for (i = 0; i < N_OUT_URB; i++) {
523 for (i = 0; i < serial->num_ports; i++) { 505 if (port->bulk_out_endpointAddress == -1)
524 port = serial->port[i]; 506 continue;
525 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
526 if (!portdata) {
527 dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
528 __func__, i);
529 return 1;
530 }
531 init_usb_anchor(&portdata->delayed);
532 507
533 for (j = 0; j < N_IN_URB; j++) { 508 buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
534 buffer = (u8 *) __get_free_page(GFP_KERNEL); 509 if (!buffer)
535 if (!buffer) 510 goto bail_out_error2;
536 goto bail_out_error; 511 portdata->out_buffer[i] = buffer;
537 portdata->in_buffer[j] = buffer;
538 }
539 512
540 for (j = 0; j < N_OUT_URB; j++) { 513 urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
541 buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); 514 USB_DIR_OUT, port,
542 if (!buffer) 515 buffer, OUT_BUFLEN,
543 goto bail_out_error2; 516 usb_wwan_outdat_callback);
544 portdata->out_buffer[j] = buffer; 517 portdata->out_urbs[i] = urb;
545 } 518 }
546 519
547 usb_set_serial_port_data(port, portdata); 520 usb_set_serial_port_data(port, portdata);
548 521
549 if (!port->interrupt_in_urb) 522 if (port->interrupt_in_urb) {
550 continue;
551 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 523 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
552 if (err) 524 if (err)
553 dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", 525 dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
554 __func__, err); 526 __func__, err);
555 } 527 }
556 usb_wwan_setup_urbs(serial); 528
557 return 0; 529 return 0;
558 530
559bail_out_error2: 531bail_out_error2:
560 for (j = 0; j < N_OUT_URB; j++) 532 for (i = 0; i < N_OUT_URB; i++) {
561 kfree(portdata->out_buffer[j]); 533 usb_free_urb(portdata->out_urbs[i]);
534 kfree(portdata->out_buffer[i]);
535 }
562bail_out_error: 536bail_out_error:
563 for (j = 0; j < N_IN_URB; j++) 537 for (i = 0; i < N_IN_URB; i++) {
564 if (portdata->in_buffer[j]) 538 usb_free_urb(portdata->in_urbs[i]);
565 free_page((unsigned long)portdata->in_buffer[j]); 539 free_page((unsigned long)portdata->in_buffer[i]);
540 }
566 kfree(portdata); 541 kfree(portdata);
567 return 1; 542
543 return -ENOMEM;
568} 544}
569EXPORT_SYMBOL(usb_wwan_startup); 545EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
570 546
571int usb_wwan_port_remove(struct usb_serial_port *port) 547int usb_wwan_port_remove(struct usb_serial_port *port)
572{ 548{