Skip to content

Commit

Permalink
Merge branch 'Expose-port-split-attributes'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
Expose port split attributes

Danielle says:

Currently, user space has no way of knowing if a port can be split and
into how many ports. Among other things, this makes it impossible to
write generic tests for port split functionality.

Therefore, this set exposes two new devlink port attributes to user
space: Number of lanes and whether the port can be split or not.

Patch set overview:

Patches #1-#4 cleanup 'struct devlink_port_attrs' and reduce the number
of parameters passed between drivers and devlink via
devlink_port_attrs_set()

Patch #5 adds devlink port lanes attributes

Patches #6-#7 add devlink port splittable attribute

Patch #8 exploits the fact that devlink is now aware of port's number of
lanes and whether the port can be split or not and moves some checks
from drivers to devlink

Patch #9 adds a port split test

Changes since v2:
* Remove some local variables from patch #3
* Reword function description in patch #5
* Fix a bug in patch #8
* Add a test for the splittable attribute in patch #9

Changes since v1:
* Rename 'width' attribute to 'lanes'
* Add 'splittable' attribute
* Move checks from drivers to devlink
====================

Reviewed-by: Jakub Kicinski <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jul 9, 2020
2 parents faea30e + f3348a8 commit 8fb49c0
Show file tree
Hide file tree
Showing 19 changed files with 424 additions and 132 deletions.
9 changes: 6 additions & 3 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ static void bnxt_dl_params_unregister(struct bnxt *bp)

int bnxt_dl_register(struct bnxt *bp)
{
struct devlink_port_attrs attrs = {};
struct devlink *dl;
int rc;

Expand Down Expand Up @@ -719,9 +720,11 @@ int bnxt_dl_register(struct bnxt *bp)
if (!BNXT_PF(bp))
return 0;

devlink_port_attrs_set(&bp->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
bp->pf.port_id, false, 0, bp->dsn,
sizeof(bp->dsn));
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = bp->pf.port_id;
memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn));
attrs.switch_id.id_len = sizeof(bp->dsn);
devlink_port_attrs_set(&bp->dl_port, &attrs);
rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
if (rc) {
netdev_err(bp->dev, "devlink_port_register failed\n");
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/intel/ice/ice_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,17 @@ int ice_devlink_create_port(struct ice_pf *pf)
struct devlink *devlink = priv_to_devlink(pf);
struct ice_vsi *vsi = ice_get_main_vsi(pf);
struct device *dev = ice_pf_to_dev(pf);
struct devlink_port_attrs attrs = {};
int err;

if (!vsi) {
dev_err(dev, "%s: unable to find main VSI\n", __func__);
return -EIO;
}

devlink_port_attrs_set(&pf->devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
pf->hw.pf_id, false, 0, NULL, 0);
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = pf->hw.pf_id;
devlink_port_attrs_set(&pf->devlink_port, &attrs);
err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id);
if (err) {
dev_err(dev, "devlink_port_register failed: %d\n", err);
Expand Down
19 changes: 9 additions & 10 deletions drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@
int mlx5e_devlink_port_register(struct mlx5e_priv *priv)
{
struct devlink *devlink = priv_to_devlink(priv->mdev);
struct devlink_port_attrs attrs = {};

if (mlx5_core_is_pf(priv->mdev))
devlink_port_attrs_set(&priv->dl_port,
DEVLINK_PORT_FLAVOUR_PHYSICAL,
PCI_FUNC(priv->mdev->pdev->devfn),
false, 0,
NULL, 0);
else
devlink_port_attrs_set(&priv->dl_port,
DEVLINK_PORT_FLAVOUR_VIRTUAL,
0, false, 0, NULL, 0);
if (mlx5_core_is_pf(priv->mdev)) {
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = PCI_FUNC(priv->mdev->pdev->devfn);
} else {
attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL;
}

devlink_port_attrs_set(&priv->dl_port, &attrs);

return devlink_port_register(devlink, &priv->dl_port, 1);
}
Expand Down
16 changes: 7 additions & 9 deletions drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ static int register_devlink_port(struct mlx5_core_dev *dev,
{
struct devlink *devlink = priv_to_devlink(dev);
struct mlx5_eswitch_rep *rep = rpriv->rep;
struct devlink_port_attrs attrs = {};
struct netdev_phys_item_id ppid = {};
unsigned int dl_port_index = 0;
u16 pfnum;
Expand All @@ -1195,19 +1196,16 @@ static int register_devlink_port(struct mlx5_core_dev *dev,
mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid);
dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, rep->vport);
pfnum = PCI_FUNC(dev->pdev->devfn);

attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = pfnum;
memcpy(attrs.switch_id.id, &ppid.id[0], ppid.id_len);
attrs.switch_id.id_len = ppid.id_len;
if (rep->vport == MLX5_VPORT_UPLINK)
devlink_port_attrs_set(&rpriv->dl_port,
DEVLINK_PORT_FLAVOUR_PHYSICAL,
pfnum, false, 0,
&ppid.id[0], ppid.id_len);
devlink_port_attrs_set(&rpriv->dl_port, &attrs);
else if (rep->vport == MLX5_VPORT_PF)
devlink_port_attrs_pci_pf_set(&rpriv->dl_port,
&ppid.id[0], ppid.id_len,
pfnum);
devlink_port_attrs_pci_pf_set(&rpriv->dl_port, pfnum);
else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport))
devlink_port_attrs_pci_vf_set(&rpriv->dl_port,
&ppid.id[0], ppid.id_len,
pfnum, rep->vport - 1);

