Skip to content

Commit

Permalink
i4l: Fix random hard freeze with AVM c4 card
Browse files Browse the repository at this point in the history
The patch
- Includes the call to capilib_data_b3_req in the spinlock. This routine
  in turn calls the offending mq_enqueue routine that triggered the
  freeze if not locked.  This should also fix other indicators of
  incosistent capilib_msgidqueue list, that trigger messages like:
  Oct  5 03:05:57 BERL0 kernel: kcapi: msgid 3019 ncci 0x30301 not on queue
  that we saw several times a day (usually several in a row).
- Fixes all occurrences of c4_dispatch_tx to be called with active
  spinlock, there were some instances where no lock was active. Mostly
  these are in very infrequently called routines, so the additional
  performance penalty is minimal.

Signed-off-by: Karsten Keil <kkeil@suse.de>
Signed-off-by: Rainer Brestan <rainer.brestan@frequentis.com>
Signed-off-by: Ralf Schlatterbeck <rsc@runtux.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Karsten Keil authored and Linus Torvalds committed Oct 18, 2007
1 parent 9713d9e commit 1ccfd63
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions drivers/isdn/hardware/avm/c4.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ static void c4_send_init(avmcard *card)
{
struct sk_buff *skb;
void *p;
unsigned long flags;

skb = alloc_skb(15, GFP_ATOMIC);
if (!skb) {
Expand All @@ -744,12 +745,15 @@ static void c4_send_init(avmcard *card)
skb_put(skb, (u8 *)p - (u8 *)skb->data);

skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
}

static int queue_sendconfigword(avmcard *card, u32 val)
{
struct sk_buff *skb;
unsigned long flags;
void *p;

skb = alloc_skb(3+4, GFP_ATOMIC);
Expand All @@ -766,7 +770,9 @@ static int queue_sendconfigword(avmcard *card, u32 val)
skb_put(skb, (u8 *)p - (u8 *)skb->data);

skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
return 0;
}

Expand Down Expand Up @@ -986,7 +992,9 @@ static void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
struct sk_buff *skb;
void *p;

spin_lock_irqsave(&card->lock, flags);
capilib_release_appl(&cinfo->ncci_head, appl);
spin_unlock_irqrestore(&card->lock, flags);

if (ctrl->cnr == card->cardnr) {
skb = alloc_skb(7, GFP_ATOMIC);
Expand Down Expand Up @@ -1019,18 +1027,18 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u16 retval = CAPI_NOERROR;
unsigned long flags;

if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
spin_lock_irqsave(&card->lock, flags);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
}
if (retval == CAPI_NOERROR) {
skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
}
spin_unlock_irqrestore(&card->lock, flags);
return retval;
}

Expand Down

0 comments on commit 1ccfd63

Please sign in to comment.