Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2018-08-28

This series contains new features and implementation updates for the
ice driver.

Anirudh reworks the current flex programming logic to add support for
a second flex descriptor profile.  Updated the transmit scheduler
code to handle changes to the spec, specifically the firmware expects
a 4KB buffer at all times so fix the default scheduler topology buffer
size.  Also the maximum children per node per layer is replaced by
maximum sibling group size.  Adds a check to ensure a reset is not in
progress before exercising a control queue operation.  Refactored the
switch rule management functions and structures to simply the logic and
to add a common function to search for a rule entry and add a new rule
entry.  Refactored the VSI allocation, deletion and rebuild flow so that
on reset we can restore all the filters that were previously added.  Did
some spring cleaning of define names and macros.

Dan updates the admin queue command for requesting resource ownership
to the latest specification by adding new enum's and change the locks.

Zhenning optimizes the driver by using the existing buffer in a
structure directly versus a local array.

Chinh implements handlers for ethtool for get and set link settings.

Sudheer implements transmit hang/timeout detection and malicious driver
detection in the driver.

Md Fahad Iqbal implements the get and set bridge mode operations.

Hieu adds the ability for firmware logging during initialization.

Brett updates the driver to only enable VSI transmit and receive pruning
when VLAN 0 is active, and when VLAN 0 is removed/not active, pruning is
disabled.

Akeem adds a flag to use for stopping the service task.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-08-28 15:57:25 -07:00
commit 09990ad164
17 changed files with 3328 additions and 1201 deletions

View File

