mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 13:23:02 -04:00
Merge branch 'devlink-add-generic-device-max_sfs-parameter'
Tariq Toukan says: ==================== devlink: add generic device max_sfs parameter This series by Nikolay introduces a new generic devlink device parameter, max_sfs, to control the number of light-weight NIC subfunctions (SFs) that can be created on a device. The first patch adds the generic devlink parameter and infrastructure support. The second patch implements support for the parameter in the mlx5 driver. With this addition, users can enable or disable SF creation directly via devlink, without relying on external vendor-specific tools. ==================== Link: https://patch.msgid.link/20260806073037.3001886-1-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -165,3 +165,9 @@ own name.
|
||||
- u32
|
||||
- Controls the maximum number of MAC address filters that can be assigned
|
||||
to a Virtual Function (VF).
|
||||
* - ``max_sfs``
|
||||
- u32
|
||||
- The maximum number of subfunctions which can be created on the device.
|
||||
Modifying this parameter may require a device restart and PCI bus
|
||||
rescanning because the BAR layout may change. A value of 0 disables
|
||||
subfunction creation.
|
||||
|
||||
@@ -45,8 +45,13 @@ Parameters
|
||||
- The range is between 1 and a device-specific max.
|
||||
- Applies to each physical function (PF) independently, if the device
|
||||
supports it. Otherwise, it applies symmetrically to all PFs.
|
||||
* - ``max_sfs``
|
||||
- permanent
|
||||
- The range is between 0 and a device-specific max.
|
||||
- Applies to each physical function (PF) independently.
|
||||
|
||||
Note: permanent parameters such as ``enable_sriov`` and ``total_vfs`` require FW reset to take effect
|
||||
Note: permanent parameters such as ``enable_sriov``, ``total_vfs`` and ``max_sfs``
|
||||
require FW reset to take effect
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
||||
@@ -68,7 +68,9 @@ struct mlx5_ifc_mnvda_reg_bits {
|
||||
|
||||
struct mlx5_ifc_nv_global_pci_conf_bits {
|
||||
u8 sriov_valid[0x1];
|
||||
u8 reserved_at_1[0x10];
|
||||
u8 reserved_at_1[0xa];
|
||||
u8 per_pf_num_sf[0x1];
|
||||
u8 reserved_at_c[0x5];
|
||||
u8 per_pf_total_vf[0x1];
|
||||
u8 reserved_at_12[0xe];
|
||||
|
||||
@@ -93,9 +95,11 @@ struct mlx5_ifc_nv_global_pci_cap_bits {
|
||||
};
|
||||
|
||||
struct mlx5_ifc_nv_pf_pci_conf_bits {
|
||||
u8 reserved_at_0[0x9];
|
||||
u8 log_sf_bar_size[0x8];
|
||||
u8 pf_total_sf_en[0x1];
|
||||
u8 pf_total_vf_en[0x1];
|
||||
u8 reserved_at_a[0x16];
|
||||
u8 reserved_at_a[0x6];
|
||||
u8 total_sf[0x10];
|
||||
|
||||
u8 reserved_at_20[0x20];
|
||||
|
||||
@@ -158,6 +162,8 @@ struct mlx5_ifc_nv_sw_accelerate_conf_bits {
|
||||
#define MLX5_GET_CFG_HDR_LEN(_mnvda_ptr) \
|
||||
MLX5_GET(mnvda_reg, _mnvda_ptr, configuration_item_header.length)
|
||||
|
||||
#define MLX5_DEFAULT_LOG_SF_BAR_SIZE 12
|
||||
|
||||
static int mlx5_nv_param_read(struct mlx5_core_dev *dev, void *mnvda,
|
||||
size_t len)
|
||||
{
|
||||
@@ -755,6 +761,115 @@ static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_devlink_max_sfs_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
|
||||
void *data;
|
||||
int err;
|
||||
|
||||
err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Failed to read global PCI configuration");
|
||||
return err;
|
||||
}
|
||||
|
||||
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
|
||||
if (!MLX5_GET(nv_global_pci_conf, data, per_pf_num_sf)) {
|
||||
ctx->val.vu32 = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(mnvda, 0, sizeof(mnvda));
|
||||
err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to read PF configuration");
|
||||
return err;
|
||||
}
|
||||
|
||||
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
|
||||
if (MLX5_GET(nv_pf_pci_conf, data, pf_total_sf_en))
|
||||
ctx->val.vu32 = MLX5_GET(nv_pf_pci_conf, data, total_sf);
|
||||
else
|
||||
ctx->val.vu32 = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_devlink_max_sfs_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (val->vu32 > U16_MAX) {
|
||||
NL_SET_ERR_MSG_FMT_MOD(extack,
|
||||
"Max SFs allowed value is %u", U16_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_devlink_max_sfs_set(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
|
||||
void *data;
|
||||
int err;
|
||||
|
||||
/* we don't explicitly disable per_pf_num_sf when max_sfs is 0 because
|
||||
* another PF may be using SFs
|
||||
*/
|
||||
if (ctx->val.vu32) {
|
||||
err = mlx5_nv_param_read_global_pci_conf(dev, mnvda,
|
||||
sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Failed to read global PCI configuration");
|
||||
return err;
|
||||
}
|
||||
|
||||
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
|
||||
/* always enable per_pf_num_sf because another PF may use SFs */
|
||||
MLX5_SET(nv_global_pci_conf, data, per_pf_num_sf, 1);
|
||||
|
||||
err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Failed to change per_pf_num_sf global PCI configuration");
|
||||
return err;
|
||||
}
|
||||
memset(mnvda, 0, sizeof(mnvda));
|
||||
}
|
||||
|
||||
err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to read PF configuration");
|
||||
return err;
|
||||
}
|
||||
|
||||
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
|
||||
MLX5_SET(nv_pf_pci_conf, data, log_sf_bar_size,
|
||||
ctx->val.vu32 ? MLX5_DEFAULT_LOG_SF_BAR_SIZE : 0);
|
||||
MLX5_SET(nv_pf_pci_conf, data, pf_total_sf_en, !!ctx->val.vu32);
|
||||
MLX5_SET(nv_pf_pci_conf, data, total_sf, ctx->val.vu32);
|
||||
|
||||
err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Failed to change PF PCI configuration");
|
||||
return err;
|
||||
}
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Modifying max_sfs requires a FW reset and PCI bus rescan");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_param mlx5_nv_param_devlink_params[] = {
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
mlx5_devlink_enable_sriov_get,
|
||||
@@ -763,6 +878,10 @@ static const struct devlink_param mlx5_nv_param_devlink_params[] = {
|
||||
mlx5_devlink_total_vfs_get,
|
||||
mlx5_devlink_total_vfs_set,
|
||||
mlx5_devlink_total_vfs_validate),
|
||||
DEVLINK_PARAM_GENERIC(MAX_SFS, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
mlx5_devlink_max_sfs_get,
|
||||
mlx5_devlink_max_sfs_set,
|
||||
mlx5_devlink_max_sfs_validate),
|
||||
DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_CQE_COMPRESSION_TYPE,
|
||||
"cqe_compress_type", DEVLINK_PARAM_TYPE_STRING,
|
||||
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
|
||||
|
||||
@@ -554,6 +554,7 @@ enum devlink_param_generic_id {
|
||||
DEVLINK_PARAM_GENERIC_ID_TOTAL_VFS,
|
||||
DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS,
|
||||
DEVLINK_PARAM_GENERIC_ID_MAX_MAC_PER_VF,
|
||||
DEVLINK_PARAM_GENERIC_ID_MAX_SFS,
|
||||
|
||||
/* add new param generic ids above here*/
|
||||
__DEVLINK_PARAM_GENERIC_ID_MAX,
|
||||
@@ -627,6 +628,9 @@ enum devlink_param_generic_id {
|
||||
#define DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_NAME "max_mac_per_vf"
|
||||
#define DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_TYPE DEVLINK_PARAM_TYPE_U32
|
||||
|
||||
#define DEVLINK_PARAM_GENERIC_MAX_SFS_NAME "max_sfs"
|
||||
#define DEVLINK_PARAM_GENERIC_MAX_SFS_TYPE DEVLINK_PARAM_TYPE_U32
|
||||
|
||||
#define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \
|
||||
{ \
|
||||
.id = DEVLINK_PARAM_GENERIC_ID_##_id, \
|
||||
|
||||
@@ -117,6 +117,11 @@ static const struct devlink_param devlink_param_generic[] = {
|
||||
.name = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_NAME,
|
||||
.type = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_TYPE,
|
||||
},
|
||||
{
|
||||
.id = DEVLINK_PARAM_GENERIC_ID_MAX_SFS,
|
||||
.name = DEVLINK_PARAM_GENERIC_MAX_SFS_NAME,
|
||||
.type = DEVLINK_PARAM_GENERIC_MAX_SFS_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static int devlink_param_generic_verify(const struct devlink_param *param)
|
||||
|
||||
Reference in New Issue
Block a user