Commit c06f9091 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "Several smaller driver fixes and a core RDMA CM regression fix:

   - Fix improperly accepting flags from userspace in mlx4

   - Add missing DMA barriers for irdma

   - Fix two kcsan warnings in irdma

   - Report the correct CQ op code to userspace in irdma

   - Report the correct MW bind error code for irdma

   - Load the destination address in RDMA CM to resolve a recent
     regression

   - Fix a QP regression in mthca

   - Remove a race processing completions in bnxt_re resulting in a
     crash

   - Fix driver unloading races with interrupts and tasklets in bnxt_re

   - Fix missing error unwind in rxe"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/irdma: Report correct WC error
  RDMA/irdma: Fix op_type reporting in CQEs
  RDMA/rxe: Fix an error handling path in rxe_bind_mw()
  RDMA/bnxt_re: Fix hang during driver unload
  RDMA/bnxt_re: Prevent handling any completions after qp destroy
  RDMA/mthca: Fix crash when polling CQ for shared QPs
  RDMA/core: Update CMA destination address on rdma_resolve_addr
  RDMA/irdma: Fix data race on CQP request done
  RDMA/irdma: Fix data race on CQP completion stats
  RDMA/irdma: Add missing read barriers
  RDMA/mlx4: Make check for invalid flags stricter
parents 2b17e90d ae463563
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4062,6 +4062,8 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv,
					   RDMA_CM_ADDR_QUERY)))
			return -EINVAL;

	} else {
		memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
	}

	if (cma_family(id_priv) != dst_addr->sa_family) {
+12 −0
Original line number Diff line number Diff line
@@ -869,7 +869,10 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
{
	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
	struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp;
	struct bnxt_re_dev *rdev = qp->rdev;
	struct bnxt_qplib_nq *scq_nq = NULL;
	struct bnxt_qplib_nq *rcq_nq = NULL;
	unsigned int flags;
	int rc;

@@ -903,6 +906,15 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
	ib_umem_release(qp->rumem);
	ib_umem_release(qp->sumem);

	/* Flush all the entries of notification queue associated with
	 * given qp.
	 */
	scq_nq = qplib_qp->scq->nq;
	rcq_nq = qplib_qp->rcq->nq;
	bnxt_re_synchronize_nq(scq_nq);
	if (scq_nq != rcq_nq)
		bnxt_re_synchronize_nq(rcq_nq);

	return 0;
}

+23 −5
Original line number Diff line number Diff line
@@ -381,6 +381,24 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
	spin_unlock_bh(&hwq->lock);
}

/* bnxt_re_synchronize_nq - self polling notification queue.
 * @nq      -     notification queue pointer
 *
 * This function will start polling entries of a given notification queue
 * for all pending  entries.
 * This function is useful to synchronize notification entries while resources
 * are going away.
 */

void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq)
{
	int budget = nq->budget;

	nq->budget = nq->hwq.max_elements;
	bnxt_qplib_service_nq(&nq->nq_tasklet);
	nq->budget = budget;
}

static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance)
{
	struct bnxt_qplib_nq *nq = dev_instance;
@@ -402,19 +420,19 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill)
	if (!nq->requested)
		return;

	tasklet_disable(&nq->nq_tasklet);
	nq->requested = false;
	/* Mask h/w interrupt */
	bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false);
	/* Sync with last running IRQ handler */
	synchronize_irq(nq->msix_vec);
	if (kill)
		tasklet_kill(&nq->nq_tasklet);

	irq_set_affinity_hint(nq->msix_vec, NULL);
	free_irq(nq->msix_vec, nq);
	kfree(nq->name);
	nq->name = NULL;
	nq->requested = false;

	if (kill)
		tasklet_kill(&nq->nq_tasklet);
	tasklet_disable(&nq->nq_tasklet);
}

void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)
+1 −0
Original line number Diff line number Diff line
@@ -553,6 +553,7 @@ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
				  struct bnxt_qplib_cqe *cqe,
				  int num_cqes);
void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq);

static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx)
{
+4 −5
Original line number Diff line number Diff line
@@ -989,19 +989,18 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
	if (!creq->requested)
		return;

	tasklet_disable(&creq->creq_tasklet);
	creq->requested = false;
	/* Mask h/w interrupts */
	bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false);
	/* Sync with last running IRQ-handler */
	synchronize_irq(creq->msix_vec);
	if (kill)
		tasklet_kill(&creq->creq_tasklet);

	free_irq(creq->msix_vec, rcfw);
	kfree(creq->irq_name);
	creq->irq_name = NULL;
	creq->requested = false;
	atomic_set(&rcfw->rcfw_intr_enabled, 0);
	if (kill)
		tasklet_kill(&creq->creq_tasklet);
	tasklet_disable(&creq->creq_tasklet);
}

void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
Loading