Commit 602d9591 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'intel-wired-lan-driver-updates-2024-05-28-e1000e-i40e-ice'

Jacob Keller says:

====================
Intel Wired LAN Driver Updates 2024-05-28 (e1000e, i40e, ice) [part]

This series includes a variety of fixes that have been accumulating on the
Intel Wired LAN dev-queue.

Hui Wang provides a fix for suspend/resume on e1000e due to failure
to correctly setup the SMBUS in enable_ulp().

Thinh Tran provides a fix for EEH I/O suspend/resume on i40e to
ensure that I/O operations can continue after a resume. To avoid duplicate
code, the common logic is factored out of i40e_suspend and i40e_resume.

Paul Greenwalt provides a fix to correctly map the 200G PHY types to link
speeds in the ice driver.

Dave Ertman provides a fix correcting devlink parameter unregistration in
the event that the driver loads in safe mode and some of the parameters
were not registered.
====================

Link: https://lore.kernel.org/r/20240528-net-2024-05-28-intel-net-fixes-v1-0-dc8593d2bbc6@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 278d65cc a51c9b1c
...@@ -1225,6 +1225,28 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) ...@@ -1225,6 +1225,28 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
} }
release: release:
/* Switching PHY interface always returns MDI error
* so disable retry mechanism to avoid wasting time
*/
e1000e_disable_phy_retry(hw);
/* Force SMBus mode in PHY */
ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
if (ret_val) {
e1000e_enable_phy_retry(hw);
hw->phy.ops.release(hw);
goto out;
}
phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
e1000e_enable_phy_retry(hw);
/* Force SMBus mode in MAC */
mac_reg = er32(CTRL_EXT);
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
ew32(CTRL_EXT, mac_reg);
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
out: out:
if (ret_val) if (ret_val)
......
...@@ -6623,7 +6623,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) ...@@ -6623,7 +6623,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 ctrl, ctrl_ext, rctl, status, wufc; u32 ctrl, ctrl_ext, rctl, status, wufc;
int retval = 0; int retval = 0;
u16 smb_ctrl;
/* Runtime suspend should only enable wakeup for link changes */ /* Runtime suspend should only enable wakeup for link changes */
if (runtime) if (runtime)
...@@ -6697,23 +6696,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) ...@@ -6697,23 +6696,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
if (retval) if (retval)
return retval; return retval;
} }
/* Force SMBUS to allow WOL */
/* Switching PHY interface always returns MDI error
* so disable retry mechanism to avoid wasting time
*/
e1000e_disable_phy_retry(hw);
e1e_rphy(hw, CV_SMB_CTRL, &smb_ctrl);
smb_ctrl |= CV_SMB_CTRL_FORCE_SMBUS;
e1e_wphy(hw, CV_SMB_CTRL, smb_ctrl);
e1000e_enable_phy_retry(hw);
/* Force SMBus mode in MAC */
ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_FORCE_SMBUS;
ew32(CTRL_EXT, ctrl_ext);
} }
/* Ensure that the appropriate bits are set in LPI_CTRL /* Ensure that the appropriate bits are set in LPI_CTRL
......
...@@ -11171,6 +11171,8 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit, ...@@ -11171,6 +11171,8 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
ret = i40e_reset(pf); ret = i40e_reset(pf);
if (!ret) if (!ret)
i40e_rebuild(pf, reinit, lock_acquired); i40e_rebuild(pf, reinit, lock_acquired);
else
dev_err(&pf->pdev->dev, "%s: i40e_reset() FAILED", __func__);
} }
/** /**
...@@ -16334,6 +16336,139 @@ static void i40e_remove(struct pci_dev *pdev) ...@@ -16334,6 +16336,139 @@ static void i40e_remove(struct pci_dev *pdev)
pci_disable_device(pdev); pci_disable_device(pdev);
} }
/**
* i40e_enable_mc_magic_wake - enable multicast magic packet wake up
* using the mac_address_write admin q function
* @pf: pointer to i40e_pf struct
**/
static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
{
struct i40e_vsi *main_vsi = i40e_pf_get_main_vsi(pf);
struct i40e_hw *hw = &pf->hw;
u8 mac_addr[6];
u16 flags = 0;
int ret;
/* Get current MAC address in case it's an LAA */
if (main_vsi && main_vsi->netdev) {
ether_addr_copy(mac_addr, main_vsi->netdev->dev_addr);
} else {
dev_err(&pf->pdev->dev,
"Failed to retrieve MAC address; using default\n");
ether_addr_copy(mac_addr, hw->mac.addr);
}
/* The FW expects the mac address write cmd to first be called with
* one of these flags before calling it again with the multicast
* enable flags.
*/
flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
if (hw->func_caps.flex10_enable && hw->partition_id != 1)
flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret) {
dev_err(&pf->pdev->dev,
"Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
return;
}
flags = I40E_AQC_MC_MAG_EN
| I40E_AQC_WOL_PRESERVE_ON_PFR
| I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret)
dev_err(&pf->pdev->dev,
"Failed to enable Multicast Magic Packet wake up\n");
}
/**
* i40e_io_suspend - suspend all IO operations
* @pf: pointer to i40e_pf struct
*
**/
static int i40e_io_suspend(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
set_bit(__I40E_DOWN, pf->state);
/* Ensure service task will not be running */
del_timer_sync(&pf->service_timer);
cancel_work_sync(&pf->service_task);
/* Client close must be called explicitly here because the timer
* has been stopped.
*/
i40e_notify_client_of_netdev_close(pf, false);
if (test_bit(I40E_HW_CAP_WOL_MC_MAGIC_PKT_WAKE, pf->hw.caps) &&
pf->wol_en)
i40e_enable_mc_magic_wake(pf);
/* Since we're going to destroy queues during the
* i40e_clear_interrupt_scheme() we should hold the RTNL lock for this
* whole section
*/
rtnl_lock();
i40e_prep_for_reset(pf);
wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
/* Clear the interrupt scheme and release our IRQs so that the system
* can safely hibernate even when there are a large number of CPUs.
* Otherwise hibernation might fail when mapping all the vectors back
* to CPU0.
*/
i40e_clear_interrupt_scheme(pf);
rtnl_unlock();
return 0;
}
/**
* i40e_io_resume - resume IO operations
* @pf: pointer to i40e_pf struct
*
**/
static int i40e_io_resume(struct i40e_pf *pf)
{
struct device *dev = &pf->pdev->dev;
int err;
/* We need to hold the RTNL lock prior to restoring interrupt schemes,
* since we're going to be restoring queues
*/
rtnl_lock();
/* We cleared the interrupt scheme when we suspended, so we need to
* restore it now to resume device functionality.
*/
err = i40e_restore_interrupt_scheme(pf);
if (err) {
dev_err(dev, "Cannot restore interrupt scheme: %d\n",
err);
}
clear_bit(__I40E_DOWN, pf->state);
i40e_reset_and_rebuild(pf, false, true);
rtnl_unlock();
/* Clear suspended state last after everything is recovered */
clear_bit(__I40E_SUSPENDED, pf->state);
/* Restart the service task */
mod_timer(&pf->service_timer,
round_jiffies(jiffies + pf->service_timer_period));
return 0;
}
/** /**
* i40e_pci_error_detected - warning that something funky happened in PCI land * i40e_pci_error_detected - warning that something funky happened in PCI land
* @pdev: PCI device information struct * @pdev: PCI device information struct
...@@ -16358,7 +16493,7 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev, ...@@ -16358,7 +16493,7 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev,
/* shutdown all operations */ /* shutdown all operations */
if (!test_bit(__I40E_SUSPENDED, pf->state)) if (!test_bit(__I40E_SUSPENDED, pf->state))
i40e_prep_for_reset(pf); i40e_io_suspend(pf);
/* Request a slot reset */ /* Request a slot reset */
return PCI_ERS_RESULT_NEED_RESET; return PCI_ERS_RESULT_NEED_RESET;
...@@ -16380,7 +16515,8 @@ static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev) ...@@ -16380,7 +16515,8 @@ static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev)
u32 reg; u32 reg;
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
if (pci_enable_device_mem(pdev)) { /* enable I/O and memory of the device */
if (pci_enable_device(pdev)) {
dev_info(&pdev->dev, dev_info(&pdev->dev,
"Cannot re-enable PCI device after reset.\n"); "Cannot re-enable PCI device after reset.\n");
result = PCI_ERS_RESULT_DISCONNECT; result = PCI_ERS_RESULT_DISCONNECT;
...@@ -16443,54 +16579,7 @@ static void i40e_pci_error_resume(struct pci_dev *pdev) ...@@ -16443,54 +16579,7 @@ static void i40e_pci_error_resume(struct pci_dev *pdev)
if (test_bit(__I40E_SUSPENDED, pf->state)) if (test_bit(__I40E_SUSPENDED, pf->state))
return; return;
i40e_handle_reset_warning(pf, false); i40e_io_resume(pf);
}
/**
* i40e_enable_mc_magic_wake - enable multicast magic packet wake up
* using the mac_address_write admin q function
* @pf: pointer to i40e_pf struct
**/
static void i40e_enable_mc_magic_wake(struct i40e_pf *pf)
{
struct i40e_vsi *main_vsi = i40e_pf_get_main_vsi(pf);
struct i40e_hw *hw = &pf->hw;
u8 mac_addr[6];
u16 flags = 0;
int ret;
/* Get current MAC address in case it's an LAA */
if (main_vsi && main_vsi->netdev) {
ether_addr_copy(mac_addr, main_vsi->netdev->dev_addr);
} else {
dev_err(&pf->pdev->dev,
"Failed to retrieve MAC address; using default\n");
ether_addr_copy(mac_addr, hw->mac.addr);
}
/* The FW expects the mac address write cmd to first be called with
* one of these flags before calling it again with the multicast
* enable flags.
*/
flags = I40E_AQC_WRITE_TYPE_LAA_WOL;
if (hw->func_caps.flex10_enable && hw->partition_id != 1)
flags = I40E_AQC_WRITE_TYPE_LAA_ONLY;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret) {
dev_err(&pf->pdev->dev,
"Failed to update MAC address registers; cannot enable Multicast Magic packet wake up");
return;
}
flags = I40E_AQC_MC_MAG_EN
| I40E_AQC_WOL_PRESERVE_ON_PFR
| I40E_AQC_WRITE_TYPE_UPDATE_MC_MAG;
ret = i40e_aq_mac_address_write(hw, flags, mac_addr, NULL);
if (ret)
dev_err(&pf->pdev->dev,
"Failed to enable Multicast Magic Packet wake up\n");
} }
/** /**
...@@ -16552,48 +16641,11 @@ static void i40e_shutdown(struct pci_dev *pdev) ...@@ -16552,48 +16641,11 @@ static void i40e_shutdown(struct pci_dev *pdev)
static int i40e_suspend(struct device *dev) static int i40e_suspend(struct device *dev)
{ {
struct i40e_pf *pf = dev_get_drvdata(dev); struct i40e_pf *pf = dev_get_drvdata(dev);
struct i40e_hw *hw = &pf->hw;
/* If we're already suspended, then there is nothing to do */ /* If we're already suspended, then there is nothing to do */
if (test_and_set_bit(__I40E_SUSPENDED, pf->state)) if (test_and_set_bit(__I40E_SUSPENDED, pf->state))
return 0; return 0;
return i40e_io_suspend(pf);
set_bit(__I40E_DOWN, pf->state);
/* Ensure service task will not be running */
del_timer_sync(&pf->service_timer);
cancel_work_sync(&pf->service_task);
/* Client close must be called explicitly here because the timer
* has been stopped.
*/
i40e_notify_client_of_netdev_close(pf, false);
if (test_bit(I40E_HW_CAP_WOL_MC_MAGIC_PKT_WAKE, pf->hw.caps) &&
pf->wol_en)
i40e_enable_mc_magic_wake(pf);
/* Since we're going to destroy queues during the
* i40e_clear_interrupt_scheme() we should hold the RTNL lock for this
* whole section
*/
rtnl_lock();
i40e_prep_for_reset(pf);
wr32(hw, I40E_PFPM_APM, (pf->wol_en ? I40E_PFPM_APM_APME_MASK : 0));
wr32(hw, I40E_PFPM_WUFC, (pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
/* Clear the interrupt scheme and release our IRQs so that the system
* can safely hibernate even when there are a large number of CPUs.
* Otherwise hibernation might fail when mapping all the vectors back
* to CPU0.
*/
i40e_clear_interrupt_scheme(pf);
rtnl_unlock();
return 0;
} }
/** /**
...@@ -16603,39 +16655,11 @@ static int i40e_suspend(struct device *dev) ...@@ -16603,39 +16655,11 @@ static int i40e_suspend(struct device *dev)
static int i40e_resume(struct device *dev) static int i40e_resume(struct device *dev)
{ {
struct i40e_pf *pf = dev_get_drvdata(dev); struct i40e_pf *pf = dev_get_drvdata(dev);
int err;
/* If we're not suspended, then there is nothing to do */ /* If we're not suspended, then there is nothing to do */
if (!test_bit(__I40E_SUSPENDED, pf->state)) if (!test_bit(__I40E_SUSPENDED, pf->state))
return 0; return 0;
return i40e_io_resume(pf);
/* We need to hold the RTNL lock prior to restoring interrupt schemes,
* since we're going to be restoring queues
*/
rtnl_lock();
/* We cleared the interrupt scheme when we suspended, so we need to
* restore it now to resume device functionality.
*/
err = i40e_restore_interrupt_scheme(pf);
if (err) {
dev_err(dev, "Cannot restore interrupt scheme: %d\n",
err);
}
clear_bit(__I40E_DOWN, pf->state);
i40e_reset_and_rebuild(pf, false, true);
rtnl_unlock();
/* Clear suspended state last after everything is recovered */
clear_bit(__I40E_SUSPENDED, pf->state);
/* Restart the service task */
mod_timer(&pf->service_timer,
round_jiffies(jiffies + pf->service_timer_period));
return 0;
} }
static const struct pci_error_handlers i40e_err_handler = { static const struct pci_error_handlers i40e_err_handler = {
......
...@@ -1388,7 +1388,7 @@ enum ice_param_id { ...@@ -1388,7 +1388,7 @@ enum ice_param_id {
ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS,
}; };
static const struct devlink_param ice_devlink_params[] = { static const struct devlink_param ice_dvl_rdma_params[] = {
DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
ice_devlink_enable_roce_get, ice_devlink_enable_roce_get,
ice_devlink_enable_roce_set, ice_devlink_enable_roce_set,
...@@ -1397,6 +1397,9 @@ static const struct devlink_param ice_devlink_params[] = { ...@@ -1397,6 +1397,9 @@ static const struct devlink_param ice_devlink_params[] = {
ice_devlink_enable_iw_get, ice_devlink_enable_iw_get,
ice_devlink_enable_iw_set, ice_devlink_enable_iw_set,
ice_devlink_enable_iw_validate), ice_devlink_enable_iw_validate),
};
static const struct devlink_param ice_dvl_sched_params[] = {
DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS,
"tx_scheduling_layers", "tx_scheduling_layers",
DEVLINK_PARAM_TYPE_U8, DEVLINK_PARAM_TYPE_U8,
...@@ -1464,21 +1467,31 @@ int ice_devlink_register_params(struct ice_pf *pf) ...@@ -1464,21 +1467,31 @@ int ice_devlink_register_params(struct ice_pf *pf)
{ {
struct devlink *devlink = priv_to_devlink(pf); struct devlink *devlink = priv_to_devlink(pf);
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
size_t params_size; int status;
params_size = ARRAY_SIZE(ice_devlink_params); status = devl_params_register(devlink, ice_dvl_rdma_params,
ARRAY_SIZE(ice_dvl_rdma_params));
if (status)
return status;
if (!hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en)
params_size--; status = devl_params_register(devlink, ice_dvl_sched_params,
ARRAY_SIZE(ice_dvl_sched_params));
return devl_params_register(devlink, ice_devlink_params, return status;
params_size);
} }
void ice_devlink_unregister_params(struct ice_pf *pf) void ice_devlink_unregister_params(struct ice_pf *pf)
{ {
devl_params_unregister(priv_to_devlink(pf), ice_devlink_params, struct devlink *devlink = priv_to_devlink(pf);
ARRAY_SIZE(ice_devlink_params)); struct ice_hw *hw = &pf->hw;
devl_params_unregister(devlink, ice_dvl_rdma_params,
ARRAY_SIZE(ice_dvl_rdma_params));
if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en)
devl_params_unregister(devlink, ice_dvl_sched_params,
ARRAY_SIZE(ice_dvl_sched_params));
} }
#define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024)
......
...@@ -3148,6 +3148,16 @@ ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) ...@@ -3148,6 +3148,16 @@ ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high)
case ICE_PHY_TYPE_HIGH_100G_AUI2: case ICE_PHY_TYPE_HIGH_100G_AUI2:
speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB; speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB;
break; break;
case ICE_PHY_TYPE_HIGH_200G_CR4_PAM4:
case ICE_PHY_TYPE_HIGH_200G_SR4:
case ICE_PHY_TYPE_HIGH_200G_FR4:
case ICE_PHY_TYPE_HIGH_200G_LR4:
case ICE_PHY_TYPE_HIGH_200G_DR4:
case ICE_PHY_TYPE_HIGH_200G_KR4_PAM4:
case ICE_PHY_TYPE_HIGH_200G_AUI4_AOC_ACC:
case ICE_PHY_TYPE_HIGH_200G_AUI4:
speed_phy_type_high = ICE_AQ_LINK_SPEED_200GB;
break;
default: default:
speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment