Skip to content

Commit 676f44c

Browse files
ShayAgrosgregkh
authored andcommitted
net: ena: Prevent reset after device destruction
[ Upstream commit 63d4a4c ] The reset work is scheduled by the timer routine whenever it detects that a device reset is required (e.g. when a keep_alive signal is missing). When releasing device resources in ena_destroy_device() the driver cancels the scheduling of the timer routine without destroying the reset work explicitly. This creates the following bug: The driver is suspended and the ena_suspend() function is called -> This function calls ena_destroy_device() to free the net device resources -> The driver waits for the timer routine to finish its execution and then cancels it, thus preventing from it to be called again. If, in its final execution, the timer routine schedules a reset, the reset routine might be called afterwards,and a redundant call to ena_restore_device() would be made. By changing the reset routine we allow it to read the device's state accurately. This is achieved by checking whether ENA_FLAG_TRIGGER_RESET flag is set before resetting the device and making both the destruction function and the flag check are under rtnl lock. The ENA_FLAG_TRIGGER_RESET is cleared at the end of the destruction routine. Also surround the flag check with 'likely' because we expect that the reset routine would be called only when ENA_FLAG_TRIGGER_RESET flag is set. The destruction of the timer and reset services in __ena_shutoff() have to stay, even though the timer routine is destroyed in ena_destroy_device(). This is to avoid a case in which the reset routine is scheduled after free_netdev() in __ena_shutoff(), which would create an access to freed memory in adapter->flags. Fixes: 8c5c7ab ("net: ena: add power management ops to the ENA driver") Signed-off-by: Shay Agroskin <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent ae405ea commit 676f44c

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

drivers/net/ethernet/amazon/ena/ena_netdev.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2647,16 +2647,14 @@ static void ena_fw_reset_device(struct work_struct *work)
26472647
{
26482648
struct ena_adapter *adapter =
26492649
container_of(work, struct ena_adapter, reset_task);
2650-
struct pci_dev *pdev = adapter->pdev;
26512650

2652-
if (unlikely(!test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
2653-
dev_err(&pdev->dev,
2654-
"device reset schedule while reset bit is off\n");
2655-
return;
2656-
}
26572651
rtnl_lock();
2658-
ena_destroy_device(adapter, false);
2659-
ena_restore_device(adapter);
2652+
2653+
if (likely(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
2654+
ena_destroy_device(adapter, false);
2655+
ena_restore_device(adapter);
2656+
}
2657+
26602658
rtnl_unlock();
26612659
}
26622660

@@ -3392,8 +3390,11 @@ static void ena_remove(struct pci_dev *pdev)
33923390
netdev->rx_cpu_rmap = NULL;
33933391
}
33943392
#endif /* CONFIG_RFS_ACCEL */
3395-
del_timer_sync(&adapter->timer_service);
33963393

3394+
/* Make sure timer and reset routine won't be called after
3395+
* freeing device resources.
3396+
*/
3397+
del_timer_sync(&adapter->timer_service);
33973398
cancel_work_sync(&adapter->reset_task);
33983399

33993400
unregister_netdev(netdev);

0 commit comments

Comments
 (0)