Skip to content

Commit

Permalink
mISDN: Fix wrong usage of flush_work_sync while holding locks
Browse files Browse the repository at this point in the history
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: Karsten Keil <[email protected]>
Cc: <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Karsten Keil authored and davem330 committed Sep 13, 2012
1 parent 9305216 commit 4b921ed
Show file tree
Hide file tree
Showing 7 changed files with 15 additions and 11 deletions.
3 changes: 2 additions & 1 deletion drivers/isdn/hardware/mISDN/avmfritz.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&fc->lock, flags);
mISDN_freebchannel(bch);
mISDN_clear_bchannel(bch);
modehdlc(bch, ISDN_P_NONE);
spin_unlock_irqrestore(&fc->lock, flags);
ch->protocol = ISDN_P_NONE;
Expand Down
3 changes: 2 additions & 1 deletion drivers/isdn/hardware/mISDN/mISDNipac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(hx->ip->hwlock, flags);
mISDN_freebchannel(bch);
mISDN_clear_bchannel(bch);
hscx_mode(hx, ISDN_P_NONE);
spin_unlock_irqrestore(hx->ip->hwlock, flags);
ch->protocol = ISDN_P_NONE;
Expand Down
3 changes: 2 additions & 1 deletion drivers/isdn/hardware/mISDN/mISDNisar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(ich->is->hwlock, flags);
mISDN_freebchannel(bch);
mISDN_clear_bchannel(bch);
modeisar(ich, ISDN_P_NONE);
spin_unlock_irqrestore(ich->is->hwlock, flags);
ch->protocol = ISDN_P_NONE;
Expand Down
3 changes: 2 additions & 1 deletion drivers/isdn/hardware/mISDN/netjet.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&card->lock, flags);
mISDN_freebchannel(bch);
mISDN_clear_bchannel(bch);
mode_tiger(bc, ISDN_P_NONE);
spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE;
Expand Down
3 changes: 2 additions & 1 deletion drivers/isdn/hardware/mISDN/w6692.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
cancel_work_sync(&bch->workq);
spin_lock_irqsave(&card->lock, flags);
mISDN_freebchannel(bch);
mISDN_clear_bchannel(bch);
w6692_mode(bc, ISDN_P_NONE);
spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE;
Expand Down
9 changes: 4 additions & 5 deletions drivers/isdn/mISDN/hwchannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch)
ch->next_minlen = ch->init_minlen;
ch->maxlen = ch->init_maxlen;
ch->next_maxlen = ch->init_maxlen;
skb_queue_purge(&ch->rqueue);
ch->rcount = 0;
}
EXPORT_SYMBOL(mISDN_clear_bchannel);

int
void
mISDN_freebchannel(struct bchannel *ch)
{
cancel_work_sync(&ch->workq);
mISDN_clear_bchannel(ch);
skb_queue_purge(&ch->rqueue);
ch->rcount = 0;
flush_work_sync(&ch->workq);
return 0;
}
EXPORT_SYMBOL(mISDN_freebchannel);

Expand Down
2 changes: 1 addition & 1 deletion include/linux/mISDNhw.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ extern int mISDN_initbchannel(struct bchannel *, unsigned short,
unsigned short);
extern int mISDN_freedchannel(struct dchannel *);
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 void queue_ch_frame(struct mISDNchannel *, u_int,
int, struct sk_buff *);
Expand Down

0 comments on commit 4b921ed

Please sign in to comment.