From c56999f94876b21cf18301076b9687ecdafdc9e5 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 4 Jun 2014 08:45:26 +0000 Subject: [PATCH] i40e/i40evf: Add set_fc and init of FC settings Add function set_fc to set the requested FC mode. This patch also adds the init of FC setting to get_link_info and replaces the init code to set FC off by default in main. Also adds i40e_set_phy_config to support this. Change-ID: I7b25bbaec81f15777137ab324a095f916e44351d Signed-off-by: Catherine Sullivan Tested-by: Jim Young Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 125 ++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 60 +-------- .../net/ethernet/intel/i40e/i40e_prototype.h | 9 ++ drivers/net/ethernet/intel/i40e/i40e_type.h | 8 ++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 8 ++ 5 files changed, 154 insertions(+), 56 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index debca01e684f..bf808d4cb7b8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1082,6 +1082,118 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw, return status; } +/** + * i40e_aq_set_phy_config + * @hw: pointer to the hw struct + * @config: structure with PHY configuration to be set + * @cmd_details: pointer to command details structure or NULL + * + * Set the various PHY configuration parameters + * supported on the Port.One or more of the Set PHY config parameters may be + * ignored in an MFP mode as the PF may not have the privilege to set some + * of the PHY Config parameters. This status will be indicated by the + * command response. + **/ +enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, + struct i40e_aq_set_phy_config *config, + struct i40e_asq_cmd_details *cmd_details) +{ + struct i40e_aq_desc desc; + struct i40e_aq_set_phy_config *cmd = + (struct i40e_aq_set_phy_config *)&desc.params.raw; + enum i40e_status_code status; + + if (!config) + return I40E_ERR_PARAM; + + i40e_fill_default_direct_cmd_desc(&desc, + i40e_aqc_opc_set_phy_config); + + *cmd = *config; + + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + + return status; +} + +/** + * i40e_set_fc + * @hw: pointer to the hw struct + * + * Set the requested flow control mode using set_phy_config. + **/ +enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, + bool atomic_restart) +{ + enum i40e_fc_mode fc_mode = hw->fc.requested_mode; + struct i40e_aq_get_phy_abilities_resp abilities; + struct i40e_aq_set_phy_config config; + enum i40e_status_code status; + u8 pause_mask = 0x0; + + *aq_failures = 0x0; + + switch (fc_mode) { + case I40E_FC_FULL: + pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX; + pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX; + break; + case I40E_FC_RX_PAUSE: + pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX; + break; + case I40E_FC_TX_PAUSE: + pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX; + break; + default: + break; + } + + /* Get the current phy config */ + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, + NULL); + if (status) { + *aq_failures |= I40E_SET_FC_AQ_FAIL_GET; + return status; + } + + memset(&config, 0, sizeof(struct i40e_aq_set_phy_config)); + /* clear the old pause settings */ + config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) & + ~(I40E_AQ_PHY_FLAG_PAUSE_RX); + /* set the new abilities */ + config.abilities |= pause_mask; + /* If the abilities have changed, then set the new config */ + if (config.abilities != abilities.abilities) { + /* Auto restart link so settings take effect */ + if (atomic_restart) + config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; + /* Copy over all the old settings */ + config.phy_type = abilities.phy_type; + config.link_speed = abilities.link_speed; + config.eee_capability = abilities.eee_capability; + config.eeer = abilities.eeer_val; + config.low_power_ctrl = abilities.d3_lpan; + status = i40e_aq_set_phy_config(hw, &config, NULL); + + if (status) + *aq_failures |= I40E_SET_FC_AQ_FAIL_SET; + } + /* Update the link info */ + status = i40e_update_link_info(hw, true); + if (status) { + /* Wait a little bit (on 40G cards it sometimes takes a really + * long time for link to come back from the atomic reset) + * and try once more + */ + msleep(1000); + status = i40e_update_link_info(hw, true); + } + if (status) + *aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE; + + return status; +} + /** * i40e_aq_clear_pxe_mode * @hw: pointer to the hw struct @@ -1158,6 +1270,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, (struct i40e_aqc_get_link_status *)&desc.params.raw; struct i40e_link_status *hw_link_info = &hw->phy.link_info; i40e_status status; + bool tx_pause, rx_pause; u16 command_flags; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_link_status); @@ -1187,6 +1300,18 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw, hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size); hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK; + /* update fc info */ + tx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_TX); + rx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_RX); + if (tx_pause & rx_pause) + hw->fc.current_mode = I40E_FC_FULL; + else if (tx_pause) + hw->fc.current_mode = I40E_FC_TX_PAUSE; + else if (rx_pause) + hw->fc.current_mode = I40E_FC_RX_PAUSE; + else + hw->fc.current_mode = I40E_FC_NONE; + if (resp->config & I40E_AQ_CONFIG_CRC_ENA) hw_link_info->crc_enable = true; else diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 71eff1676778..44cea6a854c2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4326,8 +4326,12 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) static int i40e_up_complete(struct i40e_vsi *vsi) { struct i40e_pf *pf = vsi->back; + u8 set_fc_aq_fail = 0; int err; + /* force flow control off */ + i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); + if (pf->flags & I40E_FLAG_MSIX_ENABLED) i40e_vsi_configure_msix(vsi); else @@ -8277,7 +8281,6 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) **/ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) { - u32 rxfc = 0, txfc = 0, rxfc_reg; int ret; /* find out what's out there already */ @@ -8343,62 +8346,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) /* Initialize user-specific link properties */ pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info & I40E_AQ_AN_COMPLETED) ? true : false); - /* 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_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: i40e_ptp_init(pf); return ret; diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 679087867bd2..b6849fb47db7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -74,6 +74,15 @@ i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id, struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw, + bool qualified_modules, bool report_init, + struct i40e_aq_get_phy_abilities_resp *abilities, + struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, + struct i40e_aq_set_phy_config *config, + struct i40e_asq_cmd_details *cmd_details); +enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, + bool atomic_reset); i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw, diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index f1c58ab8f60d..380eb53a83b3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -140,6 +140,14 @@ enum i40e_fc_mode { I40E_FC_DEFAULT }; +enum i40e_set_fc_aq_failures { + I40E_SET_FC_AQ_FAIL_NONE = 0, + I40E_SET_FC_AQ_FAIL_GET = 1, + I40E_SET_FC_AQ_FAIL_SET = 2, + I40E_SET_FC_AQ_FAIL_UPDATE = 4, + I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6 +}; + enum i40e_vsi_type { I40E_VSI_MAIN = 0, I40E_VSI_VMDQ1, diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 5b6e955cfc66..6dd72ad58e7d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -140,6 +140,14 @@ enum i40e_fc_mode { I40E_FC_DEFAULT }; +enum i40e_set_fc_aq_failures { + I40E_SET_FC_AQ_FAIL_NONE = 0, + I40E_SET_FC_AQ_FAIL_GET = 1, + I40E_SET_FC_AQ_FAIL_SET = 2, + I40E_SET_FC_AQ_FAIL_UPDATE = 4, + I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6 +}; + enum i40e_vsi_type { I40E_VSI_MAIN = 0, I40E_VSI_VMDQ1,