From 90ab30a38d29d838ff8cb592875793d4ce6a7b55 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Sat, 6 Sep 2003 17:11:42 +0000 Subject: [PATCH] cleanup locking, now ready for 2.6 --- drivers/isdn/hardware/mISDN/layer2.c | 123 +++++++++++++++------------ drivers/isdn/hardware/mISDN/layer2.h | 2 + 2 files changed, 71 insertions(+), 54 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/layer2.c b/drivers/isdn/hardware/mISDN/layer2.c index a89ff80..4f7f5ee 100644 --- a/drivers/isdn/hardware/mISDN/layer2.c +++ b/drivers/isdn/hardware/mISDN/layer2.c @@ -494,21 +494,28 @@ legalnr(layer2_t *l2, unsigned int nr) static void setva(layer2_t *l2, unsigned int nr) { + u_long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&l2->lock, flags); while (l2->va != nr) { - (l2->va)++; + l2->va++; if(test_bit(FLG_MOD128, &l2->flag)) l2->va %= 128; else l2->va %= 8; if (l2->windowar[l2->sow]) { skb_trim(l2->windowar[l2->sow], 0); - if (l2up(l2, DL_DATA | CONFIRM, (int)l2->windowar[l2->sow], - l2->windowar[l2->sow])) - dev_kfree_skb(l2->windowar[l2->sow]); + skb_queue_tail(&l2->tmp_queue, l2->windowar[l2->sow]); l2->windowar[l2->sow] = NULL; } l2->sow = (l2->sow + 1) % l2->window; } + spin_unlock_irqrestore(&l2->lock, flags); + while((skb =skb_dequeue(&l2->tmp_queue))) { + if (l2up(l2, DL_DATA | CONFIRM, (int)skb, skb)) + dev_kfree_skb(skb); + } } static void @@ -813,16 +820,18 @@ l2_disconnect(struct FsmInst *fi, int event, void *arg) static void l2_start_multi(struct FsmInst *fi, int event, void *arg) { - layer2_t *l2 = fi->userdata; - struct sk_buff *skb = arg; + layer2_t *l2 = fi->userdata; + struct sk_buff *skb = arg; + u_long flags; - send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP); - - clear_exception(l2); + spin_lock_irqsave(&l2->lock, flags); l2->vs = 0; l2->va = 0; l2->vr = 0; l2->sow = 0; + spin_unlock_irqrestore(&l2->lock, flags); + clear_exception(l2); + send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP); FsmChangeState(fi, ST_L2_7); FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3); skb_trim(skb, 0); @@ -851,9 +860,10 @@ l2_send_DM(struct FsmInst *fi, int event, void *arg) static void l2_restart_multi(struct FsmInst *fi, int event, void *arg) { - layer2_t *l2 = fi->userdata; - struct sk_buff *skb = arg; - int est = 0; + layer2_t *l2 = fi->userdata; + struct sk_buff *skb = arg; + int est = 0; + u_long flags; send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP); @@ -865,10 +875,12 @@ l2_restart_multi(struct FsmInst *fi, int event, void *arg) } clear_exception(l2); + spin_lock_irqsave(&l2->lock, flags); l2->vs = 0; l2->va = 0; l2->vr = 0; l2->sow = 0; + spin_unlock_irqrestore(&l2->lock, flags); FsmChangeState(fi, ST_L2_7); stop_t200(l2, 3); FsmRestartTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3); @@ -883,8 +895,8 @@ l2_restart_multi(struct FsmInst *fi, int event, void *arg) static void l2_stop_multi(struct FsmInst *fi, int event, void *arg) { - layer2_t *l2 = fi->userdata; - struct sk_buff *skb = arg; + layer2_t *l2 = fi->userdata; + struct sk_buff *skb = arg; FsmChangeState(fi, ST_L2_4); FsmDelTimer(&l2->t203, 3); @@ -899,9 +911,10 @@ l2_stop_multi(struct FsmInst *fi, int event, void *arg) static void l2_connected(struct FsmInst *fi, int event, void *arg) { - layer2_t *l2 = fi->userdata; - struct sk_buff *skb = arg; - int pr=-1; + layer2_t *l2 = fi->userdata; + struct sk_buff *skb = arg; + int pr=-1; + u_long flags; if (!get_PollFlag(l2, skb)) { l2_mdl_error_ua(fi, event, arg); @@ -917,11 +930,12 @@ l2_connected(struct FsmInst *fi, int event, void *arg) pr = DL_ESTABLISH | INDICATION; } stop_t200(l2, 5); - + spin_lock_irqsave(&l2->lock, flags); l2->vr = 0; l2->vs = 0; l2->va = 0; l2->sow = 0; + spin_unlock_irqrestore(&l2->lock, flags); FsmChangeState(fi, ST_L2_7); FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 4); if (pr != -1) @@ -1045,8 +1059,10 @@ nrerrorrecovery(struct FsmInst *fi) static void invoke_retransmission(layer2_t *l2, unsigned int nr) { - unsigned int p1; + u_int p1; + u_long flags; + spin_lock_irqsave(&l2->lock, flags); if (l2->vs != nr) { while (l2->vs != nr) { (l2->vs)--; @@ -1058,13 +1074,13 @@ invoke_retransmission(layer2_t *l2, unsigned int nr) p1 = (l2->vs - l2->va) % 8; } p1 = (p1 + l2->sow) % l2->window; -// if (test_bit(FLG_LAPB, &l2->flag)) -// st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0); skb_queue_head(&l2->i_queue, l2->windowar[p1]); l2->windowar[p1] = NULL; } + spin_unlock_irqrestore(&l2->lock, flags); FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL); - } + } else + spin_unlock_irqrestore(&l2->lock, flags); } static void @@ -1134,8 +1150,6 @@ l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg) layer2_t *l2 = fi->userdata; struct sk_buff *skb = arg; -// if (test_bit(FLG_LAPB, &l2->flag)) -// st->l1.bcs->tx_cnt += skb->len + l2headersize(l2, 0); if (!test_bit(FLG_L3_INIT, &l2->flag)) skb_queue_tail(&l2->i_queue, skb); else @@ -1148,8 +1162,6 @@ l2_feed_i_pull(struct FsmInst *fi, int event, void *arg) layer2_t *l2 = fi->userdata; struct sk_buff *skb = arg; -// if (test_bit(FLG_LAPB, &l2->flag)) -// st->l1.bcs->tx_cnt += skb->len + l2headersize(l2, 0); skb_queue_tail(&l2->i_queue, skb); FsmEvent(fi, EV_L2_ACK_PULL, NULL); } @@ -1160,8 +1172,6 @@ l2_feed_iqueue(struct FsmInst *fi, int event, void *arg) layer2_t *l2 = fi->userdata; struct sk_buff *skb = arg; -// if (test_bit(FLG_LAPB, &l2->flag)) -// st->l1.bcs->tx_cnt += skb->len + l2headersize(l2, 0); skb_queue_tail(&l2->i_queue, skb); } @@ -1172,6 +1182,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg) struct sk_buff *skb = arg; int PollFlag, i; u_int ns, nr; + u_long flags; i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { @@ -1187,29 +1198,34 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg) dev_kfree_skb(skb); if (PollFlag) enquiry_response(l2); - } else if (l2->vr == ns) { - (l2->vr)++; - if(test_bit(FLG_MOD128, &l2->flag)) - l2->vr %= 128; - else - l2->vr %= 8; - test_and_clear_bit(FLG_REJEXC, &l2->flag); - if (PollFlag) - enquiry_response(l2); - else - test_and_set_bit(FLG_ACK_PEND, &l2->flag); - skb_pull(skb, l2headersize(l2, 0)); - if (l2up(l2, DL_DATA | INDICATION, DINFO_SKB, skb)) - dev_kfree_skb(skb); } else { - /* n(s)!=v(r) */ - dev_kfree_skb(skb); - if (test_and_set_bit(FLG_REJEXC, &l2->flag)) { + spin_lock_irqsave(&l2->lock, flags); + if (l2->vr == ns) { + l2->vr++; + if(test_bit(FLG_MOD128, &l2->flag)) + l2->vr %= 128; + else + l2->vr %= 8; + test_and_clear_bit(FLG_REJEXC, &l2->flag); + spin_unlock_irqrestore(&l2->lock, flags); if (PollFlag) enquiry_response(l2); + else + test_and_set_bit(FLG_ACK_PEND, &l2->flag); + skb_pull(skb, l2headersize(l2, 0)); + if (l2up(l2, DL_DATA | INDICATION, DINFO_SKB, skb)) + dev_kfree_skb(skb); } else { - enquiry_cr(l2, REJ, RSP, PollFlag); - test_and_clear_bit(FLG_ACK_PEND, &l2->flag); + /* n(s)!=v(r) */ + spin_unlock_irqrestore(&l2->lock, flags); + dev_kfree_skb(skb); + if (test_and_set_bit(FLG_REJEXC, &l2->flag)) { + if (PollFlag) + enquiry_response(l2); + } else { + enquiry_cr(l2, REJ, RSP, PollFlag); + test_and_clear_bit(FLG_ACK_PEND, &l2->flag); + } } } if (legalnr(l2, nr)) { @@ -1364,8 +1380,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) if (!skb) return; - save_flags(flags); - cli(); + spin_lock_irqsave(&l2->lock, flags); if(test_bit(FLG_MOD128, &l2->flag)) p1 = (l2->vs - l2->va) % 128; else @@ -1377,10 +1392,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) dev_kfree_skb(l2->windowar[p1]); } l2->windowar[p1] = skb; - skb = skb_clone(skb, GFP_ATOMIC); - i = sethdraddr(l2, header, CMD); - if (test_bit(FLG_MOD128, &l2->flag)) { header[i++] = l2->vs << 1; header[i++] = l2->vr << 1; @@ -1389,14 +1401,15 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) header[i++] = (l2->vr << 5) | (l2->vs << 1); l2->vs = (l2->vs + 1) % 8; } - restore_flags(flags); + spin_unlock_irqrestore(&l2->lock, flags); + skb = skb_clone(skb, GFP_ATOMIC); p1 = skb_headroom(skb); if (p1 >= i) memcpy(skb_push(skb, i), header, i); else { printk(KERN_WARNING - "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); + "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); oskb = skb; skb = alloc_skb(oskb->len + i, GFP_ATOMIC); if (!skb) { @@ -2066,6 +2079,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { return(-ENOMEM); } memset(nl2, 0, sizeof(layer2_t)); + spin_lock_init(&nl2->lock); nl2->debug = debug; init_mISDNinstance(&nl2->inst, &isdnl2, nl2); nl2->inst.extentions = EXT_INST_CLONE; @@ -2149,6 +2163,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) { skb_queue_head_init(&nl2->i_queue); skb_queue_head_init(&nl2->ui_queue); skb_queue_head_init(&nl2->down_queue); + skb_queue_head_init(&nl2->tmp_queue); InitWin(nl2); nl2->l2m.fsm = &l2fsm; if (test_bit(FLG_LAPB, &nl2->flag) || diff --git a/drivers/isdn/hardware/mISDN/layer2.h b/drivers/isdn/hardware/mISDN/layer2.h index db838fa..71007cf 100644 --- a/drivers/isdn/hardware/mISDN/layer2.h +++ b/drivers/isdn/hardware/mISDN/layer2.h @@ -53,6 +53,8 @@ typedef struct _layer2 { struct sk_buff_head i_queue; struct sk_buff_head ui_queue; struct sk_buff_head down_queue; + struct sk_buff_head tmp_queue; + spinlock_t lock; } layer2_t; /* l2 status_info */