enc28j60: Fix race condition in enc28j60 driver
authorSergio Valverde <sergio.valverde@hpe.com>
Fri, 1 Jul 2016 17:44:30 +0000 (11:44 -0600)
committerDavid S. Miller <davem@davemloft.net>
Sat, 2 Jul 2016 18:48:14 +0000 (14:48 -0400)
commit373819ec391de0d11f63b10b2fb69ef2854236ca
tree4332984378cd9320cf8e2e527d22be6233fba5b5
parenta8b7d7709dc6db7d6d8a9a04aa9d49b029a27203
enc28j60: Fix race condition in enc28j60 driver

The interrupt worker code for the enc28j60 relies only on the TXIF flag to
determinate if the packet transmission was completed. However the datasheet
specifies in section 12.1.3 that TXERIF will clear the TXRTS after a
transmit abort. Also in section 12.1.4 that TXIF will be set
when TXRTS transitions from '1' to '0'. Therefore the TXIF flag is enabled
during transmission errors.

This causes a race condition, since the worker code will invoke
enc28j60_tx_clear() -> netif_wake_queue(), potentially invoking the
ndo_start_xmit function to send a new packet. The enc28j60_send_packet function
uses a workqueue that invokes enc28j60_hw_tx(). In between this function is
called, the worker from the interrupt handler will enter the path for error
handler because of the TXERIF flag, causing to invoke enc28j60_tx_clear() again
and releasing the packet scheduled for transmission, causing a kernel crash with
due a NULL pointer.

These crashes due a NULL pointer were observed under stress conditions of the
device. A BUG_ON() sequence was used to validate the issue was fixed, and has
been running without problems for 2 years now.

Signed-off-by: Diego Dompe <dompe@hpe.com>
Acked-by: Sergio Valverde <sergio.valverde@hpe.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/enc28j60.c