return devlink_port_register(devlink, &rpriv->dl_port, dl_port_index);
Expand Down
18 changes: 14 additions & 4 deletions drivers/net/ethernet/mellanox/mlxsw/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2122,19 +2122,27 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port,
enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_port_subnumber,
bool splittable, u32 lanes,
const unsigned char *switch_id,
unsigned char switch_id_len)
{
struct devlink *devlink = priv_to_devlink(mlxsw_core);
struct mlxsw_core_port *mlxsw_core_port =
&mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
struct devlink_port_attrs attrs = {};
int err;

attrs.split = split;
attrs.lanes = lanes;
attrs.splittable = splittable;
attrs.flavour = flavour;
attrs.phys.port_number = port_number;
attrs.phys.split_subport_number = split_port_subnumber;
memcpy(attrs.switch_id.id, switch_id, switch_id_len);
attrs.switch_id.id_len = switch_id_len;
mlxsw_core_port->local_port = local_port;
devlink_port_attrs_set(devlink_port, flavour, port_number,
split, split_port_subnumber,
switch_id, switch_id_len);
devlink_port_attrs_set(devlink_port, &attrs);
err = devlink_port_register(devlink, devlink_port, local_port);
if (err)
memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
Expand All @@ -2154,12 +2162,14 @@ static void __mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port,
u32 port_number, bool split,
u32 split_port_subnumber,
bool splittable, u32 lanes,
const unsigned char *switch_id,
unsigned char switch_id_len)
{
return __mlxsw_core_port_init(mlxsw_core, local_port,
DEVLINK_PORT_FLAVOUR_PHYSICAL,
port_number, split, split_port_subnumber,
splittable, lanes,
switch_id, switch_id_len);
}
EXPORT_SYMBOL(mlxsw_core_port_init);
Expand All @@ -2181,7 +2191,7 @@ int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core,

err = __mlxsw_core_port_init(mlxsw_core, MLXSW_PORT_CPU_PORT,
DEVLINK_PORT_FLAVOUR_CPU,
0, false, 0,
0, false, 0, false, 0,
switch_id, switch_id_len);
if (err)
return err;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,

void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port,
u32 port_number, bool split,
u32 split_port_subnumber,
u32 port_number, bool split, u32 split_port_subnumber,
bool splittable, u32 lanes,
const unsigned char *switch_id,
unsigned char switch_id_len);
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/minimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module)
int err;

