diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 191 | 
1 files changed, 117 insertions, 74 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 9ebbe3da61bb..6031223eafab 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -73,6 +73,7 @@ static const struct pci_device_id i40e_pci_tbl[] = {  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, +	{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_BC), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_SFP), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_B), 0},  	{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0}, @@ -534,6 +535,10 @@ void i40e_pf_reset_stats(struct i40e_pf *pf)  			       sizeof(pf->veb[i]->stats));  			memset(&pf->veb[i]->stats_offsets, 0,  			       sizeof(pf->veb[i]->stats_offsets)); +			memset(&pf->veb[i]->tc_stats, 0, +			       sizeof(pf->veb[i]->tc_stats)); +			memset(&pf->veb[i]->tc_stats_offsets, 0, +			       sizeof(pf->veb[i]->tc_stats_offsets));  			pf->veb[i]->stat_offsets_loaded = false;  		}  	} @@ -677,7 +682,7 @@ void i40e_update_eth_stats(struct i40e_vsi *vsi)   * i40e_update_veb_stats - Update Switch component statistics   * @veb: the VEB being updated   **/ -static void i40e_update_veb_stats(struct i40e_veb *veb) +void i40e_update_veb_stats(struct i40e_veb *veb)  {  	struct i40e_pf *pf = veb->pf;  	struct i40e_hw *hw = &pf->hw; @@ -2530,6 +2535,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  				 vsi_name,  				 i40e_stat_str(hw, aq_ret),  				 i40e_aq_str(hw, hw->aq.asq_last_status)); +		} else { +			dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n", +				 vsi->netdev->name, +				 cur_multipromisc ? "entering" : "leaving");  		}  	} @@ -2583,6 +2592,10 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)  		return;  	if (!test_and_clear_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state))  		return; +	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) { +		set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state); +		return; +	}  	for (v = 0; v < pf->num_alloc_vsi; v++) {  		if (pf->vsi[v] && @@ -2597,6 +2610,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)  			}  		}  	} +	clear_bit(__I40E_VF_DISABLE, pf->state);  }  /** @@ -3360,7 +3374,7 @@ static int i40e_vsi_configure_tx(struct i40e_vsi *vsi)  	for (i = 0; (i < vsi->num_queue_pairs) && !err; i++)  		err = i40e_configure_tx_ring(vsi->tx_rings[i]); -	if (!i40e_enabled_xdp_vsi(vsi)) +	if (err || !i40e_enabled_xdp_vsi(vsi))  		return err;  	for (i = 0; (i < vsi->num_queue_pairs) && !err; i++) @@ -6412,50 +6426,6 @@ static int i40e_resume_port_tx(struct i40e_pf *pf)  }  /** - * i40e_update_dcb_config - * @hw: pointer to the HW struct - * @enable_mib_change: enable MIB change event - * - * Update DCB configuration from the firmware - **/ -static enum i40e_status_code -i40e_update_dcb_config(struct i40e_hw *hw, bool enable_mib_change) -{ -	struct i40e_lldp_variables lldp_cfg; -	i40e_status ret; - -	if (!hw->func_caps.dcb) -		return I40E_NOT_SUPPORTED; - -	/* Read LLDP NVM area */ -	ret = i40e_read_lldp_cfg(hw, &lldp_cfg); -	if (ret) -		return I40E_ERR_NOT_READY; - -	/* Get DCBX status */ -	ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); -	if (ret) -		return ret; - -	/* Check the DCBX Status */ -	if (hw->dcbx_status == I40E_DCBX_STATUS_DONE || -	    hw->dcbx_status == I40E_DCBX_STATUS_IN_PROGRESS) { -		/* Get current DCBX configuration */ -		ret = i40e_get_dcb_config(hw); -		if (ret) -			return ret; -	} else if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) { -		return I40E_ERR_NOT_READY; -	} - -	/* Configure the LLDP MIB change event */ -	if (enable_mib_change) -		ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL); - -	return ret; -} - -/**   * i40e_init_pf_dcb - Initialize DCB configuration   * @pf: PF being configured   * @@ -6477,7 +6447,7 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf)  		goto out;  	} -	err = i40e_update_dcb_config(hw, true); +	err = i40e_init_dcb(hw, true);  	if (!err) {  		/* Device/Function is not DCBX capable */  		if ((!hw->func_caps.dcb) || @@ -6599,19 +6569,19 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)  	}  	if (pf->hw.phy.link_info.link_speed == I40E_LINK_SPEED_25GB) { -		req_fec = ", Requested FEC: None"; -		fec = ", FEC: None"; -		an = ", Autoneg: False"; +		req_fec = "None"; +		fec = "None"; +		an = "False";  		if (pf->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED) -			an = ", Autoneg: True"; +			an = "True";  		if (pf->hw.phy.link_info.fec_info &  		    I40E_AQ_CONFIG_FEC_KR_ENA) -			fec = ", FEC: CL74 FC-FEC/BASE-R"; +			fec = "CL74 FC-FEC/BASE-R";  		else if (pf->hw.phy.link_info.fec_info &  			 I40E_AQ_CONFIG_FEC_RS_ENA) -			fec = ", FEC: CL108 RS-FEC"; +			fec = "CL108 RS-FEC";  		/* 'CL108 RS-FEC' should be displayed when RS is requested, or  		 * both RS and FC are requested @@ -6620,14 +6590,19 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)  		    (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS)) {  			if (vsi->back->hw.phy.link_info.req_fec_info &  			    I40E_AQ_REQUEST_FEC_RS) -				req_fec = ", Requested FEC: CL108 RS-FEC"; +				req_fec = "CL108 RS-FEC";  			else -				req_fec = ", Requested FEC: CL74 FC-FEC/BASE-R"; +				req_fec = "CL74 FC-FEC/BASE-R";  		} +		netdev_info(vsi->netdev, +			    "NIC Link is Up, %sbps Full Duplex, Requested FEC: %s, Negotiated FEC: %s, Autoneg: %s, Flow Control: %s\n", +			    speed, req_fec, fec, an, fc); +	} else { +		netdev_info(vsi->netdev, +			    "NIC Link is Up, %sbps Full Duplex, Flow Control: %s\n", +			    speed, fc);  	} -	netdev_info(vsi->netdev, "NIC Link is Up, %sbps Full Duplex%s%s%s, Flow Control: %s\n", -		    speed, req_fec, fec, an, fc);  }  /** @@ -8486,6 +8461,11 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)  		dev_dbg(&pf->pdev->dev, "PFR requested\n");  		i40e_handle_reset_warning(pf, lock_acquired); +		dev_info(&pf->pdev->dev, +			 pf->flags & I40E_FLAG_DISABLE_FW_LLDP ? +			 "FW LLDP is disabled\n" : +			 "FW LLDP is enabled\n"); +  	} else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) {  		int v; @@ -12561,7 +12541,8 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,  	if (need_reset && prog)  		for (i = 0; i < vsi->num_queue_pairs; i++)  			if (vsi->xdp_rings[i]->xsk_umem) -				(void)i40e_xsk_async_xmit(vsi->netdev, i); +				(void)i40e_xsk_wakeup(vsi->netdev, i, +						      XDP_WAKEUP_RX);  	return 0;  } @@ -12883,7 +12864,7 @@ static const struct net_device_ops i40e_netdev_ops = {  	.ndo_bridge_setlink	= i40e_ndo_bridge_setlink,  	.ndo_bpf		= i40e_xdp,  	.ndo_xdp_xmit		= i40e_xdp_xmit, -	.ndo_xsk_async_xmit	= i40e_xsk_async_xmit, +	.ndo_xsk_wakeup	        = i40e_xsk_wakeup,  	.ndo_dfwd_add_station	= i40e_fwd_add,  	.ndo_dfwd_del_station	= i40e_fwd_del,  }; @@ -14569,9 +14550,20 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags)   **/  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) { +	u32 val = rd32(&pf->hw, I40E_GL_FWSTS) & I40E_GL_FWSTS_FWS1B_MASK; +	bool is_recovery_mode = false; + +	if (pf->hw.mac.type == I40E_MAC_XL710) +		is_recovery_mode = +		val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK || +		val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK || +		val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_TRANSITION_MASK || +		val == I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_NVM_MASK; +	if (pf->hw.mac.type == I40E_MAC_X722) +		is_recovery_mode = +		val == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK || +		val == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK; +	if (is_recovery_mode) {  		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); @@ -14585,6 +14577,51 @@ static bool i40e_check_recovery_mode(struct i40e_pf *pf)  }  /** + * i40e_pf_loop_reset - perform reset in a loop. + * @pf: board private structure + * + * This function is useful when a NIC is about to enter recovery mode. + * When a NIC's internal data structures are corrupted the NIC's + * firmware is going to enter recovery mode. + * Right after a POR it takes about 7 minutes for firmware to enter + * recovery mode. Until that time a NIC is in some kind of intermediate + * state. After that time period the NIC almost surely enters + * recovery mode. The only way for a driver to detect intermediate + * state is to issue a series of pf-resets and check a return value. + * If a PF reset returns success then the firmware could be in recovery + * mode so the caller of this code needs to check for recovery mode + * if this function returns success. There is a little chance that + * firmware will hang in intermediate state forever. + * Since waiting 7 minutes is quite a lot of time this function waits + * 10 seconds and then gives up by returning an error. + * + * Return 0 on success, negative on failure. + **/ +static i40e_status i40e_pf_loop_reset(struct i40e_pf *pf) +{ +	const unsigned short MAX_CNT = 1000; +	const unsigned short MSECS = 10; +	struct i40e_hw *hw = &pf->hw; +	i40e_status ret; +	int cnt; + +	for (cnt = 0; cnt < MAX_CNT; ++cnt) { +		ret = i40e_pf_reset(hw); +		if (!ret) +			break; +		msleep(MSECS); +	} + +	if (cnt == MAX_CNT) { +		dev_info(&pf->pdev->dev, "PF reset failed: %d\n", ret); +		return ret; +	} + +	pf->pfr_count++; +	return ret; +} + +/**   * i40e_init_recovery_mode - initialize subsystems needed in recovery mode   * @pf: board private structure   * @hw: ptr to the hardware info @@ -14812,14 +14849,22 @@ 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); -	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++; + +	err = i40e_set_mac_type(hw); +	if (err) { +		dev_warn(&pdev->dev, "unidentified MAC or BLANK NVM: %d\n", +			 err); +		goto err_pf_reset;  	} + +	err = i40e_pf_loop_reset(pf); +	if (err) { +		dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err); +		goto err_pf_reset; +	} + +	i40e_check_recovery_mode(pf); +  	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; @@ -15605,8 +15650,7 @@ static void i40e_shutdown(struct pci_dev *pdev)   **/  static int __maybe_unused i40e_suspend(struct device *dev)  { -	struct pci_dev *pdev = to_pci_dev(dev); -	struct i40e_pf *pf = pci_get_drvdata(pdev); +	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 */ @@ -15656,8 +15700,7 @@ static int __maybe_unused i40e_suspend(struct device *dev)   **/  static int __maybe_unused i40e_resume(struct device *dev)  { -	struct pci_dev *pdev = to_pci_dev(dev); -	struct i40e_pf *pf = pci_get_drvdata(pdev); +	struct i40e_pf *pf = dev_get_drvdata(dev);  	int err;  	/* If we're not suspended, then there is nothing to do */ @@ -15674,7 +15717,7 @@ static int __maybe_unused i40e_resume(struct device *dev)  	 */  	err = i40e_restore_interrupt_scheme(pf);  	if (err) { -		dev_err(&pdev->dev, "Cannot restore interrupt scheme: %d\n", +		dev_err(dev, "Cannot restore interrupt scheme: %d\n",  			err);  	}  |