diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 597 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 3 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 3 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 7 | ||||
-rw-r--r-- | drivers/isdn/gigaset/i4l.c | 2 | ||||
-rw-r--r-- | drivers/isdn/gigaset/isocdata.c | 10 |
6 files changed, 342 insertions, 280 deletions
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index f86ed6af3aa2..eb41aba3ddef 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Tilman Schmidt <tilman@imap.cc>, | 5 | * Tilman Schmidt <tilman@imap.cc>, |
6 | * Stefan Eilers. | 6 | * Stefan Eilers. |
7 | * | 7 | * |
8 | * Based on usb-gigaset.c. | ||
9 | * | ||
10 | * ===================================================================== | 8 | * ===================================================================== |
11 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License as | 10 | * modify it under the terms of the GNU General Public License as |
@@ -46,19 +44,20 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
46 | #define GIGASET_DEVFSNAME "gig/bas/" | 44 | #define GIGASET_DEVFSNAME "gig/bas/" |
47 | #define GIGASET_DEVNAME "ttyGB" | 45 | #define GIGASET_DEVNAME "ttyGB" |
48 | 46 | ||
49 | #define IF_WRITEBUF 256 //FIXME | 47 | /* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ |
48 | #define IF_WRITEBUF 264 | ||
50 | 49 | ||
51 | /* Values for the Gigaset 307x */ | 50 | /* Values for the Gigaset 307x */ |
52 | #define USB_GIGA_VENDOR_ID 0x0681 | 51 | #define USB_GIGA_VENDOR_ID 0x0681 |
53 | #define USB_GIGA_PRODUCT_ID 0x0001 | 52 | #define USB_3070_PRODUCT_ID 0x0001 |
54 | #define USB_4175_PRODUCT_ID 0x0002 | 53 | #define USB_3075_PRODUCT_ID 0x0002 |
55 | #define USB_SX303_PRODUCT_ID 0x0021 | 54 | #define USB_SX303_PRODUCT_ID 0x0021 |
56 | #define USB_SX353_PRODUCT_ID 0x0022 | 55 | #define USB_SX353_PRODUCT_ID 0x0022 |
57 | 56 | ||
58 | /* table of devices that work with this driver */ | 57 | /* table of devices that work with this driver */ |
59 | static struct usb_device_id gigaset_table [] = { | 58 | static struct usb_device_id gigaset_table [] = { |
60 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) }, | 59 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, |
61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) }, | 60 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, |
62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, | 61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, |
63 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, | 62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, |
64 | { } /* Terminating entry */ | 63 | { } /* Terminating entry */ |
@@ -77,6 +76,10 @@ static int gigaset_probe(struct usb_interface *interface, | |||
77 | /* Function will be called if the device is unplugged */ | 76 | /* Function will be called if the device is unplugged */ |
78 | static void gigaset_disconnect(struct usb_interface *interface); | 77 | static void gigaset_disconnect(struct usb_interface *interface); |
79 | 78 | ||
79 | static void read_ctrl_callback(struct urb *, struct pt_regs *); | ||
80 | static void stopurbs(struct bas_bc_state *); | ||
81 | static int atwrite_submit(struct cardstate *, unsigned char *, int); | ||
82 | static int start_cbsend(struct cardstate *); | ||
80 | 83 | ||
81 | /*==============================================================================*/ | 84 | /*==============================================================================*/ |
82 | 85 | ||
@@ -111,12 +114,14 @@ struct bas_cardstate { | |||
111 | }; | 114 | }; |
112 | 115 | ||
113 | /* status of direct USB connection to 307x base (bits in basstate) */ | 116 | /* status of direct USB connection to 307x base (bits in basstate) */ |
114 | #define BS_ATOPEN 0x001 | 117 | #define BS_ATOPEN 0x001 /* AT channel open */ |
115 | #define BS_B1OPEN 0x002 | 118 | #define BS_B1OPEN 0x002 /* B channel 1 open */ |
116 | #define BS_B2OPEN 0x004 | 119 | #define BS_B2OPEN 0x004 /* B channel 2 open */ |
117 | #define BS_ATREADY 0x008 | 120 | #define BS_ATREADY 0x008 /* base ready for AT command */ |
118 | #define BS_INIT 0x010 | 121 | #define BS_INIT 0x010 /* base has signalled INIT_OK */ |
119 | #define BS_ATTIMER 0x020 | 122 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ |
123 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ | ||
124 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ | ||
120 | 125 | ||
121 | 126 | ||
122 | static struct gigaset_driver *driver = NULL; | 127 | static struct gigaset_driver *driver = NULL; |
@@ -130,6 +135,47 @@ static struct usb_driver gigaset_usb_driver = { | |||
130 | .id_table = gigaset_table, | 135 | .id_table = gigaset_table, |
131 | }; | 136 | }; |
132 | 137 | ||
138 | /* get message text for usb_submit_urb return code | ||
139 | */ | ||
140 | static char *get_usb_rcmsg(int rc) | ||
141 | { | ||
142 | static char unkmsg[28]; | ||
143 | |||
144 | switch (rc) { | ||
145 | case 0: | ||
146 | return "success"; | ||
147 | case -ENOMEM: | ||
148 | return "out of memory"; | ||
149 | case -ENODEV: | ||
150 | return "device not present"; | ||
151 | case -ENOENT: | ||
152 | return "endpoint not present"; | ||
153 | case -ENXIO: | ||
154 | return "URB type not supported"; | ||
155 | case -EINVAL: | ||
156 | return "invalid argument"; | ||
157 | case -EAGAIN: | ||
158 | return "start frame too early or too much scheduled"; | ||
159 | case -EFBIG: | ||
160 | return "too many isochronous frames requested"; | ||
161 | case -EPIPE: | ||
162 | return "endpoint stalled"; | ||
163 | case -EMSGSIZE: | ||
164 | return "invalid packet size"; | ||
165 | case -ENOSPC: | ||
166 | return "would overcommit USB bandwidth"; | ||
167 | case -ESHUTDOWN: | ||
168 | return "device shut down"; | ||
169 | case -EPERM: | ||
170 | return "reject flag set"; | ||
171 | case -EHOSTUNREACH: | ||
172 | return "device suspended"; | ||
173 | default: | ||
174 | snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc); | ||
175 | return unkmsg; | ||
176 | } | ||
177 | } | ||
178 | |||
133 | /* get message text for USB status code | 179 | /* get message text for USB status code |
134 | */ | 180 | */ |
135 | static char *get_usb_statmsg(int status) | 181 | static char *get_usb_statmsg(int status) |
@@ -140,43 +186,37 @@ static char *get_usb_statmsg(int status) | |||
140 | case 0: | 186 | case 0: |
141 | return "success"; | 187 | return "success"; |
142 | case -ENOENT: | 188 | case -ENOENT: |
143 | return "canceled"; | 189 | return "unlinked (sync)"; |
144 | case -ECONNRESET: | ||
145 | return "canceled (async)"; | ||
146 | case -EINPROGRESS: | 190 | case -EINPROGRESS: |
147 | return "pending"; | 191 | return "pending"; |
148 | case -EPROTO: | 192 | case -EPROTO: |
149 | return "bit stuffing or unknown USB error"; | 193 | return "bit stuffing error, timeout, or unknown USB error"; |
150 | case -EILSEQ: | 194 | case -EILSEQ: |
151 | return "Illegal byte sequence (CRC mismatch)"; | 195 | return "CRC mismatch, timeout, or unknown USB error"; |
152 | case -EPIPE: | ||
153 | return "babble detect or endpoint stalled"; | ||
154 | case -ENOSR: | ||
155 | return "buffer error"; | ||
156 | case -ETIMEDOUT: | 196 | case -ETIMEDOUT: |
157 | return "timed out"; | 197 | return "timed out"; |
158 | case -ENODEV: | 198 | case -EPIPE: |
159 | return "device not present"; | 199 | return "endpoint stalled"; |
200 | case -ECOMM: | ||
201 | return "IN buffer overrun"; | ||
202 | case -ENOSR: | ||
203 | return "OUT buffer underrun"; | ||
204 | case -EOVERFLOW: | ||
205 | return "too much data"; | ||
160 | case -EREMOTEIO: | 206 | case -EREMOTEIO: |
161 | return "short packet detected"; | 207 | return "short packet detected"; |
208 | case -ENODEV: | ||
209 | return "device removed"; | ||
162 | case -EXDEV: | 210 | case -EXDEV: |
163 | return "partial isochronous transfer"; | 211 | return "partial isochronous transfer"; |
164 | case -EINVAL: | 212 | case -EINVAL: |
165 | return "invalid argument"; | 213 | return "invalid argument"; |
166 | case -ENXIO: | 214 | case -ECONNRESET: |
167 | return "URB already queued"; | 215 | return "unlinked (async)"; |
168 | case -EAGAIN: | ||
169 | return "isochronous start frame too early or too much scheduled"; | ||
170 | case -EFBIG: | ||
171 | return "too many isochronous frames requested"; | ||
172 | case -EMSGSIZE: | ||
173 | return "endpoint message size zero"; | ||
174 | case -ESHUTDOWN: | 216 | case -ESHUTDOWN: |
175 | return "endpoint shutdown"; | 217 | return "device shut down"; |
176 | case -EBUSY: | ||
177 | return "another request pending"; | ||
178 | default: | 218 | default: |
179 | snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status); | 219 | snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); |
180 | return unkmsg; | 220 | return unkmsg; |
181 | } | 221 | } |
182 | } | 222 | } |
@@ -277,18 +317,17 @@ static inline void error_hangup(struct bc_state *bcs) | |||
277 | gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", | 317 | gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", |
278 | __func__, bcs->channel); | 318 | __func__, bcs->channel); |
279 | 319 | ||
280 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { | 320 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) |
281 | //FIXME what should we do? | 321 | dev_err(cs->dev, "event queue full\n"); |
282 | return; | ||
283 | } | ||
284 | 322 | ||
285 | gigaset_schedule_event(cs); | 323 | gigaset_schedule_event(cs); |
286 | } | 324 | } |
287 | 325 | ||
288 | /* error_reset | 326 | /* error_reset |
289 | * reset Gigaset device because of an unrecoverable error | 327 | * reset Gigaset device because of an unrecoverable error |
290 | * This function may be called from any context and takes care of scheduling | 328 | * This function may be called from any context, and should take care of |
291 | * the necessary actions for execution outside of interrupt context. | 329 | * scheduling the necessary actions for execution outside of interrupt context. |
330 | * Right now, it just generates a kernel message calling for help. | ||
292 | * argument: | 331 | * argument: |
293 | * controller state structure | 332 | * controller state structure |
294 | */ | 333 | */ |
@@ -364,36 +403,38 @@ static void cmd_in_timeout(unsigned long data) | |||
364 | { | 403 | { |
365 | struct cardstate *cs = (struct cardstate *) data; | 404 | struct cardstate *cs = (struct cardstate *) data; |
366 | struct bas_cardstate *ucs = cs->hw.bas; | 405 | struct bas_cardstate *ucs = cs->hw.bas; |
367 | unsigned long flags; | ||
368 | 406 | ||
369 | spin_lock_irqsave(&cs->lock, flags); | ||
370 | if (unlikely(!cs->connected)) { | ||
371 | gig_dbg(DEBUG_USBREQ, "%s: disconnected", __func__); | ||
372 | spin_unlock_irqrestore(&cs->lock, flags); | ||
373 | return; | ||
374 | } | ||
375 | if (!ucs->rcvbuf_size) { | 407 | if (!ucs->rcvbuf_size) { |
376 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); | 408 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); |
377 | spin_unlock_irqrestore(&cs->lock, flags); | ||
378 | return; | 409 | return; |
379 | } | 410 | } |
380 | spin_unlock_irqrestore(&cs->lock, flags); | ||
381 | 411 | ||
382 | dev_err(cs->dev, "timeout reading AT response\n"); | 412 | dev_err(cs->dev, "timeout reading AT response\n"); |
383 | error_reset(cs); //FIXME retry? | 413 | error_reset(cs); //FIXME retry? |
384 | } | 414 | } |
385 | 415 | ||
416 | /* set/clear bits in base connection state, return previous state | ||
417 | */ | ||
418 | inline static int update_basstate(struct bas_cardstate *ucs, | ||
419 | int set, int clear) | ||
420 | { | ||
421 | unsigned long flags; | ||
422 | int state; | ||
386 | 423 | ||
387 | static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs); | 424 | spin_lock_irqsave(&ucs->lock, flags); |
425 | state = atomic_read(&ucs->basstate); | ||
426 | atomic_set(&ucs->basstate, (state & ~clear) | set); | ||
427 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
428 | return state; | ||
429 | } | ||
388 | 430 | ||
389 | /* atread_submit | 431 | /* atread_submit |
390 | * submit an HD_READ_ATMESSAGE command URB | 432 | * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout |
391 | * parameters: | 433 | * parameters: |
392 | * cs controller state structure | 434 | * cs controller state structure |
393 | * timeout timeout in 1/10 sec., 0: none | 435 | * timeout timeout in 1/10 sec., 0: none |
394 | * return value: | 436 | * return value: |
395 | * 0 on success | 437 | * 0 on success |
396 | * -EINVAL if a NULL pointer is encountered somewhere | ||
397 | * -EBUSY if another request is pending | 438 | * -EBUSY if another request is pending |
398 | * any URB submission error code | 439 | * any URB submission error code |
399 | */ | 440 | */ |
@@ -405,7 +446,7 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
405 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", | 446 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", |
406 | ucs->rcvbuf_size); | 447 | ucs->rcvbuf_size); |
407 | 448 | ||
408 | if (ucs->urb_cmd_in->status == -EINPROGRESS) { | 449 | if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { |
409 | dev_err(cs->dev, | 450 | dev_err(cs->dev, |
410 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); | 451 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); |
411 | return -EBUSY; | 452 | return -EBUSY; |
@@ -423,6 +464,7 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
423 | read_ctrl_callback, cs->inbuf); | 464 | read_ctrl_callback, cs->inbuf); |
424 | 465 | ||
425 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { | 466 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { |
467 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
426 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", | 468 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", |
427 | get_usb_statmsg(ret)); | 469 | get_usb_statmsg(ret)); |
428 | return ret; | 470 | return ret; |
@@ -438,26 +480,6 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
438 | return 0; | 480 | return 0; |
439 | } | 481 | } |
440 | 482 | ||
441 | static void stopurbs(struct bas_bc_state *); | ||
442 | static int start_cbsend(struct cardstate *); | ||
443 | |||
444 | /* set/clear bits in base connection state | ||
445 | */ | ||
446 | inline static void update_basstate(struct bas_cardstate *ucs, | ||
447 | int set, int clear) | ||
448 | { | ||
449 | unsigned long flags; | ||
450 | int state; | ||
451 | |||
452 | spin_lock_irqsave(&ucs->lock, flags); | ||
453 | state = atomic_read(&ucs->basstate); | ||
454 | state &= ~clear; | ||
455 | state |= set; | ||
456 | atomic_set(&ucs->basstate, state); | ||
457 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
458 | } | ||
459 | |||
460 | |||
461 | /* read_int_callback | 483 | /* read_int_callback |
462 | * USB completion handler for interrupt pipe input | 484 | * USB completion handler for interrupt pipe input |
463 | * called by the USB subsystem in interrupt context | 485 | * called by the USB subsystem in interrupt context |
@@ -471,20 +493,25 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
471 | struct bas_cardstate *ucs = cs->hw.bas; | 493 | struct bas_cardstate *ucs = cs->hw.bas; |
472 | struct bc_state *bcs; | 494 | struct bc_state *bcs; |
473 | unsigned long flags; | 495 | unsigned long flags; |
474 | int status; | 496 | int rc; |
475 | unsigned l; | 497 | unsigned l; |
476 | int channel; | 498 | int channel; |
477 | 499 | ||
478 | switch (urb->status) { | 500 | switch (urb->status) { |
479 | case 0: /* success */ | 501 | case 0: /* success */ |
480 | break; | 502 | break; |
481 | case -ENOENT: /* canceled */ | 503 | case -ENOENT: /* cancelled */ |
482 | case -ECONNRESET: /* canceled (async) */ | 504 | case -ECONNRESET: /* cancelled (async) */ |
483 | case -EINPROGRESS: /* pending */ | 505 | case -EINPROGRESS: /* pending */ |
484 | /* ignore silently */ | 506 | /* ignore silently */ |
485 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 507 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
486 | __func__, get_usb_statmsg(urb->status)); | 508 | __func__, get_usb_statmsg(urb->status)); |
487 | return; | 509 | return; |
510 | case -ENODEV: /* device removed */ | ||
511 | case -ESHUTDOWN: /* device shut down */ | ||
512 | //FIXME use this as disconnect indicator? | ||
513 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); | ||
514 | return; | ||
488 | default: /* severe trouble */ | 515 | default: /* severe trouble */ |
489 | dev_warn(cs->dev, "interrupt read: %s\n", | 516 | dev_warn(cs->dev, "interrupt read: %s\n", |
490 | get_usb_statmsg(urb->status)); | 517 | get_usb_statmsg(urb->status)); |
@@ -492,6 +519,13 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
492 | goto resubmit; | 519 | goto resubmit; |
493 | } | 520 | } |
494 | 521 | ||
522 | /* drop incomplete packets even if the missing bytes wouldn't matter */ | ||
523 | if (unlikely(urb->actual_length < 3)) { | ||
524 | dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", | ||
525 | urb->actual_length); | ||
526 | goto resubmit; | ||
527 | } | ||
528 | |||
495 | l = (unsigned) ucs->int_in_buf[1] + | 529 | l = (unsigned) ucs->int_in_buf[1] + |
496 | (((unsigned) ucs->int_in_buf[2]) << 8); | 530 | (((unsigned) ucs->int_in_buf[2]) << 8); |
497 | 531 | ||
@@ -558,25 +592,28 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
558 | } | 592 | } |
559 | spin_lock_irqsave(&cs->lock, flags); | 593 | spin_lock_irqsave(&cs->lock, flags); |
560 | if (ucs->rcvbuf_size) { | 594 | if (ucs->rcvbuf_size) { |
561 | spin_unlock_irqrestore(&cs->lock, flags); | 595 | /* throw away previous buffer - we have no queue */ |
562 | dev_err(cs->dev, | 596 | dev_err(cs->dev, |
563 | "receive AT data overrun, %d bytes lost\n", l); | 597 | "receive AT data overrun, %d bytes lost\n", |
564 | error_reset(cs); //FIXME reschedule | 598 | ucs->rcvbuf_size); |
565 | break; | 599 | kfree(ucs->rcvbuf); |
600 | ucs->rcvbuf_size = 0; | ||
566 | } | 601 | } |
567 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { | 602 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { |
568 | spin_unlock_irqrestore(&cs->lock, flags); | 603 | spin_unlock_irqrestore(&cs->lock, flags); |
569 | dev_err(cs->dev, "out of memory, %d bytes lost\n", l); | 604 | dev_err(cs->dev, "out of memory receiving AT data\n"); |
570 | error_reset(cs); //FIXME reschedule | 605 | error_reset(cs); |
571 | break; | 606 | break; |
572 | } | 607 | } |
573 | ucs->rcvbuf_size = l; | 608 | ucs->rcvbuf_size = l; |
574 | ucs->retry_cmd_in = 0; | 609 | ucs->retry_cmd_in = 0; |
575 | if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) { | 610 | if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { |
576 | kfree(ucs->rcvbuf); | 611 | kfree(ucs->rcvbuf); |
577 | ucs->rcvbuf = NULL; | 612 | ucs->rcvbuf = NULL; |
578 | ucs->rcvbuf_size = 0; | 613 | ucs->rcvbuf_size = 0; |
579 | error_reset(cs); //FIXME reschedule | 614 | if (rc != -ENODEV) |
615 | //FIXME corrective action? | ||
616 | error_reset(cs); | ||
580 | } | 617 | } |
581 | spin_unlock_irqrestore(&cs->lock, flags); | 618 | spin_unlock_irqrestore(&cs->lock, flags); |
582 | break; | 619 | break; |
@@ -598,12 +635,10 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
598 | check_pending(ucs); | 635 | check_pending(ucs); |
599 | 636 | ||
600 | resubmit: | 637 | resubmit: |
601 | spin_lock_irqsave(&cs->lock, flags); | 638 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
602 | status = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 639 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
603 | spin_unlock_irqrestore(&cs->lock, flags); | ||
604 | if (unlikely(status)) { | ||
605 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", | 640 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", |
606 | get_usb_statmsg(status)); | 641 | get_usb_rcmsg(rc)); |
607 | error_reset(cs); | 642 | error_reset(cs); |
608 | } | 643 | } |
609 | } | 644 | } |
@@ -622,18 +657,12 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
622 | struct bas_cardstate *ucs = cs->hw.bas; | 657 | struct bas_cardstate *ucs = cs->hw.bas; |
623 | int have_data = 0; | 658 | int have_data = 0; |
624 | unsigned numbytes; | 659 | unsigned numbytes; |
625 | unsigned long flags; | 660 | int rc; |
626 | 661 | ||
627 | spin_lock_irqsave(&cs->lock, flags); | 662 | update_basstate(ucs, 0, BS_ATRDPEND); |
628 | if (unlikely(!cs->connected)) { | ||
629 | warn("%s: disconnected", __func__); | ||
630 | spin_unlock_irqrestore(&cs->lock, flags); | ||
631 | return; | ||
632 | } | ||
633 | 663 | ||
634 | if (!ucs->rcvbuf_size) { | 664 | if (!ucs->rcvbuf_size) { |
635 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | 665 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); |
636 | spin_unlock_irqrestore(&cs->lock, flags); | ||
637 | return; | 666 | return; |
638 | } | 667 | } |
639 | 668 | ||
@@ -666,9 +695,11 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
666 | } | 695 | } |
667 | break; | 696 | break; |
668 | 697 | ||
669 | case -ENOENT: /* canceled */ | 698 | case -ENOENT: /* cancelled */ |
670 | case -ECONNRESET: /* canceled (async) */ | 699 | case -ECONNRESET: /* cancelled (async) */ |
671 | case -EINPROGRESS: /* pending */ | 700 | case -EINPROGRESS: /* pending */ |
701 | case -ENODEV: /* device removed */ | ||
702 | case -ESHUTDOWN: /* device shut down */ | ||
672 | /* no action necessary */ | 703 | /* no action necessary */ |
673 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 704 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
674 | __func__, get_usb_statmsg(urb->status)); | 705 | __func__, get_usb_statmsg(urb->status)); |
@@ -681,11 +712,11 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
681 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 712 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
682 | dev_notice(cs->dev, "control read: retry %d\n", | 713 | dev_notice(cs->dev, "control read: retry %d\n", |
683 | ucs->retry_cmd_in); | 714 | ucs->retry_cmd_in); |
684 | if (atread_submit(cs, BAS_TIMEOUT) >= 0) { | 715 | rc = atread_submit(cs, BAS_TIMEOUT); |
685 | /* resubmitted - bypass regular exit block */ | 716 | if (rc >= 0 || rc == -ENODEV) |
686 | spin_unlock_irqrestore(&cs->lock, flags); | 717 | /* resubmitted or disconnected */ |
718 | /* - bypass regular exit block */ | ||
687 | return; | 719 | return; |
688 | } | ||
689 | } else { | 720 | } else { |
690 | dev_err(cs->dev, | 721 | dev_err(cs->dev, |
691 | "control read: giving up after %d tries\n", | 722 | "control read: giving up after %d tries\n", |
@@ -697,7 +728,6 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
697 | kfree(ucs->rcvbuf); | 728 | kfree(ucs->rcvbuf); |
698 | ucs->rcvbuf = NULL; | 729 | ucs->rcvbuf = NULL; |
699 | ucs->rcvbuf_size = 0; | 730 | ucs->rcvbuf_size = 0; |
700 | spin_unlock_irqrestore(&cs->lock, flags); | ||
701 | if (have_data) { | 731 | if (have_data) { |
702 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | 732 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); |
703 | gigaset_schedule_event(cs); | 733 | gigaset_schedule_event(cs); |
@@ -719,8 +749,11 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
719 | int i, rc; | 749 | int i, rc; |
720 | 750 | ||
721 | /* status codes not worth bothering the tasklet with */ | 751 | /* status codes not worth bothering the tasklet with */ |
722 | if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || | 752 | if (unlikely(urb->status == -ENOENT || |
723 | urb->status == -EINPROGRESS)) { | 753 | urb->status == -ECONNRESET || |
754 | urb->status == -EINPROGRESS || | ||
755 | urb->status == -ENODEV || | ||
756 | urb->status == -ESHUTDOWN)) { | ||
724 | gig_dbg(DEBUG_ISO, "%s: %s", | 757 | gig_dbg(DEBUG_ISO, "%s: %s", |
725 | __func__, get_usb_statmsg(urb->status)); | 758 | __func__, get_usb_statmsg(urb->status)); |
726 | return; | 759 | return; |
@@ -740,9 +773,9 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
740 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 773 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
741 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; | 774 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; |
742 | if (unlikely(urb->iso_frame_desc[i].status != 0 && | 775 | if (unlikely(urb->iso_frame_desc[i].status != 0 && |
743 | urb->iso_frame_desc[i].status != -EINPROGRESS)) { | 776 | urb->iso_frame_desc[i].status != |
777 | -EINPROGRESS)) | ||
744 | ubc->loststatus = urb->iso_frame_desc[i].status; | 778 | ubc->loststatus = urb->iso_frame_desc[i].status; |
745 | } | ||
746 | urb->iso_frame_desc[i].status = 0; | 779 | urb->iso_frame_desc[i].status = 0; |
747 | urb->iso_frame_desc[i].actual_length = 0; | 780 | urb->iso_frame_desc[i].actual_length = 0; |
748 | } | 781 | } |
@@ -754,10 +787,10 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
754 | gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", | 787 | gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", |
755 | __func__); | 788 | __func__); |
756 | rc = usb_submit_urb(urb, SLAB_ATOMIC); | 789 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
757 | if (unlikely(rc != 0)) { | 790 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
758 | dev_err(bcs->cs->dev, | 791 | dev_err(bcs->cs->dev, |
759 | "could not resubmit isochronous read " | 792 | "could not resubmit isochronous read " |
760 | "URB: %s\n", get_usb_statmsg(rc)); | 793 | "URB: %s\n", get_usb_rcmsg(rc)); |
761 | dump_urb(DEBUG_ISO, "isoc read", urb); | 794 | dump_urb(DEBUG_ISO, "isoc read", urb); |
762 | error_hangup(bcs); | 795 | error_hangup(bcs); |
763 | } | 796 | } |
@@ -780,8 +813,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
780 | unsigned long flags; | 813 | unsigned long flags; |
781 | 814 | ||
782 | /* status codes not worth bothering the tasklet with */ | 815 | /* status codes not worth bothering the tasklet with */ |
783 | if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || | 816 | if (unlikely(urb->status == -ENOENT || |
784 | urb->status == -EINPROGRESS)) { | 817 | urb->status == -ECONNRESET || |
818 | urb->status == -EINPROGRESS || | ||
819 | urb->status == -ENODEV || | ||
820 | urb->status == -ESHUTDOWN)) { | ||
785 | gig_dbg(DEBUG_ISO, "%s: %s", | 821 | gig_dbg(DEBUG_ISO, "%s: %s", |
786 | __func__, get_usb_statmsg(urb->status)); | 822 | __func__, get_usb_statmsg(urb->status)); |
787 | return; | 823 | return; |
@@ -822,7 +858,6 @@ static int starturbs(struct bc_state *bcs) | |||
822 | for (k = 0; k < BAS_INURBS; k++) { | 858 | for (k = 0; k < BAS_INURBS; k++) { |
823 | urb = ubc->isoinurbs[k]; | 859 | urb = ubc->isoinurbs[k]; |
824 | if (!urb) { | 860 | if (!urb) { |
825 | dev_err(bcs->cs->dev, "isoinurbs[%d]==NULL\n", k); | ||
826 | rc = -EFAULT; | 861 | rc = -EFAULT; |
827 | goto error; | 862 | goto error; |
828 | } | 863 | } |
@@ -844,12 +879,8 @@ static int starturbs(struct bc_state *bcs) | |||
844 | } | 879 | } |
845 | 880 | ||
846 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); | 881 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); |
847 | if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { | 882 | if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) |
848 | dev_err(bcs->cs->dev, | ||
849 | "could not submit isochronous read URB %d: %s\n", | ||
850 | k, get_usb_statmsg(rc)); | ||
851 | goto error; | 883 | goto error; |
852 | } | ||
853 | } | 884 | } |
854 | 885 | ||
855 | /* initialize L2 transmission */ | 886 | /* initialize L2 transmission */ |
@@ -859,7 +890,6 @@ static int starturbs(struct bc_state *bcs) | |||
859 | for (k = 0; k < BAS_OUTURBS; ++k) { | 890 | for (k = 0; k < BAS_OUTURBS; ++k) { |
860 | urb = ubc->isoouturbs[k].urb; | 891 | urb = ubc->isoouturbs[k].urb; |
861 | if (!urb) { | 892 | if (!urb) { |
862 | dev_err(bcs->cs->dev, "isoouturbs[%d].urb==NULL\n", k); | ||
863 | rc = -EFAULT; | 893 | rc = -EFAULT; |
864 | goto error; | 894 | goto error; |
865 | } | 895 | } |
@@ -885,12 +915,8 @@ static int starturbs(struct bc_state *bcs) | |||
885 | for (k = 0; k < 2; ++k) { | 915 | for (k = 0; k < 2; ++k) { |
886 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); | 916 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); |
887 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); | 917 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); |
888 | if (rc != 0) { | 918 | if (rc != 0) |
889 | dev_err(bcs->cs->dev, | ||
890 | "could not submit isochronous write URB %d: %s\n", | ||
891 | k, get_usb_statmsg(rc)); | ||
892 | goto error; | 919 | goto error; |
893 | } | ||
894 | } | 920 | } |
895 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); | 921 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); |
896 | ubc->isooutfree = &ubc->isoouturbs[2]; | 922 | ubc->isooutfree = &ubc->isoouturbs[2]; |
@@ -916,15 +942,15 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
916 | for (k = 0; k < BAS_INURBS; ++k) { | 942 | for (k = 0; k < BAS_INURBS; ++k) { |
917 | rc = usb_unlink_urb(ubc->isoinurbs[k]); | 943 | rc = usb_unlink_urb(ubc->isoinurbs[k]); |
918 | gig_dbg(DEBUG_ISO, | 944 | gig_dbg(DEBUG_ISO, |
919 | "%s: isoc input URB %d unlinked, result = %d", | 945 | "%s: isoc input URB %d unlinked, result = %s", |
920 | __func__, k, rc); | 946 | __func__, k, get_usb_rcmsg(rc)); |
921 | } | 947 | } |
922 | 948 | ||
923 | for (k = 0; k < BAS_OUTURBS; ++k) { | 949 | for (k = 0; k < BAS_OUTURBS; ++k) { |
924 | rc = usb_unlink_urb(ubc->isoouturbs[k].urb); | 950 | rc = usb_unlink_urb(ubc->isoouturbs[k].urb); |
925 | gig_dbg(DEBUG_ISO, | 951 | gig_dbg(DEBUG_ISO, |
926 | "%s: isoc output URB %d unlinked, result = %d", | 952 | "%s: isoc output URB %d unlinked, result = %s", |
927 | __func__, k, rc); | 953 | __func__, k, get_usb_rcmsg(rc)); |
928 | } | 954 | } |
929 | } | 955 | } |
930 | 956 | ||
@@ -934,7 +960,7 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
934 | /* submit_iso_write_urb | 960 | /* submit_iso_write_urb |
935 | * fill and submit the next isochronous write URB | 961 | * fill and submit the next isochronous write URB |
936 | * parameters: | 962 | * parameters: |
937 | * bcs B channel state structure | 963 | * ucx context structure containing URB |
938 | * return value: | 964 | * return value: |
939 | * number of frames submitted in URB | 965 | * number of frames submitted in URB |
940 | * 0 if URB not submitted because no data available (isooutbuf busy) | 966 | * 0 if URB not submitted because no data available (isooutbuf busy) |
@@ -946,7 +972,6 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
946 | struct bas_bc_state *ubc = ucx->bcs->hw.bas; | 972 | struct bas_bc_state *ubc = ucx->bcs->hw.bas; |
947 | struct usb_iso_packet_descriptor *ifd; | 973 | struct usb_iso_packet_descriptor *ifd; |
948 | int corrbytes, nframe, rc; | 974 | int corrbytes, nframe, rc; |
949 | unsigned long flags; | ||
950 | 975 | ||
951 | /* urb->dev is clobbered by USB subsystem */ | 976 | /* urb->dev is clobbered by USB subsystem */ |
952 | urb->dev = ucx->bcs->cs->hw.bas->udev; | 977 | urb->dev = ucx->bcs->cs->hw.bas->udev; |
@@ -992,20 +1017,22 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
992 | ifd->status = 0; | 1017 | ifd->status = 0; |
993 | ifd->actual_length = 0; | 1018 | ifd->actual_length = 0; |
994 | } | 1019 | } |
995 | if ((urb->number_of_packets = nframe) > 0) { | 1020 | if (unlikely(nframe == 0)) |
996 | spin_lock_irqsave(&ucx->bcs->cs->lock, flags); | 1021 | return 0; /* no data to send */ |
997 | rc = ucx->bcs->cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 1022 | urb->number_of_packets = nframe; |
998 | spin_unlock_irqrestore(&ucx->bcs->cs->lock, flags); | ||
999 | 1023 | ||
1000 | if (rc) { | 1024 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
1025 | if (unlikely(rc)) { | ||
1026 | if (rc == -ENODEV) | ||
1027 | /* device removed - give up silently */ | ||
1028 | gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); | ||
1029 | else | ||
1001 | dev_err(ucx->bcs->cs->dev, | 1030 | dev_err(ucx->bcs->cs->dev, |
1002 | "could not submit isochronous write URB: %s\n", | 1031 | "could not submit isochronous write URB: %s\n", |
1003 | get_usb_statmsg(rc)); | 1032 | get_usb_rcmsg(rc)); |
1004 | dump_urb(DEBUG_ISO, "isoc write", urb); | 1033 | return rc; |
1005 | return rc; | ||
1006 | } | ||
1007 | ++ubc->numsub; | ||
1008 | } | 1034 | } |
1035 | ++ubc->numsub; | ||
1009 | return nframe; | 1036 | return nframe; |
1010 | } | 1037 | } |
1011 | 1038 | ||
@@ -1028,6 +1055,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1028 | int i; | 1055 | int i; |
1029 | struct sk_buff *skb; | 1056 | struct sk_buff *skb; |
1030 | int len; | 1057 | int len; |
1058 | int rc; | ||
1031 | 1059 | ||
1032 | /* loop while completed URBs arrive in time */ | 1060 | /* loop while completed URBs arrive in time */ |
1033 | for (;;) { | 1061 | for (;;) { |
@@ -1057,7 +1085,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1057 | ubc->isooutfree = NULL; | 1085 | ubc->isooutfree = NULL; |
1058 | spin_unlock_irqrestore(&ubc->isooutlock, flags); | 1086 | spin_unlock_irqrestore(&ubc->isooutlock, flags); |
1059 | if (next) { | 1087 | if (next) { |
1060 | if (submit_iso_write_urb(next) <= 0) { | 1088 | rc = submit_iso_write_urb(next); |
1089 | if (unlikely(rc <= 0 && rc != -ENODEV)) { | ||
1061 | /* could not submit URB, put it back */ | 1090 | /* could not submit URB, put it back */ |
1062 | spin_lock_irqsave(&ubc->isooutlock, flags); | 1091 | spin_lock_irqsave(&ubc->isooutlock, flags); |
1063 | if (ubc->isooutfree == NULL) { | 1092 | if (ubc->isooutfree == NULL) { |
@@ -1077,17 +1106,18 @@ static void write_iso_tasklet(unsigned long data) | |||
1077 | /* process completed URB */ | 1106 | /* process completed URB */ |
1078 | urb = done->urb; | 1107 | urb = done->urb; |
1079 | switch (urb->status) { | 1108 | switch (urb->status) { |
1109 | case -EXDEV: /* partial completion */ | ||
1110 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | ||
1111 | __func__); | ||
1112 | /* fall through - what's the difference anyway? */ | ||
1080 | case 0: /* normal completion */ | 1113 | case 0: /* normal completion */ |
1081 | break; | 1114 | /* inspect individual frames |
1082 | case -EXDEV: /* inspect individual frames */ | 1115 | * assumptions (for lack of documentation): |
1083 | /* assumptions (for lack of documentation): | 1116 | * - actual_length bytes of first frame in error are |
1084 | * - actual_length bytes of the frame in error are | ||
1085 | * successfully sent | 1117 | * successfully sent |
1086 | * - all following frames are not sent at all | 1118 | * - all following frames are not sent at all |
1087 | */ | 1119 | */ |
1088 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | 1120 | offset = done->limit; /* default (no error) */ |
1089 | __func__); | ||
1090 | offset = done->limit; /* just in case */ | ||
1091 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 1121 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
1092 | ifd = &urb->iso_frame_desc[i]; | 1122 | ifd = &urb->iso_frame_desc[i]; |
1093 | if (ifd->status || | 1123 | if (ifd->status || |
@@ -1122,7 +1152,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1122 | } | 1152 | } |
1123 | #endif | 1153 | #endif |
1124 | break; | 1154 | break; |
1125 | case -EPIPE: //FIXME is this the code for "underrun"? | 1155 | case -EPIPE: /* stall - probably underrun */ |
1126 | dev_err(cs->dev, "isochronous write stalled\n"); | 1156 | dev_err(cs->dev, "isochronous write stalled\n"); |
1127 | error_hangup(bcs); | 1157 | error_hangup(bcs); |
1128 | break; | 1158 | break; |
@@ -1142,7 +1172,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1142 | spin_unlock_irqrestore(&ubc->isooutlock, flags); | 1172 | spin_unlock_irqrestore(&ubc->isooutlock, flags); |
1143 | if (next) { | 1173 | if (next) { |
1144 | /* only one URB still active - resubmit one */ | 1174 | /* only one URB still active - resubmit one */ |
1145 | if (submit_iso_write_urb(next) <= 0) { | 1175 | rc = submit_iso_write_urb(next); |
1176 | if (unlikely(rc <= 0 && rc != -ENODEV)) { | ||
1146 | /* couldn't submit */ | 1177 | /* couldn't submit */ |
1147 | error_hangup(bcs); | 1178 | error_hangup(bcs); |
1148 | } | 1179 | } |
@@ -1222,10 +1253,9 @@ static void read_iso_tasklet(unsigned long data) | |||
1222 | break; | 1253 | break; |
1223 | case -ENOENT: | 1254 | case -ENOENT: |
1224 | case -ECONNRESET: | 1255 | case -ECONNRESET: |
1225 | gig_dbg(DEBUG_ISO, "%s: URB canceled", __func__); | 1256 | case -EINPROGRESS: |
1226 | continue; /* -> skip */ | 1257 | gig_dbg(DEBUG_ISO, "%s: %s", |
1227 | case -EINPROGRESS: /* huh? */ | 1258 | __func__, get_usb_statmsg(urb->status)); |
1228 | gig_dbg(DEBUG_ISO, "%s: URB still pending", __func__); | ||
1229 | continue; /* -> skip */ | 1259 | continue; /* -> skip */ |
1230 | case -EPIPE: | 1260 | case -EPIPE: |
1231 | dev_err(cs->dev, "isochronous read stalled\n"); | 1261 | dev_err(cs->dev, "isochronous read stalled\n"); |
@@ -1290,13 +1320,11 @@ static void read_iso_tasklet(unsigned long data) | |||
1290 | urb->dev = bcs->cs->hw.bas->udev; | 1320 | urb->dev = bcs->cs->hw.bas->udev; |
1291 | urb->transfer_flags = URB_ISO_ASAP; | 1321 | urb->transfer_flags = URB_ISO_ASAP; |
1292 | urb->number_of_packets = BAS_NUMFRAMES; | 1322 | urb->number_of_packets = BAS_NUMFRAMES; |
1293 | spin_lock_irqsave(&cs->lock, flags); | 1323 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
1294 | rc = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 1324 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
1295 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1296 | if (rc) { | ||
1297 | dev_err(cs->dev, | 1325 | dev_err(cs->dev, |
1298 | "could not resubmit isochronous read URB: %s\n", | 1326 | "could not resubmit isochronous read URB: %s\n", |
1299 | get_usb_statmsg(rc)); | 1327 | get_usb_rcmsg(rc)); |
1300 | dump_urb(DEBUG_ISO, "resubmit iso read", urb); | 1328 | dump_urb(DEBUG_ISO, "resubmit iso read", urb); |
1301 | error_hangup(bcs); | 1329 | error_hangup(bcs); |
1302 | } | 1330 | } |
@@ -1397,7 +1425,6 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
1397 | * timeout timeout in seconds (0: no timeout) | 1425 | * timeout timeout in seconds (0: no timeout) |
1398 | * return value: | 1426 | * return value: |
1399 | * 0 on success | 1427 | * 0 on success |
1400 | * -EINVAL if a NULL pointer is encountered somewhere | ||
1401 | * -EBUSY if another request is pending | 1428 | * -EBUSY if another request is pending |
1402 | * any URB submission error code | 1429 | * any URB submission error code |
1403 | */ | 1430 | */ |
@@ -1418,12 +1445,6 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1418 | req, ucs->pending); | 1445 | req, ucs->pending); |
1419 | return -EBUSY; | 1446 | return -EBUSY; |
1420 | } | 1447 | } |
1421 | if (ucs->urb_ctrl->status == -EINPROGRESS) { | ||
1422 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
1423 | dev_err(bcs->cs->dev, | ||
1424 | "could not submit request 0x%02x: URB busy\n", req); | ||
1425 | return -EBUSY; | ||
1426 | } | ||
1427 | 1448 | ||
1428 | ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; | 1449 | ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; |
1429 | ucs->dr_ctrl.bRequest = req; | 1450 | ucs->dr_ctrl.bRequest = req; |
@@ -1465,22 +1486,36 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1465 | static int gigaset_init_bchannel(struct bc_state *bcs) | 1486 | static int gigaset_init_bchannel(struct bc_state *bcs) |
1466 | { | 1487 | { |
1467 | int req, ret; | 1488 | int req, ret; |
1489 | unsigned long flags; | ||
1490 | |||
1491 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
1492 | if (unlikely(!bcs->cs->connected)) { | ||
1493 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1494 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1495 | return -ENODEV; | ||
1496 | } | ||
1468 | 1497 | ||
1469 | if ((ret = starturbs(bcs)) < 0) { | 1498 | if ((ret = starturbs(bcs)) < 0) { |
1470 | dev_err(bcs->cs->dev, | 1499 | dev_err(bcs->cs->dev, |
1471 | "could not start isochronous I/O for channel %d\n", | 1500 | "could not start isochronous I/O for channel B%d: %s\n", |
1472 | bcs->channel + 1); | 1501 | bcs->channel + 1, |
1473 | error_hangup(bcs); | 1502 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1503 | if (ret != -ENODEV) | ||
1504 | error_hangup(bcs); | ||
1505 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1474 | return ret; | 1506 | return ret; |
1475 | } | 1507 | } |
1476 | 1508 | ||
1477 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1509 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1478 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1510 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { |
1479 | dev_err(bcs->cs->dev, "could not open channel %d: %s\n", | 1511 | dev_err(bcs->cs->dev, "could not open channel B%d\n", |
1480 | bcs->channel + 1, get_usb_statmsg(ret)); | 1512 | bcs->channel + 1); |
1481 | stopurbs(bcs->hw.bas); | 1513 | stopurbs(bcs->hw.bas); |
1482 | error_hangup(bcs); | 1514 | if (ret != -ENODEV) |
1515 | error_hangup(bcs); | ||
1483 | } | 1516 | } |
1517 | |||
1518 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1484 | return ret; | 1519 | return ret; |
1485 | } | 1520 | } |
1486 | 1521 | ||
@@ -1497,19 +1532,30 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1497 | static int gigaset_close_bchannel(struct bc_state *bcs) | 1532 | static int gigaset_close_bchannel(struct bc_state *bcs) |
1498 | { | 1533 | { |
1499 | int req, ret; | 1534 | int req, ret; |
1535 | unsigned long flags; | ||
1536 | |||
1537 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
1538 | if (unlikely(!bcs->cs->connected)) { | ||
1539 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1540 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1541 | return -ENODEV; | ||
1542 | } | ||
1500 | 1543 | ||
1501 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & | 1544 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & |
1502 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { | 1545 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { |
1503 | /* channel not running: just signal common.c */ | 1546 | /* channel not running: just signal common.c */ |
1547 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1504 | gigaset_bchannel_down(bcs); | 1548 | gigaset_bchannel_down(bcs); |
1505 | return 0; | 1549 | return 0; |
1506 | } | 1550 | } |
1507 | 1551 | ||
1552 | /* channel running: tell device to close it */ | ||
1508 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1553 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1509 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1554 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) |
1510 | dev_err(bcs->cs->dev, | 1555 | dev_err(bcs->cs->dev, "closing channel B%d failed\n", |
1511 | "could not submit HD_CLOSE_BxCHANNEL request: %s\n", | 1556 | bcs->channel + 1); |
1512 | get_usb_statmsg(ret)); | 1557 | |
1558 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1513 | return ret; | 1559 | return ret; |
1514 | } | 1560 | } |
1515 | 1561 | ||
@@ -1545,8 +1591,6 @@ static void complete_cb(struct cardstate *cs) | |||
1545 | kfree(cb); | 1591 | kfree(cb); |
1546 | } | 1592 | } |
1547 | 1593 | ||
1548 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); | ||
1549 | |||
1550 | /* write_command_callback | 1594 | /* write_command_callback |
1551 | * USB completion handler for AT command transmission | 1595 | * USB completion handler for AT command transmission |
1552 | * called by the USB subsystem in interrupt context | 1596 | * called by the USB subsystem in interrupt context |
@@ -1560,13 +1604,17 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs) | |||
1560 | struct bas_cardstate *ucs = cs->hw.bas; | 1604 | struct bas_cardstate *ucs = cs->hw.bas; |
1561 | unsigned long flags; | 1605 | unsigned long flags; |
1562 | 1606 | ||
1607 | update_basstate(ucs, 0, BS_ATWRPEND); | ||
1608 | |||
1563 | /* check status */ | 1609 | /* check status */ |
1564 | switch (urb->status) { | 1610 | switch (urb->status) { |
1565 | case 0: /* normal completion */ | 1611 | case 0: /* normal completion */ |
1566 | break; | 1612 | break; |
1567 | case -ENOENT: /* canceled */ | 1613 | case -ENOENT: /* cancelled */ |
1568 | case -ECONNRESET: /* canceled (async) */ | 1614 | case -ECONNRESET: /* cancelled (async) */ |
1569 | case -EINPROGRESS: /* pending */ | 1615 | case -EINPROGRESS: /* pending */ |
1616 | case -ENODEV: /* device removed */ | ||
1617 | case -ESHUTDOWN: /* device shut down */ | ||
1570 | /* ignore silently */ | 1618 | /* ignore silently */ |
1571 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1619 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1572 | __func__, get_usb_statmsg(urb->status)); | 1620 | __func__, get_usb_statmsg(urb->status)); |
@@ -1627,19 +1675,17 @@ static void atrdy_timeout(unsigned long data) | |||
1627 | * len length of command to send | 1675 | * len length of command to send |
1628 | * return value: | 1676 | * return value: |
1629 | * 0 on success | 1677 | * 0 on success |
1630 | * -EFAULT if a NULL pointer is encountered somewhere | ||
1631 | * -EBUSY if another request is pending | 1678 | * -EBUSY if another request is pending |
1632 | * any URB submission error code | 1679 | * any URB submission error code |
1633 | */ | 1680 | */ |
1634 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | 1681 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) |
1635 | { | 1682 | { |
1636 | struct bas_cardstate *ucs = cs->hw.bas; | 1683 | struct bas_cardstate *ucs = cs->hw.bas; |
1637 | unsigned long flags; | 1684 | int rc; |
1638 | int ret; | ||
1639 | 1685 | ||
1640 | gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); | 1686 | gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); |
1641 | 1687 | ||
1642 | if (ucs->urb_cmd_out->status == -EINPROGRESS) { | 1688 | if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) { |
1643 | dev_err(cs->dev, | 1689 | dev_err(cs->dev, |
1644 | "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); | 1690 | "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); |
1645 | return -EBUSY; | 1691 | return -EBUSY; |
@@ -1654,29 +1700,22 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | |||
1654 | usb_sndctrlpipe(ucs->udev, 0), | 1700 | usb_sndctrlpipe(ucs->udev, 0), |
1655 | (unsigned char*) &ucs->dr_cmd_out, buf, len, | 1701 | (unsigned char*) &ucs->dr_cmd_out, buf, len, |
1656 | write_command_callback, cs); | 1702 | write_command_callback, cs); |
1657 | 1703 | rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC); | |
1658 | spin_lock_irqsave(&cs->lock, flags); | 1704 | if (unlikely(rc)) { |
1659 | ret = cs->connected ? usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC) : -ENODEV; | 1705 | update_basstate(ucs, 0, BS_ATWRPEND); |
1660 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1661 | |||
1662 | if (ret) { | ||
1663 | dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", | 1706 | dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", |
1664 | get_usb_statmsg(ret)); | 1707 | get_usb_rcmsg(rc)); |
1665 | return ret; | 1708 | return rc; |
1666 | } | 1709 | } |
1667 | 1710 | ||
1668 | /* submitted successfully */ | 1711 | /* submitted successfully, start timeout if necessary */ |
1669 | update_basstate(ucs, 0, BS_ATREADY); | 1712 | if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { |
1670 | |||
1671 | /* start timeout if necessary */ | ||
1672 | if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) { | ||
1673 | gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", | 1713 | gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", |
1674 | ATRDY_TIMEOUT); | 1714 | ATRDY_TIMEOUT); |
1675 | ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; | 1715 | ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; |
1676 | ucs->timer_atrdy.data = (unsigned long) cs; | 1716 | ucs->timer_atrdy.data = (unsigned long) cs; |
1677 | ucs->timer_atrdy.function = atrdy_timeout; | 1717 | ucs->timer_atrdy.function = atrdy_timeout; |
1678 | add_timer(&ucs->timer_atrdy); | 1718 | add_timer(&ucs->timer_atrdy); |
1679 | update_basstate(ucs, BS_ATTIMER, 0); | ||
1680 | } | 1719 | } |
1681 | return 0; | 1720 | return 0; |
1682 | } | 1721 | } |
@@ -1702,7 +1741,6 @@ static int start_cbsend(struct cardstate *cs) | |||
1702 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1741 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); |
1703 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1742 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1704 | if (rc < 0) { | 1743 | if (rc < 0) { |
1705 | dev_err(cs->dev, "could not open AT channel\n"); | ||
1706 | /* flush command queue */ | 1744 | /* flush command queue */ |
1707 | spin_lock_irqsave(&cs->cmdlock, flags); | 1745 | spin_lock_irqsave(&cs->cmdlock, flags); |
1708 | while (cs->cmdbuf != NULL) | 1746 | while (cs->cmdbuf != NULL) |
@@ -1786,8 +1824,14 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1786 | cs->lastcmdbuf = cb; | 1824 | cs->lastcmdbuf = cb; |
1787 | spin_unlock_irqrestore(&cs->cmdlock, flags); | 1825 | spin_unlock_irqrestore(&cs->cmdlock, flags); |
1788 | 1826 | ||
1827 | spin_lock_irqsave(&cs->lock, flags); | ||
1828 | if (unlikely(!cs->connected)) { | ||
1829 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1830 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1831 | return -ENODEV; | ||
1832 | } | ||
1789 | status = start_cbsend(cs); | 1833 | status = start_cbsend(cs); |
1790 | 1834 | spin_unlock_irqrestore(&cs->lock, flags); | |
1791 | return status < 0 ? status : len; | 1835 | return status < 0 ? status : len; |
1792 | } | 1836 | } |
1793 | 1837 | ||
@@ -1849,12 +1893,32 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) | |||
1849 | */ | 1893 | */ |
1850 | static int gigaset_freebcshw(struct bc_state *bcs) | 1894 | static int gigaset_freebcshw(struct bc_state *bcs) |
1851 | { | 1895 | { |
1852 | if (!bcs->hw.bas) | 1896 | struct bas_bc_state *ubc = bcs->hw.bas; |
1897 | int i; | ||
1898 | |||
1899 | if (!ubc) | ||
1853 | return 0; | 1900 | return 0; |
1854 | 1901 | ||
1855 | if (bcs->hw.bas->isooutbuf) | 1902 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1856 | kfree(bcs->hw.bas->isooutbuf); | 1903 | atomic_set(&ubc->running, 0); |
1857 | kfree(bcs->hw.bas); | 1904 | for (i = 0; i < BAS_OUTURBS; ++i) |
1905 | if (ubc->isoouturbs[i].urb) { | ||
1906 | gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d", | ||
1907 | __func__, i); | ||
1908 | usb_kill_urb(ubc->isoouturbs[i].urb); | ||
1909 | usb_free_urb(ubc->isoouturbs[i].urb); | ||
1910 | } | ||
1911 | for (i = 0; i < BAS_INURBS; ++i) | ||
1912 | if (ubc->isoinurbs[i]) { | ||
1913 | gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d", | ||
1914 | __func__, i); | ||
1915 | usb_kill_urb(ubc->isoinurbs[i]); | ||
1916 | usb_free_urb(ubc->isoinurbs[i]); | ||
1917 | } | ||
1918 | tasklet_kill(&ubc->sent_tasklet); | ||
1919 | tasklet_kill(&ubc->rcvd_tasklet); | ||
1920 | kfree(ubc->isooutbuf); | ||
1921 | kfree(ubc); | ||
1858 | bcs->hw.bas = NULL; | 1922 | bcs->hw.bas = NULL; |
1859 | return 1; | 1923 | return 1; |
1860 | } | 1924 | } |
@@ -1931,13 +1995,9 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) | |||
1931 | 1995 | ||
1932 | static void gigaset_freecshw(struct cardstate *cs) | 1996 | static void gigaset_freecshw(struct cardstate *cs) |
1933 | { | 1997 | { |
1934 | struct bas_cardstate *ucs = cs->hw.bas; | 1998 | /* timers, URBs and rcvbuf are disposed of in disconnect */ |
1935 | |||
1936 | del_timer(&ucs->timer_ctrl); | ||
1937 | del_timer(&ucs->timer_atrdy); | ||
1938 | del_timer(&ucs->timer_cmd_in); | ||
1939 | |||
1940 | kfree(cs->hw.bas); | 1999 | kfree(cs->hw.bas); |
2000 | cs->hw.bas = NULL; | ||
1941 | } | 2001 | } |
1942 | 2002 | ||
1943 | static int gigaset_initcshw(struct cardstate *cs) | 2003 | static int gigaset_initcshw(struct cardstate *cs) |
@@ -2041,23 +2101,13 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2041 | struct bas_bc_state *ubc; | 2101 | struct bas_bc_state *ubc; |
2042 | struct usb_endpoint_descriptor *endpoint; | 2102 | struct usb_endpoint_descriptor *endpoint; |
2043 | int i, j; | 2103 | int i, j; |
2044 | int ret; | 2104 | int rc; |
2045 | 2105 | ||
2046 | gig_dbg(DEBUG_ANY, | 2106 | gig_dbg(DEBUG_ANY, |
2047 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | 2107 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", |
2048 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2108 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2049 | le16_to_cpu(udev->descriptor.idProduct)); | 2109 | le16_to_cpu(udev->descriptor.idProduct)); |
2050 | 2110 | ||
2051 | /* See if the device offered us matches what we can accept */ | ||
2052 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) || | ||
2053 | (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID && | ||
2054 | le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID && | ||
2055 | le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID && | ||
2056 | le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) { | ||
2057 | gig_dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); | ||
2058 | return -ENODEV; | ||
2059 | } | ||
2060 | |||
2061 | /* set required alternate setting */ | 2111 | /* set required alternate setting */ |
2062 | hostif = interface->cur_altsetting; | 2112 | hostif = interface->cur_altsetting; |
2063 | if (hostif->desc.bAlternateSetting != 3) { | 2113 | if (hostif->desc.bAlternateSetting != 3) { |
@@ -2105,45 +2155,22 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2105 | * - three for the different uses of the default control pipe | 2155 | * - three for the different uses of the default control pipe |
2106 | * - three for each isochronous pipe | 2156 | * - three for each isochronous pipe |
2107 | */ | 2157 | */ |
2108 | ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL); | 2158 | if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) || |
2109 | if (!ucs->urb_int_in) { | 2159 | !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) || |
2110 | dev_err(cs->dev, "no free urbs available\n"); | 2160 | !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) || |
2111 | goto error; | 2161 | !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL))) |
2112 | } | 2162 | goto allocerr; |
2113 | ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL); | ||
2114 | if (!ucs->urb_cmd_in) { | ||
2115 | dev_err(cs->dev, "no free urbs available\n"); | ||
2116 | goto error; | ||
2117 | } | ||
2118 | ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL); | ||
2119 | if (!ucs->urb_cmd_out) { | ||
2120 | dev_err(cs->dev, "no free urbs available\n"); | ||
2121 | goto error; | ||
2122 | } | ||
2123 | ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL); | ||
2124 | if (!ucs->urb_ctrl) { | ||
2125 | dev_err(cs->dev, "no free urbs available\n"); | ||
2126 | goto error; | ||
2127 | } | ||
2128 | 2163 | ||
2129 | for (j = 0; j < 2; ++j) { | 2164 | for (j = 0; j < 2; ++j) { |
2130 | ubc = cs->bcs[j].hw.bas; | 2165 | ubc = cs->bcs[j].hw.bas; |
2131 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2166 | for (i = 0; i < BAS_OUTURBS; ++i) |
2132 | ubc->isoouturbs[i].urb = | 2167 | if (!(ubc->isoouturbs[i].urb = |
2133 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); | 2168 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) |
2134 | if (!ubc->isoouturbs[i].urb) { | 2169 | goto allocerr; |
2135 | dev_err(cs->dev, "no free urbs available\n"); | 2170 | for (i = 0; i < BAS_INURBS; ++i) |
2136 | goto error; | 2171 | if (!(ubc->isoinurbs[i] = |
2137 | } | 2172 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) |
2138 | } | 2173 | goto allocerr; |
2139 | for (i = 0; i < BAS_INURBS; ++i) { | ||
2140 | ubc->isoinurbs[i] = | ||
2141 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); | ||
2142 | if (!ubc->isoinurbs[i]) { | ||
2143 | dev_err(cs->dev, "no free urbs available\n"); | ||
2144 | goto error; | ||
2145 | } | ||
2146 | } | ||
2147 | } | 2174 | } |
2148 | 2175 | ||
2149 | ucs->rcvbuf = NULL; | 2176 | ucs->rcvbuf = NULL; |
@@ -2156,15 +2183,14 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2156 | (endpoint->bEndpointAddress) & 0x0f), | 2183 | (endpoint->bEndpointAddress) & 0x0f), |
2157 | ucs->int_in_buf, 3, read_int_callback, cs, | 2184 | ucs->int_in_buf, 3, read_int_callback, cs, |
2158 | endpoint->bInterval); | 2185 | endpoint->bInterval); |
2159 | ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL); | 2186 | if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) { |
2160 | if (ret) { | ||
2161 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", | 2187 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", |
2162 | get_usb_statmsg(ret)); | 2188 | get_usb_rcmsg(rc)); |
2163 | goto error; | 2189 | goto error; |
2164 | } | 2190 | } |
2165 | 2191 | ||
2166 | /* tell the device that the driver is ready */ | 2192 | /* tell the device that the driver is ready */ |
2167 | if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) | 2193 | if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) |
2168 | goto error; | 2194 | goto error; |
2169 | 2195 | ||
2170 | /* tell common part that the device is ready */ | 2196 | /* tell common part that the device is ready */ |
@@ -2179,6 +2205,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2179 | 2205 | ||
2180 | return 0; | 2206 | return 0; |
2181 | 2207 | ||
2208 | allocerr: | ||
2209 | dev_err(cs->dev, "could not allocate URBs\n"); | ||
2182 | error: | 2210 | error: |
2183 | freeurbs(cs); | 2211 | freeurbs(cs); |
2184 | usb_set_intfdata(interface, NULL); | 2212 | usb_set_intfdata(interface, NULL); |
@@ -2193,19 +2221,34 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2193 | { | 2221 | { |
2194 | struct cardstate *cs; | 2222 | struct cardstate *cs; |
2195 | struct bas_cardstate *ucs; | 2223 | struct bas_cardstate *ucs; |
2224 | int j; | ||
2196 | 2225 | ||
2197 | cs = usb_get_intfdata(interface); | 2226 | cs = usb_get_intfdata(interface); |
2198 | 2227 | ||
2199 | ucs = cs->hw.bas; | 2228 | ucs = cs->hw.bas; |
2200 | 2229 | ||
2201 | dev_info(cs->dev, "disconnecting Gigaset base\n"); | 2230 | dev_info(cs->dev, "disconnecting Gigaset base\n"); |
2231 | |||
2232 | /* mark base as not ready, all channels disconnected */ | ||
2233 | atomic_set(&ucs->basstate, 0); | ||
2234 | |||
2235 | /* tell LL all channels are down */ | ||
2236 | //FIXME shouldn't gigaset_stop() do this? | ||
2237 | for (j = 0; j < 2; ++j) | ||
2238 | gigaset_bchannel_down(cs->bcs + j); | ||
2239 | |||
2240 | /* stop driver (common part) */ | ||
2202 | gigaset_stop(cs); | 2241 | gigaset_stop(cs); |
2242 | |||
2243 | /* stop timers and URBs, free ressources */ | ||
2244 | del_timer_sync(&ucs->timer_ctrl); | ||
2245 | del_timer_sync(&ucs->timer_atrdy); | ||
2246 | del_timer_sync(&ucs->timer_cmd_in); | ||
2203 | freeurbs(cs); | 2247 | freeurbs(cs); |
2204 | usb_set_intfdata(interface, NULL); | 2248 | usb_set_intfdata(interface, NULL); |
2205 | kfree(ucs->rcvbuf); | 2249 | kfree(ucs->rcvbuf); |
2206 | ucs->rcvbuf = NULL; | 2250 | ucs->rcvbuf = NULL; |
2207 | ucs->rcvbuf_size = 0; | 2251 | ucs->rcvbuf_size = 0; |
2208 | atomic_set(&ucs->basstate, 0); | ||
2209 | usb_put_dev(ucs->udev); | 2252 | usb_put_dev(ucs->udev); |
2210 | ucs->interface = NULL; | 2253 | ucs->interface = NULL; |
2211 | ucs->udev = NULL; | 2254 | ucs->udev = NULL; |
@@ -2277,6 +2320,8 @@ error: if (cardstate) | |||
2277 | */ | 2320 | */ |
2278 | static void __exit bas_gigaset_exit(void) | 2321 | static void __exit bas_gigaset_exit(void) |
2279 | { | 2322 | { |
2323 | struct bas_cardstate *ucs = cardstate->hw.bas; | ||
2324 | |||
2280 | gigaset_blockdriver(driver); /* => probe will fail | 2325 | gigaset_blockdriver(driver); /* => probe will fail |
2281 | * => no gigaset_start any more | 2326 | * => no gigaset_start any more |
2282 | */ | 2327 | */ |
@@ -2284,14 +2329,26 @@ static void __exit bas_gigaset_exit(void) | |||
2284 | gigaset_shutdown(cardstate); | 2329 | gigaset_shutdown(cardstate); |
2285 | /* from now on, no isdn callback should be possible */ | 2330 | /* from now on, no isdn callback should be possible */ |
2286 | 2331 | ||
2287 | if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) { | 2332 | /* close all still open channels */ |
2288 | gig_dbg(DEBUG_ANY, "closing AT channel"); | 2333 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) { |
2289 | if (req_submit(cardstate->bcs, | 2334 | gig_dbg(DEBUG_INIT, "closing B1 channel"); |
2290 | HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { | 2335 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), |
2291 | /* successfully submitted */ | 2336 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, |
2292 | //FIXME wait for completion? | 2337 | NULL, 0, BAS_TIMEOUT); |
2293 | } | 2338 | } |
2339 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) { | ||
2340 | gig_dbg(DEBUG_INIT, "closing B2 channel"); | ||
2341 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | ||
2342 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, | ||
2343 | NULL, 0, BAS_TIMEOUT); | ||
2344 | } | ||
2345 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) { | ||
2346 | gig_dbg(DEBUG_INIT, "closing AT channel"); | ||
2347 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | ||
2348 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, | ||
2349 | NULL, 0, BAS_TIMEOUT); | ||
2294 | } | 2350 | } |
2351 | atomic_set(&ucs->basstate, 0); | ||
2295 | 2352 | ||
2296 | /* deregister this driver with the USB subsystem */ | 2353 | /* deregister this driver with the USB subsystem */ |
2297 | usb_deregister(&gigaset_usb_driver); | 2354 | usb_deregister(&gigaset_usb_driver); |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 749b3da1236e..e55767b2ccd3 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -781,8 +781,7 @@ error: if (cs) | |||
781 | } | 781 | } |
782 | EXPORT_SYMBOL_GPL(gigaset_initcs); | 782 | EXPORT_SYMBOL_GPL(gigaset_initcs); |
783 | 783 | ||
784 | /* ReInitialize the b-channel structure */ | 784 | /* ReInitialize the b-channel structure on hangup */ |
785 | /* e.g. called on hangup, disconnect */ | ||
786 | void gigaset_bcs_reinit(struct bc_state *bcs) | 785 | void gigaset_bcs_reinit(struct bc_state *bcs) |
787 | { | 786 | { |
788 | struct sk_buff *skb; | 787 | struct sk_buff *skb; |
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 1ba3424a286b..18e05c09b71c 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -373,6 +373,9 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ | |||
373 | 373 | ||
374 | {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, | 374 | {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, |
375 | 375 | ||
376 | /* B channel closed (general case) */ | ||
377 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | ||
378 | |||
376 | /* misc. */ | 379 | /* misc. */ |
377 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME | 380 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME |
378 | 381 | ||
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 9d21ba8757b0..22b9693f7c0a 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -75,7 +75,7 @@ extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ | |||
75 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and | 75 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and |
76 | * DEBUG_INTR. | 76 | * DEBUG_INTR. |
77 | */ | 77 | */ |
78 | enum debuglevel { /* up to 24 bits (atomic_t) */ | 78 | enum debuglevel { |
79 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ | 79 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ |
80 | DEBUG_OPEN = 0x0004, /* open/close serial port */ | 80 | DEBUG_OPEN = 0x0004, /* open/close serial port */ |
81 | DEBUG_INTR = 0x0008, /* interrupt processing */ | 81 | DEBUG_INTR = 0x0008, /* interrupt processing */ |
@@ -141,7 +141,7 @@ enum debuglevel { /* up to 24 bits (atomic_t) */ | |||
141 | printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ | 141 | printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ |
142 | ## arg); \ | 142 | ## arg); \ |
143 | } while (0) | 143 | } while (0) |
144 | #define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) | 144 | #define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) |
145 | 145 | ||
146 | #else | 146 | #else |
147 | 147 | ||
@@ -627,8 +627,7 @@ struct gigaset_ops { | |||
627 | /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ | 627 | /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ |
628 | int (*freebcshw)(struct bc_state *bcs); | 628 | int (*freebcshw)(struct bc_state *bcs); |
629 | 629 | ||
630 | /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting | 630 | /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */ |
631 | bcs->hw.xxx */ | ||
632 | void (*reinitbcshw)(struct bc_state *bcs); | 631 | void (*reinitbcshw)(struct bc_state *bcs); |
633 | 632 | ||
634 | /* Called by gigaset_initcs() for setting up cs->hw.xxx */ | 633 | /* Called by gigaset_initcs() for setting up cs->hw.xxx */ |
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 0815dbfb8291..1654fa413575 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c | |||
@@ -73,7 +73,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
73 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); | 73 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); |
74 | 74 | ||
75 | /* pass to device-specific module */ | 75 | /* pass to device-specific module */ |
76 | return cs->ops->send_skb(bcs, skb); //FIXME cs->ops->send_skb() must handle !cs->connected correctly | 76 | return cs->ops->send_skb(bcs, skb); |
77 | } | 77 | } |
78 | 78 | ||
79 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | 79 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 45f017ed6e8c..8667daaa1a82 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -992,14 +992,18 @@ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) | |||
992 | int len = skb->len; | 992 | int len = skb->len; |
993 | unsigned long flags; | 993 | unsigned long flags; |
994 | 994 | ||
995 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
996 | if (!bcs->cs->connected) { | ||
997 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
998 | return -ENODEV; | ||
999 | } | ||
1000 | |||
995 | skb_queue_tail(&bcs->squeue, skb); | 1001 | skb_queue_tail(&bcs->squeue, skb); |
996 | gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", | 1002 | gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", |
997 | __func__, skb_queue_len(&bcs->squeue)); | 1003 | __func__, skb_queue_len(&bcs->squeue)); |
998 | 1004 | ||
999 | /* tasklet submits URB if necessary */ | 1005 | /* tasklet submits URB if necessary */ |
1000 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1006 | tasklet_schedule(&bcs->hw.bas->sent_tasklet); |
1001 | if (bcs->cs->connected) | ||
1002 | tasklet_schedule(&bcs->hw.bas->sent_tasklet); | ||
1003 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1007 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1004 | 1008 | ||
1005 | return len; /* ok so far */ | 1009 | return len; /* ok so far */ |