diff options
Diffstat (limited to 'drivers/isdn/isdnloop/isdnloop.c')
-rw-r--r-- | drivers/isdn/isdnloop/isdnloop.c | 73 |
1 files changed, 32 insertions, 41 deletions
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index fabbd461603e..c3ae2edaf6fa 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c | |||
@@ -100,12 +100,11 @@ isdnloop_pollbchan(unsigned long data) | |||
100 | isdnloop_bchan_send(card, 1); | 100 | isdnloop_bchan_send(card, 1); |
101 | if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) { | 101 | if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) { |
102 | /* schedule b-channel polling again */ | 102 | /* schedule b-channel polling again */ |
103 | save_flags(flags); | 103 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
104 | cli(); | ||
105 | card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; | 104 | card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; |
106 | add_timer(&card->rb_timer); | 105 | add_timer(&card->rb_timer); |
107 | card->flags |= ISDNLOOP_FLAGS_RBTIMER; | 106 | card->flags |= ISDNLOOP_FLAGS_RBTIMER; |
108 | restore_flags(flags); | 107 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
109 | } else | 108 | } else |
110 | card->flags &= ~ISDNLOOP_FLAGS_RBTIMER; | 109 | card->flags &= ~ISDNLOOP_FLAGS_RBTIMER; |
111 | } | 110 | } |
@@ -281,8 +280,7 @@ isdnloop_putmsg(isdnloop_card * card, unsigned char c) | |||
281 | { | 280 | { |
282 | ulong flags; | 281 | ulong flags; |
283 | 282 | ||
284 | save_flags(flags); | 283 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
285 | cli(); | ||
286 | *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; | 284 | *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; |
287 | if (card->msg_buf_write == card->msg_buf_read) { | 285 | if (card->msg_buf_write == card->msg_buf_read) { |
288 | if (++card->msg_buf_read > card->msg_buf_end) | 286 | if (++card->msg_buf_read > card->msg_buf_end) |
@@ -290,7 +288,7 @@ isdnloop_putmsg(isdnloop_card * card, unsigned char c) | |||
290 | } | 288 | } |
291 | if (card->msg_buf_write > card->msg_buf_end) | 289 | if (card->msg_buf_write > card->msg_buf_end) |
292 | card->msg_buf_write = card->msg_buf; | 290 | card->msg_buf_write = card->msg_buf; |
293 | restore_flags(flags); | 291 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
294 | } | 292 | } |
295 | 293 | ||
296 | /* | 294 | /* |
@@ -372,21 +370,19 @@ isdnloop_polldchan(unsigned long data) | |||
372 | if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { | 370 | if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { |
373 | /* schedule b-channel polling */ | 371 | /* schedule b-channel polling */ |
374 | card->flags |= ISDNLOOP_FLAGS_RBTIMER; | 372 | card->flags |= ISDNLOOP_FLAGS_RBTIMER; |
375 | save_flags(flags); | 373 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
376 | cli(); | ||
377 | del_timer(&card->rb_timer); | 374 | del_timer(&card->rb_timer); |
378 | card->rb_timer.function = isdnloop_pollbchan; | 375 | card->rb_timer.function = isdnloop_pollbchan; |
379 | card->rb_timer.data = (unsigned long) card; | 376 | card->rb_timer.data = (unsigned long) card; |
380 | card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; | 377 | card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; |
381 | add_timer(&card->rb_timer); | 378 | add_timer(&card->rb_timer); |
382 | restore_flags(flags); | 379 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
383 | } | 380 | } |
384 | /* schedule again */ | 381 | /* schedule again */ |
385 | save_flags(flags); | 382 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
386 | cli(); | ||
387 | card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; | 383 | card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; |
388 | add_timer(&card->st_timer); | 384 | add_timer(&card->st_timer); |
389 | restore_flags(flags); | 385 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
390 | } | 386 | } |
391 | 387 | ||
392 | /* | 388 | /* |
@@ -416,8 +412,7 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card) | |||
416 | return 0; | 412 | return 0; |
417 | if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE) | 413 | if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE) |
418 | return 0; | 414 | return 0; |
419 | save_flags(flags); | 415 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
420 | cli(); | ||
421 | nskb = dev_alloc_skb(skb->len); | 416 | nskb = dev_alloc_skb(skb->len); |
422 | if (nskb) { | 417 | if (nskb) { |
423 | memcpy(skb_put(nskb, len), skb->data, len); | 418 | memcpy(skb_put(nskb, len), skb->data, len); |
@@ -426,7 +421,7 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card) | |||
426 | } else | 421 | } else |
427 | len = 0; | 422 | len = 0; |
428 | card->sndcount[channel] += len; | 423 | card->sndcount[channel] += len; |
429 | restore_flags(flags); | 424 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
430 | } | 425 | } |
431 | return len; | 426 | return len; |
432 | } | 427 | } |
@@ -451,7 +446,8 @@ isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card * card) | |||
451 | for (p = buf, count = 0; count < len; p++, count++) { | 446 | for (p = buf, count = 0; count < len; p++, count++) { |
452 | if (card->msg_buf_read == card->msg_buf_write) | 447 | if (card->msg_buf_read == card->msg_buf_write) |
453 | return count; | 448 | return count; |
454 | put_user(*card->msg_buf_read++, p); | 449 | if (put_user(*card->msg_buf_read++, p)) |
450 | return -EFAULT; | ||
455 | if (card->msg_buf_read > card->msg_buf_end) | 451 | if (card->msg_buf_read > card->msg_buf_end) |
456 | card->msg_buf_read = card->msg_buf; | 452 | card->msg_buf_read = card->msg_buf; |
457 | } | 453 | } |
@@ -576,8 +572,7 @@ isdnloop_atimeout(isdnloop_card * card, int ch) | |||
576 | unsigned long flags; | 572 | unsigned long flags; |
577 | char buf[60]; | 573 | char buf[60]; |
578 | 574 | ||
579 | save_flags(flags); | 575 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
580 | cli(); | ||
581 | if (card->rcard) { | 576 | if (card->rcard) { |
582 | isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1); | 577 | isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1); |
583 | card->rcard[ch]->rcard[card->rch[ch]] = NULL; | 578 | card->rcard[ch]->rcard[card->rch[ch]] = NULL; |
@@ -587,7 +582,7 @@ isdnloop_atimeout(isdnloop_card * card, int ch) | |||
587 | /* No user responding */ | 582 | /* No user responding */ |
588 | sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3)); | 583 | sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3)); |
589 | isdnloop_fake(card, buf, ch + 1); | 584 | isdnloop_fake(card, buf, ch + 1); |
590 | restore_flags(flags); | 585 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
591 | } | 586 | } |
592 | 587 | ||
593 | /* | 588 | /* |
@@ -622,8 +617,7 @@ isdnloop_start_ctimer(isdnloop_card * card, int ch) | |||
622 | { | 617 | { |
623 | unsigned long flags; | 618 | unsigned long flags; |
624 | 619 | ||
625 | save_flags(flags); | 620 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
626 | cli(); | ||
627 | init_timer(&card->c_timer[ch]); | 621 | init_timer(&card->c_timer[ch]); |
628 | card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; | 622 | card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; |
629 | if (ch) | 623 | if (ch) |
@@ -632,7 +626,7 @@ isdnloop_start_ctimer(isdnloop_card * card, int ch) | |||
632 | card->c_timer[ch].function = isdnloop_atimeout0; | 626 | card->c_timer[ch].function = isdnloop_atimeout0; |
633 | card->c_timer[ch].data = (unsigned long) card; | 627 | card->c_timer[ch].data = (unsigned long) card; |
634 | add_timer(&card->c_timer[ch]); | 628 | add_timer(&card->c_timer[ch]); |
635 | restore_flags(flags); | 629 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
636 | } | 630 | } |
637 | 631 | ||
638 | /* | 632 | /* |
@@ -647,10 +641,9 @@ isdnloop_kill_ctimer(isdnloop_card * card, int ch) | |||
647 | { | 641 | { |
648 | unsigned long flags; | 642 | unsigned long flags; |
649 | 643 | ||
650 | save_flags(flags); | 644 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
651 | cli(); | ||
652 | del_timer(&card->c_timer[ch]); | 645 | del_timer(&card->c_timer[ch]); |
653 | restore_flags(flags); | 646 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
654 | } | 647 | } |
655 | 648 | ||
656 | static u_char si2bit[] = | 649 | static u_char si2bit[] = |
@@ -706,13 +699,12 @@ isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) | |||
706 | } | 699 | } |
707 | } | 700 | } |
708 | if (num_match) { | 701 | if (num_match) { |
709 | save_flags(flags); | 702 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
710 | cli(); | ||
711 | /* channel idle? */ | 703 | /* channel idle? */ |
712 | if (!(cc->rcard[ch])) { | 704 | if (!(cc->rcard[ch])) { |
713 | /* Check SI */ | 705 | /* Check SI */ |
714 | if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { | 706 | if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { |
715 | restore_flags(flags); | 707 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
716 | return 3; | 708 | return 3; |
717 | } | 709 | } |
718 | /* ch is idle, si and number matches */ | 710 | /* ch is idle, si and number matches */ |
@@ -720,10 +712,10 @@ isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) | |||
720 | cc->rch[ch] = lch; | 712 | cc->rch[ch] = lch; |
721 | card->rcard[lch] = cc; | 713 | card->rcard[lch] = cc; |
722 | card->rch[lch] = ch; | 714 | card->rch[lch] = ch; |
723 | restore_flags(flags); | 715 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
724 | return 0; | 716 | return 0; |
725 | } else { | 717 | } else { |
726 | restore_flags(flags); | 718 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
727 | /* num matches, but busy */ | 719 | /* num matches, but busy */ |
728 | if (ch == 1) | 720 | if (ch == 1) |
729 | return 1; | 721 | return 1; |
@@ -1027,8 +1019,7 @@ isdnloop_stopcard(isdnloop_card * card) | |||
1027 | unsigned long flags; | 1019 | unsigned long flags; |
1028 | isdn_ctrl cmd; | 1020 | isdn_ctrl cmd; |
1029 | 1021 | ||
1030 | save_flags(flags); | 1022 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
1031 | cli(); | ||
1032 | if (card->flags & ISDNLOOP_FLAGS_RUNNING) { | 1023 | if (card->flags & ISDNLOOP_FLAGS_RUNNING) { |
1033 | card->flags &= ~ISDNLOOP_FLAGS_RUNNING; | 1024 | card->flags &= ~ISDNLOOP_FLAGS_RUNNING; |
1034 | del_timer(&card->st_timer); | 1025 | del_timer(&card->st_timer); |
@@ -1039,7 +1030,7 @@ isdnloop_stopcard(isdnloop_card * card) | |||
1039 | cmd.driver = card->myid; | 1030 | cmd.driver = card->myid; |
1040 | card->interface.statcallb(&cmd); | 1031 | card->interface.statcallb(&cmd); |
1041 | } | 1032 | } |
1042 | restore_flags(flags); | 1033 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1043 | } | 1034 | } |
1044 | 1035 | ||
1045 | /* | 1036 | /* |
@@ -1078,18 +1069,17 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) | |||
1078 | return -EBUSY; | 1069 | return -EBUSY; |
1079 | if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef))) | 1070 | if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef))) |
1080 | return -EFAULT; | 1071 | return -EFAULT; |
1081 | save_flags(flags); | 1072 | spin_lock_irqsave(&card->isdnloop_lock, flags); |
1082 | cli(); | ||
1083 | switch (sdef.ptype) { | 1073 | switch (sdef.ptype) { |
1084 | case ISDN_PTYPE_EURO: | 1074 | case ISDN_PTYPE_EURO: |
1085 | if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96", | 1075 | if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96", |
1086 | -1)) { | 1076 | -1)) { |
1087 | restore_flags(flags); | 1077 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1088 | return -ENOMEM; | 1078 | return -ENOMEM; |
1089 | } | 1079 | } |
1090 | card->sil[0] = card->sil[1] = 4; | 1080 | card->sil[0] = card->sil[1] = 4; |
1091 | if (isdnloop_fake(card, "TEI OK", 0)) { | 1081 | if (isdnloop_fake(card, "TEI OK", 0)) { |
1092 | restore_flags(flags); | 1082 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1093 | return -ENOMEM; | 1083 | return -ENOMEM; |
1094 | } | 1084 | } |
1095 | for (i = 0; i < 3; i++) | 1085 | for (i = 0; i < 3; i++) |
@@ -1098,12 +1088,12 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) | |||
1098 | case ISDN_PTYPE_1TR6: | 1088 | case ISDN_PTYPE_1TR6: |
1099 | if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", | 1089 | if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", |
1100 | -1)) { | 1090 | -1)) { |
1101 | restore_flags(flags); | 1091 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1102 | return -ENOMEM; | 1092 | return -ENOMEM; |
1103 | } | 1093 | } |
1104 | card->sil[0] = card->sil[1] = 4; | 1094 | card->sil[0] = card->sil[1] = 4; |
1105 | if (isdnloop_fake(card, "TEI OK", 0)) { | 1095 | if (isdnloop_fake(card, "TEI OK", 0)) { |
1106 | restore_flags(flags); | 1096 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1107 | return -ENOMEM; | 1097 | return -ENOMEM; |
1108 | } | 1098 | } |
1109 | strcpy(card->s0num[0], sdef.num[0]); | 1099 | strcpy(card->s0num[0], sdef.num[0]); |
@@ -1111,7 +1101,7 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) | |||
1111 | card->s0num[2][0] = '\0'; | 1101 | card->s0num[2][0] = '\0'; |
1112 | break; | 1102 | break; |
1113 | default: | 1103 | default: |
1114 | restore_flags(flags); | 1104 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1115 | printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n", | 1105 | printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n", |
1116 | sdef.ptype); | 1106 | sdef.ptype); |
1117 | return -EINVAL; | 1107 | return -EINVAL; |
@@ -1122,7 +1112,7 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) | |||
1122 | card->st_timer.data = (unsigned long) card; | 1112 | card->st_timer.data = (unsigned long) card; |
1123 | add_timer(&card->st_timer); | 1113 | add_timer(&card->st_timer); |
1124 | card->flags |= ISDNLOOP_FLAGS_RUNNING; | 1114 | card->flags |= ISDNLOOP_FLAGS_RUNNING; |
1125 | restore_flags(flags); | 1115 | spin_unlock_irqrestore(&card->isdnloop_lock, flags); |
1126 | return 0; | 1116 | return 0; |
1127 | } | 1117 | } |
1128 | 1118 | ||
@@ -1472,6 +1462,7 @@ isdnloop_initcard(char *id) | |||
1472 | skb_queue_head_init(&card->bqueue[i]); | 1462 | skb_queue_head_init(&card->bqueue[i]); |
1473 | } | 1463 | } |
1474 | skb_queue_head_init(&card->dqueue); | 1464 | skb_queue_head_init(&card->dqueue); |
1465 | card->isdnloop_lock = SPIN_LOCK_UNLOCKED; | ||
1475 | card->next = cards; | 1466 | card->next = cards; |
1476 | cards = card; | 1467 | cards = card; |
1477 | if (!register_isdn(&card->interface)) { | 1468 | if (!register_isdn(&card->interface)) { |