Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e44dc38 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/mthca: FMR ioremap fix
  IPoIB: Free child interfaces properly
  IB/mthca: Fix race in reference counting
  IB/srp: Fix tracking of pending requests during error handling
  IB: Fix display of 4-bit port counters in sysfs
parents 6314410d ce477ae4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -336,7 +336,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
	switch (width) {
	case 4:
		ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >>
					    (offset % 4)) & 0xf);
					    (4 - (offset % 8))) & 0xf);
		break;
	case 8:
		ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]);
+21 −20
Original line number Diff line number Diff line
@@ -238,9 +238,9 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
	spin_lock(&dev->cq_table.lock);

	cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));

	if (cq)
		atomic_inc(&cq->refcount);
		++cq->refcount;

	spin_unlock(&dev->cq_table.lock);

	if (!cq) {
@@ -254,8 +254,10 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
	if (cq->ibcq.event_handler)
		cq->ibcq.event_handler(&event, cq->ibcq.cq_context);

	if (atomic_dec_and_test(&cq->refcount))
	spin_lock(&dev->cq_table.lock);
	if (!--cq->refcount)
		wake_up(&cq->wait);
	spin_unlock(&dev->cq_table.lock);
}

static inline int is_recv_cqe(struct mthca_cqe *cqe)
@@ -267,23 +269,13 @@ static inline int is_recv_cqe(struct mthca_cqe *cqe)
		return !(cqe->is_send & 0x80);
}

void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
		    struct mthca_srq *srq)
{
	struct mthca_cq *cq;
	struct mthca_cqe *cqe;
	u32 prod_index;
	int nfreed = 0;

	spin_lock_irq(&dev->cq_table.lock);
	cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
	if (cq)
		atomic_inc(&cq->refcount);
	spin_unlock_irq(&dev->cq_table.lock);

	if (!cq)
		return;

	spin_lock_irq(&cq->lock);

