Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/roland/infiniband

* '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
  • Loading branch information
Linus Torvalds committed May 10, 2006
2 parents 6314410 + ce477ae commit 0e44dc3
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 137 deletions.
2 changes: 1 addition & 1 deletion drivers/infiniband/core/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
41 changes: 21 additions & 20 deletions drivers/infiniband/hw/mthca/mthca_cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand All @@ -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);

/*
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -929,15 +930,15 @@ 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)
synchronize_irq(dev->eq_table.eq[MTHCA_EQ_COMP].msi_x_vector);
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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/mthca/mthca_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 11 additions & 4 deletions drivers/infiniband/hw/mthca/mthca_mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -796,19 +797,25 @@ 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");
err = -ENOMEM;
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;
Expand Down
22 changes: 12 additions & 10 deletions drivers/infiniband/hw/mthca/mthca_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
31 changes: 22 additions & 9 deletions drivers/infiniband/hw/mthca/mthca_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
spin_lock(&dev->qp_table.lock);
qp = mthca_array_get(&dev->qp_table.qp, qpn & (dev->limits.num_qps - 1));
if (qp)
atomic_inc(&qp->refcount);
++qp->refcount;
spin_unlock(&dev->qp_table.lock);

if (!qp) {
Expand All @@ -257,8 +257,10 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
if (qp->ibqp.event_handler)
qp->ibqp.event_handler(&event, qp->ibqp.qp_context);

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

static int to_mthca_state(enum ib_qp_state ib_state)
Expand Down Expand Up @@ -833,10 +835,10 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
* entries and reinitialize the QP.
*/
if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);

mthca_wq_init(&qp->sq);
Expand Down Expand Up @@ -1096,7 +1098,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
int ret;
int i;

atomic_set(&qp->refcount, 1);
qp->refcount = 1;
init_waitqueue_head(&qp->wait);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
Expand Down Expand Up @@ -1318,6 +1320,17 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
return err;
}

static inline int get_qp_refcount(struct mthca_dev *dev, struct mthca_qp *qp)
{
int c;

spin_lock_irq(&dev->qp_table.lock);
c = qp->refcount;
spin_unlock_irq(&dev->qp_table.lock);

return c;
}

void mthca_free_qp(struct mthca_dev *dev,
struct mthca_qp *qp)
{
Expand All @@ -1339,14 +1352,14 @@ void mthca_free_qp(struct mthca_dev *dev,
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp,
qp->qpn & (dev->limits.num_qps - 1));
--qp->refcount;
spin_unlock(&dev->qp_table.lock);

if (send_cq != recv_cq)
spin_unlock(&recv_cq->lock);
spin_unlock_irq(&send_cq->lock);

atomic_dec(&qp->refcount);
wait_event(qp->wait, !atomic_read(&qp->refcount));
wait_event(qp->wait, !get_qp_refcount(dev, qp));

if (qp->state != IB_QPS_RESET)
mthca_MODIFY_QP(dev, qp->state, IB_QPS_RESET, qp->qpn, 0,
Expand All @@ -1358,10 +1371,10 @@ void mthca_free_qp(struct mthca_dev *dev,
* unref the mem-free tables and free the QPN in our table.
*/
if (!qp->ibqp.uobject) {
mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);

mthca_free_memfree(dev, qp);
Expand Down
23 changes: 18 additions & 5 deletions drivers/infiniband/hw/mthca/mthca_srq.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
goto err_out_mailbox;

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

if (mthca_is_memfree(dev))
Expand Down Expand Up @@ -308,6 +308,17 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
return err;
}

static inline int get_srq_refcount(struct mthca_dev *dev, struct mthca_srq *srq)
{
int c;

spin_lock_irq(&dev->srq_table.lock);
c = srq->refcount;
spin_unlock_irq(&dev->srq_table.lock);

return c;
}

void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
{
struct mthca_mailbox *mailbox;
Expand All @@ -329,10 +340,10 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq)
spin_lock_irq(&dev->srq_table.lock);
mthca_array_clear(&dev->srq_table.srq,
srq->srqn & (dev->limits.num_srqs - 1));
--srq->refcount;
spin_unlock_irq(&dev->srq_table.lock);

atomic_dec(&srq->refcount);
wait_event(srq->wait, !atomic_read(&srq->refcount));
wait_event(srq->wait, !get_srq_refcount(dev, srq));

if (!srq->ibsrq.uobject) {
mthca_free_srq_buf(dev, srq);
Expand Down Expand Up @@ -414,7 +425,7 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
spin_lock(&dev->srq_table.lock);
srq = mthca_array_get(&dev->srq_table.srq, srqn & (dev->limits.num_srqs - 1));
if (srq)
atomic_inc(&srq->refcount);
++srq->refcount;
spin_unlock(&dev->srq_table.lock);

if (!srq) {
Expand All @@ -431,8 +442,10 @@ void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
srq->ibsrq.event_handler(&event, srq->ibsrq.srq_context);

out:
if (atomic_dec_and_test(&srq->refcount))
spin_lock(&dev->srq_table.lock);
if (!--srq->refcount)
wake_up(&srq->wait);
spin_unlock(&dev->srq_table.lock);
}

/*
Expand Down
4 changes: 1 addition & 3 deletions drivers/infiniband/ulp/ipoib/ipoib_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
if (priv->pkey == pkey) {
unregister_netdev(priv->dev);
ipoib_dev_cleanup(priv->dev);

list_del(&priv->list);

kfree(priv);
free_netdev(priv->dev);

ret = 0;
break;
Expand Down
Loading

0 comments on commit 0e44dc3

Please sign in to comment.