err = mlxsw_core_port_init(mlxsw_m->core, local_port,
module + 1, false, 0,
mlxsw_m->base_mac,
module + 1, false, 0, false,
0, mlxsw_m->base_mac,
sizeof(mlxsw_m->base_mac));
if (err) {
dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to init core port\n",
Expand Down
23 changes: 7 additions & 16 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -1733,12 +1733,16 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
bool split = !!split_base_local_port;
struct mlxsw_sp_port *mlxsw_sp_port;
u32 lanes = port_mapping->width;
struct net_device *dev;
bool splittable;
int err;

splittable = lanes > 1 && !split;
err = mlxsw_core_port_init(mlxsw_sp->core, local_port,
port_mapping->module + 1, split,
port_mapping->lane / port_mapping->width,
port_mapping->lane / lanes,
splittable, lanes,
mlxsw_sp->base_mac,
sizeof(mlxsw_sp->base_mac));
if (err) {
Expand Down Expand Up @@ -2232,13 +2236,6 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
return -EINVAL;
}

/* Split ports cannot be split. */
if (mlxsw_sp_port->split) {
netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
NL_SET_ERR_MSG_MOD(extack, "Port cannot be split further");
return -EINVAL;
}

max_width = mlxsw_core_module_max_width(mlxsw_core,
mlxsw_sp_port->mapping.module);
if (max_width < 0) {
Expand All @@ -2247,19 +2244,13 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
return max_width;
}

/* Split port with non-max and 1 module width cannot be split. */
if (mlxsw_sp_port->mapping.width != max_width || max_width == 1) {
/* Split port with non-max cannot be split. */
if (mlxsw_sp_port->mapping.width != max_width) {
netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n");
NL_SET_ERR_MSG_MOD(extack, "Port cannot be split");
return -EINVAL;
}

if (count == 1 || !is_power_of_2(count) || count > max_width) {
netdev_err(mlxsw_sp_port->dev, "Invalid split count\n");
NL_SET_ERR_MSG_MOD(extack, "Invalid split count");
return -EINVAL;
}

offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
if (offset < 0) {
netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlxsw/switchib.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
int err;

err = mlxsw_core_port_init(mlxsw_sib->core, local_port,
module + 1, false, 0,
module + 1, false, 0, false, 0,
mlxsw_sib->hw_id, sizeof(mlxsw_sib->hw_id));
if (err) {
dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n",
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlxsw/switchx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ static int mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
int err;

err = mlxsw_core_port_init(mlxsw_sx->core, local_port,
module + 1, false, 0,
module + 1, false, 0, false, 0,
mlxsw_sx->hw_id, sizeof(mlxsw_sx->hw_id));
if (err) {
dev_err(mlxsw_sx->bus_info->dev, "Port %d: Failed to init core port\n",
Expand Down
17 changes: 10 additions & 7 deletions drivers/net/ethernet/netronome/nfp/nfp_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ nfp_devlink_port_split(struct devlink *devlink, unsigned int port_index,
unsigned int lanes;
int ret;

if (count < 2)
return -EINVAL;

mutex_lock(&pf->lock);

rtnl_lock();
Expand All @@ -81,7 +78,7 @@ nfp_devlink_port_split(struct devlink *devlink, unsigned int port_index,
if (ret)
goto out;

if (eth_port.is_split || eth_port.port_lanes % count) {
if (eth_port.port_lanes % count) {
ret = -EINVAL;
goto out;
}
Expand Down Expand Up @@ -353,6 +350,7 @@ const struct devlink_ops nfp_devlink_ops = {

int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
{
struct devlink_port_attrs attrs = {};
struct nfp_eth_table_port eth_port;
struct devlink *devlink;
const u8 *serial;
Expand All @@ -365,10 +363,15 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
if (ret)
return ret;

attrs.split = eth_port.is_split;
attrs.splittable = !attrs.split;
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = eth_port.label_port;
attrs.phys.split_subport_number = eth_port.label_subport;
serial_len = nfp_cpp_serial(port->app->cpp, &serial);
devlink_port_attrs_set(&port->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
eth_port.label_port, eth_port.is_split,
eth_port.label_subport, serial, serial_len);
memcpy(attrs.switch_id.id, serial, serial_len);
attrs.switch_id.id_len = serial_len;
devlink_port_attrs_set(&port->dl_port, &attrs);

devlink = priv_to_devlink(app->pf);

Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/pensando/ionic/ionic_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void ionic_devlink_free(struct ionic *ionic)
int ionic_devlink_register(struct ionic *ionic)
{
struct devlink *dl = priv_to_devlink(ionic);
struct devlink_port_attrs attrs = {};
int err;

err = devlink_register(dl, ionic->dev);
Expand All @@ -77,8 +78,8 @@ int ionic_devlink_register(struct ionic *ionic)
return err;
}

devlink_port_attrs_set(&ionic->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
0, false, 0, NULL, 0);
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
devlink_port_attrs_set(&ionic->dl_port, &attrs);
err = devlink_port_register(dl, &ionic->dl_port, 0);
if (err)
dev_err(ionic->dev, "devlink_port_register failed: %d\n", err);
Expand Down
10 changes: 6 additions & 4 deletions drivers/net/netdevsim/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
unsigned int port_index)
{
struct devlink_port_attrs attrs = {};
struct nsim_dev_port *nsim_dev_port;
struct devlink_port *devlink_port;
int err;
Expand All @@ -899,10 +900,11 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
nsim_dev_port->port_index = port_index;

devlink_port = &nsim_dev_port->devlink_port;
devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
port_index + 1, 0, 0,
nsim_dev->switch_id.id,
nsim_dev->switch_id.id_len);
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = port_index + 1;
memcpy(attrs.switch_id.id, nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
attrs.switch_id.id_len = nsim_dev->switch_id.id_len;
devlink_port_attrs_set(devlink_port, &attrs);
err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port,
port_index);
if (err)
Expand Down
Loading

0 comments on commit 8fb49c0

Please sign in to comment.