diff mbox

[3/8] caif-hsi: Fix for wakeup condition problem

Message ID 1318541369-8141-4-git-send-email-sjur.brandeland@stericsson.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

sjur.brandeland@stericsson.com Oct. 13, 2011, 9:29 p.m. UTC
From: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>

Under stressed conditions a race could happen when del_timer_sync() was called
from softirq context at the same time when mod_timer_pending() for the same
timer was called from the workqueue. This leaded to a state mismatch in the
CAIF HSI driver and following unexpected link wakeup procedure.

The fix puts del_timer_sync() and mod_timer_pending() calls under a spin lock
to protect against the race condition.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
---
 drivers/net/caif/caif_hsi.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
index 36da27b..82c4d6c 100644
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -551,7 +551,9 @@  static void cfhsi_rx_done_work(struct work_struct *work)
 		return;
 
 	/* Update inactivity timer if pending. */
+	spin_lock_bh(&cfhsi->lock);
 	mod_timer_pending(&cfhsi->timer, jiffies + CFHSI_INACTIVITY_TOUT);
+	spin_unlock_bh(&cfhsi->lock);
 
 	if (cfhsi->rx_state == CFHSI_RX_STATE_DESC) {
 		desc_pld_len = cfhsi_rx_desc(desc, cfhsi);
@@ -866,10 +868,10 @@  static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
 		start_xfer = 1;
 	}
 
-	spin_unlock_bh(&cfhsi->lock);
-
-	if (!start_xfer)
+	if (!start_xfer) {
+		spin_unlock_bh(&cfhsi->lock);
 		return 0;
+	}
 
 	/* Delete inactivity timer if started. */
 #ifdef CONFIG_SMP
@@ -878,6 +880,8 @@  static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
 	timer_active = del_timer(&cfhsi->timer);
 #endif /* CONFIG_SMP */
 
+	spin_unlock_bh(&cfhsi->lock);
+
 	if (timer_active) {
 		struct cfhsi_desc *desc = (struct cfhsi_desc *)cfhsi->tx_buf;
 		int len;