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

Commit a70c0739 authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe
Browse files

RDMA: Introduce and use GID attr helper to read RoCE L2 fields



Instead of RoCE drivers figuring out vlan, smac fields while working on
QP/AH, provide a helper routine to read the L2 fields such as vlan_id and
source mac address.

This moves logic from mlx5 driver to core for wider usage for RoCE ports.

This is a preparation patch to allow detaching netdev in subsequent patch.

Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 8f974860
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -1250,6 +1250,61 @@ struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
	return ndev;
}

static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
{
	u16 *vlan_id = data;

	if (is_vlan_dev(lower_dev))
		*vlan_id = vlan_dev_vlan_id(lower_dev);

	/* We are interested only in first level vlan device, so
	 * always return 1 to stop iterating over next level devices.
	 */
	return 1;
}

/**
 * rdma_read_gid_l2_fields - Read the vlan ID and source MAC address
 *			     of a GID entry.
 *
 * @attr:	GID attribute pointer whose L2 fields to be read
 * @vlan_id:	Pointer to vlan id to fill up if the GID entry has
 *		vlan id. It is optional.
 * @smac:	Pointer to smac to fill up for a GID entry. It is optional.
 *
 * rdma_read_gid_l2_fields() returns 0 on success and returns vlan id
 * (if gid entry has vlan) and source MAC, or returns error.
 */
int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
			    u16 *vlan_id, u8 *smac)
{
	struct net_device *ndev;

	ndev = attr->ndev;
	if (!ndev)
		return -EINVAL;

	if (smac)
		ether_addr_copy(smac, ndev->dev_addr);
	if (vlan_id) {
		*vlan_id = 0xffff;
		if (is_vlan_dev(ndev)) {
			*vlan_id = vlan_dev_vlan_id(ndev);
		} else {
			/* If the netdev is upper device and if it's lower
			 * device is vlan device, consider vlan id of the
			 * the lower vlan device for this gid entry.
			 */
			rcu_read_lock();
			netdev_walk_all_lower_dev_rcu(attr->ndev,
					get_lower_dev_vlan, vlan_id);
			rcu_read_unlock();
		}
	}
	return 0;
}
EXPORT_SYMBOL(rdma_read_gid_l2_fields);

static int config_non_roce_gid_cache(struct ib_device *device,
				     u8 port, int gid_tbl_len)
{
+12 −6
Original line number Diff line number Diff line
@@ -360,8 +360,9 @@ int bnxt_re_add_gid(const struct ib_gid_attr *attr, void **context)
	struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
	struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;

	if ((attr->ndev) && is_vlan_dev(attr->ndev))
		vlan_id = vlan_dev_vlan_id(attr->ndev);
	rc = rdma_read_gid_l2_fields(attr, &vlan_id, NULL);
	if (rc)
		return rc;

	rc = bnxt_qplib_add_sgid(sgid_tbl, (struct bnxt_qplib_gid *)&attr->gid,
				 rdev->qplib_res.netdev->dev_addr,
@@ -1637,8 +1638,11 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
				qp_attr->ah_attr.roce.dmac);

		sgid_attr = qp_attr->ah_attr.grh.sgid_attr;
		memcpy(qp->qplib_qp.smac, sgid_attr->ndev->dev_addr,
		       ETH_ALEN);
		rc = rdma_read_gid_l2_fields(sgid_attr, NULL,
					     &qp->qplib_qp.smac[0]);
		if (rc)
			return rc;

		nw_type = rdma_gid_attr_network_type(sgid_attr);
		switch (nw_type) {
		case RDMA_NETWORK_IPV4:
@@ -1857,8 +1861,10 @@ static int bnxt_re_build_qp1_send_v2(struct bnxt_re_qp *qp,

	memset(&qp->qp1_hdr, 0, sizeof(qp->qp1_hdr));

	if (is_vlan_dev(sgid_attr->ndev))
		vlan_id = vlan_dev_vlan_id(sgid_attr->ndev);
	rc = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, NULL);
	if (rc)
		return rc;

	/* Get network header type for this GID */
	nw_type = rdma_gid_attr_network_type(sgid_attr);
	switch (nw_type) {
+8 −6
Original line number Diff line number Diff line
@@ -49,20 +49,22 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
	u16 vlan_tag = 0xffff;
	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
	bool vlan_en = false;
	int ret;

	gid_attr = ah_attr->grh.sgid_attr;
	ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag, NULL);
	if (ret)
		return ret;

	/* Get mac address */
	memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);

	gid_attr = ah_attr->grh.sgid_attr;
	if (is_vlan_dev(gid_attr->ndev)) {
		vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
	if (vlan_tag < VLAN_CFI_MASK) {
		vlan_en = true;
	}

	if (vlan_tag < 0x1000)
		vlan_tag |= (rdma_ah_get_sl(ah_attr) &
			     HNS_ROCE_VLAN_SL_BIT_MASK) <<
			     HNS_ROCE_VLAN_SL_SHIFT;
	}

	ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn |
				     (rdma_ah_get_port_num(ah_attr) <<
+5 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/types.h>
#include <net/addrconf.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_umem.h>
#include <rdma/uverbs_ioctl.h>

@@ -3984,10 +3985,12 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,

		if (is_roce_protocol) {
			gid_attr = attr->ah_attr.grh.sgid_attr;
			vlan = rdma_vlan_dev_vlan_id(gid_attr->ndev);
			ret = rdma_read_gid_l2_fields(gid_attr, &vlan, NULL);
			if (ret)
				goto out;
		}

		if (is_vlan_dev(gid_attr->ndev)) {
		if (vlan < VLAN_CFI_MASK) {
			roce_set_bit(context->byte_76_srqn_op_en,
				     V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1);
			roce_set_bit(qpc_mask->byte_76_srqn_op_en,
+5 −3
Original line number Diff line number Diff line
@@ -99,9 +99,11 @@ static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
	 */
	gid_attr = ah_attr->grh.sgid_attr;
	if (gid_attr) {
		if (is_vlan_dev(gid_attr->ndev))
			vlan_tag = vlan_dev_vlan_id(gid_attr->ndev);
		memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN);
		ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag,
					      &ah->av.eth.s_mac[0]);
		if (ret)
			return ret;

		ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
		if (ret < 0)
			return ret;
Loading