Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ice/ice_common.c
/* SPDX-License-Identifier: BSD-3-Clause */ | /* SPDX-License-Identifier: BSD-3-Clause */ | ||||
/* Copyright (c) 2022, Intel Corporation | /* Copyright (c) 2023, Intel Corporation | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions are met: | * modification, are permitted provided that the following conditions are met: | ||||
* | * | ||||
* 1. Redistributions of source code must retain the above copyright notice, | * 1. Redistributions of source code must retain the above copyright notice, | ||||
* this list of conditions and the following disclaimer. | * this list of conditions and the following disclaimer. | ||||
* | * | ||||
Show All 21 Lines | |||||
#include "ice_common.h" | #include "ice_common.h" | ||||
#include "ice_sched.h" | #include "ice_sched.h" | ||||
#include "ice_adminq_cmd.h" | #include "ice_adminq_cmd.h" | ||||
#include "ice_flow.h" | #include "ice_flow.h" | ||||
#include "ice_switch.h" | #include "ice_switch.h" | ||||
#define ICE_PF_RESET_WAIT_COUNT 300 | #define ICE_PF_RESET_WAIT_COUNT 500 | ||||
static const char * const ice_link_mode_str_low[] = { | static const char * const ice_link_mode_str_low[] = { | ||||
[0] = "100BASE_TX", | ice_arr_elem_idx(0, "100BASE_TX"), | ||||
[1] = "100M_SGMII", | ice_arr_elem_idx(1, "100M_SGMII"), | ||||
[2] = "1000BASE_T", | ice_arr_elem_idx(2, "1000BASE_T"), | ||||
[3] = "1000BASE_SX", | ice_arr_elem_idx(3, "1000BASE_SX"), | ||||
[4] = "1000BASE_LX", | ice_arr_elem_idx(4, "1000BASE_LX"), | ||||
[5] = "1000BASE_KX", | ice_arr_elem_idx(5, "1000BASE_KX"), | ||||
[6] = "1G_SGMII", | ice_arr_elem_idx(6, "1G_SGMII"), | ||||
[7] = "2500BASE_T", | ice_arr_elem_idx(7, "2500BASE_T"), | ||||
[8] = "2500BASE_X", | ice_arr_elem_idx(8, "2500BASE_X"), | ||||
[9] = "2500BASE_KX", | ice_arr_elem_idx(9, "2500BASE_KX"), | ||||
[10] = "5GBASE_T", | ice_arr_elem_idx(10, "5GBASE_T"), | ||||
[11] = "5GBASE_KR", | ice_arr_elem_idx(11, "5GBASE_KR"), | ||||
[12] = "10GBASE_T", | ice_arr_elem_idx(12, "10GBASE_T"), | ||||
[13] = "10G_SFI_DA", | ice_arr_elem_idx(13, "10G_SFI_DA"), | ||||
[14] = "10GBASE_SR", | ice_arr_elem_idx(14, "10GBASE_SR"), | ||||
[15] = "10GBASE_LR", | ice_arr_elem_idx(15, "10GBASE_LR"), | ||||
[16] = "10GBASE_KR_CR1", | ice_arr_elem_idx(16, "10GBASE_KR_CR1"), | ||||
[17] = "10G_SFI_AOC_ACC", | ice_arr_elem_idx(17, "10G_SFI_AOC_ACC"), | ||||
[18] = "10G_SFI_C2C", | ice_arr_elem_idx(18, "10G_SFI_C2C"), | ||||
[19] = "25GBASE_T", | ice_arr_elem_idx(19, "25GBASE_T"), | ||||
[20] = "25GBASE_CR", | ice_arr_elem_idx(20, "25GBASE_CR"), | ||||
[21] = "25GBASE_CR_S", | ice_arr_elem_idx(21, "25GBASE_CR_S"), | ||||
[22] = "25GBASE_CR1", | ice_arr_elem_idx(22, "25GBASE_CR1"), | ||||
[23] = "25GBASE_SR", | ice_arr_elem_idx(23, "25GBASE_SR"), | ||||
[24] = "25GBASE_LR", | ice_arr_elem_idx(24, "25GBASE_LR"), | ||||
[25] = "25GBASE_KR", | ice_arr_elem_idx(25, "25GBASE_KR"), | ||||
[26] = "25GBASE_KR_S", | ice_arr_elem_idx(26, "25GBASE_KR_S"), | ||||
[27] = "25GBASE_KR1", | ice_arr_elem_idx(27, "25GBASE_KR1"), | ||||
[28] = "25G_AUI_AOC_ACC", | ice_arr_elem_idx(28, "25G_AUI_AOC_ACC"), | ||||
[29] = "25G_AUI_C2C", | ice_arr_elem_idx(29, "25G_AUI_C2C"), | ||||
[30] = "40GBASE_CR4", | ice_arr_elem_idx(30, "40GBASE_CR4"), | ||||
[31] = "40GBASE_SR4", | ice_arr_elem_idx(31, "40GBASE_SR4"), | ||||
[32] = "40GBASE_LR4", | ice_arr_elem_idx(32, "40GBASE_LR4"), | ||||
[33] = "40GBASE_KR4", | ice_arr_elem_idx(33, "40GBASE_KR4"), | ||||
[34] = "40G_XLAUI_AOC_ACC", | ice_arr_elem_idx(34, "40G_XLAUI_AOC_ACC"), | ||||
[35] = "40G_XLAUI", | ice_arr_elem_idx(35, "40G_XLAUI"), | ||||
[36] = "50GBASE_CR2", | ice_arr_elem_idx(36, "50GBASE_CR2"), | ||||
[37] = "50GBASE_SR2", | ice_arr_elem_idx(37, "50GBASE_SR2"), | ||||
[38] = "50GBASE_LR2", | ice_arr_elem_idx(38, "50GBASE_LR2"), | ||||
[39] = "50GBASE_KR2", | ice_arr_elem_idx(39, "50GBASE_KR2"), | ||||
[40] = "50G_LAUI2_AOC_ACC", | ice_arr_elem_idx(40, "50G_LAUI2_AOC_ACC"), | ||||
[41] = "50G_LAUI2", | ice_arr_elem_idx(41, "50G_LAUI2"), | ||||
[42] = "50G_AUI2_AOC_ACC", | ice_arr_elem_idx(42, "50G_AUI2_AOC_ACC"), | ||||
[43] = "50G_AUI2", | ice_arr_elem_idx(43, "50G_AUI2"), | ||||
[44] = "50GBASE_CP", | ice_arr_elem_idx(44, "50GBASE_CP"), | ||||
[45] = "50GBASE_SR", | ice_arr_elem_idx(45, "50GBASE_SR"), | ||||
[46] = "50GBASE_FR", | ice_arr_elem_idx(46, "50GBASE_FR"), | ||||
[47] = "50GBASE_LR", | ice_arr_elem_idx(47, "50GBASE_LR"), | ||||
[48] = "50GBASE_KR_PAM4", | ice_arr_elem_idx(48, "50GBASE_KR_PAM4"), | ||||
[49] = "50G_AUI1_AOC_ACC", | ice_arr_elem_idx(49, "50G_AUI1_AOC_ACC"), | ||||
[50] = "50G_AUI1", | ice_arr_elem_idx(50, "50G_AUI1"), | ||||
[51] = "100GBASE_CR4", | ice_arr_elem_idx(51, "100GBASE_CR4"), | ||||
[52] = "100GBASE_SR4", | ice_arr_elem_idx(52, "100GBASE_SR4"), | ||||
[53] = "100GBASE_LR4", | ice_arr_elem_idx(53, "100GBASE_LR4"), | ||||
[54] = "100GBASE_KR4", | ice_arr_elem_idx(54, "100GBASE_KR4"), | ||||
[55] = "100G_CAUI4_AOC_ACC", | ice_arr_elem_idx(55, "100G_CAUI4_AOC_ACC"), | ||||
[56] = "100G_CAUI4", | ice_arr_elem_idx(56, "100G_CAUI4"), | ||||
[57] = "100G_AUI4_AOC_ACC", | ice_arr_elem_idx(57, "100G_AUI4_AOC_ACC"), | ||||
[58] = "100G_AUI4", | ice_arr_elem_idx(58, "100G_AUI4"), | ||||
[59] = "100GBASE_CR_PAM4", | ice_arr_elem_idx(59, "100GBASE_CR_PAM4"), | ||||
[60] = "100GBASE_KR_PAM4", | ice_arr_elem_idx(60, "100GBASE_KR_PAM4"), | ||||
[61] = "100GBASE_CP2", | ice_arr_elem_idx(61, "100GBASE_CP2"), | ||||
[62] = "100GBASE_SR2", | ice_arr_elem_idx(62, "100GBASE_SR2"), | ||||
[63] = "100GBASE_DR", | ice_arr_elem_idx(63, "100GBASE_DR"), | ||||
}; | }; | ||||
static const char * const ice_link_mode_str_high[] = { | static const char * const ice_link_mode_str_high[] = { | ||||
[0] = "100GBASE_KR2_PAM4", | ice_arr_elem_idx(0, "100GBASE_KR2_PAM4"), | ||||
[1] = "100G_CAUI2_AOC_ACC", | ice_arr_elem_idx(1, "100G_CAUI2_AOC_ACC"), | ||||
[2] = "100G_CAUI2", | ice_arr_elem_idx(2, "100G_CAUI2"), | ||||
[3] = "100G_AUI2_AOC_ACC", | ice_arr_elem_idx(3, "100G_AUI2_AOC_ACC"), | ||||
[4] = "100G_AUI2", | ice_arr_elem_idx(4, "100G_AUI2"), | ||||
}; | }; | ||||
/** | /** | ||||
* ice_dump_phy_type - helper function to dump phy_type | * ice_dump_phy_type - helper function to dump phy_type | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @low: 64 bit value for phy_type_low | * @low: 64 bit value for phy_type_low | ||||
* @high: 64 bit value for phy_type_high | * @high: 64 bit value for phy_type_high | ||||
* @prefix: prefix string to differentiate multiple dumps | * @prefix: prefix string to differentiate multiple dumps | ||||
▲ Show 20 Lines • Show All 1,164 Lines • ▼ Show 20 Lines | static enum ice_status ice_pf_reset(struct ice_hw *hw) | ||||
wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); | wr32(hw, PFGEN_CTRL, (reg | PFGEN_CTRL_PFSWR_M)); | ||||
/* Wait for the PFR to complete. The wait time is the global config lock | /* Wait for the PFR to complete. The wait time is the global config lock | ||||
* timeout plus the PFR timeout which will account for a possible reset | * timeout plus the PFR timeout which will account for a possible reset | ||||
* that is occurring during a download package operation. | * that is occurring during a download package operation. | ||||
*/ | */ | ||||
for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT + | for (cnt = 0; cnt < ICE_GLOBAL_CFG_LOCK_TIMEOUT + | ||||
ICE_PF_RESET_WAIT_COUNT; cnt++) { | ICE_PF_RESET_WAIT_COUNT; cnt++) { | ||||
reg = rd32(hw, PFGEN_CTRL); | reg = rd32(hw, PFGEN_CTRL); | ||||
if (!(reg & PFGEN_CTRL_PFSWR_M)) | if (!(reg & PFGEN_CTRL_PFSWR_M)) | ||||
break; | break; | ||||
ice_msec_delay(1, true); | ice_msec_delay(1, true); | ||||
} | } | ||||
if (cnt == ICE_PF_RESET_WAIT_COUNT) { | if (cnt == ICE_PF_RESET_WAIT_COUNT) { | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) { | ||||
ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, | ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, | ||||
*((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); | *((u32 *)(ice_rxq_ctx + (i * sizeof(u32))))); | ||||
} | } | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | |||||
* ice_copy_rxq_ctx_from_hw - Copy rxq context register from HW | |||||
* @hw: pointer to the hardware structure | |||||
* @ice_rxq_ctx: pointer to the rxq context | |||||
* @rxq_index: the index of the Rx queue | |||||
* | |||||
* Copies rxq context from HW register space to dense structure | |||||
*/ | |||||
static enum ice_status | |||||
ice_copy_rxq_ctx_from_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index) | |||||
{ | |||||
u8 i; | |||||
if (!ice_rxq_ctx) | |||||
return ICE_ERR_BAD_PTR; | |||||
if (rxq_index > QRX_CTRL_MAX_INDEX) | |||||
return ICE_ERR_PARAM; | |||||
/* Copy each dword separately from HW */ | |||||
for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) { | |||||
u32 *ctx = (u32 *)(ice_rxq_ctx + (i * sizeof(u32))); | |||||
*ctx = rd32(hw, QRX_CONTEXT(i, rxq_index)); | |||||
ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, *ctx); | |||||
} | |||||
return ICE_SUCCESS; | |||||
} | |||||
/* LAN Rx Queue Context */ | /* LAN Rx Queue Context */ | ||||
static const struct ice_ctx_ele ice_rlan_ctx_info[] = { | static const struct ice_ctx_ele ice_rlan_ctx_info[] = { | ||||
/* Field Width LSB */ | /* Field Width LSB */ | ||||
ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0), | ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0), | ||||
ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13), | ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13), | ||||
ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32), | ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32), | ||||
ICE_CTX_STORE(ice_rlan_ctx, qlen, 13, 89), | ICE_CTX_STORE(ice_rlan_ctx, qlen, 13, 89), | ||||
ICE_CTX_STORE(ice_rlan_ctx, dbuf, 7, 102), | ICE_CTX_STORE(ice_rlan_ctx, dbuf, 7, 102), | ||||
Show All 36 Lines | ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, | ||||
rlan_ctx->prefena = 1; | rlan_ctx->prefena = 1; | ||||
ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info); | ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info); | ||||
return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index); | return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index); | ||||
} | } | ||||
/** | /** | ||||
* ice_read_rxq_ctx - Read rxq context from HW | |||||
* @hw: pointer to the hardware structure | |||||
* @rlan_ctx: pointer to the rxq context | |||||
* @rxq_index: the index of the Rx queue | |||||
* | |||||
* Read rxq context from HW register space and then converts it from dense | |||||
* structure to sparse | |||||
*/ | |||||
enum ice_status | |||||
ice_read_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx, | |||||
u32 rxq_index) | |||||
{ | |||||
u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 }; | |||||
enum ice_status status; | |||||
if (!rlan_ctx) | |||||
return ICE_ERR_BAD_PTR; | |||||
status = ice_copy_rxq_ctx_from_hw(hw, ctx_buf, rxq_index); | |||||
if (status) | |||||
return status; | |||||
return ice_get_ctx(ctx_buf, (u8 *)rlan_ctx, ice_rlan_ctx_info); | |||||
} | |||||
/** | |||||
* ice_clear_rxq_ctx | * ice_clear_rxq_ctx | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* @rxq_index: the index of the Rx queue to clear | * @rxq_index: the index of the Rx queue to clear | ||||
* | * | ||||
* Clears rxq context in HW register space | * Clears rxq context in HW register space | ||||
*/ | */ | ||||
enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index) | enum ice_status ice_clear_rxq_ctx(struct ice_hw *hw, u32 rxq_index) | ||||
{ | { | ||||
u8 i; | u8 i; | ||||
if (rxq_index > QRX_CTRL_MAX_INDEX) | if (rxq_index > QRX_CTRL_MAX_INDEX) | ||||
return ICE_ERR_PARAM; | return ICE_ERR_PARAM; | ||||
/* Clear each dword register separately */ | /* Clear each dword register separately */ | ||||
for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) | for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) | ||||
wr32(hw, QRX_CONTEXT(i, rxq_index), 0); | wr32(hw, QRX_CONTEXT(i, rxq_index), 0); | ||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/* LAN Tx Queue Context */ | /* LAN Tx Queue Context used for set Tx config by ice_aqc_opc_add_txqs, | ||||
* Bit[0-175] is valid | |||||
*/ | |||||
const struct ice_ctx_ele ice_tlan_ctx_info[] = { | const struct ice_ctx_ele ice_tlan_ctx_info[] = { | ||||
/* Field Width LSB */ | /* Field Width LSB */ | ||||
ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0), | ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0), | ||||
ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57), | ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57), | ||||
ICE_CTX_STORE(ice_tlan_ctx, cgd_num, 5, 60), | ICE_CTX_STORE(ice_tlan_ctx, cgd_num, 5, 60), | ||||
ICE_CTX_STORE(ice_tlan_ctx, pf_num, 3, 65), | ICE_CTX_STORE(ice_tlan_ctx, pf_num, 3, 65), | ||||
ICE_CTX_STORE(ice_tlan_ctx, vmvf_num, 10, 68), | ICE_CTX_STORE(ice_tlan_ctx, vmvf_num, 10, 68), | ||||
ICE_CTX_STORE(ice_tlan_ctx, vmvf_type, 2, 78), | ICE_CTX_STORE(ice_tlan_ctx, vmvf_type, 2, 78), | ||||
▲ Show 20 Lines • Show All 1,574 Lines • ▼ Show 20 Lines | |||||
* @cd: pointer to command details structure or NULL | * @cd: pointer to command details structure or NULL | ||||
* | * | ||||
* Set Physical port parameters (0x0203) | * Set Physical port parameters (0x0203) | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi, | ice_aq_set_port_params(struct ice_port_info *pi, u16 bad_frame_vsi, | ||||
bool save_bad_pac, bool pad_short_pac, bool double_vlan, | bool save_bad_pac, bool pad_short_pac, bool double_vlan, | ||||
struct ice_sq_cd *cd) | struct ice_sq_cd *cd) | ||||
{ | { | ||||
struct ice_aqc_set_port_params *cmd; | struct ice_aqc_set_port_params *cmd; | ||||
struct ice_hw *hw = pi->hw; | struct ice_hw *hw = pi->hw; | ||||
struct ice_aq_desc desc; | struct ice_aq_desc desc; | ||||
u16 cmd_flags = 0; | u16 cmd_flags = 0; | ||||
cmd = &desc.params.set_port_params; | cmd = &desc.params.set_port_params; | ||||
Show All 35 Lines | |||||
* @phy_type_low: lower part of phy_type | * @phy_type_low: lower part of phy_type | ||||
* @phy_type_high: higher part of phy_type | * @phy_type_high: higher part of phy_type | ||||
* | * | ||||
* This helper function will convert an entry in PHY type structure | * This helper function will convert an entry in PHY type structure | ||||
* [phy_type_low, phy_type_high] to its corresponding link speed. | * [phy_type_low, phy_type_high] to its corresponding link speed. | ||||
* Note: In the structure of [phy_type_low, phy_type_high], there should | * Note: In the structure of [phy_type_low, phy_type_high], there should | ||||
* be one bit set, as this function will convert one PHY type to its | * be one bit set, as this function will convert one PHY type to its | ||||
* speed. | * speed. | ||||
* If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned | * If no bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned | ||||
* If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned | * If more than one bit gets set, ICE_AQ_LINK_SPEED_UNKNOWN will be returned | ||||
*/ | */ | ||||
static u16 | static u16 | ||||
ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) | ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) | ||||
{ | { | ||||
u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; | u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; | ||||
u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; | u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; | ||||
switch (phy_type_low) { | switch (phy_type_low) { | ||||
▲ Show 20 Lines • Show All 1,661 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* ice_read_byte - read context byte into struct | * ice_read_byte - read context byte into struct | ||||
* @src_ctx: the context structure to read from | * @src_ctx: the context structure to read from | ||||
* @dest_ctx: the context to be written to | * @dest_ctx: the context to be written to | ||||
* @ce_info: a description of the struct to be filled | * @ce_info: a description of the struct to be filled | ||||
*/ | */ | ||||
static void | static void | ||||
ice_read_byte(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) | ice_read_byte(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
{ | { | ||||
u8 dest_byte, mask; | u8 dest_byte, mask; | ||||
u8 *src, *target; | u8 *src, *target; | ||||
u16 shift_width; | u16 shift_width; | ||||
/* prepare the bits and mask */ | /* prepare the bits and mask */ | ||||
shift_width = ce_info->lsb % 8; | shift_width = ce_info->lsb % 8; | ||||
mask = (u8)(BIT(ce_info->width) - 1); | mask = (u8)(BIT(ce_info->width) - 1); | ||||
/* shift to correct alignment */ | /* shift to correct alignment */ | ||||
mask <<= shift_width; | mask <<= shift_width; | ||||
/* get the current bits from the src bit string */ | /* get the current bits from the src bit string */ | ||||
src = src_ctx + (ce_info->lsb / 8); | src = src_ctx + (ce_info->lsb / 8); | ||||
ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA); | ice_memcpy(&dest_byte, src, sizeof(dest_byte), ICE_DMA_TO_NONDMA); | ||||
dest_byte &= ~(mask); | dest_byte &= mask; | ||||
dest_byte >>= shift_width; | dest_byte >>= shift_width; | ||||
/* get the address from the struct field */ | /* get the address from the struct field */ | ||||
target = dest_ctx + ce_info->offset; | target = dest_ctx + ce_info->offset; | ||||
/* put it back in the struct */ | /* put it back in the struct */ | ||||
ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA); | ice_memcpy(target, &dest_byte, sizeof(dest_byte), ICE_NONDMA_TO_DMA); | ||||
} | } | ||||
/** | /** | ||||
* ice_read_word - read context word into struct | * ice_read_word - read context word into struct | ||||
* @src_ctx: the context structure to read from | * @src_ctx: the context structure to read from | ||||
* @dest_ctx: the context to be written to | * @dest_ctx: the context to be written to | ||||
* @ce_info: a description of the struct to be filled | * @ce_info: a description of the struct to be filled | ||||
*/ | */ | ||||
static void | static void | ||||
ice_read_word(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) | ice_read_word(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
{ | { | ||||
u16 dest_word, mask; | u16 dest_word, mask; | ||||
u8 *src, *target; | u8 *src, *target; | ||||
__le16 src_word; | __le16 src_word; | ||||
u16 shift_width; | u16 shift_width; | ||||
/* prepare the bits and mask */ | /* prepare the bits and mask */ | ||||
shift_width = ce_info->lsb % 8; | shift_width = ce_info->lsb % 8; | ||||
mask = BIT(ce_info->width) - 1; | mask = BIT(ce_info->width) - 1; | ||||
/* shift to correct alignment */ | /* shift to correct alignment */ | ||||
mask <<= shift_width; | mask <<= shift_width; | ||||
/* get the current bits from the src bit string */ | /* get the current bits from the src bit string */ | ||||
src = src_ctx + (ce_info->lsb / 8); | src = src_ctx + (ce_info->lsb / 8); | ||||
ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA); | ice_memcpy(&src_word, src, sizeof(src_word), ICE_DMA_TO_NONDMA); | ||||
/* the data in the memory is stored as little endian so mask it | /* the data in the memory is stored as little endian so mask it | ||||
* correctly | * correctly | ||||
*/ | */ | ||||
src_word &= ~(CPU_TO_LE16(mask)); | src_word &= CPU_TO_LE16(mask); | ||||
/* get the data back into host order before shifting */ | /* get the data back into host order before shifting */ | ||||
dest_word = LE16_TO_CPU(src_word); | dest_word = LE16_TO_CPU(src_word); | ||||
dest_word >>= shift_width; | dest_word >>= shift_width; | ||||
/* get the address from the struct field */ | /* get the address from the struct field */ | ||||
target = dest_ctx + ce_info->offset; | target = dest_ctx + ce_info->offset; | ||||
/* put it back in the struct */ | /* put it back in the struct */ | ||||
ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA); | ice_memcpy(target, &dest_word, sizeof(dest_word), ICE_NONDMA_TO_DMA); | ||||
} | } | ||||
/** | /** | ||||
* ice_read_dword - read context dword into struct | * ice_read_dword - read context dword into struct | ||||
* @src_ctx: the context structure to read from | * @src_ctx: the context structure to read from | ||||
* @dest_ctx: the context to be written to | * @dest_ctx: the context to be written to | ||||
* @ce_info: a description of the struct to be filled | * @ce_info: a description of the struct to be filled | ||||
*/ | */ | ||||
static void | static void | ||||
ice_read_dword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) | ice_read_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
{ | { | ||||
u32 dest_dword, mask; | u32 dest_dword, mask; | ||||
__le32 src_dword; | __le32 src_dword; | ||||
u8 *src, *target; | u8 *src, *target; | ||||
u16 shift_width; | u16 shift_width; | ||||
/* prepare the bits and mask */ | /* prepare the bits and mask */ | ||||
shift_width = ce_info->lsb % 8; | shift_width = ce_info->lsb % 8; | ||||
Show All 13 Lines | ice_read_dword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
/* get the current bits from the src bit string */ | /* get the current bits from the src bit string */ | ||||
src = src_ctx + (ce_info->lsb / 8); | src = src_ctx + (ce_info->lsb / 8); | ||||
ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA); | ice_memcpy(&src_dword, src, sizeof(src_dword), ICE_DMA_TO_NONDMA); | ||||
/* the data in the memory is stored as little endian so mask it | /* the data in the memory is stored as little endian so mask it | ||||
* correctly | * correctly | ||||
*/ | */ | ||||
src_dword &= ~(CPU_TO_LE32(mask)); | src_dword &= CPU_TO_LE32(mask); | ||||
/* get the data back into host order before shifting */ | /* get the data back into host order before shifting */ | ||||
dest_dword = LE32_TO_CPU(src_dword); | dest_dword = LE32_TO_CPU(src_dword); | ||||
dest_dword >>= shift_width; | dest_dword >>= shift_width; | ||||
/* get the address from the struct field */ | /* get the address from the struct field */ | ||||
target = dest_ctx + ce_info->offset; | target = dest_ctx + ce_info->offset; | ||||
/* put it back in the struct */ | /* put it back in the struct */ | ||||
ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA); | ice_memcpy(target, &dest_dword, sizeof(dest_dword), ICE_NONDMA_TO_DMA); | ||||
} | } | ||||
/** | /** | ||||
* ice_read_qword - read context qword into struct | * ice_read_qword - read context qword into struct | ||||
* @src_ctx: the context structure to read from | * @src_ctx: the context structure to read from | ||||
* @dest_ctx: the context to be written to | * @dest_ctx: the context to be written to | ||||
* @ce_info: a description of the struct to be filled | * @ce_info: a description of the struct to be filled | ||||
*/ | */ | ||||
static void | static void | ||||
ice_read_qword(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) | ice_read_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
{ | { | ||||
u64 dest_qword, mask; | u64 dest_qword, mask; | ||||
__le64 src_qword; | __le64 src_qword; | ||||
u8 *src, *target; | u8 *src, *target; | ||||
u16 shift_width; | u16 shift_width; | ||||
/* prepare the bits and mask */ | /* prepare the bits and mask */ | ||||
shift_width = ce_info->lsb % 8; | shift_width = ce_info->lsb % 8; | ||||
Show All 13 Lines | ice_read_qword(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
/* get the current bits from the src bit string */ | /* get the current bits from the src bit string */ | ||||
src = src_ctx + (ce_info->lsb / 8); | src = src_ctx + (ce_info->lsb / 8); | ||||
ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA); | ice_memcpy(&src_qword, src, sizeof(src_qword), ICE_DMA_TO_NONDMA); | ||||
/* the data in the memory is stored as little endian so mask it | /* the data in the memory is stored as little endian so mask it | ||||
* correctly | * correctly | ||||
*/ | */ | ||||
src_qword &= ~(CPU_TO_LE64(mask)); | src_qword &= CPU_TO_LE64(mask); | ||||
/* get the data back into host order before shifting */ | /* get the data back into host order before shifting */ | ||||
dest_qword = LE64_TO_CPU(src_qword); | dest_qword = LE64_TO_CPU(src_qword); | ||||
dest_qword >>= shift_width; | dest_qword >>= shift_width; | ||||
/* get the address from the struct field */ | /* get the address from the struct field */ | ||||
target = dest_ctx + ce_info->offset; | target = dest_ctx + ce_info->offset; | ||||
/* put it back in the struct */ | /* put it back in the struct */ | ||||
ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA); | ice_memcpy(target, &dest_qword, sizeof(dest_qword), ICE_NONDMA_TO_DMA); | ||||
} | } | ||||
/** | /** | ||||
* ice_get_ctx - extract context bits from a packed structure | * ice_get_ctx - extract context bits from a packed structure | ||||
* @src_ctx: pointer to a generic packed context structure | * @src_ctx: pointer to a generic packed context structure | ||||
* @dest_ctx: pointer to a generic non-packed context structure | * @dest_ctx: pointer to a generic non-packed context structure | ||||
* @ce_info: a description of the structure to be read from | * @ce_info: a description of the structure to be read from | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, struct ice_ctx_ele *ce_info) | ice_get_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info) | ||||
{ | { | ||||
int f; | int f; | ||||
for (f = 0; ce_info[f].width; f++) { | for (f = 0; ce_info[f].width; f++) { | ||||
switch (ce_info[f].size_of) { | switch (ce_info[f].size_of) { | ||||
case 1: | case 1: | ||||
ice_read_byte(src_ctx, dest_ctx, &ce_info[f]); | ice_read_byte(src_ctx, dest_ctx, &ce_info[f]); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 819 Lines • ▼ Show 20 Lines | else if (fw_mode & ICE_FW_MODE_REC_M) | ||||
return ICE_FW_MODE_REC; | return ICE_FW_MODE_REC; | ||||
else if (fw_mode & ICE_FW_MODE_ROLLBACK_M) | else if (fw_mode & ICE_FW_MODE_ROLLBACK_M) | ||||
return ICE_FW_MODE_ROLLBACK; | return ICE_FW_MODE_ROLLBACK; | ||||
else | else | ||||
return ICE_FW_MODE_NORMAL; | return ICE_FW_MODE_NORMAL; | ||||
} | } | ||||
/** | /** | ||||
* ice_cfg_get_cur_lldp_persist_status | * ice_get_cur_lldp_persist_status | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @lldp_status: return value of LLDP persistent status | * @lldp_status: return value of LLDP persistent status | ||||
* | * | ||||
* Get the current status of LLDP persistent | * Get the current status of LLDP persistent | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status) | ice_get_cur_lldp_persist_status(struct ice_hw *hw, u32 *lldp_status) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 460 Lines • ▼ Show 20 Lines | |||||
* @options: buffer for the resultant port options | * @options: buffer for the resultant port options | ||||
* @option_count: input - size of the buffer in port options structures, | * @option_count: input - size of the buffer in port options structures, | ||||
* output - number of returned port options | * output - number of returned port options | ||||
* @lport: logical port to call the command with (optional) | * @lport: logical port to call the command with (optional) | ||||
* @lport_valid: when false, FW uses port owned by the PF instead of lport, | * @lport_valid: when false, FW uses port owned by the PF instead of lport, | ||||
* when PF owns more than 1 port it must be true | * when PF owns more than 1 port it must be true | ||||
* @active_option_idx: index of active port option in returned buffer | * @active_option_idx: index of active port option in returned buffer | ||||
* @active_option_valid: active option in returned buffer is valid | * @active_option_valid: active option in returned buffer is valid | ||||
* @pending_option_idx: index of pending port option in returned buffer | |||||
* @pending_option_valid: pending option in returned buffer is valid | |||||
* | * | ||||
* Calls Get Port Options AQC (0x06ea) and verifies result. | * Calls Get Port Options AQC (0x06ea) and verifies result. | ||||
*/ | */ | ||||
enum ice_status | enum ice_status | ||||
ice_aq_get_port_options(struct ice_hw *hw, | ice_aq_get_port_options(struct ice_hw *hw, | ||||
struct ice_aqc_get_port_options_elem *options, | struct ice_aqc_get_port_options_elem *options, | ||||
u8 *option_count, u8 lport, bool lport_valid, | u8 *option_count, u8 lport, bool lport_valid, | ||||
u8 *active_option_idx, bool *active_option_valid) | u8 *active_option_idx, bool *active_option_valid, | ||||
u8 *pending_option_idx, bool *pending_option_valid) | |||||
{ | { | ||||
struct ice_aqc_get_port_options *cmd; | struct ice_aqc_get_port_options *cmd; | ||||
struct ice_aq_desc desc; | struct ice_aq_desc desc; | ||||
enum ice_status status; | enum ice_status status; | ||||
u8 pmd_count; | |||||
u8 max_speed; | |||||
u8 i; | u8 i; | ||||
ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); | |||||
/* options buffer shall be able to hold max returned options */ | /* options buffer shall be able to hold max returned options */ | ||||
if (*option_count < ICE_AQC_PORT_OPT_COUNT_M) | if (*option_count < ICE_AQC_PORT_OPT_COUNT_M) | ||||
return ICE_ERR_PARAM; | return ICE_ERR_PARAM; | ||||
cmd = &desc.params.get_port_options; | cmd = &desc.params.get_port_options; | ||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options); | ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options); | ||||
if (lport_valid) | |||||
cmd->lport_num = lport; | cmd->lport_num = lport; | ||||
cmd->lport_num_valid = lport_valid; | cmd->lport_num_valid = lport_valid; | ||||
status = ice_aq_send_cmd(hw, &desc, options, | status = ice_aq_send_cmd(hw, &desc, options, | ||||
*option_count * sizeof(*options), NULL); | *option_count * sizeof(*options), NULL); | ||||
if (status != ICE_SUCCESS) | if (status != ICE_SUCCESS) | ||||
return status; | return status; | ||||
/* verify direct FW response & set output parameters */ | /* verify direct FW response & set output parameters */ | ||||
*option_count = cmd->port_options_count & ICE_AQC_PORT_OPT_COUNT_M; | *option_count = cmd->port_options_count & ICE_AQC_PORT_OPT_COUNT_M; | ||||
ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count); | ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count); | ||||
*active_option_valid = cmd->port_options & ICE_AQC_PORT_OPT_VALID; | *active_option_valid = cmd->port_options & ICE_AQC_PORT_OPT_VALID; | ||||
if (*active_option_valid) { | if (*active_option_valid) { | ||||
*active_option_idx = cmd->port_options & | *active_option_idx = cmd->port_options & | ||||
ICE_AQC_PORT_OPT_ACTIVE_M; | ICE_AQC_PORT_OPT_ACTIVE_M; | ||||
if (*active_option_idx > (*option_count - 1)) | if (*active_option_idx > (*option_count - 1)) | ||||
return ICE_ERR_OUT_OF_RANGE; | return ICE_ERR_OUT_OF_RANGE; | ||||
ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n", | ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n", | ||||
*active_option_idx); | *active_option_idx); | ||||
} | } | ||||
/* verify indirect FW response & mask output options fields */ | *pending_option_valid = cmd->pending_port_option_status & | ||||
ICE_AQC_PENDING_PORT_OPT_VALID; | |||||
if (*pending_option_valid) { | |||||
*pending_option_idx = cmd->pending_port_option_status & | |||||
ICE_AQC_PENDING_PORT_OPT_IDX_M; | |||||
if (*pending_option_idx > (*option_count - 1)) | |||||
return ICE_ERR_OUT_OF_RANGE; | |||||
ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n", | |||||
*pending_option_idx); | |||||
} | |||||
/* mask output options fields */ | |||||
for (i = 0; i < *option_count; i++) { | for (i = 0; i < *option_count; i++) { | ||||
options[i].pmd &= ICE_AQC_PORT_OPT_PMD_COUNT_M; | options[i].pmd &= ICE_AQC_PORT_OPT_PMD_COUNT_M; | ||||
options[i].max_lane_speed &= ICE_AQC_PORT_OPT_MAX_LANE_M; | options[i].max_lane_speed &= ICE_AQC_PORT_OPT_MAX_LANE_M; | ||||
pmd_count = options[i].pmd; | |||||
max_speed = options[i].max_lane_speed; | |||||
ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n", | ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n", | ||||
pmd_count, max_speed); | options[i].pmd, options[i].max_lane_speed); | ||||
/* check only entries containing valid max pmd speed values, | |||||
* other reserved values may be returned, when logical port | |||||
* used is unrelated to specific option | |||||
*/ | |||||
if (max_speed <= ICE_AQC_PORT_OPT_MAX_LANE_100G) { | |||||
if (pmd_count > ICE_MAX_PORT_PER_PCI_DEV) | |||||
return ICE_ERR_OUT_OF_RANGE; | |||||
if (pmd_count > 2 && | |||||
max_speed > ICE_AQC_PORT_OPT_MAX_LANE_25G) | |||||
return ICE_ERR_CFG; | |||||
if (pmd_count > 7 && | |||||
max_speed > ICE_AQC_PORT_OPT_MAX_LANE_10G) | |||||
return ICE_ERR_CFG; | |||||
} | } | ||||
} | |||||
return ICE_SUCCESS; | return ICE_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* ice_aq_set_port_option | |||||
* @hw: pointer to the hw struct | |||||
* @lport: logical port to call the command with | |||||
* @lport_valid: when false, FW uses port owned by the PF instead of lport, | |||||
* when PF owns more than 1 port it must be true | |||||
* @new_option: new port option to be written | |||||
* | |||||
* Calls Set Port Options AQC (0x06eb). | |||||
*/ | |||||
enum ice_status | |||||
ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid, | |||||
u8 new_option) | |||||
{ | |||||
struct ice_aqc_set_port_option *cmd; | |||||
struct ice_aq_desc desc; | |||||
if (new_option >= ICE_AQC_PORT_OPT_COUNT_M) | |||||
return ICE_ERR_PARAM; | |||||
cmd = &desc.params.set_port_option; | |||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option); | |||||
cmd->lport_num = lport; | |||||
cmd->lport_num_valid = lport_valid; | |||||
cmd->selected_port_option = new_option; | |||||
return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); | |||||
} | |||||
/** | |||||
* ice_aq_set_lldp_mib - Set the LLDP MIB | * ice_aq_set_lldp_mib - Set the LLDP MIB | ||||
* @hw: pointer to the HW struct | * @hw: pointer to the HW struct | ||||
* @mib_type: Local, Remote or both Local and Remote MIBs | * @mib_type: Local, Remote or both Local and Remote MIBs | ||||
* @buf: pointer to the caller-supplied buffer to store the MIB block | * @buf: pointer to the caller-supplied buffer to store the MIB block | ||||
* @buf_size: size of the buffer (in bytes) | * @buf_size: size of the buffer (in bytes) | ||||
* @cd: pointer to command details structure or NULL | * @cd: pointer to command details structure or NULL | ||||
* | * | ||||
* Set the LLDP MIB. (0x0A08) | * Set the LLDP MIB. (0x0A08) | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* Checks if the firmware supports report default configuration | * Checks if the firmware supports report default configuration | ||||
*/ | */ | ||||
bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw) | bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw) | ||||
{ | { | ||||
return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ, | return ice_is_fw_api_min_ver(hw, ICE_FW_API_REPORT_DFLT_CFG_MAJ, | ||||
ICE_FW_API_REPORT_DFLT_CFG_MIN, | ICE_FW_API_REPORT_DFLT_CFG_MIN, | ||||
ICE_FW_API_REPORT_DFLT_CFG_PATCH); | ICE_FW_API_REPORT_DFLT_CFG_PATCH); | ||||
} | |||||
/* each of the indexes into the following array match the speed of a return | |||||
* value from the list of AQ returned speeds like the range: | |||||
* ICE_AQ_LINK_SPEED_10MB .. ICE_AQ_LINK_SPEED_100GB excluding | |||||
* ICE_AQ_LINK_SPEED_UNKNOWN which is BIT(15) The array is defined as 15 | |||||
* elements long because the link_speed returned by the firmware is a 16 bit | |||||
* value, but is indexed by [fls(speed) - 1] | |||||
*/ | |||||
static const u32 ice_aq_to_link_speed[15] = { | |||||
ICE_LINK_SPEED_10MBPS, /* BIT(0) */ | |||||
ICE_LINK_SPEED_100MBPS, | |||||
ICE_LINK_SPEED_1000MBPS, | |||||
ICE_LINK_SPEED_2500MBPS, | |||||
ICE_LINK_SPEED_5000MBPS, | |||||
ICE_LINK_SPEED_10000MBPS, | |||||
ICE_LINK_SPEED_20000MBPS, | |||||
ICE_LINK_SPEED_25000MBPS, | |||||
ICE_LINK_SPEED_40000MBPS, | |||||
ICE_LINK_SPEED_50000MBPS, | |||||
ICE_LINK_SPEED_100000MBPS, /* BIT(10) */ | |||||
ICE_LINK_SPEED_UNKNOWN, | |||||
ICE_LINK_SPEED_UNKNOWN, | |||||
ICE_LINK_SPEED_UNKNOWN, | |||||
ICE_LINK_SPEED_UNKNOWN /* BIT(14) */ | |||||
}; | |||||
/** | |||||
* ice_get_link_speed - get integer speed from table | |||||
* @index: array index from fls(aq speed) - 1 | |||||
* | |||||
* Returns: u32 value containing integer speed | |||||
*/ | |||||
u32 ice_get_link_speed(u16 index) | |||||
{ | |||||
return ice_aq_to_link_speed[index]; | |||||
} | } | ||||
/** | /** | ||||
* ice_fw_supports_fec_dis_auto | * ice_fw_supports_fec_dis_auto | ||||
* @hw: pointer to the hardware structure | * @hw: pointer to the hardware structure | ||||
* | * | ||||
* Checks if the firmware supports FEC disable in Auto FEC mode | * Checks if the firmware supports FEC disable in Auto FEC mode | ||||
*/ | */ | ||||
Show All 21 Lines |