Commit 763465e6 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5-fixes-2022-11-24' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5-fixes-2022-11-24
This series provides bug fixes to mlx5 driver.

Focusing on error handling and proper memory management in mlx5, in
general and in the newly added macsec module.

I still have few fixes left in my queue and I hope those will be the
last ones for mlx5 for this cycle.

Please pull and let me know if there is any problem.

Happy thanksgiving.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1f605d6d 9034b292
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1497,8 +1497,8 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf,
		return -EFAULT;

	err = sscanf(outlen_str, "%d", &outlen);
	if (err < 0)
		return err;
	if (err != 1)
		return -EINVAL;

	ptr = kzalloc(outlen, GFP_KERNEL);
	if (!ptr)
+2 −2
Original line number Diff line number Diff line
@@ -365,7 +365,7 @@ void mlx5e_accel_fs_tcp_destroy(struct mlx5e_flow_steering *fs)
	for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++)
		accel_fs_tcp_destroy_table(fs, i);

	kfree(accel_tcp);
	kvfree(accel_tcp);
	mlx5e_fs_set_accel_tcp(fs, NULL);
}

@@ -397,7 +397,7 @@ int mlx5e_accel_fs_tcp_create(struct mlx5e_flow_steering *fs)
err_destroy_tables:
	while (--i >= 0)
		accel_fs_tcp_destroy_table(fs, i);
	kfree(accel_tcp);
	kvfree(accel_tcp);
	mlx5e_fs_set_accel_tcp(fs, NULL);
	return err;
}
+59 −79
Original line number Diff line number Diff line
@@ -229,22 +229,6 @@ static int macsec_set_replay_protection(struct mlx5_macsec_obj_attrs *attrs, voi
	if (!attrs->replay_protect)
		return 0;

	switch (attrs->replay_window) {
	case 256:
		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_256BIT;
		break;
	case 128:
		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_128BIT;
		break;
	case 64:
		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_64BIT;
		break;
	case 32:
		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_32BIT;
		break;
	default:
		return -EINVAL;
	}
	MLX5_SET(macsec_aso, aso_ctx, window_size, window_sz);
	MLX5_SET(macsec_aso, aso_ctx, mode, MLX5_MACSEC_ASO_REPLAY_PROTECTION);

@@ -427,15 +411,15 @@ mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head *list, sci_t sci)
	return NULL;
}

static int mlx5e_macsec_update_rx_sa(struct mlx5e_macsec *macsec,
static int macsec_rx_sa_active_update(struct macsec_context *ctx,
				      struct mlx5e_macsec_sa *rx_sa,
				      bool active)
{
	struct mlx5_core_dev *mdev = macsec->mdev;
	struct mlx5_macsec_obj_attrs attrs = {};
	struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
	struct mlx5e_macsec *macsec = priv->macsec;
	int err = 0;

	if (rx_sa->active != active)
	if (rx_sa->active == active)
		return 0;

	rx_sa->active = active;
@@ -444,13 +428,11 @@ static int mlx5e_macsec_update_rx_sa(struct mlx5e_macsec *macsec,
		return 0;
	}

	attrs.sci = cpu_to_be64((__force u64)rx_sa->sci);
	attrs.enc_key_id = rx_sa->enc_key_id;
	err = mlx5e_macsec_create_object(mdev, &attrs, false, &rx_sa->macsec_obj_id);
	err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false);
	if (err)
		return err;
		rx_sa->active = false;

	return 0;
	return err;
}

static bool mlx5e_macsec_secy_features_validate(struct macsec_context *ctx)
@@ -476,6 +458,11 @@ static bool mlx5e_macsec_secy_features_validate(struct macsec_context *ctx)
		return false;
	}

	if (!ctx->secy->tx_sc.encrypt) {
		netdev_err(netdev, "MACsec offload: encrypt off isn't supported\n");
		return false;
	}

	return true;
}

@@ -620,6 +607,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
	if (tx_sa->active == ctx_tx_sa->active)
		goto out;

	tx_sa->active = ctx_tx_sa->active;
	if (tx_sa->assoc_num != tx_sc->encoding_sa)
		goto out;

