Commit 78c56e53 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "Not much too exciting here, although two syzkaller bugs that seem to
  have 9 lives may have finally been squashed.

  Several core bugs and a batch of driver bug fixes:

   - Fix compilation problems in qib and hfi1

   - Do not corrupt the joined multicast group state when using
     SEND_ONLY

   - Several CMA bugs, a reference leak for listening and two syzkaller
     crashers

   - Various bug fixes for irdma

   - Fix a Sleeping while atomic bug in usnic

   - Properly sanitize kernel pointers in dmesg

   - Two bugs in the 64b CQE support for hns"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/hns: Add the check of the CQE size of the user space
  RDMA/hns: Fix the size setting error when copying CQE in clean_cq()
  RDMA/hfi1: Fix kernel pointer leak
  RDMA/usnic: Lock VF with mutex instead of spinlock
  RDMA/hns: Work around broken constant propagation in gcc 8
  RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
  RDMA/cma: Do not change route.addr.src_addr.ss_family
  RDMA/irdma: Report correct WC error when there are MW bind errors
  RDMA/irdma: Report correct WC error when transport retry counter is exceeded
  RDMA/irdma: Validate number of CQ entries on create CQ
  RDMA/irdma: Skip CQP ring during a reset
  MAINTAINERS: Update Broadcom RDMA maintainers
  RDMA/cma: Fix listener leak in rdma_cma_listen_on_all() failure
  IB/cma: Do not send IGMP leaves for sendonly Multicast groups
  IB/qib: Fix clang confusion of NULL pointer comparison
parents 02d5e016 e671f0ec
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -3820,7 +3820,6 @@ F: drivers/scsi/mpi3mr/
BROADCOM NETXTREME-E ROCE DRIVER
M:	Selvin Xavier <selvin.xavier@broadcom.com>
M:	Naresh Kumar PBS <nareshkumar.pbs@broadcom.com>
L:	linux-rdma@vger.kernel.org
S:	Supported
W:	http://www.broadcom.com
+45 −6
Original line number Diff line number Diff line
@@ -1746,15 +1746,16 @@ static void cma_cancel_route(struct rdma_id_private *id_priv)
	}
}

static void cma_cancel_listens(struct rdma_id_private *id_priv)
static void _cma_cancel_listens(struct rdma_id_private *id_priv)
{
	struct rdma_id_private *dev_id_priv;

	lockdep_assert_held(&lock);

	/*
	 * Remove from listen_any_list to prevent added devices from spawning
	 * additional listen requests.
	 */
	mutex_lock(&lock);
	list_del(&id_priv->list);

	while (!list_empty(&id_priv->listen_list)) {
@@ -1768,6 +1769,12 @@ static void cma_cancel_listens(struct rdma_id_private *id_priv)
		rdma_destroy_id(&dev_id_priv->id);
		mutex_lock(&lock);
	}
}

static void cma_cancel_listens(struct rdma_id_private *id_priv)
{
	mutex_lock(&lock);
	_cma_cancel_listens(id_priv);
	mutex_unlock(&lock);
}

