Commit 5b23ce9c authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/HiSax: Don't call back up in hard-IRQ context

We used to call writewakeup() directly from handling the "frame sent"
IRQ which potentially would call back up into the common ISDN layer and
higher up still in hard-IRQ context. Instead, queue the event and use
the usual mechanism of passing it up.
parent ab3a3b51
......@@ -460,14 +460,10 @@ HDLC_irq(struct BCState *bcs, u_int stat) {
if (bcs->tx_skb->len) {
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);
dev_kfree_skb_irq(bcs->tx_skb);
bcs->hw.hdlc.count = 0;
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hdlc_sched_event(bcs, B_CMPLREADY);
bcs->hw.hdlc.count = 0;
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hdlc.count = 0;
......
......@@ -1066,7 +1066,6 @@ init_d_st(struct Channel *chanp)
setstack_isdnl2(st, tmp);
setstack_l3dc(st, chanp);
st->lli.userdata = chanp;
st->lli.l2writewakeup = NULL;
st->lli.l3l4 = dchan_l3l4;
return 0;
......@@ -1183,6 +1182,23 @@ CallcFreeChan(struct IsdnCardState *csta)
}
}
static void
ll_writewakeup(struct Channel *chanp, struct sk_buff *skb)
{
isdn_ctrl ic;
if (skb->pkt_type != PACKET_NOACK) {
if (chanp->debug & 0x800)
link_debug(chanp, 0, "llwakeup: %d", skb->truesize);
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BSENT;
ic.arg = chanp->chan;
ic.parm.length = skb->truesize;
chanp->cs->iif.statcallb(&ic);
}
dev_kfree_skb(skb);
}
static void
lldata_handler(struct PStack *st, int pr, void *arg)
{
......@@ -1190,7 +1206,7 @@ lldata_handler(struct PStack *st, int pr, void *arg)
struct sk_buff *skb = arg;
switch (pr) {
case (DL_DATA | INDICATION):
case (DL_DATA | INDICATION):
if (chanp->data_open) {
if (chanp->debug & 0x800)
link_debug(chanp, 0, "lldata: %d", skb->len);
......@@ -1200,6 +1216,9 @@ lldata_handler(struct PStack *st, int pr, void *arg)
dev_kfree_skb(skb);
}
break;
case (DL_DATA | CONFIRM):
ll_writewakeup(chanp, skb);
break;
case (DL_ESTABLISH | INDICATION):
case (DL_ESTABLISH | CONFIRM):
FsmEvent(&chanp->fi, EV_BC_EST, NULL);
......@@ -1232,6 +1251,9 @@ lltrans_handler(struct PStack *st, int pr, void *arg)
dev_kfree_skb(skb);
}
break;
case (PH_DATA | CONFIRM):
ll_writewakeup(chanp, skb);
break;
case (PH_ACTIVATE | INDICATION):
case (PH_ACTIVATE | CONFIRM):
FsmEvent(&chanp->fi, EV_BC_EST, NULL);
......@@ -1247,21 +1269,6 @@ lltrans_handler(struct PStack *st, int pr, void *arg)
}
}
static void
ll_writewakeup(struct PStack *st, int len)
{
struct Channel *chanp = st->lli.userdata;
isdn_ctrl ic;
if (chanp->debug & 0x800)
link_debug(chanp, 0, "llwakeup: %d", len);
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BSENT;
ic.arg = chanp->chan;
ic.parm.length = len;
chanp->cs->iif.statcallb(&ic);
}
static int
init_b_st(struct Channel *chanp, int incoming)
{
......@@ -1312,8 +1319,6 @@ init_b_st(struct Channel *chanp, int incoming)
setstack_l3bc(st, chanp);
st->l3.l2l3 = lldata_handler;
st->lli.userdata = chanp;
st->lli.l1writewakeup = NULL;
st->lli.l2writewakeup = ll_writewakeup;
st->l2.l2m.debug = chanp->debug & 16;
st->l2.debug = chanp->debug & 64;
break;
......@@ -1324,7 +1329,6 @@ init_b_st(struct Channel *chanp, int incoming)
case (ISDN_PROTO_L2_FAX):
st->l2.l1l2 = lltrans_handler;
st->lli.userdata = chanp;
st->lli.l1writewakeup = ll_writewakeup;
setstack_transl2(st);
setstack_l3bc(st, chanp);
break;
......
......@@ -1910,9 +1910,10 @@ static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg)
hisax_b_sched_event(bcs, B_RCVBUFREADY);
break;
case PH_DATA | CONFIRM:
bcs->tx_cnt -= (int) arg;
if (bcs->st->lli.l1writewakeup)
bcs->st->lli.l1writewakeup(bcs->st, (int) arg);
skb = arg;
bcs->tx_cnt -= skb->truesize;
skb_queue_tail(&bcs->cmpl_queue, skb);
hisax_b_sched_event(bcs, B_CMPLREADY);
skb = skb_dequeue(&bcs->squeue);
if (skb) {
B_L2L1(b_if, PH_DATA | REQUEST, skb);
......
......@@ -563,14 +563,10 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
if (bcs->tx_skb->len) {
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);
dev_kfree_skb_irq(bcs->tx_skb);
bcs->hw.hscx.count = 0;
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->hw.hscx.count = 0;
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hscx.count = 0;
......
......@@ -299,14 +299,9 @@ modem_fill(struct BCState *bcs) {
if (bcs->tx_skb->len) {
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);
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hscx.count = 0;
......
......@@ -367,10 +367,8 @@ 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);
dev_kfree_skb_any(bcs->tx_skb);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->tx_skb = NULL;
}
WaitForBusy(cs);
......
......@@ -321,15 +321,15 @@ hfc_fill_fifo(struct BCState *bcs)
bcs->tx_cnt -= count;
if (PACKET_NOACK == bcs->tx_skb->pkt_type)
count = -1;
dev_kfree_skb_any(bcs->tx_skb);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->tx_skb = NULL;
if (bcs->mode != L1_MODE_TRANS) {
WaitForBusy(cs);
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);
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
restore_flags(flags);
......
......@@ -742,16 +742,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);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
cli();
bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */
bz->f1 = new_f1; /* next frame */
restore_flags(flags);
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
return;
......
......@@ -602,10 +602,8 @@ 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);
dev_kfree_skb_any(bcs->tx_skb);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
......
......@@ -278,8 +278,6 @@ struct Layer3 {
struct LLInterface {
void (*l3l4) (struct PStack *, int, void *);
void *userdata;
void (*l1writewakeup) (struct PStack *, int);
void (*l2writewakeup) (struct PStack *, int);
};
......@@ -489,8 +487,9 @@ struct BCState {
struct IsdnCardState *cs;
int tx_cnt; /* B-Channel transmit counter */
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 */
struct sk_buff_head rqueue; /* B-Channel receive queue */
struct sk_buff_head squeue; /* B-Channel send queue */
struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */
struct PStack *st;
u_char *blog;
u_char *conmsg;
......
......@@ -528,8 +528,7 @@ static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
}
bcs->tx_cnt = 0;
bcs->tx_skb = NULL;
B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
dev_kfree_skb_irq(skb);
B_L1L2(bcs, PH_DATA | CONFIRM, skb);
}
static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
......
......@@ -1294,8 +1294,7 @@ hfcpci_b_xmit_irq(struct hfcpci_adapter *adapter, int nr)
}
bcs->tx_skb = NULL;
B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
dev_kfree_skb_irq(skb);
B_L1L2(bcs, PH_DATA | CONFIRM, skb);
}
// ----------------------------------------------------------------------
......
......@@ -226,8 +226,7 @@ static inline void hscx_xpr_interrupt(struct hscx *hscx)
}
hscx->tx_cnt = 0;
hscx->tx_skb = NULL;
B_L1L2(hscx, PH_DATA | CONFIRM, (void *) skb->truesize);
dev_kfree_skb_irq(skb);
B_L1L2(hscx, PH_DATA | CONFIRM, skb);
}
static inline void hscx_exi_interrupt(struct hscx *hscx)
......
......@@ -169,6 +169,7 @@ close_hscxstate(struct BCState *bcs)
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
skb_queue_purge(&bcs->cmpl_queue);
if (bcs->tx_skb) {
dev_kfree_skb_any(bcs->tx_skb);
bcs->tx_skb = NULL;
......@@ -197,6 +198,7 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
}
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
skb_queue_head_init(&bcs->cmpl_queue);
}
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
......
......@@ -206,14 +206,10 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
if (bcs->tx_skb->len) {
__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);
dev_kfree_skb_irq(bcs->tx_skb);
bcs->hw.hscx.count = 0;
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->hw.hscx.count = 0;
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hscx.count = 0;
......
......@@ -751,35 +751,29 @@ 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);
bch_sched_event(bcs, B_XMTBUFREADY);
}
}
bch_fill_fifo(bcs);
goto afterXPR;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
bch_sched_event(bcs, B_CMPLREADY);
bcs->hw.hscx.count = 0;
}
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);
bch_sched_event(bcs, B_XMTBUFREADY);
}
}
afterXPR:
if (istab &0x04) { // XDU
......
......@@ -760,9 +760,8 @@ 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);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
isar_sched_event(bcs, B_CMPLREADY);
if (bcs->mode == L1_MODE_FAX) {
if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
......@@ -775,7 +774,6 @@ send_frames(struct BCState *bcs)
}
}
}
dev_kfree_skb_any(bcs->tx_skb);
bcs->hw.isar.txcnt = 0;
bcs->tx_skb = NULL;
}
......
......@@ -298,6 +298,16 @@ BChannel_proc_rcv(struct BCState *bcs)
}
}
static void
BChannel_proc_cmpl(struct BCState *bcs)
{
struct sk_buff *skb;
while ((skb = skb_dequeue(&bcs->cmpl_queue))) {
L1L2(bcs->st, PH_DATA | CONFIRM, skb);
}
}
void
BChannel_bh(void *data)
{
......@@ -307,6 +317,8 @@ BChannel_bh(void *data)
BChannel_proc_rcv(bcs);
if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))
BChannel_proc_xmt(bcs);
if (test_and_clear_bit(B_CMPLREADY, &bcs->event))
BChannel_proc_cmpl(bcs);
}
void
......
......@@ -19,6 +19,7 @@
#define B_RCVBUFREADY 0
#define B_XMTBUFREADY 1
#define B_CMPLREADY 2
extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
extern void DChannel_proc_xmt(struct IsdnCardState *cs);
......
......@@ -403,7 +403,7 @@ static void
setva(struct PStack *st, unsigned int nr)
{
struct Layer2 *l2 = &st->l2;
int len;
struct sk_buff *skb;
while (l2->va != nr) {
(l2->va)++;
......@@ -411,14 +411,11 @@ setva(struct PStack *st, unsigned int nr)
l2->va %= 128;
else
l2->va %= 8;
len = l2->windowar[l2->sow]->len;
if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
len = -1;
dev_kfree_skb(l2->windowar[l2->sow]);
skb = l2->windowar[l2->sow];
l2->windowar[l2->sow] = NULL;
l2->sow = (l2->sow + 1) % l2->window;
if (st->lli.l2writewakeup && (len >=0))
st->lli.l2writewakeup(st, len);
L2L3(st, DL_DATA | CONFIRM, skb);
}
}
......@@ -1686,6 +1683,9 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
if (ret)
FreeSkb(skb);
break;
case (PH_DATA | CONFIRM):
dev_kfree_skb(skb);
break;
case (PH_PULL | CONFIRM):
FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
break;
......
......@@ -185,14 +185,10 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
if (bcs->tx_skb->len) {
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);
dev_kfree_skb_irq(bcs->tx_skb);
bcs->hw.hscx.count = 0;
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
jade_sched_event(bcs, B_CMPLREADY);
bcs->hw.hscx.count = 0;
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hscx.count = 0;
......
......@@ -760,10 +760,8 @@ 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);
dev_kfree_skb_any(bcs->tx_skb);
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
hscx_sched_event(bcs, B_CMPLREADY);
bcs->tx_skb = NULL;
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
......
......@@ -82,8 +82,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr)
if (!skb->len) {
// Frame sent
b_out->tx_skb = NULL;
B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
dev_kfree_skb_any(skb);
B_L1L2(bcs, PH_DATA | CONFIRM, skb);
/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
/* st5481B_sched_event(bcs, B_XMTBUFREADY); */
......
......@@ -366,14 +366,10 @@ W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
if (bcs->tx_skb->len) {
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);
dev_kfree_skb_irq(bcs->tx_skb);
bcs->hw.w6692.count = 0;
bcs->tx_skb = NULL;
}
skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
W6692B_sched_event(bcs, B_CMPLREADY);
bcs->hw.w6692.count = 0;
}
if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.w6692.count = 0;
......
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