Commit dea3165f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "A lot of fixes accumulated over the holiday break:

   - Static tool fixes, value is already proven to be NULL, possible
     integer overflow

   - Many bnxt_re fixes:
      - Crashes due to a mismatch in the maximum SGE list size
      - Don't waste memory for user QPs by creating kernel-only
        structures
      - Fix compatability issues with older HW in some of the new HW
        features recently introduced: RTS->RTS feature, work around 9096
      - Do not allow destroy_qp to fail
      - Validate QP MTU against device limits
      - Add missing validation on madatory QP attributes for RTR->RTS
      - Report port_num in query_qp as required by the spec
      - Fix creation of QPs of the maximum queue size, and in the
        variable mode
      - Allow all QPs to be used on newer HW by limiting a work around
        only to HW it affects
      - Use the correct MSN table size for variable mode QPs
      - Add missing locking in create_qp() accessing the qp_tbl
      - Form WQE buffers correctly when some of the buffers are 0 hop
      - Don't crash on QP destroy if the userspace doesn't setup the
        dip_ctx
      - Add the missing QP flush handler call on the DWQE path to avoid
        hanging on error recovery
      - Consistently use ENXIO for return codes if the devices is
        fatally errored

   - Try again to fix VLAN support on iwarp, previous fix was reverted
     due to breaking other cards

   - Correct error path return code for rdma netlink events

   - Remove the seperate net_device pointer in siw and rxe which
     syzkaller found a way to UAF

   - Fix a UAF of a stack ib_sge in rtrs

   - Fix a regression where old mlx5 devices and FW were wrongly
     activing new device features and failing"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (28 commits)
  RDMA/mlx5: Enable multiplane mode only when it is supported
  RDMA/bnxt_re: Fix error recovery sequence
  RDMA/rtrs: Ensure 'ib_sge list' is accessible
  RDMA/rxe: Remove the direct link to net_device
  RDMA/hns: Fix missing flush CQE for DWQE
  RDMA/hns: Fix warning storm caused by invalid input in IO path
  RDMA/hns: Fix accessing invalid dip_ctx during destroying QP
  RDMA/hns: Fix mapping error of zero-hop WQE buffer
  RDMA/bnxt_re: Fix the locking while accessing the QP table
  RDMA/bnxt_re: Fix MSN table size for variable wqe mode
  RDMA/bnxt_re: Add send queue size check for variable wqe
  RDMA/bnxt_re: Disable use of reserved wqes
  RDMA/bnxt_re: Fix max_qp_wrs reported
  RDMA/siw: Remove direct link to net_device
  RDMA/nldev: Set error code in rdma_nl_notify_event
  RDMA/bnxt_re: Fix reporting hw_ver in query_device
  RDMA/bnxt_re: Fix to export port num to ib_query_qp
  RDMA/bnxt_re: Fix setting mandatory attributes for modify_qp
  RDMA/bnxt_re: Add check for path mtu in modify_qp
  RDMA/bnxt_re: Fix the check for 9060 condition
  ...
parents f274fffb 45d339fe
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -690,6 +690,7 @@ cma_validate_port(struct ib_device *device, u32 port,
	int bound_if_index = dev_addr->bound_dev_if;
	int dev_type = dev_addr->dev_type;
	struct net_device *ndev = NULL;
	struct net_device *pdev = NULL;

	if (!rdma_dev_access_netns(device, id_priv->id.route.addr.dev_addr.net))
		goto out;
@@ -714,6 +715,21 @@ cma_validate_port(struct ib_device *device, u32 port,

		rcu_read_lock();
		ndev = rcu_dereference(sgid_attr->ndev);
		if (ndev->ifindex != bound_if_index) {
			pdev = dev_get_by_index_rcu(dev_addr->net, bound_if_index);
			if (pdev) {
				if (is_vlan_dev(pdev)) {
					pdev = vlan_dev_real_dev(pdev);
					if (ndev->ifindex == pdev->ifindex)
						bound_if_index = pdev->ifindex;
				}
				if (is_vlan_dev(ndev)) {
					pdev = vlan_dev_real_dev(ndev);
					if (bound_if_index == pdev->ifindex)
						bound_if_index = ndev->ifindex;
				}
			}
		}
		if (!net_eq(dev_net(ndev), dev_addr->net) ||
		    ndev->ifindex != bound_if_index) {
			rdma_put_gid_attr(sgid_attr);
+1 −1
Original line number Diff line number Diff line
@@ -2833,8 +2833,8 @@ int rdma_nl_notify_event(struct ib_device *device, u32 port_num,
			  enum rdma_nl_notify_event_type type)
{
	struct sk_buff *skb;
	int ret = -EMSGSIZE;
	struct net *net;
	int ret = 0;
	void *nlh;

	net = read_pnet(&device->coredev.rdma_net);
+9 −7
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter,
{
	const void __user *res = iter->cur;

	if (iter->cur + len > iter->end)
	if (len > iter->end - iter->cur)
		return (void __force __user *)ERR_PTR(-ENOSPC);
	iter->cur += len;
	return res;
@@ -2008,11 +2008,13 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
	ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
	if (ret)
		return ret;
	wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count);
	wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size,
						       cmd.wr_count));
	if (IS_ERR(wqes))
		return PTR_ERR(wqes);
	sgls = uverbs_request_next_ptr(
		&iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
	sgls = uverbs_request_next_ptr(&iter,
				       size_mul(cmd.sge_count,
						sizeof(struct ib_uverbs_sge)));
	if (IS_ERR(sgls))
		return PTR_ERR(sgls);
	ret = uverbs_request_finish(&iter);
@@ -2198,11 +2200,11 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count,
	if (wqe_size < sizeof(struct ib_uverbs_recv_wr))
		return ERR_PTR(-EINVAL);

	wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count);
	wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count));
	if (IS_ERR(wqes))
		return ERR_CAST(wqes);
	sgls = uverbs_request_next_ptr(
		iter, sge_count * sizeof(struct ib_uverbs_sge));
	sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
						      sizeof(struct ib_uverbs_sge)));
	if (IS_ERR(sgls))
		return ERR_CAST(sgls);
	ret = uverbs_request_finish(iter);
