--- zzzz-none-000/linux-2.4.17/drivers/isdn/avmb1/kcapi.c 2001-12-21 17:41:54.000000000 +0000 +++ sangam-fb-401/linux-2.4.17/drivers/isdn/avmb1/kcapi.c 2005-09-20 11:10:33.000000000 +0000 @@ -64,6 +64,7 @@ __u32 ncci; __u32 winsize; int nmsg; + spinlock_t lock; struct msgidqueue *msgidqueue; struct msgidqueue *msgidlast; struct msgidqueue *msgidfree; @@ -73,7 +74,7 @@ struct capi_appl { __u16 applid; capi_register_params rparam; - int releasing; + atomic_t releasing; void *param; void (*signal) (__u16 applid, void *param); struct sk_buff_head recv_queue; @@ -103,14 +104,14 @@ #define APPL(a) (&applications[(a)-1]) #define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a) #define APPL_IS_FREE(a) (APPL(a)->applid == 0) -#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0); -#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0); +#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0) +#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0) #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) #define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR) #define CARD(c) (&cards[(c)-1]) -#define CARDNR(cp) (((cp)-cards)+1) +#define CARDNR(cp) ((((cp)-cards)+1) & 0xff) static struct capi_appl applications[CAPI_MAXAPPL]; static struct capi_ctr cards[CAPI_MAXCONTR]; @@ -535,8 +536,13 @@ * user process, not in bh. */ MOD_INC_USE_COUNT; +#if 0 if (schedule_task(&tq_state_notify) == 0) MOD_DEC_USE_COUNT; +#else /* #if 0 */ + queue_task(&tq_state_notify, &tq_immediate); + mark_bh(IMMEDIATE_BH); +#endif /* #if 0 */ return 0; } @@ -545,7 +551,13 @@ static void notify_up(__u32 contr) { struct capi_interface_user *p; + __u16 appl; + for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { + if (!VALID_APPLID(appl)) continue; + if (atomic_read(&APPL(appl)->releasing)) continue; + CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam); + } printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr); spin_lock(&capi_users_lock); for (p = capi_users; p; p = p->next) { @@ -640,6 +652,7 @@ static inline void mq_init(struct capi_ncci * np) { int i; + np->lock = SPIN_LOCK_UNLOCKED; np->msgidqueue = 0; np->msgidlast = 0; np->nmsg = 0; @@ -654,8 +667,11 @@ static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid) { struct msgidqueue *mq; - if ((mq = np->msgidfree) == 0) + spin_lock_bh(&np->lock); + if ((mq = np->msgidfree) == 0) { + spin_unlock_bh(&np->lock); return 0; + } np->msgidfree = mq->next; mq->msgid = msgid; mq->next = 0; @@ -665,12 +681,14 @@ if (!np->msgidqueue) np->msgidqueue = mq; np->nmsg++; + spin_unlock_bh(&np->lock); return 1; } static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid) { struct msgidqueue **pp; + spin_lock_bh(&np->lock); for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { if ((*pp)->msgid == msgid) { struct msgidqueue *mq = *pp; @@ -680,9 +698,11 @@ mq->next = np->msgidfree; np->msgidfree = mq; np->nmsg--; + spin_unlock_bh(&np->lock); return 1; } } + spin_unlock_bh(&np->lock); return 0; } @@ -705,11 +725,10 @@ nextpp = &(*pp)->next; } } - APPL(appl)->releasing--; - if (APPL(appl)->releasing <= 0) { - APPL(appl)->signal = 0; - APPL_MARK_FREE(appl); - printk(KERN_INFO "kcapi: appl %d down\n", appl); + if (atomic_dec_and_test(&APPL(appl)->releasing)) { /* only release if the application was marked for release */ + APPL(appl)->signal = 0; + APPL_MARK_FREE(appl); + printk(KERN_INFO "kcapi: appl %d down\n", appl); } } /* @@ -793,6 +812,12 @@ kfree_skb(skb); continue; } + if (atomic_read(&APPL(appl)->releasing)) { + printk(KERN_ERR "kcapi: recv_handler: applid %d is releasing\n", + appl); + kfree_skb(skb); + continue; + } if (APPL(appl)->signal == 0) { printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n", appl); @@ -863,16 +888,7 @@ static void controllercb_ready(struct capi_ctr * card) { - __u16 appl; - card->cardstate = CARD_RUNNING; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - if (!VALID_APPLID(appl)) continue; - if (APPL(appl)->releasing) continue; - card->driver->register_appl(card, appl, &APPL(appl)->rparam); - } - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", CARDNR(card), card->name); @@ -1104,7 +1120,7 @@ int appl; int i; - if (rparam->datablklen < 128) + if (rparam->datablklen < 64) return CAPI_LOGBLKSIZETOSMALL; for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { @@ -1117,6 +1133,7 @@ APPL_MARK_USED(appl); skb_queue_head_init(&APPL(appl)->recv_queue); APPL(appl)->nncci = 0; + atomic_set(&APPL(appl)->releasing,0); memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params)); @@ -1136,19 +1153,18 @@ { int i; - if (!VALID_APPLID(applid) || APPL(applid)->releasing) + if (!VALID_APPLID(applid) || atomic_read(&APPL(applid)->releasing)) return CAPI_ILLAPPNR; - APPL(applid)->releasing++; + atomic_inc(&APPL(applid)->releasing); skb_queue_purge(&APPL(applid)->recv_queue); for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate != CARD_RUNNING) continue; - APPL(applid)->releasing++; + atomic_inc(&APPL(applid)->releasing); cards[i].driver->release_appl(&cards[i], applid); } - APPL(applid)->releasing--; - if (APPL(applid)->releasing <= 0) { - APPL(applid)->signal = 0; + if (atomic_dec_and_test(&APPL(applid)->releasing)) { + APPL(applid)->signal = 0; APPL_MARK_FREE(applid); printk(KERN_INFO "kcapi: appl %d down\n", applid); }