Skip to content

Commit 218ed82

Browse files
Thinh Trankuba-moo
authored andcommitted
i40e: factoring out i40e_suspend/i40e_resume
Two new functions, i40e_io_suspend() and i40e_io_resume(), have been introduced. These functions were factored out from the existing i40e_suspend() and i40e_resume() respectively. This factoring was done due to concerns about the logic of the I40E_SUSPENSED state, which caused the device to be unable to recover. The functions are now used in the EEH handling for device suspend/resume callbacks. The function i40e_enable_mc_magic_wake() has been moved ahead of i40e_io_suspend() to ensure it is declared before being used. Tested-by: Robert Thomas <[email protected]> Signed-off-by: Thinh Tran <[email protected]> Reviewed-by: Simon Horman <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Signed-off-by: Jacob Keller <[email protected]> Link: https://lore.kernel.org/r/20240528-net-2024-05-28-intel-net-fixes-v1-2-dc8593d2bbc6@intel.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent bfd546a commit 218ed82

File tree

1 file changed

+135
-114
lines changed

1 file changed

+135
-114
lines changed

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 135 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -16334,6 +16334,139 @@ static void i40e_remove(struct pci_dev *pdev)
1633416334
pci_disable_device(pdev);
1633516335
}
1633616336

16337+
/**
16338+
* i40e_enable_mc_magic_wake - enable multicast magic packet wake up
16339+
* using the mac_address_write admin q function
16340+
* @pf: pointer to i40e_pf struct
16341+
**/
16342+
static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
16343+
{
16344+
struct i40e_vsi *main_vsi = i40e_pf_get_main_vsi(pf);
16345+
struct i40e_hw *hw = &pf->hw;
16346+
u8 mac_addr[6];
16347+
u16 flags = 0;
16348+
int ret;
16349+
16350+
/* Get current MAC address in case it's an LAA */
16351+
if (main_vsi && main_vsi->netdev) {
16352+
ether_addr_copy(mac_addr, main_vsi->netdev->dev_addr);
16353+
} else {
16354+
dev_err(&pf->pdev->dev,
16355+
"Failed to retrieve MAC address; using default\n");
16356+
ether_addr_copy(mac_addr, hw->mac.addr);
16357+
}
16358+
16359+
/* The FW expects the mac address write cmd to first be called with
16360+
* one of these flags before calling it again with the multicast
16361+
* enable flags.
16362+
*/
16363+
flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
16364+
16365+
if (hw->func_caps.flex10_enable && hw->partition_id != 1)
16366+
flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
16367+
16368+
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
16369+
if (ret) {
16370+
dev_err(&pf->pdev->dev,
16371+
"Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
16372+
return;
16373+
}
16374+
16375+
flags = I40E_AQC_MC_MAG_EN
16376+
| I40E_AQC_WOL_PRESERVE_ON_PFR
16377+
| I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
16378+
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
16379+
if (ret)
16380+
dev_err(&pf->pdev->dev,
16381+
"Failed to enable Multicast Magic Packet wake up\n");
16382+
}
16383+
16384+
/**
16385+
* i40e_io_suspend - suspend all IO operations
16386+
* @pf: pointer to i40e_pf struct
16387+
*
16388+
**/
16389+
static int i40e_io_suspend(struct i40e_pf *pf)
16390+
{
16391+
struct i40e_hw *hw = &pf->hw;
16392+
16393+
set_bit(__I40E_DOWN, pf->state);
16394+
16395+
/* Ensure service task will not be running */
16396+
del_timer_sync(&pf->service_timer);
16397+
cancel_work_sync(&pf->service_task);
16398+
16399+
/* Client close must be called explicitly here because the timer
16400+
* has been stopped.
16401+
*/
16402+
i40e_notify_client_of_netdev_close(pf, false);
16403+
16404+
if (test_bit(I40E_HW_CAP_WOL_MC_MAGIC_PKT_WAKE, pf->hw.caps) &&
16405+
pf->wol_en)
16406+
i40e_enable_mc_magic_wake(pf);
16407+
16408+
/* Since we're going to destroy queues during the
16409+
* i40e_clear_interrupt_scheme() we should hold the RTNL lock for this
16410+
* whole section
16411+
*/
16412+
rtnl_lock();
16413+
16414+
i40e_prep_for_reset(pf);
16415+
16416+
wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
16417+
wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
16418+
16419+
/* Clear the interrupt scheme and release our IRQs so that the system
16420+
* can safely hibernate even when there are a large number of CPUs.
16421+
* Otherwise hibernation might fail when mapping all the vectors back
16422+
* to CPU0.
16423+
*/
16424+
i40e_clear_interrupt_scheme(pf);
16425+
16426+
rtnl_unlock();
16427+
16428+
return 0;
16429+
}
16430+
16431+
/**
16432+
* i40e_io_resume - resume IO operations
16433+
* @pf: pointer to i40e_pf struct
16434+
*
16435+
**/
16436+
static int i40e_io_resume(struct i40e_pf *pf)
16437+
{
16438+
struct device *dev = &pf->pdev->dev;
16439+
int err;
16440+
16441+
/* We need to hold the RTNL lock prior to restoring interrupt schemes,
16442+
* since we're going to be restoring queues
16443+
*/
16444+
rtnl_lock();
16445+
16446+
/* We cleared the interrupt scheme when we suspended, so we need to
16447+
* restore it now to resume device functionality.
16448+
*/
16449+
err = i40e_restore_interrupt_scheme(pf);
16450+
if (err) {
16451+
dev_err(dev, "Cannot restore interrupt scheme: %d\n",
16452+
err);
16453+
}
16454+
16455+
clear_bit(__I40E_DOWN, pf->state);
16456+
i40e_reset_and_rebuild(pf, false, true);
16457+
16458+
rtnl_unlock();
16459+
16460+
/* Clear suspended state last after everything is recovered */
16461+
clear_bit(__I40E_SUSPENDED, pf->state);
16462+
16463+
/* Restart the service task */
16464+
mod_timer(&pf->service_timer,
16465+
round_jiffies(jiffies + pf->service_timer_period));
16466+
16467+
return 0;
16468+
}
16469+
1633716470
/**
1633816471
* i40e_pci_error_detected - warning that something funky happened in PCI land
1633916472
* @pdev: PCI device information struct
@@ -16446,53 +16579,6 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
1644616579
i40e_handle_reset_warning(pf, false);
1644716580
}
1644816581

16449-
/**
16450-
* i40e_enable_mc_magic_wake - enable multicast magic packet wake up
16451-
* using the mac_address_write admin q function
16452-
* @pf: pointer to i40e_pf struct
16453-
**/
16454-
static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
16455-
{
16456-
struct i40e_vsi *main_vsi = i40e_pf_get_main_vsi(pf);
16457-
struct i40e_hw *hw = &pf->hw;
16458-
u8 mac_addr[6];
16459-
u16 flags = 0;
16460-
int ret;
16461-
16462-
/* Get current MAC address in case it's an LAA */
16463-
if (main_vsi && main_vsi->netdev) {
16464-
ether_addr_copy(mac_addr, main_vsi->netdev->dev_addr);
16465-
} else {
16466-
dev_err(&pf->pdev->dev,
16467-
"Failed to retrieve MAC address; using default\n");
16468-
ether_addr_copy(mac_addr, hw->mac.addr);
16469-
}
16470-
16471-
/* The FW expects the mac address write cmd to first be called with
16472-
* one of these flags before calling it again with the multicast
16473-
* enable flags.
16474-
*/
16475-
flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
16476-
16477-
if (hw->func_caps.flex10_enable && hw->partition_id != 1)
16478-
flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
16479-
16480-
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
16481-
if (ret) {
16482-
dev_err(&pf->pdev->dev,
16483-
"Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
16484-
return;
16485-
}
16486-
16487-
flags = I40E_AQC_MC_MAG_EN
16488-
| I40E_AQC_WOL_PRESERVE_ON_PFR
16489-
| I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
16490-
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
16491-
if (ret)
16492-
dev_err(&pf->pdev->dev,
16493-
"Failed to enable Multicast Magic Packet wake up\n");
16494-
}
16495-
1649616582
/**
1649716583
* i40e_shutdown - PCI callback for shutting down
1649816584
* @pdev: PCI device information struct
@@ -16552,48 +16638,11 @@ static void i40e_shutdown(struct pci_dev *pdev)
1655216638
static int i40e_suspend(struct device *dev)
1655316639
{
1655416640
struct i40e_pf *pf = dev_get_drvdata(dev);
16555-
struct i40e_hw *hw = &pf->hw;
1655616641

1655716642
/* If we're already suspended, then there is nothing to do */
1655816643
if (test_and_set_bit(__I40E_SUSPENDED, pf->state))
1655916644
return 0;
16560-
16561-
set_bit(__I40E_DOWN, pf->state);
16562-
16563-
/* Ensure service task will not be running */
16564-
del_timer_sync(&pf->service_timer);
16565-
cancel_work_sync(&pf->service_task);
16566-
16567-
/* Client close must be called explicitly here because the timer
16568-
* has been stopped.
16569-
*/
16570-
i40e_notify_client_of_netdev_close(pf, false);
16571-
16572-
if (test_bit(I40E_HW_CAP_WOL_MC_MAGIC_PKT_WAKE, pf->hw.caps) &&
16573-
pf->wol_en)
16574-
i40e_enable_mc_magic_wake(pf);
16575-
16576-
/* Since we're going to destroy queues during the
16577-
* i40e_clear_interrupt_scheme() we should hold the RTNL lock for this
16578-
* whole section
16579-
*/
16580-
rtnl_lock();
16581-
16582-
i40e_prep_for_reset(pf);
16583-
16584-
wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
16585-
wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
16586-
16587-
/* Clear the interrupt scheme and release our IRQs so that the system
16588-
* can safely hibernate even when there are a large number of CPUs.
16589-
* Otherwise hibernation might fail when mapping all the vectors back
16590-
* to CPU0.
16591-
*/
16592-
i40e_clear_interrupt_scheme(pf);
16593-
16594-
rtnl_unlock();
16595-
16596-
return 0;
16645+
return i40e_io_suspend(pf);
1659716646
}
1659816647

1659916648
/**
@@ -16603,39 +16652,11 @@ static int i40e_suspend(struct device *dev)
1660316652
static int i40e_resume(struct device *dev)
1660416653
{
1660516654
struct i40e_pf *pf = dev_get_drvdata(dev);
16606-
int err;
1660716655

1660816656
/* If we're not suspended, then there is nothing to do */
1660916657
if (!test_bit(__I40E_SUSPENDED, pf->state))
1661016658
return 0;
16611-
16612-
/* We need to hold the RTNL lock prior to restoring interrupt schemes,
16613-
* since we're going to be restoring queues
16614-
*/
16615-
rtnl_lock();
16616-
16617-
/* We cleared the interrupt scheme when we suspended, so we need to
16618-
* restore it now to resume device functionality.
16619-
*/
16620-
err = i40e_restore_interrupt_scheme(pf);
16621-
if (err) {
16622-
dev_err(dev, "Cannot restore interrupt scheme: %d\n",
16623-
err);
16624-
}
16625-
16626-
clear_bit(__I40E_DOWN, pf->state);
16627-
i40e_reset_and_rebuild(pf, false, true);
16628-
16629-
rtnl_unlock();
16630-
16631-
/* Clear suspended state last after everything is recovered */
16632-
clear_bit(__I40E_SUSPENDED, pf->state);
16633-
16634-
/* Restart the service task */
16635-
mod_timer(&pf->service_timer,
16636-
round_jiffies(jiffies + pf->service_timer_period));
16637-
16638-
return 0;
16659+
return i40e_io_resume(pf);
1663916660
}
1664016661

1664116662
static const struct pci_error_handlers i40e_err_handler = {

0 commit comments

Comments
 (0)