Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Karsten Keil <keil@b1-systems.de>
Cc: <stable@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Karsten Keil and committed by
David S. Miller
4b921eda 93052169

+15 -11
+2 -1
drivers/isdn/hardware/mISDN/avmfritz.c
··· 857 857 switch (cmd) { 858 858 case CLOSE_CHANNEL: 859 859 test_and_clear_bit(FLG_OPEN, &bch->Flags); 860 + cancel_work_sync(&bch->workq); 860 861 spin_lock_irqsave(&fc->lock, flags); 861 - mISDN_freebchannel(bch); 862 + mISDN_clear_bchannel(bch); 862 863 modehdlc(bch, ISDN_P_NONE); 863 864 spin_unlock_irqrestore(&fc->lock, flags); 864 865 ch->protocol = ISDN_P_NONE;
+2 -1
drivers/isdn/hardware/mISDN/mISDNipac.c
··· 1406 1406 switch (cmd) { 1407 1407 case CLOSE_CHANNEL: 1408 1408 test_and_clear_bit(FLG_OPEN, &bch->Flags); 1409 + cancel_work_sync(&bch->workq); 1409 1410 spin_lock_irqsave(hx->ip->hwlock, flags); 1410 - mISDN_freebchannel(bch); 1411 + mISDN_clear_bchannel(bch); 1411 1412 hscx_mode(hx, ISDN_P_NONE); 1412 1413 spin_unlock_irqrestore(hx->ip->hwlock, flags); 1413 1414 ch->protocol = ISDN_P_NONE;
+2 -1
drivers/isdn/hardware/mISDN/mISDNisar.c
··· 1588 1588 switch (cmd) { 1589 1589 case CLOSE_CHANNEL: 1590 1590 test_and_clear_bit(FLG_OPEN, &bch->Flags); 1591 + cancel_work_sync(&bch->workq); 1591 1592 spin_lock_irqsave(ich->is->hwlock, flags); 1592 - mISDN_freebchannel(bch); 1593 + mISDN_clear_bchannel(bch); 1593 1594 modeisar(ich, ISDN_P_NONE); 1594 1595 spin_unlock_irqrestore(ich->is->hwlock, flags); 1595 1596 ch->protocol = ISDN_P_NONE;
+2 -1
drivers/isdn/hardware/mISDN/netjet.c
··· 812 812 switch (cmd) { 813 813 case CLOSE_CHANNEL: 814 814 test_and_clear_bit(FLG_OPEN, &bch->Flags); 815 + cancel_work_sync(&bch->workq); 815 816 spin_lock_irqsave(&card->lock, flags); 816 - mISDN_freebchannel(bch); 817 + mISDN_clear_bchannel(bch); 817 818 mode_tiger(bc, ISDN_P_NONE); 818 819 spin_unlock_irqrestore(&card->lock, flags); 819 820 ch->protocol = ISDN_P_NONE;
+2 -1
drivers/isdn/hardware/mISDN/w6692.c
··· 1054 1054 switch (cmd) { 1055 1055 case CLOSE_CHANNEL: 1056 1056 test_and_clear_bit(FLG_OPEN, &bch->Flags); 1057 + cancel_work_sync(&bch->workq); 1057 1058 spin_lock_irqsave(&card->lock, flags); 1058 - mISDN_freebchannel(bch); 1059 + mISDN_clear_bchannel(bch); 1059 1060 w6692_mode(bc, ISDN_P_NONE); 1060 1061 spin_unlock_irqrestore(&card->lock, flags); 1061 1062 ch->protocol = ISDN_P_NONE;
+4 -5
drivers/isdn/mISDN/hwchannel.c
··· 148 148 ch->next_minlen = ch->init_minlen; 149 149 ch->maxlen = ch->init_maxlen; 150 150 ch->next_maxlen = ch->init_maxlen; 151 + skb_queue_purge(&ch->rqueue); 152 + ch->rcount = 0; 151 153 } 152 154 EXPORT_SYMBOL(mISDN_clear_bchannel); 153 155 154 - int 156 + void 155 157 mISDN_freebchannel(struct bchannel *ch) 156 158 { 159 + cancel_work_sync(&ch->workq); 157 160 mISDN_clear_bchannel(ch); 158 - skb_queue_purge(&ch->rqueue); 159 - ch->rcount = 0; 160 - flush_work_sync(&ch->workq); 161 - return 0; 162 161 } 163 162 EXPORT_SYMBOL(mISDN_freebchannel); 164 163
+1 -1
include/linux/mISDNhw.h
··· 183 183 unsigned short); 184 184 extern int mISDN_freedchannel(struct dchannel *); 185 185 extern void mISDN_clear_bchannel(struct bchannel *); 186 - extern int mISDN_freebchannel(struct bchannel *); 186 + extern void mISDN_freebchannel(struct bchannel *); 187 187 extern int mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *); 188 188 extern void queue_ch_frame(struct mISDNchannel *, u_int, 189 189 int, struct sk_buff *);