aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@suse.de>2007-10-18 06:04:31 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:17 -0400
commit9713d9e650045f7f2afd81d58a068827be306993 (patch)
treee4913e15b37f9ad5da9a037fac0f53f3a78cef64
parent0c42ea3f93b5684cf60ba0ac6810ad1f865954b0 (diff)
i4l: fix random freezes with AVM B1 drivers
This fix the same issue which was debbuged for the C4 controller for the B1 versions. The capilib_ function modify or traverse a linked list without locking. This patch extends the existing locking to the calls of these function to prevent access to a list which is in the middle of a modification. Signed-off-by: Karsten Keil <kkeil@suse.de> C: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/isdn/hardware/avm/b1.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 7a69a18d07e2..4484a6417235 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -321,12 +321,15 @@ void b1_reset_ctr(struct capi_ctr *ctrl)
321 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); 321 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
322 avmcard *card = cinfo->card; 322 avmcard *card = cinfo->card;
323 unsigned int port = card->port; 323 unsigned int port = card->port;
324 unsigned long flags;
324 325
325 b1_reset(port); 326 b1_reset(port);
326 b1_reset(port); 327 b1_reset(port);
327 328
328 memset(cinfo->version, 0, sizeof(cinfo->version)); 329 memset(cinfo->version, 0, sizeof(cinfo->version));
330 spin_lock_irqsave(&card->lock, flags);
329 capilib_release(&cinfo->ncci_head); 331 capilib_release(&cinfo->ncci_head);
332 spin_unlock_irqrestore(&card->lock, flags);
330 capi_ctr_reseted(ctrl); 333 capi_ctr_reseted(ctrl);
331} 334}
332 335
@@ -361,9 +364,8 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
361 unsigned int port = card->port; 364 unsigned int port = card->port;
362 unsigned long flags; 365 unsigned long flags;
363 366
364 capilib_release_appl(&cinfo->ncci_head, appl);
365
366 spin_lock_irqsave(&card->lock, flags); 367 spin_lock_irqsave(&card->lock, flags);
368 capilib_release_appl(&cinfo->ncci_head, appl);
367 b1_put_byte(port, SEND_RELEASE); 369 b1_put_byte(port, SEND_RELEASE);
368 b1_put_word(port, appl); 370 b1_put_word(port, appl);
369 spin_unlock_irqrestore(&card->lock, flags); 371 spin_unlock_irqrestore(&card->lock, flags);
@@ -380,27 +382,27 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
380 u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); 382 u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
381 u16 dlen, retval; 383 u16 dlen, retval;
382 384
385 spin_lock_irqsave(&card->lock, flags);
383 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { 386 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
384 retval = capilib_data_b3_req(&cinfo->ncci_head, 387 retval = capilib_data_b3_req(&cinfo->ncci_head,
385 CAPIMSG_APPID(skb->data), 388 CAPIMSG_APPID(skb->data),
386 CAPIMSG_NCCI(skb->data), 389 CAPIMSG_NCCI(skb->data),
387 CAPIMSG_MSGID(skb->data)); 390 CAPIMSG_MSGID(skb->data));
388 if (retval != CAPI_NOERROR) 391 if (retval != CAPI_NOERROR) {
392 spin_unlock_irqrestore(&card->lock, flags);
389 return retval; 393 return retval;
394 }
390 395
391 dlen = CAPIMSG_DATALEN(skb->data); 396 dlen = CAPIMSG_DATALEN(skb->data);
392 397
393 spin_lock_irqsave(&card->lock, flags);
394 b1_put_byte(port, SEND_DATA_B3_REQ); 398 b1_put_byte(port, SEND_DATA_B3_REQ);
395 b1_put_slice(port, skb->data, len); 399 b1_put_slice(port, skb->data, len);
396 b1_put_slice(port, skb->data + len, dlen); 400 b1_put_slice(port, skb->data + len, dlen);
397 spin_unlock_irqrestore(&card->lock, flags);
398 } else { 401 } else {
399 spin_lock_irqsave(&card->lock, flags);
400 b1_put_byte(port, SEND_MESSAGE); 402 b1_put_byte(port, SEND_MESSAGE);
401 b1_put_slice(port, skb->data, len); 403 b1_put_slice(port, skb->data, len);
402 spin_unlock_irqrestore(&card->lock, flags);
403 } 404 }
405 spin_unlock_irqrestore(&card->lock, flags);
404 406
405 dev_kfree_skb_any(skb); 407 dev_kfree_skb_any(skb);
406 return CAPI_NOERROR; 408 return CAPI_NOERROR;
@@ -534,17 +536,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
534 536
535 ApplId = (unsigned) b1_get_word(card->port); 537 ApplId = (unsigned) b1_get_word(card->port);
536 MsgLen = b1_get_slice(card->port, card->msgbuf); 538 MsgLen = b1_get_slice(card->port, card->msgbuf);
537 spin_unlock_irqrestore(&card->lock, flags);
538 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { 539 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
539 printk(KERN_ERR "%s: incoming packet dropped\n", 540 printk(KERN_ERR "%s: incoming packet dropped\n",
540 card->name); 541 card->name);
542 spin_unlock_irqrestore(&card->lock, flags);
541 } else { 543 } else {
542 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); 544 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
543 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) 545 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
544 capilib_data_b3_conf(&cinfo->ncci_head, ApplId, 546 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
545 CAPIMSG_NCCI(skb->data), 547 CAPIMSG_NCCI(skb->data),
546 CAPIMSG_MSGID(skb->data)); 548 CAPIMSG_MSGID(skb->data));
547 549 spin_unlock_irqrestore(&card->lock, flags);
548 capi_ctr_handle_message(ctrl, ApplId, skb); 550 capi_ctr_handle_message(ctrl, ApplId, skb);
549 } 551 }
550 break; 552 break;
@@ -554,21 +556,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr)
554 ApplId = b1_get_word(card->port); 556 ApplId = b1_get_word(card->port);
555 NCCI = b1_get_word(card->port); 557 NCCI = b1_get_word(card->port);
556 WindowSize = b1_get_word(card->port); 558 WindowSize = b1_get_word(card->port);
557 spin_unlock_irqrestore(&card->lock, flags);
558
559 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); 559 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
560 560 spin_unlock_irqrestore(&card->lock, flags);
561 break; 561 break;
562 562
563 case RECEIVE_FREE_NCCI: 563 case RECEIVE_FREE_NCCI:
564 564
565 ApplId = b1_get_word(card->port); 565 ApplId = b1_get_word(card->port);
566 NCCI = b1_get_word(card->port); 566 NCCI = b1_get_word(card->port);
567 spin_unlock_irqrestore(&card->lock, flags);
568
569 if (NCCI != 0xffffffff) 567 if (NCCI != 0xffffffff)
570 capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); 568 capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
571 569 spin_unlock_irqrestore(&card->lock, flags);
572 break; 570 break;
573 571
574 case RECEIVE_START: 572 case RECEIVE_START: