Skip to content

Commit

Permalink
caif-hsi: Fix for wakeup condition problem
Browse files Browse the repository at this point in the history
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dmitry Tarnyagin authored and David S. Miller committed Oct 19, 2011
1 parent fe47f12 commit 73033c9
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions drivers/net/caif/caif_hsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down

0 comments on commit 73033c9

Please sign in to comment.