diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 18:50:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 18:50:36 +0000 |
commit | 50ba0232fd5312410f1b65247e774244f89a628e (patch) | |
tree | fd8f2fc78e9e548af0ff9590276602ee6125be00 /drivers/net/ethernet/mellanox | |
parent | Releasing progress-linux version 6.7.12-1~progress7.99u1. (diff) | |
download | linux-50ba0232fd5312410f1b65247e774244f89a628e.tar.xz linux-50ba0232fd5312410f1b65247e774244f89a628e.zip |
Merging upstream version 6.8.9.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
71 files changed, 1951 insertions, 681 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 164a13272f..619e1c3ef7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1258,8 +1258,8 @@ static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc) return -EINVAL; } -static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key, - u8 *hfunc) +static int mlx4_en_get_rxfh(struct net_device *dev, + struct ethtool_rxfh_param *rxfh) { struct mlx4_en_priv *priv = netdev_priv(dev); u32 n = mlx4_en_get_rxfh_indir_size(dev); @@ -1269,19 +1269,19 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key, rss_rings = rounddown_pow_of_two(rss_rings); for (i = 0; i < n; i++) { - if (!ring_index) + if (!rxfh->indir) break; - ring_index[i] = i % rss_rings; + rxfh->indir[i] = i % rss_rings; } - if (key) - memcpy(key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE); - if (hfunc) - *hfunc = priv->rss_hash_fn; + if (rxfh->key) + memcpy(rxfh->key, priv->rss_key, MLX4_EN_RSS_KEY_SIZE); + rxfh->hfunc = priv->rss_hash_fn; return 0; } -static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, - const u8 *key, const u8 hfunc) +static int mlx4_en_set_rxfh(struct net_device *dev, + struct ethtool_rxfh_param *rxfh, + struct netlink_ext_ack *extack) { struct mlx4_en_priv *priv = netdev_priv(dev); u32 n = mlx4_en_get_rxfh_indir_size(dev); @@ -1295,12 +1295,12 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, * between rings */ for (i = 0; i < n; i++) { - if (!ring_index) + if (!rxfh->indir) break; - if (i > 0 && !ring_index[i] && !rss_rings) + if (i > 0 && !rxfh->indir[i] && !rss_rings) rss_rings = i; - if (ring_index[i] != (i % (rss_rings ?: n))) + if (rxfh->indir[i] != (i % (rss_rings ?: n))) return -EINVAL; } @@ -1311,8 +1311,8 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, if (!is_power_of_2(rss_rings)) return -EINVAL; - if (hfunc != ETH_RSS_HASH_NO_CHANGE) { - err = mlx4_en_check_rxfh_func(dev, hfunc); + if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE) { + err = mlx4_en_check_rxfh_func(dev, rxfh->hfunc); if (err) return err; } @@ -1323,12 +1323,12 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index, mlx4_en_stop_port(dev, 1); } - if (ring_index) + if (rxfh->indir) priv->prof->rss_rings = rss_rings; - if (key) - memcpy(priv->rss_key, key, MLX4_EN_RSS_KEY_SIZE); - if (hfunc != ETH_RSS_HASH_NO_CHANGE) - priv->rss_hash_fn = hfunc; + if (rxfh->key) + memcpy(priv->rss_key, rxfh->key, MLX4_EN_RSS_KEY_SIZE); + if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE) + priv->rss_hash_fn = rxfh->hfunc; if (port_up) { err = mlx4_en_start_port(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/crdump.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/crdump.c index 28d02749d3..7659ad21e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/crdump.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/crdump.c @@ -55,7 +55,10 @@ int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data) ret = mlx5_vsc_sem_set_space(dev, MLX5_SEMAPHORE_SW_RESET, MLX5_VSC_LOCK); if (ret) { - mlx5_core_warn(dev, "Failed to lock SW reset semaphore\n"); + if (ret == -EBUSY) + mlx5_core_info(dev, "SW reset semaphore is already in use\n"); + else + mlx5_core_warn(dev, "Failed to lock SW reset semaphore\n"); goto unlock_gw; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c index 8ce5c8bcda..d74a5aaf42 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c @@ -36,11 +36,17 @@ static int mlx5_dpll_clock_id_get(struct mlx5_core_dev *mdev, u64 *clock_id) return 0; } +struct mlx5_dpll_synce_status { + enum mlx5_msees_admin_status admin_status; + enum mlx5_msees_oper_status oper_status; + bool ho_acq; + bool oper_freq_measure; + s32 frequency_diff; +}; + static int mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev, - enum mlx5_msees_admin_status *admin_status, - enum mlx5_msees_oper_status *oper_status, - bool *ho_acq) + struct mlx5_dpll_synce_status *synce_status) { u32 out[MLX5_ST_SZ_DW(msees_reg)] = {}; u32 in[MLX5_ST_SZ_DW(msees_reg)] = {}; @@ -50,11 +56,11 @@ mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev, MLX5_REG_MSEES, 0, 0); if (err) return err; - if (admin_status) - *admin_status = MLX5_GET(msees_reg, out, admin_status); - *oper_status = MLX5_GET(msees_reg, out, oper_status); - if (ho_acq) - *ho_acq = MLX5_GET(msees_reg, out, ho_acq); + synce_status->admin_status = MLX5_GET(msees_reg, out, admin_status); + synce_status->oper_status = MLX5_GET(msees_reg, out, oper_status); + synce_status->ho_acq = MLX5_GET(msees_reg, out, ho_acq); + synce_status->oper_freq_measure = MLX5_GET(msees_reg, out, oper_freq_measure); + synce_status->frequency_diff = MLX5_GET(msees_reg, out, frequency_diff); return 0; } @@ -67,21 +73,23 @@ mlx5_dpll_synce_status_set(struct mlx5_core_dev *mdev, MLX5_SET(msees_reg, in, field_select, MLX5_MSEES_FIELD_SELECT_ENABLE | + MLX5_MSEES_FIELD_SELECT_ADMIN_FREQ_MEASURE | MLX5_MSEES_FIELD_SELECT_ADMIN_STATUS); MLX5_SET(msees_reg, in, admin_status, admin_status); + MLX5_SET(msees_reg, in, admin_freq_measure, true); return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_MSEES, 0, 1); } static enum dpll_lock_status -mlx5_dpll_lock_status_get(enum mlx5_msees_oper_status oper_status, bool ho_acq) +mlx5_dpll_lock_status_get(struct mlx5_dpll_synce_status *synce_status) { - switch (oper_status) { + switch (synce_status->oper_status) { case MLX5_MSEES_OPER_STATUS_SELF_TRACK: fallthrough; case MLX5_MSEES_OPER_STATUS_OTHER_TRACK: - return ho_acq ? DPLL_LOCK_STATUS_LOCKED_HO_ACQ : - DPLL_LOCK_STATUS_LOCKED; + return synce_status->ho_acq ? DPLL_LOCK_STATUS_LOCKED_HO_ACQ : + DPLL_LOCK_STATUS_LOCKED; case MLX5_MSEES_OPER_STATUS_HOLDOVER: fallthrough; case MLX5_MSEES_OPER_STATUS_FAIL_HOLDOVER: @@ -92,31 +100,37 @@ mlx5_dpll_lock_status_get(enum mlx5_msees_oper_status oper_status, bool ho_acq) } static enum dpll_pin_state -mlx5_dpll_pin_state_get(enum mlx5_msees_admin_status admin_status, - enum mlx5_msees_oper_status oper_status) +mlx5_dpll_pin_state_get(struct mlx5_dpll_synce_status *synce_status) { - return (admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK && - (oper_status == MLX5_MSEES_OPER_STATUS_SELF_TRACK || - oper_status == MLX5_MSEES_OPER_STATUS_OTHER_TRACK)) ? + return (synce_status->admin_status == MLX5_MSEES_ADMIN_STATUS_TRACK && + (synce_status->oper_status == MLX5_MSEES_OPER_STATUS_SELF_TRACK || + synce_status->oper_status == MLX5_MSEES_OPER_STATUS_OTHER_TRACK)) ? DPLL_PIN_STATE_CONNECTED : DPLL_PIN_STATE_DISCONNECTED; } +static int +mlx5_dpll_pin_ffo_get(struct mlx5_dpll_synce_status *synce_status, + s64 *ffo) +{ + if (!synce_status->oper_freq_measure) + return -ENODATA; + *ffo = synce_status->frequency_diff; + return 0; +} + static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, void *priv, enum dpll_lock_status *status, struct netlink_ext_ack *extack) { - enum mlx5_msees_oper_status oper_status; + struct mlx5_dpll_synce_status synce_status; struct mlx5_dpll *mdpll = priv; - bool ho_acq; int err; - err = mlx5_dpll_synce_status_get(mdpll->mdev, NULL, - &oper_status, &ho_acq); + err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); if (err) return err; - - *status = mlx5_dpll_lock_status_get(oper_status, ho_acq); + *status = mlx5_dpll_lock_status_get(&synce_status); return 0; } @@ -128,18 +142,9 @@ static int mlx5_dpll_device_mode_get(const struct dpll_device *dpll, return 0; } -static bool mlx5_dpll_device_mode_supported(const struct dpll_device *dpll, - void *priv, - enum dpll_mode mode, - struct netlink_ext_ack *extack) -{ - return mode == DPLL_MODE_MANUAL; -} - static const struct dpll_device_ops mlx5_dpll_device_ops = { .lock_status_get = mlx5_dpll_device_lock_status_get, .mode_get = mlx5_dpll_device_mode_get, - .mode_supported = mlx5_dpll_device_mode_supported, }; static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin, @@ -160,16 +165,14 @@ static int mlx5_dpll_state_on_dpll_get(const struct dpll_pin *pin, enum dpll_pin_state *state, struct netlink_ext_ack *extack) { - enum mlx5_msees_admin_status admin_status; - enum mlx5_msees_oper_status oper_status; + struct mlx5_dpll_synce_status synce_status; struct mlx5_dpll *mdpll = pin_priv; int err; - err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status, - &oper_status, NULL); + err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); if (err) return err; - *state = mlx5_dpll_pin_state_get(admin_status, oper_status); + *state = mlx5_dpll_pin_state_get(&synce_status); return 0; } @@ -188,10 +191,25 @@ static int mlx5_dpll_state_on_dpll_set(const struct dpll_pin *pin, MLX5_MSEES_ADMIN_STATUS_FREE_RUNNING); } +static int mlx5_dpll_ffo_get(const struct dpll_pin *pin, void *pin_priv, + const struct dpll_device *dpll, void *dpll_priv, + s64 *ffo, struct netlink_ext_ack *extack) +{ + struct mlx5_dpll_synce_status synce_status; + struct mlx5_dpll *mdpll = pin_priv; + int err; + + err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); + if (err) + return err; + return mlx5_dpll_pin_ffo_get(&synce_status, ffo); +} + static const struct dpll_pin_ops mlx5_dpll_pins_ops = { .direction_get = mlx5_dpll_pin_direction_get, .state_on_dpll_get = mlx5_dpll_state_on_dpll_get, .state_on_dpll_set = mlx5_dpll_state_on_dpll_set, + .ffo_get = mlx5_dpll_ffo_get, }; static const struct dpll_pin_properties mlx5_dpll_pin_properties = { @@ -211,19 +229,16 @@ static void mlx5_dpll_periodic_work(struct work_struct *work) { struct mlx5_dpll *mdpll = container_of(work, struct mlx5_dpll, work.work); - enum mlx5_msees_admin_status admin_status; - enum mlx5_msees_oper_status oper_status; + struct mlx5_dpll_synce_status synce_status; enum dpll_lock_status lock_status; enum dpll_pin_state pin_state; - bool ho_acq; int err; - err = mlx5_dpll_synce_status_get(mdpll->mdev, &admin_status, - &oper_status, &ho_acq); + err = mlx5_dpll_synce_status_get(mdpll->mdev, &synce_status); if (err) goto err_out; - lock_status = mlx5_dpll_lock_status_get(oper_status, ho_acq); - pin_state = mlx5_dpll_pin_state_get(admin_status, oper_status); + lock_status = mlx5_dpll_lock_status_get(&synce_status); + pin_state = mlx5_dpll_pin_state_get(&synce_status); if (!mdpll->last.valid) goto invalid_out; @@ -246,7 +261,7 @@ static void mlx5_dpll_netdev_dpll_pin_set(struct mlx5_dpll *mdpll, { if (mdpll->tracking_netdev) return; - netdev_dpll_pin_set(netdev, mdpll->dpll_pin); + dpll_netdev_pin_set(netdev, mdpll->dpll_pin); mdpll->tracking_netdev = netdev; } @@ -254,7 +269,7 @@ static void mlx5_dpll_netdev_dpll_pin_clear(struct mlx5_dpll *mdpll) { if (!mdpll->tracking_netdev) return; - netdev_dpll_pin_clear(mdpll->tracking_netdev); + dpll_netdev_pin_clear(mdpll->tracking_netdev); mdpll->tracking_netdev = NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 729a11b5fb..55c6ace0ac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -72,7 +72,6 @@ struct page_pool; #define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) #define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) -#define MLX5E_MAX_NUM_TC 8 #define MLX5E_MAX_NUM_MQPRIO_CH_TC TC_QOPT_MAX_QUEUE #define MLX5_RX_HEADROOM NET_SKB_PAD @@ -364,7 +363,7 @@ struct mlx5e_cq { /* control */ struct net_device *netdev; struct mlx5_core_dev *mdev; - struct mlx5e_priv *priv; + struct workqueue_struct *workqueue; struct mlx5_wq_ctrl wq_ctrl; } ____cacheline_aligned_in_smp; @@ -484,10 +483,12 @@ struct mlx5e_xdp_info_fifo { struct mlx5e_xdpsq; struct mlx5e_xmit_data; +struct xsk_tx_metadata; typedef int (*mlx5e_fp_xmit_xdp_frame_check)(struct mlx5e_xdpsq *); typedef bool (*mlx5e_fp_xmit_xdp_frame)(struct mlx5e_xdpsq *, struct mlx5e_xmit_data *, - int); + int, + struct xsk_tx_metadata *); struct mlx5e_xdpsq { /* data path */ @@ -756,7 +757,7 @@ struct mlx5e_channel { /* data path */ struct mlx5e_rq rq; struct mlx5e_xdpsq rq_xdpsq; - struct mlx5e_txqsq sq[MLX5E_MAX_NUM_TC]; + struct mlx5e_txqsq sq[MLX5_MAX_NUM_TC]; struct mlx5e_icosq icosq; /* internal control operations */ struct mlx5e_txqsq __rcu * __rcu *qos_sqs; bool xdp; @@ -806,7 +807,7 @@ struct mlx5e_channels { struct mlx5e_channel_stats { struct mlx5e_ch_stats ch; - struct mlx5e_sq_stats sq[MLX5E_MAX_NUM_TC]; + struct mlx5e_sq_stats sq[MLX5_MAX_NUM_TC]; struct mlx5e_rq_stats rq; struct mlx5e_rq_stats xskrq; struct mlx5e_xdpsq_stats rq_xdpsq; @@ -816,8 +817,8 @@ struct mlx5e_channel_stats { struct mlx5e_ptp_stats { struct mlx5e_ch_stats ch; - struct mlx5e_sq_stats sq[MLX5E_MAX_NUM_TC]; - struct mlx5e_ptp_cq_stats cq[MLX5E_MAX_NUM_TC]; + struct mlx5e_sq_stats sq[MLX5_MAX_NUM_TC]; + struct mlx5e_ptp_cq_stats cq[MLX5_MAX_NUM_TC]; struct mlx5e_rq_stats rq; } ____cacheline_aligned_in_smp; @@ -885,7 +886,6 @@ struct mlx5e_priv { struct mlx5e_rq drop_rq; struct mlx5e_channels channels; - u32 tisn[MLX5_MAX_PORTS][MLX5E_MAX_NUM_TC]; struct mlx5e_rx_res *rx_res; u32 *tx_rates; @@ -983,6 +983,8 @@ struct mlx5e_profile { void (*update_stats)(struct mlx5e_priv *priv); void (*update_carrier)(struct mlx5e_priv *priv); int (*max_nch_limit)(struct mlx5_core_dev *mdev); + u32 (*get_tisn)(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv, + u8 lag_port, u8 tc); unsigned int (*stats_grps_num)(struct mlx5e_priv *priv); mlx5e_stats_grp_t *stats_grps; const struct mlx5e_rx_handlers *rx_handlers; @@ -990,6 +992,11 @@ struct mlx5e_profile { u32 features; }; +u32 mlx5e_profile_get_tisn(struct mlx5_core_dev *mdev, + struct mlx5e_priv *priv, + const struct mlx5e_profile *profile, + u8 lag_port, u8 tc); + #define mlx5e_profile_feature_cap(profile, feature) \ ((profile)->features & BIT(MLX5E_PROFILE_FEATURE_##feature)) @@ -1037,6 +1044,8 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq); struct mlx5e_create_cq_param { + struct net_device *netdev; + struct workqueue_struct *wq; struct napi_struct *napi; struct mlx5e_ch_stats *ch_stats; int node; @@ -1044,7 +1053,7 @@ struct mlx5e_create_cq_param { }; struct mlx5e_cq_param; -int mlx5e_open_cq(struct mlx5e_priv *priv, struct dim_cq_moder moder, +int mlx5e_open_cq(struct mlx5_core_dev *mdev, struct dim_cq_moder moder, struct mlx5e_cq_param *param, struct mlx5e_create_cq_param *ccp, struct mlx5e_cq *cq); void mlx5e_close_cq(struct mlx5e_cq *cq); @@ -1115,7 +1124,7 @@ static inline bool mlx5_tx_swp_supported(struct mlx5_core_dev *mdev) extern const struct ethtool_ops mlx5e_ethtool_ops; int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey); -int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev); +int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises); void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev); int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, bool enable_mc_lb); @@ -1131,8 +1140,6 @@ void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq); int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn); void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn); -int mlx5e_create_tises(struct mlx5e_priv *priv); -void mlx5e_destroy_tises(struct mlx5e_priv *priv); int mlx5e_update_nic_rx(struct mlx5e_priv *priv); void mlx5e_update_carrier(struct mlx5e_priv *priv); int mlx5e_close(struct net_device *netdev); @@ -1174,9 +1181,9 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, struct ethtool_link_ksettings *link_ksettings); int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, const struct ethtool_link_ksettings *link_ksettings); -int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc); -int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, - const u8 hfunc); +int mlx5e_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh); +int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh, + struct netlink_ext_ack *extack); u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv); u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv); int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c index 254c847390..40c8df1117 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c @@ -36,7 +36,7 @@ int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv) return true; } -void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv) +static void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv) { u32 in[MLX5_ST_SZ_DW(arm_monitor_counter_in)] = {}; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.h index e1ac4b3d22..6beba7f075 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.h @@ -7,6 +7,5 @@ int mlx5e_monitor_counter_supported(struct mlx5e_priv *priv); void mlx5e_monitor_counter_init(struct mlx5e_priv *priv); void mlx5e_monitor_counter_cleanup(struct mlx5e_priv *priv); -void mlx5e_monitor_counter_arm(struct mlx5e_priv *priv); #endif /* __MLX5_MONITOR_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 30507b7c2f..5d213a9886 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -669,6 +669,8 @@ void mlx5e_build_rq_params(struct mlx5_core_dev *mdev, void mlx5e_build_create_cq_param(struct mlx5e_create_cq_param *ccp, struct mlx5e_channel *c) { *ccp = (struct mlx5e_create_cq_param) { + .netdev = c->netdev, + .wq = c->priv->wq, .napi = &c->napi, .ch_stats = c->stats, .node = cpu_to_node(c->cpu), diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index 15d97c685a..ca05b3252a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -518,9 +518,11 @@ static int mlx5e_ptp_open_txqsqs(struct mlx5e_ptp *c, for (tc = 0; tc < num_tc; tc++) { int txq_ix = ix_base + tc; + u32 tisn; - err = mlx5e_ptp_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix, - cparams, tc, &c->ptpsq[tc]); + tisn = mlx5e_profile_get_tisn(c->mdev, c->priv, c->priv->profile, + c->lag_port, tc); + err = mlx5e_ptp_open_txqsq(c, tisn, txq_ix, cparams, tc, &c->ptpsq[tc]); if (err) goto close_txqsq; } @@ -555,6 +557,8 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c, num_tc = mlx5e_get_dcb_num_tc(params); + ccp.netdev = c->netdev; + ccp.wq = c->priv->wq; ccp.node = dev_to_node(mlx5_core_dma_dev(c->mdev)); ccp.ch_stats = c->stats; ccp.napi = &c->napi; @@ -565,7 +569,7 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c, for (tc = 0; tc < num_tc; tc++) { struct mlx5e_cq *cq = &c->ptpsq[tc].txqsq.cq; - err = mlx5e_open_cq(c->priv, ptp_moder, cq_param, &ccp, cq); + err = mlx5e_open_cq(c->mdev, ptp_moder, cq_param, &ccp, cq); if (err) goto out_err_txqsq_cq; } @@ -574,7 +578,7 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c, struct mlx5e_cq *cq = &c->ptpsq[tc].ts_cq; struct mlx5e_ptpsq *ptpsq = &c->ptpsq[tc]; - err = mlx5e_open_cq(c->priv, ptp_moder, cq_param, &ccp, cq); + err = mlx5e_open_cq(c->mdev, ptp_moder, cq_param, &ccp, cq); if (err) goto out_err_ts_cq; @@ -602,6 +606,8 @@ static int mlx5e_ptp_open_rx_cq(struct mlx5e_ptp *c, struct mlx5e_cq_param *cq_param; struct mlx5e_cq *cq = &c->rq.cq; + ccp.netdev = c->netdev; + ccp.wq = c->priv->wq; ccp.node = dev_to_node(mlx5_core_dma_dev(c->mdev)); ccp.ch_stats = c->stats; ccp.napi = &c->napi; @@ -609,7 +615,7 @@ static int mlx5e_ptp_open_rx_cq(struct mlx5e_ptp *c, cq_param = &cparams->rq_param.cqp; - return mlx5e_open_cq(c->priv, ptp_moder, cq_param, &ccp, cq); + return mlx5e_open_cq(c->mdev, ptp_moder, cq_param, &ccp, cq); } static void mlx5e_ptp_close_tx_cqs(struct mlx5e_ptp *c) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index 7b700d0f95..883c044852 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -49,7 +49,7 @@ enum { struct mlx5e_ptp { /* data path */ - struct mlx5e_ptpsq ptpsq[MLX5E_MAX_NUM_TC]; + struct mlx5e_ptpsq ptpsq[MLX5_MAX_NUM_TC]; struct mlx5e_rq rq; struct napi_struct napi; struct device *pdev; @@ -95,9 +95,15 @@ static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo * } static inline u8 +mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo) +{ + return fifo->data[fifo->mask & fifo->cc]; +} + +static inline void mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo) { - return fifo->data[fifo->mask & fifo->cc++]; + fifo->cc++; } static inline void diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c index 244bc15a42..922bc5b7c1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c @@ -77,29 +77,31 @@ int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, struct mlx5e_params *params; struct mlx5e_channel *c; struct mlx5e_txqsq *sq; + u32 tisn; params = &chs->params; txq_ix = mlx5e_qid_from_qos(chs, node_qid); - WARN_ON(node_qid > priv->htb_max_qos_sqs); - if (node_qid == priv->htb_max_qos_sqs) { - struct mlx5e_sq_stats *stats, **stats_list = NULL; + WARN_ON(node_qid >= mlx5e_htb_cur_leaf_nodes(priv->htb)); + if (!priv->htb_qos_sq_stats) { + struct mlx5e_sq_stats **stats_list; + + stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev), + sizeof(*stats_list), GFP_KERNEL); + if (!stats_list) + return -ENOMEM; + + WRITE_ONCE(priv->htb_qos_sq_stats, stats_list); + } + + if (!priv->htb_qos_sq_stats[node_qid]) { + struct mlx5e_sq_stats *stats; - if (priv->htb_max_qos_sqs == 0) { - stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev), - sizeof(*stats_list), - GFP_KERNEL); - if (!stats_list) - return -ENOMEM; - } stats = kzalloc(sizeof(*stats), GFP_KERNEL); - if (!stats) { - kvfree(stats_list); + if (!stats) return -ENOMEM; - } - if (stats_list) - WRITE_ONCE(priv->htb_qos_sq_stats, stats_list); + WRITE_ONCE(priv->htb_qos_sq_stats[node_qid], stats); /* Order htb_max_qos_sqs increment after writing the array pointer. * Pairs with smp_load_acquire in en_stats.c. @@ -123,11 +125,13 @@ int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, memset(¶m_cq, 0, sizeof(param_cq)); mlx5e_build_sq_param(priv->mdev, params, ¶m_sq); mlx5e_build_tx_cq_param(priv->mdev, params, ¶m_cq); - err = mlx5e_open_cq(priv, params->tx_cq_moderation, ¶m_cq, &ccp, &sq->cq); + err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, ¶m_cq, &ccp, &sq->cq); if (err) goto err_free_sq; - err = mlx5e_open_txqsq(c, priv->tisn[c->lag_port][0], txq_ix, params, - ¶m_sq, sq, 0, hw_id, + + tisn = mlx5e_profile_get_tisn(c->mdev, c->priv, c->priv->profile, + c->lag_port, 0); + err = mlx5e_open_txqsq(c, tisn, txq_ix, params, ¶m_sq, sq, 0, hw_id, priv->htb_qos_sq_stats[node_qid]); if (err) goto err_close_cq; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c index b12fe3c5a2..a55452c69f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c @@ -147,6 +147,20 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv, } } +static void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, + struct tc_cls_matchall_offload *ma) +{ + struct mlx5e_rep_priv *rpriv = priv->ppriv; + u64 dbytes; + u64 dpkts; + + dpkts = priv->stats.rep_stats.vport_rx_packets - rpriv->prev_vf_vport_stats.rx_packets; + dbytes = priv->stats.rep_stats.vport_rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes; + mlx5e_stats_copy_rep_stats(&rpriv->prev_vf_vport_stats, &priv->stats.rep_stats); + flow_stats_update(&ma->stats, dbytes, dpkts, 0, jiffies, + FLOW_ACTION_HW_STATS_DELAYED); +} + static int mlx5e_rep_setup_tc_cls_matchall(struct mlx5e_priv *priv, struct tc_cls_matchall_offload *ma) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c index f675b19263..f66bbc8464 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c @@ -57,6 +57,7 @@ int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock) void mlx5e_selq_cleanup(struct mlx5e_selq *selq) { + mutex_lock(selq->state_lock); WARN_ON_ONCE(selq->is_prepared); kvfree(selq->standby); @@ -67,6 +68,7 @@ void mlx5e_selq_cleanup(struct mlx5e_selq *selq) kvfree(selq->standby); selq->standby = NULL; + mutex_unlock(selq->state_lock); } void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c index 368a95fa77..b14cd62edf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c @@ -48,7 +48,8 @@ mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv, struct pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { - u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1; + u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? TCA_PEDIT_KEY_EX_CMD_SET : + TCA_PEDIT_KEY_EX_CMD_ADD; u8 htype = act->mangle.htype; int err = -EOPNOTSUPP; u32 mask, val, offset; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c index 5620d9f975..ac458a8d10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/trap.c @@ -68,11 +68,13 @@ static int mlx5e_open_trap_rq(struct mlx5e_priv *priv, struct mlx5e_trap *t) node = dev_to_node(mdev->device); + ccp.netdev = priv->netdev; + ccp.wq = priv->wq; ccp.node = node; ccp.ch_stats = t->stats; ccp.napi = &t->napi; ccp.ix = 0; - err = mlx5e_open_cq(priv, trap_moder, &rq_param->cqp, &ccp, &rq->cq); + err = mlx5e_open_cq(priv->mdev, trap_moder, &rq_param->cqp, &ccp, &rq->cq); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index 13c7ed1bb3..82b5ca1be4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -103,7 +103,7 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq, xdptxd->dma_addr = dma_addr; if (unlikely(!INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe, - mlx5e_xmit_xdp_frame, sq, xdptxd, 0))) + mlx5e_xmit_xdp_frame, sq, xdptxd, 0, NULL))) return false; /* xmit_mode == MLX5E_XDP_XMIT_MODE_FRAME */ @@ -145,7 +145,7 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq, xdptxd->dma_addr = dma_addr; if (unlikely(!INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe, - mlx5e_xmit_xdp_frame, sq, xdptxd, 0))) + mlx5e_xmit_xdp_frame, sq, xdptxd, 0, NULL))) return false; /* xmit_mode == MLX5E_XDP_XMIT_MODE_PAGE */ @@ -256,9 +256,55 @@ static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash, return 0; } +static int mlx5e_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto, + u16 *vlan_tci) +{ + const struct mlx5e_xdp_buff *_ctx = (void *)ctx; + const struct mlx5_cqe64 *cqe = _ctx->cqe; + + if (!cqe_has_vlan(cqe)) + return -ENODATA; + + *vlan_proto = htons(ETH_P_8021Q); + *vlan_tci = be16_to_cpu(cqe->vlan_info); + return 0; +} + const struct xdp_metadata_ops mlx5e_xdp_metadata_ops = { .xmo_rx_timestamp = mlx5e_xdp_rx_timestamp, .xmo_rx_hash = mlx5e_xdp_rx_hash, + .xmo_rx_vlan_tag = mlx5e_xdp_rx_vlan_tag, +}; + +struct mlx5e_xsk_tx_complete { + struct mlx5_cqe64 *cqe; + struct mlx5e_cq *cq; +}; + +static u64 mlx5e_xsk_fill_timestamp(void *_priv) +{ + struct mlx5e_xsk_tx_complete *priv = _priv; + u64 ts; + + ts = get_cqe_ts(priv->cqe); + + if (mlx5_is_real_time_rq(priv->cq->mdev) || mlx5_is_real_time_sq(priv->cq->mdev)) + return mlx5_real_time_cyc2time(&priv->cq->mdev->clock, ts); + + return mlx5_timecounter_cyc2time(&priv->cq->mdev->clock, ts); +} + +static void mlx5e_xsk_request_checksum(u16 csum_start, u16 csum_offset, void *priv) +{ + struct mlx5_wqe_eth_seg *eseg = priv; + + /* HW/FW is doing parsing, so offsets are largely ignored. */ + eseg->cs_flags |= MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM; +} + +const struct xsk_tx_metadata_ops mlx5e_xsk_tx_metadata_ops = { + .tmo_fill_timestamp = mlx5e_xsk_fill_timestamp, + .tmo_request_checksum = mlx5e_xsk_request_checksum, }; /* returns true if packet was consumed by xdp */ @@ -398,11 +444,11 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq INDIRECT_CALLABLE_SCOPE bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, - int check_result); + int check_result, struct xsk_tx_metadata *meta); INDIRECT_CALLABLE_SCOPE bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, - int check_result) + int check_result, struct xsk_tx_metadata *meta) { struct mlx5e_tx_mpwqe *session = &sq->mpwqe; struct mlx5e_xdpsq_stats *stats = sq->stats; @@ -420,7 +466,7 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx */ if (unlikely(sq->mpwqe.wqe)) mlx5e_xdp_mpwqe_complete(sq); - return mlx5e_xmit_xdp_frame(sq, xdptxd, 0); + return mlx5e_xmit_xdp_frame(sq, xdptxd, 0, meta); } if (!xdptxd->len) { skb_frag_t *frag = &xdptxdf->sinfo->frags[0]; @@ -450,6 +496,7 @@ mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptx * and it's safe to complete it at any time. */ mlx5e_xdp_mpwqe_session_start(sq); + xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, &session->wqe->eth); } mlx5e_xdp_mpwqe_add_dseg(sq, p, stats); @@ -480,7 +527,7 @@ INDIRECT_CALLABLE_SCOPE int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq) INDIRECT_CALLABLE_SCOPE bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, - int check_result) + int check_result, struct xsk_tx_metadata *meta) { struct mlx5e_xmit_data_frags *xdptxdf = container_of(xdptxd, struct mlx5e_xmit_data_frags, xd); @@ -601,6 +648,8 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, sq->pc++; } + xsk_tx_metadata_request(meta, &mlx5e_xsk_tx_metadata_ops, eseg); + sq->doorbell_cseg = cseg; stats->xmit++; @@ -610,7 +659,9 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq, struct mlx5e_xdp_wqe_info *wi, u32 *xsk_frames, - struct xdp_frame_bulk *bq) + struct xdp_frame_bulk *bq, + struct mlx5e_cq *cq, + struct mlx5_cqe64 *cqe) { struct mlx5e_xdp_info_fifo *xdpi_fifo = &sq->db.xdpi_fifo; u16 i; @@ -670,10 +721,24 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq, break; } - case MLX5E_XDP_XMIT_MODE_XSK: + case MLX5E_XDP_XMIT_MODE_XSK: { /* AF_XDP send */ + struct xsk_tx_metadata_compl *compl = NULL; + struct mlx5e_xsk_tx_complete priv = { + .cqe = cqe, + .cq = cq, + }; + + if (xp_tx_metadata_enabled(sq->xsk_pool)) { + xdpi = mlx5e_xdpi_fifo_pop(xdpi_fifo); + compl = &xdpi.xsk_meta; + + xsk_tx_metadata_complete(compl, &mlx5e_xsk_tx_metadata_ops, &priv); + } + (*xsk_frames)++; break; + } default: WARN_ON_ONCE(true); } @@ -722,7 +787,7 @@ bool mlx5e_poll_xdpsq_cq(struct mlx5e_cq *cq) sqcc += wi->num_wqebbs; - mlx5e_free_xdpsq_desc(sq, wi, &xsk_frames, &bq); + mlx5e_free_xdpsq_desc(sq, wi, &xsk_frames, &bq, cq, cqe); } while (!last_wqe); if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_REQ)) { @@ -769,7 +834,7 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq) sq->cc += wi->num_wqebbs; - mlx5e_free_xdpsq_desc(sq, wi, &xsk_frames, &bq); + mlx5e_free_xdpsq_desc(sq, wi, &xsk_frames, &bq, NULL, NULL); } xdp_flush_frame_bulk(&bq); @@ -842,7 +907,7 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, } ret = INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe, - mlx5e_xmit_xdp_frame, sq, xdptxd, 0); + mlx5e_xmit_xdp_frame, sq, xdptxd, 0, NULL); if (unlikely(!ret)) { int j; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h index ecfe93a479..e054db1e10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h @@ -33,6 +33,7 @@ #define __MLX5_EN_XDP_H__ #include <linux/indirect_call_wrapper.h> +#include <net/xdp_sock.h> #include "en.h" #include "en/txrx.h" @@ -82,7 +83,7 @@ enum mlx5e_xdp_xmit_mode { * num, page_1, page_2, ... , page_num. * * MLX5E_XDP_XMIT_MODE_XSK: - * none. + * frame.xsk_meta. */ #define MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO 4 @@ -97,6 +98,7 @@ union mlx5e_xdp_info { u8 num; struct page *page; } page; + struct xsk_tx_metadata_compl xsk_meta; }; struct mlx5e_xsk_param; @@ -112,13 +114,16 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, u32 flags); extern const struct xdp_metadata_ops mlx5e_xdp_metadata_ops; +extern const struct xsk_tx_metadata_ops mlx5e_xsk_tx_metadata_ops; INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame_mpwqe(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, - int check_result)); + int check_result, + struct xsk_tx_metadata *meta)); INDIRECT_CALLABLE_DECLARE(bool mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd, - int check_result)); + int check_result, + struct xsk_tx_metadata *meta)); INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check_mpwqe(struct mlx5e_xdpsq *sq)); INDIRECT_CALLABLE_DECLARE(int mlx5e_xmit_xdp_frame_check(struct mlx5e_xdpsq *sq)); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c index 36826b5824..82e6abbc17 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c @@ -127,7 +127,7 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params, mlx5e_build_xsk_cparam(priv->mdev, params, xsk, priv->q_counter, cparam); - err = mlx5e_open_cq(c->priv, params->rx_cq_moderation, &cparam->rq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, params->rx_cq_moderation, &cparam->rq.cqp, &ccp, &c->xskrq.cq); if (unlikely(err)) goto err_free_cparam; @@ -136,7 +136,7 @@ int mlx5e_open_xsk(struct mlx5e_priv *priv, struct mlx5e_params *params, if (unlikely(err)) goto err_close_rx_cq; - err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp, &c->xsksq.cq); if (unlikely(err)) goto err_close_rq; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c index 597f319d47..a59199ed59 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c @@ -55,12 +55,16 @@ static void mlx5e_xsk_tx_post_err(struct mlx5e_xdpsq *sq, nopwqe = mlx5e_post_nop(&sq->wq, sq->sqn, &sq->pc); mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, *xdpi); + if (xp_tx_metadata_enabled(sq->xsk_pool)) + mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, + (union mlx5e_xdp_info) { .xsk_meta = {} }); sq->doorbell_cseg = &nopwqe->ctrl; } bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget) { struct xsk_buff_pool *pool = sq->xsk_pool; + struct xsk_tx_metadata *meta = NULL; union mlx5e_xdp_info xdpi; bool work_done = true; bool flush = false; @@ -93,12 +97,13 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget) xdptxd.dma_addr = xsk_buff_raw_get_dma(pool, desc.addr); xdptxd.data = xsk_buff_raw_get_data(pool, desc.addr); xdptxd.len = desc.len; + meta = xsk_buff_get_metadata(pool, desc.addr); xsk_buff_raw_dma_sync_for_device(pool, xdptxd.dma_addr, xdptxd.len); ret = INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe, mlx5e_xmit_xdp_frame, sq, &xdptxd, - check_result); + check_result, meta); if (unlikely(!ret)) { if (sq->mpwqe.wqe) mlx5e_xdp_mpwqe_complete(sq); @@ -106,6 +111,16 @@ bool mlx5e_xsk_tx(struct mlx5e_xdpsq *sq, unsigned int budget) mlx5e_xsk_tx_post_err(sq, &xdpi); } else { mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, xdpi); + if (xp_tx_metadata_enabled(sq->xsk_pool)) { + struct xsk_tx_metadata_compl compl; + + xsk_tx_metadata_to_compl(meta, &compl); + XSK_TX_COMPL_FITS(void *); + + mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo, + (union mlx5e_xdp_info) + { .xsk_meta = compl }); + } } flush = true; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index b2cabd6ab8..cc9bcc4200 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = { .mdo_add_secy = mlx5e_macsec_add_secy, .mdo_upd_secy = mlx5e_macsec_upd_secy, .mdo_del_secy = mlx5e_macsec_del_secy, + .rx_uses_md_dst = true, }; bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index e66f486faa..415fec7763 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -45,6 +45,10 @@ struct arfs_table { struct hlist_head rules_hash[ARFS_HASH_SIZE]; }; +enum { + MLX5E_ARFS_STATE_ENABLED, +}; + enum arfs_type { ARFS_IPV4_TCP, ARFS_IPV6_TCP, @@ -59,6 +63,7 @@ struct mlx5e_arfs_tables { spinlock_t arfs_lock; int last_filter_id; struct workqueue_struct *wq; + unsigned long state; }; struct arfs_tuple { @@ -169,6 +174,8 @@ int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs) return err; } } + set_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state); + return 0; } @@ -454,6 +461,8 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs) int i; int j; + clear_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state); + spin_lock_bh(&arfs->arfs_lock); mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) { hlist_del_init(&rule->hlist); @@ -626,17 +635,8 @@ static void arfs_handle_work(struct work_struct *work) struct mlx5_flow_handle *rule; arfs = mlx5e_fs_get_arfs(priv->fs); - mutex_lock(&priv->state_lock); - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { - spin_lock_bh(&arfs->arfs_lock); - hlist_del(&arfs_rule->hlist); - spin_unlock_bh(&arfs->arfs_lock); - - mutex_unlock(&priv->state_lock); - kfree(arfs_rule); - goto out; - } - mutex_unlock(&priv->state_lock); + if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) + return; if (!arfs_rule->rule) { rule = arfs_add_rule(priv, arfs_rule); @@ -752,6 +752,11 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, return -EPROTONOSUPPORT; spin_lock_bh(&arfs->arfs_lock); + if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) { + spin_unlock_bh(&arfs->arfs_lock); + return -EPERM; + } + arfs_rule = arfs_find_rule(arfs_t, &fk); if (arfs_rule) { if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c index 41c396e764..6ed3a32b7e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c @@ -74,7 +74,73 @@ int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey) return err; } -int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) +int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn) +{ + void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); + + MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn); + + if (mlx5_lag_is_lacp_owner(mdev)) + MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1); + + return mlx5_core_create_tis(mdev, in, tisn); +} + +void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn) +{ + mlx5_core_destroy_tis(mdev, tisn); +} + +static void mlx5e_destroy_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PORTS][MLX5_MAX_NUM_TC]) +{ + int tc, i; + + for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++) + for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++) + mlx5e_destroy_tis(mdev, tisn[i][tc]); +} + +static bool mlx5_lag_should_assign_affinity(struct mlx5_core_dev *mdev) +{ + return MLX5_CAP_GEN(mdev, lag_tx_port_affinity) && mlx5e_get_num_lag_ports(mdev) > 1; +} + +static int mlx5e_create_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PORTS][MLX5_MAX_NUM_TC]) +{ + int tc, i; + int err; + + for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++) { + for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++) { + u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {}; + void *tisc; + + tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); + + MLX5_SET(tisc, tisc, prio, tc << 1); + + if (mlx5_lag_should_assign_affinity(mdev)) + MLX5_SET(tisc, tisc, lag_tx_port_affinity, i + 1); + + err = mlx5e_create_tis(mdev, in, &tisn[i][tc]); + if (err) + goto err_close_tises; + } + } + + return 0; + +err_close_tises: + for (; i >= 0; i--) { + for (tc--; tc >= 0; tc--) + mlx5e_destroy_tis(mdev, tisn[i][tc]); + tc = MLX5_MAX_NUM_TC; + } + + return err; +} + +int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises) { struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs; int err; @@ -103,6 +169,15 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) goto err_destroy_mkey; } + if (create_tises) { + err = mlx5e_create_tises(mdev, res->tisn); + if (err) { + mlx5_core_err(mdev, "alloc tises failed, %d\n", err); + goto err_destroy_bfreg; + } + res->tisn_valid = true; + } + INIT_LIST_HEAD(&res->td.tirs_list); mutex_init(&res->td.list_lock); @@ -115,6 +190,8 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) return 0; +err_destroy_bfreg: + mlx5_free_bfreg(mdev, &res->bfreg); err_destroy_mkey: mlx5_core_destroy_mkey(mdev, res->mkey); err_dealloc_transport_domain: @@ -130,6 +207,8 @@ void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev) mlx5_crypto_dek_cleanup(mdev->mlx5e_res.dek_priv); mdev->mlx5e_res.dek_priv = NULL; + if (res->tisn_valid) + mlx5e_destroy_tises(mdev, res->tisn); mlx5_free_bfreg(mdev, &res->bfreg); mlx5_core_destroy_mkey(mdev, res->mkey); mlx5_core_dealloc_transport_domain(mdev, res->td.tdn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c7c1b667b1..93461b0c57 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -451,6 +451,23 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, mutex_lock(&priv->state_lock); + /* If RXFH is configured, changing the channels number is allowed only if + * it does not require resizing the RSS table. This is because the previous + * configuration may no longer be compatible with the new RSS table. + */ + if (netif_is_rxfh_configured(priv->netdev)) { + int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels); + int new_rqt_size = mlx5e_rqt_size(priv->mdev, count); + + if (new_rqt_size != cur_rqt_size) { + err = -EINVAL; + netdev_err(priv->netdev, + "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n", + __func__, new_rqt_size, cur_rqt_size); + goto out; + } + } + /* Don't allow changing the number of channels if HTB offload is active, * because the numeration of the QoS SQs will change, while per-queue * qdiscs are attached. @@ -1262,27 +1279,29 @@ static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev) return mlx5e_ethtool_get_rxfh_indir_size(priv); } -static int mlx5e_get_rxfh_context(struct net_device *dev, u32 *indir, - u8 *key, u8 *hfunc, u32 rss_context) +int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh) { - struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5e_priv *priv = netdev_priv(netdev); + u32 rss_context = rxfh->rss_context; int err; mutex_lock(&priv->state_lock); - err = mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rss_context, indir, key, hfunc); + err = mlx5e_rx_res_rss_get_rxfh(priv->rx_res, rss_context, + rxfh->indir, rxfh->key, &rxfh->hfunc); mutex_unlock(&priv->state_lock); return err; } -static int mlx5e_set_rxfh_context(struct net_device *dev, const u32 *indir, - const u8 *key, const u8 hfunc, - u32 *rss_context, bool delete) +int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh, + struct netlink_ext_ack *extack) { struct mlx5e_priv *priv = netdev_priv(dev); + u32 *rss_context = &rxfh->rss_context; + u8 hfunc = rxfh->hfunc; int err; mutex_lock(&priv->state_lock); - if (delete) { + if (*rss_context && rxfh->rss_delete) { err = mlx5e_rx_res_rss_destroy(priv->rx_res, *rss_context); goto unlock; } @@ -1295,7 +1314,8 @@ static int mlx5e_set_rxfh_context(struct net_device *dev, const u32 *indir, goto unlock; } - err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, *rss_context, indir, key, + err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, *rss_context, + rxfh->indir, rxfh->key, hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc); unlock: @@ -1303,25 +1323,6 @@ unlock: return err; } -int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc) -{ - return mlx5e_get_rxfh_context(netdev, indir, key, hfunc, 0); -} - -int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct mlx5e_priv *priv = netdev_priv(dev); - int err; - - mutex_lock(&priv->state_lock); - err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, 0, indir, key, - hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc); - mutex_unlock(&priv->state_lock); - return err; -} - #define MLX5E_PFC_PREVEN_AUTO_TOUT_MSEC 100 #define MLX5E_PFC_PREVEN_TOUT_MAX_MSEC 8000 #define MLX5E_PFC_PREVEN_MINOR_PRECENT 85 @@ -2398,6 +2399,7 @@ static void mlx5e_get_rmon_stats(struct net_device *netdev, } const struct ethtool_ops mlx5e_ethtool_ops = { + .cap_rss_ctx_supported = true, .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES | ETHTOOL_COALESCE_USE_ADAPTIVE | @@ -2420,8 +2422,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = { .get_rxfh_indir_size = mlx5e_get_rxfh_indir_size, .get_rxfh = mlx5e_get_rxfh, .set_rxfh = mlx5e_set_rxfh, - .get_rxfh_context = mlx5e_get_rxfh_context, - .set_rxfh_context = mlx5e_set_rxfh_context, .get_rxnfc = mlx5e_get_rxnfc, .set_rxnfc = mlx5e_set_rxnfc, .get_tunable = mlx5e_get_tunable, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 0c87ddb8a7..952f1f9813 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -902,6 +902,7 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params, pp_params.nid = node; pp_params.dev = rq->pdev; pp_params.napi = rq->cq.napi; + pp_params.netdev = rq->netdev; pp_params.dma_dir = rq->buff.map_dir; pp_params.max_len = PAGE_SIZE; @@ -1351,6 +1352,17 @@ void mlx5e_close_rq(struct mlx5e_rq *rq) mlx5e_free_rq(rq); } +u32 mlx5e_profile_get_tisn(struct mlx5_core_dev *mdev, + struct mlx5e_priv *priv, + const struct mlx5e_profile *profile, + u8 lag_port, u8 tc) +{ + if (profile->get_tisn) + return profile->get_tisn(mdev, priv, lag_port, tc); + + return mdev->mlx5e_res.hw_objs.tisn[lag_port][tc]; +} + static void mlx5e_free_xdpsq_db(struct mlx5e_xdpsq *sq) { kvfree(sq->db.xdpi_fifo.xi); @@ -1919,7 +1931,8 @@ int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, return err; csp.tis_lst_sz = 1; - csp.tisn = c->priv->tisn[c->lag_port][0]; /* tc = 0 */ + csp.tisn = mlx5e_profile_get_tisn(c->mdev, c->priv, c->priv->profile, + c->lag_port, 0); /* tc = 0 */ csp.cqn = sq->cq.mcq.cqn; csp.wq_ctrl = &sq->wq_ctrl; csp.min_inline_mode = sq->min_inline_mode; @@ -1981,11 +1994,12 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq) mlx5e_free_xdpsq(sq); } -static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv, +static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev, + struct net_device *netdev, + struct workqueue_struct *workqueue, struct mlx5e_cq_param *param, struct mlx5e_cq *cq) { - struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_cq *mcq = &cq->mcq; int err; u32 i; @@ -2012,13 +2026,13 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv, } cq->mdev = mdev; - cq->netdev = priv->netdev; - cq->priv = priv; + cq->netdev = netdev; + cq->workqueue = workqueue; return 0; } -static int mlx5e_alloc_cq(struct mlx5e_priv *priv, +static int mlx5e_alloc_cq(struct mlx5_core_dev *mdev, struct mlx5e_cq_param *param, struct mlx5e_create_cq_param *ccp, struct mlx5e_cq *cq) @@ -2029,7 +2043,7 @@ static int mlx5e_alloc_cq(struct mlx5e_priv *priv, param->wq.db_numa_node = ccp->node; param->eq_ix = ccp->ix; - err = mlx5e_alloc_cq_common(priv, param, cq); + err = mlx5e_alloc_cq_common(mdev, ccp->netdev, ccp->wq, param, cq); cq->napi = ccp->napi; cq->ch_stats = ccp->ch_stats; @@ -2095,14 +2109,13 @@ static void mlx5e_destroy_cq(struct mlx5e_cq *cq) mlx5_core_destroy_cq(cq->mdev, &cq->mcq); } -int mlx5e_open_cq(struct mlx5e_priv *priv, struct dim_cq_moder moder, +int mlx5e_open_cq(struct mlx5_core_dev *mdev, struct dim_cq_moder moder, struct mlx5e_cq_param *param, struct mlx5e_create_cq_param *ccp, struct mlx5e_cq *cq) { - struct mlx5_core_dev *mdev = priv->mdev; int err; - err = mlx5e_alloc_cq(priv, param, ccp, cq); + err = mlx5e_alloc_cq(mdev, param, ccp, cq); if (err) return err; @@ -2135,7 +2148,7 @@ static int mlx5e_open_tx_cqs(struct mlx5e_channel *c, int tc; for (tc = 0; tc < c->num_tc; tc++) { - err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->txq_sq.cqp, + err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->txq_sq.cqp, ccp, &c->sq[tc].cq); if (err) goto err_close_tx_cqs; @@ -2203,12 +2216,15 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c, for (tc = 0; tc < mlx5e_get_dcb_num_tc(params); tc++) { int txq_ix = c->ix + tc * params->num_channels; u32 qos_queue_group_id; + u32 tisn; + tisn = mlx5e_profile_get_tisn(c->mdev, c->priv, c->priv->profile, + c->lag_port, tc); err = mlx5e_txq_get_qos_node_hw_id(params, txq_ix, &qos_queue_group_id); if (err) goto err_close_sqs; - err = mlx5e_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix, + err = mlx5e_open_txqsq(c, tisn, txq_ix, params, &cparam->txq_sq, &c->sq[tc], tc, qos_queue_group_id, &c->priv->channel_stats[c->ix]->sq[tc]); @@ -2336,12 +2352,12 @@ static int mlx5e_open_queues(struct mlx5e_channel *c, mlx5e_build_create_cq_param(&ccp, c); - err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, icocq_moder, &cparam->async_icosq.cqp, &ccp, &c->async_icosq.cq); if (err) return err; - err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, icocq_moder, &cparam->icosq.cqp, &ccp, &c->icosq.cq); if (err) goto err_close_async_icosq_cq; @@ -2350,17 +2366,17 @@ static int mlx5e_open_queues(struct mlx5e_channel *c, if (err) goto err_close_icosq_cq; - err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp, &c->xdpsq.cq); if (err) goto err_close_tx_cqs; - err = mlx5e_open_cq(c->priv, params->rx_cq_moderation, &cparam->rq.cqp, &ccp, + err = mlx5e_open_cq(c->mdev, params->rx_cq_moderation, &cparam->rq.cqp, &ccp, &c->rq.cq); if (err) goto err_close_xdp_tx_cqs; - err = c->xdp ? mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp, + err = c->xdp ? mlx5e_open_cq(c->mdev, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp, &c->rq_xdpsq.cq) : 0; if (err) goto err_close_rx_cq; @@ -3307,7 +3323,7 @@ static int mlx5e_alloc_drop_cq(struct mlx5e_priv *priv, param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(mdev)); param->wq.db_numa_node = dev_to_node(mlx5_core_dma_dev(mdev)); - return mlx5e_alloc_cq_common(priv, param, cq); + return mlx5e_alloc_cq_common(priv->mdev, priv->netdev, priv->wq, param, cq); } int mlx5e_open_drop_rq(struct mlx5e_priv *priv, @@ -3363,75 +3379,6 @@ void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq) mlx5e_free_cq(&drop_rq->cq); } -int mlx5e_create_tis(struct mlx5_core_dev *mdev, void *in, u32 *tisn) -{ - void *tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); - - MLX5_SET(tisc, tisc, transport_domain, mdev->mlx5e_res.hw_objs.td.tdn); - - if (MLX5_GET(tisc, tisc, tls_en)) - MLX5_SET(tisc, tisc, pd, mdev->mlx5e_res.hw_objs.pdn); - - if (mlx5_lag_is_lacp_owner(mdev)) - MLX5_SET(tisc, tisc, strict_lag_tx_port_affinity, 1); - - return mlx5_core_create_tis(mdev, in, tisn); -} - -void mlx5e_destroy_tis(struct mlx5_core_dev *mdev, u32 tisn) -{ - mlx5_core_destroy_tis(mdev, tisn); -} - -void mlx5e_destroy_tises(struct mlx5e_priv *priv) -{ - int tc, i; - - for (i = 0; i < mlx5e_get_num_lag_ports(priv->mdev); i++) - for (tc = 0; tc < priv->profile->max_tc; tc++) - mlx5e_destroy_tis(priv->mdev, priv->tisn[i][tc]); -} - -static bool mlx5e_lag_should_assign_affinity(struct mlx5_core_dev *mdev) -{ - return MLX5_CAP_GEN(mdev, lag_tx_port_affinity) && mlx5e_get_num_lag_ports(mdev) > 1; -} - -int mlx5e_create_tises(struct mlx5e_priv *priv) -{ - int tc, i; - int err; - - for (i = 0; i < mlx5e_get_num_lag_ports(priv->mdev); i++) { - for (tc = 0; tc < priv->profile->max_tc; tc++) { - u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {}; - void *tisc; - - tisc = MLX5_ADDR_OF(create_tis_in, in, ctx); - - MLX5_SET(tisc, tisc, prio, tc << 1); - - if (mlx5e_lag_should_assign_affinity(priv->mdev)) - MLX5_SET(tisc, tisc, lag_tx_port_affinity, i + 1); - - err = mlx5e_create_tis(priv->mdev, in, &priv->tisn[i][tc]); - if (err) - goto err_close_tises; - } - } - - return 0; - -err_close_tises: - for (; i >= 0; i--) { - for (tc--; tc >= 0; tc--) - mlx5e_destroy_tis(priv->mdev, priv->tisn[i][tc]); - tc = priv->profile->max_tc; - } - - return err; -} - static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) { if (priv->mqprio_rl) { @@ -3440,7 +3387,6 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) priv->mqprio_rl = NULL; } mlx5e_accel_cleanup_tx(priv); - mlx5e_destroy_tises(priv); } static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd) @@ -3542,7 +3488,7 @@ static int mlx5e_setup_tc_mqprio_dcb(struct mlx5e_priv *priv, mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; - if (tc && tc != MLX5E_MAX_NUM_TC) + if (tc && tc != MLX5_MAX_NUM_TC) return -EINVAL; new_params = priv->channels.params; @@ -5185,6 +5131,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) netdev->netdev_ops = &mlx5e_netdev_ops; netdev->xdp_metadata_ops = &mlx5e_xdp_metadata_ops; + netdev->xsk_tx_metadata_ops = &mlx5e_xsk_tx_metadata_ops; mlx5e_dcbnl_build_netdev(netdev); @@ -5265,7 +5212,6 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) netdev->gso_partial_features |= NETIF_F_GSO_UDP_L4; netdev->hw_features |= NETIF_F_GSO_UDP_L4; - netdev->features |= NETIF_F_GSO_UDP_L4; mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled); @@ -5505,23 +5451,13 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) { int err; - err = mlx5e_create_tises(priv); - if (err) { - mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err); - return err; - } - err = mlx5e_accel_init_tx(priv); if (err) - goto err_destroy_tises; + return err; mlx5e_set_mqprio_rl(priv); mlx5e_dcbnl_initialize(priv); return 0; - -err_destroy_tises: - mlx5e_destroy_tises(priv); - return err; } static void mlx5e_nic_enable(struct mlx5e_priv *priv) @@ -5616,7 +5552,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = { .update_stats = mlx5e_stats_update_ndo_stats, .update_carrier = mlx5e_update_carrier, .rx_handlers = &mlx5e_rx_handlers_nic, - .max_tc = MLX5E_MAX_NUM_TC, + .max_tc = MLX5_MAX_NUM_TC, .stats_grps = mlx5e_nic_stats_grps, .stats_grps_num = mlx5e_nic_stats_grps_num, .features = BIT(MLX5E_PROFILE_FEATURE_PTP_RX) | @@ -5759,9 +5695,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv) kfree(priv->tx_rates); kfree(priv->txq2sq); destroy_workqueue(priv->wq); - mutex_lock(&priv->state_lock); mlx5e_selq_cleanup(&priv->selq); - mutex_unlock(&priv->state_lock); free_cpumask_var(priv->scratchpad.cpumask); for (i = 0; i < priv->htb_max_qos_sqs; i++) @@ -6056,7 +5990,7 @@ static int mlx5e_resume(struct auxiliary_device *adev) if (netif_device_present(netdev)) return 0; - err = mlx5e_create_mdev_resources(mdev); + err = mlx5e_create_mdev_resources(mdev, true); if (err) return err; @@ -6069,7 +6003,7 @@ static int mlx5e_resume(struct auxiliary_device *adev) return 0; } -static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) +static int _mlx5e_suspend(struct auxiliary_device *adev) { struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); struct mlx5e_priv *priv = mlx5e_dev->priv; @@ -6087,15 +6021,18 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) return 0; } -static int mlx5e_probe(struct auxiliary_device *adev, - const struct auxiliary_device_id *id) +static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) +{ + return _mlx5e_suspend(adev); +} + +static int _mlx5e_probe(struct auxiliary_device *adev) { struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); const struct mlx5e_profile *profile = &mlx5e_nic_profile; struct mlx5_core_dev *mdev = edev->mdev; struct mlx5e_dev *mlx5e_dev; struct net_device *netdev; - pm_message_t state = {}; struct mlx5e_priv *priv; int err; @@ -6150,7 +6087,7 @@ static int mlx5e_probe(struct auxiliary_device *adev, return 0; err_resume: - mlx5e_suspend(adev, state); + _mlx5e_suspend(adev); err_profile_cleanup: profile->cleanup(priv); err_destroy_netdev: @@ -6162,16 +6099,21 @@ err_devlink_unregister: return err; } +static int mlx5e_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + return _mlx5e_probe(adev); +} + static void mlx5e_remove(struct auxiliary_device *adev) { struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); struct mlx5e_priv *priv = mlx5e_dev->priv; - pm_message_t state = {}; mlx5_core_uplink_netdev_set(priv->mdev, NULL); mlx5e_dcbnl_delete_app(priv); unregister_netdev(priv->netdev); - mlx5e_suspend(adev, state); + _mlx5e_suspend(adev); priv->profile->cleanup(priv); mlx5e_destroy_netdev(priv); mlx5e_devlink_port_unregister(mlx5e_dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index e92d4f8359..05527418fa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -112,8 +112,18 @@ static const struct counter_desc vport_rep_stats_desc[] = { tx_vport_rdma_multicast_bytes) }, }; +static const struct counter_desc vport_rep_loopback_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, + vport_loopback_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_rep_stats, + vport_loopback_bytes) }, +}; + #define NUM_VPORT_REP_SW_COUNTERS ARRAY_SIZE(sw_rep_stats_desc) #define NUM_VPORT_REP_HW_COUNTERS ARRAY_SIZE(vport_rep_stats_desc) +#define NUM_VPORT_REP_LOOPBACK_COUNTERS(dev) \ + (MLX5_CAP_GEN(dev, vport_counter_local_loopback) ? \ + ARRAY_SIZE(vport_rep_loopback_stats_desc) : 0) static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(sw_rep) { @@ -157,7 +167,8 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw_rep) static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport_rep) { - return NUM_VPORT_REP_HW_COUNTERS; + return NUM_VPORT_REP_HW_COUNTERS + + NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev); } static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport_rep) @@ -166,6 +177,9 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport_rep) for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++) strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_rep_stats_desc[i].format); + for (i = 0; i < NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev); i++) + strcpy(data + (idx++) * ETH_GSTRING_LEN, + vport_rep_loopback_stats_desc[i].format); return idx; } @@ -176,6 +190,9 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport_rep) for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++) data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.rep_stats, vport_rep_stats_desc, i); + for (i = 0; i < NUM_VPORT_REP_LOOPBACK_COUNTERS(priv->mdev); i++) + data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.rep_stats, + vport_rep_loopback_stats_desc, i); return idx; } @@ -247,6 +264,13 @@ static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep) rep_stats->tx_vport_rdma_multicast_bytes = MLX5_GET_CTR(out, received_ib_multicast.octets); + if (MLX5_CAP_GEN(priv->mdev, vport_counter_local_loopback)) { + rep_stats->vport_loopback_packets = + MLX5_GET_CTR(out, local_loopback.packets); + rep_stats->vport_loopback_bytes = + MLX5_GET_CTR(out, local_loopback.octets); + } + out: kvfree(out); } @@ -1156,12 +1180,6 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) struct mlx5e_rep_priv *rpriv = priv->ppriv; int err; - err = mlx5e_create_tises(priv); - if (err) { - mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err); - return err; - } - err = mlx5e_rep_neigh_init(rpriv); if (err) goto err_neigh_init; @@ -1184,7 +1202,6 @@ err_ht_init: err_init_tx: mlx5e_rep_neigh_cleanup(rpriv); err_neigh_init: - mlx5e_destroy_tises(priv); return err; } @@ -1198,7 +1215,6 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) mlx5e_cleanup_uplink_rep_tx(rpriv); mlx5e_rep_neigh_cleanup(rpriv); - mlx5e_destroy_tises(priv); } static void mlx5e_rep_enable(struct mlx5e_priv *priv) @@ -1428,7 +1444,7 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = { .update_stats = mlx5e_stats_update_ndo_stats, .update_carrier = mlx5e_update_carrier, .rx_handlers = &mlx5e_rx_handlers_rep, - .max_tc = MLX5E_MAX_NUM_TC, + .max_tc = MLX5_MAX_NUM_TC, .stats_grps = mlx5e_ul_rep_stats_grps, .stats_grps_num = mlx5e_ul_rep_stats_grps_num, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 8d9743a5e4..d601b5faae 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -298,8 +298,8 @@ static void mlx5e_page_release_fragmented(struct mlx5e_rq *rq, u16 drain_count = MLX5E_PAGECNT_BIAS_MAX - frag_page->frags; struct page *page = frag_page->page; - if (page_pool_defrag_page(page, drain_count) == 0) - page_pool_put_defragged_page(rq->page_pool, page, -1, true); + if (page_pool_unref_page(page, drain_count) == 0) + page_pool_put_unrefed_page(rq->page_pool, page, -1, true); } static inline int mlx5e_get_rx_frag(struct mlx5e_rq *rq, @@ -1039,7 +1039,7 @@ int mlx5e_poll_ico_cq(struct mlx5e_cq *cq) (struct mlx5_err_cqe *)cqe); mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs); if (!test_and_set_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) - queue_work(cq->priv->wq, &sq->recover_work); + queue_work(cq->workqueue, &sq->recover_work); break; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 477c547dcc..12b3607afe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -476,6 +476,8 @@ struct mlx5e_rep_stats { u64 tx_vport_rdma_multicast_packets; u64 rx_vport_rdma_multicast_bytes; u64 tx_vport_rdma_multicast_bytes; + u64 vport_loopback_packets; + u64 vport_loopback_bytes; }; struct mlx5e_stats { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 404dd1d9b2..9fb2c057bd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3210,10 +3210,10 @@ static int offload_pedit_fields(struct mlx5e_priv *priv, headers_c = mlx5e_get_match_headers_criteria(*action_flags, &parse_attr->spec); headers_v = mlx5e_get_match_headers_value(*action_flags, &parse_attr->spec); - set_masks = &hdrs[0].masks; - add_masks = &hdrs[1].masks; - set_vals = &hdrs[0].vals; - add_vals = &hdrs[1].vals; + set_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].masks; + add_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].masks; + set_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].vals; + add_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].vals; for (i = 0; i < ARRAY_SIZE(fields); i++) { bool skip; @@ -5031,22 +5031,6 @@ int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv, return apply_police_params(priv, 0, extack); } -void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, - struct tc_cls_matchall_offload *ma) -{ - struct mlx5e_rep_priv *rpriv = priv->ppriv; - struct rtnl_link_stats64 cur_stats; - u64 dbytes; - u64 dpkts; - - mlx5e_stats_copy_rep_stats(&cur_stats, &priv->stats.rep_stats); - dpkts = cur_stats.rx_packets - rpriv->prev_vf_vport_stats.rx_packets; - dbytes = cur_stats.rx_bytes - rpriv->prev_vf_vport_stats.rx_bytes; - rpriv->prev_vf_vport_stats = cur_stats; - flow_stats_update(&ma->stats, dbytes, dpkts, 0, jiffies, - FLOW_ACTION_HW_STATS_DELAYED); -} - static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index adb39e30f9..c24bda56b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -203,8 +203,6 @@ int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv, struct tc_cls_matchall_offload *f); int mlx5e_tc_delete_matchall(struct mlx5e_priv *priv, struct tc_cls_matchall_offload *f); -void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv, - struct tc_cls_matchall_offload *ma); struct mlx5e_encap_entry; void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 1ead69c5f5..e21a3b4128 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -398,6 +398,8 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) { u8 metadata_index = be32_to_cpu(eseg->flow_table_metadata); + mlx5e_ptp_metadata_fifo_pop(&sq->ptpsq->metadata_freelist); + mlx5e_skb_cb_hwtstamp_init(skb); mlx5e_ptp_metadata_map_put(&sq->ptpsq->metadata_map, skb, metadata_index); @@ -496,9 +498,6 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, err_drop: stats->dropped++; - if (unlikely(sq->ptpsq && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) - mlx5e_ptp_metadata_fifo_push(&sq->ptpsq->metadata_freelist, - be32_to_cpu(eseg->flow_table_metadata)); dev_kfree_skb_any(skb); mlx5e_tx_flush(sq); } @@ -657,7 +656,7 @@ static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb, { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) eseg->flow_table_metadata = - cpu_to_be32(mlx5e_ptp_metadata_fifo_pop(&ptpsq->metadata_freelist)); + cpu_to_be32(mlx5e_ptp_metadata_fifo_peek(&ptpsq->metadata_freelist)); } static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq, @@ -863,7 +862,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) mlx5e_dump_error_cqe(&sq->cq, sq->sqn, (struct mlx5_err_cqe *)cqe); mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs); - queue_work(cq->priv->wq, &sq->recover_work); + queue_work(cq->workqueue, &sq->recover_work); } stats->cqe_err++; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 3047d7015c..1789800faa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1868,6 +1868,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) if (err) goto abort; + dev->priv.eswitch = esw; err = esw_offloads_init(esw); if (err) goto reps_err; @@ -1892,11 +1893,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; else esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; - if (MLX5_ESWITCH_MANAGER(dev) && - mlx5_esw_vport_match_metadata_supported(esw)) - esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA; - - dev->priv.eswitch = esw; BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); esw_info(dev, @@ -1908,6 +1904,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) reps_err: mlx5_esw_vports_cleanup(esw); + dev->priv.eswitch = NULL; abort: if (esw->work_queue) destroy_workqueue(esw->work_queue); @@ -1926,7 +1923,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) esw_info(esw->dev, "cleanup\n"); - esw->dev->priv.eswitch = NULL; destroy_workqueue(esw->work_queue); WARN_ON(refcount_read(&esw->qos.refcnt)); mutex_destroy(&esw->state_lock); @@ -1937,6 +1933,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) mutex_destroy(&esw->offloads.encap_tbl_lock); mutex_destroy(&esw->offloads.decap_tbl_lock); esw_offloads_cleanup(esw); + esw->dev->priv.eswitch = NULL; mlx5_esw_vports_cleanup(esw); debugfs_remove_recursive(esw->debugfs_root); devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index b4eb17141e..349e28a6dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -618,13 +618,6 @@ static inline bool mlx5_esw_allowed(const struct mlx5_eswitch *esw) return esw && MLX5_ESWITCH_MANAGER(esw->dev); } -/* The returned number is valid only when the dev is eswitch manager. */ -static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev) -{ - return mlx5_core_is_ecpf_esw_manager(dev) ? - MLX5_VPORT_ECPF : MLX5_VPORT_PF; -} - static inline bool mlx5_esw_is_manager_vport(const struct mlx5_eswitch *esw, u16 vport_num) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index baaae628b0..e3cce110e5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2476,6 +2476,10 @@ int esw_offloads_init(struct mlx5_eswitch *esw) if (err) return err; + if (MLX5_ESWITCH_MANAGER(esw->dev) && + mlx5_esw_vport_match_metadata_supported(esw)) + esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA; + err = devl_params_register(priv_to_devlink(esw->dev), esw_devlink_params, ARRAY_SIZE(esw_devlink_params)); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index b29299c49a..9b8599c200 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -1146,3 +1146,37 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type typ return mlx5_fs_cmd_get_stub_cmds(); } } + +int mlx5_fs_cmd_set_l2table_entry_silent(struct mlx5_core_dev *dev, u8 silent_mode) +{ + u32 in[MLX5_ST_SZ_DW(set_l2_table_entry_in)] = {}; + + if (silent_mode && !MLX5_CAP_GEN(dev, silent_mode)) + return -EOPNOTSUPP; + + MLX5_SET(set_l2_table_entry_in, in, opcode, MLX5_CMD_OP_SET_L2_TABLE_ENTRY); + MLX5_SET(set_l2_table_entry_in, in, silent_mode_valid, 1); + MLX5_SET(set_l2_table_entry_in, in, silent_mode, silent_mode); + + return mlx5_cmd_exec_in(dev, set_l2_table_entry, in); +} + +int mlx5_fs_cmd_set_tx_flow_table_root(struct mlx5_core_dev *dev, u32 ft_id, bool disconnect) +{ + u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {}; + u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {}; + + if (disconnect && MLX5_CAP_FLOWTABLE_NIC_TX(dev, reset_root_to_default)) + return -EOPNOTSUPP; + + MLX5_SET(set_flow_table_root_in, in, opcode, + MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); + MLX5_SET(set_flow_table_root_in, in, table_type, + FS_FT_NIC_TX); + if (disconnect) + MLX5_SET(set_flow_table_root_in, in, op_mod, 1); + else + MLX5_SET(set_flow_table_root_in, in, table_id, ft_id); + + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 7790ae5531..53e0e5137d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -122,4 +122,6 @@ int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len, const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type type); const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void); +int mlx5_fs_cmd_set_l2table_entry_silent(struct mlx5_core_dev *dev, u8 silent_mode); +int mlx5_fs_cmd_set_tx_flow_table_root(struct mlx5_core_dev *dev, u32 ft_id, bool disconnect); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index e6bfa7e4f1..cf085a478e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1664,6 +1664,16 @@ static int create_auto_flow_group(struct mlx5_flow_table *ft, return err; } +static bool mlx5_pkt_reformat_cmp(struct mlx5_pkt_reformat *p1, + struct mlx5_pkt_reformat *p2) +{ + return p1->owner == p2->owner && + (p1->owner == MLX5_FLOW_RESOURCE_OWNER_FW ? + p1->id == p2->id : + mlx5_fs_dr_action_get_pkt_reformat_id(p1) == + mlx5_fs_dr_action_get_pkt_reformat_id(p2)); +} + static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, struct mlx5_flow_destination *d2) { @@ -1675,8 +1685,8 @@ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_VHCA_ID) ? (d1->vport.vhca_id == d2->vport.vhca_id) : true) && ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) ? - (d1->vport.pkt_reformat->id == - d2->vport.pkt_reformat->id) : true)) || + mlx5_pkt_reformat_cmp(d1->vport.pkt_reformat, + d2->vport.pkt_reformat) : true)) || (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && d1->ft == d2->ft) || (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR && @@ -1808,8 +1818,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg, } trace_mlx5_fs_set_fte(fte, false); + /* Link newly added rules into the tree. */ for (i = 0; i < handle->num_rules; i++) { - if (refcount_read(&handle->rule[i]->node.refcount) == 1) { + if (!handle->rule[i]->node.parent) { tree_add_node(&handle->rule[i]->node, &fte->node); trace_mlx5_fs_add_rule(handle->rule[i]); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 4aed1768b8..78eb6b7097 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -181,7 +181,7 @@ struct mlx5_flow_rule { struct mlx5_flow_handle { int num_rules; - struct mlx5_flow_rule *rule[]; + struct mlx5_flow_rule *rule[] __counted_by(num_rules); }; /* Type of children is mlx5_flow_group */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index 17fe30a4c0..0c26d707ee 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -539,7 +539,7 @@ struct mlx5_fc_bulk { u32 base_id; int bulk_len; unsigned long *bitmask; - struct mlx5_fc fcs[]; + struct mlx5_fc fcs[] __counted_by(bulk_len); }; static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 3a9cdf7940..2911aa34a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -348,6 +348,25 @@ static int mlx5_check_hotplug_interrupt(struct mlx5_core_dev *dev) } #endif +static const struct pci_device_id mgt_ifc_device_ids[] = { + { PCI_VDEVICE(MELLANOX, 0xc2d2) }, /* BlueField1 MGT interface device ID */ + { PCI_VDEVICE(MELLANOX, 0xc2d3) }, /* BlueField2 MGT interface device ID */ + { PCI_VDEVICE(MELLANOX, 0xc2d4) }, /* BlueField3-Lx MGT interface device ID */ + { PCI_VDEVICE(MELLANOX, 0xc2d5) }, /* BlueField3 MGT interface device ID */ + { PCI_VDEVICE(MELLANOX, 0xc2d6) }, /* BlueField4 MGT interface device ID */ +}; + +static bool mlx5_is_mgt_ifc_pci_device(struct mlx5_core_dev *dev, u16 dev_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mgt_ifc_device_ids); ++i) + if (mgt_ifc_device_ids[i].device == dev_id) + return true; + + return false; +} + static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id) { struct pci_bus *bridge_bus = dev->pdev->bus; @@ -362,10 +381,15 @@ static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id) err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id); if (err) return pcibios_err_to_errno(err); - if (sdev_id != dev_id) { - mlx5_core_warn(dev, "unrecognized dev_id (0x%x)\n", sdev_id); - return -EPERM; - } + + if (sdev_id == dev_id) + continue; + + if (mlx5_is_mgt_ifc_pci_device(dev, sdev_id)) + continue; + + mlx5_core_warn(dev, "unrecognized dev_id (0x%x)\n", sdev_id); + return -EPERM; } return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 2bf77a5251..d77be1b4dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -339,7 +339,7 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv) return err; } - err = mlx5i_create_tis(priv->mdev, ipriv->qpn, &priv->tisn[0][0]); + err = mlx5i_create_tis(priv->mdev, ipriv->qpn, &ipriv->tisn); if (err) { mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); goto err_destroy_underlay_qp; @@ -356,7 +356,7 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) { struct mlx5i_priv *ipriv = priv->ppriv; - mlx5e_destroy_tis(priv->mdev, priv->tisn[0][0]); + mlx5e_destroy_tis(priv->mdev, ipriv->tisn); mlx5i_destroy_underlay_qp(priv->mdev, ipriv->qpn); } @@ -483,6 +483,18 @@ static unsigned int mlx5i_stats_grps_num(struct mlx5e_priv *priv) return ARRAY_SIZE(mlx5i_stats_grps); } +u32 mlx5i_get_tisn(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv, u8 lag_port, u8 tc) +{ + struct mlx5i_priv *ipriv = priv->ppriv; + + if (WARN(lag_port || tc, + "IPoIB unexpected non-zero value: lag_port (%u), tc (%u)\n", + lag_port, tc)) + return 0; + + return ipriv->tisn; +} + static const struct mlx5e_profile mlx5i_nic_profile = { .init = mlx5i_init, .cleanup = mlx5i_cleanup, @@ -499,6 +511,7 @@ static const struct mlx5e_profile mlx5i_nic_profile = { .max_tc = MLX5I_MAX_NUM_TC, .stats_grps = mlx5i_stats_grps, .stats_grps_num = mlx5i_stats_grps_num, + .get_tisn = mlx5i_get_tisn, }; /* mlx5i netdev NDos */ @@ -770,7 +783,7 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u32 port_num, } /* This should only be called once per mdev */ - err = mlx5e_create_mdev_resources(mdev); + err = mlx5e_create_mdev_resources(mdev, false); if (err) goto destroy_ht; } @@ -829,7 +842,7 @@ int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev, *params = (struct rdma_netdev_alloc_params){ .sizeof_priv = sizeof(struct mlx5i_priv) + sizeof(struct mlx5e_priv), - .txqs = nch * MLX5E_MAX_NUM_TC, + .txqs = nch * MLX5_MAX_NUM_TC, .rxqs = nch, .param = mdev, .initialize_rdma_netdev = mlx5_rdma_setup_rn, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h index f3f2af9720..2ab6437a1c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h @@ -53,6 +53,7 @@ extern const struct mlx5e_rx_handlers mlx5i_rx_handlers; struct mlx5i_priv { struct rdma_netdev rn; /* keep this first */ u32 qpn; + u32 tisn; bool sub_interface; u32 num_sub_interfaces; u32 qkey; @@ -63,6 +64,7 @@ struct mlx5i_priv { }; int mlx5i_create_tis(struct mlx5_core_dev *mdev, u32 underlay_qpn, u32 *tisn); +u32 mlx5i_get_tisn(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv, u8 lag_port, u8 tc); /* Underlay QP create/destroy functions */ int mlx5i_create_underlay_qp(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c index 03e6812979..f87471306f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c @@ -218,7 +218,7 @@ static int mlx5i_pkey_open(struct net_device *netdev) goto err_unint_underlay_qp; } - err = mlx5i_create_tis(mdev, ipriv->qpn, &epriv->tisn[0][0]); + err = mlx5i_create_tis(mdev, ipriv->qpn, &ipriv->tisn); if (err) { mlx5_core_warn(mdev, "create child tis failed, %d\n", err); goto err_remove_rx_uderlay_qp; @@ -240,7 +240,7 @@ static int mlx5i_pkey_open(struct net_device *netdev) err_close_channels: mlx5e_close_channels(&epriv->channels); err_clear_state_opened_flag: - mlx5e_destroy_tis(mdev, epriv->tisn[0][0]); + mlx5e_destroy_tis(mdev, ipriv->tisn); err_remove_rx_uderlay_qp: mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qpn); err_unint_underlay_qp: @@ -269,7 +269,7 @@ static int mlx5i_pkey_close(struct net_device *netdev) mlx5i_uninit_underlay_qp(priv); mlx5e_deactivate_priv_channels(priv); mlx5e_close_channels(&priv->channels); - mlx5e_destroy_tis(mdev, priv->tisn[0][0]); + mlx5e_destroy_tis(mdev, ipriv->tisn); unlock: mutex_unlock(&priv->state_lock); return 0; @@ -361,6 +361,7 @@ static const struct mlx5e_profile mlx5i_pkey_nic_profile = { .update_stats = NULL, .rx_handlers = &mlx5i_rx_handlers, .max_tc = MLX5I_MAX_NUM_TC, + .get_tisn = mlx5i_get_tisn, }; const struct mlx5e_profile *mlx5i_pkey_get_profile(void) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index d14459e5c0..69d482f7c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -703,8 +703,10 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev) return err; } - if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) + if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) { mlx5_lag_port_sel_destroy(ldev); + ldev->buckets = 1; + } if (mlx5_lag_has_drop_rule(ldev)) mlx5_lag_drop_rule_cleanup(ldev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 0c83ef1742..0361741632 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -266,9 +266,6 @@ static int mlx5_ptp_settime_real_time(struct mlx5_core_dev *mdev, { u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {}; - if (!mlx5_modify_mtutc_allowed(mdev)) - return 0; - if (ts->tv_sec < 0 || ts->tv_sec > U32_MAX || ts->tv_nsec < 0 || ts->tv_nsec > NSEC_PER_SEC) return -EINVAL; @@ -286,12 +283,15 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 struct mlx5_timer *timer = &clock->timer; struct mlx5_core_dev *mdev; unsigned long flags; - int err; mdev = container_of(clock, struct mlx5_core_dev, clock); - err = mlx5_ptp_settime_real_time(mdev, ts); - if (err) - return err; + + if (mlx5_modify_mtutc_allowed(mdev)) { + int err = mlx5_ptp_settime_real_time(mdev, ts); + + if (err) + return err; + } write_seqlock_irqsave(&clock->lock, flags); timecounter_init(&timer->tc, &timer->cycles, timespec64_to_ns(ts)); @@ -341,9 +341,6 @@ static int mlx5_ptp_adjtime_real_time(struct mlx5_core_dev *mdev, s64 delta) { u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {}; - if (!mlx5_modify_mtutc_allowed(mdev)) - return 0; - /* HW time adjustment range is checked. If out of range, settime instead */ if (!mlx5_is_mtutc_time_adj_cap(mdev, delta)) { struct timespec64 ts; @@ -367,13 +364,16 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) struct mlx5_timer *timer = &clock->timer; struct mlx5_core_dev *mdev; unsigned long flags; - int err; mdev = container_of(clock, struct mlx5_core_dev, clock); - err = mlx5_ptp_adjtime_real_time(mdev, delta); - if (err) - return err; + if (mlx5_modify_mtutc_allowed(mdev)) { + int err = mlx5_ptp_adjtime_real_time(mdev, delta); + + if (err) + return err; + } + write_seqlock_irqsave(&clock->lock, flags); timecounter_adjtime(&timer->tc, delta); mlx5_update_clock_info_page(mdev); @@ -396,15 +396,14 @@ static int mlx5_ptp_freq_adj_real_time(struct mlx5_core_dev *mdev, long scaled_p { u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {}; - if (!mlx5_modify_mtutc_allowed(mdev)) - return 0; - MLX5_SET(mtutc_reg, in, operation, MLX5_MTUTC_OPERATION_ADJUST_FREQ_UTC); - if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_freq_adj_units)) { + if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_freq_adj_units) && + scaled_ppm <= S32_MAX && scaled_ppm >= S32_MIN) { + /* HW scaled_ppm support on mlx5 devices only supports a 32-bit value */ MLX5_SET(mtutc_reg, in, freq_adj_units, MLX5_MTUTC_FREQ_ADJ_UNITS_SCALED_PPM); - MLX5_SET(mtutc_reg, in, freq_adjustment, scaled_ppm); + MLX5_SET(mtutc_reg, in, freq_adjustment, (s32)scaled_ppm); } else { MLX5_SET(mtutc_reg, in, freq_adj_units, MLX5_MTUTC_FREQ_ADJ_UNITS_PPB); MLX5_SET(mtutc_reg, in, freq_adjustment, scaled_ppm_to_ppb(scaled_ppm)); @@ -420,13 +419,15 @@ static int mlx5_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) struct mlx5_core_dev *mdev; unsigned long flags; u32 mult; - int err; mdev = container_of(clock, struct mlx5_core_dev, clock); - err = mlx5_ptp_freq_adj_real_time(mdev, scaled_ppm); - if (err) - return err; + if (mlx5_modify_mtutc_allowed(mdev)) { + int err = mlx5_ptp_freq_adj_real_time(mdev, scaled_ppm); + + if (err) + return err; + } mult = (u32)adjust_by_scaled_ppm(timer->nominal_c_mult, scaled_ppm); @@ -1004,14 +1005,38 @@ static void mlx5_init_clock_info(struct mlx5_core_dev *mdev) info->frac = timer->tc.frac; } +static void mlx5_init_timer_max_freq_adjustment(struct mlx5_core_dev *mdev) +{ + struct mlx5_clock *clock = &mdev->clock; + u32 out[MLX5_ST_SZ_DW(mtutc_reg)] = {}; + u32 in[MLX5_ST_SZ_DW(mtutc_reg)] = {}; + u8 log_max_freq_adjustment = 0; + int err; + + err = mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), + MLX5_REG_MTUTC, 0, 0); + if (!err) + log_max_freq_adjustment = + MLX5_GET(mtutc_reg, out, log_max_freq_adjustment); + + if (log_max_freq_adjustment) + clock->ptp_info.max_adj = + min(S32_MAX, 1 << log_max_freq_adjustment); +} + static void mlx5_init_timer_clock(struct mlx5_core_dev *mdev) { struct mlx5_clock *clock = &mdev->clock; + /* Configure the PHC */ + clock->ptp_info = mlx5_ptp_clock_info; + + if (MLX5_CAP_MCAM_REG(mdev, mtutc)) + mlx5_init_timer_max_freq_adjustment(mdev); + mlx5_timecounter_init(mdev); mlx5_init_clock_info(mdev); mlx5_init_overflow_period(clock); - clock->ptp_info = mlx5_ptp_clock_info; if (mlx5_real_time_mode(mdev)) { struct timespec64 ts; @@ -1042,11 +1067,10 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev) } seqlock_init(&clock->lock); - mlx5_init_timer_clock(mdev); INIT_WORK(&clock->pps_info.out_work, mlx5_pps_out); - /* Configure the PHC */ - clock->ptp_info = mlx5_ptp_clock_info; + /* Initialize the device clock */ + mlx5_init_timer_clock(mdev); /* Initialize 1PPS data structures */ mlx5_init_pps(mdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index e8e50563e9..e7d59cfa87 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -256,6 +256,13 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom_comp_dev *devcom) devcom_free_comp_dev(devcom); } +int mlx5_devcom_comp_get_size(struct mlx5_devcom_comp_dev *devcom) +{ + struct mlx5_devcom_comp *comp = devcom->comp; + + return kref_read(&comp->ref); +} + int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, int event, int rollback_event, void *event_data) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h index fc23bbef87..ec32b686f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h @@ -31,6 +31,7 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom_comp_dev *devcom); int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, int event, int rollback_event, void *event_data); +int mlx5_devcom_comp_get_size(struct mlx5_devcom_comp_dev *devcom); void mlx5_devcom_comp_set_ready(struct mlx5_devcom_comp_dev *devcom, bool ready); bool mlx5_devcom_comp_is_ready(struct mlx5_devcom_comp_dev *devcom); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c index 9482e51ac8..7c5516b0a8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c @@ -13,11 +13,13 @@ struct mlx5_dm { unsigned long *steering_sw_icm_alloc_blocks; unsigned long *header_modify_sw_icm_alloc_blocks; unsigned long *header_modify_pattern_sw_icm_alloc_blocks; + unsigned long *header_encap_sw_icm_alloc_blocks; }; struct mlx5_dm *mlx5_dm_create(struct mlx5_core_dev *dev) { u64 header_modify_pattern_icm_blocks = 0; + u64 header_sw_encap_icm_blocks = 0; u64 header_modify_icm_blocks = 0; u64 steering_icm_blocks = 0; struct mlx5_dm *dm; @@ -54,6 +56,17 @@ struct mlx5_dm *mlx5_dm_create(struct mlx5_core_dev *dev) goto err_modify_hdr; } + if (MLX5_CAP_DEV_MEM(dev, log_indirect_encap_sw_icm_size)) { + header_sw_encap_icm_blocks = + BIT(MLX5_CAP_DEV_MEM(dev, log_indirect_encap_sw_icm_size) - + MLX5_LOG_SW_ICM_BLOCK_SIZE(dev)); + + dm->header_encap_sw_icm_alloc_blocks = + bitmap_zalloc(header_sw_encap_icm_blocks, GFP_KERNEL); + if (!dm->header_encap_sw_icm_alloc_blocks) + goto err_pattern; + } + support_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(dev, sw_owner_v2) && MLX5_CAP_FLOWTABLE_NIC_TX(dev, sw_owner_v2) && MLX5_CAP64_DEV_MEM(dev, header_modify_pattern_sw_icm_start_address); @@ -66,11 +79,14 @@ struct mlx5_dm *mlx5_dm_create(struct mlx5_core_dev *dev) dm->header_modify_pattern_sw_icm_alloc_blocks = bitmap_zalloc(header_modify_pattern_icm_blocks, GFP_KERNEL); if (!dm->header_modify_pattern_sw_icm_alloc_blocks) - goto err_pattern; + goto err_sw_encap; } return dm; +err_sw_encap: + bitmap_free(dm->header_encap_sw_icm_alloc_blocks); + err_pattern: bitmap_free(dm->header_modify_sw_icm_alloc_blocks); @@ -105,6 +121,14 @@ void mlx5_dm_cleanup(struct mlx5_core_dev *dev) bitmap_free(dm->header_modify_sw_icm_alloc_blocks); } + if (dm->header_encap_sw_icm_alloc_blocks) { + WARN_ON(!bitmap_empty(dm->header_encap_sw_icm_alloc_blocks, + BIT(MLX5_CAP_DEV_MEM(dev, + log_indirect_encap_sw_icm_size) - + MLX5_LOG_SW_ICM_BLOCK_SIZE(dev)))); + bitmap_free(dm->header_encap_sw_icm_alloc_blocks); + } + if (dm->header_modify_pattern_sw_icm_alloc_blocks) { WARN_ON(!bitmap_empty(dm->header_modify_pattern_sw_icm_alloc_blocks, BIT(MLX5_CAP_DEV_MEM(dev, @@ -164,6 +188,13 @@ int mlx5_dm_sw_icm_alloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type, log_header_modify_pattern_sw_icm_size); block_map = dm->header_modify_pattern_sw_icm_alloc_blocks; break; + case MLX5_SW_ICM_TYPE_SW_ENCAP: + icm_start_addr = MLX5_CAP64_DEV_MEM(dev, + indirect_encap_sw_icm_start_address); + log_icm_size = MLX5_CAP_DEV_MEM(dev, + log_indirect_encap_sw_icm_size); + block_map = dm->header_encap_sw_icm_alloc_blocks; + break; default: return -EINVAL; } @@ -242,6 +273,11 @@ int mlx5_dm_sw_icm_dealloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type header_modify_pattern_sw_icm_start_address); block_map = dm->header_modify_pattern_sw_icm_alloc_blocks; break; + case MLX5_SW_ICM_TYPE_SW_ENCAP: + icm_start_addr = MLX5_CAP64_DEV_MEM(dev, + indirect_encap_sw_icm_start_address); + block_map = dm->header_encap_sw_icm_alloc_blocks; + break; default: return -EINVAL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a17152c1cb..e285823bd0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -219,7 +219,6 @@ static void mlx5_set_driver_version(struct mlx5_core_dev *dev) int driver_ver_sz = MLX5_FLD_SZ_BYTES(set_driver_version_in, driver_version); u8 in[MLX5_ST_SZ_BYTES(set_driver_version_in)] = {}; - int remaining_size = driver_ver_sz; char *string; if (!MLX5_CAP_GEN(dev, driver_version)) @@ -227,22 +226,9 @@ static void mlx5_set_driver_version(struct mlx5_core_dev *dev) string = MLX5_ADDR_OF(set_driver_version_in, in, driver_version); - strncpy(string, "Linux", remaining_size); - - remaining_size = max_t(int, 0, driver_ver_sz - strlen(string)); - strncat(string, ",", remaining_size); - - remaining_size = max_t(int, 0, driver_ver_sz - strlen(string)); - strncat(string, KBUILD_MODNAME, remaining_size); - - remaining_size = max_t(int, 0, driver_ver_sz - strlen(string)); - strncat(string, ",", remaining_size); - - remaining_size = max_t(int, 0, driver_ver_sz - strlen(string)); - - snprintf(string + strlen(string), remaining_size, "%u.%u.%u", - LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL, - LINUX_VERSION_SUBLEVEL); + snprintf(string, driver_ver_sz, "Linux,%s,%u.%u.%u", + KBUILD_MODNAME, LINUX_VERSION_MAJOR, + LINUX_VERSION_PATCHLEVEL, LINUX_VERSION_SUBLEVEL); /*Send the command*/ MLX5_SET(set_driver_version_in, in, opcode, @@ -1494,6 +1480,14 @@ int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev) if (err) goto err_register; + err = mlx5_crdump_enable(dev); + if (err) + mlx5_core_err(dev, "mlx5_crdump_enable failed with error code %d\n", err); + + err = mlx5_hwmon_dev_register(dev); + if (err) + mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err); + mutex_unlock(&dev->intf_state_mutex); return 0; @@ -1519,7 +1513,10 @@ int mlx5_init_one(struct mlx5_core_dev *dev) int err; devl_lock(devlink); + devl_register(devlink); err = mlx5_init_one_devl_locked(dev); + if (err) + devl_unregister(devlink); devl_unlock(devlink); return err; } @@ -1531,6 +1528,8 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev) devl_lock(devlink); mutex_lock(&dev->intf_state_mutex); + mlx5_hwmon_dev_unregister(dev); + mlx5_crdump_disable(dev); mlx5_unregister_device(dev); if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { @@ -1548,6 +1547,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev) mlx5_function_teardown(dev, true); out: mutex_unlock(&dev->intf_state_mutex); + devl_unregister(devlink); devl_unlock(devlink); } @@ -1694,16 +1694,23 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev) } devl_lock(devlink); + devl_register(devlink); + err = mlx5_devlink_params_register(priv_to_devlink(dev)); - devl_unlock(devlink); if (err) { mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); - goto query_hca_caps_err; + goto params_reg_err; } + devl_unlock(devlink); return 0; +params_reg_err: + devl_unregister(devlink); + devl_unlock(devlink); query_hca_caps_err: + devl_unregister(devlink); + devl_unlock(devlink); mlx5_function_disable(dev, true); out: dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; @@ -1716,6 +1723,7 @@ void mlx5_uninit_one_light(struct mlx5_core_dev *dev) devl_lock(devlink); mlx5_devlink_params_unregister(priv_to_devlink(dev)); + devl_unregister(devlink); devl_unlock(devlink); if (dev->state != MLX5_DEVICE_STATE_UP) return; @@ -1957,16 +1965,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto err_init_one; } - err = mlx5_crdump_enable(dev); - if (err) - dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); - - err = mlx5_hwmon_dev_register(dev); - if (err) - mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err); - pci_save_state(pdev); - devlink_register(devlink); return 0; err_init_one: @@ -1987,16 +1986,9 @@ static void remove_one(struct pci_dev *pdev) struct devlink *devlink = priv_to_devlink(dev); set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); - /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using - * devlink notify APIs. - * Hence, we must drain them before unregistering the devlink. - */ mlx5_drain_fw_reset(dev); mlx5_drain_health_wq(dev); - devlink_unregister(devlink); mlx5_sriov_disable(pdev, false); - mlx5_hwmon_dev_unregister(dev); - mlx5_crdump_disable(dev); mlx5_uninit_one(dev); mlx5_pci_close(dev); mlx5_mdev_uninit(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 6b14e347d9..a79b795936 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -243,6 +243,7 @@ int mlx5_query_mcam_reg(struct mlx5_core_dev *dev, u32 *mcap, u8 feature_group, u8 access_reg_group); int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam, u8 feature_group, u8 access_reg_group); +int mlx5_query_mpir_reg(struct mlx5_core_dev *dev, u32 *mpir); void mlx5_lag_add_netdev(struct mlx5_core_dev *dev, struct net_device *netdev); void mlx5_lag_remove_netdev(struct mlx5_core_dev *dev, struct net_device *netdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index 4dcf995cb1..6bac8ad70b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -19,6 +19,7 @@ #define MLX5_IRQ_CTRL_SF_MAX 8 /* min num of vectors for SFs to be enabled */ #define MLX5_IRQ_VEC_COMP_BASE_SF 2 +#define MLX5_IRQ_VEC_COMP_BASE 1 #define MLX5_EQ_SHARE_IRQ_MAX_COMP (8) #define MLX5_EQ_SHARE_IRQ_MAX_CTRL (UINT_MAX) @@ -246,6 +247,7 @@ static void irq_set_name(struct mlx5_irq_pool *pool, char *name, int vecidx) return; } + vecidx -= MLX5_IRQ_VEC_COMP_BASE; snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", vecidx); } @@ -585,7 +587,7 @@ struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu, struct mlx5_irq_table *table = mlx5_irq_table_get(dev); struct mlx5_irq_pool *pool = table->pcif_pool; struct irq_affinity_desc af_desc; - int offset = 1; + int offset = MLX5_IRQ_VEC_COMP_BASE; if (!pool->xa_num_irqs.max) offset = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 7d8c732818..7fba1c46e2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -1206,3 +1206,13 @@ int mlx5_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) *speed = max_speed; return 0; } + +int mlx5_query_mpir_reg(struct mlx5_core_dev *dev, u32 *mpir) +{ + u32 in[MLX5_ST_SZ_DW(mpir_reg)] = {}; + int sz = MLX5_ST_SZ_BYTES(mpir_reg); + + MLX5_SET(mpir_reg, in, local_port, 1); + + return mlx5_core_access_reg(dev, in, sz, mpir, sz, MLX5_REG_MPIR, 0, 0); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index 169c2c68ed..7ebe712808 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -75,7 +75,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia goto peer_devlink_set_err; } - devlink_register(devlink); return 0; peer_devlink_set_err: @@ -95,24 +94,28 @@ mdev_err: static void mlx5_sf_dev_remove(struct auxiliary_device *adev) { struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); - struct devlink *devlink = priv_to_devlink(sf_dev->mdev); + struct mlx5_core_dev *mdev = sf_dev->mdev; + struct devlink *devlink; - mlx5_drain_health_wq(sf_dev->mdev); - devlink_unregister(devlink); - if (mlx5_dev_is_lightweight(sf_dev->mdev)) - mlx5_uninit_one_light(sf_dev->mdev); + devlink = priv_to_devlink(mdev); + set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); + mlx5_drain_health_wq(mdev); + if (mlx5_dev_is_lightweight(mdev)) + mlx5_uninit_one_light(mdev); else - mlx5_uninit_one(sf_dev->mdev); - iounmap(sf_dev->mdev->iseg); - mlx5_mdev_uninit(sf_dev->mdev); + mlx5_uninit_one(mdev); + iounmap(mdev->iseg); + mlx5_mdev_uninit(mdev); mlx5_devlink_free(devlink); } static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev) { struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); + struct mlx5_core_dev *mdev = sf_dev->mdev; - mlx5_unload_one(sf_dev->mdev, false); + set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); + mlx5_unload_one(mdev, false); } static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index d2b65a0ce4..2ebb61ef3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -1177,7 +1177,6 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn, bool ignore_flow_level, u32 flow_source) { - struct mlx5dr_cmd_flow_destination_hw_info tmp_hw_dest; struct mlx5dr_cmd_flow_destination_hw_info *hw_dests; struct mlx5dr_action **ref_actions; struct mlx5dr_action *action; @@ -1256,11 +1255,8 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn, * one that done in the TX. * So, if one of the ft target is wire, put it at the end of the dest list. */ - if (is_ft_wire && num_dst_ft > 1) { - tmp_hw_dest = hw_dests[last_dest]; - hw_dests[last_dest] = hw_dests[num_of_dests - 1]; - hw_dests[num_of_dests - 1] = tmp_hw_dest; - } + if (is_ft_wire && num_dst_ft > 1) + swap(hw_dests[last_dest], hw_dests[num_of_dests - 1]); action = dr_action_create_generic(DR_ACTION_TYP_FT); if (!action) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 21753f3278..1005bb6935 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -440,6 +440,27 @@ out: } EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); +int mlx5_query_nic_vport_sd_group(struct mlx5_core_dev *mdev, u8 *sd_group) +{ + int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); + u32 *out; + int err; + + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) + return -ENOMEM; + + err = mlx5_query_nic_vport_context(mdev, 0, out); + if (err) + goto out; + + *sd_group = MLX5_GET(query_nic_vport_context_out, out, + nic_vport_context.sd_group); +out: + kvfree(out); + return err; +} + int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) { u32 *out; diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index 3d09fa5459..ba30386868 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/phy.h> #include <linux/platform_device.h> +#include <linux/rtnetlink.h> #include <linux/skbuff.h> #include "mlxbf_gige.h" @@ -139,13 +140,10 @@ static int mlxbf_gige_open(struct net_device *netdev) control |= MLXBF_GIGE_CONTROL_PORT_EN; writeq(control, priv->base + MLXBF_GIGE_CONTROL); - err = mlxbf_gige_request_irqs(priv); - if (err) - return err; mlxbf_gige_cache_stats(priv); err = mlxbf_gige_clean_port(priv); if (err) - goto free_irqs; + return err; /* Clear driver's valid_polarity to match hardware, * since the above call to clean_port() resets the @@ -157,7 +155,7 @@ static int mlxbf_gige_open(struct net_device *netdev) err = mlxbf_gige_tx_init(priv); if (err) - goto free_irqs; + goto phy_deinit; err = mlxbf_gige_rx_init(priv); if (err) goto tx_deinit; @@ -166,6 +164,10 @@ static int mlxbf_gige_open(struct net_device *netdev) napi_enable(&priv->napi); netif_start_queue(netdev); + err = mlxbf_gige_request_irqs(priv); + if (err) + goto napi_deinit; + /* Set bits in INT_EN that we care about */ int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR | MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS | @@ -182,11 +184,17 @@ static int mlxbf_gige_open(struct net_device *netdev) return 0; +napi_deinit: + netif_stop_queue(netdev); + napi_disable(&priv->napi); + netif_napi_del(&priv->napi); + mlxbf_gige_rx_deinit(priv); + tx_deinit: mlxbf_gige_tx_deinit(priv); -free_irqs: - mlxbf_gige_free_irqs(priv); +phy_deinit: + phy_stop(phydev); return err; } @@ -485,8 +493,13 @@ static void mlxbf_gige_shutdown(struct platform_device *pdev) { struct mlxbf_gige *priv = platform_get_drvdata(pdev); - writeq(0, priv->base + MLXBF_GIGE_INT_EN); - mlxbf_gige_clean_port(priv); + rtnl_lock(); + netif_device_detach(priv->netdev); + + if (netif_running(priv->netdev)) + dev_close(priv->netdev); + + rtnl_unlock(); } static const struct acpi_device_id __maybe_unused mlxbf_gige_acpi_match[] = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index e827c78be1..e3271c845e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -282,6 +282,12 @@ MLXSW_ITEM32(cmd_mbox, query_fw, fw_day, 0x14, 0, 8); */ MLXSW_ITEM32(cmd_mbox, query_fw, lag_mode_support, 0x18, 1, 1); +/* cmd_mbox_query_fw_cff_support + * 0: CONFIG_PROFILE.flood_mode = 5 (CFF) is not supported by FW + * 1: CONFIG_PROFILE.flood_mode = 5 (CFF) is supported by FW + */ +MLXSW_ITEM32(cmd_mbox, query_fw, cff_support, 0x18, 2, 1); + /* cmd_mbox_query_fw_clr_int_base_offset * Clear Interrupt register's offset from clr_int_bar register * in PCI address space. @@ -779,6 +785,11 @@ enum mlxsw_cmd_mbox_config_profile_flood_mode { * used. */ MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED = 4, + /* CFF - Compressed FID Flood (CFF) mode. + * Reserved when legacy bridge model is used. + * Supported only by Spectrum-2+. + */ + MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF = 5, }; /* cmd_mbox_config_profile_flood_mode diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index f23421f038..4a79c0d7e7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -211,6 +211,13 @@ mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core) } EXPORT_SYMBOL(mlxsw_core_lag_mode); +enum mlxsw_cmd_mbox_config_profile_flood_mode +mlxsw_core_flood_mode(struct mlxsw_core *mlxsw_core) +{ + return mlxsw_core->bus->flood_mode(mlxsw_core->bus_priv); +} +EXPORT_SYMBOL(mlxsw_core_flood_mode); + void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) { return mlxsw_core->driver_priv; @@ -842,7 +849,7 @@ free_skb: static const struct mlxsw_listener mlxsw_emad_rx_listener = MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false, - EMAD, DISCARD); + EMAD, FORWARD); static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 764d14bd5b..6d11225594 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -38,6 +38,8 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag); enum mlxsw_cmd_mbox_config_profile_lag_mode mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core); +enum mlxsw_cmd_mbox_config_profile_flood_mode +mlxsw_core_flood_mode(struct mlxsw_core *mlxsw_core); void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core); @@ -322,7 +324,12 @@ struct mlxsw_config_profile { u16 max_regions; u8 max_flood_tables; u8 max_vid_flood_tables; + + /* Flood mode to use if used_flood_mode. If flood_mode_prefer_cff, + * the backup flood mode (if any) when CFF unsupported. + */ u8 flood_mode; + u8 max_fid_offset_flood_tables; u16 fid_offset_flood_table_size; u8 max_fid_flood_tables; @@ -338,6 +345,7 @@ struct mlxsw_config_profile { u8 kvd_hash_double_parts; u8 cqe_time_stamp_type; bool lag_mode_prefer_sw; + bool flood_mode_prefer_cff; struct mlxsw_swid_config swid_config[MLXSW_CONFIG_PROFILE_SWID_COUNT]; }; @@ -489,6 +497,7 @@ struct mlxsw_bus { u32 (*read_utc_sec)(void *bus_priv); u32 (*read_utc_nsec)(void *bus_priv); enum mlxsw_cmd_mbox_config_profile_lag_mode (*lag_mode)(void *bus_priv); + enum mlxsw_cmd_mbox_config_profile_flood_mode (*flood_mode)(void *priv); u8 features; }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c index faa63ea9b8..1915fa41c6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c @@ -95,7 +95,7 @@ struct mlxsw_afa_set { */ has_trap:1, has_police:1; - unsigned int ref_count; + refcount_t ref_count; struct mlxsw_afa_set *next; /* Pointer to the next set. */ struct mlxsw_afa_set *prev; /* Pointer to the previous set, * note that set may have multiple @@ -120,7 +120,7 @@ struct mlxsw_afa_fwd_entry { struct rhash_head ht_node; struct mlxsw_afa_fwd_entry_ht_key ht_key; u32 kvdl_index; - unsigned int ref_count; + refcount_t ref_count; }; static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = { @@ -282,7 +282,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first) /* Need to initialize the set to pass by default */ mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0); set->ht_key.is_first = is_first; - set->ref_count = 1; + refcount_set(&set->ref_count, 1); return set; } @@ -330,7 +330,7 @@ static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa, static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa, struct mlxsw_afa_set *set) { - if (--set->ref_count) + if (!refcount_dec_and_test(&set->ref_count)) return; if (set->shared) mlxsw_afa_set_unshare(mlxsw_afa, set); @@ -350,7 +350,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_get(struct mlxsw_afa *mlxsw_afa, set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key, mlxsw_afa_set_ht_params); if (set) { - set->ref_count++; + refcount_inc(&set->ref_count); mlxsw_afa_set_put(mlxsw_afa, orig_set); } else { set = orig_set; @@ -564,7 +564,7 @@ mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u16 local_port) if (!fwd_entry) return ERR_PTR(-ENOMEM); fwd_entry->ht_key.local_port = local_port; - fwd_entry->ref_count = 1; + refcount_set(&fwd_entry->ref_count, 1); err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht, &fwd_entry->ht_node, @@ -607,7 +607,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port) fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key, mlxsw_afa_fwd_entry_ht_params); if (fwd_entry) { - fwd_entry->ref_count++; + refcount_inc(&fwd_entry->ref_count); return fwd_entry; } return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port); @@ -616,7 +616,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port) static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa, struct mlxsw_afa_fwd_entry *fwd_entry) { - if (--fwd_entry->ref_count) + if (!refcount_dec_and_test(&fwd_entry->ref_count)) return; mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c index 0d5e6f9b46..947500f8ed 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c @@ -5,6 +5,7 @@ #include <linux/slab.h> #include <linux/list.h> #include <linux/errno.h> +#include <linux/refcount.h> #include "item.h" #include "core_acl_flex_keys.h" @@ -107,7 +108,7 @@ EXPORT_SYMBOL(mlxsw_afk_destroy); struct mlxsw_afk_key_info { struct list_head list; - unsigned int ref_count; + refcount_t ref_count; unsigned int blocks_count; int element_to_block[MLXSW_AFK_ELEMENT_MAX]; /* index is element, value * is index inside "blocks" @@ -334,7 +335,7 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk, if (err) goto err_picker; list_add(&key_info->list, &mlxsw_afk->key_info_list); - key_info->ref_count = 1; + refcount_set(&key_info->ref_count, 1); return key_info; err_picker: @@ -356,7 +357,7 @@ mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk, key_info = mlxsw_afk_key_info_find(mlxsw_afk, elusage); if (key_info) { - key_info->ref_count++; + refcount_inc(&key_info->ref_count); return key_info; } return mlxsw_afk_key_info_create(mlxsw_afk, elusage); @@ -365,7 +366,7 @@ EXPORT_SYMBOL(mlxsw_afk_key_info_get); void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info) { - if (--key_info->ref_count) + if (!refcount_dec_and_test(&key_info->ref_count)) return; mlxsw_afk_key_info_destroy(key_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 53b150b7ae..6c06b05927 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = { .got_inactive = mlxsw_env_got_inactive, }; -static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env) +static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env) { char mcam_pl[MLXSW_REG_MCAM_LEN]; - bool mcia_128b_supported; + bool mcia_128b_supported = false; int err; mlxsw_reg_mcam_pack(mcam_pl, MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES); err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl); - if (err) - return err; - - mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B, - &mcia_128b_supported); + if (!err) + mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B, + &mcia_128b_supported); mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48; - - return 0; } int mlxsw_env_init(struct mlxsw_core *mlxsw_core, @@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, if (err) goto err_type_set; - err = mlxsw_env_max_module_eeprom_len_query(env); - if (err) - goto err_eeprom_len_query; - + mlxsw_env_max_module_eeprom_len_query(env); env->line_cards[0]->active = true; return 0; -err_eeprom_len_query: err_type_set: mlxsw_env_module_event_disable(env, 0); err_mlxsw_env_module_event_enable: diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index e4b25e1874..f42a1b1c93 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -106,7 +106,9 @@ struct mlxsw_pci { u64 utc_sec_offset; u64 utc_nsec_offset; bool lag_mode_support; + bool cff_support; enum mlxsw_cmd_mbox_config_profile_lag_mode lag_mode; + enum mlxsw_cmd_mbox_config_profile_flood_mode flood_mode; struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT]; u32 doorbell_offset; struct mlxsw_core *core; @@ -130,6 +132,7 @@ struct mlxsw_pci { const struct pci_device_id *id; enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */ u8 num_sdq_cqs; /* Number of CQs used for SDQs */ + bool skip_reset; }; static void mlxsw_pci_queue_tasklet_schedule(struct mlxsw_pci_queue *q) @@ -1245,11 +1248,22 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_fid_flood_table_size_set( mbox, profile->fid_flood_table_size); } - if (profile->used_flood_mode) { + if (profile->flood_mode_prefer_cff && mlxsw_pci->cff_support) { + enum mlxsw_cmd_mbox_config_profile_flood_mode flood_mode = + MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF; + + mlxsw_cmd_mbox_config_profile_set_flood_mode_set(mbox, 1); + mlxsw_cmd_mbox_config_profile_flood_mode_set(mbox, flood_mode); + mlxsw_pci->flood_mode = flood_mode; + } else if (profile->used_flood_mode) { mlxsw_cmd_mbox_config_profile_set_flood_mode_set( mbox, 1); mlxsw_cmd_mbox_config_profile_flood_mode_set( mbox, profile->flood_mode); + mlxsw_pci->flood_mode = profile->flood_mode; + } else { + WARN_ON(1); + return -EINVAL; } if (profile->used_max_ib_mc) { mlxsw_cmd_mbox_config_profile_set_max_ib_mc_set( @@ -1476,11 +1490,47 @@ static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci, return -EBUSY; } -static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, - const struct pci_device_id *id) +static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci) { struct pci_dev *pdev = mlxsw_pci->pdev; char mrsr_pl[MLXSW_REG_MRSR_LEN]; + int err; + + mlxsw_reg_mrsr_pack(mrsr_pl, + MLXSW_REG_MRSR_COMMAND_RESET_AT_PCI_DISABLE); + err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); + if (err) + return err; + + device_lock_assert(&pdev->dev); + + pci_cfg_access_lock(pdev); + pci_save_state(pdev); + + err = __pci_reset_function_locked(pdev); + if (err) + pci_err(pdev, "PCI function reset failed with %d\n", err); + + pci_restore_state(pdev); + pci_cfg_access_unlock(pdev); + + return err; +} + +static int mlxsw_pci_reset_sw(struct mlxsw_pci *mlxsw_pci) +{ + char mrsr_pl[MLXSW_REG_MRSR_LEN]; + + mlxsw_reg_mrsr_pack(mrsr_pl, MLXSW_REG_MRSR_COMMAND_SOFTWARE_RESET); + return mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); +} + +static int +mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id) +{ + struct pci_dev *pdev = mlxsw_pci->pdev; + char mcam_pl[MLXSW_REG_MCAM_LEN]; + bool pci_reset_supported = false; u32 sys_status; int err; @@ -1491,8 +1541,24 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, return err; } - mlxsw_reg_mrsr_pack(mrsr_pl); - err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); + /* PCI core already issued a PCI reset, do not issue another reset. */ + if (mlxsw_pci->skip_reset) + return 0; + + mlxsw_reg_mcam_pack(mcam_pl, + MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES); + err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl); + if (!err) + mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET, + &pci_reset_supported); + + if (pci_reset_supported) { + pci_dbg(pdev, "Starting PCI reset flow\n"); + err = mlxsw_pci_reset_at_pci_disable(mlxsw_pci); + } else { + pci_dbg(pdev, "Starting software reset flow\n"); + err = mlxsw_pci_reset_sw(mlxsw_pci); + } if (err) return err; @@ -1537,9 +1603,9 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, if (!mbox) return -ENOMEM; - err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id); + err = mlxsw_pci_reset(mlxsw_pci, mlxsw_pci->id); if (err) - goto err_sw_reset; + goto err_reset; err = mlxsw_pci_alloc_irq_vectors(mlxsw_pci); if (err < 0) { @@ -1601,6 +1667,9 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, mlxsw_pci->lag_mode_support = mlxsw_cmd_mbox_query_fw_lag_mode_support_get(mbox); + mlxsw_pci->cff_support = + mlxsw_cmd_mbox_query_fw_cff_support_get(mbox); + num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox); err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages); if (err) @@ -1672,7 +1741,7 @@ err_iface_rev: err_query_fw: mlxsw_pci_free_irq_vectors(mlxsw_pci); err_alloc_irq: -err_sw_reset: +err_reset: mbox_put: mlxsw_cmd_mbox_free(mbox); return err; @@ -1917,6 +1986,14 @@ mlxsw_pci_lag_mode(void *bus_priv) return mlxsw_pci->lag_mode; } +static enum mlxsw_cmd_mbox_config_profile_flood_mode +mlxsw_pci_flood_mode(void *bus_priv) +{ + struct mlxsw_pci *mlxsw_pci = bus_priv; + + return mlxsw_pci->flood_mode; +} + static const struct mlxsw_bus mlxsw_pci_bus = { .kind = "pci", .init = mlxsw_pci_init, @@ -1929,6 +2006,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = { .read_utc_sec = mlxsw_pci_read_utc_sec, .read_utc_nsec = mlxsw_pci_read_utc_nsec, .lag_mode = mlxsw_pci_lag_mode, + .flood_mode = mlxsw_pci_flood_mode, .features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET, }; @@ -2059,11 +2137,34 @@ static void mlxsw_pci_remove(struct pci_dev *pdev) kfree(mlxsw_pci); } +static void mlxsw_pci_reset_prepare(struct pci_dev *pdev) +{ + struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); + + mlxsw_core_bus_device_unregister(mlxsw_pci->core, false); +} + +static void mlxsw_pci_reset_done(struct pci_dev *pdev) +{ + struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); + + mlxsw_pci->skip_reset = true; + mlxsw_core_bus_device_register(&mlxsw_pci->bus_info, &mlxsw_pci_bus, + mlxsw_pci, false, NULL, NULL); + mlxsw_pci->skip_reset = false; +} + +static const struct pci_error_handlers mlxsw_pci_err_handler = { + .reset_prepare = mlxsw_pci_reset_prepare, + .reset_done = mlxsw_pci_reset_done, +}; + int mlxsw_pci_driver_register(struct pci_driver *pci_driver) { pci_driver->probe = mlxsw_pci_probe; pci_driver->remove = mlxsw_pci_remove; pci_driver->shutdown = mlxsw_pci_remove; + pci_driver->err_handler = &mlxsw_pci_err_handler; return pci_register_driver(pci_driver); } EXPORT_SYMBOL(mlxsw_pci_driver_register); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 25b294fdeb..8892654c68 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1024,6 +1024,8 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u16 local_port, * ------------------------------------------ * The following register controls the association of flooding tables and MIDs * to packet types used for flooding. + * + * Reserved when CONFIG_PROFILE.flood_mode = CFF. */ #define MLXSW_REG_SFGC_ID 0x2011 #define MLXSW_REG_SFGC_LEN 0x14 @@ -1862,6 +1864,7 @@ MLXSW_ITEM32(reg, sfmr, fid, 0x00, 0, 16); * Access: RW * * Note: Reserved when legacy bridge model is used. + * Reserved when CONFIG_PROFILE.flood_mode = CFF. */ MLXSW_ITEM32(reg, sfmr, flood_rsp, 0x08, 31, 1); @@ -1872,6 +1875,7 @@ MLXSW_ITEM32(reg, sfmr, flood_rsp, 0x08, 31, 1); * Access: RW * * Note: Reserved when legacy bridge model is used and when flood_rsp=1. + * Reserved when CONFIG_PROFILE.flood_mode = CFF */ MLXSW_ITEM32(reg, sfmr, flood_bridge_type, 0x08, 28, 1); @@ -1880,6 +1884,8 @@ MLXSW_ITEM32(reg, sfmr, flood_bridge_type, 0x08, 28, 1); * Used to point into the flooding table selected by SFGC register if * the table is of type FID-Offset. Otherwise, this field is reserved. * Access: RW + * + * Note: Reserved when CONFIG_PROFILE.flood_mode = CFF */ MLXSW_ITEM32(reg, sfmr, fid_offset, 0x08, 0, 16); @@ -1938,6 +1944,35 @@ MLXSW_ITEM32(reg, sfmr, irif_v, 0x14, 24, 1); */ MLXSW_ITEM32(reg, sfmr, irif, 0x14, 0, 16); +/* reg_sfmr_cff_mid_base + * Pointer to PGT table. + * Range: 0..(cap_max_pgt-1) + * Access: RW + * + * Note: Reserved when SwitchX/-2 and Spectrum-1. + * Supported when CONFIG_PROFILE.flood_mode = CFF. + */ +MLXSW_ITEM32(reg, sfmr, cff_mid_base, 0x20, 0, 16); + +/* reg_sfmr_nve_flood_prf_id + * FID flooding profile_id for NVE Encap + * Range 0..(max_cap_nve_flood_prf-1) + * Access: RW + * + * Note: Reserved when SwitchX/-2 and Spectrum-1 + */ +MLXSW_ITEM32(reg, sfmr, nve_flood_prf_id, 0x24, 8, 2); + +/* reg_sfmr_cff_prf_id + * Compressed Fid Flooding profile_id + * Range 0..(max_cap_nve_flood_prf-1) + * Access: RW + * + * Note: Reserved when SwitchX/-2 and Spectrum-1 + * Supported only when CONFIG_PROFLE.flood_mode = CFF. + */ +MLXSW_ITEM32(reg, sfmr, cff_prf_id, 0x24, 0, 2); + /* reg_sfmr_smpe_valid * SMPE is valid. * Access: RW @@ -1959,18 +1994,11 @@ MLXSW_ITEM32(reg, sfmr, smpe, 0x28, 0, 16); static inline void mlxsw_reg_sfmr_pack(char *payload, enum mlxsw_reg_sfmr_op op, u16 fid, - u16 fid_offset, bool flood_rsp, - enum mlxsw_reg_bridge_type bridge_type, bool smpe_valid, u16 smpe) { MLXSW_REG_ZERO(sfmr, payload); mlxsw_reg_sfmr_op_set(payload, op); mlxsw_reg_sfmr_fid_set(payload, fid); - mlxsw_reg_sfmr_fid_offset_set(payload, fid_offset); - mlxsw_reg_sfmr_vtfp_set(payload, false); - mlxsw_reg_sfmr_vv_set(payload, false); - mlxsw_reg_sfmr_flood_rsp_set(payload, flood_rsp); - mlxsw_reg_sfmr_flood_bridge_type_set(payload, bridge_type); mlxsw_reg_sfmr_smpe_valid_set(payload, smpe_valid); mlxsw_reg_sfmr_smpe_set(payload, smpe); } @@ -2168,6 +2196,50 @@ static inline void mlxsw_reg_spvc_pack(char *payload, u16 local_port, bool et1, mlxsw_reg_spvc_et0_set(payload, et0); } +/* SFFP - Switch FID Flooding Profiles Register + * -------------------------------------------- + * The SFFP register populates the fid flooding profile tables used for the NVE + * flooding and Compressed-FID Flooding (CFF). + * + * Reserved on Spectrum-1. + */ +#define MLXSW_REG_SFFP_ID 0x2029 +#define MLXSW_REG_SFFP_LEN 0x0C + +MLXSW_REG_DEFINE(sffp, MLXSW_REG_SFFP_ID, MLXSW_REG_SFFP_LEN); + +/* reg_sffp_profile_id + * Profile ID a.k.a. SFMR.nve_flood_prf_id or SFMR.cff_prf_id + * Range 0..max_cap_nve_flood_prf-1 + * Access: Index + */ +MLXSW_ITEM32(reg, sffp, profile_id, 0x00, 16, 2); + +/* reg_sffp_type + * The traffic type to reach the flooding table. + * Same as SFGC.type + * Access: Index + */ +MLXSW_ITEM32(reg, sffp, type, 0x00, 0, 4); + +/* reg_sffp_flood_offset + * Flood offset. Offset to add to SFMR.cff_mid_base to get the final PGT address + * for FID flood; or offset to add to SFMR.nve_tunnel_flood_ptr to get KVD + * pointer for NVE underlay. + * Access: RW + */ +MLXSW_ITEM32(reg, sffp, flood_offset, 0x04, 0, 3); + +static inline void mlxsw_reg_sffp_pack(char *payload, u8 profile_id, + enum mlxsw_reg_sfgc_type type, + u8 flood_offset) +{ + MLXSW_REG_ZERO(sffp, payload); + mlxsw_reg_sffp_profile_id_set(payload, profile_id); + mlxsw_reg_sffp_type_set(payload, type); + mlxsw_reg_sffp_flood_offset_set(payload, flood_offset); +} + /* SPEVET - Switch Port Egress VLAN EtherType * ------------------------------------------ * The switch port egress VLAN EtherType configures which EtherType to push at @@ -10122,6 +10194,15 @@ mlxsw_reg_mgir_unpack(char *payload, u32 *hw_rev, char *fw_info_psid, MLXSW_REG_DEFINE(mrsr, MLXSW_REG_MRSR_ID, MLXSW_REG_MRSR_LEN); +enum mlxsw_reg_mrsr_command { + /* Switch soft reset, does not reset PCI firmware. */ + MLXSW_REG_MRSR_COMMAND_SOFTWARE_RESET = 1, + /* Reset will be done when PCI link will be disabled. + * This command will reset PCI firmware also. + */ + MLXSW_REG_MRSR_COMMAND_RESET_AT_PCI_DISABLE = 6, +}; + /* reg_mrsr_command * Reset/shutdown command * 0 - do nothing @@ -10130,10 +10211,11 @@ MLXSW_REG_DEFINE(mrsr, MLXSW_REG_MRSR_ID, MLXSW_REG_MRSR_LEN); */ MLXSW_ITEM32(reg, mrsr, command, 0x00, 0, 4); -static inline void mlxsw_reg_mrsr_pack(char *payload) +static inline void mlxsw_reg_mrsr_pack(char *payload, + enum mlxsw_reg_mrsr_command command) { MLXSW_REG_ZERO(mrsr, payload); - mlxsw_reg_mrsr_command_set(payload, 1); + mlxsw_reg_mrsr_command_set(payload, command); } /* MLCR - Management LED Control Register @@ -10584,6 +10666,8 @@ MLXSW_ITEM32(reg, mcam, feature_group, 0x00, 16, 8); enum mlxsw_reg_mcam_mng_feature_cap_mask_bits { /* If set, MCIA supports 128 bytes payloads. Otherwise, 48 bytes. */ MLXSW_REG_MCAM_MCIA_128B = 34, + /* If set, MRSR.command=6 is supported. */ + MLXSW_REG_MCAM_PCI_RESET = 48, }; #define MLXSW_REG_BYTES_PER_DWORD 0x4 @@ -12934,6 +13018,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(spvmlr), MLXSW_REG(spfsr), MLXSW_REG(spvc), + MLXSW_REG(sffp), MLXSW_REG(spevet), MLXSW_REG(smpe), MLXSW_REG(smid2), diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index 89dd2777ec..9d7977ebe1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -27,6 +27,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_FID, MLXSW_RES_ID_MAX_LAG, MLXSW_RES_ID_MAX_LAG_MEMBERS, + MLXSW_RES_ID_MAX_NVE_FLOOD_PRF, MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER, MLXSW_RES_ID_CELL_SIZE, MLXSW_RES_ID_MAX_HEADROOM_SIZE, @@ -88,6 +89,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_FID] = 0x2512, [MLXSW_RES_ID_MAX_LAG] = 0x2520, [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, + [MLXSW_RES_ID_MAX_NVE_FLOOD_PRF] = 0x2522, [MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER] = 0x2805, /* Bytes */ [MLXSW_RES_ID_CELL_SIZE] = 0x2803, /* Bytes */ [MLXSW_RES_ID_MAX_HEADROOM_SIZE] = 0x2811, /* Bytes */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index cec72d99d9..5d3413636a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3190,10 +3190,10 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, goto err_lag_init; } - err = mlxsw_sp_fids_init(mlxsw_sp); + err = mlxsw_sp->fid_core_ops->init(mlxsw_sp); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n"); - goto err_fids_init; + goto err_fid_core_init; } err = mlxsw_sp_policers_init(mlxsw_sp); @@ -3379,8 +3379,8 @@ err_devlink_traps_init: err_traps_init: mlxsw_sp_policers_fini(mlxsw_sp); err_policers_init: - mlxsw_sp_fids_fini(mlxsw_sp); -err_fids_init: + mlxsw_sp->fid_core_ops->fini(mlxsw_sp); +err_fid_core_init: mlxsw_sp_lag_fini(mlxsw_sp); err_lag_init: mlxsw_sp_pgt_fini(mlxsw_sp); @@ -3416,7 +3416,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->router_ops = &mlxsw_sp1_router_ops; mlxsw_sp->listeners = mlxsw_sp1_listener; mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener); - mlxsw_sp->fid_family_arr = mlxsw_sp1_fid_family_arr; + mlxsw_sp->fid_core_ops = &mlxsw_sp1_fid_core_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1; mlxsw_sp->pgt_smpe_index_valid = true; @@ -3450,7 +3450,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->router_ops = &mlxsw_sp2_router_ops; mlxsw_sp->listeners = mlxsw_sp2_listener; mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener); - mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr; + mlxsw_sp->fid_core_ops = &mlxsw_sp2_fid_core_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2; mlxsw_sp->pgt_smpe_index_valid = false; @@ -3484,7 +3484,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->router_ops = &mlxsw_sp2_router_ops; mlxsw_sp->listeners = mlxsw_sp2_listener; mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener); - mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr; + mlxsw_sp->fid_core_ops = &mlxsw_sp2_fid_core_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3; mlxsw_sp->pgt_smpe_index_valid = false; @@ -3518,7 +3518,7 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->router_ops = &mlxsw_sp2_router_ops; mlxsw_sp->listeners = mlxsw_sp2_listener; mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener); - mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr; + mlxsw_sp->fid_core_ops = &mlxsw_sp2_fid_core_ops; mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP4; mlxsw_sp->pgt_smpe_index_valid = false; @@ -3552,7 +3552,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) mlxsw_sp_devlink_traps_fini(mlxsw_sp); mlxsw_sp_traps_fini(mlxsw_sp); mlxsw_sp_policers_fini(mlxsw_sp); - mlxsw_sp_fids_fini(mlxsw_sp); + mlxsw_sp->fid_core_ops->fini(mlxsw_sp); mlxsw_sp_lag_fini(mlxsw_sp); mlxsw_sp_pgt_fini(mlxsw_sp); mlxsw_sp_kvdl_fini(mlxsw_sp); @@ -3598,6 +3598,7 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = { .used_cqe_time_stamp_type = 1, .cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, .lag_mode_prefer_sw = true, + .flood_mode_prefer_cff = true, }; /* Reduce number of LAGs from full capacity (256) to the maximum supported LAGs @@ -3626,6 +3627,7 @@ static const struct mlxsw_config_profile mlxsw_sp4_config_profile = { .used_cqe_time_stamp_type = 1, .cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, .lag_mode_prefer_sw = true, + .flood_mode_prefer_cff = true, }; static void @@ -4515,6 +4517,10 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_port->lagged = 1; lag->ref_count++; + err = mlxsw_sp_fid_port_join_lag(mlxsw_sp_port); + if (err) + goto err_fid_port_join_lag; + /* Port is no longer usable as a router interface */ if (mlxsw_sp_port->default_vlan->fid) mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan); @@ -4534,6 +4540,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, err_replay: mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev); err_router_join: + mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port); +err_fid_port_join_lag: lag->ref_count--; mlxsw_sp_port->lagged = 0; mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id, @@ -4569,6 +4577,8 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, */ mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev); + mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port); + if (lag->ref_count == 1) mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index c70333b460..a0c9775fa9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -205,7 +205,7 @@ struct mlxsw_sp { const struct mlxsw_sp_mall_ops *mall_ops; const struct mlxsw_sp_router_ops *router_ops; const struct mlxsw_listener *listeners; - const struct mlxsw_sp_fid_family **fid_family_arr; + const struct mlxsw_sp_fid_core_ops *fid_core_ops; size_t listeners_count; u32 lowest_shaper_bs; struct rhashtable ipv6_addr_ht; @@ -252,6 +252,11 @@ struct mlxsw_sp_ptp_ops { const struct mlxsw_tx_info *tx_info); }; +struct mlxsw_sp_fid_core_ops { + int (*init)(struct mlxsw_sp *mlxsw_sp); + void (*fini)(struct mlxsw_sp *mlxsw_sp); +}; + static inline struct mlxsw_sp_upper * mlxsw_sp_lag_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id) { @@ -508,6 +513,10 @@ enum mlxsw_sp_flood_type { MLXSW_SP_FLOOD_TYPE_UC, MLXSW_SP_FLOOD_TYPE_BC, MLXSW_SP_FLOOD_TYPE_MC, + /* For RSP FIDs in CFF mode. */ + MLXSW_SP_FLOOD_TYPE_NOT_UC, + /* For NVE traffic. */ + MLXSW_SP_FLOOD_TYPE_ANY, }; int mlxsw_sp_port_get_stats_raw(struct net_device *dev, int grp, @@ -753,6 +762,8 @@ union mlxsw_sp_l3addr { }; u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif); +int mlxsw_sp_rif_subport_port(const struct mlxsw_sp_rif *rif, + u16 *port, bool *is_lag); int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, struct netlink_ext_ack *extack); void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp); @@ -1319,11 +1330,11 @@ struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid); int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port); void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port); -int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp); +int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port); +void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port); -extern const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[]; -extern const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[]; +extern const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops; +extern const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops; /* spectrum_mr.c */ enum mlxsw_sp_mr_route_prio { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 7c59c8a135..b01b000bc7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -9,6 +9,7 @@ #include <linux/rhashtable.h> #include <linux/netdevice.h> #include <linux/mutex.h> +#include <linux/refcount.h> #include <net/net_namespace.h> #include <net/tc_act/tc_vlan.h> @@ -55,7 +56,7 @@ struct mlxsw_sp_acl_ruleset { struct rhash_head ht_node; /* Member of acl HT */ struct mlxsw_sp_acl_ruleset_ht_key ht_key; struct rhashtable rule_ht; - unsigned int ref_count; + refcount_t ref_count; unsigned int min_prio; unsigned int max_prio; unsigned long priv[]; @@ -99,7 +100,7 @@ static bool mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) { /* We hold a reference on ruleset ourselves */ - return ruleset->ref_count == 2; + return refcount_read(&ruleset->ref_count) == 2; } int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, @@ -176,7 +177,7 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp, ruleset = kzalloc(alloc_size, GFP_KERNEL); if (!ruleset) return ERR_PTR(-ENOMEM); - ruleset->ref_count = 1; + refcount_set(&ruleset->ref_count, 1); ruleset->ht_key.block = block; ruleset->ht_key.chain_index = chain_index; ruleset->ht_key.ops = ops; @@ -222,13 +223,13 @@ static void mlxsw_sp_acl_ruleset_destroy(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_acl_ruleset_ref_inc(struct mlxsw_sp_acl_ruleset *ruleset) { - ruleset->ref_count++; + refcount_inc(&ruleset->ref_count); } static void mlxsw_sp_acl_ruleset_ref_dec(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ruleset *ruleset) { - if (--ruleset->ref_count) + if (!refcount_dec_and_test(&ruleset->ref_count)) return; mlxsw_sp_acl_ruleset_destroy(mlxsw_sp, ruleset); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 50ea1eff02..92a406f02e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -9,6 +9,8 @@ #include <linux/rhashtable.h> #include <linux/netdevice.h> #include <linux/mutex.h> +#include <linux/refcount.h> +#include <linux/idr.h> #include <net/devlink.h> #include <trace/events/mlxsw.h> @@ -57,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam, u16 *p_id) { - u16 id; + int id; - id = find_first_zero_bit(tcam->used_regions, tcam->max_regions); - if (id < tcam->max_regions) { - __set_bit(id, tcam->used_regions); - *p_id = id; - return 0; - } - return -ENOBUFS; + id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1, + GFP_KERNEL); + if (id < 0) + return id; + + *p_id = id; + + return 0; } static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam, u16 id) { - __clear_bit(id, tcam->used_regions); + ida_free(&tcam->used_regions, id); } static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam, u16 *p_id) { - u16 id; + int id; - id = find_first_zero_bit(tcam->used_groups, tcam->max_groups); - if (id < tcam->max_groups) { - __set_bit(id, tcam->used_groups); - *p_id = id; - return 0; - } - return -ENOBUFS; + id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1, + GFP_KERNEL); + if (id < 0) + return id; + + *p_id = id; + + return 0; } static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam, u16 id) { - __clear_bit(id, tcam->used_groups); + ida_free(&tcam->used_groups, id); } struct mlxsw_sp_acl_tcam_pattern { @@ -155,7 +159,7 @@ struct mlxsw_sp_acl_tcam_vregion { struct mlxsw_sp_acl_tcam_rehash_ctx ctx; } rehash; struct mlxsw_sp *mlxsw_sp; - unsigned int ref_count; + refcount_t ref_count; }; struct mlxsw_sp_acl_tcam_vchunk; @@ -176,7 +180,7 @@ struct mlxsw_sp_acl_tcam_vchunk { unsigned int priority; /* Priority within the vregion and group */ struct mlxsw_sp_acl_tcam_vgroup *vgroup; struct mlxsw_sp_acl_tcam_vregion *vregion; - unsigned int ref_count; + refcount_t ref_count; }; struct mlxsw_sp_acl_tcam_entry { @@ -714,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) rehash.dw.work); int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS; + mutex_lock(&vregion->lock); mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits); + mutex_unlock(&vregion->lock); if (credits < 0) /* Rehash gone out of credits so it was interrupted. * Schedule the work as soon as possible to continue. @@ -725,6 +731,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) } static void +mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +{ + /* The entry markers are relative to the current chunk and therefore + * needs to be reset together with the chunk marker. + */ + ctx->current_vchunk = NULL; + ctx->start_ventry = NULL; + ctx->stop_ventry = NULL; +} + +static void mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk) { struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; @@ -746,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v * the current chunk pointer to make sure all chunks * are properly migrated. */ - vregion->rehash.ctx.current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx); } static struct mlxsw_sp_acl_tcam_vregion * @@ -769,7 +786,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, vregion->tcam = tcam; vregion->mlxsw_sp = mlxsw_sp; vregion->vgroup = vgroup; - vregion->ref_count = 1; + refcount_set(&vregion->ref_count, 1); vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); if (IS_ERR(vregion->key_info)) { @@ -819,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam = vregion->tcam; if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; + mutex_lock(&tcam->lock); list_del(&vregion->tlist); mutex_unlock(&tcam->lock); - cancel_delayed_work_sync(&vregion->rehash.dw); + if (cancel_delayed_work_sync(&vregion->rehash.dw) && + ctx->hints_priv) + ops->region_rehash_hints_put(ctx->hints_priv); } mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); if (vregion->region2) @@ -856,7 +877,7 @@ mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp, */ return ERR_PTR(-EOPNOTSUPP); } - vregion->ref_count++; + refcount_inc(&vregion->ref_count); return vregion; } @@ -871,7 +892,7 @@ static void mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion) { - if (--vregion->ref_count) + if (!refcount_dec_and_test(&vregion->ref_count)) return; mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); } @@ -924,7 +945,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, INIT_LIST_HEAD(&vchunk->ventry_list); vchunk->priority = priority; vchunk->vgroup = vgroup; - vchunk->ref_count = 1; + refcount_set(&vchunk->ref_count, 1); vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup, priority, elusage); @@ -1008,7 +1029,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp, if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info, elusage))) return ERR_PTR(-EINVAL); - vchunk->ref_count++; + refcount_inc(&vchunk->ref_count); return vchunk; } return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup, @@ -1019,7 +1040,7 @@ static void mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk) { - if (--vchunk->ref_count) + if (!refcount_dec_and_test(&vchunk->ref_count)) return; mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk); } @@ -1153,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, bool *activity) { - return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, - ventry->entry, activity); + struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion; + int err; + + mutex_lock(&vregion->lock); + err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry, + activity); + mutex_unlock(&vregion->lock); + return err; } static int @@ -1188,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_chunk *new_chunk; + WARN_ON(vchunk->chunk2); + new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); if (IS_ERR(new_chunk)) return PTR_ERR(new_chunk); @@ -1206,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp, { mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); vchunk->chunk2 = NULL; - ctx->current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); } static int @@ -1229,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, return 0; } + if (list_empty(&vchunk->ventry_list)) + goto out; + /* If the migration got interrupted, we have the ventry to start from * stored in context. */ @@ -1238,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, ventry = list_first_entry(&vchunk->ventry_list, typeof(*ventry), list); + WARN_ON(ventry->vchunk != vchunk); + list_for_each_entry_from(ventry, &vchunk->ventry_list, list) { /* During rollback, once we reach the ventry that failed * to migrate, we are done. @@ -1278,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, } } +out: mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx); return 0; } @@ -1291,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; + if (list_empty(&vregion->vchunk_list)) + return 0; + /* If the migration got interrupted, we have the vchunk * we are working on stored in context. */ @@ -1319,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, int err, err2; trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); - mutex_lock(&vregion->lock); err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); if (err) { + if (ctx->this_is_rollback) + return err; /* In case migration was not successful, we need to swap * so the original region pointer is assigned again * to vregion->region. */ swap(vregion->region, vregion->region2); - ctx->current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); ctx->this_is_rollback = true; err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); @@ -1339,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, /* Let the rollback to be continued later on. */ } } - mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); return err; } @@ -1388,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, ctx->hints_priv = hints_priv; ctx->this_is_rollback = false; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); return 0; @@ -1440,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx, credits); if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); + return; } if (*credits >= 0) @@ -1548,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, if (max_tcam_regions < max_regions) max_regions = max_tcam_regions; - tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL); - if (!tcam->used_regions) { - err = -ENOMEM; - goto err_alloc_used_regions; - } + ida_init(&tcam->used_regions); tcam->max_regions = max_regions; max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS); - tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL); - if (!tcam->used_groups) { - err = -ENOMEM; - goto err_alloc_used_groups; - } + ida_init(&tcam->used_groups); tcam->max_groups = max_groups; tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUP_SIZE); @@ -1574,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, return 0; err_tcam_init: - bitmap_free(tcam->used_groups); -err_alloc_used_groups: - bitmap_free(tcam->used_regions); -err_alloc_used_regions: + ida_destroy(&tcam->used_groups); + ida_destroy(&tcam->used_regions); mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp); err_rehash_params_register: mutex_destroy(&tcam->lock); @@ -1590,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; ops->fini(mlxsw_sp, tcam->priv); - bitmap_free(tcam->used_groups); - bitmap_free(tcam->used_regions); + ida_destroy(&tcam->used_groups); + ida_destroy(&tcam->used_regions); mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp); mutex_destroy(&tcam->lock); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 462bf44849..79a1d86065 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -6,15 +6,16 @@ #include <linux/list.h> #include <linux/parman.h> +#include <linux/idr.h> #include "reg.h" #include "spectrum.h" #include "core_acl_flex_keys.h" struct mlxsw_sp_acl_tcam { - unsigned long *used_regions; /* bit array */ + struct ida used_regions; unsigned int max_regions; - unsigned long *used_groups; /* bit array */ + struct ida used_groups; unsigned int max_groups; unsigned int max_group_size; struct mutex lock; /* guards vregion list */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index e954b8cd2e..65562ab208 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -11,6 +11,7 @@ #include <linux/refcount.h> #include "spectrum.h" +#include "spectrum_router.h" #include "reg.h" struct mlxsw_sp_fid_family; @@ -71,12 +72,12 @@ static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = { struct mlxsw_sp_flood_table { enum mlxsw_sp_flood_type packet_type; - enum mlxsw_flood_table_type table_type; + enum mlxsw_flood_table_type table_type; /* For flood_mode!=CFF. */ int table_index; }; struct mlxsw_sp_fid_ops { - void (*setup)(struct mlxsw_sp_fid *fid, const void *arg); + int (*setup)(struct mlxsw_sp_fid *fid, const void *arg); int (*configure)(struct mlxsw_sp_fid *fid); void (*deconfigure)(struct mlxsw_sp_fid *fid); int (*index_alloc)(struct mlxsw_sp_fid *fid, const void *arg, @@ -95,6 +96,34 @@ struct mlxsw_sp_fid_ops { const struct net_device *nve_dev); int (*vid_to_fid_rif_update)(const struct mlxsw_sp_fid *fid, const struct mlxsw_sp_rif *rif); + int (*flood_table_init)(struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_flood_table *flood_table); + int (*pgt_size)(const struct mlxsw_sp_fid_family *fid_family, + u16 *p_pgt_size); + u16 (*fid_mid)(const struct mlxsw_sp_fid *fid, + const struct mlxsw_sp_flood_table *flood_table); + void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid, + enum mlxsw_reg_sfmr_op op); + + /* These are specific to RFID families and we assume are only + * implemented by RFID families, if at all. + */ + int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_port *mlxsw_sp_port); + void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_port *mlxsw_sp_port); +}; + +enum mlxsw_sp_fid_flood_profile_id { + MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1, + MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, + MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, +}; + +struct mlxsw_sp_fid_flood_profile { + const struct mlxsw_sp_flood_table *flood_tables; + int nr_flood_tables; + const enum mlxsw_sp_fid_flood_profile_id profile_id; /* For CFF mode. */ }; struct mlxsw_sp_fid_family { @@ -104,12 +133,11 @@ struct mlxsw_sp_fid_family { u16 end_index; struct list_head fids_list; unsigned long *fids_bitmap; - const struct mlxsw_sp_flood_table *flood_tables; - int nr_flood_tables; + const struct mlxsw_sp_fid_flood_profile *flood_profile; enum mlxsw_sp_rif_type rif_type; const struct mlxsw_sp_fid_ops *ops; struct mlxsw_sp *mlxsw_sp; - bool flood_rsp; + bool flood_rsp; /* For flood_mode!=CFF. */ enum mlxsw_reg_bridge_type bridge_type; u16 pgt_base; bool smpe_index_valid; @@ -131,10 +159,31 @@ static const int mlxsw_sp_sfgc_mc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, }; +static const int mlxsw_sp_sfgc_not_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { + [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, + [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, + [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, +}; + +static const int mlxsw_sp_sfgc_any_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = { + [MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST] = 1, + [MLXSW_REG_SFGC_TYPE_BROADCAST] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP] = 1, + [MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL] = 1, + [MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6] = 1, + [MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4] = 1, +}; + static const int *mlxsw_sp_packet_type_sfgc_types[] = { [MLXSW_SP_FLOOD_TYPE_UC] = mlxsw_sp_sfgc_uc_packet_types, [MLXSW_SP_FLOOD_TYPE_BC] = mlxsw_sp_sfgc_bc_packet_types, [MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types, + [MLXSW_SP_FLOOD_TYPE_NOT_UC] = mlxsw_sp_sfgc_not_uc_packet_types, + [MLXSW_SP_FLOOD_TYPE_ANY] = mlxsw_sp_sfgc_any_packet_types, }; struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp, @@ -305,10 +354,13 @@ mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid, struct mlxsw_sp_fid_family *fid_family = fid->fid_family; int i; - for (i = 0; i < fid_family->nr_flood_tables; i++) { - if (fid_family->flood_tables[i].packet_type != packet_type) + for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { + const struct mlxsw_sp_flood_table *flood_table; + + flood_table = &fid_family->flood_profile->flood_tables[i]; + if (flood_table->packet_type != packet_type) continue; - return &fid_family->flood_tables[i]; + return flood_table; } return NULL; @@ -320,24 +372,62 @@ mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family) return fid_family->end_index - fid_family->start_index + 1; } -static u16 -mlxsw_sp_fid_family_pgt_size(const struct mlxsw_sp_fid_family *fid_family) +static int +mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family, + u16 *p_pgt_size) { u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family); - return num_fids * fid_family->nr_flood_tables; + *p_pgt_size = num_fids * fid_family->flood_profile->nr_flood_tables; + return 0; +} + +static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port) +{ + /* Port 0 is the CPU port. Since we never create RIFs based off that + * port, we don't need to count it. + */ + return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1; +} + +static int +mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family, + u16 *p_pgt_size) +{ + struct mlxsw_core *core = fid_family->mlxsw_sp->core; + unsigned int max_ports; + u16 pgt_size; + u16 max_lags; + int err; + + max_ports = mlxsw_core_max_ports(core); + + err = mlxsw_core_max_lag(core, &max_lags); + if (err) + return err; + + pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) * + fid_family->flood_profile->nr_flood_tables; + *p_pgt_size = pgt_size; + return 0; } static u16 -mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family, - const struct mlxsw_sp_flood_table *flood_table, - u16 fid_offset) +mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_flood_table *flood_table) { u16 num_fids; num_fids = mlxsw_sp_fid_family_num_fids(fid_family); - return fid_family->pgt_base + num_fids * flood_table->table_index + - fid_offset; + return fid_family->pgt_base + num_fids * flood_table->table_index; +} + +static u16 +mlxsw_sp_fid_fid_mid_ctl(const struct mlxsw_sp_fid *fid, + const struct mlxsw_sp_flood_table *flood_table) +{ + return mlxsw_sp_fid_pgt_base_ctl(fid->fid_family, flood_table) + + fid->fid_offset; } int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, @@ -348,15 +438,14 @@ int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid, const struct mlxsw_sp_flood_table *flood_table; u16 mid_index; - if (WARN_ON(!fid_family->flood_tables)) + if (WARN_ON(!fid_family->flood_profile)) return -EINVAL; flood_table = mlxsw_sp_fid_flood_table_lookup(fid, packet_type); if (!flood_table) return -ESRCH; - mid_index = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, - fid->fid_offset); + mid_index = fid_family->ops->fid_mid(fid, flood_table); return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp, mid_index, fid->fid_index, local_port, member); } @@ -410,12 +499,13 @@ u16 mlxsw_sp_fid_8021q_vid(const struct mlxsw_sp_fid *fid) return mlxsw_sp_fid_8021q_fid(fid)->vid; } -static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) +static int mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg) { u16 vid = *(u16 *) arg; mlxsw_sp_fid_8021q_fid(fid)->vid = vid; fid->fid_offset = fid->fid_index - fid->fid_family->start_index; + return 0; } static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) @@ -424,18 +514,76 @@ static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid) MLXSW_REG_SFMR_OP_DESTROY_FID; } -static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) +static void mlxsw_sp_fid_pack(char *sfmr_pl, + const struct mlxsw_sp_fid *fid, + enum mlxsw_reg_sfmr_op op) { - struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; - char sfmr_pl[MLXSW_REG_SFMR_LEN]; u16 smpe; smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; - mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index, - fid->fid_offset, fid->fid_family->flood_rsp, - fid->fid_family->bridge_type, + mlxsw_reg_sfmr_pack(sfmr_pl, op, fid->fid_index, fid->fid_family->smpe_index_valid, smpe); +} + +static void mlxsw_sp_fid_pack_ctl(char *sfmr_pl, + const struct mlxsw_sp_fid *fid, + enum mlxsw_reg_sfmr_op op) +{ + mlxsw_sp_fid_pack(sfmr_pl, fid, op); + mlxsw_reg_sfmr_fid_offset_set(sfmr_pl, fid->fid_offset); + mlxsw_reg_sfmr_flood_rsp_set(sfmr_pl, fid->fid_family->flood_rsp); + mlxsw_reg_sfmr_flood_bridge_type_set(sfmr_pl, + fid->fid_family->bridge_type); +} + +static u16 +mlxsw_sp_fid_off_pgt_base_cff(const struct mlxsw_sp_fid_family *fid_family, + u16 fid_offset) +{ + return fid_family->pgt_base + + fid_offset * fid_family->flood_profile->nr_flood_tables; +} + +static u16 mlxsw_sp_fid_pgt_base_cff(const struct mlxsw_sp_fid *fid) +{ + return mlxsw_sp_fid_off_pgt_base_cff(fid->fid_family, fid->fid_offset); +} + +static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl, + const struct mlxsw_sp_fid *fid, + enum mlxsw_reg_sfmr_op op) +{ + struct mlxsw_sp_fid_family *fid_family = fid->fid_family; + u16 pgt_base = mlxsw_sp_fid_pgt_base_cff(fid); + + mlxsw_sp_fid_pack(sfmr_pl, fid, op); + mlxsw_reg_sfmr_cff_mid_base_set(sfmr_pl, pgt_base); + mlxsw_reg_sfmr_cff_prf_id_set(sfmr_pl, + fid_family->flood_profile->profile_id); + mlxsw_reg_sfmr_nve_flood_prf_id_set(sfmr_pl, + MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE); +} + +static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp, + u16 port_lag_id, bool is_lag) +{ + u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core); + + if (is_lag) + return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + + port_lag_id; + else + return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id); +} + +static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid) +{ + struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; + char sfmr_pl[MLXSW_REG_SFMR_LEN]; + + fid->fid_family->ops->fid_pack(sfmr_pl, fid, + mlxsw_sp_sfmr_op(valid)); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); } @@ -444,15 +592,10 @@ static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid, { struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; char sfmr_pl[MLXSW_REG_SFMR_LEN]; - u16 smpe; - smpe = fid->fid_family->smpe_index_valid ? fid->fid_index : 0; + fid->fid_family->ops->fid_pack(sfmr_pl, fid, + MLXSW_REG_SFMR_OP_CREATE_FID); - mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, - fid->fid_index, fid->fid_offset, - fid->fid_family->flood_rsp, - fid->fid_family->bridge_type, - fid->fid_family->smpe_index_valid, smpe); mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid); mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni)); mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid); @@ -768,12 +911,13 @@ mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) return container_of(fid, struct mlxsw_sp_fid_8021d, common); } -static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) +static int mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg) { int br_ifindex = *(int *) arg; mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex; fid->fid_offset = fid->fid_index - fid->fid_family->start_index; + return 0; } static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid) @@ -1058,7 +1202,37 @@ mlxsw_sp_fid_8021d_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, return 0; } -static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = { +static int +mlxsw_sp_fid_flood_table_init_ctl(struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_flood_table *flood_table) +{ + enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; + struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; + const int *sfgc_packet_types; + u16 mid_base; + int err, i; + + mid_base = mlxsw_sp_fid_pgt_base_ctl(fid_family, flood_table); + + sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; + for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { + char sfgc_pl[MLXSW_REG_SFGC_LEN]; + + if (!sfgc_packet_types[i]) + continue; + + mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, + flood_table->table_type, 0, mid_base); + + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); + if (err) + return err; + } + + return 0; +} + +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_ctl = { .setup = mlxsw_sp_fid_8021d_setup, .configure = mlxsw_sp_fid_8021d_configure, .deconfigure = mlxsw_sp_fid_8021d_deconfigure, @@ -1072,6 +1246,36 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = { .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, + .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, + .pgt_size = mlxsw_sp_fid_8021d_pgt_size, + .fid_mid = mlxsw_sp_fid_fid_mid_ctl, + .fid_pack = mlxsw_sp_fid_pack_ctl, +}; + +static u16 +mlxsw_sp_fid_fid_mid_cff(const struct mlxsw_sp_fid *fid, + const struct mlxsw_sp_flood_table *flood_table) +{ + return mlxsw_sp_fid_pgt_base_cff(fid) + flood_table->table_index; +} + +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops_cff = { + .setup = mlxsw_sp_fid_8021d_setup, + .configure = mlxsw_sp_fid_8021d_configure, + .deconfigure = mlxsw_sp_fid_8021d_deconfigure, + .index_alloc = mlxsw_sp_fid_8021d_index_alloc, + .compare = mlxsw_sp_fid_8021d_compare, + .port_vid_map = mlxsw_sp_fid_8021d_port_vid_map, + .port_vid_unmap = mlxsw_sp_fid_8021d_port_vid_unmap, + .vni_set = mlxsw_sp_fid_8021d_vni_set, + .vni_clear = mlxsw_sp_fid_8021d_vni_clear, + .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, + .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, + .fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload, + .vid_to_fid_rif_update = mlxsw_sp_fid_8021d_vid_to_fid_rif_update, + .pgt_size = mlxsw_sp_fid_8021d_pgt_size, + .fid_mid = mlxsw_sp_fid_fid_mid_cff, + .fid_pack = mlxsw_sp_fid_fid_pack_cff, }; #define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2) @@ -1095,6 +1299,45 @@ static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = { }, }; +static const +struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = { + .flood_tables = mlxsw_sp_fid_8021d_flood_tables, + .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), + .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE, +}; + +static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = { + { + .packet_type = MLXSW_SP_FLOOD_TYPE_UC, + .table_index = 0, + }, + { + .packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC, + .table_index = 1, + }, +}; + +static const +struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = { + .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff, + .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff), + .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP, +}; + +static const struct mlxsw_sp_flood_table mlxsw_sp_fid_nve_flood_tables_cff[] = { + { + .packet_type = MLXSW_SP_FLOOD_TYPE_ANY, + .table_index = 0, + }, +}; + +static const +struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_nve_flood_profile_cff = { + .flood_tables = mlxsw_sp_fid_nve_flood_tables_cff, + .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_nve_flood_tables_cff), + .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_NVE, +}; + static bool mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) { @@ -1110,9 +1353,35 @@ mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid)); } -static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg) +static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid, + const void *arg) { + /* In controlled mode, the FW takes care of FID placement. */ fid->fid_offset = 0; + return 0; +} + +static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid, + const void *arg) +{ + struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; + u16 rif_index = *(const u16 *)arg; + struct mlxsw_sp_rif *rif; + bool is_lag; + u16 port; + int err; + + rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index); + if (!rif) + return -ENOENT; + + err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag); + if (err) + return err; + + fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, + is_lag); + return 0; } static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid) @@ -1238,8 +1507,8 @@ mlxsw_sp_fid_rfid_vid_to_fid_rif_update(const struct mlxsw_sp_fid *fid, return 0; } -static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = { - .setup = mlxsw_sp_fid_rfid_setup, +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = { + .setup = mlxsw_sp_fid_rfid_setup_ctl, .configure = mlxsw_sp_fid_rfid_configure, .deconfigure = mlxsw_sp_fid_rfid_deconfigure, .index_alloc = mlxsw_sp_fid_rfid_index_alloc, @@ -1251,11 +1520,146 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = { .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, + .fid_pack = mlxsw_sp_fid_pack_ctl, +}; + +static int +mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_flood_table *flood_table, + u16 pgt_addr, u16 smpe, unsigned int local_port) +{ + int err; + + err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, + local_port, true); + if (err) + return err; + + if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { + u16 router_port = mlxsw_sp_router_port(mlxsw_sp); + + err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, + router_port, true); + if (err) + goto err_entry_port_set; + } + + return 0; + +err_entry_port_set: + mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, + false); + return err; +} + +static void +mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_flood_table *flood_table, + u16 pgt_addr, u16 smpe, u16 local_port) +{ + if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) { + u16 router_port = mlxsw_sp_router_port(mlxsw_sp); + + mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, + router_port, false); + } + mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port, + false); +} + +static int +mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_flood_table *flood_table, + const struct mlxsw_sp_port *mlxsw_sp_port, + bool member) +{ + struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; + u16 local_port = mlxsw_sp_port->local_port; + u16 fid_pgt_base; + u16 fid_offset; + u16 pgt_addr; + u16 smpe; + u16 port; + + /* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */ + smpe = 0; + + port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port; + fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port, + mlxsw_sp_port->lagged); + fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset); + pgt_addr = fid_pgt_base + flood_table->table_index; + + if (member) + return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table, + pgt_addr, smpe, + local_port); + + mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe, + local_port); + return 0; +} + +static int +mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_port *mlxsw_sp_port, + bool member) +{ + int i; + + for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { + const struct mlxsw_sp_flood_table *flood_table = + &fid_family->flood_profile->flood_tables[i]; + int err; + + err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family, + flood_table, + mlxsw_sp_port, member); + if (err) + return err; + } + + return 0; +} + +static int +mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_port *mlxsw_sp_port) +{ + return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true); +} + +static void +mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family, + const struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false); +} + +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = { + .setup = mlxsw_sp_fid_rfid_setup_cff, + .configure = mlxsw_sp_fid_rfid_configure, + .deconfigure = mlxsw_sp_fid_rfid_deconfigure, + .index_alloc = mlxsw_sp_fid_rfid_index_alloc, + .compare = mlxsw_sp_fid_rfid_compare, + .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map, + .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap, + .vni_set = mlxsw_sp_fid_rfid_vni_set, + .vni_clear = mlxsw_sp_fid_rfid_vni_clear, + .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set, + .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear, + .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update, + .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff, + .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff, + .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff, + .fid_mid = mlxsw_sp_fid_fid_mid_cff, + .fid_pack = mlxsw_sp_fid_fid_pack_cff, }; -static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) +static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg) { fid->fid_offset = 0; + return 0; } static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid) @@ -1312,6 +1716,7 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = { .vni_clear = mlxsw_sp_fid_dummy_vni_clear, .nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set, .nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear, + .fid_pack = mlxsw_sp_fid_pack, }; static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) @@ -1395,7 +1800,7 @@ mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, __mlxsw_sp_fid_port_vid_map(fid, local_port, vid, false); } -static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = { +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_ctl = { .setup = mlxsw_sp_fid_8021q_setup, .configure = mlxsw_sp_fid_8021q_configure, .deconfigure = mlxsw_sp_fid_8021q_deconfigure, @@ -1409,6 +1814,29 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = { .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, + .flood_table_init = mlxsw_sp_fid_flood_table_init_ctl, + .pgt_size = mlxsw_sp_fid_8021d_pgt_size, + .fid_mid = mlxsw_sp_fid_fid_mid_ctl, + .fid_pack = mlxsw_sp_fid_pack_ctl, +}; + +static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops_cff = { + .setup = mlxsw_sp_fid_8021q_setup, + .configure = mlxsw_sp_fid_8021q_configure, + .deconfigure = mlxsw_sp_fid_8021q_deconfigure, + .index_alloc = mlxsw_sp_fid_8021d_index_alloc, + .compare = mlxsw_sp_fid_8021q_compare, + .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, + .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, + .vni_set = mlxsw_sp_fid_8021d_vni_set, + .vni_clear = mlxsw_sp_fid_8021d_vni_clear, + .nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set, + .nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear, + .fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload, + .vid_to_fid_rif_update = mlxsw_sp_fid_8021q_vid_to_fid_rif_update, + .pgt_size = mlxsw_sp_fid_8021d_pgt_size, + .fid_mid = mlxsw_sp_fid_fid_mid_cff, + .fid_pack = mlxsw_sp_fid_fid_pack_cff, }; /* There are 4K-2 802.1Q FIDs */ @@ -1434,10 +1862,9 @@ static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = { .fid_size = sizeof(struct mlxsw_sp_fid_8021q), .start_index = MLXSW_SP_FID_8021Q_START, .end_index = MLXSW_SP_FID_8021Q_END, - .flood_tables = mlxsw_sp_fid_8021d_flood_tables, - .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, .rif_type = MLXSW_SP_RIF_TYPE_VLAN, - .ops = &mlxsw_sp_fid_8021q_ops, + .ops = &mlxsw_sp_fid_8021q_ops_ctl, .flood_rsp = false, .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, .smpe_index_valid = false, @@ -1448,10 +1875,9 @@ static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = { .fid_size = sizeof(struct mlxsw_sp_fid_8021d), .start_index = MLXSW_SP_FID_8021D_START, .end_index = MLXSW_SP_FID_8021D_END, - .flood_tables = mlxsw_sp_fid_8021d_flood_tables, - .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, .rif_type = MLXSW_SP_RIF_TYPE_FID, - .ops = &mlxsw_sp_fid_8021d_ops, + .ops = &mlxsw_sp_fid_8021d_ops_ctl, .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, .smpe_index_valid = false, }; @@ -1465,47 +1891,45 @@ static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_dummy_family = { .smpe_index_valid = false, }; -static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = { +static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_ctl = { .type = MLXSW_SP_FID_TYPE_RFID, .fid_size = sizeof(struct mlxsw_sp_fid), .start_index = MLXSW_SP_RFID_START, .end_index = MLXSW_SP_RFID_END, .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, - .ops = &mlxsw_sp_fid_rfid_ops, + .ops = &mlxsw_sp_fid_rfid_ops_ctl, .flood_rsp = true, .smpe_index_valid = false, }; -const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { +static const struct mlxsw_sp_fid_family *mlxsw_sp1_fid_family_arr[] = { [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp1_fid_8021q_family, [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp1_fid_8021d_family, [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp1_fid_dummy_family, - [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, + [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, }; -static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = { +static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_ctl = { .type = MLXSW_SP_FID_TYPE_8021Q, .fid_size = sizeof(struct mlxsw_sp_fid_8021q), .start_index = MLXSW_SP_FID_8021Q_START, .end_index = MLXSW_SP_FID_8021Q_END, - .flood_tables = mlxsw_sp_fid_8021d_flood_tables, - .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, .rif_type = MLXSW_SP_RIF_TYPE_VLAN, - .ops = &mlxsw_sp_fid_8021q_ops, + .ops = &mlxsw_sp_fid_8021q_ops_ctl, .flood_rsp = false, .bridge_type = MLXSW_REG_BRIDGE_TYPE_0, .smpe_index_valid = true, }; -static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = { +static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_ctl = { .type = MLXSW_SP_FID_TYPE_8021D, .fid_size = sizeof(struct mlxsw_sp_fid_8021d), .start_index = MLXSW_SP_FID_8021D_START, .end_index = MLXSW_SP_FID_8021D_END, - .flood_tables = mlxsw_sp_fid_8021d_flood_tables, - .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables), + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, .rif_type = MLXSW_SP_RIF_TYPE_FID, - .ops = &mlxsw_sp_fid_8021d_ops, + .ops = &mlxsw_sp_fid_8021d_ops_ctl, .bridge_type = MLXSW_REG_BRIDGE_TYPE_1, .smpe_index_valid = true, }; @@ -1519,11 +1943,51 @@ static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_dummy_family = { .smpe_index_valid = false, }; -const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr[] = { - [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family, - [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family, +static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_ctl[] = { + [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_ctl, + [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_ctl, [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, - [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family, + [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_ctl, +}; + +static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family_cff = { + .type = MLXSW_SP_FID_TYPE_8021Q, + .fid_size = sizeof(struct mlxsw_sp_fid_8021q), + .start_index = MLXSW_SP_FID_8021Q_START, + .end_index = MLXSW_SP_FID_8021Q_END, + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, + .rif_type = MLXSW_SP_RIF_TYPE_VLAN, + .ops = &mlxsw_sp_fid_8021q_ops_cff, + .smpe_index_valid = true, +}; + +static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = { + .type = MLXSW_SP_FID_TYPE_8021D, + .fid_size = sizeof(struct mlxsw_sp_fid_8021d), + .start_index = MLXSW_SP_FID_8021D_START, + .end_index = MLXSW_SP_FID_8021D_END, + .flood_profile = &mlxsw_sp_fid_8021d_flood_profile, + .rif_type = MLXSW_SP_RIF_TYPE_FID, + .ops = &mlxsw_sp_fid_8021d_ops_cff, + .smpe_index_valid = true, +}; + +static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = { + .type = MLXSW_SP_FID_TYPE_RFID, + .fid_size = sizeof(struct mlxsw_sp_fid), + .start_index = MLXSW_SP_RFID_START, + .end_index = MLXSW_SP_RFID_END, + .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff, + .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT, + .ops = &mlxsw_sp_fid_rfid_ops_cff, + .smpe_index_valid = false, +}; + +static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = { + [MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff, + [MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff, + [MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family, + [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff, }; static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp, @@ -1571,7 +2035,9 @@ static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, fid->fid_index = fid_index; __set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); - fid->fid_family->ops->setup(fid, arg); + err = fid->fid_family->ops->setup(fid, arg); + if (err) + goto err_setup; err = fid->fid_family->ops->configure(fid); if (err) @@ -1589,6 +2055,7 @@ static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp, err_rhashtable_insert: fid->fid_family->ops->deconfigure(fid); err_configure: +err_setup: __clear_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap); err_index_alloc: @@ -1650,36 +2117,6 @@ struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp) } static int -mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family, - const struct mlxsw_sp_flood_table *flood_table) -{ - enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; - struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; - const int *sfgc_packet_types; - u16 mid_base; - int err, i; - - mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0); - - sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; - for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { - char sfgc_pl[MLXSW_REG_SFGC_LEN]; - - if (!sfgc_packet_types[i]) - continue; - - mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type, - flood_table->table_type, 0, mid_base); - - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl); - if (err) - return err; - } - - return 0; -} - -static int mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) { struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; @@ -1687,22 +2124,28 @@ mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family) int err; int i; - if (!fid_family->nr_flood_tables) - return 0; + err = fid_family->ops->pgt_size(fid_family, &pgt_size); + if (err) + return err; - pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family); err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base, pgt_size); if (err) return err; - for (i = 0; i < fid_family->nr_flood_tables; i++) { + if (!fid_family->flood_profile) + return 0; + + for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) { const struct mlxsw_sp_flood_table *flood_table; - flood_table = &fid_family->flood_tables[i]; - err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table); - if (err) - goto err_flood_table_init; + flood_table = &fid_family->flood_profile->flood_tables[i]; + if (fid_family->ops->flood_table_init) { + err = fid_family->ops->flood_table_init(fid_family, + flood_table); + if (err) + goto err_flood_table_init; + } } return 0; @@ -1717,11 +2160,12 @@ mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family) { struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp; u16 pgt_size; + int err; - if (!fid_family->nr_flood_tables) + err = fid_family->ops->pgt_size(fid_family, &pgt_size); + if (WARN_ON_ONCE(err)) return; - pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family); mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size); } @@ -1744,7 +2188,7 @@ static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, goto err_alloc_fids_bitmap; } - if (fid_family->flood_tables) { + if (fid_family->flood_profile) { err = mlxsw_sp_fid_flood_tables_init(fid_family); if (err) goto err_fid_flood_tables_init; @@ -1767,7 +2211,7 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, { mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; - if (fid_family->flood_tables) + if (fid_family->flood_profile) mlxsw_sp_fid_flood_tables_fini(fid_family); bitmap_free(fid_family->fids_bitmap); @@ -1775,9 +2219,34 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, kfree(fid_family); } +static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_fid_family *rfid_family; + + rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; + if (rfid_family->ops->fid_port_init) + return rfid_family->ops->fid_port_init(rfid_family, + mlxsw_sp_port); + return 0; +} + +static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID; + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_fid_family *rfid_family; + + rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid]; + if (rfid_family->ops->fid_port_fini) + rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port); +} + int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + int err; /* Track number of FIDs configured on the port with mapping type * PORT_VID_TO_FID, so that we know when to transition the port @@ -1785,17 +2254,42 @@ int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port) */ mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; - return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); + err = mlxsw_sp_fid_port_init(mlxsw_sp_port); + if (err) + return err; + + err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); + if (err) + goto err_vp_mode_set; + + return 0; + +err_vp_mode_set: + mlxsw_sp_fid_port_fini(mlxsw_sp_port); + return err; } void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + mlxsw_sp_fid_port_fini(mlxsw_sp_port); mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0; } -int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp) +int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + return mlxsw_sp_fid_port_init(mlxsw_sp_port); +} + +void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_fid_port_fini(mlxsw_sp_port); +} + +static int +mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_fid_family *fid_family_arr[]) { unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); struct mlxsw_sp_fid_core *fid_core; @@ -1822,8 +2316,7 @@ int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp) } for (i = 0; i < MLXSW_SP_FID_TYPE_MAX; i++) { - err = mlxsw_sp_fid_family_register(mlxsw_sp, - mlxsw_sp->fid_family_arr[i]); + err = mlxsw_sp_fid_family_register(mlxsw_sp, fid_family_arr[i]); if (err) goto err_fid_ops_register; @@ -1848,7 +2341,7 @@ err_rhashtable_fid_init: return err; } -void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) +static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) { struct mlxsw_sp_fid_core *fid_core = mlxsw_sp->fid_core; int i; @@ -1861,3 +2354,143 @@ void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) rhashtable_destroy(&fid_core->fid_ht); kfree(fid_core); } + +static int mlxsw_sp1_fids_init(struct mlxsw_sp *mlxsw_sp) +{ + return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp1_fid_family_arr); +} + +const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops = { + .init = mlxsw_sp1_fids_init, + .fini = mlxsw_sp_fids_fini, +}; + +static int mlxsw_sp_fid_check_flood_profile_id(struct mlxsw_sp *mlxsw_sp, + int profile_id) +{ + u32 max_profiles; + + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_NVE_FLOOD_PRF)) + return -EIO; + + max_profiles = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_NVE_FLOOD_PRF); + if (WARN_ON_ONCE(!profile_id) || + WARN_ON_ONCE(profile_id >= max_profiles)) + return -EINVAL; + + return 0; +} + +static int +mlxsw_sp2_fids_init_flood_table(struct mlxsw_sp *mlxsw_sp, + enum mlxsw_sp_fid_flood_profile_id profile_id, + const struct mlxsw_sp_flood_table *flood_table) +{ + enum mlxsw_sp_flood_type packet_type = flood_table->packet_type; + const int *sfgc_packet_types; + int err; + int i; + + sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type]; + for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) { + char sffp_pl[MLXSW_REG_SFFP_LEN]; + + if (!sfgc_packet_types[i]) + continue; + + mlxsw_reg_sffp_pack(sffp_pl, profile_id, i, + flood_table->table_index); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sffp), sffp_pl); + if (err) + return err; + } + + return 0; +} + +static int +mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_fid_flood_profile * + flood_profile) +{ + int err; + int i; + + err = mlxsw_sp_fid_check_flood_profile_id(mlxsw_sp, + flood_profile->profile_id); + if (err) + return err; + + for (i = 0; i < flood_profile->nr_flood_tables; i++) { + const struct mlxsw_sp_flood_table *flood_table; + + flood_table = &flood_profile->flood_tables[i]; + err = mlxsw_sp2_fids_init_flood_table(mlxsw_sp, + flood_profile->profile_id, + flood_table); + if (err) + return err; + } + + return 0; +} + +static const +struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = { + &mlxsw_sp_fid_8021d_flood_profile, + &mlxsw_sp_fid_rsp_flood_profile_cff, + &mlxsw_sp_fid_nve_flood_profile_cff, +}; + +static int +mlxsw_sp2_fids_init_flood_profiles(struct mlxsw_sp *mlxsw_sp) +{ + int err; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_fid_flood_profiles); i++) { + const struct mlxsw_sp_fid_flood_profile *flood_profile; + + flood_profile = mlxsw_sp_fid_flood_profiles[i]; + err = mlxsw_sp2_fids_init_flood_profile(mlxsw_sp, + flood_profile); + if (err) + return err; + } + + return 0; +} + +static int mlxsw_sp2_fids_init_ctl(struct mlxsw_sp *mlxsw_sp) +{ + return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_ctl); +} + +static int mlxsw_sp2_fids_init_cff(struct mlxsw_sp *mlxsw_sp) +{ + int err; + + err = mlxsw_sp2_fids_init_flood_profiles(mlxsw_sp); + if (err) + return err; + + return mlxsw_sp_fids_init(mlxsw_sp, mlxsw_sp2_fid_family_arr_cff); +} + +static int mlxsw_sp2_fids_init(struct mlxsw_sp *mlxsw_sp) +{ + switch (mlxsw_core_flood_mode(mlxsw_sp->core)) { + case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED: + return mlxsw_sp2_fids_init_ctl(mlxsw_sp); + case MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CFF: + return mlxsw_sp2_fids_init_cff(mlxsw_sp); + default: + WARN_ON_ONCE(1); + return -EINVAL; + } +} + +const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops = { + .init = mlxsw_sp2_fids_init, + .fini = mlxsw_sp_fids_fini, +}; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 39e6d941fd..87617df694 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -501,7 +501,7 @@ struct mlxsw_sp_rt6 { struct mlxsw_sp_lpm_tree { u8 id; /* tree ID */ - unsigned int ref_count; + refcount_t ref_count; enum mlxsw_sp_l3proto proto; unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT]; struct mlxsw_sp_prefix_usage prefix_usage; @@ -578,7 +578,7 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp) for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) { lpm_tree = &mlxsw_sp->router->lpm.trees[i]; - if (lpm_tree->ref_count == 0) + if (refcount_read(&lpm_tree->ref_count) == 0) return lpm_tree; } return NULL; @@ -654,7 +654,7 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, sizeof(lpm_tree->prefix_usage)); memset(&lpm_tree->prefix_ref_count, 0, sizeof(lpm_tree->prefix_ref_count)); - lpm_tree->ref_count = 1; + refcount_set(&lpm_tree->ref_count, 1); return lpm_tree; err_left_struct_set: @@ -678,7 +678,7 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) { lpm_tree = &mlxsw_sp->router->lpm.trees[i]; - if (lpm_tree->ref_count != 0 && + if (refcount_read(&lpm_tree->ref_count) && lpm_tree->proto == proto && mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage, prefix_usage)) { @@ -691,14 +691,15 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree) { - lpm_tree->ref_count++; + refcount_inc(&lpm_tree->ref_count); } static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_lpm_tree *lpm_tree) { - if (--lpm_tree->ref_count == 0) - mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree); + if (!refcount_dec_and_test(&lpm_tree->ref_count)) + return; + mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree); } #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */ @@ -8419,6 +8420,9 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, rif->ops = ops; rif->rif_entries = rif_entries; + if (ops->setup) + ops->setup(rif, params); + if (ops->fid_get) { fid = ops->fid_get(rif, params, extack); if (IS_ERR(fid)) { @@ -8428,9 +8432,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, rif->fid = fid; } - if (ops->setup) - ops->setup(rif, params); - err = ops->configure(rif, extack); if (err) goto err_configure; @@ -8660,6 +8661,20 @@ mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif) return container_of(rif, struct mlxsw_sp_rif_subport, common); } +int mlxsw_sp_rif_subport_port(const struct mlxsw_sp_rif *rif, + u16 *port, bool *is_lag) +{ + struct mlxsw_sp_rif_subport *rif_subport; + + if (WARN_ON(rif->ops->type != MLXSW_SP_RIF_TYPE_SUBPORT)) + return -EINVAL; + + rif_subport = mlxsw_sp_rif_subport_rif(rif); + *is_lag = rif_subport->lag; + *port = *is_lag ? rif_subport->lag_id : rif_subport->system_port; + return 0; +} + static struct mlxsw_sp_rif * mlxsw_sp_rif_subport_get(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_rif_params *params, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 6c749c1481..6397ff0dc9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -61,7 +61,7 @@ struct mlxsw_sp_bridge_port { struct mlxsw_sp_bridge_device *bridge_device; struct list_head list; struct list_head vlans_list; - unsigned int ref_count; + refcount_t ref_count; u8 stp_state; unsigned long flags; bool mrouter; @@ -495,7 +495,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device, BR_MCAST_FLOOD; INIT_LIST_HEAD(&bridge_port->vlans_list); list_add(&bridge_port->list, &bridge_device->ports_list); - bridge_port->ref_count = 1; + refcount_set(&bridge_port->ref_count, 1); err = switchdev_bridge_port_offload(brport_dev, mlxsw_sp_port->dev, NULL, NULL, NULL, false, extack); @@ -531,7 +531,7 @@ mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge, bridge_port = mlxsw_sp_bridge_port_find(bridge, brport_dev); if (bridge_port) { - bridge_port->ref_count++; + refcount_inc(&bridge_port->ref_count); return bridge_port; } @@ -558,7 +558,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge, { struct mlxsw_sp_bridge_device *bridge_device; - if (--bridge_port->ref_count != 0) + if (!refcount_dec_and_test(&bridge_port->ref_count)) return; bridge_device = bridge_port->bridge_device; mlxsw_sp_bridge_port_destroy(bridge_port); |