> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf Of
> Pawel Kaminski
> Sent: Friday, December 8, 2023 1:42 AM
> To: [email protected]
> Cc: Kitszel, Przemyslaw <[email protected]>;
> [email protected]; Kaminski, Pawel <[email protected]>;
> Wilczynski, Michal <[email protected]>
> Subject: [Intel-wired-lan] [PATCH iwl-next v2] ice: Add support for devlink
> loopback param.
> 
> Add support for driver-specific devlink loopback param. Supported values are
> "enabled", "disabled" and "prioritized". Default configuration is set to
> "enabled".
> 
> Add documentation in networking/devlink/ice.rst.
> 
> In previous generations of Intel NICs the trasmit scheduler was only limited 
> by
> PCIe bandwidth when scheduling/assigning hairpin-badwidth between VFs.
> Changes to E810 HW design introduced scheduler limitation, so that available
> hairpin-bandwidth is bound to external port speed.
> In order to address this limitation and enable NFV services such as "service
> chaining" a knob to adjust the scheduler config was created.
> Driver can send a configuration message to the FW over admin queue and
> internal FW logic will reconfigure HW to prioritize and add more BW to VF to
> VF traffic. As end result for example 10G port will no longer limit hairpin-
> badwith to 10G and much higher speeds can be achieved.
> 
> Devlink loopback param set to "prioritized" enables higher hairpin-badwitdh
> on related PFs. Configuration is applicable only to 8x10G and 4x25G cards.
> 
> 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 runtime
> 
> Co-developed-by: Michal Wilczynski <[email protected]>
> Signed-off-by: Michal Wilczynski <[email protected]>
> Reviewed-by: Przemek Kitszel <[email protected]>
> Signed-off-by: Pawel Kaminski <[email protected]>
> ---
> Changes in v2:
>  - improved commit message,
>  - added documentation change
>  - changed parameter devlink mode to "runtime"
>  - Link to v1: https://lore.kernel.org/all/20231201235949.62728-1-
> [email protected]/
> ---
>  Documentation/networking/devlink/ice.rst      |  15 ++
>  .../net/ethernet/intel/ice/ice_adminq_cmd.h   |  11 +-
>  drivers/net/ethernet/intel/ice/ice_common.c   |   6 +-
>  drivers/net/ethernet/intel/ice/ice_devlink.c  | 128 +++++++++++++++++-
>  drivers/net/ethernet/intel/ice/ice_type.h     |   1 +
>  5 files changed, 158 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/networking/devlink/ice.rst
> b/Documentation/networking/devlink/ice.rst
> index 7f30ebd5debb..efc6be109dc3 100644
> --- a/Documentation/networking/devlink/ice.rst
> +++ b/Documentation/networking/devlink/ice.rst
> @@ -11,6 +11,7 @@ Parameters
>  ==========
> 
>  .. list-table:: Generic parameters implemented
> +   :widths: 5 5 90
> 
>     * - Name
>       - Mode
> @@ -22,6 +23,20 @@ Parameters
>       - runtime
>       - mutually exclusive with ``enable_roce``
> 
> +.. list-table:: Driver specific parameters implemented
> +   :widths: 5 5 90
> +
> +   * - Name
> +     - Mode
> +     - Description
> +   * - ``loopback``
> +     - runtime
> +     - Controls loopback behavior by tuning scheduler bandwidth.
> +       Supported values are ``enabled``, ``disabled``, ``prioritized``.
> +       The latter allows for bandwidth higher than external port speed
> +       when looping back traffic between VFs. Works with 8x10G and 4x25G
> +       cards.
> +
>  Info versions
>  =============
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> index 6a5e974a1776..13d0e3cbc24c 100644
> --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
> @@ -230,6 +230,13 @@ struct ice_aqc_get_sw_cfg_resp_elem {
>  #define ICE_AQC_GET_SW_CONF_RESP_IS_VF               BIT(15)
>  };
> 
> +/* Loopback port parameter mode values. */ enum ice_loopback_mode {
> +     ICE_LOOPBACK_MODE_ENABLED = 0,
> +     ICE_LOOPBACK_MODE_DISABLED = 1,
> +     ICE_LOOPBACK_MODE_PRIORITIZED = 2,
> +};
> +
>  /* Set Port parameters, (direct, 0x0203) */  struct ice_aqc_set_port_params {
>       __le16 cmd_flags;
> @@ -238,7 +245,9 @@ struct ice_aqc_set_port_params {
>       __le16 swid;
>  #define ICE_AQC_PORT_SWID_VALID                      BIT(15)
>  #define ICE_AQC_PORT_SWID_M                  0xFF
> -     u8 reserved[10];
> +     u8 loopback_mode;
> +#define ICE_AQC_SET_P_PARAMS_LOOPBACK_MODE_VALID BIT(2)
> +     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 2f67ea1feb60..2efa781efcdb 100644
> --- a/drivers/net/ethernet/intel/ice/ice_common.c
> +++ b/drivers/net/ethernet/intel/ice/ice_common.c
> @@ -1019,7 +1019,7 @@ int ice_init_hw(struct ice_hw *hw)
>               status = -ENOMEM;
>               goto err_unroll_cqinit;
>       }
> -
> +     hw->port_info->loopback_mode = ICE_LOOPBACK_MODE_ENABLED;
>       /* set the back pointer to HW */
>       hw->port_info->hw = hw;
> 
> @@ -2962,6 +2962,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 65be56f2af9e..97182bacafa3 100644
> --- a/drivers/net/ethernet/intel/ice/ice_devlink.c
> +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
> @@ -1429,6 +1429,127 @@ ice_devlink_enable_iw_validate(struct devlink
> *devlink, u32 id,
>       return 0;
>  }
> 
> +#define DEVLINK_LPBK_DISABLED_STR "disabled"
> +#define DEVLINK_LPBK_ENABLED_STR "enabled"
> +#define DEVLINK_LPBK_PRIORITIZED_STR "prioritized"
> +
> +/**
> + * ice_devlink_loopback_mode_to_str - Get string for loopback mode.
> + * @mode: Loopback mode used in port_info struct.
> + *
> + * Return: Mode respective string or "Invalid".
> + */
> +static const char *ice_devlink_loopback_mode_to_str(enum
> +ice_loopback_mode mode) {
> +     switch (mode) {
> +     case ICE_LOOPBACK_MODE_ENABLED:
> +             return DEVLINK_LPBK_ENABLED_STR;
> +     case ICE_LOOPBACK_MODE_PRIORITIZED:
> +             return DEVLINK_LPBK_PRIORITIZED_STR;
> +     case ICE_LOOPBACK_MODE_DISABLED:
> +             return DEVLINK_LPBK_DISABLED_STR;
> +     }
> +
> +     return "Invalid";
> +}
> +
> +/**
> + * ice_devlink_loopback_str_to_mode - Get loopback mode from string
> name.
> + * @mode_str: Loopback mode string.
> + *
> + * Return: Mode value or negative number if invalid.
> + */
> +static int ice_devlink_loopback_str_to_mode(const char *mode_str) {
> +     if (!strcmp(mode_str, DEVLINK_LPBK_ENABLED_STR))
> +             return ICE_LOOPBACK_MODE_ENABLED;
> +     else if (!strcmp(mode_str, DEVLINK_LPBK_PRIORITIZED_STR))
> +             return ICE_LOOPBACK_MODE_PRIORITIZED;
> +     else if (!strcmp(mode_str, DEVLINK_LPBK_DISABLED_STR))
> +             return ICE_LOOPBACK_MODE_DISABLED;
> +
> +     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.
> + *
> + * Return: Zero.
> + */
> +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;
> +     const char *mode_str;
> +
> +     pi = pf->hw.port_info;
> +     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.
> + *
> + * Return: Zero.
> + */
> +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 device *dev = ice_pf_to_dev(pf);
> +     struct ice_port_info *pi;
> +
> +     pi = pf->hw.port_info;
> +     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.
> + *
> + * Return: 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_LOOPBACK,
> +};
> +
>  static const struct devlink_param ice_devlink_params[] = {
>       DEVLINK_PARAM_GENERIC(ENABLE_ROCE,
> BIT(DEVLINK_PARAM_CMODE_RUNTIME),
>                             ice_devlink_enable_roce_get,
> @@ -1438,7 +1559,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_LOOPBACK,
> +                          "loopback", DEVLINK_PARAM_TYPE_STRING,
> +                          BIT(DEVLINK_PARAM_CMODE_RUNTIME),
> +                          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 1fff865d0661..c8d75a1820a1 100644
> --- a/drivers/net/ethernet/intel/ice/ice_type.h
> +++ b/drivers/net/ethernet/intel/ice/ice_type.h
> @@ -713,6 +713,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
> 
> _______________________________________________
> Intel-wired-lan mailing list
> [email protected]
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan


Tested-by: Rafal Romanowski <[email protected]>



Reply via email to