@@ -1776,6 +1783,14 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv,
{
	switch (state) {
	case RDMA_CM_ADDR_QUERY:
		/*
		 * We can avoid doing the rdma_addr_cancel() based on state,
		 * only RDMA_CM_ADDR_QUERY has a work that could still execute.
		 * Notice that the addr_handler work could still be exiting
		 * outside this state, however due to the interaction with the
		 * handler_mutex the work is guaranteed not to touch id_priv
		 * during exit.
		 */
		rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
		break;
	case RDMA_CM_ROUTE_QUERY:
@@ -1810,6 +1825,8 @@ static void cma_release_port(struct rdma_id_private *id_priv)
static void destroy_mc(struct rdma_id_private *id_priv,
		       struct cma_multicast *mc)
{
	bool send_only = mc->join_state == BIT(SENDONLY_FULLMEMBER_JOIN);

	if (rdma_cap_ib_mcast(id_priv->id.device, id_priv->id.port_num))
		ib_sa_free_multicast(mc->sa_mc);

@@ -1826,7 +1843,10 @@ static void destroy_mc(struct rdma_id_private *id_priv,

			cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr,
				     &mgid);

			if (!send_only)
				cma_igmp_send(ndev, &mgid, false);

			dev_put(ndev);
		}

@@ -2574,7 +2594,7 @@ static int cma_listen_on_all(struct rdma_id_private *id_priv)
	return 0;

err_listen:
	list_del(&id_priv->list);
	_cma_cancel_listens(id_priv);
	mutex_unlock(&lock);
	if (to_destroy)
		rdma_destroy_id(&to_destroy->id);
@@ -3413,6 +3433,21 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
		if (dst_addr->sa_family == AF_IB) {
			ret = cma_resolve_ib_addr(id_priv);
		} else {
			/*
			 * The FSM can return back to RDMA_CM_ADDR_BOUND after
			 * rdma_resolve_ip() is called, eg through the error
			 * path in addr_handler(). If this happens the existing
			 * request must be canceled before issuing a new one.
			 * Since canceling a request is a bit slow and this
			 * oddball path is rare, keep track once a request has
			 * been issued. The track turns out to be a permanent
			 * state since this is the only cancel as it is
			 * immediately before rdma_resolve_ip().
			 */
			if (id_priv->used_resolve_ip)
				rdma_addr_cancel(&id->route.addr.dev_addr);
			else
				id_priv->used_resolve_ip = 1;
			ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr,
					      &id->route.addr.dev_addr,
					      timeout_ms, addr_handler,
@@ -3771,9 +3806,13 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
	int ret;

	if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) {
		struct sockaddr_in any_in = {
			.sin_family = AF_INET,
			.sin_addr.s_addr = htonl(INADDR_ANY),
		};

		/* For a well behaved ULP state will be RDMA_CM_IDLE */
		id->route.addr.src_addr.ss_family = AF_INET;
		ret = rdma_bind_addr(id, cma_src_addr(id_priv));
		ret = rdma_bind_addr(id, (struct sockaddr *)&any_in);
		if (ret)
			return ret;
		if (WARN_ON(!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND,
+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ struct rdma_id_private {
	u8			afonly;
	u8			timeout;
	u8			min_rnr_timer;
	u8 used_resolve_ip;
	enum ib_gid_type	gid_type;

	/*
+4 −4
Original line number Diff line number Diff line
@@ -876,14 +876,14 @@ void hfi1_ipoib_tx_timeout(struct net_device *dev, unsigned int q)
	struct hfi1_ipoib_txq *txq = &priv->txqs[q];
	u64 completed = atomic64_read(&txq->complete_txreqs);

	dd_dev_info(priv->dd, "timeout txq %llx q %u stopped %u stops %d no_desc %d ring_full %d\n",
		    (unsigned long long)txq, q,
	dd_dev_info(priv->dd, "timeout txq %p q %u stopped %u stops %d no_desc %d ring_full %d\n",
		    txq, q,
		    __netif_subqueue_stopped(dev, txq->q_idx),
		    atomic_read(&txq->stops),
		    atomic_read(&txq->no_desc),
		    atomic_read(&txq->ring_full));
	dd_dev_info(priv->dd, "sde %llx engine %u\n",
		    (unsigned long long)txq->sde,
	dd_dev_info(priv->dd, "sde %p engine %u\n",
		    txq->sde,
		    txq->sde ? txq->sde->this_idx : 0);
	dd_dev_info(priv->dd, "flow %x\n", txq->flow.as_int);
	dd_dev_info(priv->dd, "sent %llu completed %llu used %llu\n",
+22 −9
Original line number Diff line number Diff line
@@ -326,19 +326,30 @@ static void set_cq_param(struct hns_roce_cq *hr_cq, u32 cq_entries, int vector,
	INIT_LIST_HEAD(&hr_cq->rq_list);
}

static void set_cqe_size(struct hns_roce_cq *hr_cq, struct ib_udata *udata,
static int set_cqe_size(struct hns_roce_cq *hr_cq, struct ib_udata *udata,
			struct hns_roce_ib_create_cq *ucmd)
{
	struct hns_roce_dev *hr_dev = to_hr_dev(hr_cq->ib_cq.device);

	if (udata) {
		if (udata->inlen >= offsetofend(typeof(*ucmd), cqe_size))
	if (!udata) {
		hr_cq->cqe_size = hr_dev->caps.cqe_sz;
		return 0;
	}

	if (udata->inlen >= offsetofend(typeof(*ucmd), cqe_size)) {
		if (ucmd->cqe_size != HNS_ROCE_V2_CQE_SIZE &&
		    ucmd->cqe_size != HNS_ROCE_V3_CQE_SIZE) {
			ibdev_err(&hr_dev->ib_dev,
				  "invalid cqe size %u.\n", ucmd->cqe_size);
			return -EINVAL;
		}

		hr_cq->cqe_size = ucmd->cqe_size;
		else
			hr_cq->cqe_size = HNS_ROCE_V2_CQE_SIZE;
	} else {
		hr_cq->cqe_size = hr_dev->caps.cqe_sz;
		hr_cq->cqe_size = HNS_ROCE_V2_CQE_SIZE;
	}

	return 0;
}

int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr,
@@ -366,7 +377,9 @@ int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr,

	set_cq_param(hr_cq, attr->cqe, attr->comp_vector, &ucmd);

	set_cqe_size(hr_cq, udata, &ucmd);
	ret = set_cqe_size(hr_cq, udata, &ucmd);
	if (ret)
		return ret;

	ret = alloc_cq_buf(hr_dev, hr_cq, udata, ucmd.buf_addr);
	if (ret) {
Loading