Commit 9d108841 authored by David S. Miller's avatar David S. Miller

Merge branch 'devlink-port-flavours-and-phys_port_name'

Jiri Pirko says:

====================
devlink: introduce port flavours and common phys_port_name generation

This patchset resolves 2 issues we have right now:
1) There are many netdevices / ports in the system, for port, pf, vf
   represenatation but the user has no way to see which is which
2) The ndo_get_phys_port_name is implemented in each driver separatelly,
   which may lead to inconsistent names between drivers.

This patchset introduces port flavours which should address the first
problem. In this initial patchset, I focus on DSA and their port
flavours. As a follow-up, I plan to add PF and VF representor flavours.
However, that needs additional dependencies in drivers (nfp, mlx5).

The common phys_port_name generation is used by mlxsw. An example output
for mlxsw looks like this:

...
pci/0000:03:00.0/59: type eth netdev enp3s0np4 flavour physical number 4
pci/0000:03:00.0/61: type eth netdev enp3s0np1 flavour physical number 1
pci/0000:03:00.0/63: type eth netdev enp3s0np2 flavour physical number 2
pci/0000:03:00.0/49: type eth netdev enp3s0np8s0 flavour physical number 8 split_group 8 subport 0
pci/0000:03:00.0/50: type eth netdev enp3s0np8s1 flavour physical number 8 split_group 8 subport 1
pci/0000:03:00.0/51: type eth netdev enp3s0np8s2 flavour physical number 8 split_group 8 subport 2
pci/0000:03:00.0/52: type eth netdev enp3s0np8s3 flavour physical number 8 split_group 8 subport 3

As you can see, the netdev names are generated according to the flavour
and port number. In case the port is split, the split subnumber is also
included.

An example output for dsa_loop testing module looks like this:
mdio_bus/fixed-0:1f/0: type eth netdev lan1 flavour physical number 0
mdio_bus/fixed-0:1f/1: type eth netdev lan2 flavour physical number 1
mdio_bus/fixed-0:1f/2: type eth netdev lan3 flavour physical number 2
mdio_bus/fixed-0:1f/3: type eth netdev lan4 flavour physical number 3
mdio_bus/fixed-0:1f/4: type notset
mdio_bus/fixed-0:1f/5: type notset flavour cpu number 5
mdio_bus/fixed-0:1f/6: type notset
mdio_bus/fixed-0:1f/7: type notset
mdio_bus/fixed-0:1f/8: type notset
mdio_bus/fixed-0:1f/9: type notset
mdio_bus/fixed-0:1f/10: type notset
mdio_bus/fixed-0:1f/11: type notset

---
RFC->v1:
-removed nfp patches, removed DSA patch that used name generation helper
-patch 1:
 - Reduced the nfp change just to simply use newly created attr_set func
-patch 2:
 - rebased
 - removed pf/vf reps flavours
-patch 3:
 - rebased
-patch 4:
 - added missing break pointed out by Andrew
