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>
This commit is contained in:
parent
930521695c
commit
4b921eda53
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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 *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user