[openib-general] [PATCH] 1/2 separate locking for send and receive q in mthca
Michael S. Tsirkin
mst at mellanox.co.il
Thu Feb 3 09:54:19 PST 2005
Hello!
Send and receive q posting both serialise on the same spinlock in mthca.
Not good for SMP. The following patch solves this.
Together with my rx/tx split patch, I get about 2% more bandwidth on
ip over ib with this.
Applies on top of the "bugfix: remove unbalanced qp refcount" patch.
Now that I see real effect, I'll repost the ip over ib rx/tx split patch, too,
for completeness.
Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>
Index: hw/mthca/mthca_provider.h
===================================================================
--- hw/mthca/mthca_provider.h (revision 1725)
+++ hw/mthca/mthca_provider.h (working copy)
@@ -147,6 +147,7 @@ struct mthca_cq {
};
struct mthca_wq {
+ spinlock_t lock;
int max;
int cur;
int next;
@@ -159,7 +160,6 @@ struct mthca_wq {
struct mthca_qp {
struct ib_qp ibqp;
- spinlock_t lock;
atomic_t refcount;
u32 qpn;
int is_direct;
Index: hw/mthca/mthca_cq.c
===================================================================
--- hw/mthca/mthca_cq.c (revision 1725)
+++ hw/mthca/mthca_cq.c (working copy)
@@ -370,12 +370,14 @@ static void dump_cqe(struct mthca_cqe *c
static inline int mthca_poll_one(struct mthca_dev *dev,
struct mthca_cq *cq,
- struct mthca_qp **cur_qp,
+ struct mthca_wq **cur_wq,
int *freed,
struct ib_wc *entry)
{
struct mthca_wq *wq;
+ struct mthca_qp *qp;
struct mthca_cqe *cqe;
+ u32 qpn;
int wqe_index;
int is_error;
int is_send;
@@ -392,9 +394,11 @@ static inline int mthca_poll_one(struct
*/
rmb();
+ qpn = be32_to_cpu(cqe->my_qpn);
+
if (0) {
mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
- cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
+ cq->cqn, cq->cons_index, qpn,
be32_to_cpu(cqe->wqe));
dump_cqe(cqe);
@@ -404,14 +408,21 @@ static inline int mthca_poll_one(struct
MTHCA_ERROR_CQE_OPCODE_MASK;
is_send = is_error ? cqe->opcode & 0x01 : cqe->is_send & 0x80;
- if (!*cur_qp || be32_to_cpu(cqe->my_qpn) != (*cur_qp)->qpn) {
- if (*cur_qp) {
+ wq = *cur_wq;
+
+ if (is_send)
+ qp = wq ? container_of(wq, struct mthca_qp, sq) : NULL;
+ else
+ qp = wq ? container_of(wq, struct mthca_qp, rq) : NULL;
+
+ if (!qp || be32_to_cpu(cqe->my_qpn) != qp->qpn) {
+ if (qp) {
if (*freed) {
wmb();
inc_cons_index(dev, cq, *freed);
*freed = 0;
}
- spin_unlock(&(*cur_qp)->lock);
+ spin_unlock(&wq->lock);
}
/*
@@ -421,31 +430,29 @@ static inline int mthca_poll_one(struct
* because CQs will be locked while QPs are removed
* from the table.
*/
- *cur_qp = mthca_array_get(&dev->qp_table.qp,
+ qp = mthca_array_get(&dev->qp_table.qp,
be32_to_cpu(cqe->my_qpn) &
(dev->limits.num_qps - 1));
- if (!*cur_qp) {
+ if (!qp) {
mthca_warn(dev, "CQ entry for unknown QP %06x\n",
be32_to_cpu(cqe->my_qpn) & 0xffffff);
err = -EINVAL;
goto out;
}
- spin_lock(&(*cur_qp)->lock);
+ *cur_wq = wq = is_send ? &qp->sq : &qp->rq;
+ spin_lock(&wq->lock);
}
- entry->qp_num = (*cur_qp)->qpn;
+ entry->qp_num = qpn;
if (is_send) {
- wq = &(*cur_qp)->sq;
- wqe_index = ((be32_to_cpu(cqe->wqe) - (*cur_qp)->send_wqe_offset)
+ wqe_index = ((be32_to_cpu(cqe->wqe) - qp->send_wqe_offset)
>> wq->wqe_shift);
- entry->wr_id = (*cur_qp)->wrid[wqe_index +
- (*cur_qp)->rq.max];
+ entry->wr_id = qp->wrid[wqe_index + qp->rq.max];
} else {
- wq = &(*cur_qp)->rq;
wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
- entry->wr_id = (*cur_qp)->wrid[wqe_index];
+ entry->wr_id = qp->wrid[wqe_index];
}
if (wq->last_comp < wqe_index)
@@ -458,10 +465,10 @@ static inline int mthca_poll_one(struct
if (0)
mthca_dbg(dev, "%s completion for QP %06x, index %d (nr %d)\n",
is_send ? "Send" : "Receive",
- (*cur_qp)->qpn, wqe_index, wq->max);
+ qp->qpn, wqe_index, wq->max);
if (is_error) {
- err = handle_error_cqe(dev, cq, *cur_qp, wqe_index, is_send,
+ err = handle_error_cqe(dev, cq, qp, wqe_index, is_send,
(struct mthca_err_cqe *) cqe,
entry, &free_cqe);
goto out;
@@ -515,7 +522,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
{
struct mthca_dev *dev = to_mdev(ibcq->device);
struct mthca_cq *cq = to_mcq(ibcq);
- struct mthca_qp *qp = NULL;
+ struct mthca_wq *wq = NULL;
unsigned long flags;
int err = 0;
int freed = 0;
@@ -524,7 +531,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
spin_lock_irqsave(&cq->lock, flags);
for (npolled = 0; npolled < num_entries; ++npolled) {
- err = mthca_poll_one(dev, cq, &qp,
+ err = mthca_poll_one(dev, cq, &wq,
&freed, entry + npolled);
if (err)
break;
@@ -535,8 +542,8 @@ int mthca_poll_cq(struct ib_cq *ibcq, in
inc_cons_index(dev, cq, freed);
}
- if (qp)
- spin_unlock(&qp->lock);
+ if (wq)
+ spin_unlock(&wq->lock);
spin_unlock_irqrestore(&cq->lock, flags);
Index: hw/mthca/mthca_qp.c
===================================================================
--- hw/mthca/mthca_qp.c (revision 1725)
+++ hw/mthca/mthca_qp.c (working copy)
@@ -552,9 +552,11 @@ int mthca_modify_qp(struct ib_qp *ibqp,
else
cur_state = attr->cur_qp_state;
} else {
- spin_lock_irq(&qp->lock);
+ spin_lock_irq(&qp->sq.lock);
+ spin_lock(&qp->rq.lock);
cur_state = qp->state;
- spin_unlock_irq(&qp->lock);
+ spin_unlock(&qp->rq.lock);
+ spin_unlock_irq(&qp->sq.lock);
}
if (attr_mask & IB_QP_STATE) {
@@ -982,7 +984,8 @@ static int mthca_alloc_qp_common(struct
{
int err;
- spin_lock_init(&qp->lock);
+ spin_lock_init(&qp->sq.lock);
+ spin_lock_init(&qp->rq.lock);
atomic_set(&qp->refcount, 1);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
@@ -1272,7 +1275,7 @@ int mthca_post_send(struct ib_qp *ibqp,
[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
};
- spin_lock_irqsave(&qp->lock, flags);
+ spin_lock_irqsave(&qp->sq.lock, flags);
/* XXX check that state is OK to post send */
@@ -1455,7 +1458,7 @@ out:
qp->sq.cur += nreq;
qp->sq.next = ind;
- spin_unlock_irqrestore(&qp->lock, flags);
+ spin_unlock_irqrestore(&qp->sq.lock, flags);
return err;
}
@@ -1474,7 +1477,7 @@ int mthca_post_receive(struct ib_qp *ibq
void *wqe;
void *prev_wqe;
- spin_lock_irqsave(&qp->lock, flags);
+ spin_lock_irqsave(&qp->rq.lock, flags);
/* XXX check that state is OK to post receive */
@@ -1554,7 +1557,7 @@ out:
qp->rq.cur += nreq;
qp->rq.next = ind;
- spin_unlock_irqrestore(&qp->lock, flags);
+ spin_unlock_irqrestore(&qp->rq.lock, flags);
return err;
}
--
MST - Michael S. Tsirkin
More information about the general
mailing list