aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/isdn/gigaset/capi.c225
-rw-r--r--drivers/isdn/gigaset/common.c4
-rw-r--r--drivers/isdn/gigaset/gigaset.h4
3 files changed, 180 insertions, 53 deletions
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 665673f4d667..6fbe8999c419 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -70,7 +70,7 @@
70#define MAX_NUMBER_DIGITS 20 70#define MAX_NUMBER_DIGITS 20
71#define MAX_FMT_IE_LEN 20 71#define MAX_FMT_IE_LEN 20
72 72
73/* values for gigaset_capi_appl.connected */ 73/* values for bcs->apconnstate */
74#define APCONN_NONE 0 /* inactive/listening */ 74#define APCONN_NONE 0 /* inactive/listening */
75#define APCONN_SETUP 1 /* connecting */ 75#define APCONN_SETUP 1 /* connecting */
76#define APCONN_ACTIVE 2 /* B channel up */ 76#define APCONN_ACTIVE 2 /* B channel up */
@@ -84,7 +84,6 @@ struct gigaset_capi_appl {
84 u16 nextMessageNumber; 84 u16 nextMessageNumber;
85 u32 listenInfoMask; 85 u32 listenInfoMask;
86 u32 listenCIPmask; 86 u32 listenCIPmask;
87 int connected;
88}; 87};
89 88
90/* CAPI specific controller data structure */ 89/* CAPI specific controller data structure */
@@ -384,7 +383,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
384 } 383 }
385 384
386 /* don't send further B3 messages if disconnected */ 385 /* don't send further B3 messages if disconnected */
387 if (ap->connected < APCONN_ACTIVE) { 386 if (bcs->apconnstate < APCONN_ACTIVE) {
388 gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); 387 gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
389 return; 388 return;
390 } 389 }
@@ -428,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
428 } 427 }
429 428
430 /* don't send further B3 messages if disconnected */ 429 /* don't send further B3 messages if disconnected */
431 if (ap->connected < APCONN_ACTIVE) { 430 if (bcs->apconnstate < APCONN_ACTIVE) {
432 gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); 431 gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
433 dev_kfree_skb_any(skb); 432 dev_kfree_skb_any(skb);
434 return; 433 return;
@@ -500,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
500 u32 actCIPmask; 499 u32 actCIPmask;
501 struct sk_buff *skb; 500 struct sk_buff *skb;
502 unsigned int msgsize; 501 unsigned int msgsize;
502 unsigned long flags;
503 int i; 503 int i;
504 504
505 /* 505 /*
@@ -624,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
624 format_ie(iif->hcmsg.CalledPartyNumber)); 624 format_ie(iif->hcmsg.CalledPartyNumber));
625 625
626 /* scan application list for matching listeners */ 626 /* scan application list for matching listeners */
627 bcs->ap = NULL; 627 spin_lock_irqsave(&bcs->aplock, flags);
628 if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
629 dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
630 __func__, bcs->ap, bcs->apconnstate);
631 bcs->ap = NULL;
632 bcs->apconnstate = APCONN_NONE;
633 }
634 spin_unlock_irqrestore(&bcs->aplock, flags);
628 actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); 635 actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
629 list_for_each_entry(ap, &iif->appls, ctrlist) 636 list_for_each_entry(ap, &iif->appls, ctrlist)
630 if (actCIPmask & ap->listenCIPmask) { 637 if (actCIPmask & ap->listenCIPmask) {
@@ -642,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
642 dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); 649 dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
643 650
644 /* add to listeners on this B channel, update state */ 651 /* add to listeners on this B channel, update state */
652 spin_lock_irqsave(&bcs->aplock, flags);
645 ap->bcnext = bcs->ap; 653 ap->bcnext = bcs->ap;
646 bcs->ap = ap; 654 bcs->ap = ap;
647 bcs->chstate |= CHS_NOTIFY_LL; 655 bcs->chstate |= CHS_NOTIFY_LL;
648 ap->connected = APCONN_SETUP; 656 bcs->apconnstate = APCONN_SETUP;
657 spin_unlock_irqrestore(&bcs->aplock, flags);
649 658
650 /* emit message */ 659 /* emit message */
651 capi_ctr_handle_message(&iif->ctr, ap->id, skb); 660 capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -670,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,
670 struct gigaset_capi_ctr *iif = cs->iif; 679 struct gigaset_capi_ctr *iif = cs->iif;
671 struct sk_buff *skb; 680 struct sk_buff *skb;
672 681
673 if (ap->connected == APCONN_NONE) 682 if (bcs->apconnstate == APCONN_NONE)
674 return; 683 return;
675 684
676 capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, 685 capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -684,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,
684 } 693 }
685 capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); 694 capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
686 dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); 695 dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
687 ap->connected = APCONN_NONE;
688 capi_ctr_handle_message(&iif->ctr, ap->id, skb); 696 capi_ctr_handle_message(&iif->ctr, ap->id, skb);
689} 697}
690 698
@@ -701,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
701 struct sk_buff *skb; 709 struct sk_buff *skb;
702 710
703 /* nothing to do if no logical connection active */ 711 /* nothing to do if no logical connection active */
704 if (ap->connected < APCONN_ACTIVE) 712 if (bcs->apconnstate < APCONN_ACTIVE)
705 return; 713 return;
706 ap->connected = APCONN_SETUP; 714 bcs->apconnstate = APCONN_SETUP;
707 715
708 capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, 716 capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
709 ap->nextMessageNumber++, 717 ap->nextMessageNumber++,
@@ -730,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)
730{ 738{
731 struct cardstate *cs = bcs->cs; 739 struct cardstate *cs = bcs->cs;
732 struct gigaset_capi_ctr *iif = cs->iif; 740 struct gigaset_capi_ctr *iif = cs->iif;
733 struct gigaset_capi_appl *ap = bcs->ap; 741 struct gigaset_capi_appl *ap;
734 struct sk_buff *skb; 742 struct sk_buff *skb;
735 unsigned int msgsize; 743 unsigned int msgsize;
744 unsigned long flags;
736 745
746 spin_lock_irqsave(&bcs->aplock, flags);
747 ap = bcs->ap;
737 if (!ap) { 748 if (!ap) {
749 spin_unlock_irqrestore(&bcs->aplock, flags);
738 dev_err(cs->dev, "%s: no application\n", __func__); 750 dev_err(cs->dev, "%s: no application\n", __func__);
739 return; 751 return;
740 } 752 }
753 if (bcs->apconnstate == APCONN_NONE) {
754 spin_unlock_irqrestore(&bcs->aplock, flags);
755 dev_warn(cs->dev, "%s: application %u not connected\n",
756 __func__, ap->id);
757 return;
758 }
759 spin_unlock_irqrestore(&bcs->aplock, flags);
741 while (ap->bcnext) { 760 while (ap->bcnext) {
742 /* this should never happen */ 761 /* this should never happen */
743 dev_warn(cs->dev, "%s: dropping extra application %u\n", 762 dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -746,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)
746 CapiCallGivenToOtherApplication); 765 CapiCallGivenToOtherApplication);
747 ap->bcnext = ap->bcnext->bcnext; 766 ap->bcnext = ap->bcnext->bcnext;
748 } 767 }
749 if (ap->connected == APCONN_NONE) {
750 dev_warn(cs->dev, "%s: application %u not connected\n",
751 __func__, ap->id);
752 return;
753 }
754 768
755 /* prepare CONNECT_ACTIVE_IND message 769 /* prepare CONNECT_ACTIVE_IND message
756 * Note: LLC not supported by device 770 * Note: LLC not supported by device
@@ -788,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)
788void gigaset_isdn_hupD(struct bc_state *bcs) 802void gigaset_isdn_hupD(struct bc_state *bcs)
789{ 803{
790 struct gigaset_capi_appl *ap; 804 struct gigaset_capi_appl *ap;
805 unsigned long flags;
791 806
792 /* 807 /*
793 * ToDo: pass on reason code reported by device 808 * ToDo: pass on reason code reported by device
794 * (requires ev-layer state machine extension to collect 809 * (requires ev-layer state machine extension to collect
795 * ZCAU device reply) 810 * ZCAU device reply)
796 */ 811 */
797 for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { 812 spin_lock_irqsave(&bcs->aplock, flags);
813 while (bcs->ap != NULL) {
814 ap = bcs->ap;
815 bcs->ap = ap->bcnext;
816 spin_unlock_irqrestore(&bcs->aplock, flags);
798 send_disconnect_b3_ind(bcs, ap); 817 send_disconnect_b3_ind(bcs, ap);
799 send_disconnect_ind(bcs, ap, 0); 818 send_disconnect_ind(bcs, ap, 0);
819 spin_lock_irqsave(&bcs->aplock, flags);