wl3501_cs: Add spinlock to wl3501_reset

Likely wl3501_reset should acquire spinlock as wl3501_{open, close}.
One of calls of wl3501_reset has been already protected.
The others were unprotected and might lead to a race condition.
The patch adds spinlock into the wl3501_reset and removes it from
wl3501_tx_timeout.

Found by Linux Driver Verification project (linuxtesting.org)

Signed-off-by: Pavel Andrianov <andrianov@ispras.ru>
Acked-by: Vaishali Thakkar <vaishali.thakkar@oracle.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Pavel Andrianov 2016-08-02 12:41:53 +03:00 коммит произвёл Kalle Valo
Родитель b0d80f19c1
Коммит bd6b024265
1 изменённых файлов: 3 добавлений и 4 удалений

Просмотреть файл

@ -1258,7 +1258,9 @@ static int wl3501_reset(struct net_device *dev)
{
struct wl3501_card *this = netdev_priv(dev);
int rc = -ENODEV;
unsigned long flags;
spin_lock_irqsave(&this->lock, flags);
wl3501_block_interrupt(this);
if (wl3501_init_firmware(this)) {
@ -1280,20 +1282,17 @@ static int wl3501_reset(struct net_device *dev)
pr_debug("%s: device reset", dev->name);
rc = 0;
out:
spin_unlock_irqrestore(&this->lock, flags);
return rc;
}
static void wl3501_tx_timeout(struct net_device *dev)
{
struct wl3501_card *this = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
unsigned long flags;
int rc;
stats->tx_errors++;
spin_lock_irqsave(&this->lock, flags);
rc = wl3501_reset(dev);
spin_unlock_irqrestore(&this->lock, flags);
if (rc)
printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",
dev->name, rc);