diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox')
53 files changed, 1630 insertions, 506 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 164a13272faa..619e1c3ef7f9 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 28d02749d3c4..7659ad21e6e5 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 2cd81bb32c66..18fed2b34fb1 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; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 729a11b5fb25..0bfe1ca8a364 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); @@ -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 254c84739046..40c8df111754 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 e1ac4b3d22fb..6beba7f075c1 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 e097f336e1c4..284253b79266 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 af3928eddafd..c206cc0a8483 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 7b700d0f956a..86f1854698b4 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; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c index 244bc15a42ab..34adf8c3f81a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c @@ -77,6 +77,7 @@ 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; @@ -123,11 +124,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 b12fe3c5a258..a55452c69f06 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/tc/act/pedit.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c index 368a95fa77d3..b14cd62edffc 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 5620d9f97518..ac458a8d10e0 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 13c7ed1bb37e..82b5ca1be4f3 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 ecfe93a479da..e054db1e10f8 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 36826b582484..82e6abbc1734 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 597f319d4770..a59199ed590d 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_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c index 41c396e76457..67f546683e85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c @@ -74,6 +74,72 @@ int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey) return err; } +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 < MLX5_MAX_PORTS; 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 < MLX5_MAX_PORTS; 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) { struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs; @@ -103,6 +169,11 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) goto err_destroy_mkey; } + err = mlx5e_create_tises(mdev, res->tisn); + if (err) { + mlx5_core_err(mdev, "alloc tises failed, %d\n", err); + goto err_destroy_bfreg; + } INIT_LIST_HEAD(&res->td.tirs_list); mutex_init(&res->td.list_lock); @@ -115,6 +186,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 +203,7 @@ 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; + 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 c7c1b667b105..cc51ce16df14 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1262,27 +1262,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 +1297,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 +1306,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 +2382,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 +2405,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 0c87ddb8a7a2..b5f1c4ca38ba 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) | @@ -6069,7 +6005,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 +6023,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 +6089,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 +6101,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 e92d4f83592e..05527418fa64 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 8d9743a5e42c..d601b5faaed5 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 477c547dcc04..12b3607afecd 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 96af9e2ab1d8..30932c9c9a8f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3209,10 +3209,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; @@ -5030,22 +5030,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 adb39e30f90f..c24bda56b2b5 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 f0b506e562df..5c166d9d2dca 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -861,7 +861,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/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index a4b925331661..1616a6144f7b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -1144,3 +1144,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 7790ae5531e1..53e0e5137d3f 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.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 4aed1768b85f..78eb6b7097e1 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 17fe30a4c06c..0c26d707eed2 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 c4e19d627da2..f27eab6e4929 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 2bf77a5251b4..58845121954c 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 */ @@ -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 f3f2af972020..2ab6437a1c49 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 03e681297937..f87471306f6b 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/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 0c83ef174275..0361741632a6 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 e8e50563e956..e7d59cfa8708 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 fc23bbef87b4..ec32b686f586 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/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a17152c1cbb2..bccf6e53556c 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, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 6b14e347d914..a79b7959361b 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/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 7d8c732818f2..7fba1c46e2ac 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/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index e3ec559369fa..6f9790e97fed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -1170,7 +1170,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; @@ -1249,11 +1248,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/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index 954ba0826c61..3d09fa54598f 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -130,9 +130,15 @@ static int mlxbf_gige_open(struct net_device *netdev) { struct mlxbf_gige *priv = netdev_priv(netdev); struct phy_device *phydev = netdev->phydev; + u64 control; u64 int_en; int err; + /* Perform general init of GigE block */ + control = readq(priv->base + MLXBF_GIGE_CONTROL); + control |= MLXBF_GIGE_CONTROL_PORT_EN; + writeq(control, priv->base + MLXBF_GIGE_CONTROL); + err = mlxbf_gige_request_irqs(priv); if (err) return err; @@ -147,14 +153,14 @@ static int mlxbf_gige_open(struct net_device *netdev) */ priv->valid_polarity = 0; - err = mlxbf_gige_rx_init(priv); + phy_start(phydev); + + err = mlxbf_gige_tx_init(priv); if (err) goto free_irqs; - err = mlxbf_gige_tx_init(priv); + err = mlxbf_gige_rx_init(priv); if (err) - goto rx_deinit; - - phy_start(phydev); + goto tx_deinit; netif_napi_add(netdev, &priv->napi, mlxbf_gige_poll); napi_enable(&priv->napi); @@ -176,8 +182,8 @@ static int mlxbf_gige_open(struct net_device *netdev) return 0; -rx_deinit: - mlxbf_gige_rx_deinit(priv); +tx_deinit: + mlxbf_gige_tx_deinit(priv); free_irqs: mlxbf_gige_free_irqs(priv); @@ -365,7 +371,6 @@ static int mlxbf_gige_probe(struct platform_device *pdev) void __iomem *plu_base; void __iomem *base; int addr, phy_irq; - u64 control; int err; base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MAC); @@ -380,11 +385,6 @@ static int mlxbf_gige_probe(struct platform_device *pdev) if (IS_ERR(plu_base)) return PTR_ERR(plu_base); - /* Perform general init of GigE block */ - control = readq(base + MLXBF_GIGE_CONTROL); - control |= MLXBF_GIGE_CONTROL_PORT_EN; - writeq(control, base + MLXBF_GIGE_CONTROL); - netdev = devm_alloc_etherdev(&pdev->dev, sizeof(*priv)); if (!netdev) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c index 227d01cace3f..699984358493 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c @@ -142,6 +142,9 @@ int mlxbf_gige_rx_init(struct mlxbf_gige *priv) writeq(MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS_EN, priv->base + MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS); + writeq(ilog2(priv->rx_q_entries), + priv->base + MLXBF_GIGE_RX_WQE_SIZE_LOG2); + /* Clear MLXBF_GIGE_INT_MASK 'receive pkt' bit to * indicate readiness to receive interrupts */ @@ -154,9 +157,6 @@ int mlxbf_gige_rx_init(struct mlxbf_gige *priv) data |= MLXBF_GIGE_RX_DMA_EN; writeq(data, priv->base + MLXBF_GIGE_RX_DMA); - writeq(ilog2(priv->rx_q_entries), - priv->base + MLXBF_GIGE_RX_WQE_SIZE_LOG2); - return 0; free_wqe_and_skb: diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index e827c78be114..e3271c845ee6 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 f23421f038f3..e4d7739bd7c8 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; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 764d14bd5bc0..6d11225594dd 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/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index e4b25e187467..af99bf17eb36 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; u32 sys_status; int err; @@ -1491,8 +1541,26 @@ 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) + return 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 +1605,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 +1669,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 +1743,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 +1988,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 +2008,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 +2139,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 25b294fdeb3d..8892654c685f 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 89dd2777ec4d..9d7977ebe186 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 cec72d99d9c9..5d3413636a62 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 c70333b460ea..a0c9775fa955 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_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index e954b8cd2ee8..65562ab208b3 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 82a95125d9ca..2c255ed9b8a9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -8419,6 +8419,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 +8431,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 +8660,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, |