Commit 71d3bdae authored by Jacob Moroni's avatar Jacob Moroni Committed by Leon Romanovsky
Browse files

RDMA/irdma: Do not directly rely on IB_PD_UNSAFE_GLOBAL_RKEY



The HW disables bounds checking for MRs with a length of zero, so
the driver will only allow a zero length MR if the "all_memory"
flag is set, and this flag is only set if IB_PD_UNSAFE_GLOBAL_RKEY
is set for the PD.

This means that the "get_dma_mr" method will currently fail unless
the IB_PD_UNSAFE_GLOBAL_RKEY flag is set. This has not been an issue
because the "get_dma_mr" method is only ever invoked if the device
does not support the local DMA key or if IB_PD_UNSAFE_GLOBAL_RKEY
is set, and so far, all IRDMA HW supports the local DMA lkey.

However, some new HW does not support the local DMA lkey, so the
"get_dma_mr" method needs to work without IB_PD_UNSAFE_GLOBAL_RKEY
being set.

To support HW that does not allow the local DMA lkey, the logic has
been changed to pass an explicit flag to indicate when a dma_mr is
being created so that the zero length will be allowed.

Also, the "all_memory" flag has been forced to false for normal MR
allocation since these MRs are never supposed to provide global
unsafe rkey semantics anyway; only the MR created with "get_dma_mr"
should support this.

Fixes: bb6d73d9 ("RDMA/irdma: Prevent zero-length STAG registration")
Signed-off-by: default avatarJacob Moroni <jmoroni@google.com>
Signed-off-by: default avatarTatyana Nikolova <tatyana.e.nikolova@intel.com>
Link: https://patch.msgid.link/20251125025350.180-7-tatyana.e.nikolova@intel.com


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent 35bd787b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3710,7 +3710,7 @@ int irdma_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
	iwpd = iwqp->iwpd;
	tagged_offset = (uintptr_t)iwqp->ietf_mem.va;
	ibmr = irdma_reg_phys_mr(&iwpd->ibpd, iwqp->ietf_mem.pa, buf_len,
				 IB_ACCESS_LOCAL_WRITE, &tagged_offset);
				 IB_ACCESS_LOCAL_WRITE, &tagged_offset, false);
	if (IS_ERR(ibmr)) {
		ret = -ENOMEM;
		goto error;
+1 −1
Original line number Diff line number Diff line
@@ -556,7 +556,7 @@ void irdma_copy_ip_htonl(__be32 *dst, u32 *src);
u16 irdma_get_vlan_ipv4(u32 *addr);
void irdma_get_vlan_mac_ipv6(u32 *addr, u16 *vlan_id, u8 *mac);
struct ib_mr *irdma_reg_phys_mr(struct ib_pd *ib_pd, u64 addr, u64 size,
				int acc, u64 *iova_start);
				int acc, u64 *iova_start, bool dma_mr);
int irdma_upload_qp_context(struct irdma_qp *iwqp, bool freeze, bool raw);
void irdma_cqp_ce_handler(struct irdma_pci_f *rf, struct irdma_sc_cq *cq);
int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd,
+8 −7
Original line number Diff line number Diff line
@@ -3116,7 +3116,6 @@ static int irdma_hw_alloc_stag(struct irdma_device *iwdev,
	info->stag_idx = iwmr->stag >> IRDMA_CQPSQ_STAG_IDX_S;
	info->pd_id = iwpd->sc_pd.pd_id;
	info->total_len = iwmr->len;
	info->all_memory = pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY;
	info->remote_access = true;
	cqp_info->cqp_cmd = IRDMA_OP_ALLOC_STAG;
	cqp_info->post_sq = 1;
@@ -3127,7 +3126,7 @@ static int irdma_hw_alloc_stag(struct irdma_device *iwdev,
	if (status)
		return status;

	iwmr->is_hwreg = 1;
	iwmr->is_hwreg = true;
	return 0;
}

@@ -3270,7 +3269,7 @@ static int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr,
	if (iwdev->rf->sc_dev.hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_ATOMIC_OPS)
		stag_info->remote_atomics_en = (access & IB_ACCESS_REMOTE_ATOMIC) ? 1 : 0;
	stag_info->pd_id = iwpd->sc_pd.pd_id;
	stag_info->all_memory = pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY;
	stag_info->all_memory = iwmr->dma_mr;
	if (stag_info->access_rights & IRDMA_ACCESS_FLAGS_ZERO_BASED)
		stag_info->addr_type = IRDMA_ADDR_TYPE_ZERO_BASED;
	else
@@ -3297,7 +3296,7 @@ static int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr,
	irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);

	if (!ret)
		iwmr->is_hwreg = 1;
		iwmr->is_hwreg = true;

	return ret;
}
@@ -3669,7 +3668,7 @@ static int irdma_hwdereg_mr(struct ib_mr *ib_mr)
	if (status)
		return status;

	iwmr->is_hwreg = 0;
	iwmr->is_hwreg = false;
	return 0;
}

@@ -3792,9 +3791,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
 * @size: size of memory to register
 * @access: Access rights
 * @iova_start: start of virtual address for physical buffers
 * @dma_mr: Flag indicating whether this region is a PD DMA MR
 */
struct ib_mr *irdma_reg_phys_mr(struct ib_pd *pd, u64 addr, u64 size, int access,
				u64 *iova_start)
				u64 *iova_start, bool dma_mr)
{
	struct irdma_device *iwdev = to_iwdev(pd->device);
	struct irdma_pbl *iwpbl;
@@ -3811,6 +3811,7 @@ struct ib_mr *irdma_reg_phys_mr(struct ib_pd *pd, u64 addr, u64 size, int access
	iwpbl = &iwmr->iwpbl;
	iwpbl->iwmr = iwmr;
	iwmr->type = IRDMA_MEMREG_TYPE_MEM;
	iwmr->dma_mr = dma_mr;
	iwpbl->user_base = *iova_start;
	stag = irdma_create_stag(iwdev);
	if (!stag) {
@@ -3849,7 +3850,7 @@ static struct ib_mr *irdma_get_dma_mr(struct ib_pd *pd, int acc)
{
	u64 kva = 0;

	return irdma_reg_phys_mr(pd, 0, 0, acc, &kva);
	return irdma_reg_phys_mr(pd, 0, 0, acc, &kva, true);
}

/**
+2 −1
Original line number Diff line number Diff line
@@ -111,7 +111,8 @@ struct irdma_mr {
	};
	struct ib_umem *region;
	int access;
	u8 is_hwreg;
	bool is_hwreg:1;
	bool dma_mr:1;
	u16 type;
	u32 page_cnt;
	u64 page_size;