caif-hsi: Fixing a race condition in the caif_hsi code
cfhsi->tx_state was not protected by a spin lock. TX soft-irq could interrupt cfhsi_tx_done_work work leading to inconsistent state of the driver. Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
94230febe4
commit
fe47f12508
|
@ -304,14 +304,22 @@ static void cfhsi_tx_done_work(struct work_struct *work)
|
||||||
spin_unlock_bh(&cfhsi->lock);
|
spin_unlock_bh(&cfhsi->lock);
|
||||||
|
|
||||||
/* Create HSI frame. */
|
/* Create HSI frame. */
|
||||||
len = cfhsi_tx_frm(desc, cfhsi);
|
do {
|
||||||
if (!len) {
|
len = cfhsi_tx_frm(desc, cfhsi);
|
||||||
cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
|
if (!len) {
|
||||||
/* Start inactivity timer. */
|
spin_lock_bh(&cfhsi->lock);
|
||||||
mod_timer(&cfhsi->timer,
|
if (unlikely(skb_peek(&cfhsi->qhead))) {
|
||||||
|
spin_unlock_bh(&cfhsi->lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
|
||||||
|
/* Start inactivity timer. */
|
||||||
|
mod_timer(&cfhsi->timer,
|
||||||
jiffies + CFHSI_INACTIVITY_TOUT);
|
jiffies + CFHSI_INACTIVITY_TOUT);
|
||||||
break;
|
spin_unlock_bh(&cfhsi->lock);
|
||||||
}
|
goto done;
|
||||||
|
}
|
||||||
|
} while (!len);
|
||||||
|
|
||||||
/* Set up new transfer. */
|
/* Set up new transfer. */
|
||||||
res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
|
res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev);
|
||||||
|
@ -320,6 +328,9 @@ static void cfhsi_tx_done_work(struct work_struct *work)
|
||||||
__func__, res);
|
__func__, res);
|
||||||
}
|
}
|
||||||
} while (res < 0);
|
} while (res < 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
|
static void cfhsi_tx_done_cb(struct cfhsi_drv *drv)
|
||||||
|
|
Loading…
Reference in New Issue