Commit fcef1046 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma into master

Pull rdma fixes from Jason Gunthorpe:
 "One merge window regression, some corruption bugs in HNS and a few
  more syzkaller fixes:

   - Two long standing syzkaller races

   - Fix incorrect HW configuration in HNS

   - Restore accidentally dropped locking in IB CM

   - Fix ODP prefetch bug added in the big rework several versions ago"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/mlx5: Prevent prefetch from racing with implicit destruction
  RDMA/cm: Protect access to remote_sidr_table
  RDMA/core: Fix race in rdma_alloc_commit_uobject()
  RDMA/hns: Fix wrong PBL offset when VA is not aligned to PAGE_SIZE
  RDMA/hns: Fix wrong assignment of lp_pktn_ini in QPC
  RDMA/mlx5: Use xa_lock_irq when access to SRQ table
parents a38a19ef a862192e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3676,10 +3676,12 @@ static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
		return ret;
	}
	cm_id_priv->id.state = IB_CM_IDLE;
	spin_lock_irq(&cm.lock);
	if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
		rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
		RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
	}
	spin_unlock_irq(&cm.lock);
	return 0;
}

+3 −3
Original line number Diff line number Diff line
@@ -649,9 +649,6 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
{
	struct ib_uverbs_file *ufile = attrs->ufile;

	/* alloc_commit consumes the uobj kref */
	uobj->uapi_object->type_class->alloc_commit(uobj);

	/* kref is held so long as the uobj is on the uobj list. */
	uverbs_uobject_get(uobj);
	spin_lock_irq(&ufile->uobjects_lock);
@@ -661,6 +658,9 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,
	/* matches atomic_set(-1) in alloc_uobj */
	atomic_set(&uobj->usecnt, 0);

	/* alloc_commit consumes the uobj kref */
	uobj->uapi_object->type_class->alloc_commit(uobj);

	/* Matches the down_read in rdma_alloc_begin_uobject */
	up_read(&ufile->hw_destroy_rwsem);
}
+22 −12
Original line number Diff line number Diff line
@@ -3954,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
	return 0;
}

static inline enum ib_mtu get_mtu(struct ib_qp *ibqp,
				  const struct ib_qp_attr *attr)
{
	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
		return IB_MTU_4096;

	return attr->path_mtu;
}

static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
				 const struct ib_qp_attr *attr, int attr_mask,
				 struct hns_roce_v2_qp_context *context,
@@ -3965,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
	struct ib_device *ibdev = &hr_dev->ib_dev;
	dma_addr_t trrl_ba;
	dma_addr_t irrl_ba;
	enum ib_mtu mtu;
	u8 port_num;
	u64 *mtts;
	u8 *dmac;
@@ -4062,22 +4072,22 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
	roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M,
		       V2_QPC_BYTE_52_DMAC_S, 0);

	/* mtu*(2^LP_PKTN_INI) should not bigger than 1 message length 64kb */
	roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
		       V2_QPC_BYTE_56_LP_PKTN_INI_S,
		       ilog2(hr_dev->caps.max_sq_inline / IB_MTU_4096));
	roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
		       V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);
	mtu = get_mtu(ibqp, attr);

	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
		roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
			       V2_QPC_BYTE_24_MTU_S, IB_MTU_4096);
	else if (attr_mask & IB_QP_PATH_MTU)
	if (attr_mask & IB_QP_PATH_MTU) {
		roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
			       V2_QPC_BYTE_24_MTU_S, attr->path_mtu);

			       V2_QPC_BYTE_24_MTU_S, mtu);
		roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
			       V2_QPC_BYTE_24_MTU_S, 0);
	}

#define MAX_LP_MSG_LEN 65536
	/* MTU*(2^LP_PKTN_INI) shouldn't be bigger than 64kb */
	roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
		       V2_QPC_BYTE_56_LP_PKTN_INI_S,
		       ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu)));
	roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
		       V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);

	roce_set_bit(qpc_mask->byte_108_rx_reqepsn,
		     V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0);
+1 −1
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr,

	mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num;
	buf_attr.page_shift = is_fast ? PAGE_SHIFT :
			      hr_dev->caps.pbl_buf_pg_sz + HNS_HW_PAGE_SHIFT;
			      hr_dev->caps.pbl_buf_pg_sz + PAGE_SHIFT;
	buf_attr.region[0].size = length;
	buf_attr.region[0].hopnum = mr->pbl_hop_num;
	buf_attr.region_count = 1;
+19 −3
Original line number Diff line number Diff line
@@ -601,6 +601,23 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
	 */
	synchronize_srcu(&dev->odp_srcu);

	/*
	 * All work on the prefetch list must be completed, xa_erase() prevented
	 * new work from being created.
	 */
	wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));

	/*
	 * At this point it is forbidden for any other thread to enter
	 * pagefault_mr() on this imr. It is already forbidden to call
	 * pagefault_mr() on an implicit child. Due to this additions to
	 * implicit_children are prevented.
	 */

	/*
	 * Block destroy_unused_implicit_child_mr() from incrementing
	 * num_deferred_work.
	 */
	xa_lock(&imr->implicit_children);
	xa_for_each (&imr->implicit_children, idx, mtt) {
		__xa_erase(&imr->implicit_children, idx);
@@ -609,9 +626,8 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
	xa_unlock(&imr->implicit_children);

	/*
	 * num_deferred_work can only be incremented inside the odp_srcu, or
	 * under xa_lock while the child is in the xarray. Thus at this point
	 * it is only decreasing, and all work holding it is now on the wq.
	 * Wait for any concurrent destroy_unused_implicit_child_mr() to
	 * complete.
	 */
	wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));

Loading