From: Karsten Keil This patch fix a deadlock in HiSax (reported from David Woodhouse ). upper layer was called back while holding the card lock fix is to move the wakeup call into BH handler to avoid direct callbacks. --- 25-akpm/drivers/isdn/hisax/avm_pci.c | 15 ++++++--- 25-akpm/drivers/isdn/hisax/callc.c | 16 +++++----- 25-akpm/drivers/isdn/hisax/config.c | 11 +++++-- 25-akpm/drivers/isdn/hisax/diva.c | 15 ++++++--- 25-akpm/drivers/isdn/hisax/elsa_ser.c | 14 +++++---- 25-akpm/drivers/isdn/hisax/hfc_2bds0.c | 13 +++++--- 25-akpm/drivers/isdn/hisax/hfc_2bs0.c | 12 +++++-- 25-akpm/drivers/isdn/hisax/hfc_pci.c | 26 +++++++++++----- 25-akpm/drivers/isdn/hisax/hfc_sx.c | 15 ++++++--- 25-akpm/drivers/isdn/hisax/hisax.h | 10 ++++-- 25-akpm/drivers/isdn/hisax/hscx_irq.c | 13 +++++--- 25-akpm/drivers/isdn/hisax/ipacx.c | 51 +++++++++++++++++---------------- 25-akpm/drivers/isdn/hisax/isar.c | 13 +++++--- 25-akpm/drivers/isdn/hisax/isdnl1.c | 21 ++++++++++++- 25-akpm/drivers/isdn/hisax/isdnl1.h | 7 ++-- 25-akpm/drivers/isdn/hisax/isdnl2.c | 8 ++--- 25-akpm/drivers/isdn/hisax/jade_irq.c | 13 +++++--- 25-akpm/drivers/isdn/hisax/netjet.c | 15 ++++++--- 25-akpm/drivers/isdn/hisax/w6692.c | 15 ++++++--- 19 files changed, 199 insertions(+), 104 deletions(-) diff -puN drivers/isdn/hisax/avm_pci.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/avm_pci.c --- 25/drivers/isdn/hisax/avm_pci.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/avm_pci.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.29.2.3 2004/01/13 14:31:24 keil Exp $ +/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $ * * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * @@ -22,7 +22,7 @@ #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.29.2.3 $"; +static const char *avm_pci_rev = "$Revision: 1.29.2.4 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -427,9 +427,14 @@ HDLC_irq(struct BCState *bcs, u_int stat hdlc_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hdlc.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.hdlc.count = 0; bcs->tx_skb = NULL; diff -puN drivers/isdn/hisax/callc.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/callc.c --- 25/drivers/isdn/hisax/callc.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/callc.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.59.2.3 2004/01/13 14:31:24 keil Exp $ +/* $Id: callc.c,v 2.59.2.4 2004/02/11 13:21:32 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -21,7 +21,7 @@ #include "hisax.h" #include -const char *lli_revision = "$Revision: 2.59.2.3 $"; +const char *lli_revision = "$Revision: 2.59.2.4 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -1065,7 +1065,6 @@ init_d_st(struct Channel *chanp) setstack_isdnl2(st, tmp); setstack_l3dc(st, chanp); st->lli.userdata = chanp; - st->lli.l2writewakeup = NULL; st->l3.l3l4 = dchan_l3l4; return 0; @@ -1247,8 +1246,8 @@ lltrans_handler(struct PStack *st, int p } } -static void -ll_writewakeup(struct PStack *st, int len) +void +lli_writewakeup(struct PStack *st, int len) { struct Channel *chanp = st->lli.userdata; isdn_ctrl ic; @@ -1312,8 +1311,8 @@ init_b_st(struct Channel *chanp, int inc setstack_l3bc(st, chanp); st->l2.l2l3 = lldata_handler; st->lli.userdata = chanp; - st->lli.l1writewakeup = NULL; - st->lli.l2writewakeup = ll_writewakeup; + test_and_clear_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_set_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; break; @@ -1324,7 +1323,8 @@ init_b_st(struct Channel *chanp, int inc case (ISDN_PROTO_L2_FAX): st->l1.l1l2 = lltrans_handler; st->lli.userdata = chanp; - st->lli.l1writewakeup = ll_writewakeup; + test_and_set_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_clear_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); setstack_transl2(st); setstack_l3bc(st, chanp); break; diff -puN drivers/isdn/hisax/config.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/config.c --- 25/drivers/isdn/hisax/config.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/config.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 2.84.2.4 2004/01/24 20:47:20 keil Exp $ +/* $Id: config.c,v 2.84.2.5 2004/02/11 13:21:33 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -1734,8 +1734,13 @@ static void hisax_b_l1l2(struct hisax_if break; case PH_DATA | CONFIRM: bcs->tx_cnt -= (int) arg; - if (bcs->st->lli.l1writewakeup) - bcs->st->lli.l1writewakeup(bcs->st, (int) arg); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += (int) arg; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } skb = skb_dequeue(&bcs->squeue); if (skb) { B_L2L1(b_if, PH_DATA | REQUEST, skb); diff -puN drivers/isdn/hisax/diva.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/diva.c --- 25/drivers/isdn/hisax/diva.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/diva.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.33.2.5 2004/01/14 00:49:43 keil Exp $ +/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 keil Exp $ * * low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -28,7 +28,7 @@ extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.33.2.5 $"; +const char *Diva_revision = "$Revision: 1.33.2.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -542,9 +542,14 @@ Memhscx_interrupt(struct IsdnCardState * Memhscx_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; diff -puN drivers/isdn/hisax/elsa_ser.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/elsa_ser.c --- 25/drivers/isdn/hisax/elsa_ser.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/elsa_ser.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.14.2.2 2004/01/12 22:52:26 keil Exp $ +/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $ * * stuff for the serial modem on ELSA cards * @@ -283,10 +283,14 @@ modem_fill(struct BCState *bcs) { write_modem(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, - bcs->hw.hscx.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } diff -puN drivers/isdn/hisax/hfc_2bds0.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/hfc_2bds0.c --- 25/drivers/isdn/hisax/hfc_2bds0.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hfc_2bds0.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.18.2.5 2004/01/19 15:31:50 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -314,9 +314,14 @@ hfc_fill_fifo(struct BCState *bcs) printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } diff -puN drivers/isdn/hisax/hfc_2bs0.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/hfc_2bs0.c --- 25/drivers/isdn/hisax/hfc_2bs0.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hfc_2bs0.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.20.2.5 2004/01/19 15:31:50 keil Exp $ +/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BS0 * @@ -308,8 +308,14 @@ hfc_fill_fifo(struct BCState *bcs) WaitNoBusy(cs); cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); } - if (bcs->st->lli.l1writewakeup && (count >= 0)) - bcs->st->lli.l1writewakeup(bcs->st, count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (count >= 0)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } return; diff -puN drivers/isdn/hisax/hfc_pci.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/hfc_pci.c --- 25/drivers/isdn/hisax/hfc_pci.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hfc_pci.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.48.2.3 2004/01/13 14:31:25 keil Exp $ +/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $ * * low level driver for CCD´s hfc-pci based cards * @@ -25,7 +25,7 @@ extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.48.2.3 $"; +static const char *hfcpci_revision = "$Revision: 1.48.2.4 $"; /* table entry in the PCI devices list */ typedef struct { @@ -649,9 +649,14 @@ hfcpci_fill_fifo(struct BCState *bcs) debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", bcs->channel, bcs->tx_skb->len); - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ @@ -707,9 +712,14 @@ hfcpci_fill_fifo(struct BCState *bcs) memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } bz->za[new_f1].z1 = new_z1; /* for next buffer */ bz->f1 = new_f1; /* next frame */ diff -puN drivers/isdn/hisax/hfc_sx.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/hfc_sx.c --- 25/drivers/isdn/hisax/hfc_sx.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hfc_sx.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_sx.c,v 1.12.2.4 2004/01/14 16:04:48 keil Exp $ +/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $ * * level driver for Cologne Chip Designs hfc-s+/sp based cards * @@ -20,7 +20,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.12.2.4 $"; +static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; /***************************************/ /* IRQ-table for CCDs demo board */ @@ -540,9 +540,14 @@ hfcsx_fill_fifo(struct BCState *bcs) HFCSX_BTRANS_THRESHOLD : 0)) { bcs->tx_cnt -= bcs->tx_skb->len; - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); diff -puN drivers/isdn/hisax/hisax.h~i4l-hisax-deadlock-fix drivers/isdn/hisax/hisax.h --- 25/drivers/isdn/hisax/hisax.h~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hisax.h Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 2.64.2.3 2004/01/24 20:47:23 keil Exp $ +/* $Id: hisax.h,v 2.64.2.4 2004/02/11 13:21:33 keil Exp $ * * Basic declarations, defines and prototypes * @@ -280,10 +280,11 @@ struct LLInterface { void (*l4l3) (struct PStack *, int, void *); int (*l4l3_proto) (struct PStack *, isdn_ctrl *); void *userdata; - void (*l1writewakeup) (struct PStack *, int); - void (*l2writewakeup) (struct PStack *, int); + u_long flag; }; +#define FLG_LLI_L1WAKEUP 1 +#define FLG_LLI_L2WAKEUP 2 struct Management { int ri; @@ -494,6 +495,8 @@ struct BCState { struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ struct sk_buff_head rqueue; /* B-Channel receive Queue */ struct sk_buff_head squeue; /* B-Channel send Queue */ + int ackcnt; + spinlock_t aclock; struct PStack *st; u_char *blog; u_char *conmsg; @@ -1281,6 +1284,7 @@ void setstack_isdnl2(struct PStack *st, void releasestack_isdnl2(struct PStack *st); void setstack_transl2(struct PStack *st); void releasestack_transl2(struct PStack *st); +void lli_writewakeup(struct PStack *st, int len); void setstack_l3dc(struct PStack *st, struct Channel *chanp); void setstack_l3bc(struct PStack *st, struct Channel *chanp); diff -puN drivers/isdn/hisax/hscx_irq.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/hscx_irq.c --- 25/drivers/isdn/hisax/hscx_irq.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/hscx_irq.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.18.2.2 2004/01/12 22:52:26 keil Exp $ +/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $ * * low level b-channel stuff for Siemens HSCX * @@ -197,9 +197,14 @@ hscx_interrupt(struct IsdnCardState *cs, hscx_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; diff -puN drivers/isdn/hisax/ipacx.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/ipacx.c --- 25/drivers/isdn/hisax/ipacx.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/ipacx.c Wed Feb 11 13:59:06 2004 @@ -733,35 +733,38 @@ bch_int(struct IsdnCardState *cs, u_char if (istab &0x20) { // RFO if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: RFO error", hscx); - cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES + debugl1(cs, "bch_int() B-%d: RFO error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES } if (istab &0x10) { // XPR if (bcs->tx_skb) { if (bcs->tx_skb->len) { - bch_fill_fifo(bcs); - goto afterXPR; - } - else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) { - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - } - dev_kfree_skb_irq(bcs->tx_skb); - bcs->hw.hscx.count = 0; - bcs->tx_skb = NULL; - } - } - if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->hw.hscx.count = 0; - set_bit(BC_FLG_BUSY, &bcs->Flag); - bch_fill_fifo(bcs); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - schedule_event(bcs, B_XMTBUFREADY); - } - } + bch_fill_fifo(bcs); + goto afterXPR; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bch_fill_fifo(bcs); + } else { + clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } + } afterXPR: if (istab &0x04) { // XDU diff -puN drivers/isdn/hisax/isar.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/isar.c --- 25/drivers/isdn/hisax/isar.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/isar.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.22.2.5 2004/01/14 00:49:44 keil Exp $ +/* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -759,9 +759,14 @@ send_frames(struct BCState *bcs) isar_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.isar.txcnt; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } if (bcs->mode == L1_MODE_FAX) { if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { diff -puN drivers/isdn/hisax/isdnl1.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/isdnl1.c --- 25/drivers/isdn/hisax/isdnl1.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/isdnl1.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.46.2.4 2004/01/13 21:46:03 keil Exp $ +/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $ * * common low level stuff for Siemens Chipsetbased isdn cards * @@ -18,7 +18,7 @@ * */ -const char *l1_revision = "$Revision: 2.46.2.4 $"; +const char *l1_revision = "$Revision: 2.46.2.5 $"; #include #include "hisax.h" @@ -299,6 +299,20 @@ BChannel_proc_rcv(struct BCState *bcs) } } +static void +BChannel_proc_ack(struct BCState *bcs) +{ + u_long flags; + int ack; + + spin_lock_irqsave(&bcs->aclock, flags); + ack = bcs->ackcnt; + bcs->ackcnt = 0; + spin_unlock_irqrestore(&bcs->aclock, flags); + if (ack) + lli_writewakeup(bcs->st, ack); +} + void BChannel_bh(struct BCState *bcs) { @@ -308,6 +322,8 @@ BChannel_bh(struct BCState *bcs) BChannel_proc_rcv(bcs); if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event)) BChannel_proc_xmt(bcs); + if (test_and_clear_bit(B_ACKPENDING, &bcs->event)) + BChannel_proc_ack(bcs); } void @@ -346,6 +362,7 @@ init_bcstate(struct IsdnCardState *cs, i bcs->cs = cs; bcs->channel = bc; INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + spin_lock_init(&bcs->aclock); bcs->BC_SetStack = NULL; bcs->BC_Close = NULL; bcs->Flag = 0; diff -puN drivers/isdn/hisax/isdnl1.h~i4l-hisax-deadlock-fix drivers/isdn/hisax/isdnl1.h --- 25/drivers/isdn/hisax/isdnl1.h~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/isdnl1.h Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.h,v 2.12.2.2 2004/01/12 22:52:27 keil Exp $ +/* $Id: isdnl1.h,v 2.12.2.3 2004/02/11 13:21:34 keil Exp $ * * Layer 1 defines * @@ -17,8 +17,9 @@ #define D_TX_MON1 7 #define E_RCVBUFREADY 8 -#define B_RCVBUFREADY 0 -#define B_XMTBUFREADY 1 +#define B_RCVBUFREADY 0 +#define B_XMTBUFREADY 1 +#define B_ACKPENDING 2 extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); diff -puN drivers/isdn/hisax/isdnl2.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/isdnl2.c --- 25/drivers/isdn/hisax/isdnl2.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/isdnl2.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl2.c,v 2.30.2.3 2004/01/13 14:31:25 keil Exp $ +/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -19,7 +19,7 @@ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.30.2.3 $"; +const char *l2_revision = "$Revision: 2.30.2.4 $"; static void l2m_debug(struct FsmInst *fi, char *fmt, ...); @@ -420,8 +420,8 @@ setva(struct PStack *st, unsigned int nr l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; spin_unlock_irqrestore(&l2->lock, flags); - if (st->lli.l2writewakeup && (len >=0)) - st->lli.l2writewakeup(st, len); + if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0)) + lli_writewakeup(st, len); spin_lock_irqsave(&l2->lock, flags); } spin_unlock_irqrestore(&l2->lock, flags); diff -puN drivers/isdn/hisax/jade_irq.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/jade_irq.c --- 25/drivers/isdn/hisax/jade_irq.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/jade_irq.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: jade_irq.c,v 1.7.2.3 2004/01/14 16:04:48 keil Exp $ +/* $Id: jade_irq.c,v 1.7.2.4 2004/02/11 13:21:34 keil Exp $ * * Low level JADE IRQ stuff (derived from original hscx_irq.c) * @@ -175,9 +175,14 @@ jade_interrupt(struct IsdnCardState *cs, jade_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; diff -puN drivers/isdn/hisax/netjet.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/netjet.c --- 25/drivers/isdn/hisax/netjet.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/netjet.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.29.2.3 2004/01/13 14:31:26 keil Exp $ +/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $ * * low level stuff for Traverse Technologie NETJet ISDN cards * @@ -25,7 +25,7 @@ #include #include "netjet.h" -const char *NETjet_revision = "$Revision: 1.29.2.3 $"; +const char *NETjet_revision = "$Revision: 1.29.2.4 $"; /* Interface functions */ @@ -748,9 +748,14 @@ static void write_raw(struct BCState *bc if (!bcs->tx_skb) { debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt); } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } diff -puN drivers/isdn/hisax/w6692.c~i4l-hisax-deadlock-fix drivers/isdn/hisax/w6692.c --- 25/drivers/isdn/hisax/w6692.c~i4l-hisax-deadlock-fix Wed Feb 11 13:59:06 2004 +++ 25-akpm/drivers/isdn/hisax/w6692.c Wed Feb 11 13:59:06 2004 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.18.2.3 2004/01/13 14:31:26 keil Exp $ +/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $ * * Winbond W6692 specific routines * @@ -41,7 +41,7 @@ static const PCI_ENTRY id_list[] = extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.18.2.3 $"; +const char *w6692_revision = "$Revision: 1.18.2.4 $"; #define DBUSY_TIMER_VALUE 80 @@ -376,9 +376,14 @@ W6692B_interrupt(struct IsdnCardState *c W6692B_fill_fifo(bcs); return; } else { - if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.w6692.count); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.w6692.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } dev_kfree_skb_irq(bcs->tx_skb); bcs->hw.w6692.count = 0; bcs->tx_skb = NULL; _