diff options
author | Arun Murthy <arun.murthy@stericsson.com> | 2011-09-09 18:49:22 +0530 |
---|---|---|
committer | Mathieu J. Poirier <mathieu.poirier@linaro.org> | 2011-11-10 11:12:23 -0700 |
commit | 44f9b3d8c11ff71fd599827643a323e6f5a3b6d2 (patch) | |
tree | 32cf44d4039e1d3ece994b7c8098f4057eeb608a | |
parent | faab5ee79062a0f8cb6cea9735a97212b4b22d79 (diff) |
caif-shm: Fix deadlock caused due to improper locking
Improper usage of spin lock, which leads to deadlock.
Tx: acquire_lock1 -> trying to acquire lock2
Rx: acquire_lock2 -> trying to acquire lock1
Fix: locking was done through out the function which is not required.
Only in placed where list has be accessed or modified locking is required.
ST-Ericsson Linux next: NA
ST-Ericsson ID: 360284
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I962fcb35f44b6030d6f1151f118d35e328b69156
Signed-off-by: Arun Murthy <arun.murthy@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30980
Reviewed-by: Hemant-vilas RAMDASI <hemant.ramdasi@stericsson.com>
Tested-by: Hemant-vilas RAMDASI <hemant.ramdasi@stericsson.com>
Reviewed-by: Durga Prasada Rao BATHINA <durgaprasadarao.b@stericsson.com>
-rw-r--r-- | drivers/net/caif/caif_shmcore.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/drivers/net/caif/caif_shmcore.c b/drivers/net/caif/caif_shmcore.c index d4b26fb24ed..27392cd05fd 100644 --- a/drivers/net/caif/caif_shmcore.c +++ b/drivers/net/caif/caif_shmcore.c @@ -238,11 +238,11 @@ int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv) if ((avail_emptybuff > HIGH_WATERMARK) && (!pshm_drv->tx_empty_available)) { pshm_drv->tx_empty_available = 1; + spin_unlock_irqrestore(&pshm_drv->lock, flags); pshm_drv->cfdev.flowctrl (pshm_drv->pshm_dev->pshm_netdev, CAIF_FLOW_ON); - spin_unlock_irqrestore(&pshm_drv->lock, flags); /* Schedule the work queue. if required */ if (!work_pending(&pshm_drv->shm_tx_work)) @@ -285,6 +285,7 @@ static void shm_rx_work_func(struct work_struct *rx_work) list_entry(pshm_drv->rx_full_list.next, struct buf_list, list); list_del_init(&pbuf->list); + spin_unlock_irqrestore(&pshm_drv->lock, flags); /* Retrieve pointer to start of the packet descriptor area. */ pck_desc = (struct shm_pck_desc *) pbuf->desc_vptr; @@ -360,6 +361,7 @@ static void shm_rx_work_func(struct work_struct *rx_work) pck_desc++; } + spin_lock_irqsave(&pshm_drv->lock, flags); list_add_tail(&pbuf->list, &pshm_drv->rx_pend_list); spin_unlock_irqrestore(&pshm_drv->lock, flags); @@ -412,7 +414,6 @@ static void shm_tx_work_func(struct work_struct *tx_work) if (skb == NULL) goto send_msg; - /* Check the available no. of buffers in the empty list */ list_for_each(pos, &pshm_drv->tx_empty_list) avail_emptybuff++; @@ -421,9 +422,11 @@ static void shm_tx_work_func(struct work_struct *tx_work) pshm_drv->tx_empty_available) { /* Update blocking condition. */ pshm_drv->tx_empty_available = 0; + spin_unlock_irqrestore(&pshm_drv->lock, flags); pshm_drv->cfdev.flowctrl (pshm_drv->pshm_dev->pshm_netdev, CAIF_FLOW_OFF); + spin_lock_irqsave(&pshm_drv->lock, flags); } /* * We simply return back to the caller if we do not have space @@ -512,16 +515,11 @@ send_msg: static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev) { struct shmdrv_layer *pshm_drv; - unsigned long flags = 0; pshm_drv = netdev_priv(shm_netdev); - spin_lock_irqsave(&pshm_drv->lock, flags); - skb_queue_tail(&pshm_drv->sk_qhead, skb); - spin_unlock_irqrestore(&pshm_drv->lock, flags); - /* Schedule Tx work queue. for deferred processing of skbs*/ if (!work_pending(&pshm_drv->shm_tx_work)) queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work); |