+25 −25
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ int bnxt_re_query_device(struct ib_device *ibdev,

	ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
	ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
	ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
	ib_attr->hw_ver = rdev->en_dev->pdev->revision;
	ib_attr->max_qp = dev_attr->max_qp;
	ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
	ib_attr->device_cap_flags =
@@ -967,13 +967,13 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
	unsigned int flags;
	int rc;

	bnxt_re_debug_rem_qpinfo(rdev, qp);

	bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);

	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
	if (rc) {
	if (rc)
		ibdev_err(&rdev->ibdev, "Failed to destroy HW QP");
		return rc;
	}

	if (rdma_is_kernel_res(&qp->ib_qp.res)) {
		flags = bnxt_re_lock_cqs(qp);
@@ -983,11 +983,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)

	bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);

	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
		rc = bnxt_re_destroy_gsi_sqp(qp);
		if (rc)
			return rc;
	}
	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp)
		bnxt_re_destroy_gsi_sqp(qp);

	mutex_lock(&rdev->qp_lock);
	list_del(&qp->list);
@@ -998,8 +995,6 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
	else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD)
		atomic_dec(&rdev->stats.res.ud_qp_count);

	bnxt_re_debug_rem_qpinfo(rdev, qp);

	ib_umem_release(qp->rumem);
	ib_umem_release(qp->sumem);

@@ -2167,18 +2162,20 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
		}
	}

	if (qp_attr->qp_state == IB_QPS_RTR) {
		enum ib_mtu qpmtu;

		qpmtu = iboe_get_mtu(rdev->netdev->mtu);
		if (qp_attr_mask & IB_QP_PATH_MTU) {
		qp->qplib_qp.modify_flags |=
				CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
		qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
	} else if (qp_attr->qp_state == IB_QPS_RTR) {
		qp->qplib_qp.modify_flags |=
			CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
		qp->qplib_qp.path_mtu =
			__from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
		qp->qplib_qp.mtu =
			ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
			if (ib_mtu_enum_to_int(qp_attr->path_mtu) >
			    ib_mtu_enum_to_int(qpmtu))
				return -EINVAL;
			qpmtu = qp_attr->path_mtu;
		}

		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
		qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu);
		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qpmtu);
	}

	if (qp_attr_mask & IB_QP_TIMEOUT) {
@@ -2328,6 +2325,7 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
	qp_attr->retry_cnt = qplib_qp->retry_cnt;
	qp_attr->rnr_retry = qplib_qp->rnr_retry;
	qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer;
	qp_attr->port_num = __to_ib_port_num(qplib_qp->port_id);
	qp_attr->rq_psn = qplib_qp->rq.psn;
	qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic;
	qp_attr->sq_psn = qplib_qp->sq.psn;
@@ -2824,6 +2822,7 @@ static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
		wr = wr->next;
	}
	bnxt_qplib_post_send_db(&qp->qplib_qp);
	if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
		bnxt_ud_qp_hw_stall_workaround(qp);
	spin_unlock_irqrestore(&qp->sq_lock, flags);
	return rc;
@@ -2936,6 +2935,7 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
		wr = wr->next;
	}
	bnxt_qplib_post_send_db(&qp->qplib_qp);
	if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
		bnxt_ud_qp_hw_stall_workaround(qp);
	spin_unlock_irqrestore(&qp->sq_lock, flags);

+4 −0
Original line number Diff line number Diff line
@@ -268,6 +268,10 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);

static inline u32 __to_ib_port_num(u16 port_id)
{
	return (u32)port_id + 1;
}

unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp);
void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags);
Loading