diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
commit | bc47ab0241c7c86da4f5e5f82fbca7d45387c18d (patch) | |
tree | b9c33ae8b6de43e44cc5fcbaa3e4a15f18a5ed42 /drivers/usb/serial/sierra.c | |
parent | 37f9ef553bed630957e025504cdcbc76f5de49d5 (diff) | |
parent | 8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff) |
Merge commit 'origin/master' into next
Manual merge of:
arch/powerpc/kernel/asm-offsets.c
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r-- | drivers/usb/serial/sierra.c | 351 |
1 files changed, 228 insertions, 123 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 913225c61610..17ac34f4d668 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -26,12 +26,10 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
28 | #include <linux/usb/serial.h> | 28 | #include <linux/usb/serial.h> |
29 | #include <linux/usb/ch9.h> | ||
30 | 29 | ||
31 | #define SWIMS_USB_REQUEST_SetPower 0x00 | 30 | #define SWIMS_USB_REQUEST_SetPower 0x00 |
32 | #define SWIMS_USB_REQUEST_SetNmea 0x07 | 31 | #define SWIMS_USB_REQUEST_SetNmea 0x07 |
33 | 32 | ||
34 | /* per port private data */ | ||
35 | #define N_IN_URB 4 | 33 | #define N_IN_URB 4 |
36 | #define N_OUT_URB 4 | 34 | #define N_OUT_URB 4 |
37 | #define IN_BUFLEN 4096 | 35 | #define IN_BUFLEN 4096 |
@@ -39,6 +37,12 @@ | |||
39 | static int debug; | 37 | static int debug; |
40 | static int nmea; | 38 | static int nmea; |
41 | 39 | ||
40 | /* Used in interface blacklisting */ | ||
41 | struct sierra_iface_info { | ||
42 | const u32 infolen; /* number of interface numbers on blacklist */ | ||
43 | const u8 *ifaceinfo; /* pointer to the array holding the numbers */ | ||
44 | }; | ||
45 | |||
42 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | 46 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) |
43 | { | 47 | { |
44 | int result; | 48 | int result; |
@@ -85,6 +89,23 @@ static int sierra_calc_num_ports(struct usb_serial *serial) | |||
85 | return result; | 89 | return result; |
86 | } | 90 | } |
87 | 91 | ||
92 | static int is_blacklisted(const u8 ifnum, | ||
93 | const struct sierra_iface_info *blacklist) | ||
94 | { | ||
95 | const u8 *info; | ||
96 | int i; | ||
97 | |||
98 | if (blacklist) { | ||
99 | info = blacklist->ifaceinfo; | ||
100 | |||
101 | for (i = 0; i < blacklist->infolen; i++) { | ||
102 | if (info[i] == ifnum) | ||
103 | return 1; | ||
104 | } | ||
105 | } | ||
106 | return 0; | ||
107 | } | ||
108 | |||
88 | static int sierra_calc_interface(struct usb_serial *serial) | 109 | static int sierra_calc_interface(struct usb_serial *serial) |
89 | { | 110 | { |
90 | int interface; | 111 | int interface; |
@@ -153,9 +174,25 @@ static int sierra_probe(struct usb_serial *serial, | |||
153 | */ | 174 | */ |
154 | usb_set_serial_data(serial, (void *)num_ports); | 175 | usb_set_serial_data(serial, (void *)num_ports); |
155 | 176 | ||
177 | /* ifnum could have changed - by calling usb_set_interface */ | ||
178 | ifnum = sierra_calc_interface(serial); | ||
179 | |||
180 | if (is_blacklisted(ifnum, | ||
181 | (struct sierra_iface_info *)id->driver_info)) { | ||
182 | dev_dbg(&serial->dev->dev, | ||
183 | "Ignoring blacklisted interface #%d\n", ifnum); | ||
184 | return -ENODEV; | ||
185 | } | ||
186 | |||
156 | return result; | 187 | return result; |
157 | } | 188 | } |
158 | 189 | ||
190 | static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; | ||
191 | static const struct sierra_iface_info direct_ip_interface_blacklist = { | ||
192 | .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), | ||
193 | .ifaceinfo = direct_ip_non_serial_ifaces, | ||
194 | }; | ||
195 | |||
159 | static struct usb_device_id id_table [] = { | 196 | static struct usb_device_id id_table [] = { |
160 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 197 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
161 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | 198 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ |
@@ -188,9 +225,11 @@ static struct usb_device_id id_table [] = { | |||
188 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ | 225 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ |
189 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ | 226 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ |
190 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ | 227 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ |
191 | { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */ | 228 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ |
192 | { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */ | 229 | { USB_DEVICE(0x1199, 0x683C) }, |
193 | { USB_DEVICE(0x1199, 0x683E) }, /* Sierra Wireless MC8790 */ | 230 | { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8791 Composite */ |
231 | /* Sierra Wireless MC8790, MC8791, MC8792 */ | ||
232 | { USB_DEVICE(0x1199, 0x683E) }, | ||
194 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ | 233 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ |
195 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ | 234 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ |
196 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ | 235 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ |
@@ -211,6 +250,10 @@ static struct usb_device_id id_table [] = { | |||
211 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | 250 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ |
212 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | 251 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ |
213 | 252 | ||
253 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ | ||
254 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | ||
255 | }, | ||
256 | |||
214 | { } | 257 | { } |
215 | }; | 258 | }; |
216 | MODULE_DEVICE_TABLE(usb, id_table); | 259 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -229,7 +272,6 @@ struct sierra_port_private { | |||
229 | 272 | ||
230 | /* Input endpoints and buffers for this port */ | 273 | /* Input endpoints and buffers for this port */ |
231 | struct urb *in_urbs[N_IN_URB]; | 274 | struct urb *in_urbs[N_IN_URB]; |
232 | char *in_buffer[N_IN_URB]; | ||
233 | 275 | ||
234 | /* Settings for the port */ | 276 | /* Settings for the port */ |
235 | int rts_state; /* Handshaking pins (outputs) */ | 277 | int rts_state; /* Handshaking pins (outputs) */ |
@@ -240,57 +282,50 @@ struct sierra_port_private { | |||
240 | int ri_state; | 282 | int ri_state; |
241 | }; | 283 | }; |
242 | 284 | ||
243 | static int sierra_send_setup(struct tty_struct *tty, | 285 | static int sierra_send_setup(struct usb_serial_port *port) |
244 | struct usb_serial_port *port) | ||
245 | { | 286 | { |
246 | struct usb_serial *serial = port->serial; | 287 | struct usb_serial *serial = port->serial; |
247 | struct sierra_port_private *portdata; | 288 | struct sierra_port_private *portdata; |
248 | __u16 interface = 0; | 289 | __u16 interface = 0; |
290 | int val = 0; | ||
249 | 291 | ||
250 | dev_dbg(&port->dev, "%s", __func__); | 292 | dev_dbg(&port->dev, "%s", __func__); |
251 | 293 | ||
252 | portdata = usb_get_serial_port_data(port); | 294 | portdata = usb_get_serial_port_data(port); |
253 | 295 | ||
254 | if (tty) { | 296 | if (portdata->dtr_state) |
255 | int val = 0; | 297 | val |= 0x01; |
256 | if (portdata->dtr_state) | 298 | if (portdata->rts_state) |
257 | val |= 0x01; | 299 | val |= 0x02; |
258 | if (portdata->rts_state) | ||
259 | val |= 0x02; | ||
260 | |||
261 | /* If composite device then properly report interface */ | ||
262 | if (serial->num_ports == 1) { | ||
263 | interface = sierra_calc_interface(serial); | ||
264 | |||
265 | /* Control message is sent only to interfaces with | ||
266 | * interrupt_in endpoints | ||
267 | */ | ||
268 | if (port->interrupt_in_urb) { | ||
269 | /* send control message */ | ||
270 | return usb_control_msg(serial->dev, | ||
271 | usb_rcvctrlpipe(serial->dev, 0), | ||
272 | 0x22, 0x21, val, interface, | ||
273 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | /* Otherwise the need to do non-composite mapping */ | ||
278 | else { | ||
279 | if (port->bulk_out_endpointAddress == 2) | ||
280 | interface = 0; | ||
281 | else if (port->bulk_out_endpointAddress == 4) | ||
282 | interface = 1; | ||
283 | else if (port->bulk_out_endpointAddress == 5) | ||
284 | interface = 2; | ||
285 | 300 | ||
301 | /* If composite device then properly report interface */ | ||
302 | if (serial->num_ports == 1) { | ||
303 | interface = sierra_calc_interface(serial); | ||
304 | /* Control message is sent only to interfaces with | ||
305 | * interrupt_in endpoints | ||
306 | */ | ||
307 | if (port->interrupt_in_urb) { | ||
308 | /* send control message */ | ||
286 | return usb_control_msg(serial->dev, | 309 | return usb_control_msg(serial->dev, |
287 | usb_rcvctrlpipe(serial->dev, 0), | 310 | usb_rcvctrlpipe(serial->dev, 0), |
288 | 0x22, 0x21, val, interface, | 311 | 0x22, 0x21, val, interface, |
289 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 312 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
290 | |||
291 | } | 313 | } |
292 | } | 314 | } |
293 | 315 | ||
316 | /* Otherwise the need to do non-composite mapping */ | ||
317 | else { | ||
318 | if (port->bulk_out_endpointAddress == 2) | ||
319 | interface = 0; | ||
320 | else if (port->bulk_out_endpointAddress == 4) | ||
321 | interface = 1; | ||
322 | else if (port->bulk_out_endpointAddress == 5) | ||
323 | interface = 2; | ||
324 | return usb_control_msg(serial->dev, | ||
325 | usb_rcvctrlpipe(serial->dev, 0), | ||
326 | 0x22, 0x21, val, interface, | ||
327 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
328 | } | ||
294 | return 0; | 329 | return 0; |
295 | } | 330 | } |
296 | 331 | ||
@@ -299,7 +334,7 @@ static void sierra_set_termios(struct tty_struct *tty, | |||
299 | { | 334 | { |
300 | dev_dbg(&port->dev, "%s", __func__); | 335 | dev_dbg(&port->dev, "%s", __func__); |
301 | tty_termios_copy_hw(tty->termios, old_termios); | 336 | tty_termios_copy_hw(tty->termios, old_termios); |
302 | sierra_send_setup(tty, port); | 337 | sierra_send_setup(port); |
303 | } | 338 | } |
304 | 339 | ||
305 | static int sierra_tiocmget(struct tty_struct *tty, struct file *file) | 340 | static int sierra_tiocmget(struct tty_struct *tty, struct file *file) |
@@ -338,7 +373,18 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file, | |||
338 | portdata->rts_state = 0; | 373 | portdata->rts_state = 0; |
339 | if (clear & TIOCM_DTR) | 374 | if (clear & TIOCM_DTR) |
340 | portdata->dtr_state = 0; | 375 | portdata->dtr_state = 0; |
341 | return sierra_send_setup(tty, port); | 376 | return sierra_send_setup(port); |
377 | } | ||
378 | |||
379 | static void sierra_release_urb(struct urb *urb) | ||
380 | { | ||
381 | struct usb_serial_port *port; | ||
382 | if (urb) { | ||
383 | port = urb->context; | ||
384 | dev_dbg(&port->dev, "%s: %p\n", __func__, urb); | ||
385 | kfree(urb->transfer_buffer); | ||
386 | usb_free_urb(urb); | ||
387 | } | ||
342 | } | 388 | } |
343 | 389 | ||
344 | static void sierra_outdat_callback(struct urb *urb) | 390 | static void sierra_outdat_callback(struct urb *urb) |
@@ -465,7 +511,7 @@ static void sierra_indat_callback(struct urb *urb) | |||
465 | " received", __func__); | 511 | " received", __func__); |
466 | 512 | ||
467 | /* Resubmit urb so we continue receiving */ | 513 | /* Resubmit urb so we continue receiving */ |
468 | if (port->port.count && status != -ESHUTDOWN) { | 514 | if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { |
469 | err = usb_submit_urb(urb, GFP_ATOMIC); | 515 | err = usb_submit_urb(urb, GFP_ATOMIC); |
470 | if (err) | 516 | if (err) |
471 | dev_err(&port->dev, "resubmit read urb failed." | 517 | dev_err(&port->dev, "resubmit read urb failed." |
@@ -557,67 +603,99 @@ static int sierra_write_room(struct tty_struct *tty) | |||
557 | return 2048; | 603 | return 2048; |
558 | } | 604 | } |
559 | 605 | ||
560 | static int sierra_open(struct tty_struct *tty, | 606 | static void sierra_stop_rx_urbs(struct usb_serial_port *port) |
561 | struct usb_serial_port *port, struct file *filp) | ||
562 | { | 607 | { |
563 | struct sierra_port_private *portdata; | ||
564 | struct usb_serial *serial = port->serial; | ||
565 | int i; | 608 | int i; |
566 | struct urb *urb; | 609 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
567 | int result; | ||
568 | 610 | ||
569 | portdata = usb_get_serial_port_data(port); | 611 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) |
612 | usb_kill_urb(portdata->in_urbs[i]); | ||
570 | 613 | ||
571 | dev_dbg(&port->dev, "%s", __func__); | 614 | usb_kill_urb(port->interrupt_in_urb); |
615 | } | ||
572 | 616 | ||
573 | /* Set some sane defaults */ | 617 | static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags) |
574 | portdata->rts_state = 1; | 618 | { |
575 | portdata->dtr_state = 1; | 619 | int ok_cnt; |
620 | int err = -EINVAL; | ||
621 | int i; | ||
622 | struct urb *urb; | ||
623 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | ||
576 | 624 | ||
577 | /* Reset low level data toggle and start reading from endpoints */ | 625 | ok_cnt = 0; |
578 | for (i = 0; i < N_IN_URB; i++) { | 626 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { |
579 | urb = portdata->in_urbs[i]; | 627 | urb = portdata->in_urbs[i]; |
580 | if (!urb) | 628 | if (!urb) |
581 | continue; | 629 | continue; |
582 | if (urb->dev != serial->dev) { | 630 | err = usb_submit_urb(urb, mem_flags); |
583 | dev_dbg(&port->dev, "%s: dev %p != %p", | 631 | if (err) { |
584 | __func__, urb->dev, serial->dev); | 632 | dev_err(&port->dev, "%s: submit urb failed: %d\n", |
585 | continue; | 633 | __func__, err); |
634 | } else { | ||
635 | ok_cnt++; | ||
586 | } | 636 | } |
637 | } | ||
587 | 638 | ||
588 | /* | 639 | if (ok_cnt && port->interrupt_in_urb) { |
589 | * make sure endpoint data toggle is synchronized with the | 640 | err = usb_submit_urb(port->interrupt_in_urb, mem_flags); |
590 | * device | 641 | if (err) { |
591 | */ | 642 | dev_err(&port->dev, "%s: submit intr urb failed: %d\n", |
592 | usb_clear_halt(urb->dev, urb->pipe); | 643 | __func__, err); |
593 | |||
594 | result = usb_submit_urb(urb, GFP_KERNEL); | ||
595 | if (result) { | ||
596 | dev_err(&port->dev, "submit urb %d failed (%d) %d\n", | ||
597 | i, result, urb->transfer_buffer_length); | ||
598 | } | 644 | } |
599 | } | 645 | } |
600 | 646 | ||
601 | sierra_send_setup(tty, port); | 647 | if (ok_cnt > 0) /* at least one rx urb submitted */ |
648 | return 0; | ||
649 | else | ||
650 | return err; | ||
651 | } | ||
652 | |||
653 | static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, | ||
654 | int dir, void *ctx, int len, | ||
655 | gfp_t mem_flags, | ||
656 | usb_complete_t callback) | ||
657 | { | ||
658 | struct urb *urb; | ||
659 | u8 *buf; | ||
660 | |||
661 | if (endpoint == -1) | ||
662 | return NULL; | ||
602 | 663 | ||
603 | /* start up the interrupt endpoint if we have one */ | 664 | urb = usb_alloc_urb(0, mem_flags); |
604 | if (port->interrupt_in_urb) { | 665 | if (urb == NULL) { |
605 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 666 | dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n", |
606 | if (result) | 667 | __func__, endpoint); |
607 | dev_err(&port->dev, "submit irq_in urb failed %d\n", | 668 | return NULL; |
608 | result); | ||
609 | } | 669 | } |
610 | return 0; | 670 | |
671 | buf = kmalloc(len, mem_flags); | ||
672 | if (buf) { | ||
673 | /* Fill URB using supplied data */ | ||
674 | usb_fill_bulk_urb(urb, serial->dev, | ||
675 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
676 | buf, len, callback, ctx); | ||
677 | |||
678 | /* debug */ | ||
679 | dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__, | ||
680 | dir == USB_DIR_IN ? 'i' : 'o', urb, buf); | ||
681 | } else { | ||
682 | dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__, | ||
683 | dir == USB_DIR_IN ? 'i' : 'o', urb, buf); | ||
684 | |||
685 | sierra_release_urb(urb); | ||
686 | urb = NULL; | ||
687 | } | ||
688 | |||
689 | return urb; | ||
611 | } | 690 | } |
612 | 691 | ||
613 | static void sierra_close(struct tty_struct *tty, | 692 | static void sierra_close(struct usb_serial_port *port) |
614 | struct usb_serial_port *port, struct file *filp) | ||
615 | { | 693 | { |
616 | int i; | 694 | int i; |
617 | struct usb_serial *serial = port->serial; | 695 | struct usb_serial *serial = port->serial; |
618 | struct sierra_port_private *portdata; | 696 | struct sierra_port_private *portdata; |
619 | 697 | ||
620 | dev_dbg(&port->dev, "%s", __func__); | 698 | dev_dbg(&port->dev, "%s\n", __func__); |
621 | portdata = usb_get_serial_port_data(port); | 699 | portdata = usb_get_serial_port_data(port); |
622 | 700 | ||
623 | portdata->rts_state = 0; | 701 | portdata->rts_state = 0; |
@@ -626,25 +704,83 @@ static void sierra_close(struct tty_struct *tty, | |||
626 | if (serial->dev) { | 704 | if (serial->dev) { |
627 | mutex_lock(&serial->disc_mutex); | 705 | mutex_lock(&serial->disc_mutex); |
628 | if (!serial->disconnected) | 706 | if (!serial->disconnected) |
629 | sierra_send_setup(tty, port); | 707 | sierra_send_setup(port); |
630 | mutex_unlock(&serial->disc_mutex); | 708 | mutex_unlock(&serial->disc_mutex); |
631 | 709 | ||
632 | /* Stop reading/writing urbs */ | 710 | /* Stop reading urbs */ |
633 | for (i = 0; i < N_IN_URB; i++) | 711 | sierra_stop_rx_urbs(port); |
634 | usb_kill_urb(portdata->in_urbs[i]); | 712 | /* .. and release them */ |
713 | for (i = 0; i < N_IN_URB; i++) { | ||
714 | sierra_release_urb(portdata->in_urbs[i]); | ||
715 | portdata->in_urbs[i] = NULL; | ||
716 | } | ||
635 | } | 717 | } |
718 | } | ||
636 | 719 | ||
637 | usb_kill_urb(port->interrupt_in_urb); | 720 | static int sierra_open(struct tty_struct *tty, |
638 | tty_port_tty_set(&port->port, NULL); | 721 | struct usb_serial_port *port, struct file *filp) |
722 | { | ||
723 | struct sierra_port_private *portdata; | ||
724 | struct usb_serial *serial = port->serial; | ||
725 | int i; | ||
726 | int err; | ||
727 | int endpoint; | ||
728 | struct urb *urb; | ||
729 | |||
730 | portdata = usb_get_serial_port_data(port); | ||
731 | |||
732 | dev_dbg(&port->dev, "%s", __func__); | ||
733 | |||
734 | /* Set some sane defaults */ | ||
735 | portdata->rts_state = 1; | ||
736 | portdata->dtr_state = 1; | ||
737 | |||
738 | |||
739 | endpoint = port->bulk_in_endpointAddress; | ||
740 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { | ||
741 | urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, | ||
742 | IN_BUFLEN, GFP_KERNEL, | ||
743 | sierra_indat_callback); | ||
744 | portdata->in_urbs[i] = urb; | ||
745 | } | ||
746 | /* clear halt condition */ | ||
747 | usb_clear_halt(serial->dev, | ||
748 | usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN); | ||
749 | |||
750 | err = sierra_submit_rx_urbs(port, GFP_KERNEL); | ||
751 | if (err) { | ||
752 | /* get rid of everything as in close */ | ||
753 | sierra_close(port); | ||
754 | return err; | ||
755 | } | ||
756 | sierra_send_setup(port); | ||
757 | |||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | |||
762 | static void sierra_dtr_rts(struct usb_serial_port *port, int on) | ||
763 | { | ||
764 | struct usb_serial *serial = port->serial; | ||
765 | struct sierra_port_private *portdata; | ||
766 | |||
767 | portdata = usb_get_serial_port_data(port); | ||
768 | portdata->rts_state = on; | ||
769 | portdata->dtr_state = on; | ||
770 | |||
771 | if (serial->dev) { | ||
772 | mutex_lock(&serial->disc_mutex); | ||
773 | if (!serial->disconnected) | ||
774 | sierra_send_setup(port); | ||
775 | mutex_unlock(&serial->disc_mutex); | ||
776 | } | ||
639 | } | 777 | } |
640 | 778 | ||
641 | static int sierra_startup(struct usb_serial *serial) | 779 | static int sierra_startup(struct usb_serial *serial) |
642 | { | 780 | { |
643 | struct usb_serial_port *port; | 781 | struct usb_serial_port *port; |
644 | struct sierra_port_private *portdata; | 782 | struct sierra_port_private *portdata; |
645 | struct urb *urb; | ||
646 | int i; | 783 | int i; |
647 | int j; | ||
648 | 784 | ||
649 | dev_dbg(&serial->dev->dev, "%s", __func__); | 785 | dev_dbg(&serial->dev->dev, "%s", __func__); |
650 | 786 | ||
@@ -666,34 +802,8 @@ static int sierra_startup(struct usb_serial *serial) | |||
666 | return -ENOMEM; | 802 | return -ENOMEM; |
667 | } | 803 | } |
668 | spin_lock_init(&portdata->lock); | 804 | spin_lock_init(&portdata->lock); |
669 | for (j = 0; j < N_IN_URB; j++) { | 805 | /* Set the port private data pointer */ |
670 | portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); | ||
671 | if (!portdata->in_buffer[j]) { | ||
672 | for (--j; j >= 0; j--) | ||
673 | kfree(portdata->in_buffer[j]); | ||
674 | kfree(portdata); | ||
675 | return -ENOMEM; | ||
676 | } | ||
677 | } | ||
678 | |||
679 | usb_set_serial_port_data(port, portdata); | 806 | usb_set_serial_port_data(port, portdata); |
680 | |||
681 | /* initialize the in urbs */ | ||
682 | for (j = 0; j < N_IN_URB; ++j) { | ||
683 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
684 | if (urb == NULL) { | ||
685 | dev_dbg(&port->dev, "%s: alloc for in " | ||
686 | "port failed.", __func__); | ||
687 | continue; | ||
688 | } | ||
689 | /* Fill URB using supplied data. */ | ||
690 | usb_fill_bulk_urb(urb, serial->dev, | ||
691 | usb_rcvbulkpipe(serial->dev, | ||
692 | port->bulk_in_endpointAddress), | ||
693 | portdata->in_buffer[j], IN_BUFLEN, | ||
694 | sierra_indat_callback, port); | ||
695 | portdata->in_urbs[j] = urb; | ||
696 | } | ||
697 | } | 807 | } |
698 | 808 | ||
699 | return 0; | 809 | return 0; |
@@ -701,7 +811,7 @@ static int sierra_startup(struct usb_serial *serial) | |||
701 | 811 | ||
702 | static void sierra_shutdown(struct usb_serial *serial) | 812 | static void sierra_shutdown(struct usb_serial *serial) |
703 | { | 813 | { |
704 | int i, j; | 814 | int i; |
705 | struct usb_serial_port *port; | 815 | struct usb_serial_port *port; |
706 | struct sierra_port_private *portdata; | 816 | struct sierra_port_private *portdata; |
707 | 817 | ||
@@ -714,12 +824,6 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
714 | portdata = usb_get_serial_port_data(port); | 824 | portdata = usb_get_serial_port_data(port); |
715 | if (!portdata) | 825 | if (!portdata) |
716 | continue; | 826 | continue; |
717 | |||
718 | for (j = 0; j < N_IN_URB; j++) { | ||
719 | usb_kill_urb(portdata->in_urbs[j]); | ||
720 | usb_free_urb(portdata->in_urbs[j]); | ||
721 | kfree(portdata->in_buffer[j]); | ||
722 | } | ||
723 | kfree(portdata); | 827 | kfree(portdata); |
724 | usb_set_serial_port_data(port, NULL); | 828 | usb_set_serial_port_data(port, NULL); |
725 | } | 829 | } |
@@ -737,6 +841,7 @@ static struct usb_serial_driver sierra_device = { | |||
737 | .probe = sierra_probe, | 841 | .probe = sierra_probe, |
738 | .open = sierra_open, | 842 | .open = sierra_open, |
739 | .close = sierra_close, | 843 | .close = sierra_close, |
844 | .dtr_rts = sierra_dtr_rts, | ||
740 | .write = sierra_write, | 845 | .write = sierra_write, |
741 | .write_room = sierra_write_room, | 846 | .write_room = sierra_write_room, |
742 | .set_termios = sierra_set_termios, | 847 | .set_termios = sierra_set_termios, |