@@ -635,8 +623,6 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)

		mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
	}

	tx_sa->active = ctx_tx_sa->active;
out:
	mutex_unlock(&macsec->lock);

@@ -736,9 +722,14 @@ static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx)

	sc_xarray_element->rx_sc = rx_sc;
	err = xa_alloc(&macsec->sc_xarray, &sc_xarray_element->fs_id, sc_xarray_element,
		       XA_LIMIT(1, USHRT_MAX), GFP_KERNEL);
	if (err)
		       XA_LIMIT(1, MLX5_MACEC_RX_FS_ID_MAX), GFP_KERNEL);
	if (err) {
		if (err == -EBUSY)
			netdev_err(ctx->netdev,
				   "MACsec offload: unable to create entry for RX SC (%d Rx SCs already allocated)\n",
				   MLX5_MACEC_RX_FS_ID_MAX);
		goto destroy_sc_xarray_elemenet;
	}

	rx_sc->md_dst = metadata_dst_alloc(0, METADATA_MACSEC, GFP_KERNEL);
	if (!rx_sc->md_dst) {
@@ -798,16 +789,16 @@ static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
		goto out;
	}

	rx_sc->active = ctx_rx_sc->active;
	if (rx_sc->active == ctx_rx_sc->active)
		goto out;

	rx_sc->active = ctx_rx_sc->active;
	for (i = 0; i < MACSEC_NUM_AN; ++i) {
		rx_sa = rx_sc->rx_sa[i];
		if (!rx_sa)
			continue;

		err = mlx5e_macsec_update_rx_sa(macsec, rx_sa, rx_sa->active && ctx_rx_sc->active);
		err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active);
		if (err)
			goto out;
	}
@@ -818,16 +809,43 @@ static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
	return err;
}

static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc)
{
	struct mlx5e_macsec_sa *rx_sa;
	int i;

	for (i = 0; i < MACSEC_NUM_AN; ++i) {
		rx_sa = rx_sc->rx_sa[i];
		if (!rx_sa)
			continue;

		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
		mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);

		kfree(rx_sa);
		rx_sc->rx_sa[i] = NULL;
	}

	/* At this point the relevant MACsec offload Rx rule already removed at
	 * mlx5e_macsec_cleanup_sa need to wait for datapath to finish current
	 * Rx related data propagating using xa_erase which uses rcu to sync,
	 * once fs_id is erased then this rx_sc is hidden from datapath.
	 */
	list_del_rcu(&rx_sc->rx_sc_list_element);
	xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id);
	metadata_dst_free(rx_sc->md_dst);
	kfree(rx_sc->sc_xarray_element);
	kfree_rcu(rx_sc);
}

static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
{
	struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
	struct mlx5e_macsec_device *macsec_device;
	struct mlx5e_macsec_rx_sc *rx_sc;
	struct mlx5e_macsec_sa *rx_sa;
	struct mlx5e_macsec *macsec;
	struct list_head *list;
	int err = 0;
	int i;

	mutex_lock(&priv->macsec->lock);

@@ -849,31 +867,7 @@ static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
		goto out;
	}

	for (i = 0; i < MACSEC_NUM_AN; ++i) {
		rx_sa = rx_sc->rx_sa[i];
		if (!rx_sa)
			continue;

		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
		mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);

		kfree(rx_sa);
		rx_sc->rx_sa[i] = NULL;
	}

/*
 * At this point the relevant MACsec offload Rx rule already removed at
 * mlx5e_macsec_cleanup_sa need to wait for datapath to finish current
 * Rx related data propagating using xa_erase which uses rcu to sync,
 * once fs_id is erased then this rx_sc is hidden from datapath.
 */
	list_del_rcu(&rx_sc->rx_sc_list_element);
	xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id);
	metadata_dst_free(rx_sc->md_dst);
	kfree(rx_sc->sc_xarray_element);

	kfree_rcu(rx_sc);

	macsec_del_rxsc_ctx(macsec, rx_sc);
out:
	mutex_unlock(&macsec->lock);