	/*
@@ -301,7 +293,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,

	if (0)
		mthca_dbg(dev, "Cleaning QPN %06x from CQN %06x; ci %d, pi %d\n",
			  qpn, cqn, cq->cons_index, prod_index);
			  qpn, cq->cqn, cq->cons_index, prod_index);

	/*
	 * Now sweep backwards through the CQ, removing CQ entries
@@ -325,8 +317,6 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
	}

	spin_unlock_irq(&cq->lock);
	if (atomic_dec_and_test(&cq->refcount))
		wake_up(&cq->wait);
}

void mthca_cq_resize_copy_cqes(struct mthca_cq *cq)
@@ -821,7 +811,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
	}

	spin_lock_init(&cq->lock);
	atomic_set(&cq->refcount, 1);
	cq->refcount = 1;
	init_waitqueue_head(&cq->wait);

	memset(cq_context, 0, sizeof *cq_context);
@@ -896,6 +886,17 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
	return err;
}

static inline int get_cq_refcount(struct mthca_dev *dev, struct mthca_cq *cq)
{
	int c;

	spin_lock_irq(&dev->cq_table.lock);
	c = cq->refcount;
	spin_unlock_irq(&dev->cq_table.lock);

	return c;
}

void mthca_free_cq(struct mthca_dev *dev,
		   struct mthca_cq *cq)
{
@@ -929,6 +930,7 @@ void mthca_free_cq(struct mthca_dev *dev,
	spin_lock_irq(&dev->cq_table.lock);
	mthca_array_clear(&dev->cq_table.cq,
			  cq->cqn & (dev->limits.num_cqs - 1));
	--cq->refcount;
	spin_unlock_irq(&dev->cq_table.lock);

	if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
@@ -936,8 +938,7 @@ void mthca_free_cq(struct mthca_dev *dev,
	else
		synchronize_irq(dev->pdev->irq);

	atomic_dec(&cq->refcount);
	wait_event(cq->wait, !atomic_read(&cq->refcount));
	wait_event(cq->wait, !get_cq_refcount(dev, cq));

	if (cq->is_kernel) {
		mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
+1 −1
Original line number Diff line number Diff line
@@ -496,7 +496,7 @@ void mthca_free_cq(struct mthca_dev *dev,
void mthca_cq_completion(struct mthca_dev *dev, u32 cqn);
void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
		    enum ib_event_type event_type);
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
		    struct mthca_srq *srq);
void mthca_cq_resize_copy_cqes(struct mthca_cq *cq);
int mthca_alloc_cq_buf(struct mthca_dev *dev, struct mthca_cq_buf *buf, int nent);
+11 −4
Original line number Diff line number Diff line
@@ -761,6 +761,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)

int __devinit mthca_init_mr_table(struct mthca_dev *dev)
{
	unsigned long addr;
	int err, i;

	err = mthca_alloc_init(&dev->mr_table.mpt_alloc,
@@ -796,9 +797,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
			goto err_fmr_mpt;
		}

		addr = pci_resource_start(dev->pdev, 4) +
			((pci_resource_len(dev->pdev, 4) - 1) &
			 dev->mr_table.mpt_base);

		dev->mr_table.tavor_fmr.mpt_base =
			ioremap(dev->mr_table.mpt_base,
				(1 << i) * sizeof (struct mthca_mpt_entry));
			ioremap(addr, (1 << i) * sizeof(struct mthca_mpt_entry));

		if (!dev->mr_table.tavor_fmr.mpt_base) {
			mthca_warn(dev, "MPT ioremap for FMR failed.\n");
@@ -806,9 +810,12 @@ int __devinit mthca_init_mr_table(struct mthca_dev *dev)
			goto err_fmr_mpt;
		}

		addr = pci_resource_start(dev->pdev, 4) +
			((pci_resource_len(dev->pdev, 4) - 1) &
			 dev->mr_table.mtt_base);

		dev->mr_table.tavor_fmr.mtt_base =
			ioremap(dev->mr_table.mtt_base,
				(1 << i) * MTHCA_MTT_SEG_SIZE);
			ioremap(addr, (1 << i) * MTHCA_MTT_SEG_SIZE);
		if (!dev->mr_table.tavor_fmr.mtt_base) {
			mthca_warn(dev, "MTT ioremap for FMR failed.\n");
			err = -ENOMEM;
+12 −10
Original line number Diff line number Diff line
@@ -139,11 +139,12 @@ struct mthca_ah {
 * a qp may be locked, with the send cq locked first.  No other
 * nesting should be done.
 *
 * Each struct mthca_cq/qp also has an atomic_t ref count.  The
 * pointer from the cq/qp_table to the struct counts as one reference.
 * This reference also is good for access through the consumer API, so
 * modifying the CQ/QP etc doesn't need to take another reference.
 * Access because of a completion being polled does need a reference.
 * Each struct mthca_cq/qp also has an ref count, protected by the
 * corresponding table lock.  The pointer from the cq/qp_table to the
 * struct counts as one reference.  This reference also is good for
 * access through the consumer API, so modifying the CQ/QP etc doesn't
 * need to take another reference.  Access to a QP because of a
 * completion being polled does not need a reference either.
 *
 * Finally, each struct mthca_cq/qp has a wait_queue_head_t for the
 * destroy function to sleep on.
@@ -159,8 +160,9 @@ struct mthca_ah {
 * - decrement ref count; if zero, wake up waiters
 *
 * To destroy a CQ/QP, we can do the following:
 * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
 * - decrement ref count
 * - lock cq/qp_table
 * - remove pointer and decrement ref count
 * - unlock cq/qp_table lock
 * - wait_event until ref count is zero
 *
 * It is the consumer's responsibilty to make sure that no QP
@@ -197,7 +199,7 @@ struct mthca_cq_resize {
struct mthca_cq {
	struct ib_cq		ibcq;
	spinlock_t		lock;
	atomic_t		refcount;
	int			refcount;
	int			cqn;
	u32			cons_index;
	struct mthca_cq_buf	buf;
@@ -217,7 +219,7 @@ struct mthca_cq {
struct mthca_srq {
	struct ib_srq		ibsrq;
	spinlock_t		lock;
	atomic_t		refcount;
	int			refcount;
	int			srqn;
	int			max;
	int			max_gs;
@@ -254,7 +256,7 @@ struct mthca_wq {

struct mthca_qp {
	struct ib_qp           ibqp;
	atomic_t               refcount;
	int                    refcount;
	u32                    qpn;
	int                    is_direct;
	u8                     port; /* for SQP and memfree use only */
Loading