@ -62,6 +62,7 @@ extern const char ice_drv_ver[];
#define ICE_RES_VALID_BIT 0x8000
#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
#define ICE_INVAL_Q_INDEX 0xffff
#define ICE_INVAL_VFID 256
#define ICE_VSIQF_HKEY_ARRAY_SIZE ((VSIQF_HKEY_MAX_INDEX + 1) * 4)
@ -122,6 +123,7 @@ struct ice_sw {
enum ice_state {
__ICE_DOWN,
__ICE_NEEDS_RESTART,
__ICE_PREPARED_FOR_RESET, /* set by driver when prepared */
__ICE_RESET_RECOVERY_PENDING, /* set by driver when reset starts */
__ICE_PFR_REQ, /* set by driver and peers */
__ICE_CORER_REQ, /* set by driver and peers */
@ -132,9 +134,11 @@ enum ice_state {
__ICE_SUSPENDED, /* set on module remove path */
__ICE_RESET_FAILED, /* set by reset/rebuild */
__ICE_ADMINQ_EVENT_PENDING,
__ICE_MDD_EVENT_PENDING,
__ICE_FLTR_OVERFLOW_PROMISC,
__ICE_CFG_BUSY,
__ICE_SERVICE_SCHED,
__ICE_SERVICE_DIS,
__ICE_STATE_NBITS /* must be last */
};
@ -270,6 +274,9 @@ struct ice_pf {
struct ice_hw_port_stats stats_prev;
struct ice_hw hw;
u8 stat_prev_loaded; /* has previous stats been loaded */
u32 tx_timeout_count;
unsigned long tx_timeout_last_recovery;
u32 tx_timeout_recovery_level;
char int_name[ICE_INT_NAME_STR_LEN];
};

View File

@ -443,6 +443,8 @@ struct ice_aqc_vsi_props {
u8 reserved[24];
};
#define ICE_MAX_NUM_RECIPES 64
/* Add/Update/Remove/Get switch rules (indirect 0x02A0, 0x02A1, 0x02A2, 0x02A3)
*/
struct ice_aqc_sw_rules {
@ -771,9 +773,8 @@ struct ice_aqc_layer_props {
u8 chunk_size;
__le16 max_device_nodes;
__le16 max_pf_nodes;
u8 rsvd0[2];
__le16 max_shared_rate_lmtr;
__le16 max_children;
u8 rsvd0[4];
__le16 max_sibl_grp_sz;
__le16 max_cir_rl_profiles;
__le16 max_eir_rl_profiles;
__le16 max_srl_profiles;
@ -921,7 +922,9 @@ struct ice_aqc_set_phy_cfg_data {
#define ICE_AQ_PHY_ENA_RX_PAUSE_ABILITY BIT(1)
#define ICE_AQ_PHY_ENA_LOW_POWER BIT(2)
#define ICE_AQ_PHY_ENA_LINK BIT(3)
#define ICE_AQ_PHY_ENA_ATOMIC_LINK BIT(5)
#define ICE_AQ_PHY_ENA_AUTO_LINK_UPDT BIT(5)
#define ICE_AQ_PHY_ENA_LESM BIT(6)
#define ICE_AQ_PHY_ENA_AUTO_FEC BIT(7)
u8 low_power_ctrl;
__le16 eee_cap; /* Value from ice_aqc_get_phy_caps */
__le16 eeer_value;
@ -1203,6 +1206,84 @@ struct ice_aqc_dis_txq {
struct ice_aqc_dis_txq_item qgrps[1];
};
/* Configure Firmware Logging Command (indirect 0xFF09)
* Logging Information Read Response (indirect 0xFF10)
* Note: The 0xFF10 command has no input parameters.
*/
struct ice_aqc_fw_logging {
u8 log_ctrl;
#define ICE_AQC_FW_LOG_AQ_EN BIT(0)
#define ICE_AQC_FW_LOG_UART_EN BIT(1)
u8 rsvd0;
u8 log_ctrl_valid; /* Not used by 0xFF10 Response */
#define ICE_AQC_FW_LOG_AQ_VALID BIT(0)
#define ICE_AQC_FW_LOG_UART_VALID BIT(1)
u8 rsvd1[5];
__le32 addr_high;
__le32 addr_low;
};
enum ice_aqc_fw_logging_mod {
ICE_AQC_FW_LOG_ID_GENERAL = 0,
ICE_AQC_FW_LOG_ID_CTRL,
ICE_AQC_FW_LOG_ID_LINK,
ICE_AQC_FW_LOG_ID_LINK_TOPO,
ICE_AQC_FW_LOG_ID_DNL,
ICE_AQC_FW_LOG_ID_I2C,
ICE_AQC_FW_LOG_ID_SDP,
ICE_AQC_FW_LOG_ID_MDIO,
ICE_AQC_FW_LOG_ID_ADMINQ,
ICE_AQC_FW_LOG_ID_HDMA,
ICE_AQC_FW_LOG_ID_LLDP,
ICE_AQC_FW_LOG_ID_DCBX,
ICE_AQC_FW_LOG_ID_DCB,
ICE_AQC_FW_LOG_ID_NETPROXY,
ICE_AQC_FW_LOG_ID_NVM,
ICE_AQC_FW_LOG_ID_AUTH,
ICE_AQC_FW_LOG_ID_VPD,
ICE_AQC_FW_LOG_ID_IOSF,
ICE_AQC_FW_LOG_ID_PARSER,
ICE_AQC_FW_LOG_ID_SW,
ICE_AQC_FW_LOG_ID_SCHEDULER,
ICE_AQC_FW_LOG_ID_TXQ,
ICE_AQC_FW_LOG_ID_RSVD,
ICE_AQC_FW_LOG_ID_POST,
ICE_AQC_FW_LOG_ID_WATCHDOG,
ICE_AQC_FW_LOG_ID_TASK_DISPATCH,
ICE_AQC_FW_LOG_ID_MNG,
ICE_AQC_FW_LOG_ID_MAX,
};
/* This is the buffer for both of the logging commands.
* The entry array size depends on the datalen parameter in the descriptor.
* There will be a total of datalen / 2 entries.
*/
struct ice_aqc_fw_logging_data {
__le16 entry[1];
#define ICE_AQC_FW_LOG_ID_S 0
#define ICE_AQC_FW_LOG_ID_M (0xFFF << ICE_AQC_FW_LOG_ID_S)
#define ICE_AQC_FW_LOG_CONF_SUCCESS 0 /* Used by response */
#define ICE_AQC_FW_LOG_CONF_BAD_INDX BIT(12) /* Used by response */
#define ICE_AQC_FW_LOG_EN_S 12
#define ICE_AQC_FW_LOG_EN_M (0xF << ICE_AQC_FW_LOG_EN_S)
#define ICE_AQC_FW_LOG_INFO_EN BIT(12) /* Used by command */
#define ICE_AQC_FW_LOG_INIT_EN BIT(13) /* Used by command */
#define ICE_AQC_FW_LOG_FLOW_EN BIT(14) /* Used by command */
#define ICE_AQC_FW_LOG_ERR_EN BIT(15) /* Used by command */
};
/* Get/Clear FW Log (indirect 0xFF11) */
struct ice_aqc_get_clear_fw_log {
u8 flags;
#define ICE_AQC_FW_LOG_CLEAR BIT(0)
#define ICE_AQC_FW_LOG_MORE_DATA_AVAIL BIT(1)
u8 rsvd1[7];
__le32 addr_high;
__le32 addr_low;
};
/**
* struct ice_aq_desc - Admin Queue (AQ) descriptor
* @flags: ICE_AQ_FLAG_* flags
@ -1252,6 +1333,9 @@ struct ice_aq_desc {
struct ice_aqc_add_txqs add_txqs;
struct ice_aqc_dis_txqs dis_txqs;
struct ice_aqc_add_get_update_free_vsi vsi_cmd;
struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res;
struct ice_aqc_fw_logging fw_logging;
struct ice_aqc_get_clear_fw_log get_clear_fw_log;
struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
struct ice_aqc_set_event_mask set_event_mask;
struct ice_aqc_get_link_status get_link_status;
@ -1349,6 +1433,9 @@ enum ice_adminq_opc {
/* TX queue handling commands/events */
ice_aqc_opc_add_txqs = 0x0C30,
ice_aqc_opc_dis_txqs = 0x0C31,
/* debug commands */
ice_aqc_opc_fw_logging = 0xFF09,
};
#endif /* _ICE_ADMINQ_CMD_H_ */

View File

@ -7,16 +7,16 @@
#define ICE_PF_RESET_WAIT_COUNT 200
#define ICE_NIC_FLX_ENTRY(hw, mdid, idx) \
wr32((hw), GLFLXP_RXDID_FLX_WRD_##idx(ICE_RXDID_FLEX_NIC), \
#define ICE_PROG_FLEX_ENTRY(hw, rxdid, mdid, idx) \
wr32((hw), GLFLXP_RXDID_FLX_WRD_##idx(rxdid), \
((ICE_RX_OPC_MDID << \
GLFLXP_RXDID_FLX_WRD_##idx##_RXDID_OPCODE_S) & \
GLFLXP_RXDID_FLX_WRD_##idx##_RXDID_OPCODE_M) | \
(((mdid) << GLFLXP_RXDID_FLX_WRD_##idx##_PROT_MDID_S) & \
GLFLXP_RXDID_FLX_WRD_##idx##_PROT_MDID_M))
#define ICE_NIC_FLX_FLG_ENTRY(hw, flg_0, flg_1, flg_2, flg_3, idx) \
wr32((hw), GLFLXP_RXDID_FLAGS(ICE_RXDID_FLEX_NIC, idx), \
#define ICE_PROG_FLG_ENTRY(hw, rxdid, flg_0, flg_1, flg_2, flg_3, idx) \
wr32((hw), GLFLXP_RXDID_FLAGS(rxdid, idx), \
(((flg_0) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) & \
GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) | \
(((flg_1) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S) & \
@ -125,7 +125,7 @@ ice_aq_manage_mac_read(struct ice_hw *hw, void *buf, u16 buf_size,
*
* Returns the various PHY capabilities supported on the Port (0x0600)
*/
static enum ice_status
enum ice_status
ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
struct ice_aqc_get_phy_caps_data *pcaps,
struct ice_sq_cd *cd)
@ -290,30 +290,85 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
}
/**
* ice_init_flex_parser - initialize rx flex parser
* ice_init_flex_flags
* @hw: pointer to the hardware structure
* @prof_id: Rx Descriptor Builder profile ID
*
* Function to initialize flex descriptors
* Function to initialize Rx flex flags
*/
static void ice_init_flex_parser(struct ice_hw *hw)
static void ice_init_flex_flags(struct ice_hw *hw, enum ice_rxdid prof_id)
{
u8 idx = 0;
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_HASH_LOW, 0);
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_HASH_HIGH, 1);
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_FLOW_ID_LOWER, 2);
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_FLOW_ID_HIGH, 3);
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_PKT_FRG, ICE_RXFLG_UDP_GRE,
ICE_RXFLG_PKT_DSI, ICE_RXFLG_FIN, idx++);
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_SYN, ICE_RXFLG_RST,
/* Flex-flag fields (0-2) are programmed with FLG64 bits with layout:
* flexiflags0[5:0] - TCP flags, is_packet_fragmented, is_packet_UDP_GRE
* flexiflags1[3:0] - Not used for flag programming
* flexiflags2[7:0] - Tunnel and VLAN types
* 2 invalid fields in last index
*/
switch (prof_id) {
/* Rx flex flags are currently programmed for the NIC profiles only.
* Different flag bit programming configurations can be added per
* profile as needed.
*/
case ICE_RXDID_FLEX_NIC:
case ICE_RXDID_FLEX_NIC_2:
ICE_PROG_FLG_ENTRY(hw, prof_id, ICE_RXFLG_PKT_FRG,
ICE_RXFLG_UDP_GRE, ICE_RXFLG_PKT_DSI,
ICE_RXFLG_FIN, idx++);
/* flex flag 1 is not used for flexi-flag programming, skipping
* these four FLG64 bits.
*/
ICE_PROG_FLG_ENTRY(hw, prof_id, ICE_RXFLG_SYN, ICE_RXFLG_RST,
ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI, idx++);
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI,
ICE_RXFLG_EVLAN_x8100, ICE_RXFLG_EVLAN_x9100,
idx++);
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_VLAN_x8100, ICE_RXFLG_TNL_VLAN,
ICE_RXFLG_TNL_MAC, ICE_RXFLG_TNL0, idx++);
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_TNL1, ICE_RXFLG_TNL2,
ICE_PROG_FLG_ENTRY(hw, prof_id, ICE_RXFLG_PKT_DSI,
ICE_RXFLG_PKT_DSI, ICE_RXFLG_EVLAN_x8100,
ICE_RXFLG_EVLAN_x9100, idx++);
ICE_PROG_FLG_ENTRY(hw, prof_id, ICE_RXFLG_VLAN_x8100,
ICE_RXFLG_TNL_VLAN, ICE_RXFLG_TNL_MAC,
ICE_RXFLG_TNL0, idx++);
ICE_PROG_FLG_ENTRY(hw, prof_id, ICE_RXFLG_TNL1, ICE_RXFLG_TNL2,
ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI, idx);
break;
default:
ice_debug(hw, ICE_DBG_INIT,
"Flag programming for profile ID %d not supported\n",
prof_id);
}
}
/**
* ice_init_flex_flds
* @hw: pointer to the hardware structure
* @prof_id: Rx Descriptor Builder profile ID
*
* Function to initialize flex descriptors
*/
static void ice_init_flex_flds(struct ice_hw *hw, enum ice_rxdid prof_id)
{
enum ice_flex_rx_mdid mdid;
switch (prof_id) {
case ICE_RXDID_FLEX_NIC:
case ICE_RXDID_FLEX_NIC_2:
ICE_PROG_FLEX_ENTRY(hw, prof_id, ICE_RX_MDID_HASH_LOW, 0);
ICE_PROG_FLEX_ENTRY(hw, prof_id, ICE_RX_MDID_HASH_HIGH, 1);
ICE_PROG_FLEX_ENTRY(hw, prof_id, ICE_RX_MDID_FLOW_ID_LOWER, 2);
mdid = (prof_id == ICE_RXDID_FLEX_NIC_2) ?
ICE_RX_MDID_SRC_VSI : ICE_RX_MDID_FLOW_ID_HIGH;
ICE_PROG_FLEX_ENTRY(hw, prof_id, mdid, 3);
ice_init_flex_flags(hw, prof_id);
break;
default:
ice_debug(hw, ICE_DBG_INIT,
"Field init for profile ID %d not supported\n",
prof_id);
}
}
/**
@ -333,20 +388,7 @@ static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
INIT_LIST_HEAD(&sw->vsi_list_map_head);
mutex_init(&sw->mac_list_lock);
INIT_LIST_HEAD(&sw->mac_list_head);
mutex_init(&sw->vlan_list_lock);
INIT_LIST_HEAD(&sw->vlan_list_head);
mutex_init(&sw->eth_m_list_lock);
INIT_LIST_HEAD(&sw->eth_m_list_head);
mutex_init(&sw->promisc_list_lock);
INIT_LIST_HEAD(&sw->promisc_list_head);
mutex_init(&sw->mac_vlan_list_lock);
INIT_LIST_HEAD(&sw->mac_vlan_list_head);
ice_init_def_sw_recp(hw);
return 0;
}
@ -360,22 +402,201 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
struct ice_switch_info *sw = hw->switch_info;
struct ice_vsi_list_map_info *v_pos_map;
struct ice_vsi_list_map_info *v_tmp_map;
struct ice_sw_recipe *recps;
u8 i;
list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
list_entry) {
list_del(&v_pos_map->list_entry);
devm_kfree(ice_hw_to_dev(hw), v_pos_map);
}
recps = hw->switch_info->recp_list;
for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
struct ice_fltr_mgmt_list_entry *lst_itr, *tmp_entry;
mutex_destroy(&sw->mac_list_lock);
mutex_destroy(&sw->vlan_list_lock);
mutex_destroy(&sw->eth_m_list_lock);
mutex_destroy(&sw->promisc_list_lock);
mutex_destroy(&sw->mac_vlan_list_lock);
recps[i].root_rid = i;
mutex_destroy(&recps[i].filt_rule_lock);
list_for_each_entry_safe(lst_itr, tmp_entry,
&recps[i].filt_rules, list_entry) {
list_del(&lst_itr->list_entry);
devm_kfree(ice_hw_to_dev(hw), lst_itr);
}
}
devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
devm_kfree(ice_hw_to_dev(hw), sw);
}
#define ICE_FW_LOG_DESC_SIZE(n) (sizeof(struct ice_aqc_fw_logging_data) + \
(((n) - 1) * sizeof(((struct ice_aqc_fw_logging_data *)0)->entry)))
#define ICE_FW_LOG_DESC_SIZE_MAX \
ICE_FW_LOG_DESC_SIZE(ICE_AQC_FW_LOG_ID_MAX)
/**
* ice_cfg_fw_log - configure FW logging
* @hw: pointer to the hw struct
* @enable: enable certain FW logging events if true, disable all if false
*
* This function enables/disables the FW logging via Rx CQ events and a UART
* port based on predetermined configurations. FW logging via the Rx CQ can be
* enabled/disabled for individual PF's. However, FW logging via the UART can
* only be enabled/disabled for all PFs on the same device.
*
* To enable overall FW logging, the "cq_en" and "uart_en" enable bits in
* hw->fw_log need to be set accordingly, e.g. based on user-provided input,
* before initializing the device.
*
* When re/configuring FW logging, callers need to update the "cfg" elements of
* the hw->fw_log.evnts array with the desired logging event configurations for
* modules of interest. When disabling FW logging completely, the callers can
* just pass false in the "enable" parameter. On completion, the function will
* update the "cur" element of the hw->fw_log.evnts array with the resulting
* logging event configurations of the modules that are being re/configured. FW
* logging modules that are not part of a reconfiguration operation retain their
* previous states.
*
* Before resetting the device, it is recommended that the driver disables FW
* logging before shutting down the control queue. When disabling FW logging
* ("enable" = false), the latest configurations of FW logging events stored in
* hw->fw_log.evnts[] are not overridden to allow them to be reconfigured after
* a device reset.
*
* When enabling FW logging to emit log messages via the Rx CQ during the
* device's initialization phase, a mechanism alternative to interrupt handlers
* needs to be used to extract FW log messages from the Rx CQ periodically and
* to prevent the Rx CQ from being full and stalling other types of control
* messages from FW to SW. Interrupts are typically disabled during the device's
* initialization phase.
*/
static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable)
{
struct ice_aqc_fw_logging_data *data = NULL;
struct ice_aqc_fw_logging *cmd;
enum ice_status status = 0;
u16 i, chgs = 0, len = 0;
struct ice_aq_desc desc;
u8 actv_evnts = 0;
void *buf = NULL;
if (!hw->fw_log.cq_en && !hw->fw_log.uart_en)
return 0;
/* Disable FW logging only when the control queue is still responsive */
if (!enable &&
(!hw->fw_log.actv_evnts || !ice_check_sq_alive(hw, &hw->adminq)))
return 0;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_fw_logging);
cmd = &desc.params.fw_logging;
/* Indicate which controls are valid */
if (hw->fw_log.cq_en)
cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_AQ_VALID;
if (hw->fw_log.uart_en)
cmd->log_ctrl_valid |= ICE_AQC_FW_LOG_UART_VALID;
if (enable) {
/* Fill in an array of entries with FW logging modules and
* logging events being reconfigured.
*/
for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
u16 val;
/* Keep track of enabled event types */
actv_evnts |= hw->fw_log.evnts[i].cfg;
if (hw->fw_log.evnts[i].cfg == hw->fw_log.evnts[i].cur)
continue;
if (!data) {
data = devm_kzalloc(ice_hw_to_dev(hw),
ICE_FW_LOG_DESC_SIZE_MAX,
GFP_KERNEL);
if (!data)
return ICE_ERR_NO_MEMORY;
}
val = i << ICE_AQC_FW_LOG_ID_S;
val |= hw->fw_log.evnts[i].cfg << ICE_AQC_FW_LOG_EN_S;
data->entry[chgs++] = cpu_to_le16(val);
}
/* Only enable FW logging if at least one module is specified.
* If FW logging is currently enabled but all modules are not
* enabled to emit log messages, disable FW logging altogether.
*/
if (actv_evnts) {
/* Leave if there is effectively no change */
if (!chgs)
goto out;
if (hw->fw_log.cq_en)
cmd->log_ctrl |= ICE_AQC_FW_LOG_AQ_EN;
if (hw->fw_log.uart_en)
cmd->log_ctrl |= ICE_AQC_FW_LOG_UART_EN;
buf = data;
len = ICE_FW_LOG_DESC_SIZE(chgs);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
}
}
status = ice_aq_send_cmd(hw, &desc, buf, len, NULL);
if (!status) {
/* Update the current configuration to reflect events enabled.
* hw->fw_log.cq_en and hw->fw_log.uart_en indicate if the FW
* logging mode is enabled for the device. They do not reflect
* actual modules being enabled to emit log messages. So, their
* values remain unchanged even when all modules are disabled.
*/
u16 cnt = enable ? chgs : (u16)ICE_AQC_FW_LOG_ID_MAX;
hw->fw_log.actv_evnts = actv_evnts;
for (i = 0; i < cnt; i++) {
u16 v, m;
if (!enable) {
/* When disabling all FW logging events as part
* of device's de-initialization, the original
* configurations are retained, and can be used
* to reconfigure FW logging later if the device
* is re-initialized.
*/
hw->fw_log.evnts[i].cur = 0;
continue;
}
v = le16_to_cpu(data->entry[i]);
m = (v & ICE_AQC_FW_LOG_ID_M) >> ICE_AQC_FW_LOG_ID_S;
hw->fw_log.evnts[m].cur = hw->fw_log.evnts[m].cfg;
}
}
out:
if (data)
devm_kfree(ice_hw_to_dev(hw), data);
return status;
}
/**
* ice_output_fw_log
* @hw: pointer to the hw struct
* @desc: pointer to the AQ message descriptor
* @buf: pointer to the buffer accompanying the AQ message
*
* Formats a FW Log message and outputs it via the standard driver logs.
*/
void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf)
{
ice_debug(hw, ICE_DBG_AQ_MSG, "[ FW Log Msg Start ]\n");
ice_debug_array(hw, ICE_DBG_AQ_MSG, 16, 1, (u8 *)buf,
le16_to_cpu(desc->datalen));
ice_debug(hw, ICE_DBG_AQ_MSG, "[ FW Log Msg End ]\n");
}
/**
* ice_init_hw - main hardware initialization routine
* @hw: pointer to the hardware structure
@ -410,6 +631,11 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_cqinit;
/* Enable FW logging. Not fatal if this fails. */
status = ice_cfg_fw_log(hw, true);
if (status)
ice_debug(hw, ICE_DBG_INIT, "Failed to enable FW logging.\n");
status = ice_clear_pf_cfg(hw);
if (status)
goto err_unroll_cqinit;
@ -472,6 +698,13 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_sched;
/* need a valid SW entry point to build a Tx tree */
if (!hw->sw_entry_point_layer) {
ice_debug(hw, ICE_DBG_SCHED, "invalid sw entry point\n");
status = ICE_ERR_CFG;
goto err_unroll_sched;
}
status = ice_init_fltr_mgmt_struct(hw);
if (status)
goto err_unroll_sched;
@ -494,7 +727,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
if (status)
goto err_unroll_fltr_mgmt_struct;
ice_init_flex_parser(hw);
ice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC);
ice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC_2);
return 0;
@ -515,15 +749,18 @@ err_unroll_cqinit:
*/
void ice_deinit_hw(struct ice_hw *hw)
{
ice_cleanup_fltr_mgmt_struct(hw);
ice_sched_cleanup_all(hw);
ice_shutdown_all_ctrlq(hw);
if (hw->port_info) {
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
hw->port_info = NULL;
}
ice_cleanup_fltr_mgmt_struct(hw);
/* Attempt to disable FW logging before shutting down control queues */
ice_cfg_fw_log(hw, false);
ice_shutdown_all_ctrlq(hw);
}
/**
@ -652,6 +889,8 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
ice_debug(hw, ICE_DBG_INIT, "GlobalR requested\n");
val = GLGEN_RTRIG_GLOBR_M;
break;
default:
return ICE_ERR_PARAM;
}
val |= rd32(hw, GLGEN_RTRIG);
@ -904,7 +1143,22 @@ enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
* @timeout: the maximum time in ms that the driver may hold the resource
* @cd: pointer to command details structure or NULL
*
* requests common resource using the admin queue commands (0x0008)
* Requests common resource using the admin queue commands (0x0008).
* When attempting to acquire the Global Config Lock, the driver can
* learn of three states:
* 1) ICE_SUCCESS - acquired lock, and can perform download package
* 2) ICE_ERR_AQ_ERROR - did not get lock, driver should fail to load
* 3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
* successfully downloaded the package; the driver does
* not have to download the package and can continue
* loading
*
* Note that if the caller is in an acquire lock, perform action, release lock
* phase of operation, it is possible that the FW may detect a timeout and issue
* a CORER. In this case, the driver will receive a CORER interrupt and will
* have to determine its cause. The calling thread that is handling this flow
* will likely get an error propagated back to it indicating the Download
* Package, Update Package or the Release Resource AQ commands timed out.
*/
static enum ice_status
ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
@ -922,13 +1176,43 @@ ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
cmd_resp->res_id = cpu_to_le16(res);
cmd_resp->access_type = cpu_to_le16(access);
cmd_resp->res_number = cpu_to_le32(sdp_number);
cmd_resp->timeout = cpu_to_le32(*timeout);
*timeout = 0;
status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
/* The completion specifies the maximum time in ms that the driver
* may hold the resource in the Timeout field.
* If the resource is held by someone else, the command completes with
* busy return value and the timeout field indicates the maximum time
* the current owner of the resource has to free it.
*/
/* Global config lock response utilizes an additional status field.
*
* If the Global config lock resource is held by some other driver, the
* command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
* and the timeout field indicates the maximum time the current owner
* of the resource has to free it.
*/
if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
*timeout = le32_to_cpu(cmd_resp->timeout);
return 0;
} else if (le16_to_cpu(cmd_resp->status) ==
ICE_AQ_RES_GLBL_IN_PROG) {
*timeout = le32_to_cpu(cmd_resp->timeout);
return ICE_ERR_AQ_ERROR;
} else if (le16_to_cpu(cmd_resp->status) ==
ICE_AQ_RES_GLBL_DONE) {
return ICE_ERR_AQ_NO_WORK;
}
/* invalid FW response, force a timeout immediately */
*timeout = 0;
return ICE_ERR_AQ_ERROR;
}
/* If the resource is held by some other driver, the command completes
* with a busy return value and the timeout field indicates the maximum
* time the current owner of the resource has to free it.
*/
if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
*timeout = le32_to_cpu(cmd_resp->timeout);
@ -967,30 +1251,28 @@ ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
* @hw: pointer to the HW structure
* @res: resource id
* @access: access type (read or write)
* @timeout: timeout in milliseconds
*
* This function will attempt to acquire the ownership of a resource.
*/
enum ice_status
ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
enum ice_aq_res_access_type access)
enum ice_aq_res_access_type access, u32 timeout)
{
#define ICE_RES_POLLING_DELAY_MS 10
u32 delay = ICE_RES_POLLING_DELAY_MS;
u32 time_left = timeout;
enum ice_status status;
u32 time_left = 0;
u32 timeout;
status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
/* An admin queue return code of ICE_AQ_RC_EEXIST means that another
* driver has previously acquired the resource and performed any
* necessary updates; in this case the caller does not obtain the
* resource and has no further work to do.
/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
* previously acquired the resource and performed any necessary updates;
* in this case the caller does not obtain the resource and has no
* further work to do.
*/
if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
status = ICE_ERR_AQ_NO_WORK;
if (status == ICE_ERR_AQ_NO_WORK)
goto ice_acquire_res_exit;
}
if (status)
ice_debug(hw, ICE_DBG_RES,
@ -1003,11 +1285,9 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
timeout = (timeout > delay) ? timeout - delay : 0;
status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);
if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
if (status == ICE_ERR_AQ_NO_WORK)
/* lock free, but no work to do */
status = ICE_ERR_AQ_NO_WORK;
break;
}
if (!status)
/* lock acquired */
@ -1306,6 +1586,110 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
ice_aq_clear_pxe_mode(hw);
}
/**
* ice_get_link_speed_based_on_phy_type - returns link speed
* @phy_type_low: lower part of phy_type
*
* This helper function will convert a phy_type_low to its corresponding link
* speed.
* Note: In the structure of phy_type_low, there should be one bit set, as
* this function will convert one phy type to its speed.
* If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
* If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned
*/
static u16
ice_get_link_speed_based_on_phy_type(u64 phy_type_low)
{
u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
switch (phy_type_low) {
case ICE_PHY_TYPE_LOW_100BASE_TX:
case ICE_PHY_TYPE_LOW_100M_SGMII:
speed_phy_type_low = ICE_AQ_LINK_SPEED_100MB;
break;
case ICE_PHY_TYPE_LOW_1000BASE_T:
case ICE_PHY_TYPE_LOW_1000BASE_SX:
case ICE_PHY_TYPE_LOW_1000BASE_LX:
case ICE_PHY_TYPE_LOW_1000BASE_KX:
case ICE_PHY_TYPE_LOW_1G_SGMII:
speed_phy_type_low = ICE_AQ_LINK_SPEED_1000MB;
break;
case ICE_PHY_TYPE_LOW_2500BASE_T:
case ICE_PHY_TYPE_LOW_2500BASE_X:
case ICE_PHY_TYPE_LOW_2500BASE_KX:
speed_phy_type_low = ICE_AQ_LINK_SPEED_2500MB;
break;
case ICE_PHY_TYPE_LOW_5GBASE_T:
case ICE_PHY_TYPE_LOW_5GBASE_KR:
speed_phy_type_low = ICE_AQ_LINK_SPEED_5GB;
break;
case ICE_PHY_TYPE_LOW_10GBASE_T:
case ICE_PHY_TYPE_LOW_10G_SFI_DA:
case ICE_PHY_TYPE_LOW_10GBASE_SR:
case ICE_PHY_TYPE_LOW_10GBASE_LR:
case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
speed_phy_type_low = ICE_AQ_LINK_SPEED_10GB;
break;
case ICE_PHY_TYPE_LOW_25GBASE_T:
case ICE_PHY_TYPE_LOW_25GBASE_CR:
case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
case ICE_PHY_TYPE_LOW_25GBASE_CR1:
case ICE_PHY_TYPE_LOW_25GBASE_SR:
case ICE_PHY_TYPE_LOW_25GBASE_LR:
case ICE_PHY_TYPE_LOW_25GBASE_KR:
case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
case ICE_PHY_TYPE_LOW_25GBASE_KR1:
case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
case ICE_PHY_TYPE_LOW_25G_AUI_C2C:
speed_phy_type_low = ICE_AQ_LINK_SPEED_25GB;
break;
case ICE_PHY_TYPE_LOW_40GBASE_CR4:
case ICE_PHY_TYPE_LOW_40GBASE_SR4:
case ICE_PHY_TYPE_LOW_40GBASE_LR4:
case ICE_PHY_TYPE_LOW_40GBASE_KR4:
case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
case ICE_PHY_TYPE_LOW_40G_XLAUI:
speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB;
break;
default:
speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN;
break;
}
return speed_phy_type_low;
}
/**
* ice_update_phy_type
* @phy_type_low: pointer to the lower part of phy_type
* @link_speeds_bitmap: targeted link speeds bitmap
*
* Note: For the link_speeds_bitmap structure, you can check it at
* [ice_aqc_get_link_status->link_speed]. Caller can pass in
* link_speeds_bitmap include multiple speeds.
*
* The value of phy_type_low will present a certain link speed. This helper
* function will turn on bits in the phy_type_low based on the value of
* link_speeds_bitmap input parameter.
*/
void ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap)
{
u16 speed = ICE_AQ_LINK_SPEED_UNKNOWN;
u64 pt_low;
int index;
/* We first check with low part of phy_type */
for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) {
pt_low = BIT_ULL(index);
speed = ice_get_link_speed_based_on_phy_type(pt_low);
if (link_speeds_bitmap & speed)
*phy_type_low |= BIT_ULL(index);
}
}
/**
* ice_aq_set_phy_cfg
* @hw: pointer to the hw struct
@ -1318,19 +1702,18 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
* 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 (0x0601).
*/
static enum ice_status
enum ice_status
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd)
{
struct ice_aqc_set_phy_cfg *cmd;
struct ice_aq_desc desc;
if (!cfg)
return ICE_ERR_PARAM;
cmd = &desc.params.set_phy;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_phy_cfg);
cmd->lport_num = lport;
desc.params.set_phy.lport_num = lport;
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
return ice_aq_send_cmd(hw, &desc, cfg, sizeof(*cfg), cd);
}
@ -1379,12 +1762,12 @@ out:
* ice_set_fc
* @pi: port information structure
* @aq_failures: pointer to status code, specific to ice_set_fc routine
* @atomic_restart: enable automatic link update
* @ena_auto_link_update: enable automatic link update
*
* Set the requested flow control mode.
*/
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool atomic_restart)
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update)
{
struct ice_aqc_set_phy_cfg_data cfg = { 0 };
struct ice_aqc_get_phy_caps_data *pcaps;
@ -1434,8 +1817,8 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool atomic_restart)
int retry_count, retry_max = 10;
/* Auto restart link so settings take effect */
if (atomic_restart)
cfg.caps |= ICE_AQ_PHY_ENA_ATOMIC_LINK;
if (ena_auto_link_update)
cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
/* Copy over all the old settings */
cfg.phy_type_low = pcaps->phy_type_low;
cfg.low_power_ctrl = pcaps->low_power_ctrl;

