aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSlava Shwartsman <slavash@FreeBSD.org>2018-12-05 14:22:30 +0000
committerSlava Shwartsman <slavash@FreeBSD.org>2018-12-05 14:22:30 +0000
commit42390bb8840b1d9aeef1de60b09888294ddcf795 (patch)
tree215e02144c4c637d80e4a24733b7240b0e549bc3
parentf292a94d6ba0bf4a3b255f0574f2ae0aa471f34f (diff)
downloadsrc-42390bb8840b1d9aeef1de60b09888294ddcf795.tar.gz
src-42390bb8840b1d9aeef1de60b09888294ddcf795.zip
mlx5en: Add support for IFM_10G_LR and IFM_40G_ER4 media types.
Inspect the ethernet compliance code to figure out actual cable type by reading the PDDR module info register. Submitted by: hselasky@ Approved by: hselasky (mentor) MFC after: 1 week Sponsored by: Mellanox Technologies
Notes
Notes: svn path=/head/; revision=341581
-rw-r--r--sys/dev/mlx5/mlx5_core/mlx5_port.c36
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_main.c48
-rw-r--r--sys/dev/mlx5/mlx5_ifc.h109
-rw-r--r--sys/dev/mlx5/port.h2
4 files changed, 193 insertions, 2 deletions
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_port.c b/sys/dev/mlx5/mlx5_core/mlx5_port.c
index 0d8a2b9a48ce..e56f522105b4 100644
--- a/sys/dev/mlx5/mlx5_core/mlx5_port.c
+++ b/sys/dev/mlx5/mlx5_core/mlx5_port.c
@@ -1146,3 +1146,39 @@ out:
kfree(out);
return err;
}
+
+int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type)
+{
+ u32 pddr_reg[MLX5_ST_SZ_DW(pddr_reg)] = {};
+ int sz = MLX5_ST_SZ_BYTES(pddr_reg);
+ int error;
+ u8 ecc;
+ u8 ci;
+
+ MLX5_SET(pddr_reg, pddr_reg, local_port, local_port);
+ MLX5_SET(pddr_reg, pddr_reg, page_select, 3 /* module info page */);
+
+ error = mlx5_core_access_reg(mdev, pddr_reg, sz, pddr_reg, sz,
+ MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR, 0, 0);
+ if (error != 0)
+ return (error);
+
+ ecc = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.ethernet_compliance_code);
+ ci = MLX5_GET(pddr_reg, pddr_reg, page_data.pddr_module_info.cable_identifier);
+
+ switch (ci) {
+ case 0: /* QSFP28 */
+ case 1: /* QSFP+ */
+ *is_er_type = 0;
+ break;
+ case 2: /* SFP28/SFP+ */
+ case 3: /* QSA (QSFP->SFP) */
+ *is_er_type = ((ecc & (1 << 7)) != 0);
+ break;
+ default:
+ *is_er_type = 0;
+ break;
+ }
+ return (0);
+}
+EXPORT_SYMBOL_GPL(mlx5_query_pddr_range_info);
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
index 429bb0e3b481..0cc4a27878de 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -169,6 +169,7 @@ mlx5e_update_carrier(struct mlx5e_priv *priv)
u32 eth_proto_oper;
int error;
u8 port_state;
+ u8 is_er_type;
u8 i;
port_state = mlx5_query_vport_state(mdev,
@@ -197,10 +198,33 @@ mlx5e_update_carrier(struct mlx5e_priv *priv)
if (mlx5e_mode_table[i].baudrate == 0)
continue;
if (MLX5E_PROT_MASK(i) & eth_proto_oper) {
+ u32 subtype = mlx5e_mode_table[i].subtype;
+
priv->ifp->if_baudrate =
mlx5e_mode_table[i].baudrate;
- priv->media_active_last =
- mlx5e_mode_table[i].subtype | IFM_ETHER | IFM_FDX;
+
+ switch (subtype) {
+ case IFM_10G_ER:
+ error = mlx5_query_pddr_range_info(mdev, 1, &is_er_type);
+ if (error != 0) {
+ if_printf(priv->ifp, "%s: query port pddr failed: %d\n",
+ __func__, error);
+ }
+ if (error != 0 || is_er_type == 0)
+ subtype = IFM_10G_LR;
+ break;
+ case IFM_40G_LR4:
+ error = mlx5_query_pddr_range_info(mdev, 1, &is_er_type);
+ if (error != 0) {
+ if_printf(priv->ifp, "%s: query port pddr failed: %d\n",
+ __func__, error);
+ }
+ if (error == 0 && is_er_type != 0)
+ subtype = IFM_40G_ER4;
+ break;
+ }
+ priv->media_active_last = subtype | IFM_ETHER | IFM_FDX;
+ break;
}
}
if_link_state_change(priv->ifp, LINK_STATE_UP);
@@ -224,6 +248,15 @@ mlx5e_find_link_mode(u32 subtype)
u32 i;
u32 link_mode = 0;
+ switch (subtype) {
+ case IFM_10G_LR:
+ subtype = IFM_10G_ER;
+ break;
+ case IFM_40G_ER4:
+ subtype = IFM_40G_LR4;
+ break;
+ }
+
for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
if (mlx5e_mode_table[i].baudrate == 0)
continue;
@@ -3724,6 +3757,17 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
}
}
+ /* Additional supported medias */
+ ifmedia_add(&priv->media, IFM_10G_LR | IFM_ETHER, 0, NULL);
+ ifmedia_add(&priv->media, IFM_10G_LR |
+ IFM_ETHER | IFM_FDX |
+ IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE, 0, NULL);
+
+ ifmedia_add(&priv->media, IFM_40G_ER4 | IFM_ETHER, 0, NULL);
+ ifmedia_add(&priv->media, IFM_40G_ER4 |
+ IFM_ETHER | IFM_FDX |
+ IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE, 0, NULL);
+
ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO | IFM_FDX |
IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE, 0, NULL);
diff --git a/sys/dev/mlx5/mlx5_ifc.h b/sys/dev/mlx5/mlx5_ifc.h
index 473efa4e1296..e3a80ef7c0db 100644
--- a/sys/dev/mlx5/mlx5_ifc.h
+++ b/sys/dev/mlx5/mlx5_ifc.h
@@ -755,6 +755,115 @@ struct mlx5_ifc_flow_table_nic_cap_bits {
u8 reserved_1[0x7200];
};
+enum {
+ MLX5_ACCESS_REG_SUMMARY_CTRL_ID_PDDR = 0x5031,
+};
+
+struct mlx5_ifc_pddr_module_info_bits {
+ u8 cable_technology[0x8];
+ u8 cable_breakout[0x8];
+ u8 ext_ethernet_compliance_code[0x8];
+ u8 ethernet_compliance_code[0x8];
+
+ u8 cable_type[0x4];
+ u8 cable_vendor[0x4];
+ u8 cable_length[0x8];
+ u8 cable_identifier[0x8];
+ u8 cable_power_class[0x8];
+
+ u8 reserved_at_40[0x8];
+ u8 cable_rx_amp[0x8];
+ u8 cable_rx_emphasis[0x8];
+ u8 cable_tx_equalization[0x8];
+
+ u8 reserved_at_60[0x8];
+ u8 cable_attenuation_12g[0x8];
+ u8 cable_attenuation_7g[0x8];
+ u8 cable_attenuation_5g[0x8];
+
+ u8 reserved_at_80[0x8];
+ u8 rx_cdr_cap[0x4];
+ u8 tx_cdr_cap[0x4];
+ u8 reserved_at_90[0x4];
+ u8 rx_cdr_state[0x4];
+ u8 reserved_at_98[0x4];
+ u8 tx_cdr_state[0x4];
+
+ u8 vendor_name[16][0x8];
+
+ u8 vendor_pn[16][0x8];
+
+ u8 vendor_rev[0x20];
+
+ u8 fw_version[0x20];
+
+ u8 vendor_sn[16][0x8];
+
+ u8 temperature[0x10];
+ u8 voltage[0x10];
+
+ u8 rx_power_lane0[0x10];
+ u8 rx_power_lane1[0x10];
+
+ u8 rx_power_lane2[0x10];
+ u8 rx_power_lane3[0x10];
+
+ u8 reserved_at_2c0[0x40];
+
+ u8 tx_power_lane0[0x10];
+ u8 tx_power_lane1[0x10];
+
+ u8 tx_power_lane2[0x10];
+ u8 tx_power_lane3[0x10];
+
+ u8 reserved_at_340[0x40];
+
+ u8 tx_bias_lane0[0x10];
+ u8 tx_bias_lane1[0x10];
+
+ u8 tx_bias_lane2[0x10];
+ u8 tx_bias_lane3[0x10];
+
+ u8 reserved_at_3c0[0x40];
+
+ u8 temperature_high_th[0x10];
+ u8 temperature_low_th[0x10];
+
+ u8 voltage_high_th[0x10];
+ u8 voltage_low_th[0x10];
+
+ u8 rx_power_high_th[0x10];
+ u8 rx_power_low_th[0x10];
+
+ u8 tx_power_high_th[0x10];
+ u8 tx_power_low_th[0x10];
+
+ u8 tx_bias_high_th[0x10];
+ u8 tx_bias_low_th[0x10];
+
+ u8 reserved_at_4a0[0x10];
+ u8 wavelength[0x10];
+
+ u8 reserved_at_4c0[0x300];
+};
+
+union mlx5_ifc_pddr_operation_info_page_pddr_phy_info_page_pddr_troubleshooting_page_pddr_module_info_auto_bits {
+ struct mlx5_ifc_pddr_module_info_bits pddr_module_info;
+ u8 reserved_at_0[0x7c0];
+};
+
+struct mlx5_ifc_pddr_reg_bits {
+ u8 reserved_at_0[0x8];
+ u8 local_port[0x8];
+ u8 pnat[0x2];
+ u8 reserved_at_12[0xe];
+
+ u8 reserved_at_20[0x18];
+ u8 page_select[0x8];
+
+ union mlx5_ifc_pddr_operation_info_page_pddr_phy_info_page_pddr_troubleshooting_page_pddr_module_info_auto_bits page_data;
+};
+
struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
u8 csum_cap[0x1];
u8 vlan_cap[0x1];
diff --git a/sys/dev/mlx5/port.h b/sys/dev/mlx5/port.h
index 38924eeedf46..1007bb471bd5 100644
--- a/sys/dev/mlx5/port.h
+++ b/sys/dev/mlx5/port.h
@@ -174,4 +174,6 @@ int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state);
int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, const u8 *dscp2prio);
int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio);
+int mlx5_query_pddr_range_info(struct mlx5_core_dev *mdev, u8 local_port, u8 *is_er_type);
+
#endif /* __MLX5_PORT_H__ */