Commit 095d2a71e51bd2a3e476232156e8d9c2dbc0596d
Committed by
David S. Miller
1 parent
005b0b076f
Exists in
master
and in
6 other branches
caif-shm: Bugfixes for caif_shmcore.c
Various bugfixes for caif_shmcore.c: - fix deadlocks due to improper usage of spin-lock - add missing spin-lock init - don't call dev_kfree_skb() with irqs disabled, use dev_kfree_skb_irq() instead. - fix potential skb null pointer de-reference. Squashed original patches from: Rabin Vincent <rabin.vincent@stericsson.com> Durga Prasada Rao BATHINA <durgaprasadarao.b@stericcson.com> Arun Murthy <arun.murthy@stericsson.com> Bibek Basu <bibek.basu@stericsson.com> Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 11 additions and 10 deletions Side-by-side Diff
drivers/net/caif/caif_shmcore.c
... | ... | @@ -238,11 +238,11 @@ |
238 | 238 | if ((avail_emptybuff > HIGH_WATERMARK) && |
239 | 239 | (!pshm_drv->tx_empty_available)) { |
240 | 240 | pshm_drv->tx_empty_available = 1; |
241 | + spin_unlock_irqrestore(&pshm_drv->lock, flags); | |
241 | 242 | pshm_drv->cfdev.flowctrl |
242 | 243 | (pshm_drv->pshm_dev->pshm_netdev, |
243 | 244 | CAIF_FLOW_ON); |
244 | 245 | |
245 | - spin_unlock_irqrestore(&pshm_drv->lock, flags); | |
246 | 246 | |
247 | 247 | /* Schedule the work queue. if required */ |
248 | 248 | if (!work_pending(&pshm_drv->shm_tx_work)) |
... | ... | @@ -285,6 +285,7 @@ |
285 | 285 | list_entry(pshm_drv->rx_full_list.next, struct buf_list, |
286 | 286 | list); |
287 | 287 | list_del_init(&pbuf->list); |
288 | + spin_unlock_irqrestore(&pshm_drv->lock, flags); | |
288 | 289 | |
289 | 290 | /* Retrieve pointer to start of the packet descriptor area. */ |
290 | 291 | pck_desc = (struct shm_pck_desc *) pbuf->desc_vptr; |
... | ... | @@ -360,6 +361,7 @@ |
360 | 361 | pck_desc++; |
361 | 362 | } |
362 | 363 | |
364 | + spin_lock_irqsave(&pshm_drv->lock, flags); | |
363 | 365 | list_add_tail(&pbuf->list, &pshm_drv->rx_pend_list); |
364 | 366 | |
365 | 367 | spin_unlock_irqrestore(&pshm_drv->lock, flags); |
... | ... | @@ -412,7 +414,6 @@ |
412 | 414 | |
413 | 415 | if (skb == NULL) |
414 | 416 | goto send_msg; |
415 | - | |
416 | 417 | /* Check the available no. of buffers in the empty list */ |
417 | 418 | list_for_each(pos, &pshm_drv->tx_empty_list) |
418 | 419 | avail_emptybuff++; |
419 | 420 | |
... | ... | @@ -421,9 +422,11 @@ |
421 | 422 | pshm_drv->tx_empty_available) { |
422 | 423 | /* Update blocking condition. */ |
423 | 424 | pshm_drv->tx_empty_available = 0; |
425 | + spin_unlock_irqrestore(&pshm_drv->lock, flags); | |
424 | 426 | pshm_drv->cfdev.flowctrl |
425 | 427 | (pshm_drv->pshm_dev->pshm_netdev, |
426 | 428 | CAIF_FLOW_OFF); |
429 | + spin_lock_irqsave(&pshm_drv->lock, flags); | |
427 | 430 | } |
428 | 431 | /* |
429 | 432 | * We simply return back to the caller if we do not have space |
... | ... | @@ -469,6 +472,8 @@ |
469 | 472 | } |
470 | 473 | |
471 | 474 | skb = skb_dequeue(&pshm_drv->sk_qhead); |
475 | + if (skb == NULL) | |
476 | + break; | |
472 | 477 | /* Copy in CAIF frame. */ |
473 | 478 | skb_copy_bits(skb, 0, pbuf->desc_vptr + |
474 | 479 | pbuf->frm_ofs + SHM_HDR_LEN + |
... | ... | @@ -477,7 +482,7 @@ |
477 | 482 | pshm_drv->pshm_dev->pshm_netdev->stats.tx_packets++; |
478 | 483 | pshm_drv->pshm_dev->pshm_netdev->stats.tx_bytes += |
479 | 484 | frmlen; |
480 | - dev_kfree_skb(skb); | |
485 | + dev_kfree_skb_irq(skb); | |
481 | 486 | |
482 | 487 | /* Fill in the shared memory packet descriptor area. */ |
483 | 488 | pck_desc = (struct shm_pck_desc *) (pbuf->desc_vptr); |
484 | 489 | |
485 | 490 | |
... | ... | @@ -512,16 +517,11 @@ |
512 | 517 | static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev) |
513 | 518 | { |
514 | 519 | struct shmdrv_layer *pshm_drv; |
515 | - unsigned long flags = 0; | |
516 | 520 | |
517 | 521 | pshm_drv = netdev_priv(shm_netdev); |
518 | 522 | |
519 | - spin_lock_irqsave(&pshm_drv->lock, flags); | |
520 | - | |
521 | 523 | skb_queue_tail(&pshm_drv->sk_qhead, skb); |
522 | 524 | |
523 | - spin_unlock_irqrestore(&pshm_drv->lock, flags); | |
524 | - | |
525 | 525 | /* Schedule Tx work queue. for deferred processing of skbs*/ |
526 | 526 | if (!work_pending(&pshm_drv->shm_tx_work)) |
527 | 527 | queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work); |
... | ... | @@ -606,6 +606,7 @@ |
606 | 606 | pshm_drv->shm_rx_addr = pshm_dev->shm_base_addr + |
607 | 607 | (NR_TX_BUF * TX_BUF_SZ); |
608 | 608 | |
609 | + spin_lock_init(&pshm_drv->lock); | |
609 | 610 | INIT_LIST_HEAD(&pshm_drv->tx_empty_list); |
610 | 611 | INIT_LIST_HEAD(&pshm_drv->tx_pend_list); |
611 | 612 | INIT_LIST_HEAD(&pshm_drv->tx_full_list); |
... | ... | @@ -640,7 +641,7 @@ |
640 | 641 | tx_buf->frm_ofs = SHM_CAIF_FRM_OFS; |
641 | 642 | |
642 | 643 | if (pshm_dev->shm_loopback) |
643 | - tx_buf->desc_vptr = (char *)tx_buf->phy_addr; | |
644 | + tx_buf->desc_vptr = (unsigned char *)tx_buf->phy_addr; | |
644 | 645 | else |
645 | 646 | tx_buf->desc_vptr = |
646 | 647 | ioremap(tx_buf->phy_addr, TX_BUF_SZ); |
... | ... | @@ -664,7 +665,7 @@ |
664 | 665 | rx_buf->len = RX_BUF_SZ; |
665 | 666 | |
666 | 667 | if (pshm_dev->shm_loopback) |
667 | - rx_buf->desc_vptr = (char *)rx_buf->phy_addr; | |
668 | + rx_buf->desc_vptr = (unsigned char *)rx_buf->phy_addr; | |
668 | 669 | else |
669 | 670 | rx_buf->desc_vptr = |
670 | 671 | ioremap(rx_buf->phy_addr, RX_BUF_SZ); |