View File

@ -23,7 +23,7 @@ enum ice_status
ice_get_link_status(struct ice_port_info *pi, bool *link_up);
enum ice_status
ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
enum ice_aq_res_access_type access);
enum ice_aq_res_access_type access, u32 timeout);
void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status
@ -58,12 +58,24 @@ enum ice_status
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
void *buf, u16 buf_size, struct ice_sq_cd *cd);
enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd);
enum ice_status
ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
struct ice_aqc_get_phy_caps_data *caps,
struct ice_sq_cd *cd);
void
ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap);
enum ice_status
ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags,
struct ice_sq_cd *cd);
enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool atomic_restart);
ice_aq_set_phy_cfg(struct ice_hw *hw, u8 lport,
struct ice_aqc_set_phy_cfg_data *cfg, struct ice_sq_cd *cd);
enum ice_status
ice_set_fc(struct ice_port_info *pi, u8 *aq_failures,
bool ena_auto_link_update);
enum ice_status
ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link,
struct ice_sq_cd *cd);
@ -83,4 +95,5 @@ enum ice_status
ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_id, u8 tc, u8 num_qgrps,
struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
struct ice_sq_cd *cd);
void ice_output_fw_log(struct ice_hw *hw, struct ice_aq_desc *desc, void *buf);
#endif /* _ICE_COMMON_H_ */

