/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
*/
#include "i40e_type.h"
case I40E_DEV_ID_10G_BASE_T_BC:
case I40E_DEV_ID_10G_B:
case I40E_DEV_ID_10G_SFP:
+ case I40E_DEV_ID_5G_BASE_T_BC:
case I40E_DEV_ID_20G_KR2:
case I40E_DEV_ID_20G_KR2_A:
case I40E_DEV_ID_25G_B:
u32 gpio_val = 0;
u32 port;
- if (!hw->func_caps.led[idx])
+ if (!I40E_IS_X710TL_DEVICE(hw->device_id) &&
+ !hw->func_caps.led[idx])
return 0;
-
gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
#define I40E_FILTER_ACTIVITY 0xE
#define I40E_LINK_ACTIVITY 0xC
#define I40E_MAC_ACTIVITY 0xD
+#define I40E_FW_LED BIT(4)
+#define I40E_LED_MODE_VALID (I40E_GLGEN_GPIO_CTL_LED_MODE_MASK >> \
+ I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+
#define I40E_LED0 22
+#define I40E_PIN_FUNC_SDP 0x0
+#define I40E_PIN_FUNC_LED 0x1
+
/**
* i40e_led_get - return current on/off mode
* @hw: pointer to the hw struct
u32 current_mode = 0;
int i;
- if (mode & 0xfffffff0)
+ if (mode & ~I40E_LED_MODE_VALID) {
DEBUGOUT1("invalid mode passed in %X\n", mode);
+ return;
+ }
/* as per the documentation GPIO 22-29 are the LED
* GPIO pins named LED0..LED7
break;
}
+ if (I40E_IS_X710TL_DEVICE(hw->device_id)) {
+ u32 pin_func = 0;
+
+ if (mode & I40E_FW_LED)
+ pin_func = I40E_PIN_FUNC_SDP;
+ else
+ pin_func = I40E_PIN_FUNC_LED;
+
+ gpio_val &= ~I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK;
+ gpio_val |= ((pin_func <<
+ I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT) &
+ I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK);
+ }
gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
/* this & is a bit of paranoia, but serves as a range check */
gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
status = i40e_asq_send_command(hw, &desc, abilities,
abilities_size, cmd_details);
- if (status != I40E_SUCCESS)
- break;
-
- if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) {
+ switch (hw->aq.asq_last_status) {
+ case I40E_AQ_RC_EIO:
status = I40E_ERR_UNKNOWN_PHY;
break;
- } else if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) {
+ case I40E_AQ_RC_EAGAIN:
i40e_msec_delay(1);
total_delay++;
status = I40E_ERR_TIMEOUT;
+ break;
+ /* also covers I40E_AQ_RC_OK */
+ default:
+ break;
}
- } while ((hw->aq.asq_last_status != I40E_AQ_RC_OK) &&
- (total_delay < max_delay));
+
+ } while ((hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) &&
+ (total_delay < max_delay));
if (status != I40E_SUCCESS)
return status;
return status;
}
+/**
+ * i40e_hw_ver_ge
+ * @hw: pointer to the hw struct
+ * @maj: api major value
+ * @min: api minor value
+ *
+ * Assert whether current HW api version is greater/equal than provided.
+ **/
+static bool i40e_hw_ver_ge(struct i40e_hw *hw, u16 maj, u16 min)
+{
+ if (hw->aq.api_maj_ver > maj ||
+ (hw->aq.api_maj_ver == maj && hw->aq.api_min_ver >= min))
+ return true;
+ return false;
+}
+
/**
* i40e_aq_add_vsi
* @hw: pointer to the hw struct
if (set) {
flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
- if (rx_only_promisc &&
- (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) ||
- (hw->aq.api_maj_ver > 1)))
- flags |= I40E_AQC_SET_VSI_PROMISC_TX;
+ if (rx_only_promisc && i40e_hw_ver_ge(hw, 1, 5))
+ flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
}
cmd->promiscuous_flags = CPU_TO_LE16(flags);
cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
- if (((hw->aq.api_maj_ver >= 1) && (hw->aq.api_min_ver >= 5)) ||
- (hw->aq.api_maj_ver > 1))
- cmd->valid_flags |= CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_TX);
+ if (i40e_hw_ver_ge(hw, 1, 5))
+ cmd->valid_flags |=
+ CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
cmd->seid = CPU_TO_LE16(seid);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_vsi_promiscuous_modes);
- if (enable)
+ if (enable) {
flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
+ if (i40e_hw_ver_ge(hw, 1, 5))
+ flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
+ }
cmd->promiscuous_flags = CPU_TO_LE16(flags);
cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
+ if (i40e_hw_ver_ge(hw, 1, 5))
+ cmd->valid_flags |=
+ CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
cmd->seid = CPU_TO_LE16(seid);
cmd->vlan_tag = CPU_TO_LE16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
if (status)
return status;
- hw->phy.link_info.req_fec_info =
- abilities.fec_cfg_curr_mod_ext_info &
- (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS);
+ if (abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_ENABLE_FEC_AUTO)
+ hw->phy.link_info.req_fec_info =
+ (I40E_AQ_REQUEST_FEC_KR |
+ I40E_AQ_REQUEST_FEC_RS);
+ else
+ hw->phy.link_info.req_fec_info =
+ abilities.fec_cfg_curr_mod_ext_info &
+ (I40E_AQ_REQUEST_FEC_KR |
+ I40E_AQ_REQUEST_FEC_RS);
i40e_memcpy(hw->phy.link_info.module_type, &abilities.module_type,
sizeof(hw->phy.link_info.module_type), I40E_NONDMA_TO_NONDMA);
return status;
}
+/**
+ * i40e_aq_nvm_update_in_process
+ * @hw: pointer to the hw struct
+ * @update_flow_state: True indicates that update flow starts, false that ends
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Indicate NVM update in process.
+ **/
+enum i40e_status_code
+i40e_aq_nvm_update_in_process(struct i40e_hw *hw,
+ bool update_flow_state,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_nvm_update_in_process *cmd =
+ (struct i40e_aqc_nvm_update_in_process *)&desc.params.raw;
+ enum i40e_status_code status;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_nvm_update_in_process);
+
+ cmd->command = I40E_AQ_UPDATE_FLOW_END;
+
+ if (update_flow_state)
+ cmd->command |= I40E_AQ_UPDATE_FLOW_START;
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40e_aq_min_rollback_rev_update - triggers an ow after update
+ * @hw: pointer to the hw struct
+ * @mode: opt-in mode, 1b for single module update, 0b for bulk update
+ * @module: module to be updated. Ignored if mode is 0b
+ * @min_rrev: value of the new minimal version. Ignored if mode is 0b
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+enum i40e_status_code
+i40e_aq_min_rollback_rev_update(struct i40e_hw *hw, u8 mode, u8 module,
+ u32 min_rrev,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_rollback_revision_update *cmd =
+ (struct i40e_aqc_rollback_revision_update *)&desc.params.raw;
+ enum i40e_status_code status;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_rollback_revision_update);
+ cmd->optin_mode = mode;
+ cmd->module_selected = module;
+ cmd->min_rrev = min_rrev;
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
/**
* i40e_aq_oem_post_update - triggers an OEM specific flow after update
* @hw: pointer to the hw struct
"HW Capability: wr_csr_prot = 0x%llX\n\n",
(p->wr_csr_prot & 0xffff));
break;
+ case I40E_AQ_CAP_ID_DIS_UNUSED_PORTS:
+ p->dis_unused_ports = (bool)number;
+ i40e_debug(hw, I40E_DEBUG_INIT,
+ "HW Capability: dis_unused_ports = %d\n\n",
+ p->dis_unused_ports);
+ break;
case I40E_AQ_CAP_ID_NVM_MGMT:
if (number & I40E_NVM_MGMT_SEC_REV_DISABLED)
p->sec_rev_disabled = true;
return status;
}
-/**
- * i40e_aq_nvm_progress
- * @hw: pointer to the hw struct
- * @progress: pointer to progress returned from AQ
- * @cmd_details: pointer to command details structure or NULL
- *
- * Gets progress of flash rearrangement process
- **/
-enum i40e_status_code i40e_aq_nvm_progress(struct i40e_hw *hw, u8 *progress,
- struct i40e_asq_cmd_details *cmd_details)
-{
- enum i40e_status_code status;
- struct i40e_aq_desc desc;
-
- DEBUGFUNC("i40e_aq_nvm_progress");
-
- i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_progress);
- status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
- *progress = desc.params.raw[0];
- return status;
-}
-
/**
* i40e_aq_get_lldp_mib
* @hw: pointer to the hw struct
cmd->num_unicast_etags = num_tags_in_buf;
desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
- if (length > I40E_AQ_LARGE_BUF)
- desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
status = i40e_asq_send_command(hw, &desc, buf, length, cmd_details);
/* Cache current configuration */
config.phy_type = abilities.phy_type;
+ config.phy_type_ext = abilities.phy_type_ext;
config.link_speed = abilities.link_speed;
config.abilities = abilities.abilities |
I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
case I40E_DEV_ID_10G_BASE_T:
case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_10G_BASE_T_BC:
+ case I40E_DEV_ID_5G_BASE_T_BC:
case I40E_DEV_ID_10G_BASE_T_X722:
case I40E_DEV_ID_25G_B:
case I40E_DEV_ID_25G_SFP28:
break;
case I40E_DEV_ID_10G_BASE_T:
case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_5G_BASE_T_BC:
case I40E_DEV_ID_10G_BASE_T_X722:
case I40E_DEV_ID_25G_B:
case I40E_DEV_ID_25G_SFP28:
* @led_addr: LED register address
* @reg_val: read register value
**/
-static enum i40e_status_code i40e_led_get_reg(struct i40e_hw *hw, u16 led_addr,
- u32 *reg_val)
+enum i40e_status_code i40e_led_get_reg(struct i40e_hw *hw, u16 led_addr,
+ u32 *reg_val)
{
enum i40e_status_code status;
u8 phy_addr = 0;
* @led_addr: LED register address
* @reg_val: register value to write
**/
-static enum i40e_status_code i40e_led_set_reg(struct i40e_hw *hw, u16 led_addr,
- u32 reg_val)
+enum i40e_status_code i40e_led_set_reg(struct i40e_hw *hw, u16 led_addr,
+ u32 reg_val)
{
enum i40e_status_code status;
u8 phy_addr = 0;
struct i40e_hw_port_stats *stat)
{
enum i40e_status_code ret = I40E_SUCCESS;
+ bool eee_mrvl_phy;
+ bool eee_bcm_phy;
u32 val;
stat->rx_lpi_status = 0;
stat->tx_lpi_status = 0;
- if (hw->device_id == I40E_DEV_ID_10G_BASE_T_BC &&
- (hw->phy.link_info.link_speed == I40E_LINK_SPEED_2_5GB ||
- hw->phy.link_info.link_speed == I40E_LINK_SPEED_5GB)) {
+ eee_bcm_phy =
+ (hw->device_id == I40E_DEV_ID_10G_BASE_T_BC ||
+ hw->device_id == I40E_DEV_ID_5G_BASE_T_BC) &&
+ (hw->phy.link_info.link_speed == I40E_LINK_SPEED_2_5GB ||
+ hw->phy.link_info.link_speed == I40E_LINK_SPEED_5GB);
+ eee_mrvl_phy =
+ hw->device_id == I40E_DEV_ID_1G_BASE_T_X722;
+
+ if (eee_bcm_phy || eee_mrvl_phy) {
+ /* read Clause 45 PCS Status 1 register */
ret = i40e_aq_get_phy_register(hw,
I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
I40E_BCM_PHY_PCS_STATUS1_PAGE,
/* only X710-T*L requires special handling of counters
* for other devices we just read the MAC registers
*/
- if (hw->device_id == I40E_DEV_ID_10G_BASE_T_BC &&
+ if ((hw->device_id == I40E_DEV_ID_10G_BASE_T_BC ||
+ hw->device_id == I40E_DEV_ID_5G_BASE_T_BC) &&
hw->phy.link_info.link_speed != I40E_LINK_SPEED_1GB) {
enum i40e_status_code retval;
u32 cmd_status = 0;
I40E_AQ_RUN_PHY_ACT_DNL_OPCODE_GET_EEE_STAT,
&cmd_status, tx_counter, rx_counter, NULL);
- if (cmd_status != I40E_AQ_RUN_PHY_ACT_CMD_STAT_SUCC)
+ if (!retval && cmd_status != I40E_AQ_RUN_PHY_ACT_CMD_STAT_SUCC)
retval = I40E_ERR_ADMIN_QUEUE_ERROR;
return retval;
return I40E_SUCCESS;
}
+/**
+ * i40e_get_lpi_duration - read LPI time duration from EEE statistics
+ * @hw: pointer to the hw struct
+ * @stat: pointer to structure with status of rx and tx lpi
+ * @tx_duration: pointer to memory for TX LPI time duration
+ * @rx_duration: pointer to memory for RX LPI time duration
+ *
+ * Read Low Power Idle (LPI) mode time duration from Energy Efficient
+ * Ethernet (EEE) statistics.
+ */
+enum i40e_status_code i40e_get_lpi_duration(struct i40e_hw *hw,
+ struct i40e_hw_port_stats *stat,
+ u64 *tx_duration, u64 *rx_duration)
+{
+ u32 tx_time_dur, rx_time_dur;
+ enum i40e_status_code retval;
+ u32 cmd_status;
+
+ if (hw->device_id != I40E_DEV_ID_10G_BASE_T_BC &&
+ hw->device_id != I40E_DEV_ID_5G_BASE_T_BC)
+ return I40E_ERR_NOT_IMPLEMENTED;
+
+ retval = i40e_aq_run_phy_activity
+ (hw, I40E_AQ_RUN_PHY_ACT_ID_USR_DFND,
+ I40E_AQ_RUN_PHY_ACT_DNL_OPCODE_GET_EEE_DUR,
+ &cmd_status, &tx_time_dur, &rx_time_dur, NULL);
+
+ if (retval)
+ return retval;
+ if ((cmd_status & I40E_AQ_RUN_PHY_ACT_CMD_STAT_MASK) !=
+ I40E_AQ_RUN_PHY_ACT_CMD_STAT_SUCC)
+ return I40E_ERR_ADMIN_QUEUE_ERROR;
+
+ if (hw->phy.link_info.link_speed == I40E_LINK_SPEED_1GB &&
+ !tx_time_dur && !rx_time_dur &&
+ stat->tx_lpi_status && stat->rx_lpi_status) {
+ retval = i40e_aq_run_phy_activity
+ (hw, I40E_AQ_RUN_PHY_ACT_ID_USR_DFND,
+ I40E_AQ_RUN_PHY_ACT_DNL_OPCODE_GET_EEE_STAT_DUR,
+ &cmd_status,
+ &tx_time_dur, &rx_time_dur, NULL);
+
+ if (retval)
+ return retval;
+ if ((cmd_status & I40E_AQ_RUN_PHY_ACT_CMD_STAT_MASK) !=
+ I40E_AQ_RUN_PHY_ACT_CMD_STAT_SUCC)
+ return I40E_ERR_ADMIN_QUEUE_ERROR;
+ tx_time_dur = 0;
+ rx_time_dur = 0;
+ }
+
+ *tx_duration = tx_time_dur;
+ *rx_duration = rx_time_dur;
+
+ return retval;
+}
+
/**
* i40e_lpi_stat_update - update LPI counters with values relative to offset
* @hw: pointer to the hw struct