Commit 93ab17e8 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] i4l: hisax deadlock fix

From: Karsten Keil <kkeil@suse.de>

This patch fix a deadlock in HiSax (reported from David Woodhouse
<dwmw2@infradead.org>).  upper layer was called back while holding the card
lock fix is to move the wakeup call into BH handler to avoid direct
callbacks.
parent bb257be4
/* $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 <linux/interrupt.h>
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;
......
/* $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 <keil@isdn4linux.de>
......@@ -21,7 +21,7 @@
#include "hisax.h"
#include <linux/isdn/capicmd.h>
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 pr, void *arg)
}
}
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 incoming)
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 incoming)
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;
......
/* $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 <keil@isdn4linux.de>
......@@ -1734,8 +1734,13 @@ static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg)
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);
......
/* $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 *cs, u_char val, u_char hscx)
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;
......
/* $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;
}
......
/* $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;
}
......
/* $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;
......
/* $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 CCDs 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 */
......@@ -1689,11 +1699,11 @@ setup_hfcpci(struct IsdnCard *card)
/* Allocate memory for FIFOS */
/* Because the HFC-PCI needs a 32K physical alignment, we */
/* need to allocate the double mem and align the address */
if (!((void *) cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
return 0;
}
(ulong) cs->hw.hfcpci.fifos =
cs->hw.hfcpci.fifos = (void *)
(((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
......
/* $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);
......
/* $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, char *debug_id);
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);
......
/* $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, u_char val, u_char hscx)
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;
......
......@@ -733,35 +733,38 @@ bch_int(struct IsdnCardState *cs, u_char hscx)
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
......
/* $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)) {
......
/* $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 <linux/init.h>
#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, int bc)
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;
......
/* $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);
......
/* $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);
......
/* $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, u_char val, u_char jade)
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;
......
/* $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 <asm/io.h>
#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 *bcs, u_int *buf, int cnt) {
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;
}
......
/* $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 *cs, u_char bchan)
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment