[Intel-wired-lan] [PATCH net v2] iavf: Fix asynchronous tasks during driver remove
Stefan Assmann
sassmann at redhat.com
Fri Mar 12 12:36:15 UTC 2021
On 2021-03-12 10:33, Eryk Rybak wrote:
> Although rare, is possible for unexpected driver watchdog or Admin
> Queue tasks to run during the execution of iavf_remove function.
> Then, is not possible to obtain the standard __IAVF_IN_CRITICAL_TASK
> lock and difficult to ensure that the driver state stays consistent
> during the full removal process.
If you shutdown the watchdog task before closing the device, how do you
ensure the client task is properly shutdown?
Calling iavf_close() sets the IAVF_FLAG_CLIENT_NEEDS_CLOSE flag, which
would call iavf_notify_client_close(&adapter->vsi, false); in the
client task, but the client task does no longer get scheduled by the
watchdog task because it has been shutdown already.
Stefan
> Fully stops all asynchronous tasks in the beginning of iavf_remove,
> and uses a single-threaded flow to shut down the driver.
>
> Fixes: fdd4044ffdc8("iavf: Remove timer for work triggering, use delaying work instead")
> Signed-off-by: Nick Nunley <nicholas.d.nunley at intel.com>
> Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov at intel.com>
> Signed-off-by: Eryk Rybak <eryk.roch.rybak at intel.com>
> ---
> drivers/net/ethernet/intel/iavf/iavf_main.c | 31 +++++++++++++++++----
> 1 file changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
> index dc5b3c06d1e0..e752ecb7ad89 100644
> --- a/drivers/net/ethernet/intel/iavf/iavf_main.c
> +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
> @@ -1887,6 +1887,12 @@ static void iavf_watchdog_task(struct work_struct *work)
> struct iavf_hw *hw = &adapter->hw;
> u32 reg_val;
>
> + /* If the driver is in the process of being removed then don't run or
> + * reschedule the watchdog task.
> + */
> + if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
> + return;
> +
> if (test_and_set_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section))
> goto restart_watchdog;
>
> @@ -2267,6 +2273,12 @@ static void iavf_adminq_task(struct work_struct *work)
> u32 val, oldval;
> u16 pending;
>
> + /* If the driver is in the process of being removed then return
> + * immediately and don't re-enable the Admin Queue interrupt.
> + */
> + if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
> + return;
> +
> if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
> goto out;
>
> @@ -3245,6 +3257,13 @@ static int iavf_close(struct net_device *netdev)
>
> clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
>
> + /* If the interface is closing as part of driver removal it doesn't
> + * wait. The VF resources will be reinitialized when the hardware is
> + * reset.
> + */
> + if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
> + return 0;
> +
> /* We explicitly don't free resources here because the hardware is
> * still active and can DMA into memory. Resources are cleared in
> * iavf_virtchnl_completion() after we get confirmation from the PF
> @@ -3850,11 +3869,16 @@ static void iavf_remove(struct pci_dev *pdev)
> struct iavf_cloud_filter *cf, *cftmp;
> struct iavf_hw *hw = &adapter->hw;
> int err;
> - /* Indicate we are in remove and not to run reset_task */
> + /* Indicate that program driver is remove task and not
> + * to run/schedule any driver tasks
> + */
> set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section);
> cancel_delayed_work_sync(&adapter->init_task);
> cancel_work_sync(&adapter->reset_task);
> cancel_delayed_work_sync(&adapter->client_task);
> + cancel_work_sync(&adapter->adminq_task);
> + cancel_delayed_work_sync(&adapter->watchdog_task);
> + iavf_misc_irq_disable(adapter);
> if (adapter->netdev_registered) {
> unregister_netdev(netdev);
> adapter->netdev_registered = false;
> @@ -3879,15 +3903,10 @@ static void iavf_remove(struct pci_dev *pdev)
> }
> iavf_free_all_tx_resources(adapter);
> iavf_free_all_rx_resources(adapter);
> - iavf_misc_irq_disable(adapter);
> iavf_free_misc_irq(adapter);
> iavf_reset_interrupt_capability(adapter);
> iavf_free_q_vectors(adapter);
>
> - cancel_delayed_work_sync(&adapter->watchdog_task);
> -
> - cancel_work_sync(&adapter->adminq_task);
> -
> iavf_free_rss(adapter);
>
> if (hw->aq.asq.count)
>
> base-commit: c1acda9807e2bbe1d2026b44f37d959d6d8266c8
> --
> 2.20.1
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan at osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
>
More information about the Intel-wired-lan
mailing list