Skip to content

Commit 58f9416

Browse files
committed
Merge branch 'ice-support-to-dump-phy-config-fec'
Tony Nguyen says: ==================== ice: Support to dump PHY config, FEC Anil Samal says: Implementation to dump PHY configuration and FEC statistics to facilitate link level debugging of customer issues. Implementation has two parts a. Serdes equalization # ethtool -d eth0 Output: Offset Values ------ ------ 0x0000: 00 00 00 00 03 00 00 00 05 00 00 00 01 08 00 40 0x0010: 01 00 00 40 00 00 39 3c 01 00 00 00 00 00 00 00 0x0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 0x01f0: 01 00 00 00 ef be ad de 8f 00 00 00 00 00 00 00 0x0200: 00 00 00 00 ef be ad de 00 00 00 00 00 00 00 00 0x0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0230: 00 00 00 00 00 00 00 00 00 00 00 00 fa ff 00 00 0x0240: 06 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 0x0250: 0f b0 0f b0 00 00 00 00 00 00 00 00 00 00 00 00 0x0260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x02a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x02b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x02c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x02d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x02e0: 00 00 00 00 00 00 00 00 00 00 00 00 Current implementation appends 176 bytes i.e. 44 bytes * 4 serdes lane. For port with 2 serdes lane, first 88 bytes are valid values and remaining 88 bytes are filled with zero. Similarly for port with 1 serdes lane, first 44 bytes are valid and remaining 132 bytes are marked zero. Each set of serdes equalizer parameter (i.e. set of 44 bytes) follows below order a. rx_equalization_pre2 b. rx_equalization_pre1 c. rx_equalization_post1 d. rx_equalization_bflf e. rx_equalization_bfhf f. rx_equalization_drate g. tx_equalization_pre1 h. tx_equalization_pre3 i. tx_equalization_atten j. tx_equalization_post1 k. tx_equalization_pre2 Where each individual equalizer parameter is of 4 bytes. As ethtool prints values as individual bytes, for little endian machine these values will be in reverse byte order. b. FEC block counts # ethtool -I --show-fec eth0 Output: FEC parameters for eth0: Supported/Configured FEC encodings: Auto RS BaseR Active FEC encoding: RS Statistics: corrected_blocks: 0 uncorrectable_blocks: 0 This series do following: Patch 1 - Implementation to support user provided flag for side band queue command. Patch 2 - Currently driver does not have a way to derive serdes lane number, pcs quad , pcs port from port number. So we introduced a mechanism to derive above info. Ethtool interface extension to include FEC statistics counter. Patch 3 - Ethtool interface extension to include serdes equalizer output. v1: https://lore.kernel.org/netdev/[email protected]/ ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents d00ba1d + 7083893 commit 58f9416

File tree

7 files changed

+662
-15
lines changed

7 files changed

+662
-15
lines changed

drivers/net/ethernet/intel/ice/ice_adminq_cmd.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,55 @@ struct ice_aqc_get_sensor_reading_resp {
14611461
} data;
14621462
};
14631463