View File

@ -806,6 +806,9 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
u16 retval = 0;
u32 val = 0;
/* if reset is in progress return a soft error */
if (hw->reset_ongoing)
return ICE_ERR_RESET_ONGOING;
mutex_lock(&cq->sq_lock);
cq->sq_last_status = ICE_AQ_RC_OK;

View File

@ -332,58 +332,473 @@ ice_get_ethtool_stats(struct net_device *netdev,
}
}
static int
ice_get_link_ksettings(struct net_device *netdev,
/**
* ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes
* @netdev: network interface device structure
* @ks: ethtool link ksettings struct to fill out
*/
static void ice_phy_type_to_ethtool(struct net_device *netdev,
struct ethtool_link_ksettings *ks)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_link_status *hw_link_info;
struct ice_vsi *vsi = np->vsi;
bool link_up;
u64 phy_types_low;
hw_link_info = &vsi->port_info->phy.link_info;
link_up = hw_link_info->link_info & ICE_AQ_LINK_UP;
phy_types_low = vsi->port_info->phy.phy_type_low;
ethtool_link_ksettings_zero_link_mode(ks, supported);
ethtool_link_ksettings_zero_link_mode(ks, advertising);
if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) {
ethtool_link_ksettings_add_link_mode(ks, supported,
100baseT_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
100baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseKX_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseKX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX ||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) {
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseX_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) {
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseT_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X ||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) {
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseX_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseX_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) {
ethtool_link_ksettings_add_link_mode(ks, supported,
5000baseT_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
5000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseT_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseKR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseKR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseSR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) {
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseLR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseLR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 ||
phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseSR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseSR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) {
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseKR_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseKR_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseKR4_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseKR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 ||
phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC ||
phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseCR4_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseCR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseSR4_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseSR4_Full);
}
if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) {
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseLR4_Full);
if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB)
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseLR4_Full);
}
/* set speed and duplex */
if (link_up) {
switch (hw_link_info->link_speed) {
case ICE_AQ_LINK_SPEED_100MB:
ks->base.speed = SPEED_100;
/* Autoneg PHY types */
if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX ||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX ||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX ||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR ||
phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S ||
phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 ||
phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 ||
phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) {
ethtool_link_ksettings_add_link_mode(ks, supported,
Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
Autoneg);
}
}
#define TEST_SET_BITS_TIMEOUT 50
#define TEST_SET_BITS_SLEEP_MAX 2000
#define TEST_SET_BITS_SLEEP_MIN 1000
/**
* ice_get_settings_link_up - Get Link settings for when link is up
* @ks: ethtool ksettings to fill in
* @netdev: network interface device structure
*/
static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks,
struct net_device *netdev)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ethtool_link_ksettings cap_ksettings;
struct ice_link_status *link_info;
struct ice_vsi *vsi = np->vsi;
bool unrecog_phy_low = false;
link_info = &vsi->port_info->phy.link_info;
/* Initialize supported and advertised settings based on phy settings */
switch (link_info->phy_type_low) {
case ICE_PHY_TYPE_LOW_100BASE_TX:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
100baseT_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
100baseT_Full);
break;
case ICE_AQ_LINK_SPEED_2500MB:
ks->base.speed = SPEED_2500;
case ICE_PHY_TYPE_LOW_100M_SGMII:
ethtool_link_ksettings_add_link_mode(ks, supported,
100baseT_Full);
break;
case ICE_AQ_LINK_SPEED_5GB:
ks->base.speed = SPEED_5000;
case ICE_PHY_TYPE_LOW_1000BASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseT_Full);
break;
case ICE_AQ_LINK_SPEED_10GB:
ks->base.speed = SPEED_10000;
case ICE_PHY_TYPE_LOW_1G_SGMII:
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseT_Full);
break;
case ICE_PHY_TYPE_LOW_1000BASE_SX:
case ICE_PHY_TYPE_LOW_1000BASE_LX:
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseX_Full);
break;
case ICE_PHY_TYPE_LOW_1000BASE_KX:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
1000baseKX_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
1000baseKX_Full);
break;
case ICE_PHY_TYPE_LOW_2500BASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseT_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseT_Full);
break;
case ICE_PHY_TYPE_LOW_2500BASE_X:
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseX_Full);
break;
case ICE_PHY_TYPE_LOW_2500BASE_KX:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
2500baseX_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
2500baseX_Full);
break;
case ICE_PHY_TYPE_LOW_5GBASE_T:
case ICE_PHY_TYPE_LOW_5GBASE_KR:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
5000baseT_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
5000baseT_Full);
break;
case ICE_PHY_TYPE_LOW_10GBASE_T:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseT_Full);
break;
case ICE_PHY_TYPE_LOW_10G_SFI_DA:
case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
case ICE_PHY_TYPE_LOW_10G_SFI_C2C:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseT_Full);
break;
case ICE_PHY_TYPE_LOW_10GBASE_SR:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full);
break;
case ICE_PHY_TYPE_LOW_10GBASE_LR:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseLR_Full);
break;
case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseKR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
10000baseKR_Full);
break;
case ICE_PHY_TYPE_LOW_25GBASE_T:
case ICE_PHY_TYPE_LOW_25GBASE_CR:
case ICE_PHY_TYPE_LOW_25GBASE_CR_S:
case ICE_PHY_TYPE_LOW_25GBASE_CR1:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseCR_Full);
break;
case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseCR_Full);
break;
case ICE_PHY_TYPE_LOW_25GBASE_SR:
case ICE_PHY_TYPE_LOW_25GBASE_LR:
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseSR_Full);
break;
case ICE_PHY_TYPE_LOW_25GBASE_KR:
case ICE_PHY_TYPE_LOW_25GBASE_KR1:
case ICE_PHY_TYPE_LOW_25GBASE_KR_S:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseKR_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
25000baseKR_Full);
break;
case ICE_PHY_TYPE_LOW_40GBASE_CR4:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseCR4_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseCR4_Full);
break;
case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC:
case ICE_PHY_TYPE_LOW_40G_XLAUI:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseCR4_Full);
break;
case ICE_PHY_TYPE_LOW_40GBASE_SR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseSR4_Full);
break;
case ICE_PHY_TYPE_LOW_40GBASE_LR4:
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseLR4_Full);
break;
case ICE_PHY_TYPE_LOW_40GBASE_KR4:
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, supported,
40000baseKR4_Full);
ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
ethtool_link_ksettings_add_link_mode(ks, advertising,
40000baseKR4_Full);
break;
default:
unrecog_phy_low = true;
}
if (unrecog_phy_low) {
/* if we got here and link is up something bad is afoot */
netdev_info(netdev, "WARNING: Unrecognized PHY_Low (0x%llx).\n",
(u64)link_info->phy_type_low);
}
/* Now that we've worked out everything that could be supported by the
* current PHY type, get what is supported by the NVM and intersect
* them to get what is truly supported
*/
memset(&cap_ksettings, 0, sizeof(struct ethtool_link_ksettings));
ice_phy_type_to_ethtool(netdev, &cap_ksettings);
ethtool_intersect_link_masks(ks, &cap_ksettings);
switch (link_info->link_speed) {
case ICE_AQ_LINK_SPEED_40GB:
ks->base.speed = SPEED_40000;
break;
case ICE_AQ_LINK_SPEED_25GB:
ks->base.speed = SPEED_25000;
break;
case ICE_AQ_LINK_SPEED_40GB:
ks->base.speed = SPEED_40000;
case ICE_AQ_LINK_SPEED_20GB:
ks->base.speed = SPEED_20000;
break;
case ICE_AQ_LINK_SPEED_10GB:
ks->base.speed = SPEED_10000;
break;
case ICE_AQ_LINK_SPEED_5GB:
ks->base.speed = SPEED_5000;
break;
case ICE_AQ_LINK_SPEED_2500MB:
ks->base.speed = SPEED_2500;
break;
case ICE_AQ_LINK_SPEED_1000MB:
ks->base.speed = SPEED_1000;
break;
case ICE_AQ_LINK_SPEED_100MB:
ks->base.speed = SPEED_100;
break;
default:
ks->base.speed = SPEED_UNKNOWN;
netdev_info(netdev,
"WARNING: Unrecognized link_speed (0x%x).\n",
link_info->link_speed);
break;
}
ks->base.duplex = DUPLEX_FULL;
} else {
}
/**
* ice_get_settings_link_down - Get the Link settings when link is down
* @ks: ethtool ksettings to fill in
* @netdev: network interface device structure
*
* Reports link settings that can be determined when link is down
*/
static void
ice_get_settings_link_down(struct ethtool_link_ksettings *ks,
struct net_device __always_unused *netdev)
{
/* link is down and the driver needs to fall back on
* supported phy types to figure out what info to display
*/
ice_phy_type_to_ethtool(netdev, ks);
/* With no link, speed and duplex are unknown */
ks->base.speed = SPEED_UNKNOWN;
ks->base.duplex = DUPLEX_UNKNOWN;
}
}
/**
* ice_get_link_ksettings - Get Link Speed and Duplex settings
* @netdev: network interface device structure
* @ks: ethtool ksettings
*
* Reports speed/duplex settings based on media_type
*/
static int ice_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *ks)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_link_status *hw_link_info;
struct ice_vsi *vsi = np->vsi;
ethtool_link_ksettings_zero_link_mode(ks, supported);
ethtool_link_ksettings_zero_link_mode(ks, advertising);
hw_link_info = &vsi->port_info->phy.link_info;
/* set speed and duplex */
if (hw_link_info->link_info & ICE_AQ_LINK_UP)
ice_get_settings_link_up(ks, netdev);
else
ice_get_settings_link_down(ks, netdev);
/* set autoneg settings */
ks->base.autoneg = ((hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ?
AUTONEG_ENABLE : AUTONEG_DISABLE);
ks->base.autoneg = (hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ?
AUTONEG_ENABLE : AUTONEG_DISABLE;
/* set media type settings */
switch (vsi->port_info->phy.media_type) {
@ -441,6 +856,311 @@ ice_get_link_ksettings(struct net_device *netdev,
return 0;
}
/**
* ice_ksettings_find_adv_link_speed - Find advertising link speed
* @ks: ethtool ksettings
*/
static u16
ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks)
{
u16 adv_link_speed = 0;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
100baseT_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_100MB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
1000baseX_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
1000baseT_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
1000baseKX_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
2500baseT_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
2500baseX_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
5000baseT_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_5GB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
10000baseT_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
10000baseKR_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_10GB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
10000baseSR_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
10000baseLR_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_10GB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
25000baseCR_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
25000baseSR_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
25000baseKR_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_25GB;
if (ethtool_link_ksettings_test_link_mode(ks, advertising,
40000baseCR4_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
40000baseSR4_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
40000baseLR4_Full) ||
ethtool_link_ksettings_test_link_mode(ks, advertising,
40000baseKR4_Full))
adv_link_speed |= ICE_AQ_LINK_SPEED_40GB;
return adv_link_speed;
}
/**
* ice_setup_autoneg
* @p: port info
* @ks: ethtool_link_ksettings
* @config: configuration that will be sent down to FW
* @autoneg_enabled: autonegotiation is enabled or not
* @autoneg_changed: will there a change in autonegotiation
* @netdev: network interface device structure
*
* Setup PHY autonegotiation feature
*/
static int
ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks,
struct ice_aqc_set_phy_cfg_data *config,
u8 autoneg_enabled, u8 *autoneg_changed,
struct net_device *netdev)
{
int err = 0;
*autoneg_changed = 0;
/* Check autoneg */
if (autoneg_enabled == AUTONEG_ENABLE) {
/* If autoneg was not already enabled */
if (!(p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)) {
/* If autoneg is not supported, return error */
if (!ethtool_link_ksettings_test_link_mode(ks,
supported,
Autoneg)) {
netdev_info(netdev, "Autoneg not supported on this phy.\n");
err = -EINVAL;
} else {
/* Autoneg is allowed to change */
config->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
*autoneg_changed = 1;
}
}
} else {
/* If autoneg is currently enabled */
if (p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) {
/* If autoneg is supported 10GBASE_T is the only phy
* that can disable it, so otherwise return error
*/
if (ethtool_link_ksettings_test_link_mode(ks,
supported,
Autoneg)) {
netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
err = -EINVAL;
} else {
/* Autoneg is allowed to change */
config->caps &= ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
*autoneg_changed = 1;
}
}
}
return err;
}
/**
* ice_set_link_ksettings - Set Speed and Duplex
* @netdev: network interface device structure
* @ks: ethtool ksettings
*
* Set speed/duplex per media_types advertised/forced
*/
static int ice_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *ks)
{
u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0;
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ethtool_link_ksettings safe_ks, copy_ks;
struct ice_aqc_get_phy_caps_data *abilities;
u16 adv_link_speed, curr_link_speed, idx;
struct ice_aqc_set_phy_cfg_data config;
struct ice_pf *pf = np->vsi->back;
struct ice_port_info *p;
u8 autoneg_changed = 0;
enum ice_status status;
u64 phy_type_low;
int err = 0;
bool linkup;
p = np->vsi->port_info;
if (!p)
return -EOPNOTSUPP;
/* Check if this is lan vsi */
for (idx = 0 ; idx < pf->num_alloc_vsi ; idx++) {
if (pf->vsi[idx]->type == ICE_VSI_PF) {
if (np->vsi != pf->vsi[idx])
return -EOPNOTSUPP;
break;
}
}
if (p->phy.media_type != ICE_MEDIA_BASET &&
p->phy.media_type != ICE_MEDIA_FIBER &&
p->phy.media_type != ICE_MEDIA_BACKPLANE &&
p->phy.media_type != ICE_MEDIA_DA &&
p->phy.link_info.link_info & ICE_AQ_LINK_UP)
return -EOPNOTSUPP;
/* copy the ksettings to copy_ks to avoid modifying the original */
memcpy(&copy_ks, ks, sizeof(struct ethtool_link_ksettings));
/* save autoneg out of ksettings */
autoneg = copy_ks.base.autoneg;
memset(&safe_ks, 0, sizeof(safe_ks));
/* Get link modes supported by hardware.*/
ice_phy_type_to_ethtool(netdev, &safe_ks);
/* and check against modes requested by user.
* Return an error if unsupported mode was set.
*/
if (!bitmap_subset(copy_ks.link_modes.advertising,
safe_ks.link_modes.supported,
__ETHTOOL_LINK_MODE_MASK_NBITS))
return -EINVAL;
/* get our own copy of the bits to check against */
memset(&safe_ks, 0, sizeof(struct ethtool_link_ksettings));
safe_ks.base.cmd = copy_ks.base.cmd;
safe_ks.base.link_mode_masks_nwords =
copy_ks.base.link_mode_masks_nwords;
ice_get_link_ksettings(netdev, &safe_ks);
/* set autoneg back to what it currently is */
copy_ks.base.autoneg = safe_ks.base.autoneg;
/* we don't compare the speed */
copy_ks.base.speed = safe_ks.base.speed;
/* If copy_ks.base and safe_ks.base are not the same now, then they are
* trying to set something that we do not support.
*/
if (memcmp(&copy_ks.base, &safe_ks.base,
sizeof(struct ethtool_link_settings)))
return -EOPNOTSUPP;
while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) {
timeout--;
if (!timeout)
return -EBUSY;
usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX);
}
abilities = devm_kzalloc(&pf->pdev->dev, sizeof(*abilities),
GFP_KERNEL);
if (!abilities)
return -ENOMEM;
/* Get the current phy config */
status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities,
NULL);
if (status) {
err = -EAGAIN;
goto done;
}
/* Copy abilities to config in case autoneg is not set below */
memset(&config, 0, sizeof(struct ice_aqc_set_phy_cfg_data));
config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE;
if (abilities->caps & ICE_AQC_PHY_AN_MODE)
config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
/* Check autoneg */
err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed,
netdev);
if (err)
goto done;
/* Call to get the current link speed */
p->phy.get_link_info = true;
status = ice_get_link_status(p, &linkup);
if (status) {
err = -EAGAIN;
goto done;
}
curr_link_speed = p->phy.link_info.link_speed;
adv_link_speed = ice_ksettings_find_adv_link_speed(ks);
/* If speed didn't get set, set it to what it currently is.
* This is needed because if advertise is 0 (as it is when autoneg
* is disabled) then speed won't get set.
*/
if (!adv_link_speed)
adv_link_speed = curr_link_speed;
/* Convert the advertise link speeds to their corresponded PHY_TYPE */
ice_update_phy_type(&phy_type_low, adv_link_speed);
if (!autoneg_changed && adv_link_speed == curr_link_speed) {
netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
goto done;
}
/* copy over the rest of the abilities */
config.low_power_ctrl = abilities->low_power_ctrl;
config.eee_cap = abilities->eee_cap;
config.eeer_value = abilities->eeer_value;
config.link_fec_opt = abilities->link_fec_options;
/* save the requested speeds */
p->phy.link_info.req_speeds = adv_link_speed;
/* set link and auto negotiation so changes take effect */
config.caps |= ICE_AQ_PHY_ENA_LINK;
if (phy_type_low) {
config.phy_type_low = cpu_to_le64(phy_type_low) &
abilities->phy_type_low;
} else {
err = -EAGAIN;
netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n");
goto done;
}
/* If link is up put link down */
if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) {
/* Tell the OS link is going down, the link will go
* back up when fw says it is ready asynchronously
*/
ice_print_link_msg(np->vsi, false);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
}
/* make the aq call */
status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL);
if (status) {
netdev_info(netdev, "Set phy config failed,\n");
err = -EAGAIN;
}
done:
devm_kfree(&pf->pdev->dev, abilities);
clear_bit(__ICE_CFG_BUSY, pf->state);
return err;
}
/**
* ice_get_rxnfc - command to get RX flow classification rules
* @netdev: network interface device structure
@ -933,6 +1653,7 @@ static int ice_set_rxfh(struct net_device *netdev, const u32 *indir,
static const struct ethtool_ops ice_ethtool_ops = {
.get_link_ksettings = ice_get_link_ksettings,
.set_link_ksettings = ice_set_link_ksettings,
.get_drvinfo = ice_get_drvinfo,
.get_regs_len = ice_get_regs_len,
.get_regs = ice_get_regs,

View File

@ -10,171 +10,169 @@
#define PF_FW_ARQBAH 0x00080180
#define PF_FW_ARQBAL 0x00080080
#define PF_FW_ARQH 0x00080380
#define PF_FW_ARQH_ARQH_S 0
#define PF_FW_ARQH_ARQH_M ICE_M(0x3FF, PF_FW_ARQH_ARQH_S)
#define PF_FW_ARQH_ARQH_M ICE_M(0x3FF, 0)
#define PF_FW_ARQLEN 0x00080280
#define PF_FW_ARQLEN_ARQLEN_S 0
#define PF_FW_ARQLEN_ARQLEN_M ICE_M(0x3FF, PF_FW_ARQLEN_ARQLEN_S)
#define PF_FW_ARQLEN_ARQVFE_S 28
#define PF_FW_ARQLEN_ARQVFE_M BIT(PF_FW_ARQLEN_ARQVFE_S)
#define PF_FW_ARQLEN_ARQOVFL_S 29
#define PF_FW_ARQLEN_ARQOVFL_M BIT(PF_FW_ARQLEN_ARQOVFL_S)
#define PF_FW_ARQLEN_ARQCRIT_S 30
#define PF_FW_ARQLEN_ARQCRIT_M BIT(PF_FW_ARQLEN_ARQCRIT_S)
#define PF_FW_ARQLEN_ARQENABLE_S 31
#define PF_FW_ARQLEN_ARQENABLE_M BIT(PF_FW_ARQLEN_ARQENABLE_S)
#define PF_FW_ARQLEN_ARQLEN_M ICE_M(0x3FF, 0)
#define PF_FW_ARQLEN_ARQVFE_M BIT(28)
#define PF_FW_ARQLEN_ARQOVFL_M BIT(29)
#define PF_FW_ARQLEN_ARQCRIT_M BIT(30)
#define PF_FW_ARQLEN_ARQENABLE_M BIT(31)
#define PF_FW_ARQT 0x00080480
#define PF_FW_ATQBAH 0x00080100
#define PF_FW_ATQBAL 0x00080000
#define PF_FW_ATQH 0x00080300
#define PF_FW_ATQH_ATQH_S 0
#define PF_FW_ATQH_ATQH_M ICE_M(0x3FF, PF_FW_ATQH_ATQH_S)
#define PF_FW_ATQH_ATQH_M ICE_M(0x3FF, 0)
#define PF_FW_ATQLEN 0x00080200
#define PF_FW_ATQLEN_ATQLEN_S 0
#define PF_FW_ATQLEN_ATQLEN_M ICE_M(0x3FF, PF_FW_ATQLEN_ATQLEN_S)
#define PF_FW_ATQLEN_ATQVFE_S 28
#define PF_FW_ATQLEN_ATQVFE_M BIT(PF_FW_ATQLEN_ATQVFE_S)
#define PF_FW_ATQLEN_ATQOVFL_S 29
#define PF_FW_ATQLEN_ATQOVFL_M BIT(PF_FW_ATQLEN_ATQOVFL_S)
#define PF_FW_ATQLEN_ATQCRIT_S 30
#define PF_FW_ATQLEN_ATQCRIT_M BIT(PF_FW_ATQLEN_ATQCRIT_S)
#define PF_FW_ATQLEN_ATQENABLE_S 31
#define PF_FW_ATQLEN_ATQENABLE_M BIT(PF_FW_ATQLEN_ATQENABLE_S)
#define PF_FW_ATQLEN_ATQLEN_M ICE_M(0x3FF, 0)
#define PF_FW_ATQLEN_ATQVFE_M BIT(28)
#define PF_FW_ATQLEN_ATQOVFL_M BIT(29)
#define PF_FW_ATQLEN_ATQCRIT_M BIT(30)
#define PF_FW_ATQLEN_ATQENABLE_M BIT(31)
#define PF_FW_ATQT 0x00080400
#define GLFLXP_RXDID_FLAGS(_i, _j) (0x0045D000 + ((_i) * 4 + (_j) * 256))
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S 0
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M ICE_M(0x3F, 0)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S 8
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_M ICE_M(0x3F, 8)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_S 16
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_S)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_M ICE_M(0x3F, 16)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_S 24
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_S)
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_M ICE_M(0x3F, 24)
#define GLFLXP_RXDID_FLX_WRD_0(_i) (0x0045c800 + ((_i) * 4))
#define GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_S 0
#define GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_S)
#define GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_M ICE_M(0xFF, 0)
#define GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_S 30
#define GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_S)
#define GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_M ICE_M(0x3, 30)
#define GLFLXP_RXDID_FLX_WRD_1(_i) (0x0045c900 + ((_i) * 4))
#define GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_S 0
#define GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_S)
#define GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_M ICE_M(0xFF, 0)
#define GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_S 30
#define GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_S)
#define GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_M ICE_M(0x3, 30)
#define GLFLXP_RXDID_FLX_WRD_2(_i) (0x0045ca00 + ((_i) * 4))
#define GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_S 0
#define GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_S)
#define GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_M ICE_M(0xFF, 0)
#define GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_S 30
#define GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_S)
#define GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_M ICE_M(0x3, 30)
#define GLFLXP_RXDID_FLX_WRD_3(_i) (0x0045cb00 + ((_i) * 4))
#define GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_S 0
#define GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_S)
#define GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_M ICE_M(0xFF, 0)
#define GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_S 30
#define GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_S)
#define GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_M ICE_M(0x3, 30)
#define QRXFLXP_CNTXT(_QRX) (0x00480000 + ((_QRX) * 4))
#define QRXFLXP_CNTXT_RXDID_IDX_S 0
#define QRXFLXP_CNTXT_RXDID_IDX_M ICE_M(0x3F, QRXFLXP_CNTXT_RXDID_IDX_S)
#define QRXFLXP_CNTXT_RXDID_IDX_M ICE_M(0x3F, 0)
#define QRXFLXP_CNTXT_RXDID_PRIO_S 8
#define QRXFLXP_CNTXT_RXDID_PRIO_M ICE_M(0x7, QRXFLXP_CNTXT_RXDID_PRIO_S)
#define QRXFLXP_CNTXT_TS_S 11
#define QRXFLXP_CNTXT_TS_M BIT(QRXFLXP_CNTXT_TS_S)
#define QRXFLXP_CNTXT_RXDID_PRIO_M ICE_M(0x7, 8)
#define GLGEN_RSTAT 0x000B8188
#define GLGEN_RSTAT_DEVSTATE_S 0
#define GLGEN_RSTAT_DEVSTATE_M ICE_M(0x3, GLGEN_RSTAT_DEVSTATE_S)
#define GLGEN_RSTAT_DEVSTATE_M ICE_M(0x3, 0)
#define GLGEN_RSTCTL 0x000B8180
#define GLGEN_RSTCTL_GRSTDEL_S 0
#define GLGEN_RSTCTL_GRSTDEL_M ICE_M(0x3F, GLGEN_RSTCTL_GRSTDEL_S)
#define GLGEN_RSTAT_RESET_TYPE_S 2
#define GLGEN_RSTAT_RESET_TYPE_M ICE_M(0x3, GLGEN_RSTAT_RESET_TYPE_S)
#define GLGEN_RSTAT_RESET_TYPE_M ICE_M(0x3, 2)
#define GLGEN_RTRIG 0x000B8190
#define GLGEN_RTRIG_CORER_S 0
#define GLGEN_RTRIG_CORER_M BIT(GLGEN_RTRIG_CORER_S)
#define GLGEN_RTRIG_GLOBR_S 1
#define GLGEN_RTRIG_GLOBR_M BIT(GLGEN_RTRIG_GLOBR_S)
#define GLGEN_RTRIG_CORER_M BIT(0)
#define GLGEN_RTRIG_GLOBR_M BIT(1)
#define GLGEN_STAT 0x000B612C
#define PFGEN_CTRL 0x00091000
#define PFGEN_CTRL_PFSWR_S 0
#define PFGEN_CTRL_PFSWR_M BIT(PFGEN_CTRL_PFSWR_S)
#define PFGEN_CTRL_PFSWR_M BIT(0)
#define PFGEN_STATE 0x00088000
#define PRTGEN_STATUS 0x000B8100
#define PFHMC_ERRORDATA 0x00520500
#define PFHMC_ERRORINFO 0x00520400
#define GLINT_DYN_CTL(_INT) (0x00160000 + ((_INT) * 4))
#define GLINT_DYN_CTL_INTENA_S 0
#define GLINT_DYN_CTL_INTENA_M BIT(GLINT_DYN_CTL_INTENA_S)
#define GLINT_DYN_CTL_CLEARPBA_S 1
#define GLINT_DYN_CTL_CLEARPBA_M BIT(GLINT_DYN_CTL_CLEARPBA_S)
#define GLINT_DYN_CTL_SWINT_TRIG_S 2
#define GLINT_DYN_CTL_SWINT_TRIG_M BIT(GLINT_DYN_CTL_SWINT_TRIG_S)
#define GLINT_DYN_CTL_INTENA_M BIT(0)
#define GLINT_DYN_CTL_CLEARPBA_M BIT(1)
#define GLINT_DYN_CTL_SWINT_TRIG_M BIT(2)
#define GLINT_DYN_CTL_ITR_INDX_S 3
#define GLINT_DYN_CTL_SW_ITR_INDX_S 25
#define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, GLINT_DYN_CTL_SW_ITR_INDX_S)
#define GLINT_DYN_CTL_INTENA_MSK_S 31
#define GLINT_DYN_CTL_INTENA_MSK_M BIT(GLINT_DYN_CTL_INTENA_MSK_S)
#define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25)
#define GLINT_DYN_CTL_INTENA_MSK_M BIT(31)
#define GLINT_ITR(_i, _INT) (0x00154000 + ((_i) * 8192 + (_INT) * 4))
#define PFINT_FW_CTL 0x0016C800
#define PFINT_FW_CTL_MSIX_INDX_S 0
#define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, PFINT_FW_CTL_MSIX_INDX_S)
#define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0)
#define PFINT_FW_CTL_ITR_INDX_S 11
#define PFINT_FW_CTL_ITR_INDX_M ICE_M(0x3, PFINT_FW_CTL_ITR_INDX_S)
#define PFINT_FW_CTL_CAUSE_ENA_S 30
#define PFINT_FW_CTL_CAUSE_ENA_M BIT(PFINT_FW_CTL_CAUSE_ENA_S)
#define PFINT_FW_CTL_ITR_INDX_M ICE_M(0x3, 11)
#define PFINT_FW_CTL_CAUSE_ENA_M BIT(30)
#define PFINT_OICR 0x0016CA00
#define PFINT_OICR_ECC_ERR_S 16
#define PFINT_OICR_ECC_ERR_M BIT(PFINT_OICR_ECC_ERR_S)
#define PFINT_OICR_MAL_DETECT_S 19
#define PFINT_OICR_MAL_DETECT_M BIT(PFINT_OICR_MAL_DETECT_S)
#define PFINT_OICR_GRST_S 20
#define PFINT_OICR_GRST_M BIT(PFINT_OICR_GRST_S)
#define PFINT_OICR_PCI_EXCEPTION_S 21
#define PFINT_OICR_PCI_EXCEPTION_M BIT(PFINT_OICR_PCI_EXCEPTION_S)
#define PFINT_OICR_HMC_ERR_S 26
#define PFINT_OICR_HMC_ERR_M BIT(PFINT_OICR_HMC_ERR_S)
#define PFINT_OICR_PE_CRITERR_S 28
#define PFINT_OICR_PE_CRITERR_M BIT(PFINT_OICR_PE_CRITERR_S)
#define PFINT_OICR_ECC_ERR_M BIT(16)
#define PFINT_OICR_MAL_DETECT_M BIT(19)
#define PFINT_OICR_GRST_M BIT(20)
#define PFINT_OICR_PCI_EXCEPTION_M BIT(21)
#define PFINT_OICR_HMC_ERR_M BIT(26)
#define PFINT_OICR_PE_CRITERR_M BIT(28)
#define PFINT_OICR_CTL 0x0016CA80
#define PFINT_OICR_CTL_MSIX_INDX_S 0
#define PFINT_OICR_CTL_MSIX_INDX_M ICE_M(0x7FF, PFINT_OICR_CTL_MSIX_INDX_S)
#define PFINT_OICR_CTL_MSIX_INDX_M ICE_M(0x7FF, 0)
#define PFINT_OICR_CTL_ITR_INDX_S 11
#define PFINT_OICR_CTL_ITR_INDX_M ICE_M(0x3, PFINT_OICR_CTL_ITR_INDX_S)
#define PFINT_OICR_CTL_CAUSE_ENA_S 30
#define PFINT_OICR_CTL_CAUSE_ENA_M BIT(PFINT_OICR_CTL_CAUSE_ENA_S)
#define PFINT_OICR_CTL_ITR_INDX_M ICE_M(0x3, 11)
#define PFINT_OICR_CTL_CAUSE_ENA_M BIT(30)
#define PFINT_OICR_ENA 0x0016C900
#define QINT_RQCTL(_QRX) (0x00150000 + ((_QRX) * 4))
#define QINT_RQCTL_MSIX_INDX_S 0
#define QINT_RQCTL_ITR_INDX_S 11
#define QINT_RQCTL_CAUSE_ENA_S 30
#define QINT_RQCTL_CAUSE_ENA_M BIT(QINT_RQCTL_CAUSE_ENA_S)
#define QINT_RQCTL_CAUSE_ENA_M BIT(30)
#define QINT_TQCTL(_DBQM) (0x00140000 + ((_DBQM) * 4))
#define QINT_TQCTL_MSIX_INDX_S 0
#define QINT_TQCTL_ITR_INDX_S 11
#define QINT_TQCTL_CAUSE_ENA_S 30
#define QINT_TQCTL_CAUSE_ENA_M BIT(QINT_TQCTL_CAUSE_ENA_S)
#define GLLAN_RCTL_0 0x002941F8
#define QINT_TQCTL_CAUSE_ENA_M BIT(30)
#define QRX_CONTEXT(_i, _QRX) (0x00280000 + ((_i) * 8192 + (_QRX) * 4))
#define QRX_CTRL(_QRX) (0x00120000 + ((_QRX) * 4))
#define QRX_CTRL_MAX_INDEX 2047
#define QRX_CTRL_QENA_REQ_S 0
#define QRX_CTRL_QENA_REQ_M BIT(QRX_CTRL_QENA_REQ_S)
#define QRX_CTRL_QENA_REQ_M BIT(0)
#define QRX_CTRL_QENA_STAT_S 2
#define QRX_CTRL_QENA_STAT_M BIT(QRX_CTRL_QENA_STAT_S)
#define QRX_CTRL_QENA_STAT_M BIT(2)
#define QRX_ITR(_QRX) (0x00292000 + ((_QRX) * 4))
#define QRX_TAIL(_QRX) (0x00290000 + ((_QRX) * 4))
#define QRX_TAIL_MAX_INDEX 2047
#define QRX_TAIL_TAIL_S 0
#define QRX_TAIL_TAIL_M ICE_M(0x1FFF, 0)
#define GL_MDET_RX 0x00294C00
#define GL_MDET_RX_QNUM_S 0
#define GL_MDET_RX_QNUM_M ICE_M(0x7FFF, 0)
#define GL_MDET_RX_VF_NUM_S 15
#define GL_MDET_RX_VF_NUM_M ICE_M(0xFF, 15)
#define GL_MDET_RX_PF_NUM_S 23
#define GL_MDET_RX_PF_NUM_M ICE_M(0x7, 23)
#define GL_MDET_RX_MAL_TYPE_S 26
#define GL_MDET_RX_MAL_TYPE_M ICE_M(0x1F, 26)
#define GL_MDET_RX_VALID_M BIT(31)
#define GL_MDET_TX_PQM 0x002D2E00
#define GL_MDET_TX_PQM_PF_NUM_S 0
#define GL_MDET_TX_PQM_PF_NUM_M ICE_M(0x7, 0)
#define GL_MDET_TX_PQM_VF_NUM_S 4
#define GL_MDET_TX_PQM_VF_NUM_M ICE_M(0xFF, 4)
#define GL_MDET_TX_PQM_QNUM_S 12
#define GL_MDET_TX_PQM_QNUM_M ICE_M(0x3FFF, 12)
#define GL_MDET_TX_PQM_MAL_TYPE_S 26
#define GL_MDET_TX_PQM_MAL_TYPE_M ICE_M(0x1F, 26)
#define GL_MDET_TX_PQM_VALID_M BIT(31)
#define GL_MDET_TX_TCLAN 0x000FC068
#define GL_MDET_TX_TCLAN_QNUM_S 0
#define GL_MDET_TX_TCLAN_QNUM_M ICE_M(0x7FFF, 0)
#define GL_MDET_TX_TCLAN_VF_NUM_S 15
#define GL_MDET_TX_TCLAN_VF_NUM_M ICE_M(0xFF, 15)
#define GL_MDET_TX_TCLAN_PF_NUM_S 23
#define GL_MDET_TX_TCLAN_PF_NUM_M ICE_M(0x7, 23)
#define GL_MDET_TX_TCLAN_MAL_TYPE_S 26
#define GL_MDET_TX_TCLAN_MAL_TYPE_M ICE_M(0x1F, 26)
#define GL_MDET_TX_TCLAN_VALID_M BIT(31)
#define PF_MDET_RX 0x00294280
#define PF_MDET_RX_VALID_M BIT(0)
#define PF_MDET_TX_PQM 0x002D2C80
#define PF_MDET_TX_PQM_VALID_M BIT(0)
#define PF_MDET_TX_TCLAN 0x000FC000
#define PF_MDET_TX_TCLAN_VALID_M BIT(0)
#define GLNVM_FLA 0x000B6108
#define GLNVM_FLA_LOCKED_S 6
#define GLNVM_FLA_LOCKED_M BIT(GLNVM_FLA_LOCKED_S)
#define GLNVM_FLA_LOCKED_M BIT(6)
#define GLNVM_GENS 0x000B6100
#define GLNVM_GENS_SR_SIZE_S 5
#define GLNVM_GENS_SR_SIZE_M ICE_M(0x7, GLNVM_GENS_SR_SIZE_S)
#define GLNVM_GENS_SR_SIZE_M ICE_M(0x7, 5)
#define GLNVM_ULD 0x000B6008
#define GLNVM_ULD_CORER_DONE_S 3
#define GLNVM_ULD_CORER_DONE_M BIT(GLNVM_ULD_CORER_DONE_S)
#define GLNVM_ULD_GLOBR_DONE_S 4
#define GLNVM_ULD_GLOBR_DONE_M BIT(GLNVM_ULD_GLOBR_DONE_S)
#define GLNVM_ULD_CORER_DONE_M BIT(3)
#define GLNVM_ULD_GLOBR_DONE_M BIT(4)
#define PF_FUNC_RID 0x0009E880
#define PF_FUNC_RID_FUNC_NUM_S 0
#define PF_FUNC_RID_FUNC_NUM_M ICE_M(0x7, PF_FUNC_RID_FUNC_NUM_S)
#define PF_FUNC_RID_FUNC_NUM_M ICE_M(0x7, 0)
#define GLPRT_BPRCH(_i) (0x00381384 + ((_i) * 8))
#define GLPRT_BPRCL(_i) (0x00381380 + ((_i) * 8))
#define GLPRT_BPTCH(_i) (0x00381244 + ((_i) * 8))

View File

@ -188,23 +188,25 @@ struct ice_32b_rx_flex_desc_nic {
* with a specific metadata (profile 7 reserved for HW)
*/
enum ice_rxdid {
ICE_RXDID_START = 0,
ICE_RXDID_LEGACY_0 = ICE_RXDID_START,
ICE_RXDID_LEGACY_1,
ICE_RXDID_FLX_START,
ICE_RXDID_FLEX_NIC = ICE_RXDID_FLX_START,
ICE_RXDID_FLX_LAST = 63,
ICE_RXDID_LAST = ICE_RXDID_FLX_LAST
ICE_RXDID_LEGACY_0 = 0,
ICE_RXDID_LEGACY_1 = 1,
ICE_RXDID_FLEX_NIC = 2,
ICE_RXDID_FLEX_NIC_2 = 6,
ICE_RXDID_HW = 7,
ICE_RXDID_LAST = 63,
};
/* Receive Flex Descriptor Rx opcode values */
#define ICE_RX_OPC_MDID 0x01
/* Receive Descriptor MDID values */
#define ICE_RX_MDID_FLOW_ID_LOWER 5
#define ICE_RX_MDID_FLOW_ID_HIGH 6
#define ICE_RX_MDID_HASH_LOW 56
#define ICE_RX_MDID_HASH_HIGH 57
enum ice_flex_rx_mdid {
ICE_RX_MDID_FLOW_ID_LOWER = 5,
ICE_RX_MDID_FLOW_ID_HIGH,
ICE_RX_MDID_SRC_VSI = 19,
ICE_RX_MDID_HASH_LOW = 56,
ICE_RX_MDID_HASH_HIGH,
};
/* Rx Flag64 packet flag bits */
enum ice_rx_flg64_bits {

File diff suppressed because it is too large Load Diff

View File

@ -137,7 +137,7 @@ ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access)
if (hw->nvm.blank_nvm_mode)
return 0;
return ice_acquire_res(hw, ICE_NVM_RES_ID, access);
return ice_acquire_res(hw, ICE_NVM_RES_ID, access, ICE_NVM_TIMEOUT);
}
/**

View File

@ -17,7 +17,6 @@ ice_sched_add_root_node(struct ice_port_info *pi,
{
struct ice_sched_node *root;
struct ice_hw *hw;
u16 max_children;
if (!pi)
return ICE_ERR_PARAM;
@ -28,8 +27,8 @@ ice_sched_add_root_node(struct ice_port_info *pi,
if (!root)
return ICE_ERR_NO_MEMORY;
max_children = le16_to_cpu(hw->layer_info[0].max_children);
root->children = devm_kcalloc(ice_hw_to_dev(hw), max_children,
/* coverity[suspicious_sizeof] */
root->children = devm_kcalloc(ice_hw_to_dev(hw), hw->max_children[0],
sizeof(*root), GFP_KERNEL);
if (!root->children) {
devm_kfree(ice_hw_to_dev(hw), root);
@ -100,7 +99,6 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer,
struct ice_sched_node *parent;
struct ice_sched_node *node;
struct ice_hw *hw;
u16 max_children;
if (!pi)
return ICE_ERR_PARAM;
@ -120,9 +118,10 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer,
node = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*node), GFP_KERNEL);
if (!node)
return ICE_ERR_NO_MEMORY;
max_children = le16_to_cpu(hw->layer_info[layer].max_children);
if (max_children) {
node->children = devm_kcalloc(ice_hw_to_dev(hw), max_children,
if (hw->max_children[layer]) {
/* coverity[suspicious_sizeof] */
node->children = devm_kcalloc(ice_hw_to_dev(hw),
hw->max_children[layer],
sizeof(*node), GFP_KERNEL);
if (!node->children) {
devm_kfree(ice_hw_to_dev(hw), node);
@ -192,14 +191,17 @@ ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
buf = devm_kzalloc(ice_hw_to_dev(hw), buf_size, GFP_KERNEL);
if (!buf)
return ICE_ERR_NO_MEMORY;
buf->hdr.parent_teid = parent->info.node_teid;
buf->hdr.num_elems = cpu_to_le16(num_nodes);
for (i = 0; i < num_nodes; i++)
buf->teid[i] = cpu_to_le32(node_teids[i]);
status = ice_aq_delete_sched_elems(hw, 1, buf, buf_size,
&num_groups_removed, NULL);
if (status || num_groups_removed != 1)
ice_debug(hw, ICE_DBG_SCHED, "remove elements failed\n");
devm_kfree(ice_hw_to_dev(hw), buf);
return status;
}
@ -592,12 +594,15 @@ static void ice_sched_clear_port(struct ice_port_info *pi)
*/
void ice_sched_cleanup_all(struct ice_hw *hw)
{
if (!hw || !hw->port_info)
if (!hw)
return;
if (hw->layer_info)
if (hw->layer_info) {
devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
hw->layer_info = NULL;
}
if (hw->port_info)
ice_sched_clear_port(hw->port_info);
hw->num_tx_sched_layers = 0;
@ -671,9 +676,13 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
ICE_AQC_ELEM_VALID_EIR;
buf->generic[i].data.generic = 0;
buf->generic[i].data.cir_bw.bw_profile_idx =
ICE_SCHED_DFLT_RL_PROF_ID;
cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
buf->generic[i].data.cir_bw.bw_alloc =
cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
buf->generic[i].data.eir_bw.bw_profile_idx =
ICE_SCHED_DFLT_RL_PROF_ID;
cpu_to_le16(ICE_SCHED_DFLT_RL_PROF_ID);
buf->generic[i].data.eir_bw.bw_alloc =
cpu_to_le16(ICE_SCHED_DFLT_BW_WT);
}
status = ice_aq_add_sched_elems(hw, 1, buf, buf_size,
@ -697,7 +706,6 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
teid = le32_to_cpu(buf->generic[i].node_teid);
new_node = ice_sched_find_node_by_teid(parent, teid);
if (!new_node) {
ice_debug(hw, ICE_DBG_SCHED,
"Node is missing for teid =%d\n", teid);
@ -710,7 +718,6 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
/* add it to previous node sibling pointer */
/* Note: siblings are not linked across branches */
prev = ice_sched_get_first_node(hw, tc_node, layer);
if (prev && prev != new_node) {
while (prev->sibling)
prev = prev->sibling;
@ -760,8 +767,7 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
return ICE_ERR_PARAM;
/* max children per node per layer */
max_child_nodes =
le16_to_cpu(hw->layer_info[parent->tx_sched_layer].max_children);
max_child_nodes = hw->max_children[parent->tx_sched_layer];
/* current number of children + required nodes exceed max children ? */
if ((parent->num_children + num_nodes) > max_child_nodes) {
@ -850,78 +856,6 @@ static u8 ice_sched_get_vsi_layer(struct ice_hw *hw)
return hw->sw_entry_point_layer;
}
/**
* ice_sched_get_num_nodes_per_layer - Get the total number of nodes per layer
* @pi: pointer to the port info struct
* @layer: layer number
*
* This function calculates the number of nodes present in the scheduler tree
* including all the branches for a given layer
*/
static u16
ice_sched_get_num_nodes_per_layer(struct ice_port_info *pi, u8 layer)
{
struct ice_hw *hw;
u16 num_nodes = 0;
u8 i;
if (!pi)
return num_nodes;
hw = pi->hw;
/* Calculate the number of nodes for all TCs */
for (i = 0; i < pi->root->num_children; i++) {
struct ice_sched_node *tc_node, *node;
tc_node = pi->root->children[i];
/* Get the first node */
node = ice_sched_get_first_node(hw, tc_node, layer);
if (!node)
continue;
/* count the siblings */
while (node) {
num_nodes++;
node = node->sibling;
}
}
return num_nodes;
}
/**
* ice_sched_val_max_nodes - check max number of nodes reached or not
* @pi: port information structure
* @new_num_nodes_per_layer: pointer to the new number of nodes array
*
* This function checks whether the scheduler tree layers have enough space to
* add new nodes
*/
static enum ice_status
ice_sched_validate_for_max_nodes(struct ice_port_info *pi,
u16 *new_num_nodes_per_layer)
{
struct ice_hw *hw = pi->hw;
u8 i, qg_layer;
u16 num_nodes;
qg_layer = ice_sched_get_qgrp_layer(hw);
/* walk through all the layers from SW entry point to qgroup layer */
for (i = hw->sw_entry_point_layer; i <= qg_layer; i++) {
num_nodes = ice_sched_get_num_nodes_per_layer(pi, i);
if (num_nodes + new_num_nodes_per_layer[i] >
le16_to_cpu(hw->layer_info[i].max_pf_nodes)) {
ice_debug(hw, ICE_DBG_SCHED,
"max nodes reached for layer = %d\n", i);
return ICE_ERR_CFG;
}
}
return 0;
}
/**
* ice_rm_dflt_leaf_node - remove the default leaf node in the tree
* @pi: port information structure
@ -1003,14 +937,12 @@ enum ice_status ice_sched_init_port(struct ice_port_info *pi)
hw = pi->hw;
/* Query the Default Topology from FW */
buf = devm_kcalloc(ice_hw_to_dev(hw), ICE_TXSCHED_MAX_BRANCHES,
sizeof(*buf), GFP_KERNEL);
buf = devm_kzalloc(ice_hw_to_dev(hw), ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
if (!buf)
return ICE_ERR_NO_MEMORY;
/* Query default scheduling tree topology */
status = ice_aq_get_dflt_topo(hw, pi->lport, buf,
sizeof(*buf) * ICE_TXSCHED_MAX_BRANCHES,
status = ice_aq_get_dflt_topo(hw, pi->lport, buf, ICE_AQ_MAX_BUF_LEN,
&num_branches, NULL);
if (status)
goto err_init_port;
@ -1097,6 +1029,8 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
{
struct ice_aqc_query_txsched_res_resp *buf;
enum ice_status status = 0;
__le16 max_sibl;
u8 i;
if (hw->layer_info)
return status;
@ -1115,7 +1049,20 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
hw->flattened_layers = buf->sched_props.flattening_bitmap;
hw->max_cgds = buf->sched_props.max_pf_cgds;
hw->layer_info = devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
/* max sibling group size of current layer refers to the max children
* of the below layer node.
* layer 1 node max children will be layer 2 max sibling group size
* layer 2 node max children will be layer 3 max sibling group size
* and so on. This array will be populated from root (index 0) to
* qgroup layer 7. Leaf node has no children.
*/
for (i = 0; i < hw->num_tx_sched_layers; i++) {
max_sibl = buf->layer_props[i].max_sibl_grp_sz;
hw->max_children[i] = le16_to_cpu(max_sibl);
}
hw->layer_info = (struct ice_aqc_layer_props *)
devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props,
(hw->num_tx_sched_layers *
sizeof(*hw->layer_info)),
GFP_KERNEL);
@ -1202,7 +1149,7 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
u8 qgrp_layer;
qgrp_layer = ice_sched_get_qgrp_layer(pi->hw);
max_children = le16_to_cpu(pi->hw->layer_info[qgrp_layer].max_children);
max_children = pi->hw->max_children[qgrp_layer];
list_elem = ice_sched_get_vsi_info_entry(pi, vsi_id);
if (!list_elem)
@ -1278,10 +1225,8 @@ ice_sched_calc_vsi_child_nodes(struct ice_hw *hw, u16 num_qs, u16 *num_nodes)
/* calculate num nodes from q group to VSI layer */
for (i = qgl; i > vsil; i--) {
u16 max_children = le16_to_cpu(hw->layer_info[i].max_children);
/* round to the next integer if there is a remainder */
num = DIV_ROUND_UP(num, max_children);
num = DIV_ROUND_UP(num, hw->max_children[i]);
/* need at least one node */
num_nodes[i] = num ? num : 1;
@ -1311,16 +1256,13 @@ ice_sched_add_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_id,
u16 num_added = 0;
u8 i, qgl, vsil;
status = ice_sched_validate_for_max_nodes(pi, num_nodes);
if (status)
return status;
qgl = ice_sched_get_qgrp_layer(hw);
vsil = ice_sched_get_vsi_layer(hw);
parent = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
for (i = vsil + 1; i <= qgl; i++) {
if (!parent)
return ICE_ERR_CFG;
status = ice_sched_add_nodes_to_layer(pi, tc_node, parent, i,
num_nodes[i],
&first_node_teid,
@ -1398,8 +1340,8 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
struct ice_sched_node *tc_node, u16 *num_nodes)
{
struct ice_sched_node *node;
u16 max_child;
u8 i, vsil;
u8 vsil;
int i;
vsil = ice_sched_get_vsi_layer(hw);
for (i = vsil; i >= hw->sw_entry_point_layer; i--)
@ -1412,12 +1354,10 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
/* If intermediate nodes are reached max children
* then add a new one.
*/
node = ice_sched_get_first_node(hw, tc_node, i);
max_child = le16_to_cpu(hw->layer_info[i].max_children);
node = ice_sched_get_first_node(hw, tc_node, (u8)i);
/* scan all the siblings */
while (node) {
if (node->num_children < max_child)
if (node->num_children < hw->max_children[i])
break;
node = node->sibling;
}
@ -1451,10 +1391,6 @@ ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_id,
if (!pi)
return ICE_ERR_PARAM;
status = ice_sched_validate_for_max_nodes(pi, num_nodes);
if (status)
return status;
vsil = ice_sched_get_vsi_layer(pi->hw);
for (i = pi->hw->sw_entry_point_layer; i <= vsil; i++) {
status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,
@ -1479,6 +1415,7 @@ ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_id,
if (i == vsil)
parent->vsi_id = vsi_id;
}
return 0;
}
@ -1633,9 +1570,11 @@ ice_sched_cfg_vsi(struct ice_port_info *pi, u16 vsi_id, u8 tc, u16 maxqs,
status = ice_sched_add_vsi_to_topo(pi, vsi_id, tc);
if (status)
return status;
vsi_node = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
if (!vsi_node)
return ICE_ERR_CFG;
vsi->vsi_node[tc] = vsi_node;
vsi_node->in_use = true;
}

View File

@ -20,6 +20,7 @@ enum ice_status {
ICE_ERR_ALREADY_EXISTS = -14,
ICE_ERR_DOES_NOT_EXIST = -15,
ICE_ERR_MAX_LIMIT = -17,
ICE_ERR_RESET_ONGOING = -18,
ICE_ERR_BUF_TOO_SHORT = -52,
ICE_ERR_NVM_BLANK_MODE = -53,
ICE_ERR_AQ_ERROR = -100,

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@ enum ice_sw_lkup_type {
ICE_SW_LKUP_DFLT = 5,
ICE_SW_LKUP_ETHERTYPE_MAC = 8,
ICE_SW_LKUP_PROMISC_VLAN = 9,
ICE_SW_LKUP_LAST
};
struct ice_fltr_info {
@ -98,6 +99,31 @@ struct ice_fltr_info {
u8 lan_en; /* Indicate if packet can be forwarded to the uplink */
};
struct ice_sw_recipe {
struct list_head l_entry;
/* To protect modification of filt_rule list
* defined below
*/
struct mutex filt_rule_lock;
/* List of type ice_fltr_mgmt_list_entry */
struct list_head filt_rules;
/* linked list of type recipe_list_entry */
struct list_head rg_list;
/* linked list of type ice_sw_fv_list_entry*/
struct list_head fv_list;
struct ice_aqc_recipe_data_elem *r_buf;
u8 recp_count;
u8 root_rid;
u8 num_profs;
u8 *prof_ids;
/* recipe bitmap: what all recipes makes this recipe */
DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
};
/* Bookkeeping structure to hold bitmap of VSIs corresponding to VSI list id */
struct ice_vsi_list_map_info {
struct list_head list_entry;
@ -105,15 +131,9 @@ struct ice_vsi_list_map_info {
u16 vsi_list_id;
};
enum ice_sw_fltr_status {
ICE_FLTR_STATUS_NEW = 0,
ICE_FLTR_STATUS_FW_SUCCESS,
ICE_FLTR_STATUS_FW_FAIL,
};
struct ice_fltr_list_entry {
struct list_head list_entry;
enum ice_sw_fltr_status status;
enum ice_status status;
struct ice_fltr_info fltr_info;
};
@ -138,18 +158,18 @@ struct ice_fltr_mgmt_list_entry {
/* VSI related commands */
enum ice_status
ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
struct ice_sq_cd *cd);
enum ice_status
ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
bool keep_vsi_alloc, struct ice_sq_cd *cd);
enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);
/* Switch/bridge related commands */
enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw);
enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_lst);
enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_lst);
void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id);
@ -158,4 +178,8 @@ enum ice_status ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list);
enum ice_status
ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_id, bool set, u8 direction);
enum ice_status ice_replay_all_fltr(struct ice_hw *hw);
enum ice_status ice_init_def_sw_recp(struct ice_hw *hw);
#endif /* _ICE_SWITCH_H_ */

View File

@ -251,6 +251,7 @@ int ice_setup_tx_ring(struct ice_ring *tx_ring)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
tx_ring->tx_stats.prev_pkt = -1;
return 0;
err:

View File

@ -71,6 +71,7 @@ struct ice_txq_stats {
u64 restart_q;
u64 tx_busy;
u64 tx_linearize;
int prev_pkt; /* negative if no pending Tx descriptors */
};
struct ice_rxq_stats {

View File

@ -34,10 +34,15 @@ static inline bool ice_is_tc_ena(u8 bitmap, u8 tc)
enum ice_aq_res_ids {
ICE_NVM_RES_ID = 1,
ICE_SPD_RES_ID,
ICE_GLOBAL_CFG_LOCK_RES_ID,
ICE_CHANGE_LOCK_RES_ID
ICE_CHANGE_LOCK_RES_ID,
ICE_GLOBAL_CFG_LOCK_RES_ID
};
/* FW update timeout definitions are in milliseconds */
#define ICE_NVM_TIMEOUT 180000
#define ICE_CHANGE_LOCK_TIMEOUT 1000
#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 3000
enum ice_aq_res_access_type {
ICE_RES_READ = 1,
ICE_RES_WRITE
@ -144,9 +149,10 @@ struct ice_mac_info {
/* Various RESET request, These are not tied with HW reset types */
enum ice_reset_req {
ICE_RESET_PFR = 0,
ICE_RESET_CORER = 1,
ICE_RESET_GLOBR = 2,
ICE_RESET_INVAL = 0,
ICE_RESET_PFR = 1,
ICE_RESET_CORER = 2,
ICE_RESET_GLOBR = 3,
};
/* Bus parameters */
@ -204,6 +210,7 @@ enum ice_agg_type {
};
#define ICE_SCHED_DFLT_RL_PROF_ID 0
#define ICE_SCHED_DFLT_BW_WT 1
/* vsi type list entry to locate corresponding vsi/ag nodes */
struct ice_sched_vsi_info {
@ -247,19 +254,26 @@ struct ice_port_info {
};
struct ice_switch_info {
/* Switch VSI lists to MAC/VLAN translation */
struct mutex mac_list_lock; /* protect MAC list */
struct list_head mac_list_head;
struct mutex vlan_list_lock; /* protect VLAN list */
struct list_head vlan_list_head;
struct mutex eth_m_list_lock; /* protect ethtype list */
struct list_head eth_m_list_head;
struct mutex promisc_list_lock; /* protect promisc mode list */
struct list_head promisc_list_head;
struct mutex mac_vlan_list_lock; /* protect MAC-VLAN list */
struct list_head mac_vlan_list_head;
struct list_head vsi_list_map_head;
struct ice_sw_recipe *recp_list;
};
/* FW logging configuration */
struct ice_fw_log_evnt {
u8 cfg : 4; /* New event enables to configure */
u8 cur : 4; /* Current/active event enables */
};
struct ice_fw_log_cfg {
u8 cq_en : 1; /* FW logging is enabled via the control queue */
u8 uart_en : 1; /* FW logging is enabled via UART for all PFs */
u8 actv_evnts; /* Cumulation of currently enabled log events */
#define ICE_FW_LOG_EVNT_INFO (ICE_AQC_FW_LOG_INFO_EN >> ICE_AQC_FW_LOG_EN_S)
#define ICE_FW_LOG_EVNT_INIT (ICE_AQC_FW_LOG_INIT_EN >> ICE_AQC_FW_LOG_EN_S)
#define ICE_FW_LOG_EVNT_FLOW (ICE_AQC_FW_LOG_FLOW_EN >> ICE_AQC_FW_LOG_EN_S)
#define ICE_FW_LOG_EVNT_ERR (ICE_AQC_FW_LOG_ERR_EN >> ICE_AQC_FW_LOG_EN_S)
struct ice_fw_log_evnt evnts[ICE_AQC_FW_LOG_ID_MAX];
};
/* Port hardware description */
@ -286,8 +300,11 @@ struct ice_hw {
u8 flattened_layers;
u8 max_cgds;
u8 sw_entry_point_layer;
u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI];
u8 evb_veb; /* true for VEB, false for VEPA */
u8 reset_ongoing; /* true if hw is in reset, false otherwise */
struct ice_bus_info bus;
struct ice_nvm_info nvm;
struct ice_hw_dev_caps dev_caps; /* device capabilities */
@ -308,6 +325,7 @@ struct ice_hw {
u8 fw_patch; /* firmware patch version */
u32 fw_build; /* firmware build number */
struct ice_fw_log_cfg fw_log;
/* minimum allowed value for different speeds */
#define ICE_ITR_GRAN_MIN_200 1
#define ICE_ITR_GRAN_MIN_100 1