diff --git a/drivers/isdn/hardware/mISDN/hfcs_usb.c b/drivers/isdn/hardware/mISDN/hfcs_usb.c index 7dc7c40..ea9a344 100644 --- a/drivers/isdn/hardware/mISDN/hfcs_usb.c +++ b/drivers/isdn/hardware/mISDN/hfcs_usb.c @@ -131,6 +131,7 @@ typedef struct _hfcsusb_t { int ctrl_paksize; /* control pipe packet size */ int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */ spinlock_t ctrl_lock; /* queueing ctrl urbs needs to be locked */ + spinlock_t lock; volatile __u8 threshold_mask; /* threshold in fifo flow control */ __u8 old_led_state, led_state; @@ -736,14 +737,18 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb) { int ret = 0; mISDN_head_t *hh = mISDN_HEAD_P(skb); + hfcsusb_t *hw = bch->hw; + u_long flags; if ((hh->prim == (PH_ACTIVATE | REQUEST)) || (hh->prim == (DL_ESTABLISH | REQUEST))) { + spin_lock_irqsave(&hw->lock, flags); if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) { ret = setup_bchannel(bch, bch->inst.pid.protocol[1]); if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS) test_and_set_bit(FLG_L2DATA, &bch->Flags); } + spin_unlock_irqrestore(&hw->lock, flags); #ifdef FIXME if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) if (bch->dev) @@ -756,6 +761,7 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb) (hh->prim == (DL_RELEASE | REQUEST)) || ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) { + spin_lock_irqsave(&hw->lock, flags); if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) { dev_kfree_skb(bch->next_skb); bch->next_skb = NULL; @@ -773,6 +779,7 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb) test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); setup_bchannel(bch, ISDN_PID_NONE); test_and_clear_bit(FLG_ACTIVE, &bch->Flags); + spin_unlock_irqrestore(&hw->lock, flags); skb_trim(skb, 0); if (hh->prim != (PH_CONTROL | REQUEST)) { #ifdef FIXME @@ -805,18 +812,23 @@ hfcsusb_l2l1(mISDNinstance_t *inst, struct sk_buff *skb) channel_t *chan = container_of(inst, channel_t, inst); int ret = 0; mISDN_head_t *hh = mISDN_HEAD_P(skb); + u_long flags; int i; if ((hh->prim == PH_DATA_REQ) || (hh->prim == DL_DATA_REQ)) { + spin_lock_irqsave(inst->hwlock, flags); ret = channel_senddata(chan, hh->dinfo, skb); if (ret > 0) { - + if (!(chan)) { - printk ("CRITICAL ERROR! chan is NULL pointer!\n"); + printk (KERN_INFO "HFC-S USB: CRITICAL ERROR! chan is NULL pointer!\n"); + spin_unlock_irqrestore(inst->hwlock, flags); return(-EINVAL); } + if (!(chan->tx_skb)) { - printk ("CRITICAL ERROR! channel_senddata returned %d without chan->tx_skb\n", ret); + printk (KERN_INFO "HFC-S USB: CRITICAL ERROR! channel_senddata returned %d without chan->tx_skb\n", ret); + spin_unlock_irqrestore(inst->hwlock, flags); return(-EINVAL); } @@ -835,6 +847,7 @@ hfcsusb_l2l1(mISDNinstance_t *inst, struct sk_buff *skb) /* data gets transmitted later in USB ISO OUT traffic */ ret = 0; } + spin_unlock_irqrestore(inst->hwlock, flags); return(ret); } if (test_bit(FLG_DCHANNEL, &chan->Flags)) { @@ -1734,6 +1747,7 @@ setup_instance(hfcsusb_t * card) card->chan[D].debug = debug; spin_lock_init(&card->ctrl_lock); + spin_lock_init(&card->lock); /* link card->fifos[] to card->chan[] */ card->fifos[HFCUSB_D_RX].ch_idx = D; @@ -1747,7 +1761,7 @@ setup_instance(hfcsusb_t * card) card->chan[D].channel = D; card->chan[D].state = 0; - card->chan[D].inst.hwlock = NULL; + card->chan[D].inst.hwlock = &card->lock; card->chan[D].inst.pid.layermask = ISDN_LAYER(0); card->chan[D].inst.pid.protocol[0] = ISDN_PID_L0_TE_S0; card->chan[D].inst.class_dev.dev = &card->dev->dev; @@ -1762,7 +1776,7 @@ setup_instance(hfcsusb_t * card) card->chan[i].channel = i; mISDN_init_instance(&card->chan[i].inst, &hw_mISDNObj, card, hfcsusb_l2l1); card->chan[i].inst.pid.layermask = ISDN_LAYER(0); - card->chan[i].inst.hwlock = NULL; + card->chan[i].inst.hwlock = &card->lock; card->chan[i].inst.class_dev.dev = &card->dev->dev; card->chan[i].debug = debug; sprintf(card->chan[i].inst.name, "%s B%d",