Commit 095d2a71e51bd2a3e476232156e8d9c2dbc0596d

Authored by sjur.brandeland@stericsson.com
Committed by David S. Miller
1 parent 005b0b076f

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);