[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231121012830.2261-1-pawel.kaminski@intel.com>
Date: Mon, 20 Nov 2023 17:28:30 -0800
From: Pawel Kaminski <pawel.kaminski@...el.com>
To: intel-wired-lan@...osl.org
Cc: netdev@...r.kernel.org,
Pawel Kaminski <pawel.kaminski@...el.com>,
Michal Wilczynski <michal.wilczynski@...el.com>
Subject: [PATCH iwl-next] ice: Add support for devlink loopback param.
Add support for devlink loopback param. Supported values are "enabled",
"disabled" and "prioritized". Default configuration is set to "enabled.
By default loopback traffic BW is locked to PF configured BW. HW is
capable of higher speeds on loopback traffic. Loopback param set to
"prioritized" enables HW BW prioritization for VF to VF traffic,
effectively increasing BW between VFs. Applicable to 8x10G and 4x25G
cards.
Recommendation for user:
- Make, as much as possible, fair distribution of loopback usages
between groups to gain maximal loopback BW.
- Try to dedicate ports for loopback only traffic, with minimal network
traffic.
Changing loopback configuration will trigger CORER reset in order to take
effect.
Example command to change current value:
devlink dev param set pci/0000:b2:00.3 name loopback value prioritized \
cmode permanent
Signed-off-by: Pawel Kaminski <pawel.kaminski@...el.com>
Co-developed-by: Michal Wilczynski <michal.wilczynski@...el.com>
Signed-off-by: Michal Wilczynski <michal.wilczynski@...el.com>
---
.../net/ethernet/intel/ice/ice_adminq_cmd.h | 7 +-
drivers/net/ethernet/intel/ice/ice_common.c | 7 +-
drivers/net/ethernet/intel/ice/ice_devlink.c | 127 +++++++++++++++++-
drivers/net/ethernet/intel/ice/ice_type.h | 1 +
4 files changed, 139 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 838d9b274d68..2f6b32b6bcdc 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -232,7 +232,12 @@ struct ice_aqc_set_port_params {
#define ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA BIT(2)
__le16 bad_frame_vsi;
__le16 swid;
- u8 reserved[10];
+ u8 loopback_mode;
+#define ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_VALID BIT(2)
+#define ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NORMAL 0x00
+#define ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NO 0x01
+#define ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_HIGH 0x02
+ u8 reserved[9];
};
/* These resource type defines are used for all switch resource
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 0157f6e98d3e..cb127c21cd42 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -1121,7 +1121,8 @@ int ice_init_hw(struct ice_hw *hw)
status = -ENOMEM;
goto err_unroll_cqinit;
}
-
+ hw->port_info->loopback_mode =
+ ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NORMAL;
/* set the back pointer to HW */
hw->port_info->hw = hw;
@@ -2924,6 +2925,10 @@ ice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
cmd = &desc.params.set_port_params;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_params);
+
+ cmd->loopback_mode = pi->loopback_mode |
+ ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_VALID;
+
if (double_vlan)
cmd_flags |= ICE_AQC_SET_P_PARAMS_DOUBLE_VLAN_ENA;
cmd->cmd_flags = cpu_to_le16(cmd_flags);
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index bc44cc220818..4475cce03967 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -1382,6 +1382,126 @@ ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
return 0;
}
+#define DEVLINK_LPBK_DISABLED "disabled"
+#define DEVLINK_LPBK_ENABLED "enabled"
+#define DEVLINK_LPBK_PRIORITIZED "prioritized"
+
+/**
+ * ice_devlink_loopback_mode_to_str - Get string for lpbk mode
+ * @loopback_mode: loopback_mode used in port_info struct
+ *
+ * Returns mode respective string or "Invalid".
+ */
+static const char *ice_devlink_loopback_mode_to_str(u32 loopback_mode)
+{
+ switch (loopback_mode) {
+ case ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NORMAL:
+ return DEVLINK_LPBK_ENABLED;
+ case ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_HIGH:
+ return DEVLINK_LPBK_PRIORITIZED;
+ case ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NO:
+ return DEVLINK_LPBK_DISABLED;
+ }
+
+ return "Invalid mode";
+}
+
+/**
+ * ice_devlink_loopback_str_to_mode - Get lpbk mode from string name
+ * @mode_str: loopback mode string
+ *
+ * Returns mode value or -1 if invalid.
+ */
+static int ice_devlink_loopback_str_to_mode(const char *mode_str)
+{
+ if (!strcmp(mode_str, DEVLINK_LPBK_ENABLED))
+ return ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NORMAL;
+ else if (!strcmp(mode_str, DEVLINK_LPBK_PRIORITIZED))
+ return ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_HIGH;
+ else if (!strcmp(mode_str, DEVLINK_LPBK_DISABLED))
+ return ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_NO;
+
+ return -EINVAL;
+}
+
+/**
+ * ice_devlink_loopback_get - Get loopback parameter
+ * @devlink: pointer to the devlink instance
+ * @id: the parameter ID to set
+ * @ctx: context to store the parameter value
+ *
+ * Returns zero on success.
+ */
+static int ice_devlink_loopback_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct ice_pf *pf = devlink_priv(devlink);
+ struct ice_port_info *pi = pf->hw.port_info;
+ const char *mode_str;
+
+ mode_str = ice_devlink_loopback_mode_to_str(pi->loopback_mode);
+ snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", mode_str);
+
+ return 0;
+}
+
+/**
+ * ice_devlink_loopback_set - Set loopback parameter
+ * @devlink: pointer to the devlink instance
+ * @id: the parameter ID to set
+ * @ctx: context to get the parameter value
+ *
+ * Returns zero on success.
+ */
+static int ice_devlink_loopback_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ int new_loopback_mode = ice_devlink_loopback_str_to_mode(ctx->val.vstr);
+ struct ice_pf *pf = devlink_priv(devlink);
+ struct ice_port_info *pi = pf->hw.port_info;
+ struct device *dev = ice_pf_to_dev(pf);
+
+ if (pi->loopback_mode != new_loopback_mode) {
+ pi->loopback_mode = new_loopback_mode;
+ dev_info(dev, "Setting loopback to %s\n", ctx->val.vstr);
+ ice_schedule_reset(pf, ICE_RESET_CORER);
+ }
+
+ return 0;
+}
+
+/**
+ * ice_devlink_loopback_validate - Validate passed loopback parameter value
+ * @devlink: unused pointer to devlink instance
+ * @id: the parameter ID to validate
+ * @val: value to validate
+ * @extack: netlink extended ACK structure
+ *
+ * Supported values are:
+ * "enabled" - loopback is enabled, "disabled" - loopback is disabled
+ * "prioritized" - loopback traffic is prioritized in scheduling
+ *
+ * Returns zero when passed parameter value is supported. Negative value on
+ * error.
+ */
+static int ice_devlink_loopback_validate(struct devlink *devlink, u32 id,
+ union devlink_param_value val,
+ struct netlink_ext_ack *extack)
+{
+ if (ice_devlink_loopback_str_to_mode(val.vstr) < 0) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Error: Requested value is not supported.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+enum ice_param_id {
+ ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+ ICE_DEVLINK_PARAM_ID_TX_LOOPBACK,
+};
+
static const struct devlink_param ice_devlink_params[] = {
DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
ice_devlink_enable_roce_get,
@@ -1391,7 +1511,12 @@ static const struct devlink_param ice_devlink_params[] = {
ice_devlink_enable_iw_get,
ice_devlink_enable_iw_set,
ice_devlink_enable_iw_validate),
-
+ DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_LOOPBACK,
+ "loopback", DEVLINK_PARAM_TYPE_STRING,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ ice_devlink_loopback_get,
+ ice_devlink_loopback_set,
+ ice_devlink_loopback_validate),
};
static void ice_devlink_free(void *devlink_ptr)
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index a09556e57803..822e44562302 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -700,6 +700,7 @@ struct ice_port_info {
u16 sw_id; /* Initial switch ID belongs to port */
u16 pf_vf_num;
u8 port_state;
+ u8 loopback_mode;
#define ICE_SCHED_PORT_STATE_INIT 0x0
#define ICE_SCHED_PORT_STATE_READY 0x1
u8 lport;
--
2.41.0
Powered by blists - more mailing lists