Commit 4b921eda authored by Karsten Keil's avatar Karsten Keil Committed by David S. Miller

mISDN: Fix wrong usage of flush_work_sync while holding locks

It is a bad idea to hold a spinlock and call flush_work_sync.
Move the workqueue cleanup outside the spinlock and use cancel_work_sync,
on closing the channel this seems to be the more correct function.
Remove the never used and constant return value of mISDN_freebchannel.
Signed-off-by: default avatarKarsten Keil <keil@b1-systems.de>
Cc: <stable@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 93052169
...@@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) ...@@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) { switch (cmd) {
case CLOSE_CHANNEL: case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags); test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&fc->lock, flags); spin_lock_irqsave(&fc->lock, flags);
mISDN_freebchannel(bch); mISDN_clear_bchannel(bch);
modehdlc(bch, ISDN_P_NONE); modehdlc(bch, ISDN_P_NONE);
spin_unlock_irqrestore(&fc->lock, flags); spin_unlock_irqrestore(&fc->lock, flags);
ch->protocol = ISDN_P_NONE; ch->protocol = ISDN_P_NONE;
......
...@@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) ...@@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) { switch (cmd) {
case CLOSE_CHANNEL: case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags); test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(hx->ip->hwlock, flags); spin_lock_irqsave(hx->ip->hwlock, flags);
mISDN_freebchannel(bch); mISDN_clear_bchannel(bch);
hscx_mode(hx, ISDN_P_NONE); hscx_mode(hx, ISDN_P_NONE);
spin_unlock_irqrestore(hx->ip->hwlock, flags); spin_unlock_irqrestore(hx->ip->hwlock, flags);
ch->protocol = ISDN_P_NONE; ch->protocol = ISDN_P_NONE;
......
...@@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) ...@@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) { switch (cmd) {
case CLOSE_CHANNEL: case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags); test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(ich->is->hwlock, flags); spin_lock_irqsave(ich->is->hwlock, flags);
mISDN_freebchannel(bch); mISDN_clear_bchannel(bch);
modeisar(ich, ISDN_P_NONE); modeisar(ich, ISDN_P_NONE);
spin_unlock_irqrestore(ich->is->hwlock, flags); spin_unlock_irqrestore(ich->is->hwlock, flags);
ch->protocol = ISDN_P_NONE; ch->protocol = ISDN_P_NONE;
......
...@@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) ...@@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) { switch (cmd) {
case CLOSE_CHANNEL: case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags); test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
mISDN_freebchannel(bch); mISDN_clear_bchannel(bch);
mode_tiger(bc, ISDN_P_NONE); mode_tiger(bc, ISDN_P_NONE);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE; ch->protocol = ISDN_P_NONE;
......
...@@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) ...@@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) { switch (cmd) {
case CLOSE_CHANNEL: case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags); test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
mISDN_freebchannel(bch); mISDN_clear_bchannel(bch);
w6692_mode(bc, ISDN_P_NONE); w6692_mode(bc, ISDN_P_NONE);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE; ch->protocol = ISDN_P_NONE;
......
...@@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch) ...@@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch)
ch->next_minlen = ch->init_minlen; ch->next_minlen = ch->init_minlen;
ch->maxlen = ch->init_maxlen; ch->maxlen = ch->init_maxlen;
ch->next_maxlen = ch->init_maxlen; ch->next_maxlen = ch->init_maxlen;
skb_queue_purge(&ch->rqueue);
ch->rcount = 0;
} }
EXPORT_SYMBOL(mISDN_clear_bchannel); EXPORT_SYMBOL(mISDN_clear_bchannel);
int void
mISDN_freebchannel(struct bchannel *ch) mISDN_freebchannel(struct bchannel *ch)
{ {
cancel_work_sync(&ch->workq);
mISDN_clear_bchannel(ch); mISDN_clear_bchannel(ch);
skb_queue_purge(&ch->rqueue);
ch->rcount = 0;
flush_work_sync(&ch->workq);
return 0;
} }
EXPORT_SYMBOL(mISDN_freebchannel); EXPORT_SYMBOL(mISDN_freebchannel);
......
...@@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short, ...@@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short,
unsigned short); unsigned short);
extern int mISDN_freedchannel(struct dchannel *); extern int mISDN_freedchannel(struct dchannel *);
extern void mISDN_clear_bchannel(struct bchannel *); extern void mISDN_clear_bchannel(struct bchannel *);
extern int mISDN_freebchannel(struct bchannel *); extern void mISDN_freebchannel(struct bchannel *);
extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *);
extern void queue_ch_frame(struct mISDNchannel *, u_int, extern void queue_ch_frame(struct mISDNchannel *, u_int,
int, struct sk_buff *); int, struct sk_buff *);
......
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