diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/capi/capi.c | 54 | ||||
-rw-r--r-- | drivers/isdn/divert/isdn_divert.c | 2 | ||||
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 298 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 2 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 13 | ||||
-rw-r--r-- | drivers/isdn/hisax/q931.c | 4 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_common.c | 2 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_tty.c | 2 |
8 files changed, 223 insertions, 154 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 173c899a1fb4..2e541fa02024 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -87,6 +87,11 @@ struct capincci; | |||
87 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 87 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
88 | struct capiminor; | 88 | struct capiminor; |
89 | 89 | ||
90 | struct datahandle_queue { | ||
91 | struct list_head list; | ||
92 | u16 datahandle; | ||
93 | }; | ||
94 | |||
90 | struct capiminor { | 95 | struct capiminor { |
91 | struct list_head list; | 96 | struct list_head list; |
92 | struct capincci *nccip; | 97 | struct capincci *nccip; |
@@ -109,12 +114,9 @@ struct capiminor { | |||
109 | int outbytes; | 114 | int outbytes; |
110 | 115 | ||
111 | /* transmit path */ | 116 | /* transmit path */ |
112 | struct datahandle_queue { | 117 | struct list_head ackqueue; |
113 | struct datahandle_queue *next; | ||
114 | u16 datahandle; | ||
115 | } *ackqueue; | ||
116 | int nack; | 118 | int nack; |
117 | 119 | spinlock_t ackqlock; | |
118 | }; | 120 | }; |
119 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 121 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
120 | 122 | ||
@@ -156,48 +158,54 @@ static LIST_HEAD(capiminor_list); | |||
156 | 158 | ||
157 | static int capincci_add_ack(struct capiminor *mp, u16 datahandle) | 159 | static int capincci_add_ack(struct capiminor *mp, u16 datahandle) |
158 | { | 160 | { |
159 | struct datahandle_queue *n, **pp; | 161 | struct datahandle_queue *n; |
162 | unsigned long flags; | ||
160 | 163 | ||
161 | n = kmalloc(sizeof(*n), GFP_ATOMIC); | 164 | n = kmalloc(sizeof(*n), GFP_ATOMIC); |
162 | if (!n) { | 165 | if (unlikely(!n)) { |
163 | printk(KERN_ERR "capi: alloc datahandle failed\n"); | 166 | printk(KERN_ERR "capi: alloc datahandle failed\n"); |
164 | return -1; | 167 | return -1; |
165 | } | 168 | } |
166 | n->next = NULL; | ||
167 | n->datahandle = datahandle; | 169 | n->datahandle = datahandle; |
168 | for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ; | 170 | INIT_LIST_HEAD(&n->list); |
169 | *pp = n; | 171 | spin_lock_irqsave(&mp->ackqlock, flags); |
172 | list_add_tail(&n->list, &mp->ackqueue); | ||
170 | mp->nack++; | 173 | mp->nack++; |
174 | spin_unlock_irqrestore(&mp->ackqlock, flags); | ||
171 | return 0; | 175 | return 0; |
172 | } | 176 | } |
173 | 177 | ||
174 | static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) | 178 | static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) |
175 | { | 179 | { |
176 | struct datahandle_queue **pp, *p; | 180 | struct datahandle_queue *p, *tmp; |
181 | unsigned long flags; | ||
177 | 182 | ||
178 | for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { | 183 | spin_lock_irqsave(&mp->ackqlock, flags); |
179 | if ((*pp)->datahandle == datahandle) { | 184 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { |
180 | p = *pp; | 185 | if (p->datahandle == datahandle) { |
181 | *pp = (*pp)->next; | 186 | list_del(&p->list); |
182 | kfree(p); | 187 | kfree(p); |
183 | mp->nack--; | 188 | mp->nack--; |
189 | spin_unlock_irqrestore(&mp->ackqlock, flags); | ||
184 | return 0; | 190 | return 0; |
185 | } | 191 | } |
186 | } | 192 | } |
193 | spin_unlock_irqrestore(&mp->ackqlock, flags); | ||
187 | return -1; | 194 | return -1; |
188 | } | 195 | } |
189 | 196 | ||
190 | static void capiminor_del_all_ack(struct capiminor *mp) | 197 | static void capiminor_del_all_ack(struct capiminor *mp) |
191 | { | 198 | { |
192 | struct datahandle_queue **pp, *p; | 199 | struct datahandle_queue *p, *tmp; |
200 | unsigned long flags; | ||
193 | 201 | ||
194 | pp = &mp->ackqueue; | 202 | spin_lock_irqsave(&mp->ackqlock, flags); |
195 | while (*pp) { | 203 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { |
196 | p = *pp; | 204 | list_del(&p->list); |
197 | *pp = (*pp)->next; | ||
198 | kfree(p); | 205 | kfree(p); |
199 | mp->nack--; | 206 | mp->nack--; |
200 | } | 207 | } |
208 | spin_unlock_irqrestore(&mp->ackqlock, flags); | ||
201 | } | 209 | } |
202 | 210 | ||
203 | 211 | ||
@@ -220,6 +228,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) | |||
220 | mp->ncci = ncci; | 228 | mp->ncci = ncci; |
221 | mp->msgid = 0; | 229 | mp->msgid = 0; |
222 | atomic_set(&mp->ttyopencount,0); | 230 | atomic_set(&mp->ttyopencount,0); |
231 | INIT_LIST_HEAD(&mp->ackqueue); | ||
232 | spin_lock_init(&mp->ackqlock); | ||
223 | 233 | ||
224 | skb_queue_head_init(&mp->inqueue); | 234 | skb_queue_head_init(&mp->inqueue); |
225 | skb_queue_head_init(&mp->outqueue); | 235 | skb_queue_head_init(&mp->outqueue); |
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index f1a1f9a9b88e..1f5ebe9ee72c 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c | |||
@@ -592,7 +592,7 @@ static int put_address(char *st, u_char *p, int len) | |||
592 | } /* put_address */ | 592 | } /* put_address */ |
593 | 593 | ||
594 | /*************************************/ | 594 | /*************************************/ |
595 | /* report a succesfull interrogation */ | 595 | /* report a successful interrogation */ |
596 | /*************************************/ | 596 | /*************************************/ |
597 | static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) | 597 | static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) |
598 | { char *src = ic->parm.dss1_io.data; | 598 | { char *src = ic->parm.dss1_io.data; |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index eb41aba3ddef..8a45715dd4c1 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -65,23 +65,22 @@ static struct usb_device_id gigaset_table [] = { | |||
65 | 65 | ||
66 | MODULE_DEVICE_TABLE(usb, gigaset_table); | 66 | MODULE_DEVICE_TABLE(usb, gigaset_table); |
67 | 67 | ||
68 | /*======================= local function prototypes =============================*/ | 68 | /*======================= local function prototypes ==========================*/ |
69 | 69 | ||
70 | /* This function is called if a new device is connected to the USB port. It | 70 | /* function called if a new device belonging to this driver is connected */ |
71 | * checks whether this new device belongs to this driver. | ||
72 | */ | ||
73 | static int gigaset_probe(struct usb_interface *interface, | 71 | static int gigaset_probe(struct usb_interface *interface, |
74 | const struct usb_device_id *id); | 72 | const struct usb_device_id *id); |
75 | 73 | ||
76 | /* Function will be called if the device is unplugged */ | 74 | /* Function will be called if the device is unplugged */ |
77 | static void gigaset_disconnect(struct usb_interface *interface); | 75 | static void gigaset_disconnect(struct usb_interface *interface); |
78 | 76 | ||
79 | static void read_ctrl_callback(struct urb *, struct pt_regs *); | 77 | static int atread_submit(struct cardstate *, int); |
80 | static void stopurbs(struct bas_bc_state *); | 78 | static void stopurbs(struct bas_bc_state *); |
79 | static int req_submit(struct bc_state *, int, int, int); | ||
81 | static int atwrite_submit(struct cardstate *, unsigned char *, int); | 80 | static int atwrite_submit(struct cardstate *, unsigned char *, int); |
82 | static int start_cbsend(struct cardstate *); | 81 | static int start_cbsend(struct cardstate *); |
83 | 82 | ||
84 | /*==============================================================================*/ | 83 | /*============================================================================*/ |
85 | 84 | ||
86 | struct bas_cardstate { | 85 | struct bas_cardstate { |
87 | struct usb_device *udev; /* USB device pointer */ | 86 | struct usb_device *udev; /* USB device pointer */ |
@@ -91,6 +90,7 @@ struct bas_cardstate { | |||
91 | struct urb *urb_ctrl; /* control pipe default URB */ | 90 | struct urb *urb_ctrl; /* control pipe default URB */ |
92 | struct usb_ctrlrequest dr_ctrl; | 91 | struct usb_ctrlrequest dr_ctrl; |
93 | struct timer_list timer_ctrl; /* control request timeout */ | 92 | struct timer_list timer_ctrl; /* control request timeout */ |
93 | int retry_ctrl; | ||
94 | 94 | ||
95 | struct timer_list timer_atrdy; /* AT command ready timeout */ | 95 | struct timer_list timer_atrdy; /* AT command ready timeout */ |
96 | struct urb *urb_cmd_out; /* for sending AT commands */ | 96 | struct urb *urb_cmd_out; /* for sending AT commands */ |
@@ -307,6 +307,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
307 | * hang up any existing connection because of an unrecoverable error | 307 | * hang up any existing connection because of an unrecoverable error |
308 | * This function may be called from any context and takes care of scheduling | 308 | * This function may be called from any context and takes care of scheduling |
309 | * the necessary actions for execution outside of interrupt context. | 309 | * the necessary actions for execution outside of interrupt context. |
310 | * cs->lock must not be held. | ||
310 | * argument: | 311 | * argument: |
311 | * B channel control structure | 312 | * B channel control structure |
312 | */ | 313 | */ |
@@ -325,14 +326,17 @@ static inline void error_hangup(struct bc_state *bcs) | |||
325 | 326 | ||
326 | /* error_reset | 327 | /* error_reset |
327 | * reset Gigaset device because of an unrecoverable error | 328 | * reset Gigaset device because of an unrecoverable error |
328 | * This function may be called from any context, and should take care of | 329 | * This function may be called from any context, and takes care of |
329 | * scheduling the necessary actions for execution outside of interrupt context. | 330 | * scheduling the necessary actions for execution outside of interrupt context. |
330 | * Right now, it just generates a kernel message calling for help. | 331 | * cs->lock must not be held. |
331 | * argument: | 332 | * argument: |
332 | * controller state structure | 333 | * controller state structure |
333 | */ | 334 | */ |
334 | static inline void error_reset(struct cardstate *cs) | 335 | static inline void error_reset(struct cardstate *cs) |
335 | { | 336 | { |
337 | /* close AT command channel to recover (ignore errors) */ | ||
338 | req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); | ||
339 | |||
336 | //FIXME try to recover without bothering the user | 340 | //FIXME try to recover without bothering the user |
337 | dev_err(cs->dev, | 341 | dev_err(cs->dev, |
338 | "unrecoverable error - please disconnect Gigaset base to reset\n"); | 342 | "unrecoverable error - please disconnect Gigaset base to reset\n"); |
@@ -403,14 +407,30 @@ static void cmd_in_timeout(unsigned long data) | |||
403 | { | 407 | { |
404 | struct cardstate *cs = (struct cardstate *) data; | 408 | struct cardstate *cs = (struct cardstate *) data; |
405 | struct bas_cardstate *ucs = cs->hw.bas; | 409 | struct bas_cardstate *ucs = cs->hw.bas; |
410 | int rc; | ||
406 | 411 | ||
407 | if (!ucs->rcvbuf_size) { | 412 | if (!ucs->rcvbuf_size) { |
408 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); | 413 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); |
409 | return; | 414 | return; |
410 | } | 415 | } |
411 | 416 | ||
412 | dev_err(cs->dev, "timeout reading AT response\n"); | 417 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
413 | error_reset(cs); //FIXME retry? | 418 | dev_notice(cs->dev, "control read: timeout, retry %d\n", |
419 | ucs->retry_cmd_in); | ||
420 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
421 | if (rc >= 0 || rc == -ENODEV) | ||
422 | /* resubmitted or disconnected */ | ||
423 | /* - bypass regular exit block */ | ||
424 | return; | ||
425 | } else { | ||
426 | dev_err(cs->dev, | ||
427 | "control read: timeout, giving up after %d tries\n", | ||
428 | ucs->retry_cmd_in); | ||
429 | } | ||
430 | kfree(ucs->rcvbuf); | ||
431 | ucs->rcvbuf = NULL; | ||
432 | ucs->rcvbuf_size = 0; | ||
433 | error_reset(cs); | ||
414 | } | 434 | } |
415 | 435 | ||
416 | /* set/clear bits in base connection state, return previous state | 436 | /* set/clear bits in base connection state, return previous state |
@@ -428,6 +448,96 @@ inline static int update_basstate(struct bas_cardstate *ucs, | |||
428 | return state; | 448 | return state; |
429 | } | 449 | } |
430 | 450 | ||
451 | /* read_ctrl_callback | ||
452 | * USB completion handler for control pipe input | ||
453 | * called by the USB subsystem in interrupt context | ||
454 | * parameter: | ||
455 | * urb USB request block | ||
456 | * urb->context = inbuf structure for controller state | ||
457 | */ | ||
458 | static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | ||
459 | { | ||
460 | struct inbuf_t *inbuf = urb->context; | ||
461 | struct cardstate *cs = inbuf->cs; | ||
462 | struct bas_cardstate *ucs = cs->hw.bas; | ||
463 | int have_data = 0; | ||
464 | unsigned numbytes; | ||
465 | int rc; | ||
466 | |||
467 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
468 | |||
469 | if (!ucs->rcvbuf_size) { | ||
470 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | del_timer(&ucs->timer_cmd_in); | ||
475 | |||
476 | switch (urb->status) { | ||
477 | case 0: /* normal completion */ | ||
478 | numbytes = urb->actual_length; | ||
479 | if (unlikely(numbytes != ucs->rcvbuf_size)) { | ||
480 | dev_warn(cs->dev, | ||
481 | "control read: received %d chars, expected %d\n", | ||
482 | numbytes, ucs->rcvbuf_size); | ||
483 | if (numbytes > ucs->rcvbuf_size) | ||
484 | numbytes = ucs->rcvbuf_size; | ||
485 | } | ||
486 | |||
487 | /* copy received bytes to inbuf */ | ||
488 | have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); | ||
489 | |||
490 | if (unlikely(numbytes < ucs->rcvbuf_size)) { | ||
491 | /* incomplete - resubmit for remaining bytes */ | ||
492 | ucs->rcvbuf_size -= numbytes; | ||
493 | ucs->retry_cmd_in = 0; | ||
494 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
495 | if (rc >= 0 || rc == -ENODEV) | ||
496 | /* resubmitted or disconnected */ | ||
497 | /* - bypass regular exit block */ | ||
498 | return; | ||
499 | error_reset(cs); | ||
500 | } | ||
501 | break; | ||
502 | |||
503 | case -ENOENT: /* cancelled */ | ||
504 | case -ECONNRESET: /* cancelled (async) */ | ||
505 | case -EINPROGRESS: /* pending */ | ||
506 | case -ENODEV: /* device removed */ | ||
507 | case -ESHUTDOWN: /* device shut down */ | ||
508 | /* no action necessary */ | ||
509 | gig_dbg(DEBUG_USBREQ, "%s: %s", | ||
510 | __func__, get_usb_statmsg(urb->status)); | ||
511 | break; | ||
512 | |||
513 | default: /* severe trouble */ | ||
514 | dev_warn(cs->dev, "control read: %s\n", | ||
515 | get_usb_statmsg(urb->status)); | ||
516 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | ||
517 | dev_notice(cs->dev, "control read: retry %d\n", | ||
518 | ucs->retry_cmd_in); | ||
519 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
520 | if (rc >= 0 || rc == -ENODEV) | ||
521 | /* resubmitted or disconnected */ | ||
522 | /* - bypass regular exit block */ | ||
523 | return; | ||
524 | } else { | ||
525 | dev_err(cs->dev, | ||
526 | "control read: giving up after %d tries\n", | ||
527 | ucs->retry_cmd_in); | ||
528 | } | ||
529 | error_reset(cs); | ||
530 | } | ||
531 | |||
532 | kfree(ucs->rcvbuf); | ||
533 | ucs->rcvbuf = NULL; | ||
534 | ucs->rcvbuf_size = 0; | ||
535 | if (have_data) { | ||
536 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | ||
537 | gigaset_schedule_event(cs); | ||
538 | } | ||
539 | } | ||
540 | |||
431 | /* atread_submit | 541 | /* atread_submit |
432 | * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout | 542 | * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout |
433 | * parameters: | 543 | * parameters: |
@@ -466,7 +576,7 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
466 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { | 576 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { |
467 | update_basstate(ucs, 0, BS_ATRDPEND); | 577 | update_basstate(ucs, 0, BS_ATRDPEND); |
468 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", | 578 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", |
469 | get_usb_statmsg(ret)); | 579 | get_usb_rcmsg(ret)); |
470 | return ret; | 580 | return ret; |
471 | } | 581 | } |
472 | 582 | ||
@@ -611,9 +721,12 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
611 | kfree(ucs->rcvbuf); | 721 | kfree(ucs->rcvbuf); |
612 | ucs->rcvbuf = NULL; | 722 | ucs->rcvbuf = NULL; |
613 | ucs->rcvbuf_size = 0; | 723 | ucs->rcvbuf_size = 0; |
614 | if (rc != -ENODEV) | 724 | if (rc != -ENODEV) { |
615 | //FIXME corrective action? | 725 | //FIXME corrective action? |
726 | spin_unlock_irqrestore(&cs->lock, flags); | ||
616 | error_reset(cs); | 727 | error_reset(cs); |
728 | break; | ||
729 | } | ||
617 | } | 730 | } |
618 | spin_unlock_irqrestore(&cs->lock, flags); | 731 | spin_unlock_irqrestore(&cs->lock, flags); |
619 | break; | 732 | break; |
@@ -643,97 +756,6 @@ resubmit: | |||
643 | } | 756 | } |
644 | } | 757 | } |
645 | 758 | ||
646 | /* read_ctrl_callback | ||
647 | * USB completion handler for control pipe input | ||
648 | * called by the USB subsystem in interrupt context | ||
649 | * parameter: | ||
650 | * urb USB request block | ||
651 | * urb->context = inbuf structure for controller state | ||
652 | */ | ||
653 | static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | ||
654 | { | ||
655 | struct inbuf_t *inbuf = urb->context; | ||
656 | struct cardstate *cs = inbuf->cs; | ||
657 | struct bas_cardstate *ucs = cs->hw.bas; | ||
658 | int have_data = 0; | ||
659 | unsigned numbytes; | ||
660 | int rc; | ||
661 | |||
662 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
663 | |||
664 | if (!ucs->rcvbuf_size) { | ||
665 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | ||
666 | return; | ||
667 | } | ||
668 | |||
669 | del_timer(&ucs->timer_cmd_in); | ||
670 | |||
671 | switch (urb->status) { | ||
672 | case 0: /* normal completion */ | ||
673 | numbytes = urb->actual_length; | ||
674 | if (unlikely(numbytes == 0)) { | ||
675 | dev_warn(cs->dev, | ||
676 | "control read: empty block received\n"); | ||
677 | goto retry; | ||
678 | } | ||
679 | if (unlikely(numbytes != ucs->rcvbuf_size)) { | ||
680 | dev_warn(cs->dev, | ||
681 | "control read: received %d chars, expected %d\n", | ||
682 | numbytes, ucs->rcvbuf_size); | ||
683 | if (numbytes > ucs->rcvbuf_size) | ||
684 | numbytes = ucs->rcvbuf_size; | ||
685 | } | ||
686 | |||
687 | /* copy received bytes to inbuf */ | ||
688 | have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); | ||
689 | |||
690 | if (unlikely(numbytes < ucs->rcvbuf_size)) { | ||
691 | /* incomplete - resubmit for remaining bytes */ | ||
692 | ucs->rcvbuf_size -= numbytes; | ||
693 | ucs->retry_cmd_in = 0; | ||
694 | goto retry; | ||
695 | } | ||
696 | break; | ||
697 | |||
698 | case -ENOENT: /* cancelled */ | ||
699 | case -ECONNRESET: /* cancelled (async) */ | ||
700 | case -EINPROGRESS: /* pending */ | ||
701 | case -ENODEV: /* device removed */ | ||
702 | case -ESHUTDOWN: /* device shut down */ | ||
703 | /* no action necessary */ | ||
704 | gig_dbg(DEBUG_USBREQ, "%s: %s", | ||
705 | __func__, get_usb_statmsg(urb->status)); | ||
706 | break; | ||
707 | |||
708 | default: /* severe trouble */ | ||
709 | dev_warn(cs->dev, "control read: %s\n", | ||
710 | get_usb_statmsg(urb->status)); | ||
711 | retry: | ||
712 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | ||
713 | dev_notice(cs->dev, "control read: retry %d\n", | ||
714 | ucs->retry_cmd_in); | ||
715 | rc = atread_submit(cs, BAS_TIMEOUT); | ||
716 | if (rc >= 0 || rc == -ENODEV) | ||
717 | /* resubmitted or disconnected */ | ||
718 | /* - bypass regular exit block */ | ||
719 | return; | ||
720 | } else { | ||
721 | dev_err(cs->dev, | ||
722 | "control read: giving up after %d tries\n", | ||
723 | ucs->retry_cmd_in); | ||
724 | } | ||
725 | error_reset(cs); | ||
726 | } | ||
727 | |||
728 | kfree(ucs->rcvbuf); | ||
729 | ucs->rcvbuf = NULL; | ||
730 | ucs->rcvbuf_size = 0; | ||
731 | if (have_data) { | ||
732 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | ||
733 | gigaset_schedule_event(cs); | ||
734 | } | ||
735 | } | ||
736 | |||
737 | /* read_iso_callback | 759 | /* read_iso_callback |
738 | * USB completion handler for B channel isochronous input | 760 | * USB completion handler for B channel isochronous input |
739 | * called by the USB subsystem in interrupt context | 761 | * called by the USB subsystem in interrupt context |
@@ -1378,6 +1400,7 @@ static void req_timeout(unsigned long data) | |||
1378 | case HD_CLOSE_B1CHANNEL: | 1400 | case HD_CLOSE_B1CHANNEL: |
1379 | dev_err(bcs->cs->dev, "timeout closing channel %d\n", | 1401 | dev_err(bcs->cs->dev, "timeout closing channel %d\n", |
1380 | bcs->channel + 1); | 1402 | bcs->channel + 1); |
1403 | error_reset(bcs->cs); | ||
1381 | break; | 1404 | break; |
1382 | 1405 | ||
1383 | default: | 1406 | default: |
@@ -1396,22 +1419,61 @@ static void req_timeout(unsigned long data) | |||
1396 | static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) | 1419 | static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) |
1397 | { | 1420 | { |
1398 | struct bas_cardstate *ucs = urb->context; | 1421 | struct bas_cardstate *ucs = urb->context; |
1422 | int rc; | ||
1399 | unsigned long flags; | 1423 | unsigned long flags; |
1400 | 1424 | ||
1401 | spin_lock_irqsave(&ucs->lock, flags); | 1425 | /* check status */ |
1402 | if (urb->status && ucs->pending) { | 1426 | switch (urb->status) { |
1403 | dev_err(&ucs->interface->dev, | 1427 | case 0: /* normal completion */ |
1404 | "control request 0x%02x failed: %s\n", | 1428 | spin_lock_irqsave(&ucs->lock, flags); |
1405 | ucs->pending, get_usb_statmsg(urb->status)); | 1429 | switch (ucs->pending) { |
1406 | del_timer(&ucs->timer_ctrl); | 1430 | case HD_DEVICE_INIT_ACK: /* no reply expected */ |
1407 | ucs->pending = 0; | 1431 | del_timer(&ucs->timer_ctrl); |
1408 | } | 1432 | ucs->pending = 0; |
1409 | /* individual handling of specific request types */ | 1433 | break; |
1410 | switch (ucs->pending) { | 1434 | } |
1411 | case HD_DEVICE_INIT_ACK: /* no reply expected */ | 1435 | spin_unlock_irqrestore(&ucs->lock, flags); |
1412 | ucs->pending = 0; | 1436 | return; |
1437 | |||
1438 | case -ENOENT: /* cancelled */ | ||
1439 | case -ECONNRESET: /* cancelled (async) */ | ||
1440 | case -EINPROGRESS: /* pending */ | ||
1441 | case -ENODEV: /* device removed */ | ||
1442 | case -ESHUTDOWN: /* device shut down */ | ||
1443 | /* ignore silently */ | ||
1444 | gig_dbg(DEBUG_USBREQ, "%s: %s", | ||
1445 | __func__, get_usb_statmsg(urb->status)); | ||
1413 | break; | 1446 | break; |
1447 | |||
1448 | default: /* any failure */ | ||
1449 | if (++ucs->retry_ctrl > BAS_RETRY) { | ||
1450 | dev_err(&ucs->interface->dev, | ||
1451 | "control request 0x%02x failed: %s\n", | ||
1452 | ucs->dr_ctrl.bRequest, | ||
1453 | get_usb_statmsg(urb->status)); | ||
1454 | break; /* give up */ | ||
1455 | } | ||
1456 | dev_notice(&ucs->interface->dev, | ||
1457 | "control request 0x%02x: %s, retry %d\n", | ||
1458 | ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), | ||
1459 | ucs->retry_ctrl); | ||
1460 | /* urb->dev is clobbered by USB subsystem */ | ||
1461 | urb->dev = ucs->udev; | ||
1462 | rc = usb_submit_urb(urb, SLAB_ATOMIC); | ||
1463 | if (unlikely(rc)) { | ||
1464 | dev_err(&ucs->interface->dev, | ||
1465 | "could not resubmit request 0x%02x: %s\n", | ||
1466 | ucs->dr_ctrl.bRequest, get_usb_rcmsg(rc)); | ||
1467 | break; | ||
1468 | } | ||
1469 | /* resubmitted */ | ||
1470 | return; | ||
1414 | } | 1471 | } |
1472 | |||
1473 | /* failed, clear pending request */ | ||
1474 | spin_lock_irqsave(&ucs->lock, flags); | ||
1475 | del_timer(&ucs->timer_ctrl); | ||
1476 | ucs->pending = 0; | ||
1415 | spin_unlock_irqrestore(&ucs->lock, flags); | 1477 | spin_unlock_irqrestore(&ucs->lock, flags); |
1416 | } | 1478 | } |
1417 | 1479 | ||
@@ -1455,9 +1517,11 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1455 | usb_sndctrlpipe(ucs->udev, 0), | 1517 | usb_sndctrlpipe(ucs->udev, 0), |
1456 | (unsigned char*) &ucs->dr_ctrl, NULL, 0, | 1518 | (unsigned char*) &ucs->dr_ctrl, NULL, 0, |
1457 | write_ctrl_callback, ucs); | 1519 | write_ctrl_callback, ucs); |
1458 | if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) { | 1520 | ucs->retry_ctrl = 0; |
1521 | ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC); | ||
1522 | if (unlikely(ret)) { | ||
1459 | dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", | 1523 | dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", |
1460 | req, get_usb_statmsg(ret)); | 1524 | req, get_usb_rcmsg(ret)); |
1461 | spin_unlock_irqrestore(&ucs->lock, flags); | 1525 | spin_unlock_irqrestore(&ucs->lock, flags); |
1462 | return ret; | 1526 | return ret; |
1463 | } | 1527 | } |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index acb7e2656780..2a56bf33a673 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -981,7 +981,7 @@ exit: | |||
981 | EXPORT_SYMBOL_GPL(gigaset_stop); | 981 | EXPORT_SYMBOL_GPL(gigaset_stop); |
982 | 982 | ||
983 | static LIST_HEAD(drivers); | 983 | static LIST_HEAD(drivers); |
984 | static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; | 984 | static DEFINE_SPINLOCK(driver_lock); |
985 | 985 | ||
986 | struct cardstate *gigaset_get_cs_by_id(int id) | 986 | struct cardstate *gigaset_get_cs_by_id(int id) |
987 | { | 987 | { |
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 18e05c09b71c..44f02dbd1111 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -1262,7 +1262,8 @@ static void do_action(int action, struct cardstate *cs, | |||
1262 | break; | 1262 | break; |
1263 | case ACT_HUPMODEM: | 1263 | case ACT_HUPMODEM: |
1264 | /* send "+++" (hangup in unimodem mode) */ | 1264 | /* send "+++" (hangup in unimodem mode) */ |
1265 | cs->ops->write_cmd(cs, "+++", 3, NULL); | 1265 | if (cs->connected) |
1266 | cs->ops->write_cmd(cs, "+++", 3, NULL); | ||
1266 | break; | 1267 | break; |
1267 | case ACT_RING: | 1268 | case ACT_RING: |
1268 | /* get fresh AT state structure for new CID */ | 1269 | /* get fresh AT state structure for new CID */ |
@@ -1294,7 +1295,6 @@ static void do_action(int action, struct cardstate *cs, | |||
1294 | break; | 1295 | break; |
1295 | case ACT_ICALL: | 1296 | case ACT_ICALL: |
1296 | handle_icall(cs, bcs, p_at_state); | 1297 | handle_icall(cs, bcs, p_at_state); |
1297 | at_state = *p_at_state; | ||
1298 | break; | 1298 | break; |
1299 | case ACT_FAILSDOWN: | 1299 | case ACT_FAILSDOWN: |
1300 | dev_warn(cs->dev, "Could not shut down the device.\n"); | 1300 | dev_warn(cs->dev, "Could not shut down the device.\n"); |
@@ -1334,10 +1334,8 @@ static void do_action(int action, struct cardstate *cs, | |||
1334 | */ | 1334 | */ |
1335 | at_state->pending_commands |= PC_DLE0; | 1335 | at_state->pending_commands |= PC_DLE0; |
1336 | atomic_set(&cs->commands_pending, 1); | 1336 | atomic_set(&cs->commands_pending, 1); |
1337 | } else { | 1337 | } else |
1338 | disconnect(p_at_state); | 1338 | disconnect(p_at_state); |
1339 | at_state = *p_at_state; | ||
1340 | } | ||
1341 | break; | 1339 | break; |
1342 | case ACT_FAKEDLE0: | 1340 | case ACT_FAKEDLE0: |
1343 | at_state->int_var[VAR_ZDLE] = 0; | 1341 | at_state->int_var[VAR_ZDLE] = 0; |
@@ -1354,10 +1352,8 @@ static void do_action(int action, struct cardstate *cs, | |||
1354 | at_state->cid = -1; | 1352 | at_state->cid = -1; |
1355 | if (bcs && cs->onechannel) | 1353 | if (bcs && cs->onechannel) |
1356 | at_state->pending_commands |= PC_DLE0; | 1354 | at_state->pending_commands |= PC_DLE0; |
1357 | else { | 1355 | else |
1358 | disconnect(p_at_state); | 1356 | disconnect(p_at_state); |
1359 | at_state = *p_at_state; | ||
1360 | } | ||
1361 | schedule_init(cs, MS_RECOVER); | 1357 | schedule_init(cs, MS_RECOVER); |
1362 | break; | 1358 | break; |
1363 | case ACT_FAILDLE0: | 1359 | case ACT_FAILDLE0: |
@@ -1410,7 +1406,6 @@ static void do_action(int action, struct cardstate *cs, | |||
1410 | 1406 | ||
1411 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ | 1407 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ |
1412 | disconnect(p_at_state); | 1408 | disconnect(p_at_state); |
1413 | at_state = *p_at_state; | ||
1414 | break; | 1409 | break; |
1415 | 1410 | ||
1416 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ | 1411 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ |
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index abecabf8c271..aacbf0d14b64 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c | |||
@@ -1402,12 +1402,12 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) | |||
1402 | } | 1402 | } |
1403 | /* No, locate it in the table */ | 1403 | /* No, locate it in the table */ |
1404 | if (cset == 0) { | 1404 | if (cset == 0) { |
1405 | for (i = 0; i < IESIZE; i++) | 1405 | for (i = 0; i < IESIZE_NI1; i++) |
1406 | if (*buf == ielist_ni1[i].nr) | 1406 | if (*buf == ielist_ni1[i].nr) |
1407 | break; | 1407 | break; |
1408 | 1408 | ||
1409 | /* When not found, give appropriate msg */ | 1409 | /* When not found, give appropriate msg */ |
1410 | if (i != IESIZE) { | 1410 | if (i != IESIZE_NI1) { |
1411 | dp += sprintf(dp, " %s\n", ielist_ni1[i].descr); | 1411 | dp += sprintf(dp, " %s\n", ielist_ni1[i].descr); |
1412 | dp += ielist_ni1[i].f(dp, buf); | 1412 | dp += ielist_ni1[i].f(dp, buf); |
1413 | } else | 1413 | } else |
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 81accdf35168..b26e509ec759 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c | |||
@@ -933,7 +933,7 @@ isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack) | |||
933 | count_put = count_pull; | 933 | count_put = count_pull; |
934 | if(count_put > 1) | 934 | if(count_put > 1) |
935 | tty_insert_flip_string(tty, skb->data, count_put - 1); | 935 | tty_insert_flip_string(tty, skb->data, count_put - 1); |
936 | last = skb->data[count_put] - 1; | 936 | last = skb->data[count_put - 1]; |
937 | len -= count_put; | 937 | len -= count_put; |
938 | #ifdef CONFIG_ISDN_AUDIO | 938 | #ifdef CONFIG_ISDN_AUDIO |
939 | } | 939 | } |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2ac90242d263..433389daedb2 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -82,7 +82,7 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb) | |||
82 | int l = skb->len; | 82 | int l = skb->len; |
83 | unsigned char *dp = skb->data; | 83 | unsigned char *dp = skb->data; |
84 | while (--l) { | 84 | while (--l) { |
85 | if (*skb->data == DLE) | 85 | if (*dp == DLE) |
86 | tty_insert_flip_char(tty, DLE, 0); | 86 | tty_insert_flip_char(tty, DLE, 0); |
87 | tty_insert_flip_char(tty, *dp++, 0); | 87 | tty_insert_flip_char(tty, *dp++, 0); |
88 | } | 88 | } |