Commit 0c88eda9 authored by David S. Miller's avatar David S. Miller

Merge tag 'mlx5-updates-2021-03-16' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2021-03-16

mlx5 uplink representor netdev persistence.

Before this patchset we used to have separate netdevs for Native NIC mode
and Switchdev mode (uplink representor netdev), meaning that if user
switches modes between Native to Switchdev and vice versa, the driver
would cleanup the current netdev representor and create a new one for the
new mode, such behavior created an administrative nightmare for users,
where users need to be aware of such loss of both data path and control
path configurations, e.g. netdev attributes and arp/route tables,
where the later is more painful.

A simple solution for this is not to replace the netdev in first place
and use a single netdev to serve the uplink/physical port whether it is
in switchdev mode or native mode.

We already have different HW profiles for each netdev mode, in this series
we just replace the HW profile on the fly and we keep the same netdev
attached.

Refactoring: Some refactoring has been made to overcome some technical
difficulties
1) The netdev is created with the maximum amount of tx/rx queues to serve
the two profiles.

2) Some ndos are not supported in some modes, so we added a mode check for
   such cases, e.g legacy sriov ndos must be blocked in switchdev mode.

3) Some mlx5 netdev private attributes need to be moved out of profiles
   and kept in a persistent place, where the netdev is created
   e.g devlink port and other global HW resources

4) The netdev devlink port is now always registered with the switch id

Implementation: the last three patches implement the mechanism now as the
netdev can be shared.