====================
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Tested-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eb38401c ec932fbd
...@@ -1714,15 +1714,16 @@ EXPORT_SYMBOL(mlxsw_core_port_fini); ...@@ -1714,15 +1714,16 @@ EXPORT_SYMBOL(mlxsw_core_port_fini);
void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv, struct net_device *dev, void *port_driver_priv, struct net_device *dev,
bool split, u32 split_group) u32 port_number, bool split,
u32 split_port_subnumber)
{ {
struct mlxsw_core_port *mlxsw_core_port = struct mlxsw_core_port *mlxsw_core_port =
&mlxsw_core->ports[local_port]; &mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
mlxsw_core_port->port_driver_priv = port_driver_priv; mlxsw_core_port->port_driver_priv = port_driver_priv;
if (split) devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
devlink_port_split_set(devlink_port, split_group); port_number, split, split_port_subnumber);
devlink_port_type_eth_set(devlink_port, dev); devlink_port_type_eth_set(devlink_port, dev);
} }
EXPORT_SYMBOL(mlxsw_core_port_eth_set); EXPORT_SYMBOL(mlxsw_core_port_eth_set);
...@@ -1762,6 +1763,17 @@ enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, ...@@ -1762,6 +1763,17 @@ enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
} }
EXPORT_SYMBOL(mlxsw_core_port_type_get); EXPORT_SYMBOL(mlxsw_core_port_type_get);
int mlxsw_core_port_get_phys_port_name(struct mlxsw_core *mlxsw_core,
u8 local_port, char *name, size_t len)
{
struct mlxsw_core_port *mlxsw_core_port =
&mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
return devlink_port_get_phys_port_name(devlink_port, name, len);
}
EXPORT_SYMBOL(mlxsw_core_port_get_phys_port_name);
static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
const char *buf, size_t size) const char *buf, size_t size)
{ {
......
...@@ -201,13 +201,16 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port); ...@@ -201,13 +201,16 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port); void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port, void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv, struct net_device *dev, void *port_driver_priv, struct net_device *dev,
bool split, u32 split_group); u32 port_number, bool split,
u32 split_port_subnumber);
void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port, void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv); void *port_driver_priv);
void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port, void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv); void *port_driver_priv);
enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
u8 local_port); u8 local_port);
int mlxsw_core_port_get_phys_port_name(struct mlxsw_core *mlxsw_core,
u8 local_port, char *name, size_t len);
int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);
bool mlxsw_core_schedule_work(struct work_struct *work); bool mlxsw_core_schedule_work(struct work_struct *work);
......
...@@ -1238,21 +1238,10 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name, ...@@ -1238,21 +1238,10 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name,
size_t len) size_t len)
{ {
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
u8 module = mlxsw_sp_port->mapping.module;
u8 width = mlxsw_sp_port->mapping.width;
u8 lane = mlxsw_sp_port->mapping.lane;
int err;
if (!mlxsw_sp_port->split)
err = snprintf(name, len, "p%d", module + 1);
else
err = snprintf(name, len, "p%ds%d", module + 1,
lane / width);
if (err >= len) return mlxsw_core_port_get_phys_port_name(mlxsw_sp_port->mlxsw_sp->core,
return -EINVAL; mlxsw_sp_port->local_port,
name, len);
return 0;
} }
static struct mlxsw_sp_port_mall_tc_entry * static struct mlxsw_sp_port_mall_tc_entry *
...@@ -2927,8 +2916,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -2927,8 +2916,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
} }
mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port, mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
mlxsw_sp_port, dev, mlxsw_sp_port->split, mlxsw_sp_port, dev, module + 1,
module); mlxsw_sp_port->split, lane / width);
mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0); mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0);
return 0; return 0;
......
...@@ -417,13 +417,10 @@ static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name, ...@@ -417,13 +417,10 @@ static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name,
size_t len) size_t len)
{ {
struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev);
int err;
err = snprintf(name, len, "p%d", mlxsw_sx_port->mapping.module + 1);
if (err >= len)
return -EINVAL;
return 0; return mlxsw_core_port_get_phys_port_name(mlxsw_sx_port->mlxsw_sx->core,
mlxsw_sx_port->local_port,
name, len);
} }
static const struct net_device_ops mlxsw_sx_port_netdev_ops = { static const struct net_device_ops mlxsw_sx_port_netdev_ops = {
...@@ -1149,7 +1146,7 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, ...@@ -1149,7 +1146,7 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
} }
mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port, mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
mlxsw_sx_port, dev, false, 0); mlxsw_sx_port, dev, module + 1, false, 0);
mlxsw_sx->ports[local_port] = mlxsw_sx_port; mlxsw_sx->ports[local_port] = mlxsw_sx_port;
return 0; return 0;
......
...@@ -175,8 +175,9 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) ...@@ -175,8 +175,9 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
return ret; return ret;
devlink_port_type_eth_set(&port->dl_port, port->netdev); devlink_port_type_eth_set(&port->dl_port, port->netdev);
if (eth_port.is_split) devlink_port_attrs_set(&port->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
devlink_port_split_set(&port->dl_port, eth_port.label_port); eth_port.label_port, eth_port.is_split,
eth_port.label_subport);
devlink = priv_to_devlink(app->pf); devlink = priv_to_devlink(app->pf);
......
...@@ -35,6 +35,14 @@ struct devlink { ...@@ -35,6 +35,14 @@ struct devlink {
char priv[0] __aligned(NETDEV_ALIGN); char priv[0] __aligned(NETDEV_ALIGN);
}; };
struct devlink_port_attrs {
bool set;
enum devlink_port_flavour flavour;
u32 port_number; /* same value as "split group" */
bool split;
u32 split_subport_number;
};
struct devlink_port { struct devlink_port {
struct list_head list; struct list_head list;
struct devlink *devlink; struct devlink *devlink;
...@@ -43,8 +51,7 @@ struct devlink_port { ...@@ -43,8 +51,7 @@ struct devlink_port {
enum devlink_port_type type; enum devlink_port_type type;
enum devlink_port_type desired_type; enum devlink_port_type desired_type;
void *type_dev; void *type_dev;
bool split; struct devlink_port_attrs attrs;
u32 split_group;
}; };
struct devlink_sb_pool_info { struct devlink_sb_pool_info {
...@@ -367,8 +374,12 @@ void devlink_port_type_eth_set(struct devlink_port *devlink_port, ...@@ -367,8 +374,12 @@ void devlink_port_type_eth_set(struct devlink_port *devlink_port,
void devlink_port_type_ib_set(struct devlink_port *devlink_port, void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev); struct ib_device *ibdev);
void devlink_port_type_clear(struct devlink_port *devlink_port); void devlink_port_type_clear(struct devlink_port *devlink_port);
void devlink_port_split_set(struct devlink_port *devlink_port, void devlink_port_attrs_set(struct devlink_port *devlink_port,
u32 split_group); enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number);
int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
char *name, size_t len);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count, u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count, u16 egress_pools_count, u16 ingress_tc_count,
...@@ -466,11 +477,20 @@ static inline void devlink_port_type_clear(struct devlink_port *devlink_port) ...@@ -466,11 +477,20 @@ static inline void devlink_port_type_clear(struct devlink_port *devlink_port)
{ {
} }
static inline void devlink_port_split_set(struct devlink_port *devlink_port, static inline void devlink_port_attrs_set(struct devlink_port *devlink_port,
u32 split_group) enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number)
{ {
} }
static inline int
devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
char *name, size_t len)
{
return -EOPNOTSUPP;
}
static inline int devlink_sb_register(struct devlink *devlink, static inline int devlink_sb_register(struct devlink *devlink,
unsigned int sb_index, u32 size, unsigned int sb_index, u32 size,
u16 ingress_pools_count, u16 ingress_pools_count,
......
...@@ -132,6 +132,16 @@ enum devlink_eswitch_encap_mode { ...@@ -132,6 +132,16 @@ enum devlink_eswitch_encap_mode {
DEVLINK_ESWITCH_ENCAP_MODE_BASIC, DEVLINK_ESWITCH_ENCAP_MODE_BASIC,
}; };
enum devlink_port_flavour {
DEVLINK_PORT_FLAVOUR_PHYSICAL, /* Any kind of a port physically
* facing the user.
*/
DEVLINK_PORT_FLAVOUR_CPU, /* CPU port */
DEVLINK_PORT_FLAVOUR_DSA, /* Distributed switch architecture
* interconnect port.
*/
};
enum devlink_attr { enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */ /* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC, DEVLINK_ATTR_UNSPEC,
...@@ -224,6 +234,10 @@ enum devlink_attr { ...@@ -224,6 +234,10 @@ enum devlink_attr {
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, /* u64 */ DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, /* u64 */
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,/* u64 */ DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,/* u64 */
DEVLINK_ATTR_PORT_FLAVOUR, /* u16 */
DEVLINK_ATTR_PORT_NUMBER, /* u32 */
DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, /* u32 */
/* add new attributes above here, update the policy in devlink.c */ /* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX, __DEVLINK_ATTR_MAX,
......
...@@ -453,6 +453,27 @@ static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) ...@@ -453,6 +453,27 @@ static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
} }
static int devlink_nl_port_attrs_put(struct sk_buff *msg,
struct devlink_port *devlink_port)
{
struct devlink_port_attrs *attrs = &devlink_port->attrs;
if (!attrs->set)
return 0;
if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
return -EMSGSIZE;
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
return -EMSGSIZE;
if (!attrs->split)
return 0;
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
return -EMSGSIZE;
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
attrs->split_subport_number))
return -EMSGSIZE;
return 0;
}
static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
struct devlink_port *devlink_port, struct devlink_port *devlink_port,
enum devlink_command cmd, u32 portid, enum devlink_command cmd, u32 portid,
...@@ -492,9 +513,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, ...@@ -492,9 +513,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
ibdev->name)) ibdev->name))
goto nla_put_failure; goto nla_put_failure;
} }
if (devlink_port->split && if (devlink_nl_port_attrs_put(msg, devlink_port))
nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
devlink_port->split_group))
goto nla_put_failure; goto nla_put_failure;
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
...@@ -2971,19 +2990,64 @@ void devlink_port_type_clear(struct devlink_port *devlink_port) ...@@ -2971,19 +2990,64 @@ void devlink_port_type_clear(struct devlink_port *devlink_port)
EXPORT_SYMBOL_GPL(devlink_port_type_clear); EXPORT_SYMBOL_GPL(devlink_port_type_clear);
/** /**
* devlink_port_split_set - Set port is split * devlink_port_attrs_set - Set port attributes
* *
* @devlink_port: devlink port * @devlink_port: devlink port
* @split_group: split group - identifies group split port is part of * @flavour: flavour of the port
* @port_number: number of the port that is facing user, for example
* the front panel port number
* @split: indicates if this is split port
* @split_subport_number: if the port is split, this is the number
* of subport.
*/ */
void devlink_port_split_set(struct devlink_port *devlink_port, void devlink_port_attrs_set(struct devlink_port *devlink_port,
u32 split_group) enum devlink_port_flavour flavour,
{ u32 port_number, bool split,
devlink_port->split = true; u32 split_subport_number)
devlink_port->split_group = split_group; {
struct devlink_port_attrs *attrs = &devlink_port->attrs;
attrs->set = true;
attrs->flavour = flavour;
attrs->port_number = port_number;
attrs->split = split;
attrs->split_subport_number = split_subport_number;
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
} }
EXPORT_SYMBOL_GPL(devlink_port_split_set); EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
char *name, size_t len)
{
struct devlink_port_attrs *attrs = &devlink_port->attrs;
int n = 0;
if (!attrs->set)
return -EOPNOTSUPP;
switch (attrs->flavour) {
case DEVLINK_PORT_FLAVOUR_PHYSICAL:
if (!attrs->split)
n = snprintf(name, len, "p%u", attrs->port_number);
else
n = snprintf(name, len, "p%us%u", attrs->port_number,
attrs->split_subport_number);
break;
case DEVLINK_PORT_FLAVOUR_CPU:
case DEVLINK_PORT_FLAVOUR_DSA:
/* As CPU and DSA ports do not have a netdevice associated
* case should not ever happen.
*/
WARN_ON(1);
return -EINVAL;
}
if (n >= len)
return -EINVAL;
return 0;
}
EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count, u32 size, u16 ingress_pools_count,
......
...@@ -270,7 +270,28 @@ static int dsa_port_setup(struct dsa_port *dp) ...@@ -270,7 +270,28 @@ static int dsa_port_setup(struct dsa_port *dp)
case DSA_PORT_TYPE_UNUSED: case DSA_PORT_TYPE_UNUSED:
break; break;
case DSA_PORT_TYPE_CPU: case DSA_PORT_TYPE_CPU:
/* dp->index is used now as port_number. However
* CPU ports should have separate numbering
* independent from front panel port numbers.
*/
devlink_port_attrs_set(&dp->devlink_port,
DEVLINK_PORT_FLAVOUR_CPU,
dp->index, false, 0);
err = dsa_port_link_register_of(dp);
if (err) {
dev_err(ds->dev, "failed to setup link for port %d.%d\n",
ds->index, dp->index);
return err;
}
break;
case DSA_PORT_TYPE_DSA: case DSA_PORT_TYPE_DSA:
/* dp->index is used now as port_number. However
* DSA ports should have separate numbering
* independent from front panel port numbers.
*/
devlink_port_attrs_set(&dp->devlink_port,
DEVLINK_PORT_FLAVOUR_DSA,
dp->index, false, 0);
err = dsa_port_link_register_of(dp); err = dsa_port_link_register_of(dp);
if (err) { if (err) {
dev_err(ds->dev, "failed to setup link for port %d.%d\n", dev_err(ds->dev, "failed to setup link for port %d.%d\n",
...@@ -279,6 +300,9 @@ static int dsa_port_setup(struct dsa_port *dp) ...@@ -279,6 +300,9 @@ static int dsa_port_setup(struct dsa_port *dp)
} }
break; break;
case DSA_PORT_TYPE_USER: case DSA_PORT_TYPE_USER:
devlink_port_attrs_set(&dp->devlink_port,
DEVLINK_PORT_FLAVOUR_PHYSICAL,
dp->index, false, 0);
err = dsa_slave_create(dp); err = dsa_slave_create(dp);
if (err) if (err)
dev_err(ds->dev, "failed to create slave for port %d.%d\n", dev_err(ds->dev, "failed to create slave for port %d.%d\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment