Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1679200f authored by Yevgeny Petrilin's avatar Yevgeny Petrilin Committed by David S. Miller
Browse files

mlx4_en: Enabling new steering



The mlx4_en module now uses the new steering mechanism.
The RX packets are now steered through the MCG table instead
of Mac table for unicast, and default entry for multicast.
The feature is enabled through INIT_HCA

Signed-off-by: default avatarYevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b12d93d6
Loading
Loading
Loading
Loading
+106 −27
Original line number Diff line number Diff line
@@ -156,9 +156,8 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
	mutex_lock(&mdev->state_lock);
	if (priv->port_up) {
		/* Remove old MAC and insert the new one */
		mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
		err = mlx4_register_mac(mdev->dev, priv->port,
					priv->mac, &priv->mac_index);
		err = mlx4_replace_mac(mdev->dev, priv->port,
				       priv->base_qpn, priv->mac, 0);
		if (err)
			en_err(priv, "Failed changing HW MAC address\n");
	} else
@@ -214,6 +213,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
	struct mlx4_en_dev *mdev = priv->mdev;
	struct net_device *dev = priv->dev;
	u64 mcast_addr = 0;
	u8 mc_list[16] = {0};
	int err;

	mutex_lock(&mdev->state_lock);
@@ -239,8 +239,12 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
			priv->flags |= MLX4_EN_FLAG_PROMISC;

			/* Enable promiscouos mode */
			if (!mdev->dev->caps.vep_uc_steering)
				err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
							     priv->base_qpn, 1);
			else
				err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
							       priv->port);
			if (err)
				en_err(priv, "Failed enabling "
					     "promiscous mode\n");
@@ -252,11 +256,22 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
				en_err(priv, "Failed disabling "
					     "multicast filter\n");

			/* Add the default qp number as multicast promisc */
			if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
				err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
								 priv->port);
				if (err)
					en_err(priv, "Failed entering multicast promisc mode\n");
				priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
			}

			if (priv->vlgrp) {
				/* Disable port VLAN filter */
				err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
				if (err)
					en_err(priv, "Failed disabling VLAN filter\n");
			}
		}
		goto out;
	}

@@ -270,11 +285,24 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
		priv->flags &= ~MLX4_EN_FLAG_PROMISC;

		/* Disable promiscouos mode */
		if (!mdev->dev->caps.vep_uc_steering)
			err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
						     priv->base_qpn, 0);
		else
			err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
							  priv->port);
		if (err)
			en_err(priv, "Failed disabling promiscous mode\n");

		/* Disable Multicast promisc */
		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
			err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
							    priv->port);
			if (err)
				en_err(priv, "Failed disabling multicast promiscous mode\n");
			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
		}

		/* Enable port VLAN filter */
		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
		if (err)
@@ -287,14 +315,38 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
					  0, MLX4_MCAST_DISABLE);
		if (err)
			en_err(priv, "Failed disabling multicast filter\n");

		/* Add the default qp number as multicast promisc */
		if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
			err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
							 priv->port);
			if (err)
				en_err(priv, "Failed entering multicast promisc mode\n");
			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
		}
	} else {
		int i;
		/* Disable Multicast promisc */
		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
			err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
							    priv->port);
			if (err)
				en_err(priv, "Failed disabling multicast promiscous mode\n");
			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
		}

		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
					  0, MLX4_MCAST_DISABLE);
		if (err)
			en_err(priv, "Failed disabling multicast filter\n");

		/* Detach our qp from all the multicast addresses */
		for (i = 0; i < priv->mc_addrs_cnt; i++) {
			memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
			mc_list[5] = priv->port;
			mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
					      mc_list, MLX4_PROT_ETH);
		}
		/* Flush mcast filter and init it with broadcast address */
		mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
				    1, MLX4_MCAST_CONFIG);
@@ -307,6 +359,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
		for (i = 0; i < priv->mc_addrs_cnt; i++) {
			mcast_addr =
			      mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN);
			memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
			mc_list[5] = priv->port;
			mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
					      mc_list, 0, MLX4_PROT_ETH);
			mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
					    mcast_addr, 0, MLX4_MCAST_CONFIG);
		}
@@ -314,8 +370,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
					  0, MLX4_MCAST_ENABLE);
		if (err)
			en_err(priv, "Failed enabling multicast filter\n");

		mlx4_en_clear_list(dev);
	}
out:
	mutex_unlock(&mdev->state_lock);
@@ -557,6 +611,7 @@ int mlx4_en_start_port(struct net_device *dev)
	int err = 0;
	int i;
	int j;
	u8 mc_list[16] = {0};
	char name[32];

	if (priv->port_up) {
@@ -596,10 +651,20 @@ int mlx4_en_start_port(struct net_device *dev)
		++rx_index;
	}

	/* Set port mac number */
	en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
	err = mlx4_register_mac(mdev->dev, priv->port,
				priv->mac, &priv->base_qpn, 0);
	if (err) {
		en_err(priv, "Failed setting port mac\n");
		goto cq_err;
	}
	mdev->mac_removed[priv->port] = 0;

	err = mlx4_en_config_rss_steer(priv);
	if (err) {
		en_err(priv, "Failed configuring rss steering\n");
		goto cq_err;
		goto mac_err;
	}

	if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
@@ -661,24 +726,22 @@ int mlx4_en_start_port(struct net_device *dev)
		en_err(priv, "Failed setting default qp numbers\n");
		goto tx_err;
	}
	/* Set port mac number */
	en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
	err = mlx4_register_mac(mdev->dev, priv->port,
				priv->mac, &priv->mac_index);
	if (err) {
		en_err(priv, "Failed setting port mac\n");
		goto tx_err;
	}
	mdev->mac_removed[priv->port] = 0;

	/* Init port */
	en_dbg(HW, priv, "Initializing port\n");
	err = mlx4_INIT_PORT(mdev->dev, priv->port);
	if (err) {
		en_err(priv, "Failed Initializing port\n");
		goto mac_err;
		goto tx_err;
	}

	/* Attach rx QP to bradcast address */
	memset(&mc_list[10], 0xff, ETH_ALEN);
	mc_list[5] = priv->port;
	if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
				  0, MLX4_PROT_ETH))
		mlx4_warn(mdev, "Failed Attaching Broadcast\n");

	/* Schedule multicast task to populate multicast list */
	queue_work(mdev->workqueue, &priv->mcast_task);

@@ -686,8 +749,6 @@ int mlx4_en_start_port(struct net_device *dev)
	netif_tx_start_all_queues(dev);
	return 0;

mac_err:
	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
tx_err:
	while (tx_index--) {
		mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
@@ -695,6 +756,8 @@ int mlx4_en_start_port(struct net_device *dev)
	}

	mlx4_en_release_rss_steer(priv);
mac_err:
	mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
cq_err:
	while (rx_index--)
		mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
@@ -710,6 +773,7 @@ void mlx4_en_stop_port(struct net_device *dev)
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_en_dev *mdev = priv->mdev;
	int i;
	u8 mc_list[16] = {0};

	if (!priv->port_up) {
		en_dbg(DRV, priv, "stop port called while port already down\n");
@@ -724,8 +788,23 @@ void mlx4_en_stop_port(struct net_device *dev)
	/* Set port as not active */
	priv->port_up = false;

	/* Detach All multicasts */
	memset(&mc_list[10], 0xff, ETH_ALEN);
	mc_list[5] = priv->port;
	mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
			      MLX4_PROT_ETH);
	for (i = 0; i < priv->mc_addrs_cnt; i++) {
		memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
		mc_list[5] = priv->port;
		mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
				      mc_list, MLX4_PROT_ETH);
	}
	mlx4_en_clear_list(dev);
	/* Flush multicast filter */
	mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);

	/* Unregister Mac address for the port */
	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
	mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
	mdev->mac_removed[priv->port] = 1;

	/* Free TX Rings */
