This commit extends mlx5e_safe_switch_channels() to support on-the-fly
configuration changes, when the channels are open, but don't need to be
recreated. Such flows exist when a parameter being changed doesn't
affect how the queues are created, or when the queues can be modified
while remaining active.
Before this commit, such flows were handled as special cases on the
caller site. This commit adds this functionality to
mlx5e_safe_switch_channels(), allowing the caller to pass a boolean
indicating whether it's required to recreate the channels or it's
allowed to skip it. The logic of switching channel parameters is now
completely encapsulated into mlx5e_safe_switch_channels().
Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
+ void *context, bool reset);
int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv);
int mlx5e_num_channels_changed(struct mlx5e_priv *priv);
int mlx5e_num_channels_changed_ctx(struct mlx5e_priv *priv, void *context);
int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv);
int mlx5e_num_channels_changed(struct mlx5e_priv *priv);
int mlx5e_num_channels_changed_ctx(struct mlx5e_priv *priv, void *context);
static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
{
struct mlx5e_channels new_channels = {};
static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
{
struct mlx5e_channels new_channels = {};
+ bool reset = true;
+ int err;
mutex_lock(&priv->state_lock);
mutex_lock(&priv->state_lock);
/* Skip if tx_min_inline is the same */
if (new_channels.params.tx_min_inline_mode ==
/* Skip if tx_min_inline is the same */
if (new_channels.params.tx_min_inline_mode ==
- priv->channels.params.tx_min_inline_mode) {
- err = mlx5e_update_trust_state_hw(priv, &trust_state);
- goto out;
- }
+ priv->channels.params.tx_min_inline_mode)
+ reset = false;
err = mlx5e_safe_switch_channels(priv, &new_channels,
mlx5e_update_trust_state_hw,
err = mlx5e_safe_switch_channels(priv, &new_channels,
mlx5e_update_trust_state_hw,
mutex_unlock(&priv->state_lock);
return err;
mutex_unlock(&priv->state_lock);
return err;
- err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
unlock:
mutex_unlock(&priv->state_lock);
unlock:
mutex_unlock(&priv->state_lock);
/* Switch to new channels, set new parameters and close old ones */
err = mlx5e_safe_switch_channels(priv, &new_channels,
/* Switch to new channels, set new parameters and close old ones */
err = mlx5e_safe_switch_channels(priv, &new_channels,
- mlx5e_num_channels_changed_ctx, NULL);
+ mlx5e_num_channels_changed_ctx, NULL, true);
if (arfs_enabled) {
int err2 = mlx5e_arfs_enable(priv);
if (arfs_enabled) {
int err2 = mlx5e_arfs_enable(priv);
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
bool reset_rx, reset_tx;
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
bool reset_rx, reset_tx;
int err = 0;
if (!MLX5_CAP_GEN(mdev, cq_moderation))
int err = 0;
if (!MLX5_CAP_GEN(mdev, cq_moderation))
mlx5e_set_priv_channels_rx_coalesce(priv, coal);
if (!coal->use_adaptive_tx_coalesce)
mlx5e_set_priv_channels_tx_coalesce(priv, coal);
mlx5e_set_priv_channels_rx_coalesce(priv, coal);
if (!coal->use_adaptive_tx_coalesce)
mlx5e_set_priv_channels_tx_coalesce(priv, coal);
- priv->channels.params = new_channels.params;
- goto out;
- err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, reset);
mutex_unlock(&priv->state_lock);
return err;
}
mutex_unlock(&priv->state_lock);
return err;
}
else
mlx5e_set_tx_cq_mode_params(&new_channels.params, cq_period_mode);
else
mlx5e_set_tx_cq_mode_params(&new_channels.params, cq_period_mode);
- return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
}
static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
}
static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
if (priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE)
new_channels.params.ptp_rx = new_val;
if (priv->tstamp.rx_filter != HWTSTAMP_FILTER_NONE)
new_channels.params.ptp_rx = new_val;
if (new_channels.params.ptp_rx == priv->channels.params.ptp_rx)
if (new_channels.params.ptp_rx == priv->channels.params.ptp_rx)
- err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
else
err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_ptp_rx_manage_fs_ctx,
else
err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_ptp_rx_manage_fs_ctx,
- &new_channels.params.ptp_rx);
+ &new_channels.params.ptp_rx, true);
MLX5E_SET_PFLAG(&new_channels.params, MLX5E_PFLAG_RX_STRIDING_RQ, enable);
mlx5e_set_rq_type(mdev, &new_channels.params);
MLX5E_SET_PFLAG(&new_channels.params, MLX5E_PFLAG_RX_STRIDING_RQ, enable);
mlx5e_set_rq_type(mdev, &new_channels.params);
- return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
}
static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
}
static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
MLX5E_SET_PFLAG(&new_channels.params, flag, enable);
MLX5E_SET_PFLAG(&new_channels.params, flag, enable);
- return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
}
static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable)
}
static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable)
*/
err = mlx5e_safe_switch_channels(priv, &new_channels,
*/
err = mlx5e_safe_switch_channels(priv, &new_channels,
- mlx5e_num_channels_changed_ctx, NULL);
+ mlx5e_num_channels_changed_ctx, NULL, true);
if (!err)
priv->tx_ptp_opened = true;
if (!err)
priv->tx_ptp_opened = true;
mlx5e_deactivate_channels(&priv->channels);
}
mlx5e_deactivate_channels(&priv->channels);
}
+static int mlx5e_switch_priv_params(struct mlx5e_priv *priv,
+ struct mlx5e_params *new_params,
+ mlx5e_fp_preactivate preactivate,
+ void *context)
+{
+ struct mlx5e_params old_params;
+
+ old_params = priv->channels.params;
+ priv->channels.params = *new_params;
+
+ if (preactivate) {
+ int err;
+
+ err = preactivate(priv, context);
+ if (err) {
+ priv->channels.params = old_params;
+ return err;
+ }
+ }
+
+ return 0;
+}
+
static int mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
static int mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
struct net_device *netdev = priv->netdev;
struct mlx5e_channels old_chs;
int carrier_ok;
struct net_device *netdev = priv->netdev;
struct mlx5e_channels old_chs;
int carrier_ok;
- opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
- if (opened) {
- carrier_ok = netif_carrier_ok(netdev);
- netif_carrier_off(netdev);
+ carrier_ok = netif_carrier_ok(netdev);
+ netif_carrier_off(netdev);
- mlx5e_deactivate_priv_channels(priv);
- }
+ mlx5e_deactivate_priv_channels(priv);
old_chs = priv->channels;
priv->channels = *new_chs;
old_chs = priv->channels;
priv->channels = *new_chs;
- if (opened) {
- mlx5e_close_channels(&old_chs);
- priv->profile->update_rx(priv);
- }
+ mlx5e_close_channels(&old_chs);
+ priv->profile->update_rx(priv);
- if (opened) {
- mlx5e_activate_priv_channels(priv);
+ mlx5e_activate_priv_channels(priv);
- /* return carrier back if needed */
- if (carrier_ok)
- netif_carrier_on(netdev);
- }
+ /* return carrier back if needed */
+ if (carrier_ok)
+ netif_carrier_on(netdev);
int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *new_chs,
mlx5e_fp_preactivate preactivate,
+ void *context, bool reset)
- opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
-
- if (opened) {
- err = mlx5e_open_channels(priv, new_chs);
- if (err)
- return err;
- }
+ reset &= test_bit(MLX5E_STATE_OPENED, &priv->state);
+ if (!reset)
+ return mlx5e_switch_priv_params(priv, &new_chs->params, preactivate, context);
+ err = mlx5e_open_channels(priv, new_chs);
+ if (err)
+ return err;
err = mlx5e_switch_priv_channels(priv, new_chs, preactivate, context);
if (err)
err = mlx5e_switch_priv_channels(priv, new_chs, preactivate, context);
if (err)
- goto err_close;
-
- return 0;
-
-err_close:
- if (opened)
mlx5e_close_channels(new_chs);
return err;
mlx5e_close_channels(new_chs);
return err;
struct mlx5e_channels new_channels = {};
new_channels.params = priv->channels.params;
struct mlx5e_channels new_channels = {};
new_channels.params = priv->channels.params;
- return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);
}
void mlx5e_timestamp_init(struct mlx5e_priv *priv)
}
void mlx5e_timestamp_init(struct mlx5e_priv *priv)
new_channels.params.num_tc = tc ? tc : 1;
err = mlx5e_safe_switch_channels(priv, &new_channels,
new_channels.params.num_tc = tc ? tc : 1;
err = mlx5e_safe_switch_channels(priv, &new_channels,
- mlx5e_num_channels_changed_ctx, NULL);
+ mlx5e_num_channels_changed_ctx, NULL, true);
out:
priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
out:
priv->max_opened_tc = max_t(u8, priv->max_opened_tc,
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
struct mlx5e_params *cur_params;
struct mlx5_core_dev *mdev = priv->mdev;
struct mlx5e_channels new_channels = {};
struct mlx5e_params *cur_params;
- bool skip_reset = false;
int err = 0;
mutex_lock(&priv->state_lock);
int err = 0;
mutex_lock(&priv->state_lock);
if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) ==
mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_channels.params, NULL))
if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) ==
mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_channels.params, NULL))
- skip_reset = true;
- }
-
- if (skip_reset) {
- struct mlx5e_params old_params;
-
- old_params = *cur_params;
- *cur_params = new_channels.params;
- err = mlx5e_modify_tirs_lro(priv);
- if (err)
- *cur_params = old_params;
- goto out;
}
err = mlx5e_safe_switch_channels(priv, &new_channels,
}
err = mlx5e_safe_switch_channels(priv, &new_channels,
- mlx5e_modify_tirs_lro_ctx, NULL);
+ mlx5e_modify_tirs_lro_ctx, NULL, reset);
out:
mutex_unlock(&priv->state_lock);
return err;
out:
mutex_unlock(&priv->state_lock);
return err;
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_channels new_channels = {};
struct mlx5e_params *params;
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_channels new_channels = {};
struct mlx5e_params *params;
- bool skip_reset = false;
int err = 0;
mutex_lock(&priv->state_lock);
int err = 0;
mutex_lock(&priv->state_lock);
if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
bool is_linear_old = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, params, NULL);
if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
bool is_linear_old = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, params, NULL);
*/
if (!is_linear_old && !is_linear_new && !priv->xsk.refcnt &&
ppw_old == ppw_new)
*/
if (!is_linear_old && !is_linear_new && !priv->xsk.refcnt &&
ppw_old == ppw_new)
- skip_reset = true;
- }
-
- if (skip_reset) {
- unsigned int old_mtu = params->sw_mtu;
-
- params->sw_mtu = new_mtu;
- if (preactivate) {
- err = preactivate(priv, NULL);
- if (err) {
- params->sw_mtu = old_mtu;
- goto out;
- }
- }
- goto out;
- err = mlx5e_safe_switch_channels(priv, &new_channels, preactivate, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, preactivate, NULL, reset);
out:
netdev->mtu = params->sw_mtu;
out:
netdev->mtu = params->sw_mtu;
goto out;
err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_ptp_rx_manage_fs_ctx,
goto out;
err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_ptp_rx_manage_fs_ctx,
- &new_channels.params.ptp_rx);
+ &new_channels.params.ptp_rx, true);
if (err) {
mutex_unlock(&priv->state_lock);
return err;
if (err) {
mutex_unlock(&priv->state_lock);
return err;
static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_channels new_channels = {};
struct bpf_prog *old_prog;
struct bpf_prog *old_prog;
- bool reset, was_opened;
int i;
mutex_lock(&priv->state_lock);
int i;
mutex_lock(&priv->state_lock);
- was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
/* no need for full reset when exchanging programs */
reset = (!priv->channels.params.xdp_prog || !prog);
/* no need for full reset when exchanging programs */
reset = (!priv->channels.params.xdp_prog || !prog);
- if (was_opened && !reset)
- /* num_channels is invariant here, so we can take the
- * batched reference right upfront.
- */
- bpf_prog_add(prog, priv->channels.num);
-
- if (reset) {
- struct mlx5e_channels new_channels = {};
-
- new_channels.params = priv->channels.params;
- new_channels.params.xdp_prog = prog;
+ new_channels.params = priv->channels.params;
+ new_channels.params.xdp_prog = prog;
+ if (reset)
mlx5e_set_rq_type(priv->mdev, &new_channels.params);
mlx5e_set_rq_type(priv->mdev, &new_channels.params);
- old_prog = priv->channels.params.xdp_prog;
+ old_prog = priv->channels.params.xdp_prog;
- err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
- if (err)
- goto unlock;
- } else {
- /* exchange programs, extra prog reference we got from caller
- * as long as we don't fail from this point onwards.
- */
- old_prog = xchg(&priv->channels.params.xdp_prog, prog);
- }
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, reset);
+ if (err)
+ goto unlock;
if (old_prog)
bpf_prog_put(old_prog);
if (old_prog)
bpf_prog_put(old_prog);
- if (!was_opened || reset)
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset)
goto unlock;
/* exchanging programs w/o reset, we update ref counts on behalf
* of the channels RQs here.
*/
goto unlock;
/* exchanging programs w/o reset, we update ref counts on behalf
* of the channels RQs here.
*/
+ bpf_prog_add(prog, priv->channels.num);
for (i = 0; i < priv->channels.num; i++) {
struct mlx5e_channel *c = priv->channels.c[i];
for (i = 0; i < priv->channels.num; i++) {
struct mlx5e_channel *c = priv->channels.c[i];
new_channels.params = priv->channels.params;
new_channels.params.sw_mtu = new_mtu;
new_channels.params = priv->channels.params;
new_channels.params.sw_mtu = new_mtu;
- err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
+ err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL, true);