Commit b599a5b9 authored by David S. Miller's avatar David S. Miller

Merge branch 'devlink-show-controller-number'

Parav Pandit says:

====================
devlink show controller number

Currently a devlink instance that supports an eswitch handles eswitch
ports of two type of controllers.
(1) controller discovered on same system where eswitch resides.
This is the case where PCI PF/VF of a controller and devlink eswitch
instance both are located on a single system.
(2) controller located on external system.
This is the case where a controller is plugged in one system and its
devlink eswitch ports are located in a different system. In this case
devlink instance of the eswitch only have access to ports of the
controller.
However, there is no way to describe that a eswitch devlink port
belongs to which controller (mainly which external host controller).
This problem is more prevalent when port attribute such as PF and VF
numbers are overlapping between multiple controllers of same eswitch.
Due to this, for a specific switch_id, unique phys_port_name cannot
be constructed for such devlink ports.

This short series overcomes this limitation by defining two new
attributes.
(a) external: Indicates if port belongs to external controller
(b) controller number: Indicates a controller number of the port

Based on this a unique phys_port_name is prepared using controller
number.

phys_port_name construction using unique controller number is only
applicable to external controller ports. This ensures that for
non smartnic usecases where there is no external controller,
phys_port_name stays same as before.

Patch summary:
Patch-1 Added mlx5 driver to read controller number
Patch-2 Adds the missing comment for the port attributes
Patch-3 Move structure comments away from structure fields
Patch-4 external attribute added for PCI port flavours
Patch-5 Add controller number
Patch-6 Use controller number to build phys_port_name

---
Changelog:
v2->v3:
 - Updated diagram to get rid of controller 'A' and 'B'
 - Kept ports of single controller together in diagram
 - Updated diagram for pf1's VF and SF and its ports
v1->v2:
 - Added text diagram of multiple controllers
 - Updated example for a VF
 - Addressed comments from Jiri and Jakub
 - Moved controller number attribute to PCI port flavours
   This enables to better, hirerchical view with controller and its
    PF, VF numbers
 - Split 'external' and 'controller number' attributes as two
   different attributes
 - Merged mlx5_core driver to avoid compiliation break