+9 −2
Original line number Diff line number Diff line
@@ -119,6 +119,10 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
	struct mlx4_set_port_rqp_calc_context *context;
	int err;
	u32 in_mod;
	u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;

	if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
		return 0;

	mailbox = mlx4_alloc_cmd_mailbox(dev);
	if (IS_ERR(mailbox))
@@ -127,8 +131,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
	memset(context, 0, sizeof *context);

	context->base_qpn = cpu_to_be32(base_qpn);
	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
	context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn);
	context->n_mac = 0x7;
	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
				       base_qpn);
	context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
				     base_qpn);
	context->intra_no_vlan = 0;
	context->no_vlan = MLX4_NO_VLAN_IDX;
	context->intra_vlan_miss = 0;
+14 −5
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@


#define SET_PORT_GEN_ALL_VALID	0x7
#define SET_PORT_PROMISC_EN_SHIFT	31
#define SET_PORT_PROMISC_MODE_SHIFT	30
#define SET_PORT_PROMISC_SHIFT	31
#define SET_PORT_MC_PROMISC_SHIFT	30

enum {
	MLX4_CMD_SET_VLAN_FLTR  = 0x47,
@@ -45,6 +45,12 @@ enum {
	MLX4_CMD_DUMP_ETH_STATS = 0x49,
};

enum {
	MCAST_DIRECT_ONLY       = 0,
	MCAST_DIRECT            = 1,
	MCAST_DEFAULT           = 2
};

struct mlx4_set_port_general_context {
	u8 reserved[3];
	u8 flags;
@@ -60,14 +66,17 @@ struct mlx4_set_port_general_context {

struct mlx4_set_port_rqp_calc_context {
	__be32 base_qpn;
	__be32 flags;
	u8 reserved[3];
	u8 rererved;
	u8 n_mac;
	u8 n_vlan;
	u8 n_prio;
	u8 reserved2[3];
	u8 mac_miss;
	u8 intra_no_vlan;
	u8 no_vlan;
	u8 intra_vlan_miss;
	u8 vlan_miss;
	u8 reserved2[3];
	u8 reserved3[3];
	u8 no_vlan_prio;
	__be32 promisc;
	__be32 mcast;
+1 −10
Original line number Diff line number Diff line
@@ -845,16 +845,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
	}

	/* Configure RSS indirection qp */
	err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
	if (err) {
		en_err(priv, "Failed to reserve range for RSS "
			     "indirection qp\n");
		goto rss_err;
	}
	err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
	if (err) {
		en_err(priv, "Failed to allocate RSS indirection QP\n");
		goto reserve_err;
		goto rss_err;
	}
	rss_map->indir_qp.event = mlx4_en_sqp_event;
	mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
@@ -881,8 +875,6 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
		       MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
	mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
	mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
reserve_err:
	mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
rss_err:
	for (i = 0; i < good_qps; i++) {
		mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -904,7 +896,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
		       MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
	mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
	mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
	mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);

	for (i = 0; i < priv->rx_ring_num; i++) {
		mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
+3 −0
Original line number Diff line number Diff line
@@ -740,6 +740,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define	 INIT_HCA_MC_BASE_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x00)
#define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
#define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x16)
#define  INIT_HCA_UC_STEERING_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x18)
#define	 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
#define INIT_HCA_TPT_OFFSET		 0x0f0
#define	 INIT_HCA_DMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x00)
@@ -800,6 +801,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
	MLX4_PUT(inbox, param->mc_base,		INIT_HCA_MC_BASE_OFFSET);
	MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
	MLX4_PUT(inbox, param->log_mc_hash_sz,  INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
	if (dev->caps.vep_mc_steering)
		MLX4_PUT(inbox, (u8) (1 << 3),	INIT_HCA_UC_STEERING_OFFSET);
	MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);

	/* TPT attributes */
Loading