1464+
/* DNL call command (indirect 0x0682)
1465+
* Struct is used for both command and response
1466+
*/
1467+
struct ice_aqc_dnl_call_command {
1468+
u8 ctx; /* Used in command, reserved in response */
1469+
u8 reserved;
1470+
__le16 activity_id;
1471+
#define ICE_AQC_ACT_ID_DNL 0x1129
1472+
__le32 reserved1;
1473+
__le32 addr_high;
1474+
__le32 addr_low;
1475+
};
1476+
1477+
struct ice_aqc_dnl_equa_param {
1478+
__le16 data_in;
1479+
#define ICE_AQC_RX_EQU_SHIFT 8
1480+
#define ICE_AQC_RX_EQU_PRE2 (0x10 << ICE_AQC_RX_EQU_SHIFT)
1481+
#define ICE_AQC_RX_EQU_PRE1 (0x11 << ICE_AQC_RX_EQU_SHIFT)
1482+
#define ICE_AQC_RX_EQU_POST1 (0x12 << ICE_AQC_RX_EQU_SHIFT)
1483+
#define ICE_AQC_RX_EQU_BFLF (0x13 << ICE_AQC_RX_EQU_SHIFT)
1484+
#define ICE_AQC_RX_EQU_BFHF (0x14 << ICE_AQC_RX_EQU_SHIFT)
1485+
#define ICE_AQC_RX_EQU_DRATE (0x15 << ICE_AQC_RX_EQU_SHIFT)
1486+
#define ICE_AQC_TX_EQU_PRE1 0x0
1487+
#define ICE_AQC_TX_EQU_PRE3 0x3
1488+
#define ICE_AQC_TX_EQU_ATTEN 0x4
1489+
#define ICE_AQC_TX_EQU_POST1 0x8
1490+
#define ICE_AQC_TX_EQU_PRE2 0xC
1491+
__le16 op_code_serdes_sel;
1492+
#define ICE_AQC_OP_CODE_SHIFT 4
1493+
#define ICE_AQC_OP_CODE_RX_EQU (0x9 << ICE_AQC_OP_CODE_SHIFT)
1494+
#define ICE_AQC_OP_CODE_TX_EQU (0x10 << ICE_AQC_OP_CODE_SHIFT)
1495+
__le32 reserved[3];
1496+
};
1497+
1498+
struct ice_aqc_dnl_equa_respon {
1499+
/* Equalization value can be negative */
1500+
int val;
1501+
__le32 reserved[3];
1502+
};
1503+
1504+
/* DNL call command/response buffer (indirect 0x0682) */
1505+
struct ice_aqc_dnl_call {
1506+
union {
1507+
struct ice_aqc_dnl_equa_param txrx_equa_reqs;
1508+
__le32 stores[4];
1509+
struct ice_aqc_dnl_equa_respon txrx_equa_resp;
1510+
} sto;
1511+
};
1512+
14641513
struct ice_aqc_link_topo_params {
14651514
u8 lport_num;
14661515
u8 lport_num_valid;
@@ -2564,6 +2613,7 @@ struct ice_aq_desc {
25642613
struct ice_aqc_get_link_status get_link_status;
25652614
struct ice_aqc_event_lan_overflow lan_overflow;
25662615
struct ice_aqc_get_link_topo get_link_topo;
2616+
struct ice_aqc_dnl_call_command dnl_call;
25672617
struct ice_aqc_i2c read_write_i2c;
25682618
struct ice_aqc_read_i2c_resp read_i2c_resp;
25692619
struct ice_aqc_get_set_tx_topo get_set_tx_topo;
@@ -2688,6 +2738,7 @@ enum ice_adminq_opc {
26882738
ice_aqc_opc_set_phy_rec_clk_out = 0x0630,
26892739
ice_aqc_opc_get_phy_rec_clk_out = 0x0631,
26902740
ice_aqc_opc_get_sensor_reading = 0x0632,
2741+
ice_aqc_opc_dnl_call = 0x0682,
26912742
ice_aqc_opc_get_link_topo = 0x06E0,
26922743
ice_aqc_opc_read_i2c = 0x06E2,
26932744
ice_aqc_opc_write_i2c = 0x06E3,

drivers/net/ethernet/intel/ice/ice_common.c

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,8 +1497,9 @@ ice_sbq_send_cmd(struct ice_hw *hw, struct ice_sbq_cmd_desc *desc,
14971497
* ice_sbq_rw_reg - Fill Sideband Queue command
14981498
* @hw: pointer to the HW struct
14991499
* @in: message info to be filled in descriptor
1500+
* @flags: control queue descriptor flags
15001501
*/
1501-
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
1502+
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flags)
15021503
{
15031504
struct ice_sbq_cmd_desc desc = {0};
15041505
struct ice_sbq_msg_req msg = {0};
@@ -1522,7 +1523,7 @@ int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in)
15221523
*/
15231524
msg_len -= sizeof(msg.data);
15241525

1525-
desc.flags = cpu_to_le16(ICE_AQ_FLAG_RD);
1526+
desc.flags = cpu_to_le16(flags);
15261527
desc.opcode = cpu_to_le16(ice_sbq_opc_neigh_dev_req);
15271528
desc.param0.cmd_len = cpu_to_le16(msg_len);
15281529
status = ice_sbq_send_cmd(hw, &desc, &msg, msg_len, NULL);
@@ -3370,6 +3371,100 @@ int ice_update_link_info(struct ice_port_info *pi)
33703371
return status;
33713372
}
33723373

3374+
/**
3375+
* ice_aq_get_phy_equalization - function to read serdes equaliser
3376+
* value from firmware using admin queue command.
3377+
* @hw: pointer to the HW struct
3378+
* @data_in: represents the serdes equalization parameter requested
3379+
* @op_code: represents the serdes number and flag to represent tx or rx
3380+
* @serdes_num: represents the serdes number
3381+
* @output: pointer to the caller-supplied buffer to return serdes equaliser
3382+
*
3383+
* Return: non-zero status on error and 0 on success.
3384+
*/
3385+
int ice_aq_get_phy_equalization(struct ice_hw *hw, u16 data_in, u16 op_code,
3386+
u8 serdes_num, int *output)
3387+
{
3388+
struct ice_aqc_dnl_call_command *cmd;
3389+
struct ice_aqc_dnl_call buf = {};
3390+
struct ice_aq_desc desc;
3391+
int err;
3392+
3393+
buf.sto.txrx_equa_reqs.data_in = cpu_to_le16(data_in);
3394+
buf.sto.txrx_equa_reqs.op_code_serdes_sel =
3395+
cpu_to_le16(op_code | (serdes_num & 0xF));
3396+
cmd = &desc.params.dnl_call;
3397+
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dnl_call);
3398+
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_BUF |
3399+
ICE_AQ_FLAG_RD |
3400+
ICE_AQ_FLAG_SI);
3401+
desc.datalen = cpu_to_le16(sizeof(struct ice_aqc_dnl_call));
3402+
cmd->activity_id = cpu_to_le16(ICE_AQC_ACT_ID_DNL);
3403+
3404+
err = ice_aq_send_cmd(hw, &desc, &buf, sizeof(struct ice_aqc_dnl_call),
3405+
NULL);
3406+
*output = err ? 0 : buf.sto.txrx_equa_resp.val;
3407+
3408+
return err;
3409+
}
3410+
3411+
#define FEC_REG_PORT(port) { \
3412+
FEC_CORR_LOW_REG_PORT##port, \
3413+
FEC_CORR_HIGH_REG_PORT##port, \
3414+
FEC_UNCORR_LOW_REG_PORT##port, \
3415+
FEC_UNCORR_HIGH_REG_PORT##port, \
3416+
}
3417+
3418+
static const u32 fec_reg[][ICE_FEC_MAX] = {
3419+
FEC_REG_PORT(0),
3420+
FEC_REG_PORT(1),
3421+
FEC_REG_PORT(2),
3422+
FEC_REG_PORT(3)
3423+
};
3424+
3425+
/**
3426+
* ice_aq_get_fec_stats - reads fec stats from phy
3427+
* @hw: pointer to the HW struct
3428+
* @pcs_quad: represents pcsquad of user input serdes
3429+
* @pcs_port: represents the pcs port number part of above pcs quad
3430+
* @fec_type: represents FEC stats type
3431+
* @output: pointer to the caller-supplied buffer to return requested fec stats
3432+
*
3433+
* Return: non-zero status on error and 0 on success.
3434+
*/
3435+
int ice_aq_get_fec_stats(struct ice_hw *hw, u16 pcs_quad, u16 pcs_port,
3436+
enum ice_fec_stats_types fec_type, u32 *output)
3437+
{
3438+
u16 flag = (ICE_AQ_FLAG_RD | ICE_AQ_FLAG_BUF | ICE_AQ_FLAG_SI);
3439+
struct ice_sbq_msg_input msg = {};
3440+
u32 receiver_id, reg_offset;
3441+
int err;
3442+
3443+
if (pcs_port > 3)
3444+
return -EINVAL;
3445+
3446+
reg_offset = fec_reg[pcs_port][fec_type];
3447+
3448+
if (pcs_quad == 0)
3449+
receiver_id = FEC_RECEIVER_ID_PCS0;
3450+
else if (pcs_quad == 1)
3451+
receiver_id = FEC_RECEIVER_ID_PCS1;
3452+
else
3453+
return -EINVAL;
3454+
3455+
msg.msg_addr_low = lower_16_bits(reg_offset);
3456+
msg.msg_addr_high = receiver_id;
3457+
msg.opcode = ice_sbq_msg_rd;
3458+
msg.dest_dev = rmn_0;
3459+
3460+
err = ice_sbq_rw_reg(hw, &msg, flag);
3461+
if (err)
3462+
return err;
3463+
3464+
*output = msg.data;
3465+
return 0;
3466+
}
3467+
33733468
/**
33743469
* ice_cache_phy_user_req
33753470
* @pi: port information structure

drivers/net/ethernet/intel/ice/ice_common.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@
1717
#define ICE_SQ_SEND_DELAY_TIME_MS 10
1818
#define ICE_SQ_SEND_MAX_EXECUTE 3
1919

20+
#define FEC_REG_SHIFT 2
21+
#define FEC_RECV_ID_SHIFT 4
22+
#define FEC_CORR_LOW_REG_PORT0 (0x02 << FEC_REG_SHIFT)
23+
#define FEC_CORR_HIGH_REG_PORT0 (0x03 << FEC_REG_SHIFT)
24+
#define FEC_UNCORR_LOW_REG_PORT0 (0x04 << FEC_REG_SHIFT)
25+
#define FEC_UNCORR_HIGH_REG_PORT0 (0x05 << FEC_REG_SHIFT)
26+
#define FEC_CORR_LOW_REG_PORT1 (0x42 << FEC_REG_SHIFT)
27+
#define FEC_CORR_HIGH_REG_PORT1 (0x43 << FEC_REG_SHIFT)
28+
#define FEC_UNCORR_LOW_REG_PORT1 (0x44 << FEC_REG_SHIFT)
29+
#define FEC_UNCORR_HIGH_REG_PORT1 (0x45 << FEC_REG_SHIFT)
30+
#define FEC_CORR_LOW_REG_PORT2 (0x4A << FEC_REG_SHIFT)
31+
#define FEC_CORR_HIGH_REG_PORT2 (0x4B << FEC_REG_SHIFT)
32+
#define FEC_UNCORR_LOW_REG_PORT2 (0x4C << FEC_REG_SHIFT)
33+
#define FEC_UNCORR_HIGH_REG_PORT2 (0x4D << FEC_REG_SHIFT)
34+
#define FEC_CORR_LOW_REG_PORT3 (0x52 << FEC_REG_SHIFT)
35+
#define FEC_CORR_HIGH_REG_PORT3 (0x53 << FEC_REG_SHIFT)
36+
#define FEC_UNCORR_LOW_REG_PORT3 (0x54 << FEC_REG_SHIFT)
37+
#define FEC_UNCORR_HIGH_REG_PORT3 (0x55 << FEC_REG_SHIFT)
38+
#define FEC_RECEIVER_ID_PCS0 (0x33 << FEC_RECV_ID_SHIFT)
39+
#define FEC_RECEIVER_ID_PCS1 (0x34 << FEC_RECV_ID_SHIFT)
40+
2041
int ice_init_hw(struct ice_hw *hw);
2142
void ice_deinit_hw(struct ice_hw *hw);
2243
int ice_check_reset(struct ice_hw *hw);
@@ -121,6 +142,11 @@ int
121142
ice_get_link_default_override(struct ice_link_default_override_tlv *ldo,
122143
struct ice_port_info *pi);
123144
bool ice_is_phy_caps_an_enabled(struct ice_aqc_get_phy_caps_data *caps);
145+
int ice_aq_get_phy_equalization(struct ice_hw *hw, u16 data_in, u16 op_code,
146+
u8 serdes_num, int *output);
147+
int
148+
ice_aq_get_fec_stats(struct ice_hw *hw, u16 pcs_quad, u16 pcs_port,
149+
enum ice_fec_stats_types fec_type, u32 *output);
124150

125151
enum ice_fc_mode ice_caps_to_fc_mode(u8 caps);
126152
enum ice_fec_mode ice_caps_to_fec_mode(u8 caps, u8 fec_options);
@@ -201,7 +227,7 @@ int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle);
201227
void ice_replay_post(struct ice_hw *hw);
202228
struct ice_q_ctx *
203229
ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle);
204-
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in);
230+
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flag);
205231
int
206232
ice_aq_get_cgu_abilities(struct ice_hw *hw,
207233
struct ice_aqc_get_cgu_abilities *abilities);

0 commit comments

Comments
 (0)