====================
Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6b5472d4 66b17082
......@@ -1210,16 +1210,22 @@ is_devlink_port_supported(const struct mlx5_core_dev *dev,
static int register_devlink_port(struct mlx5_core_dev *dev,
struct mlx5e_rep_priv *rpriv)
{
struct mlx5_esw_offload *offloads = &dev->priv.eswitch->offloads;
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;
u32 controller_num = 0;
bool external;
u16 pfnum;
if (!is_devlink_port_supported(dev, rpriv))
return 0;
external = mlx5_core_is_ecpf_esw_manager(dev);
if (external)
controller_num = offloads->host_number + 1;
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);
......@@ -1232,12 +1238,13 @@ static int register_devlink_port(struct mlx5_core_dev *dev,
} else if (rep->vport == MLX5_VPORT_PF) {
memcpy(rpriv->dl_port.attrs.switch_id.id, &ppid.id[0], ppid.id_len);
rpriv->dl_port.attrs.switch_id.id_len = ppid.id_len;
devlink_port_attrs_pci_pf_set(&rpriv->dl_port, pfnum);
devlink_port_attrs_pci_pf_set(&rpriv->dl_port, controller_num,
pfnum, external);
} else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch, rpriv->rep->vport)) {
memcpy(rpriv->dl_port.attrs.switch_id.id, &ppid.id[0], ppid.id_len);
rpriv->dl_port.attrs.switch_id.id_len = ppid.id_len;
devlink_port_attrs_pci_vf_set(&rpriv->dl_port,
pfnum, rep->vport - 1);
devlink_port_attrs_pci_vf_set(&rpriv->dl_port, controller_num,
pfnum, rep->vport - 1, external);
}
return devlink_port_register(devlink, &rpriv->dl_port, dl_port_index);
}
......
......@@ -217,6 +217,7 @@ struct mlx5_esw_offload {
atomic64_t num_flows;
enum devlink_eswitch_encap_mode encap;
struct ida vport_metadata_ida;
unsigned int host_number; /* ECPF supports one external host */
};
/* E-Switch MC FDB table hash node */
......
......@@ -2110,6 +2110,24 @@ int mlx5_esw_funcs_changed_handler(struct notifier_block *nb, unsigned long type
return NOTIFY_OK;
}
static int mlx5_esw_host_number_init(struct mlx5_eswitch *esw)
{
const u32 *query_host_out;
if (!mlx5_core_is_ecpf_esw_manager(esw->dev))
return 0;
query_host_out = mlx5_esw_query_functions(esw->dev);
if (IS_ERR(query_host_out))
return PTR_ERR(query_host_out);
/* Mark non local controller with non zero controller number. */
esw->offloads.host_number = MLX5_GET(query_esw_functions_out, query_host_out,
host_params_context.host_number);
kvfree(query_host_out);
return 0;
}
int esw_offloads_enable(struct mlx5_eswitch *esw)
{
struct mlx5_vport *vport;
......@@ -2124,6 +2142,10 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
mutex_init(&esw->offloads.termtbl_mutex);
mlx5_rdma_enable_roce(esw->dev);
err = mlx5_esw_host_number_init(esw);
if (err)
goto err_vport_metadata;
err = esw_set_passing_vport_metadata(esw, true);
if (err)
goto err_vport_metadata;
......
......@@ -57,13 +57,30 @@ struct devlink_port_phys_attrs {
u32 split_subport_number; /* If the port is split, this is the number of subport. */
};
/**
* struct devlink_port_pci_pf_attrs - devlink port's PCI PF attributes
* @controller: Associated controller number
* @pf: Associated PCI PF number for this port.
* @external: when set, indicates if a port is for an external controller
*/
struct devlink_port_pci_pf_attrs {
u16 pf; /* Associated PCI PF for this port. */
u32 controller;
u16 pf;
u8 external:1;
};
/**
* struct devlink_port_pci_vf_attrs - devlink port's PCI VF attributes
* @controller: Associated controller number
* @pf: Associated PCI PF number for this port.
* @vf: Associated PCI VF for of the PCI PF for this port.
* @external: when set, indicates if a port is for an external controller
*/
struct devlink_port_pci_vf_attrs {
u16 pf; /* Associated PCI PF for this port. */
u16 vf; /* Associated PCI VF for of the PCI PF for this port. */
u32 controller;
u16 pf;
u16 vf;
u8 external:1;
};
/**
......@@ -73,6 +90,9 @@ struct devlink_port_pci_vf_attrs {
* @splittable: indicates if the port can be split.
* @lanes: maximum number of lanes the port supports. 0 value is not passed to netlink.
* @switch_id: if the port is part of switch, this is buffer with ID, otherwise this is NULL
* @phys: physical port attributes
* @pci_pf: PCI PF port attributes
* @pci_vf: PCI VF port attributes
*/
struct devlink_port_attrs {
u8 split:1,
......@@ -1203,9 +1223,10 @@ void devlink_port_type_ib_set(struct devlink_port *devlink_port,
void devlink_port_type_clear(struct devlink_port *devlink_port);
void devlink_port_attrs_set(struct devlink_port *devlink_port,
struct devlink_port_attrs *devlink_port_attrs);
void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u16 pf);
void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
u16 pf, u16 vf);
void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
u16 pf, bool external);
void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
u16 pf, u16 vf, bool external);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count,
......
......@@ -458,6 +458,8 @@ enum devlink_attr {
DEVLINK_ATTR_PORT_LANES, /* u32 */
DEVLINK_ATTR_PORT_SPLITTABLE, /* u8 */
DEVLINK_ATTR_PORT_EXTERNAL, /* u8 */
DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, /* u32 */
/* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX,
......
......@@ -523,15 +523,20 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg,
return -EMSGSIZE;
switch (devlink_port->attrs.flavour) {
case DEVLINK_PORT_FLAVOUR_PCI_PF:
if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
attrs->pci_pf.pf))
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER,
attrs->pci_pf.controller) ||
nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_pf.pf))
return -EMSGSIZE;
if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_pf.external))
return -EMSGSIZE;
break;
case DEVLINK_PORT_FLAVOUR_PCI_VF:
if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
attrs->pci_vf.pf) ||
nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
attrs->pci_vf.vf))
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER,
attrs->pci_vf.controller) ||
nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_vf.pf) ||
nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, attrs->pci_vf.vf))
return -EMSGSIZE;
if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external))
return -EMSGSIZE;
break;
case DEVLINK_PORT_FLAVOUR_PHYSICAL:
......@@ -7715,9 +7720,12 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
* devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
*
* @devlink_port: devlink port
* @controller: associated controller number for the devlink port instance
* @pf: associated PF for the devlink port instance
* @external: indicates if the port is for an external controller
*/
void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u16 pf)
void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
u16 pf, bool external)
{
struct devlink_port_attrs *attrs = &devlink_port->attrs;
int ret;
......@@ -7726,8 +7734,9 @@ void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u16 pf)
DEVLINK_PORT_FLAVOUR_PCI_PF);
if (ret)
return;
attrs->pci_pf.controller = controller;
attrs->pci_pf.pf = pf;
attrs->pci_pf.external = external;
}
EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
......@@ -7735,11 +7744,13 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
* devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
*
* @devlink_port: devlink port
* @controller: associated controller number for the devlink port instance
* @pf: associated PF for the devlink port instance
* @vf: associated VF of a PF for the devlink port instance
* @external: indicates if the port is for an external controller
*/
void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
u16 pf, u16 vf)
void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
u16 pf, u16 vf, bool external)
{
struct devlink_port_attrs *attrs = &devlink_port->attrs;
int ret;
......@@ -7748,8 +7759,10 @@ void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
DEVLINK_PORT_FLAVOUR_PCI_VF);
if (ret)
return;
attrs->pci_vf.controller = controller;
attrs->pci_vf.pf = pf;
attrs->pci_vf.vf = vf;
attrs->pci_vf.external = external;
}
EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
......@@ -7780,9 +7793,23 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
WARN_ON(1);
return -EINVAL;
case DEVLINK_PORT_FLAVOUR_PCI_PF:
if (attrs->pci_pf.external) {
n = snprintf(name, len, "c%u", attrs->pci_pf.controller);
if (n >= len)
return -EINVAL;
len -= n;
name += n;
}
n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
break;
case DEVLINK_PORT_FLAVOUR_PCI_VF:
if (attrs->pci_vf.external) {
n = snprintf(name, len, "c%u", attrs->pci_vf.controller);
if (n >= len)
return -EINVAL;
len -= n;
name += n;
}
n = snprintf(name, len, "pf%uvf%u",
attrs->pci_vf.pf, attrs->pci_vf.vf);
break;
......
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