|
@@ -6911,6 +6911,7 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig)
|
|
|
**/
|
|
|
static int i40e_setup_pf_switch(struct i40e_pf *pf)
|
|
|
{
|
|
|
+ u32 rxfc, txfc, rxfc_reg;
|
|
|
int ret;
|
|
|
|
|
|
/* find out what's out there already */
|
|
@@ -6981,20 +6982,65 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf)
|
|
|
i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
|
|
|
i40e_link_event(pf);
|
|
|
|
|
|
- /* Initialize user-specifics link properties */
|
|
|
+ /* Initialize user-specific link properties */
|
|
|
pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
|
|
|
I40E_AQ_AN_COMPLETED) ? true : false);
|
|
|
- pf->hw.fc.requested_mode = I40E_FC_DEFAULT;
|
|
|
- if (pf->hw.phy.link_info.an_info &
|
|
|
- (I40E_AQ_LINK_PAUSE_TX | I40E_AQ_LINK_PAUSE_RX))
|
|
|
+ /* requested_mode is set in probe or by ethtool */
|
|
|
+ if (!pf->fc_autoneg_status)
|
|
|
+ goto no_autoneg;
|
|
|
+
|
|
|
+ if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) &&
|
|
|
+ (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX))
|
|
|
pf->hw.fc.current_mode = I40E_FC_FULL;
|
|
|
else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
|
|
|
pf->hw.fc.current_mode = I40E_FC_TX_PAUSE;
|
|
|
else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
|
|
|
pf->hw.fc.current_mode = I40E_FC_RX_PAUSE;
|
|
|
else
|
|
|
- pf->hw.fc.current_mode = I40E_FC_DEFAULT;
|
|
|
+ pf->hw.fc.current_mode = I40E_FC_NONE;
|
|
|
+
|
|
|
+ /* sync the flow control settings with the auto-neg values */
|
|
|
+ switch (pf->hw.fc.current_mode) {
|
|
|
+ case I40E_FC_FULL:
|
|
|
+ txfc = 1;
|
|
|
+ rxfc = 1;
|
|
|
+ break;
|
|
|
+ case I40E_FC_TX_PAUSE:
|
|
|
+ txfc = 1;
|
|
|
+ rxfc = 0;
|
|
|
+ break;
|
|
|
+ case I40E_FC_RX_PAUSE:
|
|
|
+ txfc = 0;
|
|
|
+ rxfc = 1;
|
|
|
+ break;
|
|
|
+ case I40E_FC_NONE:
|
|
|
+ case I40E_FC_DEFAULT:
|
|
|
+ txfc = 0;
|
|
|
+ rxfc = 0;
|
|
|
+ break;
|
|
|
+ case I40E_FC_PFC:
|
|
|
+ /* TBD */
|
|
|
+ break;
|
|
|
+ /* no default case, we have to handle all possibilities here */
|
|
|
+ }
|
|
|
+
|
|
|
+ wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
|
|
|
+
|
|
|
+ rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
|
|
|
+ ~I40E_PRTDCB_MFLCN_RFCE_MASK;
|
|
|
+ rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
|
|
|
+
|
|
|
+ wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg);
|
|
|
|
|
|
+ goto fc_complete;
|
|
|
+
|
|
|
+no_autoneg:
|
|
|
+ /* disable L2 flow control, user can turn it on if they wish */
|
|
|
+ wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0);
|
|
|
+ wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
|
|
|
+ ~I40E_PRTDCB_MFLCN_RFCE_MASK);
|
|
|
+
|
|
|
+fc_complete:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -7288,6 +7334,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
goto err_pf_reset;
|
|
|
}
|
|
|
|
|
|
+ /* set up a default setting for link flow control */
|
|
|
+ pf->hw.fc.requested_mode = I40E_FC_NONE;
|
|
|
+
|
|
|
err = i40e_init_adminq(hw);
|
|
|
dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
|
|
|
if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
|