5) Don't recreate the netdev on switchdev mode changes
6) Prevent changing switchdev mode when some netdev operations
are active, mostly when TC rules are being processed.
This is required since the netdev is kept registered while switchdev mode
can be changed.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ebfbc46b 7dc84de9
...@@ -58,9 +58,6 @@ static bool is_eth_supported(struct mlx5_core_dev *dev) ...@@ -58,9 +58,6 @@ static bool is_eth_supported(struct mlx5_core_dev *dev)
if (!IS_ENABLED(CONFIG_MLX5_CORE_EN)) if (!IS_ENABLED(CONFIG_MLX5_CORE_EN))
return false; return false;
if (is_eth_rep_supported(dev))
return false;
if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
return false; return false;
......
...@@ -880,7 +880,6 @@ struct mlx5e_priv { ...@@ -880,7 +880,6 @@ struct mlx5e_priv {
#endif #endif
struct devlink_health_reporter *tx_reporter; struct devlink_health_reporter *tx_reporter;
struct devlink_health_reporter *rx_reporter; struct devlink_health_reporter *rx_reporter;
struct devlink_port dl_port;
struct mlx5e_xsk xsk; struct mlx5e_xsk xsk;
#if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) #if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE)
struct mlx5e_hv_vhca_stats_agent stats_agent; struct mlx5e_hv_vhca_stats_agent stats_agent;
...@@ -1174,6 +1173,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv); ...@@ -1174,6 +1173,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv);
void mlx5e_destroy_netdev(struct mlx5e_priv *priv); void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
int mlx5e_netdev_change_profile(struct mlx5e_priv *priv, int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
const struct mlx5e_profile *new_profile, void *new_ppriv); const struct mlx5e_profile *new_profile, void *new_ppriv);
void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv);
void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv); void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv);
void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 mtu); void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 mtu);
void mlx5e_build_rq_params(struct mlx5_core_dev *mdev, void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
......
...@@ -2,37 +2,65 @@ ...@@ -2,37 +2,65 @@
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
#include "en/devlink.h" #include "en/devlink.h"
#include "eswitch.h"
static void
mlx5e_devlink_get_port_parent_id(struct mlx5_core_dev *dev, struct netdev_phys_item_id *ppid)
{
u64 parent_id;
parent_id = mlx5_query_nic_system_image_guid(dev);
ppid->id_len = sizeof(parent_id);
memcpy(ppid->id, &parent_id, sizeof(parent_id));
}
int mlx5e_devlink_port_register(struct mlx5e_priv *priv) int mlx5e_devlink_port_register(struct mlx5e_priv *priv)
{ {
struct devlink *devlink = priv_to_devlink(priv->mdev); struct devlink *devlink = priv_to_devlink(priv->mdev);
struct devlink_port_attrs attrs = {}; struct devlink_port_attrs attrs = {};
struct netdev_phys_item_id ppid = {};
struct devlink_port *dl_port;
unsigned int dl_port_index;
if (mlx5_core_is_pf(priv->mdev)) { if (mlx5_core_is_pf(priv->mdev)) {
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
attrs.phys.port_number = PCI_FUNC(priv->mdev->pdev->devfn); attrs.phys.port_number = PCI_FUNC(priv->mdev->pdev->devfn);
if (MLX5_ESWITCH_MANAGER(priv->mdev)) {
mlx5e_devlink_get_port_parent_id(priv->mdev, &ppid);
memcpy(attrs.switch_id.id, ppid.id, ppid.id_len);
attrs.switch_id.id_len = ppid.id_len;
}
dl_port_index = mlx5_esw_vport_to_devlink_port_index(priv->mdev,
MLX5_VPORT_UPLINK);
} else { } else {
attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL; attrs.flavour = DEVLINK_PORT_FLAVOUR_VIRTUAL;
dl_port_index = mlx5_esw_vport_to_devlink_port_index(priv->mdev, 0);
} }
devlink_port_attrs_set(&priv->dl_port, &attrs); dl_port = mlx5e_devlink_get_dl_port(priv);
memset(dl_port, 0, sizeof(*dl_port));
devlink_port_attrs_set(dl_port, &attrs);
return devlink_port_register(devlink, &priv->dl_port, 1); return devlink_port_register(devlink, dl_port, dl_port_index);
} }
void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv) void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv)
{ {
devlink_port_type_eth_set(&priv->dl_port, priv->netdev); struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
devlink_port_type_eth_set(dl_port, priv->netdev);
} }
void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv) void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv)
{ {
devlink_port_unregister(&priv->dl_port); struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
devlink_port_unregister(dl_port);
} }
struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev) struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
return &priv->dl_port; return mlx5e_devlink_get_dl_port(priv);
} }
...@@ -12,4 +12,10 @@ void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv); ...@@ -12,4 +12,10 @@ void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv);
void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv); void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv);
struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev); struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev);
static inline struct devlink_port *
mlx5e_devlink_get_dl_port(struct mlx5e_priv *priv)
{
return &priv->mdev->mlx5e_res.dl_port;
}
#endif #endif
...@@ -174,7 +174,7 @@ static int mlx5e_ptp_alloc_txqsq(struct mlx5e_port_ptp *c, int txq_ix, ...@@ -174,7 +174,7 @@ static int mlx5e_ptp_alloc_txqsq(struct mlx5e_port_ptp *c, int txq_ix,
sq->mdev = mdev; sq->mdev = mdev;
sq->ch_ix = c->ix; sq->ch_ix = c->ix;
sq->txq_ix = txq_ix; sq->txq_ix = txq_ix;
sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map;
sq->min_inline_mode = params->tx_min_inline_mode; sq->min_inline_mode = params->tx_min_inline_mode;
sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
sq->stats = &c->priv->port_ptp_stats.sq[tc]; sq->stats = &c->priv->port_ptp_stats.sq[tc];
...@@ -475,7 +475,7 @@ int mlx5e_port_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, ...@@ -475,7 +475,7 @@ int mlx5e_port_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
c->ix = 0; c->ix = 0;
c->pdev = mlx5_core_dma_dev(priv->mdev); c->pdev = mlx5_core_dma_dev(priv->mdev);
c->netdev = priv->netdev; c->netdev = priv->netdev;
c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey.key);
c->num_tc = params->num_tc; c->num_tc = params->num_tc;
c->stats = &priv->port_ptp_stats.ch; c->stats = &priv->port_ptp_stats.ch;
c->lag_port = lag_port; c->lag_port = lag_port;
......
...@@ -169,6 +169,9 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data, ...@@ -169,6 +169,9 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD); unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD);
struct mlx5e_priv *priv = cb_priv; struct mlx5e_priv *priv = cb_priv;
if (!priv->netdev || !netif_device_present(priv->netdev))
return -EOPNOTSUPP;
switch (type) { switch (type) {
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags); return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags);
...@@ -321,6 +324,9 @@ mlx5e_rep_indr_offload(struct net_device *netdev, ...@@ -321,6 +324,9 @@ mlx5e_rep_indr_offload(struct net_device *netdev,
struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev); struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev);
int err = 0; int err = 0;
if (!netif_device_present(indr_priv->rpriv->netdev))
return -EOPNOTSUPP;
switch (flower->command) { switch (flower->command) {
case FLOW_CLS_REPLACE: case FLOW_CLS_REPLACE:
err = mlx5e_configure_flower(netdev, priv, flower, flags); err = mlx5e_configure_flower(netdev, priv, flower, flags);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "health.h" #include "health.h"
#include "params.h" #include "params.h"
#include "txrx.h" #include "txrx.h"
#include "devlink.h"
static int mlx5e_query_rq_state(struct mlx5_core_dev *dev, u32 rqn, u8 *state) static int mlx5e_query_rq_state(struct mlx5_core_dev *dev, u32 rqn, u8 *state)
{ {
...@@ -615,9 +616,10 @@ static const struct devlink_health_reporter_ops mlx5_rx_reporter_ops = { ...@@ -615,9 +616,10 @@ static const struct devlink_health_reporter_ops mlx5_rx_reporter_ops = {
void mlx5e_reporter_rx_create(struct mlx5e_priv *priv) void mlx5e_reporter_rx_create(struct mlx5e_priv *priv)
{ {
struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
reporter = devlink_port_health_reporter_create(&priv->dl_port, &mlx5_rx_reporter_ops, reporter = devlink_port_health_reporter_create(dl_port, &mlx5_rx_reporter_ops,
MLX5E_REPORTER_RX_GRACEFUL_PERIOD, priv); MLX5E_REPORTER_RX_GRACEFUL_PERIOD, priv);
if (IS_ERR(reporter)) { if (IS_ERR(reporter)) {
netdev_warn(priv->netdev, "Failed to create rx reporter, err = %ld\n", netdev_warn(priv->netdev, "Failed to create rx reporter, err = %ld\n",
...@@ -633,4 +635,5 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv) ...@@ -633,4 +635,5 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
return; return;
devlink_port_health_reporter_destroy(priv->rx_reporter); devlink_port_health_reporter_destroy(priv->rx_reporter);
priv->rx_reporter = NULL;
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "health.h" #include "health.h"
#include "en/ptp.h" #include "en/ptp.h"
#include "en/devlink.h"
static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq)
{ {
...@@ -572,9 +573,10 @@ static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { ...@@ -572,9 +573,10 @@ static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = {
void mlx5e_reporter_tx_create(struct mlx5e_priv *priv) void mlx5e_reporter_tx_create(struct mlx5e_priv *priv)
{ {
struct devlink_port *dl_port = mlx5e_devlink_get_dl_port(priv);
struct devlink_health_reporter *reporter; struct devlink_health_reporter *reporter;
reporter = devlink_port_health_reporter_create(&priv->dl_port, &mlx5_tx_reporter_ops, reporter = devlink_port_health_reporter_create(dl_port, &mlx5_tx_reporter_ops,
MLX5_REPORTER_TX_GRACEFUL_PERIOD, priv); MLX5_REPORTER_TX_GRACEFUL_PERIOD, priv);
if (IS_ERR(reporter)) { if (IS_ERR(reporter)) {
netdev_warn(priv->netdev, netdev_warn(priv->netdev,
...@@ -591,4 +593,5 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv) ...@@ -591,4 +593,5 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
return; return;
devlink_port_health_reporter_destroy(priv->tx_reporter); devlink_port_health_reporter_destroy(priv->tx_reporter);
priv->tx_reporter = NULL;
} }
...@@ -84,7 +84,7 @@ static int mlx5e_alloc_trap_rq(struct mlx5e_priv *priv, struct mlx5e_rq_param *r ...@@ -84,7 +84,7 @@ static int mlx5e_alloc_trap_rq(struct mlx5e_priv *priv, struct mlx5e_rq_param *r
if (err) if (err)
goto err_free_frags; goto err_free_frags;
rq->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); rq->mkey_be = cpu_to_be32(mdev->mlx5e_res.hw_objs.mkey.key);
mlx5e_rq_set_trap_handlers(rq, params); mlx5e_rq_set_trap_handlers(rq, params);
...@@ -213,7 +213,7 @@ static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct ml ...@@ -213,7 +213,7 @@ static int mlx5e_create_trap_direct_rq_tir(struct mlx5_core_dev *mdev, struct ml
return -ENOMEM; return -ENOMEM;
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx); tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.td.tdn); MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn);
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE); MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT); MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
MLX5_SET(tirc, tirc, inline_rqn, rqn); MLX5_SET(tirc, tirc, inline_rqn, rqn);
...@@ -266,7 +266,7 @@ static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv) ...@@ -266,7 +266,7 @@ static struct mlx5e_trap *mlx5e_open_trap(struct mlx5e_priv *priv)
t->tstamp = &priv->tstamp; t->tstamp = &priv->tstamp;
t->pdev = mlx5_core_dma_dev(priv->mdev); t->pdev = mlx5_core_dma_dev(priv->mdev);
t->netdev = priv->netdev; t->netdev = priv->netdev;
t->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); t->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey.key);
t->stats = &priv->trap_stats.ch; t->stats = &priv->trap_stats.ch;
netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64); netif_napi_add(netdev, &t->napi, mlx5e_trap_napi_poll, 64);
......
...@@ -84,7 +84,7 @@ static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn ...@@ -84,7 +84,7 @@ static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, u32 *tirn, u32 rqtn
tirc = MLX5_ADDR_OF(create_tir_in, in, ctx); tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.td.tdn); MLX5_SET(tirc, tirc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn);
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT); MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8); MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
MLX5_SET(tirc, tirc, indirect_table, rqtn); MLX5_SET(tirc, tirc, indirect_table, rqtn);
......
...@@ -38,15 +38,16 @@ ...@@ -38,15 +38,16 @@
int mlx5e_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 *in) int mlx5e_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 *in)
{ {
struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
int err; int err;
err = mlx5_core_create_tir(mdev, in, &tir->tirn); err = mlx5_core_create_tir(mdev, in, &tir->tirn);
if (err) if (err)
return err; return err;
mutex_lock(&mdev->mlx5e_res.td.list_lock); mutex_lock(&res->td.list_lock);
list_add(&tir->list, &mdev->mlx5e_res.td.tirs_list); list_add(&tir->list, &res->td.tirs_list);
mutex_unlock(&mdev->mlx5e_res.td.list_lock); mutex_unlock(&res->td.list_lock);
return 0; return 0;
} }
...@@ -54,10 +55,12 @@ int mlx5e_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 *in) ...@@ -54,10 +55,12 @@ int mlx5e_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 *in)
void mlx5e_destroy_tir(struct mlx5_core_dev *mdev, void mlx5e_destroy_tir(struct mlx5_core_dev *mdev,
struct mlx5e_tir *tir) struct mlx5e_tir *tir)
{ {
mutex_lock(&mdev->mlx5e_res.td.list_lock); struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
mutex_lock(&res->td.list_lock);
mlx5_core_destroy_tir(mdev, tir->tirn); mlx5_core_destroy_tir(mdev, tir->tirn);
list_del(&tir->list); list_del(&tir->list);
mutex_unlock(&mdev->mlx5e_res.td.list_lock); mutex_unlock(&res->td.list_lock);
} }
void mlx5e_mkey_set_relaxed_ordering(struct mlx5_core_dev *mdev, void *mkc) void mlx5e_mkey_set_relaxed_ordering(struct mlx5_core_dev *mdev, void *mkc)
...@@ -99,7 +102,7 @@ static int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, ...@@ -99,7 +102,7 @@ static int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn,
int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev)
{ {
struct mlx5e_resources *res = &mdev->mlx5e_res; struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
int err; int err;
err = mlx5_core_alloc_pd(mdev, &res->pdn); err = mlx5_core_alloc_pd(mdev, &res->pdn);
...@@ -126,8 +129,8 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) ...@@ -126,8 +129,8 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev)
goto err_destroy_mkey; goto err_destroy_mkey;
} }
INIT_LIST_HEAD(&mdev->mlx5e_res.td.tirs_list); INIT_LIST_HEAD(&res->td.tirs_list);
mutex_init(&mdev->mlx5e_res.td.list_lock); mutex_init(&res->td.list_lock);
return 0; return 0;
...@@ -142,7 +145,7 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) ...@@ -142,7 +145,7 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev)
void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev) void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev)
{ {
struct mlx5e_resources *res = &mdev->mlx5e_res; struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs;
mlx5_free_bfreg(mdev, &res->bfreg); mlx5_free_bfreg(mdev, &res->bfreg);
mlx5_core_destroy_mkey(mdev, &res->mkey); mlx5_core_destroy_mkey(mdev, &res->mkey);
...@@ -180,8 +183,8 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, ...@@ -180,8 +183,8 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1); MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
mutex_lock(&mdev->mlx5e_res.td.list_lock); mutex_lock(&mdev->mlx5e_res.hw_objs.td.list_lock);
list_for_each_entry(tir, &mdev->mlx5e_res.td.tirs_list, list) { list_for_each_entry(tir, &mdev->mlx5e_res.hw_objs.td.tirs_list, list) {
tirn = tir->tirn; tirn = tir->tirn;
err = mlx5_core_modify_tir(mdev, tirn, in); err = mlx5_core_modify_tir(mdev, tirn, in);
if (err) if (err)
...@@ -192,7 +195,7 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, ...@@ -192,7 +195,7 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
kvfree(in); kvfree(in);
if (err) if (err)
netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err); netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err);
mutex_unlock(&mdev->mlx5e_res.td.list_lock); mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
return err; return err;
} }
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/mlx5/fs.h> #include <linux/mlx5/fs.h>
#include "en.h" #include "en.h"
#include "en_rep.h"
#include "lib/mpfs.h" #include "lib/mpfs.h"
static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv, static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
...@@ -435,6 +436,9 @@ int mlx5e_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) ...@@ -435,6 +436,9 @@ int mlx5e_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
if (mlx5e_is_uplink_rep(priv))
return 0; /* no vlan table for uplink rep */
if (be16_to_cpu(proto) == ETH_P_8021Q) if (be16_to_cpu(proto) == ETH_P_8021Q)
return mlx5e_vlan_rx_add_cvid(priv, vid); return mlx5e_vlan_rx_add_cvid(priv, vid);
else if (be16_to_cpu(proto) == ETH_P_8021AD) else if (be16_to_cpu(proto) == ETH_P_8021AD)
...@@ -447,6 +451,9 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid) ...@@ -447,6 +451,9 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
if (mlx5e_is_uplink_rep(priv))
return 0; /* no vlan table for uplink rep */
if (be16_to_cpu(proto) == ETH_P_8021Q) { if (be16_to_cpu(proto) == ETH_P_8021Q) {
clear_bit(vid, priv->fs.vlan.active_cvlans); clear_bit(vid, priv->fs.vlan.active_cvlans);
mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid); mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, vid);
......
...@@ -302,7 +302,7 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev, ...@@ -302,7 +302,7 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT); MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_MTT);
mlx5e_mkey_set_relaxed_ordering(mdev, mkc); mlx5e_mkey_set_relaxed_ordering(mdev, mkc);
MLX5_SET(mkc, mkc, qpn, 0xffffff); MLX5_SET(mkc, mkc, qpn, 0xffffff);
MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn); MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.hw_objs.pdn);
MLX5_SET64(mkc, mkc, len, npages << page_shift); MLX5_SET64(mkc, mkc, len, npages << page_shift);
MLX5_SET(mkc, mkc, translations_octword_size, MLX5_SET(mkc, mkc, translations_octword_size,
MLX5_MTT_OCTW(npages)); MLX5_MTT_OCTW(npages));
...@@ -1019,7 +1019,7 @@ static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c, ...@@ -1019,7 +1019,7 @@ static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c,
sq->pdev = c->pdev; sq->pdev = c->pdev;
sq->mkey_be = c->mkey_be; sq->mkey_be = c->mkey_be;
sq->channel = c; sq->channel = c;
sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map;
sq->min_inline_mode = params->tx_min_inline_mode; sq->min_inline_mode = params->tx_min_inline_mode;
sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
sq->xsk_pool = xsk_pool; sq->xsk_pool = xsk_pool;
...@@ -1090,7 +1090,7 @@ static int mlx5e_alloc_icosq(struct mlx5e_channel *c, ...@@ -1090,7 +1090,7 @@ static int mlx5e_alloc_icosq(struct mlx5e_channel *c,
int err; int err;
sq->channel = c; sq->channel = c;
sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map;
param->wq.db_numa_node = cpu_to_node(c->cpu); param->wq.db_numa_node = cpu_to_node(c->cpu);
err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl); err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
...@@ -1174,7 +1174,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, ...@@ -1174,7 +1174,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
sq->priv = c->priv; sq->priv = c->priv;
sq->ch_ix = c->ix; sq->ch_ix = c->ix;
sq->txq_ix = txq_ix; sq->txq_ix = txq_ix;
sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map;
sq->min_inline_mode = params->tx_min_inline_mode; sq->min_inline_mode = params->tx_min_inline_mode;
sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work);
...@@ -1257,7 +1257,7 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, ...@@ -1257,7 +1257,7 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
MLX5_SET(sqc, sqc, flush_in_error_en, 1); MLX5_SET(sqc, sqc, flush_in_error_en, 1);
MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.bfreg.index); MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.hw_objs.bfreg.index);
MLX5_SET(wq, wq, log_wq_pg_sz, csp->wq_ctrl->buf.page_shift - MLX5_SET(wq, wq, log_wq_pg_sz, csp->wq_ctrl->buf.page_shift -
MLX5_ADAPTER_PAGE_SHIFT); MLX5_ADAPTER_PAGE_SHIFT);
MLX5_SET64(wq, wq, dbr_addr, csp->wq_ctrl->db.dma); MLX5_SET64(wq, wq, dbr_addr, csp->wq_ctrl->db.dma);
...@@ -2032,7 +2032,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, ...@@ -2032,7 +2032,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
c->cpu = cpu; c->cpu = cpu;
c->pdev = mlx5_core_dma_dev(priv->mdev); c->pdev = mlx5_core_dma_dev(priv->mdev);
c->netdev = priv->netdev; c->netdev = priv->netdev;
c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.mkey.key); c->mkey_be = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey.key);
c->num_tc = params->num_tc; c->num_tc = params->num_tc;
c->xdp = !!params->xdp_prog; c->xdp = !!params->xdp_prog;
c->stats = &priv->channel_stats[ix].ch; c->stats = &priv->channel_stats[ix].ch;
...@@ -2217,7 +2217,7 @@ void mlx5e_build_rq_param(struct mlx5e_priv *priv, ...@@ -2217,7 +2217,7 @@ void mlx5e_build_rq_param(struct mlx5e_priv *priv,
MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN); MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
MLX5_SET(wq, wq, log_wq_stride, MLX5_SET(wq, wq, log_wq_stride,
mlx5e_get_rqwq_log_stride(params->rq_wq_type, ndsegs)); mlx5e_get_rqwq_log_stride(params->rq_wq_type, ndsegs));
MLX5_SET(wq, wq, pd, mdev->mlx5e_res.pdn); MLX5_SET(wq, wq, pd, mdev->mlx5e_res.hw_objs.pdn);
MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter); MLX5_SET(rqc, rqc, counter_set_id, priv->q_counter);
MLX5_SET(rqc, rqc, vsd, params->vlan_strip_disable); MLX5_SET(rqc, rqc, vsd, params->vlan_strip_disable);
MLX5_SET(rqc, rqc, scatter_fcs, params->scatter_fcs_en); MLX5_SET(rqc, rqc, scatter_fcs, params->scatter_fcs_en);
...@@ -2248,7 +2248,7 @@ void mlx5e_build_sq_param_common(struct mlx5e_priv *priv, ...@@ -2248,7 +2248,7 @@ void mlx5e_build_sq_param_common(struct mlx5e_priv *priv,
void *wq = MLX5_ADDR_OF(sqc, sqc, wq); void *wq = MLX5_ADDR_OF(sqc, sqc, wq);
MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB)); MLX5_SET(wq, wq, log_wq_stride, ilog2(MLX5_SEND_WQE_BB));
MLX5_SET(wq, wq, pd, priv->mdev->mlx5e_res.pdn); MLX5_SET(wq, wq, pd, priv->mdev->mlx5e_res.hw_objs.pdn);
param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(priv->mdev)); param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(priv->mdev));
} }
...@@ -3421,10 +3421,10 @@ int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn) ...@@ -3421,10 +3421,10 @@ int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn)
{ {
void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.td.tdn); MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn);
if (MLX5_GET(tisc, tisc, tls_en)) if (MLX5_GET(tisc, tisc, tls_en))
MLX5_SET(tisc, tisc, pd, mdev->mlx5e_res.pdn); MLX5_SET(tisc, tisc, pd, mdev->mlx5e_res.hw_objs.pdn);
if (mlx5_lag_is_lacp_owner(mdev)) if (mlx5_lag_is_lacp_owner(mdev))
MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1); MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1);
...@@ -3494,7 +3494,7 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) ...@@ -3494,7 +3494,7 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
static void mlx5e_build_indir_tir_ctx_common(struct mlx5e_priv *priv, static void mlx5e_build_indir_tir_ctx_common(struct mlx5e_priv *priv,
u32 rqtn, u32 *tirc) u32 rqtn, u32 *tirc)
{ {
MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn); MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.hw_objs.td.tdn);
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT); MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
MLX5_SET(tirc, tirc, indirect_table, rqtn); MLX5_SET(tirc, tirc, indirect_table, rqtn);
MLX5_SET(tirc, tirc, tunneled_offload_en, MLX5_SET(tirc, tirc, tunneled_offload_en,
...@@ -3769,8 +3769,16 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type, ...@@ -3769,8 +3769,16 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data) void *type_data)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
bool tc_unbind = false;
int err; int err;
if (type == TC_SETUP_BLOCK &&
((struct flow_block_offload *)type_data)->command == FLOW_BLOCK_UNBIND)
tc_unbind = true;
if (!netif_device_present(dev) && !tc_unbind)
return -ENODEV;
switch (type) { switch (type) {
case TC_SETUP_BLOCK: { case TC_SETUP_BLOCK: {
struct flow_block_offload *f = type_data; struct flow_block_offload *f = type_data;
...@@ -3823,6 +3831,9 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) ...@@ -3823,6 +3831,9 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_pport_stats *pstats = &priv->stats.pport; struct mlx5e_pport_stats *pstats = &priv->stats.pport;
if (!netif_device_present(dev))
return;
/* In switchdev mode, monitor counters doesn't monitor /* In switchdev mode, monitor counters doesn't monitor
* rx/tx stats of 802_3. The update stats mechanism * rx/tx stats of 802_3. The update stats mechanism
* should keep the 802_3 layout counters updated * should keep the 802_3 layout counters updated
...@@ -3857,11 +3868,19 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) ...@@ -3857,11 +3868,19 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;
} }
static void mlx5e_nic_set_rx_mode(struct mlx5e_priv *priv)
{
if (mlx5e_is_uplink_rep(priv))
return; /* no rx mode for uplink rep */
queue_work(priv->wq, &priv->set_rx_mode_work);
}
static void mlx5e_set_rx_mode(struct net_device *dev) static void mlx5e_set_rx_mode(struct net_device *dev)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
queue_work(priv->wq, &priv->set_rx_mode_work); mlx5e_nic_set_rx_mode(priv);
} }
static int mlx5e_set_mac(struct net_device *netdev, void *addr) static int mlx5e_set_mac(struct net_device *netdev, void *addr)
...@@ -3876,7 +3895,7 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr) ...@@ -3876,7 +3895,7 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
ether_addr_copy(netdev->dev_addr, saddr->sa_data); ether_addr_copy(netdev->dev_addr, saddr->sa_data);
netif_addr_unlock_bh(netdev); netif_addr_unlock_bh(netdev);
queue_work(priv->wq, &priv->set_rx_mode_work); mlx5e_nic_set_rx_mode(priv);
return 0; return 0;
} }
...@@ -4414,6 +4433,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf, ...@@ -4414,6 +4433,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
if (mlx5e_is_uplink_rep(priv))
return -EOPNOTSUPP;
return mlx5_eswitch_set_vport_state(mdev->priv.eswitch, vf + 1, return mlx5_eswitch_set_vport_state(mdev->priv.eswitch, vf + 1,
mlx5_ifla_link2vport(link_state)); mlx5_ifla_link2vport(link_state));
} }
...@@ -4425,6 +4447,9 @@ int mlx5e_get_vf_config(struct net_device *dev, ...@@ -4425,6 +4447,9 @@ int mlx5e_get_vf_config(struct net_device *dev,
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
int err; int err;
if (!netif_device_present(dev))
return -EOPNOTSUPP;
err = mlx5_eswitch_get_vport_config(mdev->priv.eswitch, vf + 1, ivi); err = mlx5_eswitch_get_vport_config(mdev->priv.eswitch, vf + 1, ivi);
if (err) if (err)
return err; return err;
...@@ -4441,6 +4466,32 @@ int mlx5e_get_vf_stats(struct net_device *dev, ...@@ -4441,6 +4466,32 @@ int mlx5e_get_vf_stats(struct net_device *dev,
return mlx5_eswitch_get_vport_stats(mdev->priv.eswitch, vf + 1, return mlx5_eswitch_get_vport_stats(mdev->priv.eswitch, vf + 1,
vf_stats); vf_stats);
} }
static bool
mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
{
struct mlx5e_priv *priv = netdev_priv(dev);
if (!netif_device_present(dev))
return false;
if (!mlx5e_is_uplink_rep(priv))
return false;
return mlx5e_rep_has_offload_stats(dev, attr_id);
}
static int
mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
void *sp)
{
struct mlx5e_priv *priv = netdev_priv(dev);
if (!mlx5e_is_uplink_rep(priv))
return -EOPNOTSUPP;
return mlx5e_rep_get_offload_stats(attr_id, dev, sp);
}
#endif #endif
static bool mlx5e_tunnel_proto_supported_tx(struct mlx5_core_dev *mdev, u8 proto_type) static bool mlx5e_tunnel_proto_supported_tx(struct mlx5_core_dev *mdev, u8 proto_type)
...@@ -4797,6 +4848,8 @@ const struct net_device_ops mlx5e_netdev_ops = { ...@@ -4797,6 +4848,8 @@ const struct net_device_ops mlx5e_netdev_ops = {
.ndo_get_vf_config = mlx5e_get_vf_config, .ndo_get_vf_config = mlx5e_get_vf_config,
.ndo_set_vf_link_state = mlx5e_set_vf_link_state, .ndo_set_vf_link_state = mlx5e_set_vf_link_state,
.ndo_get_vf_stats = mlx5e_get_vf_stats, .ndo_get_vf_stats = mlx5e_get_vf_stats,
.ndo_has_offload_stats = mlx5e_has_offload_stats,
.ndo_get_offload_stats = mlx5e_get_offload_stats,
#endif #endif
.ndo_get_devlink_port = mlx5e_get_devlink_port, .ndo_get_devlink_port = mlx5e_get_devlink_port,
}; };
...@@ -5253,10 +5306,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, ...@@ -5253,10 +5306,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
if (err) if (err)
mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
err = mlx5e_devlink_port_register(priv);
if (err)
mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
mlx5e_health_create_reporters(priv); mlx5e_health_create_reporters(priv);
return 0; return 0;
...@@ -5265,7 +5314,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, ...@@ -5265,7 +5314,6 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
static void mlx5e_nic_cleanup(struct mlx5e_priv *priv) static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
{ {
mlx5e_health_destroy_reporters(priv); mlx5e_health_destroy_reporters(priv);
mlx5e_devlink_port_unregister(priv);
mlx5e_tls_cleanup(priv); mlx5e_tls_cleanup(priv);
mlx5e_ipsec_cleanup(priv); mlx5e_ipsec_cleanup(priv);
} }
...@@ -5405,7 +5453,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) ...@@ -5405,7 +5453,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
return; return;
mlx5e_dcbnl_init_app(priv); mlx5e_dcbnl_init_app(priv);
queue_work(priv->wq, &priv->set_rx_mode_work); mlx5e_nic_set_rx_mode(priv);
rtnl_lock(); rtnl_lock();
if (netif_running(netdev)) if (netif_running(netdev))
...@@ -5428,7 +5476,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) ...@@ -5428,7 +5476,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
netif_device_detach(priv->netdev); netif_device_detach(priv->netdev);
rtnl_unlock(); rtnl_unlock();
queue_work(priv->wq, &priv->set_rx_mode_work); mlx5e_nic_set_rx_mode(priv);
mlx5e_hv_vhca_stats_destroy(priv); mlx5e_hv_vhca_stats_destroy(priv);
if (mlx5e_monitor_counter_supported(priv)) if (mlx5e_monitor_counter_supported(priv))
...@@ -5694,6 +5742,11 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv, ...@@ -5694,6 +5742,11 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
return err; return err;
} }
void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv)
{
mlx5e_netdev_change_profile(priv, &mlx5e_nic_profile, NULL);
}
void mlx5e_destroy_netdev(struct mlx5e_priv *priv) void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
{ {
struct net_device *netdev = priv->netdev; struct net_device *netdev = priv->netdev;
...@@ -5776,10 +5829,17 @@ static int mlx5e_probe(struct auxiliary_device *adev, ...@@ -5776,10 +5829,17 @@ static int mlx5e_probe(struct auxiliary_device *adev,
priv->profile = profile; priv->profile = profile;
priv->ppriv = NULL; priv->ppriv = NULL;
err = mlx5e_devlink_port_register(priv);
if (err) {
mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err);
goto err_destroy_netdev;
}
err = profile->init(mdev, netdev); err = profile->init(mdev, netdev);
if (err) { if (err) {
mlx5_core_err(mdev, "mlx5e_nic_profile init failed, %d\n", err); mlx5_core_err(mdev, "mlx5e_nic_profile init failed, %d\n", err);
goto err_destroy_netdev; goto err_devlink_cleanup;
} }
err = mlx5e_resume(adev); err = mlx5e_resume(adev);
...@@ -5797,12 +5857,15 @@ static int mlx5e_probe(struct auxiliary_device *adev, ...@@ -5797,12 +5857,15 @@ static int mlx5e_probe(struct auxiliary_device *adev,
mlx5e_devlink_port_type_eth_set(priv); mlx5e_devlink_port_type_eth_set(priv);
mlx5e_dcbnl_init_app(priv); mlx5e_dcbnl_init_app(priv);
mlx5_uplink_netdev_set(mdev, netdev);
return 0; return 0;
err_resume: err_resume:
mlx5e_suspend(adev, state); mlx5e_suspend(adev, state);
err_profile_cleanup: err_profile_cleanup:
profile->cleanup(priv); profile->cleanup(priv);
err_devlink_cleanup:
mlx5e_devlink_port_unregister(priv);
err_destroy_netdev: err_destroy_netdev:
mlx5e_destroy_netdev(priv); mlx5e_destroy_netdev(priv);
return err; return err;
...@@ -5817,6 +5880,7 @@ static void mlx5e_remove(struct auxiliary_device *adev) ...@@ -5817,6 +5880,7 @@ static void mlx5e_remove(struct auxiliary_device *adev)
unregister_netdev(priv->netdev); unregister_netdev(priv->netdev);
mlx5e_suspend(adev, state); mlx5e_suspend(adev, state);
priv->profile->cleanup(priv); priv->profile->cleanup(priv);
mlx5e_devlink_port_unregister(priv);
mlx5e_destroy_netdev(priv); mlx5e_destroy_netdev(priv);
} }
...@@ -5842,18 +5906,18 @@ int mlx5e_init(void) ...@@ -5842,18 +5906,18 @@ int mlx5e_init(void)
mlx5e_ipsec_build_inverse_table(); mlx5e_ipsec_build_inverse_table();
mlx5e_build_ptys2ethtool_map(); mlx5e_build_ptys2ethtool_map();
ret = mlx5e_rep_init(); ret = auxiliary_driver_register(&mlx5e_driver);
if (ret) if (ret)
return ret; return ret;
ret = auxiliary_driver_register(&mlx5e_driver); ret = mlx5e_rep_init();
if (ret) if (ret)
mlx5e_rep_cleanup(); auxiliary_driver_unregister(&mlx5e_driver);
return ret; return ret;
} }
void mlx5e_cleanup(void) void mlx5e_cleanup(void)
{ {
auxiliary_driver_unregister(&mlx5e_driver);
mlx5e_rep_cleanup(); mlx5e_rep_cleanup();
auxiliary_driver_unregister(&mlx5e_driver);
} }
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "en_tc.h" #include "en_tc.h"
#include "en/rep/tc.h" #include "en/rep/tc.h"
#include "en/rep/neigh.h" #include "en/rep/neigh.h"
#include "en/devlink.h"
#include "fs_core.h" #include "fs_core.h"
#include "lib/mlx5.h" #include "lib/mlx5.h"
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -69,16 +70,6 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev, ...@@ -69,16 +70,6 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev,
fw_rev_sub(mdev), mdev->board_id); fw_rev_sub(mdev), mdev->board_id);
} }
static void mlx5e_uplink_rep_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
{
struct mlx5e_priv *priv = netdev_priv(dev);
mlx5e_rep_get_drvinfo(dev, drvinfo);
strlcpy(drvinfo->bus_info, pci_name(priv->mdev->pdev),
sizeof(drvinfo->bus_info));
}
static const struct counter_desc sw_rep_stats_desc[] = { static const struct counter_desc sw_rep_stats_desc[] = {
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
...@@ -285,46 +276,6 @@ static u32 mlx5e_rep_get_rxfh_indir_size(struct net_device *netdev) ...@@ -285,46 +276,6 @@ static u32 mlx5e_rep_get_rxfh_indir_size(struct net_device *netdev)
return mlx5e_ethtool_get_rxfh_indir_size(priv); return mlx5e_ethtool_get_rxfh_indir_size(priv);
} }
static void mlx5e_uplink_rep_get_pause_stats(struct net_device *netdev,
struct ethtool_pause_stats *stats)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
mlx5e_stats_pause_get(priv, stats);
}
static void mlx5e_uplink_rep_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pauseparam)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
mlx5e_ethtool_get_pauseparam(priv, pauseparam);
}
static int mlx5e_uplink_rep_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pauseparam)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
return mlx5e_ethtool_set_pauseparam(priv, pauseparam);
}
static int mlx5e_uplink_rep_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *link_ksettings)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
return mlx5e_ethtool_get_link_ksettings(priv, link_ksettings);
}
static int mlx5e_uplink_rep_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *link_ksettings)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
return mlx5e_ethtool_set_link_ksettings(priv, link_ksettings);
}
static const struct ethtool_ops mlx5e_rep_ethtool_ops = { static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS | .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_MAX_FRAMES |
...@@ -344,34 +295,6 @@ static const struct ethtool_ops mlx5e_rep_ethtool_ops = { ...@@ -344,34 +295,6 @@ static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
.get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size, .get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size,
}; };
static const struct ethtool_ops mlx5e_uplink_rep_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE,
.get_drvinfo = mlx5e_uplink_rep_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_strings = mlx5e_rep_get_strings,
.get_sset_count = mlx5e_rep_get_sset_count,
.get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
.get_ringparam = mlx5e_rep_get_ringparam,
.set_ringparam = mlx5e_rep_set_ringparam,
.get_channels = mlx5e_rep_get_channels,
.set_channels = mlx5e_rep_set_channels,
.get_coalesce = mlx5e_rep_get_coalesce,
.set_coalesce = mlx5e_rep_set_coalesce,
.get_link_ksettings = mlx5e_uplink_rep_get_link_ksettings,
.set_link_ksettings = mlx5e_uplink_rep_set_link_ksettings,
.get_rxfh_key_size = mlx5e_rep_get_rxfh_key_size,
.get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size,
.get_rxfh = mlx5e_get_rxfh,
.set_rxfh = mlx5e_set_rxfh,
.get_rxnfc = mlx5e_get_rxnfc,
.set_rxnfc = mlx5e_set_rxnfc,
.get_pause_stats = mlx5e_uplink_rep_get_pause_stats,
.get_pauseparam = mlx5e_uplink_rep_get_pauseparam,
.set_pauseparam = mlx5e_uplink_rep_set_pauseparam,
};
static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep) struct mlx5_eswitch_rep *rep)
{ {
...@@ -522,7 +445,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) ...@@ -522,7 +445,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
return (rep->vport == MLX5_VPORT_UPLINK); return (rep->vport == MLX5_VPORT_UPLINK);
} }
static bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id) bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id)
{ {
switch (attr_id) { switch (attr_id) {
case IFLA_OFFLOAD_XSTATS_CPU_HIT: case IFLA_OFFLOAD_XSTATS_CPU_HIT:
...@@ -542,7 +465,7 @@ mlx5e_get_sw_stats64(const struct net_device *dev, ...@@ -542,7 +465,7 @@ mlx5e_get_sw_stats64(const struct net_device *dev,
return 0; return 0;
} }
static int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev, int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev,
void *sp) void *sp)
{ {
switch (attr_id) { switch (attr_id) {
...@@ -568,34 +491,6 @@ static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -568,34 +491,6 @@ static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu)
return mlx5e_change_mtu(netdev, new_mtu, NULL); return mlx5e_change_mtu(netdev, new_mtu, NULL);
} }
static int mlx5e_uplink_rep_change_mtu(struct net_device *netdev, int new_mtu)
{
return mlx5e_change_mtu(netdev, new_mtu, mlx5e_set_dev_port_mtu_ctx);
}
static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
{
struct sockaddr *saddr = addr;
if (!is_valid_ether_addr(saddr->sa_data))
return -EADDRNOTAVAIL;
ether_addr_copy(netdev->dev_addr, saddr->sa_data);
return 0;
}
static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
__be16 vlan_proto)
{
netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n");
if (vlan != 0)
return -EOPNOTSUPP;
/* allow setting 0-vid for compatibility with libvirt */
return 0;
}
static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *netdev) static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *netdev)
{ {
struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5e_priv *priv = netdev_priv(netdev);
...@@ -641,29 +536,10 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = { ...@@ -641,29 +536,10 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
.ndo_change_carrier = mlx5e_rep_change_carrier, .ndo_change_carrier = mlx5e_rep_change_carrier,
}; };
static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
.ndo_open = mlx5e_open,
.ndo_stop = mlx5e_close,
.ndo_start_xmit = mlx5e_xmit,
.ndo_set_mac_address = mlx5e_uplink_rep_set_mac,
.ndo_setup_tc = mlx5e_rep_setup_tc,
.ndo_get_devlink_port = mlx5e_rep_get_devlink_port,
.ndo_get_stats64 = mlx5e_get_stats,
.ndo_has_offload_stats = mlx5e_rep_has_offload_stats,
.ndo_get_offload_stats = mlx5e_rep_get_offload_stats,
.ndo_change_mtu = mlx5e_uplink_rep_change_mtu,
.ndo_features_check = mlx5e_features_check,
.ndo_set_vf_mac = mlx5e_set_vf_mac,
.ndo_set_vf_rate = mlx5e_set_vf_rate,
.ndo_get_vf_config = mlx5e_get_vf_config,
.ndo_get_vf_stats = mlx5e_get_vf_stats,
.ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan,
.ndo_set_features = mlx5e_set_features,
};
bool mlx5e_eswitch_uplink_rep(struct net_device *netdev) bool mlx5e_eswitch_uplink_rep(struct net_device *netdev)
{ {
return netdev->netdev_ops == &mlx5e_netdev_ops_uplink_rep; return netdev->netdev_ops == &mlx5e_netdev_ops &&
mlx5e_is_uplink_rep(netdev_priv(netdev));
} }
bool mlx5e_eswitch_vf_rep(struct net_device *netdev) bool mlx5e_eswitch_vf_rep(struct net_device *netdev)
...@@ -713,26 +589,15 @@ static void mlx5e_build_rep_params(struct net_device *netdev) ...@@ -713,26 +589,15 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
} }
static void mlx5e_build_rep_netdev(struct net_device *netdev, static void mlx5e_build_rep_netdev(struct net_device *netdev,
struct mlx5_core_dev *mdev, struct mlx5_core_dev *mdev)
struct mlx5_eswitch_rep *rep)
{ {
SET_NETDEV_DEV(netdev, mdev->device); SET_NETDEV_DEV(netdev, mdev->device);
if (rep->vport == MLX5_VPORT_UPLINK) {
netdev->netdev_ops = &mlx5e_netdev_ops_uplink_rep;
/* we want a persistent mac for the uplink rep */
mlx5_query_mac_address(mdev, netdev->dev_addr);
netdev->ethtool_ops = &mlx5e_uplink_rep_ethtool_ops;
mlx5e_dcbnl_build_rep_netdev(netdev);
} else {
netdev->netdev_ops = &mlx5e_netdev_ops_rep; netdev->netdev_ops = &mlx5e_netdev_ops_rep;
eth_hw_addr_random(netdev); eth_hw_addr_random(netdev);
netdev->ethtool_ops = &mlx5e_rep_ethtool_ops; netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
}
netdev->watchdog_timeo = 15 * HZ; netdev->watchdog_timeo = 15 * HZ;
netdev->features |= NETIF_F_NETNS_LOCAL;
#if IS_ENABLED(CONFIG_MLX5_CLS_ACT) #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
netdev->hw_features |= NETIF_F_HW_TC; netdev->hw_features |= NETIF_F_HW_TC;
#endif #endif
...@@ -744,12 +609,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev, ...@@ -744,12 +609,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
netdev->hw_features |= NETIF_F_TSO6; netdev->hw_features |= NETIF_F_TSO6;
netdev->hw_features |= NETIF_F_RXCSUM; netdev->hw_features |= NETIF_F_RXCSUM;
if (rep->vport == MLX5_VPORT_UPLINK)
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
else
netdev->features |= NETIF_F_VLAN_CHALLENGED;
netdev->features |= netdev->hw_features; netdev->features |= netdev->hw_features;
netdev->features |= NETIF_F_VLAN_CHALLENGED;
netdev->features |= NETIF_F_NETNS_LOCAL;
} }
static int mlx5e_init_rep(struct mlx5_core_dev *mdev, static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
...@@ -1115,6 +977,14 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) ...@@ -1115,6 +977,14 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
mlx5e_dcbnl_initialize(priv); mlx5e_dcbnl_initialize(priv);
mlx5e_dcbnl_init_app(priv); mlx5e_dcbnl_init_app(priv);
mlx5e_rep_neigh_init(rpriv); mlx5e_rep_neigh_init(rpriv);
netdev->wanted_features |= NETIF_F_HW_TC;
rtnl_lock();
if (netif_running(netdev))
mlx5e_open(netdev);
netif_device_attach(netdev);
rtnl_unlock();
} }
static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
...@@ -1122,6 +992,12 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) ...@@ -1122,6 +992,12 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
rtnl_lock();
if (netif_running(priv->netdev))
mlx5e_close(priv->netdev);
netif_device_detach(priv->netdev);
rtnl_unlock();
mlx5e_rep_neigh_cleanup(rpriv); mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_dcbnl_delete_app(priv); mlx5e_dcbnl_delete_app(priv);
mlx5_notifier_unregister(mdev, &priv->events_nb); mlx5_notifier_unregister(mdev, &priv->events_nb);
...@@ -1198,33 +1074,64 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = { ...@@ -1198,33 +1074,64 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
.update_carrier = mlx5e_update_carrier, .update_carrier = mlx5e_update_carrier,
.rx_handlers = &mlx5e_rx_handlers_rep, .rx_handlers = &mlx5e_rx_handlers_rep,
.max_tc = MLX5E_MAX_NUM_TC, .max_tc = MLX5E_MAX_NUM_TC,
.rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR), /* XSK is needed so we can replace profile with NIC netdev */
.rq_groups = MLX5E_NUM_RQ_GROUPS(XSK),
.stats_grps = mlx5e_ul_rep_stats_grps, .stats_grps = mlx5e_ul_rep_stats_grps,
.stats_grps_num = mlx5e_ul_rep_stats_grps_num, .stats_grps_num = mlx5e_ul_rep_stats_grps_num,
}; };
/* e-Switch vport representors */ /* e-Switch vport representors */
static int static int
mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev));
struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
struct devlink_port *dl_port;
int err;
rpriv->netdev = priv->netdev;
err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
rpriv);
if (err)
return err;
dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port)
devlink_port_type_eth_set(dl_port, rpriv->netdev);
return 0;
}
static void
mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
{ {
struct net_device *netdev = rpriv->netdev;
struct devlink_port *dl_port;
struct mlx5_core_dev *dev;
struct mlx5e_priv *priv;
priv = netdev_priv(netdev);
dev = priv->mdev;
dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port)
devlink_port_type_clear(dl_port);
mlx5e_netdev_attach_nic_profile(priv);
}
static int
mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
const struct mlx5e_profile *profile; const struct mlx5e_profile *profile;
struct mlx5e_rep_priv *rpriv;
struct devlink_port *dl_port; struct devlink_port *dl_port;
struct net_device *netdev; struct net_device *netdev;
struct mlx5e_priv *priv; struct mlx5e_priv *priv;
unsigned int txqs, rxqs; unsigned int txqs, rxqs;
int nch, err; int nch, err;
rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL); profile = &mlx5e_rep_profile;
if (!rpriv)
return -ENOMEM;
/* rpriv->rep to be looked up when profile->init() is called */
rpriv->rep = rep;
profile = (rep->vport == MLX5_VPORT_UPLINK) ?
&mlx5e_uplink_rep_profile : &mlx5e_rep_profile;
nch = mlx5e_get_max_num_channels(dev); nch = mlx5e_get_max_num_channels(dev);
txqs = nch * profile->max_tc; txqs = nch * profile->max_tc;
rxqs = nch * profile->rq_groups; rxqs = nch * profile->rq_groups;
...@@ -1233,21 +1140,11 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -1233,21 +1140,11 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
mlx5_core_warn(dev, mlx5_core_warn(dev,
"Failed to create representor netdev for vport %d\n", "Failed to create representor netdev for vport %d\n",
rep->vport); rep->vport);
kfree(rpriv);
return -EINVAL; return -EINVAL;
} }
mlx5e_build_rep_netdev(netdev, dev, rep); mlx5e_build_rep_netdev(netdev, dev);
rpriv->netdev = netdev; rpriv->netdev = netdev;
rep->rep_data[REP_ETH].priv = rpriv;
INIT_LIST_HEAD(&rpriv->vport_sqs_list);
if (rep->vport == MLX5_VPORT_UPLINK) {
err = mlx5e_create_mdev_resources(dev);
if (err)
goto err_destroy_netdev;
}
priv = netdev_priv(netdev); priv = netdev_priv(netdev);
priv->profile = profile; priv->profile = profile;
...@@ -1255,7 +1152,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -1255,7 +1152,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
err = profile->init(dev, netdev); err = profile->init(dev, netdev);
if (err) { if (err) {
netdev_warn(netdev, "rep profile init failed, %d\n", err); netdev_warn(netdev, "rep profile init failed, %d\n", err);
goto err_destroy_mdev_resources; goto err_destroy_netdev;
} }
err = mlx5e_attach_netdev(netdev_priv(netdev)); err = mlx5e_attach_netdev(netdev_priv(netdev));
...@@ -1285,13 +1182,34 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -1285,13 +1182,34 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
err_cleanup_profile: err_cleanup_profile:
priv->profile->cleanup(priv); priv->profile->cleanup(priv);
err_destroy_mdev_resources:
if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(dev);
err_destroy_netdev: err_destroy_netdev:
mlx5e_destroy_netdev(netdev_priv(netdev)); mlx5e_destroy_netdev(netdev_priv(netdev));
return err;
}
static int
mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_priv *rpriv;
int err;
rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
if (!rpriv)
return -ENOMEM;
/* rpriv->rep to be looked up when profile->init() is called */
rpriv->rep = rep;
rep->rep_data[REP_ETH].priv = rpriv;
INIT_LIST_HEAD(&rpriv->vport_sqs_list);
if (rep->vport == MLX5_VPORT_UPLINK)
err = mlx5e_vport_uplink_rep_load(dev, rep);
else
err = mlx5e_vport_vf_rep_load(dev, rep);
if (err)
kfree(rpriv); kfree(rpriv);
return err; return err;
} }
...@@ -1305,15 +1223,19 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep) ...@@ -1305,15 +1223,19 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
struct devlink_port *dl_port; struct devlink_port *dl_port;
void *ppriv = priv->ppriv; void *ppriv = priv->ppriv;
if (rep->vport == MLX5_VPORT_UPLINK) {
mlx5e_vport_uplink_rep_unload(rpriv);
goto free_ppriv;
}
dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport); dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port) if (dl_port)
devlink_port_type_clear(dl_port); devlink_port_type_clear(dl_port);
unregister_netdev(netdev); unregister_netdev(netdev);
mlx5e_detach_netdev(priv); mlx5e_detach_netdev(priv);
priv->profile->cleanup(priv); priv->profile->cleanup(priv);
if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(priv->mdev);
mlx5e_destroy_netdev(priv); mlx5e_destroy_netdev(priv);
free_ppriv:
kfree(ppriv); /* mlx5e_rep_priv */ kfree(ppriv); /* mlx5e_rep_priv */
} }
......
...@@ -220,6 +220,10 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw, ...@@ -220,6 +220,10 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw,
const struct net_device *lag_dev); const struct net_device *lag_dev);
int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup); int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup);
bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id);
int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev,
void *sp);
bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv); bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv); int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv); void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
...@@ -240,6 +244,11 @@ static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; } ...@@ -240,6 +244,11 @@ static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; }
static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {} static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {}
static inline int mlx5e_rep_init(void) { return 0; }; static inline int mlx5e_rep_init(void) { return 0; };
static inline void mlx5e_rep_cleanup(void) {}; static inline void mlx5e_rep_cleanup(void) {};
static inline bool mlx5e_rep_has_offload_stats(const struct net_device *dev,
int attr_id) { return false; }
static inline int mlx5e_rep_get_offload_stats(int attr_id,
const struct net_device *dev,
void *sp) { return -EOPNOTSUPP; }
#endif #endif
static inline bool mlx5e_is_vport_rep(struct mlx5e_priv *priv) static inline bool mlx5e_is_vport_rep(struct mlx5e_priv *priv)
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "en/health.h" #include "en/health.h"
#include "en/params.h" #include "en/params.h"
#include "devlink.h" #include "devlink.h"
#include "en/devlink.h"
static struct sk_buff * static struct sk_buff *
mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi, mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
...@@ -1823,6 +1824,7 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe ...@@ -1823,6 +1824,7 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe
struct mlx5e_priv *priv = netdev_priv(rq->netdev); struct mlx5e_priv *priv = netdev_priv(rq->netdev);
struct mlx5_wq_cyc *wq = &rq->wqe.wq; struct mlx5_wq_cyc *wq = &rq->wqe.wq;
struct mlx5e_wqe_frag_info *wi; struct mlx5e_wqe_frag_info *wi;
struct devlink_port *dl_port;
struct sk_buff *skb; struct sk_buff *skb;
u32 cqe_bcnt; u32 cqe_bcnt;
u16 trap_id; u16 trap_id;
...@@ -1845,7 +1847,8 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe ...@@ -1845,7 +1847,8 @@ static void mlx5e_trap_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
skb_push(skb, ETH_HLEN); skb_push(skb, ETH_HLEN);
mlx5_devlink_trap_report(rq->mdev, trap_id, skb, &priv->dl_port); dl_port = mlx5e_devlink_get_dl_port(priv);
mlx5_devlink_trap_report(rq->mdev, trap_id, skb, dl_port);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
free_wqe: free_wqe:
......
...@@ -4323,6 +4323,11 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, ...@@ -4323,6 +4323,11 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow; struct mlx5e_tc_flow *flow;
int err = 0; int err = 0;
if (!mlx5_esw_hold(priv->mdev))
return -EAGAIN;
mlx5_esw_get(priv->mdev);
rcu_read_lock(); rcu_read_lock();
flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params); flow = rhashtable_lookup(tc_ht, &f->cookie, tc_ht_params);
if (flow) { if (flow) {
...@@ -4360,11 +4365,14 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, ...@@ -4360,11 +4365,14 @@ int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv,
if (err) if (err)
goto err_free; goto err_free;
mlx5_esw_release(priv->mdev);
return 0; return 0;
err_free: err_free:
mlx5e_flow_put(priv, flow); mlx5e_flow_put(priv, flow);
out: out:
mlx5_esw_put(priv->mdev);
mlx5_esw_release(priv->mdev);
return err; return err;
} }
...@@ -4404,6 +4412,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv, ...@@ -4404,6 +4412,7 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
trace_mlx5e_delete_flower(f); trace_mlx5e_delete_flower(f);
mlx5e_flow_put(priv, flow); mlx5e_flow_put(priv, flow);
mlx5_esw_put(priv->mdev);
return 0; return 0;
errout: errout:
...@@ -4892,9 +4901,17 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv, ...@@ -4892,9 +4901,17 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data, int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
void *cb_priv) void *cb_priv)
{ {
unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(NIC_OFFLOAD); unsigned long flags = MLX5_TC_FLAG(INGRESS);
struct mlx5e_priv *priv = cb_priv; struct mlx5e_priv *priv = cb_priv;
if (!priv->netdev || !netif_device_present(priv->netdev))
return -EOPNOTSUPP;
if (mlx5e_is_uplink_rep(priv))
flags |= MLX5_TC_FLAG(ESW_OFFLOAD);
else
flags |= MLX5_TC_FLAG(NIC_OFFLOAD);
switch (type) { switch (type) {
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
return mlx5e_setup_tc_cls_flower(priv, type_data, flags); return mlx5e_setup_tc_cls_flower(priv, type_data, flags);
......
...@@ -435,6 +435,7 @@ static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw) ...@@ -435,6 +435,7 @@ static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
esw->fdb_table.legacy.addr_grp = NULL; esw->fdb_table.legacy.addr_grp = NULL;
esw->fdb_table.legacy.allmulti_grp = NULL; esw->fdb_table.legacy.allmulti_grp = NULL;
esw->fdb_table.legacy.promisc_grp = NULL; esw->fdb_table.legacy.promisc_grp = NULL;
atomic64_set(&esw->user_count, 0);
} }
static int esw_create_legacy_table(struct mlx5_eswitch *esw) static int esw_create_legacy_table(struct mlx5_eswitch *esw)
...@@ -442,6 +443,7 @@ static int esw_create_legacy_table(struct mlx5_eswitch *esw) ...@@ -442,6 +443,7 @@ static int esw_create_legacy_table(struct mlx5_eswitch *esw)
int err; int err;
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb)); memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
atomic64_set(&esw->user_count, 0);
err = esw_create_legacy_vepa_table(esw); err = esw_create_legacy_vepa_table(esw);
if (err) if (err)
...@@ -1720,7 +1722,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) ...@@ -1720,7 +1722,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
if (!ESW_ALLOWED(esw)) if (!ESW_ALLOWED(esw))
return 0; return 0;
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
if (esw->mode == MLX5_ESWITCH_NONE) { if (esw->mode == MLX5_ESWITCH_NONE) {
ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs); ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs);
} else { } else {
...@@ -1732,7 +1734,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) ...@@ -1732,7 +1734,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
if (!ret) if (!ret)
esw->esw_funcs.num_vfs = num_vfs; esw->esw_funcs.num_vfs = num_vfs;
} }
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return ret; return ret;
} }
...@@ -1780,10 +1782,10 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf) ...@@ -1780,10 +1782,10 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
if (!ESW_ALLOWED(esw)) if (!ESW_ALLOWED(esw))
return; return;
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
mlx5_eswitch_disable_locked(esw, clear_vf); mlx5_eswitch_disable_locked(esw, clear_vf);
esw->esw_funcs.num_vfs = 0; esw->esw_funcs.num_vfs = 0;
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
} }
int mlx5_eswitch_init(struct mlx5_core_dev *dev) int mlx5_eswitch_init(struct mlx5_core_dev *dev)
...@@ -1840,7 +1842,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) ...@@ -1840,7 +1842,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
ida_init(&esw->offloads.vport_metadata_ida); ida_init(&esw->offloads.vport_metadata_ida);
xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC); xa_init_flags(&esw->offloads.vhca_map, XA_FLAGS_ALLOC);
mutex_init(&esw->state_lock); mutex_init(&esw->state_lock);
mutex_init(&esw->mode_lock); init_rwsem(&esw->mode_lock);
mlx5_esw_for_all_vports(esw, i, vport) { mlx5_esw_for_all_vports(esw, i, vport) {
vport->vport = mlx5_eswitch_index_to_vport_num(esw, i); vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
...@@ -1876,7 +1878,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) ...@@ -1876,7 +1878,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
esw->dev->priv.eswitch = NULL; esw->dev->priv.eswitch = NULL;
destroy_workqueue(esw->work_queue); destroy_workqueue(esw->work_queue);
esw_offloads_cleanup_reps(esw); esw_offloads_cleanup_reps(esw);
mutex_destroy(&esw->mode_lock);
mutex_destroy(&esw->state_lock); mutex_destroy(&esw->state_lock);
WARN_ON(!xa_empty(&esw->offloads.vhca_map)); WARN_ON(!xa_empty(&esw->offloads.vhca_map));
xa_destroy(&esw->offloads.vhca_map); xa_destroy(&esw->offloads.vhca_map);
...@@ -2040,6 +2041,10 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, ...@@ -2040,6 +2041,10 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
vport = 0; vport = 0;
} }
mutex_lock(&esw->state_lock); mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state); err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
if (err) { if (err) {
...@@ -2111,7 +2116,7 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, ...@@ -2111,7 +2116,7 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos) u16 vport, u16 vlan, u8 qos)
{ {
u8 set_flags = 0; u8 set_flags = 0;
int err; int err = 0;
if (!ESW_ALLOWED(esw)) if (!ESW_ALLOWED(esw))
return -EPERM; return -EPERM;
...@@ -2120,9 +2125,18 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, ...@@ -2120,9 +2125,18 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT; set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
mutex_lock(&esw->state_lock); mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
if (!vlan)
goto unlock; /* compatibility with libvirt */
err = -EOPNOTSUPP;
goto unlock;
}
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags); err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
mutex_unlock(&esw->state_lock);
unlock:
mutex_unlock(&esw->state_lock);
return err; return err;
} }
...@@ -2139,6 +2153,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, ...@@ -2139,6 +2153,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
return PTR_ERR(evport); return PTR_ERR(evport);
mutex_lock(&esw->state_lock); mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
pschk = evport->info.spoofchk; pschk = evport->info.spoofchk;
evport->info.spoofchk = spoofchk; evport->info.spoofchk = spoofchk;
if (pschk && !is_valid_ether_addr(evport->info.mac)) if (pschk && !is_valid_ether_addr(evport->info.mac))
...@@ -2149,8 +2167,9 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, ...@@ -2149,8 +2167,9 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
err = esw_acl_ingress_lgcy_setup(esw, evport); err = esw_acl_ingress_lgcy_setup(esw, evport);
if (err) if (err)
evport->info.spoofchk = pschk; evport->info.spoofchk = pschk;
mutex_unlock(&esw->state_lock);
unlock:
mutex_unlock(&esw->state_lock);
return err; return err;
} }
...@@ -2271,6 +2290,7 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, ...@@ -2271,6 +2290,7 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport, bool setting) u16 vport, bool setting)
{ {
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
int err = 0;
if (!ESW_ALLOWED(esw)) if (!ESW_ALLOWED(esw))
return -EPERM; return -EPERM;
...@@ -2278,12 +2298,17 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, ...@@ -2278,12 +2298,17 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
return PTR_ERR(evport); return PTR_ERR(evport);
mutex_lock(&esw->state_lock); mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
evport->info.trusted = setting; evport->info.trusted = setting;
if (evport->enabled) if (evport->enabled)
esw_vport_change_handle_locked(evport); esw_vport_change_handle_locked(evport);
mutex_unlock(&esw->state_lock);
return 0; unlock:
mutex_unlock(&esw->state_lock);
return err;
} }
static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw) static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
...@@ -2558,3 +2583,94 @@ void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifie ...@@ -2558,3 +2583,94 @@ void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifie
{ {
blocking_notifier_chain_unregister(&esw->n_head, nb); blocking_notifier_chain_unregister(&esw->n_head, nb);
} }
/**
* mlx5_esw_hold() - Try to take a read lock on esw mode lock.
* @mdev: mlx5 core device.
*
* Should be called by esw resources callers.
*
* Return: true on success or false.
*/
bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
/* e.g. VF doesn't have eswitch so nothing to do */
if (!ESW_ALLOWED(esw))
return true;
if (down_read_trylock(&esw->mode_lock) != 0)
return true;
return false;
}
/**
* mlx5_esw_release() - Release a read lock on esw mode lock.
* @mdev: mlx5 core device.
*/
void mlx5_esw_release(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
up_read(&esw->mode_lock);
}
/**
* mlx5_esw_get() - Increase esw user count.
* @mdev: mlx5 core device.
*/
void mlx5_esw_get(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
atomic64_inc(&esw->user_count);
}
/**
* mlx5_esw_put() - Decrease esw user count.
* @mdev: mlx5 core device.
*/
void mlx5_esw_put(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
atomic64_dec_if_positive(&esw->user_count);
}
/**
* mlx5_esw_try_lock() - Take a write lock on esw mode lock.
* @esw: eswitch device.
*
* Should be called by esw mode change routine.
*
* Return:
* * 0 - esw mode if successfully locked and refcount is 0.
* * -EBUSY - refcount is not 0.
* * -EINVAL - In the middle of switching mode or lock is already held.
*/
int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
{
if (down_write_trylock(&esw->mode_lock) == 0)
return -EINVAL;
if (atomic64_read(&esw->user_count) > 0) {
up_write(&esw->mode_lock);
return -EBUSY;
}
return esw->mode;
}
/**
* mlx5_esw_unlock() - Release write lock on esw mode lock
* @esw: eswitch device.
*/
void mlx5_esw_unlock(struct mlx5_eswitch *esw)
{
up_write(&esw->mode_lock);
}
...@@ -271,7 +271,8 @@ struct mlx5_eswitch { ...@@ -271,7 +271,8 @@ struct mlx5_eswitch {
/* Protects eswitch mode change that occurs via one or more /* Protects eswitch mode change that occurs via one or more
* user commands, i.e. sriov state change, devlink commands. * user commands, i.e. sriov state change, devlink commands.
*/ */
struct mutex mode_lock; struct rw_semaphore mode_lock;
atomic64_t user_count;
struct { struct {
bool enabled; bool enabled;
...@@ -761,6 +762,14 @@ struct mlx5_esw_event_info { ...@@ -761,6 +762,14 @@ struct mlx5_esw_event_info {
int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *n); int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *n);
void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *n); void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *n);
bool mlx5_esw_hold(struct mlx5_core_dev *dev);
void mlx5_esw_release(struct mlx5_core_dev *dev);
void mlx5_esw_get(struct mlx5_core_dev *dev);
void mlx5_esw_put(struct mlx5_core_dev *dev);
int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
void mlx5_esw_unlock(struct mlx5_eswitch *esw);
#else /* CONFIG_MLX5_ESWITCH */ #else /* CONFIG_MLX5_ESWITCH */
/* eswitch API stubs */ /* eswitch API stubs */
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
...@@ -781,6 +790,13 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag) ...@@ -781,6 +790,13 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
{ {
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
} }
static inline unsigned int
mlx5_esw_vport_to_devlink_port_index(const struct mlx5_core_dev *dev,
u16 vport_num)
{
return vport_num;
}
#endif /* CONFIG_MLX5_ESWITCH */ #endif /* CONFIG_MLX5_ESWITCH */
#endif /* __MLX5_ESWITCH_H__ */ #endif /* __MLX5_ESWITCH_H__ */
...@@ -1854,6 +1854,7 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw) ...@@ -1854,6 +1854,7 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
/* Holds true only as long as DMFS is the default */ /* Holds true only as long as DMFS is the default */
mlx5_flow_namespace_set_mode(esw->fdb_table.offloads.ns, mlx5_flow_namespace_set_mode(esw->fdb_table.offloads.ns,
MLX5_FLOW_STEERING_MODE_DMFS); MLX5_FLOW_STEERING_MODE_DMFS);
atomic64_set(&esw->user_count, 0);
} }
static int esw_create_offloads_table(struct mlx5_eswitch *esw) static int esw_create_offloads_table(struct mlx5_eswitch *esw)
...@@ -2259,9 +2260,11 @@ int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) ...@@ -2259,9 +2260,11 @@ int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
if (esw->mode != MLX5_ESWITCH_OFFLOADS) if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return 0; return 0;
if (vport_num != MLX5_VPORT_UPLINK) {
err = mlx5_esw_offloads_devlink_port_register(esw, vport_num); err = mlx5_esw_offloads_devlink_port_register(esw, vport_num);
if (err) if (err)
return err; return err;
}
err = mlx5_esw_offloads_rep_load(esw, vport_num); err = mlx5_esw_offloads_rep_load(esw, vport_num);
if (err) if (err)
...@@ -2269,6 +2272,7 @@ int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num) ...@@ -2269,6 +2272,7 @@ int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
return err; return err;
load_err: load_err:
if (vport_num != MLX5_VPORT_UPLINK)
mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
return err; return err;
} }
...@@ -2279,6 +2283,8 @@ void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num) ...@@ -2279,6 +2283,8 @@ void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num)
return; return;
mlx5_esw_offloads_rep_unload(esw, vport_num); mlx5_esw_offloads_rep_unload(esw, vport_num);
if (vport_num != MLX5_VPORT_UPLINK)
mlx5_esw_offloads_devlink_port_unregister(esw, vport_num); mlx5_esw_offloads_devlink_port_unregister(esw, vport_num);
} }
...@@ -2579,6 +2585,7 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw) ...@@ -2579,6 +2585,7 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb)); memset(&esw->fdb_table.offloads, 0, sizeof(struct offloads_fdb));
mutex_init(&esw->fdb_table.offloads.vports.lock); mutex_init(&esw->fdb_table.offloads.vports.lock);
hash_init(esw->fdb_table.offloads.vports.table); hash_init(esw->fdb_table.offloads.vports.table);
atomic64_set(&esw->user_count, 0);
indir = mlx5_esw_indir_table_init(); indir = mlx5_esw_indir_table_init();
if (IS_ERR(indir)) { if (IS_ERR(indir)) {
...@@ -2920,8 +2927,14 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, ...@@ -2920,8 +2927,14 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
if (esw_mode_from_devlink(mode, &mlx5_mode)) if (esw_mode_from_devlink(mode, &mlx5_mode))
return -EINVAL; return -EINVAL;
mutex_lock(&esw->mode_lock); err = mlx5_esw_try_lock(esw);
cur_mlx5_mode = esw->mode; if (err < 0) {
NL_SET_ERR_MSG_MOD(extack, "Can't change mode, E-Switch is busy");
return err;
}
cur_mlx5_mode = err;
err = 0;
if (cur_mlx5_mode == mlx5_mode) if (cur_mlx5_mode == mlx5_mode)
goto unlock; goto unlock;
...@@ -2933,7 +2946,7 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, ...@@ -2933,7 +2946,7 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
err = -EINVAL; err = -EINVAL;
unlock: unlock:
mutex_unlock(&esw->mode_lock); mlx5_esw_unlock(esw);
return err; return err;
} }
...@@ -2946,14 +2959,14 @@ int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) ...@@ -2946,14 +2959,14 @@ int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
if (IS_ERR(esw)) if (IS_ERR(esw))
return PTR_ERR(esw); return PTR_ERR(esw);
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
err = eswitch_devlink_esw_mode_check(esw); err = eswitch_devlink_esw_mode_check(esw);
if (err) if (err)
goto unlock; goto unlock;
err = esw_mode_to_devlink(esw->mode, mode); err = esw_mode_to_devlink(esw->mode, mode);
unlock: unlock:
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return err; return err;
} }
...@@ -2969,7 +2982,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, ...@@ -2969,7 +2982,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
if (IS_ERR(esw)) if (IS_ERR(esw))
return PTR_ERR(esw); return PTR_ERR(esw);
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
err = eswitch_devlink_esw_mode_check(esw); err = eswitch_devlink_esw_mode_check(esw);
if (err) if (err)
goto out; goto out;
...@@ -3008,7 +3021,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, ...@@ -3008,7 +3021,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
} }
esw->offloads.inline_mode = mlx5_mode; esw->offloads.inline_mode = mlx5_mode;
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return 0; return 0;
revert_inline_mode: revert_inline_mode:
...@@ -3018,7 +3031,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, ...@@ -3018,7 +3031,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
vport, vport,
esw->offloads.inline_mode); esw->offloads.inline_mode);
out: out:
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return err; return err;
} }
...@@ -3031,14 +3044,14 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode) ...@@ -3031,14 +3044,14 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
if (IS_ERR(esw)) if (IS_ERR(esw))
return PTR_ERR(esw); return PTR_ERR(esw);
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
err = eswitch_devlink_esw_mode_check(esw); err = eswitch_devlink_esw_mode_check(esw);
if (err) if (err)
goto unlock; goto unlock;
err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode); err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
unlock: unlock:
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return err; return err;
} }
...@@ -3054,7 +3067,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, ...@@ -3054,7 +3067,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
if (IS_ERR(esw)) if (IS_ERR(esw))
return PTR_ERR(esw); return PTR_ERR(esw);
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
err = eswitch_devlink_esw_mode_check(esw); err = eswitch_devlink_esw_mode_check(esw);
if (err) if (err)
goto unlock; goto unlock;
...@@ -3100,7 +3113,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, ...@@ -3100,7 +3113,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
} }
unlock: unlock:
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return err; return err;
} }
...@@ -3115,14 +3128,14 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, ...@@ -3115,14 +3128,14 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
return PTR_ERR(esw); return PTR_ERR(esw);
mutex_lock(&esw->mode_lock); down_write(&esw->mode_lock);
err = eswitch_devlink_esw_mode_check(esw); err = eswitch_devlink_esw_mode_check(esw);
if (err) if (err)
goto unlock; goto unlock;
*encap = esw->offloads.encap; *encap = esw->offloads.encap;
unlock: unlock:
mutex_unlock(&esw->mode_lock); up_write(&esw->mode_lock);
return 0; return 0;
} }
......
...@@ -708,7 +708,7 @@ static void mlx5_rdma_netdev_free(struct net_device *netdev) ...@@ -708,7 +708,7 @@ static void mlx5_rdma_netdev_free(struct net_device *netdev)
static bool mlx5_is_sub_interface(struct mlx5_core_dev *mdev) static bool mlx5_is_sub_interface(struct mlx5_core_dev *mdev)
{ {
return mdev->mlx5e_res.pdn != 0; return mdev->mlx5e_res.hw_objs.pdn != 0;
} }
static const struct mlx5e_profile *mlx5_get_profile(struct mlx5_core_dev *mdev) static const struct mlx5e_profile *mlx5_get_profile(struct mlx5_core_dev *mdev)
......
...@@ -46,7 +46,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev, ...@@ -46,7 +46,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
MLX5_CMD_OP_CREATE_GENERAL_OBJECT); MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
MLX5_GENERAL_OBJECT_TYPES_ENCRYPTION_KEY); MLX5_GENERAL_OBJECT_TYPES_ENCRYPTION_KEY);
MLX5_SET(encryption_key_obj, obj, pd, mdev->mlx5e_res.pdn); MLX5_SET(encryption_key_obj, obj, pd, mdev->mlx5e_res.hw_objs.pdn);
err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
if (!err) if (!err)
......
...@@ -95,4 +95,13 @@ static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev) ...@@ -95,4 +95,13 @@ static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
return devlink_net(priv_to_devlink(dev)); return devlink_net(priv_to_devlink(dev));
} }
static inline void mlx5_uplink_netdev_set(struct mlx5_core_dev *mdev, struct net_device *netdev)
{
mdev->mlx5e_res.uplink_netdev = netdev;
}
static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev)
{
return mdev->mlx5e_res.uplink_netdev;
}
#endif #endif
...@@ -644,10 +644,14 @@ struct mlx5_td { ...@@ -644,10 +644,14 @@ struct mlx5_td {
}; };
struct mlx5e_resources { struct mlx5e_resources {
struct mlx5e_hw_objs {
u32 pdn; u32 pdn;
struct mlx5_td td; struct mlx5_td td;
struct mlx5_core_mkey mkey; struct mlx5_core_mkey mkey;
struct mlx5_sq_bfreg bfreg; struct mlx5_sq_bfreg bfreg;
} hw_objs;
struct devlink_port dl_port;
struct net_device *uplink_netdev;
}; };
enum mlx5_sw_icm_type { enum mlx5_sw_icm_type {
......
...@@ -4175,7 +4175,7 @@ static inline bool netif_oper_up(const struct net_device *dev) ...@@ -4175,7 +4175,7 @@ static inline bool netif_oper_up(const struct net_device *dev)
* *
* Check if device has not been removed from system. * Check if device has not been removed from system.
*/ */
static inline bool netif_device_present(struct net_device *dev) static inline bool netif_device_present(const struct net_device *dev)
{ {
return test_bit(__LINK_STATE_PRESENT, &dev->state); return test_bit(__LINK_STATE_PRESENT, &dev->state);
} }
......
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