@@ -1015,7 +1009,7 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
		goto out;
	}

	err = mlx5e_macsec_update_rx_sa(macsec, rx_sa, ctx_rx_sa->active);
	err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active);
out:
	mutex_unlock(&macsec->lock);

@@ -1234,7 +1228,6 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
	struct mlx5e_priv *priv = netdev_priv(ctx->netdev);
	struct mlx5e_macsec_device *macsec_device;
	struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
	struct mlx5e_macsec_sa *rx_sa;
	struct mlx5e_macsec_sa *tx_sa;
	struct mlx5e_macsec *macsec;
	struct list_head *list;
@@ -1263,28 +1256,15 @@ static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
	}

	list = &macsec_device->macsec_rx_sc_list_head;
	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) {
		for (i = 0; i < MACSEC_NUM_AN; ++i) {
			rx_sa = rx_sc->rx_sa[i];
			if (!rx_sa)
				continue;

			mlx5e_macsec_cleanup_sa(macsec, rx_sa, false);
			mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
			kfree(rx_sa);
			rx_sc->rx_sa[i] = NULL;
		}

		list_del_rcu(&rx_sc->rx_sc_list_element);

		kfree_rcu(rx_sc);
	}
	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element)
		macsec_del_rxsc_ctx(macsec, rx_sc);

	kfree(macsec_device->dev_addr);
	macsec_device->dev_addr = NULL;

	list_del_rcu(&macsec_device->macsec_device_list_element);
	--macsec->num_of_devices;
	kfree(macsec_device);

out:
	mutex_unlock(&macsec->lock);
@@ -1748,7 +1728,7 @@ void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
	if (!macsec)
		return;

	fs_id = MLX5_MACSEC_METADATA_HANDLE(macsec_meta_data);
	fs_id = MLX5_MACSEC_RX_METADAT_HANDLE(macsec_meta_data);

	rcu_read_lock();
	sc_xarray_element = xa_load(&macsec->sc_xarray, fs_id);
+4 −2
Original line number Diff line number Diff line
@@ -10,9 +10,11 @@
#include <net/macsec.h>
#include <net/dst_metadata.h>

/* Bit31 - 30: MACsec marker, Bit3-0: MACsec id */
/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */
#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */
#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX
#define MLX5_MACSEC_METADATA_MARKER(metadata)  ((((metadata) >> 30) & 0x3)  == 0x1)
#define MLX5_MACSEC_METADATA_HANDLE(metadata)  ((metadata) & GENMASK(3, 0))
#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata)  ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK)

struct mlx5e_priv;
struct mlx5e_macsec;
+11 −6
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs)
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_spec *spec;
	u32 *flow_group_in;
	int err = 0;
	int err;

	ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
	if (!ns)
@@ -261,8 +261,10 @@ static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs)
		return -ENOMEM;

	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
	if (!flow_group_in)
	if (!flow_group_in) {
		err = -ENOMEM;
		goto out_spec;
	}

	tx_tables = &tx_fs->tables;
	ft_crypto = &tx_tables->ft_crypto;
@@ -898,7 +900,7 @@ static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs)
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_spec *spec;
	u32 *flow_group_in;
	int err = 0;
	int err;

	ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
	if (!ns)
@@ -909,8 +911,10 @@ static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs)
		return -ENOMEM;

	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
	if (!flow_group_in)
	if (!flow_group_in) {
		err = -ENOMEM;
		goto free_spec;
	}

	rx_tables = &rx_fs->tables;
	ft_crypto = &rx_tables->ft_crypto;
@@ -1142,10 +1146,10 @@ macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
	ft_crypto = &rx_tables->ft_crypto;

	/* Set bit[31 - 30] macsec marker - 0x01 */
	/* Set bit[3-0] fs id */
	/* Set bit[15-0] fs id */
	MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
	MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
	MLX5_SET(set_action_in, action, data, fs_id | BIT(30));
	MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30));
	MLX5_SET(set_action_in, action, offset, 0);
	MLX5_SET(set_action_in, action, length, 32);

@@ -1205,6 +1209,7 @@ macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
		rx_rule->rule[1] = rule;
	}

	kvfree(spec);
	return macsec_rule;

err:
Loading