Commit 68569b74 authored by Karsten Keil's avatar Karsten Keil Committed by Linus Torvalds

[PATCH] i4l: fix deadlock in CAPI code, reenable SMP

This patch fix a deadlock in CAPI device driver registration code and
reenable SMP for the activ AVM cards., also some minor cleanup and fixes.
Signed-off-by: default avatarKarsten Keil <kkeil@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent dd70a6a7
...@@ -2058,6 +2058,10 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) ...@@ -2058,6 +2058,10 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
return -1; return -1;
} }
card->myid = card->interface.channels; card->myid = card->interface.channels;
memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
for (i = 0; i < card->nbchan; i++) {
card->bchans[i].contr = card;
}
spin_lock_irqsave(&global_lock, flags); spin_lock_irqsave(&global_lock, flags);
card->next = global.contr_list; card->next = global.contr_list;
...@@ -2065,11 +2069,6 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) ...@@ -2065,11 +2069,6 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
global.ncontr++; global.ncontr++;
spin_unlock_irqrestore(&global_lock, flags); spin_unlock_irqrestore(&global_lock, flags);
memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
for (i = 0; i < card->nbchan; i++) {
card->bchans[i].contr = card;
}
cmd.command = ISDN_STAT_RUN; cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid; cmd.driver = card->myid;
card->interface.statcallb(&cmd); card->interface.statcallb(&cmd);
...@@ -2077,10 +2076,9 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) ...@@ -2077,10 +2076,9 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
card->cipmask = 0x1FFF03FF; /* any */ card->cipmask = 0x1FFF03FF; /* any */
card->cipmask2 = 0; card->cipmask2 = 0;
send_listen(card);
card->listentimer.data = (unsigned long)card; card->listentimer.data = (unsigned long)card;
card->listentimer.function = listentimerfunc; card->listentimer.function = listentimerfunc;
send_listen(card);
mod_timer(&card->listentimer, jiffies + 60*HZ); mod_timer(&card->listentimer, jiffies + 60*HZ);
printk(KERN_INFO "%s: now up (%d B channels)\n", printk(KERN_INFO "%s: now up (%d B channels)\n",
......
...@@ -150,7 +150,10 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param ...@@ -150,7 +150,10 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param
{ {
card = capi_ctr_get(card); card = capi_ctr_get(card);
card->register_appl(card, applid, rparam); if (card)
card->register_appl(card, applid, rparam);
else
printk(KERN_WARNING "%s: cannot get card resources\n", __FUNCTION__);
} }
...@@ -173,10 +176,15 @@ static void notify_up(u32 contr) ...@@ -173,10 +176,15 @@ static void notify_up(u32 contr)
if (showcapimsgs & 1) { if (showcapimsgs & 1) {
printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
} }
if (!card) {
printk(KERN_WARNING "%s: invalid contr %d\n", __FUNCTION__, contr);
return;
}
for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
ap = get_capi_appl_by_nr(applid); ap = get_capi_appl_by_nr(applid);
if (ap && ap->callback && !ap->release_in_progress) if (!ap || ap->release_in_progress) continue;
register_appl(card, applid, &ap->rparam);
if (ap->callback && !ap->release_in_progress)
ap->callback(KCI_CONTRUP, contr, &card->profile); ap->callback(KCI_CONTRUP, contr, &card->profile);
} }
} }
...@@ -319,19 +327,8 @@ EXPORT_SYMBOL(capi_ctr_handle_message); ...@@ -319,19 +327,8 @@ EXPORT_SYMBOL(capi_ctr_handle_message);
void capi_ctr_ready(struct capi_ctr * card) void capi_ctr_ready(struct capi_ctr * card)
{ {
u16 appl;
struct capi20_appl *ap;
card->cardstate = CARD_RUNNING; card->cardstate = CARD_RUNNING;
down(&controller_sem);
for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
ap = get_capi_appl_by_nr(appl);
if (!ap || ap->release_in_progress) continue;
register_appl(card, appl, &ap->rparam);
}
up(&controller_sem);
printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
card->cnr, card->name); card->cnr, card->name);
......
...@@ -12,13 +12,13 @@ config CAPI_AVM ...@@ -12,13 +12,13 @@ config CAPI_AVM
config ISDN_DRV_AVMB1_B1ISA config ISDN_DRV_AVMB1_B1ISA
tristate "AVM B1 ISA support" tristate "AVM B1 ISA support"
depends on CAPI_AVM && ISDN_CAPI && ISA && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI && ISA
help help
Enable support for the ISA version of the AVM B1 card. Enable support for the ISA version of the AVM B1 card.
config ISDN_DRV_AVMB1_B1PCI config ISDN_DRV_AVMB1_B1PCI
tristate "AVM B1 PCI support" tristate "AVM B1 PCI support"
depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI && PCI
help help
Enable support for the PCI version of the AVM B1 card. Enable support for the PCI version of the AVM B1 card.
...@@ -30,14 +30,14 @@ config ISDN_DRV_AVMB1_B1PCIV4 ...@@ -30,14 +30,14 @@ config ISDN_DRV_AVMB1_B1PCIV4
config ISDN_DRV_AVMB1_T1ISA config ISDN_DRV_AVMB1_T1ISA
tristate "AVM T1/T1-B ISA support" tristate "AVM T1/T1-B ISA support"
depends on CAPI_AVM && ISDN_CAPI && ISA && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI && ISA
help help
Enable support for the AVM T1 T1B card. Enable support for the AVM T1 T1B card.
Note: This is a PRI card and handle 30 B-channels. Note: This is a PRI card and handle 30 B-channels.
config ISDN_DRV_AVMB1_B1PCMCIA config ISDN_DRV_AVMB1_B1PCMCIA
tristate "AVM B1/M1/M2 PCMCIA support" tristate "AVM B1/M1/M2 PCMCIA support"
depends on CAPI_AVM && ISDN_CAPI && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI
help help
Enable support for the PCMCIA version of the AVM B1 card. Enable support for the PCMCIA version of the AVM B1 card.
...@@ -50,14 +50,14 @@ config ISDN_DRV_AVMB1_AVM_CS ...@@ -50,14 +50,14 @@ config ISDN_DRV_AVMB1_AVM_CS
config ISDN_DRV_AVMB1_T1PCI config ISDN_DRV_AVMB1_T1PCI
tristate "AVM T1/T1-B PCI support" tristate "AVM T1/T1-B PCI support"
depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI && PCI
help help
Enable support for the AVM T1 T1B card. Enable support for the AVM T1 T1B card.
Note: This is a PRI card and handle 30 B-channels. Note: This is a PRI card and handle 30 B-channels.
config ISDN_DRV_AVMB1_C4 config ISDN_DRV_AVMB1_C4
tristate "AVM C4/C2 support" tristate "AVM C4/C2 support"
depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP depends on CAPI_AVM && ISDN_CAPI && PCI
help help
Enable support for the AVM C4/C2 PCI cards. Enable support for the AVM C4/C2 PCI cards.
These cards handle 4/2 BRI ISDN lines (8/4 channels). These cards handle 4/2 BRI ISDN lines (8/4 channels).
......
...@@ -662,15 +662,16 @@ static void c4_handle_rx(avmcard *card) ...@@ -662,15 +662,16 @@ static void c4_handle_rx(avmcard *card)
static irqreturn_t c4_handle_interrupt(avmcard *card) static irqreturn_t c4_handle_interrupt(avmcard *card)
{ {
unsigned long flags;
u32 status; u32 status;
spin_lock(&card->lock); spin_lock_irqsave(&card->lock, flags);
status = c4inmeml(card->mbase+DOORBELL); status = c4inmeml(card->mbase+DOORBELL);
if (status & DBELL_RESET_HOST) { if (status & DBELL_RESET_HOST) {
u_int i; u_int i;
c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
spin_unlock(&card->lock); spin_unlock_irqrestore(&card->lock, flags);
if (card->nlogcontr == 0) if (card->nlogcontr == 0)
return IRQ_HANDLED; return IRQ_HANDLED;
printk(KERN_ERR "%s: unexpected reset\n", card->name); printk(KERN_ERR "%s: unexpected reset\n", card->name);
...@@ -686,7 +687,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) ...@@ -686,7 +687,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
if (!status) { if (!status) {
spin_unlock(&card->lock); spin_unlock_irqrestore(&card->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
c4outmeml(card->mbase+DOORBELL, status); c4outmeml(card->mbase+DOORBELL, status);
...@@ -709,7 +710,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) ...@@ -709,7 +710,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
c4_dispatch_tx(card); c4_dispatch_tx(card);
} }
} }
spin_unlock(&card->lock); spin_unlock_irqrestore(&card->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
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