mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-16 21:16:40 +07:00
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue
Jeff Kirsher says: ==================== 40GbE Intel Wired LAN Driver Updates 2019-05-03 This series contains updates to the i40e driver only. Carolyn changes the driver behavior to now disable the VF after one MDD event instead of allowing a couple of MDD events before doing the reset. Aleksandr changes the driver to only report an error when a VF tries to remove VLAN when a port VLAN is configured, unless it is VLAN 0. Also extends the LLDP support to be able to keep the current LLDP state persistent across a power cycle. Maciej fixes the checksum calculation due to firmware changes, which requires the driver to perform a double shadow RAM dump in some cases. Adam adds advertising support for 40GBase_LR4, 40GBase_CR4 and fibre in the driver. Jake cleans up a check that is not needed and was producing a warning in GCC 8. Harshitha fixes a misleading message by ensuring that a success message is only printed on the host side when the promiscuous mode change has been successful. Stefan Assmann adds the vendor id and device id to the dmesg log entry during probe to help with bug reports when lspci output may not be available. Alice and Piotr add recovery mode support in the i40e driver, which is needed for migrating from a structured to a flat firmware image. v2: Removed patch 1 "i40e: replace switch-statement to speed-up retpoline-enabled builds" from the series since it is no longer needed. Also updated the last patch in the series that introduces recovery mode support, to include a more detailed patch description and removed code not intended for the upstream kernel. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
2ce1aef9cd
@ -149,6 +149,7 @@ enum i40e_state_t {
|
||||
__I40E_CLIENT_L2_CHANGE,
|
||||
__I40E_CLIENT_RESET,
|
||||
__I40E_VIRTCHNL_OP_PENDING,
|
||||
__I40E_RECOVERY_MODE,
|
||||
/* This must be last as it determines the size of the BITMAP */
|
||||
__I40E_STATE_SIZE__,
|
||||
};
|
||||
|
@ -608,6 +608,11 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
|
||||
hw->aq.api_min_ver >= 7))
|
||||
hw->flags |= I40E_HW_FLAG_802_1AD_CAPABLE;
|
||||
|
||||
if (hw->aq.api_maj_ver > 1 ||
|
||||
(hw->aq.api_maj_ver == 1 &&
|
||||
hw->aq.api_min_ver >= 8))
|
||||
hw->flags |= I40E_HW_FLAG_FW_LLDP_PERSISTENT;
|
||||
|
||||
if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) {
|
||||
ret_code = I40E_ERR_FIRMWARE_API_VERSION;
|
||||
goto init_adminq_free_arq;
|
||||
|
@ -261,6 +261,7 @@ enum i40e_admin_queue_opc {
|
||||
i40e_aqc_opc_get_cee_dcb_cfg = 0x0A07,
|
||||
i40e_aqc_opc_lldp_set_local_mib = 0x0A08,
|
||||
i40e_aqc_opc_lldp_stop_start_spec_agent = 0x0A09,
|
||||
i40e_aqc_opc_lldp_restore = 0x0A0A,
|
||||
|
||||
/* Tunnel commands */
|
||||
i40e_aqc_opc_add_udp_tunnel = 0x0B00,
|
||||
@ -2498,18 +2499,19 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv);
|
||||
/* Stop LLDP (direct 0x0A05) */
|
||||
struct i40e_aqc_lldp_stop {
|
||||
u8 command;
|
||||
#define I40E_AQ_LLDP_AGENT_STOP 0x0
|
||||
#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1
|
||||
#define I40E_AQ_LLDP_AGENT_STOP 0x0
|
||||
#define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1
|
||||
#define I40E_AQ_LLDP_AGENT_STOP_PERSIST 0x2
|
||||
u8 reserved[15];
|
||||
};
|
||||
|
||||
I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop);
|
||||
|
||||
/* Start LLDP (direct 0x0A06) */
|
||||
|
||||
struct i40e_aqc_lldp_start {
|
||||
u8 command;
|
||||
#define I40E_AQ_LLDP_AGENT_START 0x1
|
||||
#define I40E_AQ_LLDP_AGENT_START 0x1
|
||||
#define I40E_AQ_LLDP_AGENT_START_PERSIST 0x2
|
||||
u8 reserved[15];
|
||||
};
|
||||
|
||||
@ -2633,6 +2635,16 @@ struct i40e_aqc_lldp_stop_start_specific_agent {
|
||||
|
||||
I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop_start_specific_agent);
|
||||
|
||||
/* Restore LLDP Agent factory settings (direct 0x0A0A) */
|
||||
struct i40e_aqc_lldp_restore {
|
||||
u8 command;
|
||||
#define I40E_AQ_LLDP_AGENT_RESTORE_NOT 0x0
|
||||
#define I40E_AQ_LLDP_AGENT_RESTORE 0x1
|
||||
u8 reserved[15];
|
||||
};
|
||||
|
||||
I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_restore);
|
||||
|
||||
/* Add Udp Tunnel command and completion (direct 0x0B00) */
|
||||
struct i40e_aqc_add_udp_tunnel {
|
||||
__le16 udp_port;
|
||||
|
@ -3623,15 +3623,55 @@ i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_restore_lldp
|
||||
* @hw: pointer to the hw struct
|
||||
* @setting: pointer to factory setting variable or NULL
|
||||
* @restore: True if factory settings should be restored
|
||||
* @cmd_details: pointer to command details structure or NULL
|
||||
*
|
||||
* Restore LLDP Agent factory settings if @restore set to True. In other case
|
||||
* only returns factory setting in AQ response.
|
||||
**/
|
||||
enum i40e_status_code
|
||||
i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
|
||||
struct i40e_asq_cmd_details *cmd_details)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_lldp_restore *cmd =
|
||||
(struct i40e_aqc_lldp_restore *)&desc.params.raw;
|
||||
i40e_status status;
|
||||
|
||||
if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)) {
|
||||
i40e_debug(hw, I40E_DEBUG_ALL,
|
||||
"Restore LLDP not supported by current FW version.\n");
|
||||
return I40E_ERR_DEVICE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore);
|
||||
|
||||
if (restore)
|
||||
cmd->command |= I40E_AQ_LLDP_AGENT_RESTORE;
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
|
||||
|
||||
if (setting)
|
||||
*setting = cmd->command & 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_stop_lldp
|
||||
* @hw: pointer to the hw struct
|
||||
* @shutdown_agent: True if LLDP Agent needs to be Shutdown
|
||||
* @persist: True if stop of LLDP should be persistent across power cycles
|
||||
* @cmd_details: pointer to command details structure or NULL
|
||||
*
|
||||
* Stop or Shutdown the embedded LLDP Agent
|
||||
**/
|
||||
i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
bool persist,
|
||||
struct i40e_asq_cmd_details *cmd_details)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
@ -3644,6 +3684,14 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
if (shutdown_agent)
|
||||
cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN;
|
||||
|
||||
if (persist) {
|
||||
if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
|
||||
cmd->command |= I40E_AQ_LLDP_AGENT_STOP_PERSIST;
|
||||
else
|
||||
i40e_debug(hw, I40E_DEBUG_ALL,
|
||||
"Persistent Stop LLDP not supported by current FW version.\n");
|
||||
}
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
|
||||
|
||||
return status;
|
||||
@ -3653,13 +3701,14 @@ i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
* i40e_aq_start_lldp
|
||||
* @hw: pointer to the hw struct
|
||||
* @buff: buffer for result
|
||||
* @persist: True if start of LLDP should be persistent across power cycles
|
||||
* @buff_size: buffer size
|
||||
* @cmd_details: pointer to command details structure or NULL
|
||||
*
|
||||
* Start the embedded LLDP Agent on all ports.
|
||||
**/
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details)
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, bool persist,
|
||||
struct i40e_asq_cmd_details *cmd_details)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_lldp_start *cmd =
|
||||
@ -3669,6 +3718,15 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
|
||||
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start);
|
||||
|
||||
cmd->command = I40E_AQ_LLDP_AGENT_START;
|
||||
|
||||
if (persist) {
|
||||
if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
|
||||
cmd->command |= I40E_AQ_LLDP_AGENT_START_PERSIST;
|
||||
else
|
||||
i40e_debug(hw, I40E_DEBUG_ALL,
|
||||
"Persistent Start LLDP not supported by current FW version.\n");
|
||||
}
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
|
||||
|
||||
return status;
|
||||
|
@ -1321,7 +1321,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
|
||||
if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
|
||||
int ret;
|
||||
|
||||
ret = i40e_aq_stop_lldp(&pf->hw, false, NULL);
|
||||
ret = i40e_aq_stop_lldp(&pf->hw, false, false, NULL);
|
||||
if (ret) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"Stop LLDP AQ command failed =0x%x\n",
|
||||
@ -1358,7 +1358,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
|
||||
/* Continue and start FW LLDP anyways */
|
||||
}
|
||||
|
||||
ret = i40e_aq_start_lldp(&pf->hw, NULL);
|
||||
ret = i40e_aq_start_lldp(&pf->hw, false, NULL);
|
||||
if (ret) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"Start LLDP AQ command failed =0x%x\n",
|
||||
|
@ -541,9 +541,12 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf,
|
||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
||||
40000baseSR4_Full);
|
||||
}
|
||||
if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4)
|
||||
if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) {
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
||||
40000baseLR4_Full);
|
||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
||||
40000baseLR4_Full);
|
||||
}
|
||||
if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) {
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
||||
40000baseLR4_Full);
|
||||
@ -723,6 +726,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
|
||||
case I40E_PHY_TYPE_40GBASE_AOC:
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
||||
40000baseCR4_Full);
|
||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
||||
40000baseCR4_Full);
|
||||
break;
|
||||
case I40E_PHY_TYPE_40GBASE_SR4:
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
||||
@ -733,6 +738,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
|
||||
case I40E_PHY_TYPE_40GBASE_LR4:
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported,
|
||||
40000baseLR4_Full);
|
||||
ethtool_link_ksettings_add_link_mode(ks, advertising,
|
||||
40000baseLR4_Full);
|
||||
break;
|
||||
case I40E_PHY_TYPE_25GBASE_SR:
|
||||
case I40E_PHY_TYPE_25GBASE_LR:
|
||||
@ -1038,6 +1045,7 @@ static int i40e_get_link_ksettings(struct net_device *netdev,
|
||||
break;
|
||||
case I40E_MEDIA_TYPE_FIBER:
|
||||
ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE);
|
||||
ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE);
|
||||
ks->base.port = PORT_FIBRE;
|
||||
break;
|
||||
case I40E_MEDIA_TYPE_UNKNOWN:
|
||||
@ -4950,7 +4958,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
|
||||
if (pf->flags & I40E_FLAG_DISABLE_FW_LLDP) {
|
||||
struct i40e_dcbx_config *dcbcfg;
|
||||
|
||||
i40e_aq_stop_lldp(&pf->hw, true, NULL);
|
||||
i40e_aq_stop_lldp(&pf->hw, true, false, NULL);
|
||||
i40e_aq_set_dcb_parameters(&pf->hw, true, NULL);
|
||||
/* reset local_dcbx_config to default */
|
||||
dcbcfg = &pf->hw.local_dcbx_config;
|
||||
@ -4965,7 +4973,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
|
||||
dcbcfg->pfc.willing = 1;
|
||||
dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
|
||||
} else {
|
||||
i40e_aq_start_lldp(&pf->hw, NULL);
|
||||
i40e_aq_start_lldp(&pf->hw, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5133,6 +5141,12 @@ static int i40e_get_module_eeprom(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops i40e_ethtool_recovery_mode_ops = {
|
||||
.set_eeprom = i40e_set_eeprom,
|
||||
.get_eeprom_len = i40e_get_eeprom_len,
|
||||
.get_eeprom = i40e_get_eeprom,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops i40e_ethtool_ops = {
|
||||
.get_drvinfo = i40e_get_drvinfo,
|
||||
.get_regs_len = i40e_get_regs_len,
|
||||
@ -5181,5 +5195,11 @@ static const struct ethtool_ops i40e_ethtool_ops = {
|
||||
|
||||
void i40e_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
netdev->ethtool_ops = &i40e_ethtool_ops;
|
||||
struct i40e_netdev_priv *np = netdev_priv(netdev);
|
||||
struct i40e_pf *pf = np->vsi->back;
|
||||
|
||||
if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
|
||||
netdev->ethtool_ops = &i40e_ethtool_ops;
|
||||
else
|
||||
netdev->ethtool_ops = &i40e_ethtool_recovery_mode_ops;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ static const char i40e_driver_string[] =
|
||||
|
||||
#define DRV_VERSION_MAJOR 2
|
||||
#define DRV_VERSION_MINOR 8
|
||||
#define DRV_VERSION_BUILD 10
|
||||
#define DRV_VERSION_BUILD 20
|
||||
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
|
||||
__stringify(DRV_VERSION_MINOR) "." \
|
||||
__stringify(DRV_VERSION_BUILD) DRV_KERN
|
||||
@ -46,6 +46,10 @@ static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
|
||||
static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
|
||||
static int i40e_reset(struct i40e_pf *pf);
|
||||
static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
|
||||
static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf);
|
||||
static int i40e_restore_interrupt_scheme(struct i40e_pf *pf);
|
||||
static bool i40e_check_recovery_mode(struct i40e_pf *pf);
|
||||
static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw);
|
||||
static void i40e_fdir_sb_setup(struct i40e_pf *pf);
|
||||
static int i40e_veb_get_bw_info(struct i40e_veb *veb);
|
||||
static int i40e_get_capabilities(struct i40e_pf *pf,
|
||||
@ -278,8 +282,9 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
|
||||
**/
|
||||
void i40e_service_event_schedule(struct i40e_pf *pf)
|
||||
{
|
||||
if (!test_bit(__I40E_DOWN, pf->state) &&
|
||||
!test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
|
||||
if ((!test_bit(__I40E_DOWN, pf->state) &&
|
||||
!test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) ||
|
||||
test_bit(__I40E_RECOVERY_MODE, pf->state))
|
||||
queue_work(i40e_wq, &pf->service_task);
|
||||
}
|
||||
|
||||
@ -4019,7 +4024,8 @@ static irqreturn_t i40e_intr(int irq, void *data)
|
||||
enable_intr:
|
||||
/* re-enable interrupt causes */
|
||||
wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
|
||||
if (!test_bit(__I40E_DOWN, pf->state)) {
|
||||
if (!test_bit(__I40E_DOWN, pf->state) ||
|
||||
test_bit(__I40E_RECOVERY_MODE, pf->state)) {
|
||||
i40e_service_event_schedule(pf);
|
||||
i40e_irq_dynamic_enable_icr0(pf);
|
||||
}
|
||||
@ -9409,6 +9415,7 @@ static int i40e_reset(struct i40e_pf *pf)
|
||||
**/
|
||||
static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
||||
{
|
||||
int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state);
|
||||
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u8 set_fc_aq_fail = 0;
|
||||
@ -9416,7 +9423,14 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
||||
u32 val;
|
||||
int v;
|
||||
|
||||
if (test_bit(__I40E_DOWN, pf->state))
|
||||
if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
|
||||
i40e_check_recovery_mode(pf)) {
|
||||
i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
|
||||
}
|
||||
|
||||
if (test_bit(__I40E_DOWN, pf->state) &&
|
||||
!test_bit(__I40E_RECOVERY_MODE, pf->state) &&
|
||||
!old_recovery_mode_bit)
|
||||
goto clear_recovery;
|
||||
dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
|
||||
|
||||
@ -9445,6 +9459,44 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
||||
if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state))
|
||||
i40e_verify_eeprom(pf);
|
||||
|
||||
/* if we are going out of or into recovery mode we have to act
|
||||
* accordingly with regard to resources initialization
|
||||
* and deinitialization
|
||||
*/
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state) ||
|
||||
old_recovery_mode_bit) {
|
||||
if (i40e_get_capabilities(pf,
|
||||
i40e_aqc_opc_list_func_capabilities))
|
||||
goto end_unlock;
|
||||
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
|
||||
/* we're staying in recovery mode so we'll reinitialize
|
||||
* misc vector here
|
||||
*/
|
||||
if (i40e_setup_misc_vector_for_recovery_mode(pf))
|
||||
goto end_unlock;
|
||||
} else {
|
||||
if (!lock_acquired)
|
||||
rtnl_lock();
|
||||
/* we're going out of recovery mode so we'll free
|
||||
* the IRQ allocated specifically for recovery mode
|
||||
* and restore the interrupt scheme
|
||||
*/
|
||||
free_irq(pf->pdev->irq, pf);
|
||||
i40e_clear_interrupt_scheme(pf);
|
||||
if (i40e_restore_interrupt_scheme(pf))
|
||||
goto end_unlock;
|
||||
}
|
||||
|
||||
/* tell the firmware that we're starting */
|
||||
i40e_send_version(pf);
|
||||
|
||||
/* bail out in case recovery mode was detected, as there is
|
||||
* no need for further configuration.
|
||||
*/
|
||||
goto end_unlock;
|
||||
}
|
||||
|
||||
i40e_clear_pxe_mode(hw);
|
||||
ret = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
|
||||
if (ret)
|
||||
@ -9696,7 +9748,6 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
bool mdd_detected = false;
|
||||
bool pf_mdd_detected = false;
|
||||
struct i40e_vf *vf;
|
||||
u32 reg;
|
||||
int i;
|
||||
@ -9742,19 +9793,12 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
|
||||
reg = rd32(hw, I40E_PF_MDET_TX);
|
||||
if (reg & I40E_PF_MDET_TX_VALID_MASK) {
|
||||
wr32(hw, I40E_PF_MDET_TX, 0xFFFF);
|
||||
dev_info(&pf->pdev->dev, "TX driver issue detected, PF reset issued\n");
|
||||
pf_mdd_detected = true;
|
||||
dev_dbg(&pf->pdev->dev, "TX driver issue detected on PF\n");
|
||||
}
|
||||
reg = rd32(hw, I40E_PF_MDET_RX);
|
||||
if (reg & I40E_PF_MDET_RX_VALID_MASK) {
|
||||
wr32(hw, I40E_PF_MDET_RX, 0xFFFF);
|
||||
dev_info(&pf->pdev->dev, "RX driver issue detected, PF reset issued\n");
|
||||
pf_mdd_detected = true;
|
||||
}
|
||||
/* Queue belongs to the PF, initiate a reset */
|
||||
if (pf_mdd_detected) {
|
||||
set_bit(__I40E_PF_RESET_REQUESTED, pf->state);
|
||||
i40e_service_event_schedule(pf);
|
||||
dev_dbg(&pf->pdev->dev, "RX driver issue detected on PF\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -9767,6 +9811,9 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
|
||||
vf->num_mdd_events++;
|
||||
dev_info(&pf->pdev->dev, "TX driver issue detected on VF %d\n",
|
||||
i);
|
||||
dev_info(&pf->pdev->dev,
|
||||
"Use PF Control I/F to re-enable the VF\n");
|
||||
set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
|
||||
}
|
||||
|
||||
reg = rd32(hw, I40E_VP_MDET_RX(i));
|
||||
@ -9775,11 +9822,6 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
|
||||
vf->num_mdd_events++;
|
||||
dev_info(&pf->pdev->dev, "RX driver issue detected on VF %d\n",
|
||||
i);
|
||||
}
|
||||
|
||||
if (vf->num_mdd_events > I40E_DEFAULT_NUM_MDD_EVENTS_ALLOWED) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"Too many MDD events on VF %d, disabled\n", i);
|
||||
dev_info(&pf->pdev->dev,
|
||||
"Use PF Control I/F to re-enable the VF\n");
|
||||
set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
|
||||
@ -9906,31 +9948,38 @@ static void i40e_service_task(struct work_struct *work)
|
||||
unsigned long start_time = jiffies;
|
||||
|
||||
/* don't bother with service tasks if a reset is in progress */
|
||||
if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
|
||||
if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
|
||||
test_bit(__I40E_SUSPENDED, pf->state))
|
||||
return;
|
||||
|
||||
if (test_and_set_bit(__I40E_SERVICE_SCHED, pf->state))
|
||||
return;
|
||||
|
||||
i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
|
||||
i40e_sync_filters_subtask(pf);
|
||||
i40e_reset_subtask(pf);
|
||||
i40e_handle_mdd_event(pf);
|
||||
i40e_vc_process_vflr_event(pf);
|
||||
i40e_watchdog_subtask(pf);
|
||||
i40e_fdir_reinit_subtask(pf);
|
||||
if (test_and_clear_bit(__I40E_CLIENT_RESET, pf->state)) {
|
||||
/* Client subtask will reopen next time through. */
|
||||
i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], true);
|
||||
if (!test_bit(__I40E_RECOVERY_MODE, pf->state)) {
|
||||
i40e_detect_recover_hung(pf->vsi[pf->lan_vsi]);
|
||||
i40e_sync_filters_subtask(pf);
|
||||
i40e_reset_subtask(pf);
|
||||
i40e_handle_mdd_event(pf);
|
||||
i40e_vc_process_vflr_event(pf);
|
||||
i40e_watchdog_subtask(pf);
|
||||
i40e_fdir_reinit_subtask(pf);
|
||||
if (test_and_clear_bit(__I40E_CLIENT_RESET, pf->state)) {
|
||||
/* Client subtask will reopen next time through. */
|
||||
i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi],
|
||||
true);
|
||||
} else {
|
||||
i40e_client_subtask(pf);
|
||||
if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
|
||||
pf->state))
|
||||
i40e_notify_client_of_l2_param_changes(
|
||||
pf->vsi[pf->lan_vsi]);
|
||||
}
|
||||
i40e_sync_filters_subtask(pf);
|
||||
i40e_sync_udp_filters_subtask(pf);
|
||||
} else {
|
||||
i40e_client_subtask(pf);
|
||||
if (test_and_clear_bit(__I40E_CLIENT_L2_CHANGE,
|
||||
pf->state))
|
||||
i40e_notify_client_of_l2_param_changes(
|
||||
pf->vsi[pf->lan_vsi]);
|
||||
i40e_reset_subtask(pf);
|
||||
}
|
||||
i40e_sync_filters_subtask(pf);
|
||||
i40e_sync_udp_filters_subtask(pf);
|
||||
|
||||
i40e_clean_adminq_subtask(pf);
|
||||
|
||||
/* flush memory to make sure state is correct before next watchdog */
|
||||
@ -10752,6 +10801,48 @@ static int i40e_restore_interrupt_scheme(struct i40e_pf *pf)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_setup_misc_vector_for_recovery_mode - Setup the misc vector to handle
|
||||
* non queue events in recovery mode
|
||||
* @pf: board private structure
|
||||
*
|
||||
* This sets up the handler for MSIX 0 or MSI/legacy, which is used to manage
|
||||
* the non-queue interrupts, e.g. AdminQ and errors in recovery mode.
|
||||
* This is handled differently than in recovery mode since no Tx/Rx resources
|
||||
* are being allocated.
|
||||
**/
|
||||
static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
|
||||
err = i40e_setup_misc_vector(pf);
|
||||
|
||||
if (err) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"MSI-X misc vector request failed, error %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
u32 flags = pf->flags & I40E_FLAG_MSI_ENABLED ? 0 : IRQF_SHARED;
|
||||
|
||||
err = request_irq(pf->pdev->irq, i40e_intr, flags,
|
||||
pf->int_name, pf);
|
||||
|
||||
if (err) {
|
||||
dev_info(&pf->pdev->dev,
|
||||
"MSI/legacy misc vector request failed, error %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
i40e_enable_misc_int_causes(pf);
|
||||
i40e_irq_dynamic_enable_icr0(pf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_setup_misc_vector - Setup the misc vector to handle non queue events
|
||||
* @pf: board private structure
|
||||
@ -13914,6 +14005,125 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags)
|
||||
*flags &= ~(I40E_FLAG_RS_FEC | I40E_FLAG_BASE_R_FEC);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_check_recovery_mode - check if we are running transition firmware
|
||||
* @pf: board private structure
|
||||
*
|
||||
* Check registers indicating the firmware runs in recovery mode. Sets the
|
||||
* appropriate driver state.
|
||||
*
|
||||
* Returns true if the recovery mode was detected, false otherwise
|
||||
**/
|
||||
static bool i40e_check_recovery_mode(struct i40e_pf *pf)
|
||||
{
|
||||
u32 val = rd32(&pf->hw, I40E_GL_FWSTS);
|
||||
|
||||
if (val & I40E_GL_FWSTS_FWS1B_MASK) {
|
||||
dev_notice(&pf->pdev->dev, "Firmware recovery mode detected. Limiting functionality.\n");
|
||||
dev_notice(&pf->pdev->dev, "Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
|
||||
set_bit(__I40E_RECOVERY_MODE, pf->state);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (test_and_clear_bit(__I40E_RECOVERY_MODE, pf->state))
|
||||
dev_info(&pf->pdev->dev, "Reinitializing in normal mode with full functionality.\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_init_recovery_mode - initialize subsystems needed in recovery mode
|
||||
* @pf: board private structure
|
||||
* @hw: ptr to the hardware info
|
||||
*
|
||||
* This function does a minimal setup of all subsystems needed for running
|
||||
* recovery mode.
|
||||
*
|
||||
* Returns 0 on success, negative on failure
|
||||
**/
|
||||
static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
|
||||
{
|
||||
struct i40e_vsi *vsi;
|
||||
int err;
|
||||
int v_idx;
|
||||
|
||||
pci_save_state(pf->pdev);
|
||||
|
||||
/* set up periodic task facility */
|
||||
timer_setup(&pf->service_timer, i40e_service_timer, 0);
|
||||
pf->service_timer_period = HZ;
|
||||
|
||||
INIT_WORK(&pf->service_task, i40e_service_task);
|
||||
clear_bit(__I40E_SERVICE_SCHED, pf->state);
|
||||
|
||||
err = i40e_init_interrupt_scheme(pf);
|
||||
if (err)
|
||||
goto err_switch_setup;
|
||||
|
||||
/* The number of VSIs reported by the FW is the minimum guaranteed
|
||||
* to us; HW supports far more and we share the remaining pool with
|
||||
* the other PFs. We allocate space for more than the guarantee with
|
||||
* the understanding that we might not get them all later.
|
||||
*/
|
||||
if (pf->hw.func_caps.num_vsis < I40E_MIN_VSI_ALLOC)
|
||||
pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC;
|
||||
else
|
||||
pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
|
||||
|
||||
/* Set up the vsi struct and our local tracking of the MAIN PF vsi. */
|
||||
pf->vsi = kcalloc(pf->num_alloc_vsi, sizeof(struct i40e_vsi *),
|
||||
GFP_KERNEL);
|
||||
if (!pf->vsi) {
|
||||
err = -ENOMEM;
|
||||
goto err_switch_setup;
|
||||
}
|
||||
|
||||
/* We allocate one VSI which is needed as absolute minimum
|
||||
* in order to register the netdev
|
||||
*/
|
||||
v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
|
||||
if (v_idx < 0)
|
||||
goto err_switch_setup;
|
||||
pf->lan_vsi = v_idx;
|
||||
vsi = pf->vsi[v_idx];
|
||||
if (!vsi)
|
||||
goto err_switch_setup;
|
||||
vsi->alloc_queue_pairs = 1;
|
||||
err = i40e_config_netdev(vsi);
|
||||
if (err)
|
||||
goto err_switch_setup;
|
||||
err = register_netdev(vsi->netdev);
|
||||
if (err)
|
||||
goto err_switch_setup;
|
||||
vsi->netdev_registered = true;
|
||||
i40e_dbg_pf_init(pf);
|
||||
|
||||
err = i40e_setup_misc_vector_for_recovery_mode(pf);
|
||||
if (err)
|
||||
goto err_switch_setup;
|
||||
|
||||
/* tell the firmware that we're starting */
|
||||
i40e_send_version(pf);
|
||||
|
||||
/* since everything's happy, start the service_task timer */
|
||||
mod_timer(&pf->service_timer,
|
||||
round_jiffies(jiffies + pf->service_timer_period));
|
||||
|
||||
return 0;
|
||||
|
||||
err_switch_setup:
|
||||
i40e_reset_interrupt_capability(pf);
|
||||
del_timer_sync(&pf->service_timer);
|
||||
i40e_shutdown_adminq(hw);
|
||||
iounmap(hw->hw_addr);
|
||||
pci_disable_pcie_error_reporting(pf->pdev);
|
||||
pci_release_mem_regions(pf->pdev);
|
||||
pci_disable_device(pf->pdev);
|
||||
kfree(pf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_probe - Device initialization routine
|
||||
* @pdev: PCI device information struct
|
||||
@ -14039,13 +14249,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
/* Reset here to make sure all is clean and to define PF 'n' */
|
||||
i40e_clear_hw(hw);
|
||||
err = i40e_pf_reset(hw);
|
||||
if (err) {
|
||||
dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err);
|
||||
goto err_pf_reset;
|
||||
if (!i40e_check_recovery_mode(pf)) {
|
||||
err = i40e_pf_reset(hw);
|
||||
if (err) {
|
||||
dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err);
|
||||
goto err_pf_reset;
|
||||
}
|
||||
pf->pfr_count++;
|
||||
}
|
||||
pf->pfr_count++;
|
||||
|
||||
hw->aq.num_arq_entries = I40E_AQ_LEN;
|
||||
hw->aq.num_asq_entries = I40E_AQ_LEN;
|
||||
hw->aq.arq_buf_size = I40E_MAX_AQ_BUF_SIZE;
|
||||
@ -14083,11 +14294,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
i40e_get_oem_version(hw);
|
||||
|
||||
/* provide nvm, fw, api versions */
|
||||
dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s\n",
|
||||
/* provide nvm, fw, api versions, vendor:device id, subsys vendor:device id */
|
||||
dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s [%04x:%04x] [%04x:%04x]\n",
|
||||
hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build,
|
||||
hw->aq.api_maj_ver, hw->aq.api_min_ver,
|
||||
i40e_nvm_version_str(hw));
|
||||
i40e_nvm_version_str(hw), hw->vendor_id, hw->device_id,
|
||||
hw->subsystem_vendor_id, hw->subsystem_device_id);
|
||||
|
||||
if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
|
||||
hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw))
|
||||
@ -14112,6 +14324,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev_warn(&pdev->dev, "This device is a pre-production adapter/LOM. Please be aware there may be issues with your hardware. If you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
|
||||
|
||||
i40e_clear_pxe_mode(hw);
|
||||
|
||||
err = i40e_get_capabilities(pf, i40e_aqc_opc_list_func_capabilities);
|
||||
if (err)
|
||||
goto err_adminq_setup;
|
||||
@ -14122,6 +14335,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto err_sw_init;
|
||||
}
|
||||
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state))
|
||||
return i40e_init_recovery_mode(pf, hw);
|
||||
|
||||
err = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
|
||||
hw->func_caps.num_rx_qp, 0, 0);
|
||||
if (err) {
|
||||
@ -14142,7 +14358,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
*/
|
||||
if (pf->hw_features & I40E_HW_STOP_FW_LLDP) {
|
||||
dev_info(&pdev->dev, "Stopping firmware LLDP agent.\n");
|
||||
i40e_aq_stop_lldp(hw, true, NULL);
|
||||
i40e_aq_stop_lldp(hw, true, false, NULL);
|
||||
}
|
||||
|
||||
/* allow a platform config to override the HW addr */
|
||||
@ -14507,6 +14723,19 @@ static void i40e_remove(struct pci_dev *pdev)
|
||||
if (pf->service_task.func)
|
||||
cancel_work_sync(&pf->service_task);
|
||||
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
|
||||
struct i40e_vsi *vsi = pf->vsi[0];
|
||||
|
||||
/* We know that we have allocated only one vsi for this PF,
|
||||
* it was just for registering netdevice, so the interface
|
||||
* could be visible in the 'ifconfig' output
|
||||
*/
|
||||
unregister_netdev(vsi->netdev);
|
||||
free_netdev(vsi->netdev);
|
||||
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
/* Client close must be called explicitly here because the timer
|
||||
* has been stopped.
|
||||
*/
|
||||
@ -14556,6 +14785,12 @@ static void i40e_remove(struct pci_dev *pdev)
|
||||
ret_code);
|
||||
}
|
||||
|
||||
unmap:
|
||||
/* Free MSI/legacy interrupt 0 when in recovery mode. */
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state) &&
|
||||
!(pf->flags & I40E_FLAG_MSIX_ENABLED))
|
||||
free_irq(pf->pdev->irq, pf);
|
||||
|
||||
/* shutdown the adminq */
|
||||
i40e_shutdown_adminq(hw);
|
||||
|
||||
@ -14568,7 +14803,8 @@ static void i40e_remove(struct pci_dev *pdev)
|
||||
i40e_clear_interrupt_scheme(pf);
|
||||
for (i = 0; i < pf->num_alloc_vsi; i++) {
|
||||
if (pf->vsi[i]) {
|
||||
i40e_vsi_clear_rings(pf->vsi[i]);
|
||||
if (!test_bit(__I40E_RECOVERY_MODE, pf->state))
|
||||
i40e_vsi_clear_rings(pf->vsi[i]);
|
||||
i40e_vsi_clear(pf->vsi[i]);
|
||||
pf->vsi[i] = NULL;
|
||||
}
|
||||
@ -14776,6 +15012,11 @@ static void i40e_shutdown(struct pci_dev *pdev)
|
||||
wr32(hw, I40E_PFPM_WUFC,
|
||||
(pf->wol_en ? I40E_PFPM_WUFC_MAG_MASK : 0));
|
||||
|
||||
/* Free MSI/legacy interrupt 0 when in recovery mode. */
|
||||
if (test_bit(__I40E_RECOVERY_MODE, pf->state) &&
|
||||
!(pf->flags & I40E_FLAG_MSIX_ENABLED))
|
||||
free_irq(pf->pdev->irq, pf);
|
||||
|
||||
/* Since we're going to destroy queues during the
|
||||
* i40e_clear_interrupt_scheme() we should hold the RTNL lock for this
|
||||
* whole section
|
||||
|
@ -574,13 +574,34 @@ static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
|
||||
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code;
|
||||
u16 checksum;
|
||||
u16 checksum, checksum_sr;
|
||||
__le16 le_sum;
|
||||
|
||||
ret_code = i40e_calc_nvm_checksum(hw, &checksum);
|
||||
if (!ret_code) {
|
||||
le_sum = cpu_to_le16(checksum);
|
||||
ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
|
||||
if (ret_code)
|
||||
return ret_code;
|
||||
|
||||
le_sum = cpu_to_le16(checksum);
|
||||
ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
|
||||
1, &le_sum, true);
|
||||
if (ret_code)
|
||||
return ret_code;
|
||||
|
||||
/* Due to changes in FW the SW is required to perform double SR-dump
|
||||
* in some cases. SR-dump is the process when internal shadow RAM is
|
||||
* dumped into flash bank. It is triggered by setting "last_command"
|
||||
* argument in i40e_write_nvm_aq function call.
|
||||
* Since FW 1.8 we need to calculate SR checksum again and update it
|
||||
* in flash if it is not equal to previously computed checksum.
|
||||
* This situation would occur only in FW >= 1.8
|
||||
*/
|
||||
ret_code = i40e_calc_nvm_checksum(hw, &checksum_sr);
|
||||
if (ret_code)
|
||||
return ret_code;
|
||||
if (checksum_sr != checksum) {
|
||||
le_sum = cpu_to_le16(checksum_sr);
|
||||
ret_code = i40e_write_nvm_aq(hw, 0x00,
|
||||
I40E_SR_SW_CHECKSUM_WORD,
|
||||
1, &le_sum, true);
|
||||
}
|
||||
|
||||
|
@ -203,14 +203,18 @@ i40e_status i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type,
|
||||
i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
|
||||
bool enable_update,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
enum i40e_status_code
|
||||
i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
bool persist,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_dcb_parameters(struct i40e_hw *hw,
|
||||
bool dcb_enable,
|
||||
struct i40e_asq_cmd_details
|
||||
*cmd_details);
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, bool persist,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_cee_dcb_config(struct i40e_hw *hw,
|
||||
void *buff, u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
|
@ -616,6 +616,7 @@ struct i40e_hw {
|
||||
#define I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE BIT_ULL(2)
|
||||
#define I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK BIT_ULL(3)
|
||||
#define I40E_HW_FLAG_FW_LLDP_STOPPABLE BIT_ULL(4)
|
||||
#define I40E_HW_FLAG_FW_LLDP_PERSISTENT BIT_ULL(5)
|
||||
u64 flags;
|
||||
|
||||
/* Used in set switch config AQ command */
|
||||
|
@ -1112,15 +1112,6 @@ static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf,
|
||||
if (!i40e_vc_isvalid_vsi_id(vf, vsi_id) || !vsi)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
|
||||
(allmulti || alluni)) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"Unprivileged VF %d is attempting to configure promiscuous mode\n",
|
||||
vf->vf_id);
|
||||
/* Lie to the VF on purpose. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vf->port_vlan_id) {
|
||||
aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, vsi->seid,
|
||||
allmulti,
|
||||
@ -1997,8 +1988,21 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg)
|
||||
bool allmulti = false;
|
||||
bool alluni = false;
|
||||
|
||||
if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
|
||||
return I40E_ERR_PARAM;
|
||||
if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
|
||||
aq_ret = I40E_ERR_PARAM;
|
||||
goto err_out;
|
||||
}
|
||||
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"Unprivileged VF %d is attempting to configure promiscuous mode\n",
|
||||
vf->vf_id);
|
||||
|
||||
/* Lie to the VF on purpose, because this is an error we can
|
||||
* ignore. Unprivileged VF is not a virtual channel error.
|
||||
*/
|
||||
aq_ret = 0;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Multicast promiscuous handling*/
|
||||
if (info->flags & FLAG_VF_MULTICAST_PROMISC)
|
||||
@ -2032,7 +2036,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg)
|
||||
clear_bit(I40E_VF_STATE_UC_PROMISC, &vf->vf_states);
|
||||
}
|
||||
}
|
||||
|
||||
err_out:
|
||||
/* send the response to the VF */
|
||||
return i40e_vc_send_resp_to_vf(vf,
|
||||
VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
|
||||
@ -2766,7 +2770,8 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg)
|
||||
|
||||
vsi = pf->vsi[vf->lan_vsi_idx];
|
||||
if (vsi->info.pvid) {
|
||||
aq_ret = I40E_ERR_PARAM;
|
||||
if (vfl->num_elements > 1 || vfl->vlan_id[0])
|
||||
aq_ret = I40E_ERR_PARAM;
|
||||
goto error_param;
|
||||
}
|
||||
|
||||
@ -3128,7 +3133,7 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf,
|
||||
}
|
||||
|
||||
if (mask.dst_port & data.dst_port) {
|
||||
if (!data.dst_port || be16_to_cpu(data.dst_port) > 0xFFFF) {
|
||||
if (!data.dst_port) {
|
||||
dev_info(&pf->pdev->dev, "VF %d: Invalid Dest port\n",
|
||||
vf->vf_id);
|
||||
goto err;
|
||||
@ -3136,7 +3141,7 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf,
|
||||
}
|
||||
|
||||
if (mask.src_port & data.src_port) {
|
||||
if (!data.src_port || be16_to_cpu(data.src_port) > 0xFFFF) {
|
||||
if (!data.src_port) {
|
||||
dev_info(&pf->pdev->dev, "VF %d: Invalid Source port\n",
|
||||
vf->vf_id);
|
||||
goto err;
|
||||
|
Loading…
Reference in New Issue
Block a user