Skip to content

Commit

Permalink
[PATCH] IB/ipath: rC receive interrupt performance changes
Browse files Browse the repository at this point in the history
This patch separates QP state used for sending and receiving RC packets so the
processing in the receive interrupt handler can be done mostly without locks
being held.  ACK packets are now sent without requiring synchronization with
the send tasklet.

Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Cc: "Michael S. Tsirkin" <mst@mellanox.co.il>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Bryan O'Sullivan authored and Linus Torvalds committed Jul 1, 2006
1 parent fba7520 commit 12eef41
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 269 deletions.
50 changes: 28 additions & 22 deletions drivers/infiniband/hw/ipath/ipath_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
struct ib_sge *sge, int acc)
{
struct ipath_mregion *mr;
unsigned n, m;
size_t off;
int ret;

Expand Down Expand Up @@ -152,20 +153,22 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
}

off += mr->offset;
isge->mr = mr;
isge->m = 0;
isge->n = 0;
while (off >= mr->map[isge->m]->segs[isge->n].length) {
off -= mr->map[isge->m]->segs[isge->n].length;
isge->n++;
if (isge->n >= IPATH_SEGSZ) {
isge->m++;
isge->n = 0;
m = 0;
n = 0;
while (off >= mr->map[m]->segs[n].length) {
off -= mr->map[m]->segs[n].length;
n++;
if (n >= IPATH_SEGSZ) {
m++;
n = 0;
}
}
isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
isge->length = mr->map[isge->m]->segs[isge->n].length - off;
isge->mr = mr;
isge->vaddr = mr->map[m]->segs[n].vaddr + off;
isge->length = mr->map[m]->segs[n].length - off;
isge->sge_length = sge->length;
isge->m = m;
isge->n = n;

ret = 1;

Expand All @@ -190,6 +193,7 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
struct ipath_lkey_table *rkt = &dev->lk_table;
struct ipath_sge *sge = &ss->sge;
struct ipath_mregion *mr;
unsigned n, m;
size_t off;
int ret;

Expand All @@ -207,20 +211,22 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
}

off += mr->offset;
sge->mr = mr;
sge->m = 0;
sge->n = 0;
while (off >= mr->map[sge->m]->segs[sge->n].length) {
off -= mr->map[sge->m]->segs[sge->n].length;
sge->n++;
if (sge->n >= IPATH_SEGSZ) {
sge->m++;
sge->n = 0;
m = 0;
n = 0;
while (off >= mr->map[m]->segs[n].length) {
off -= mr->map[m]->segs[n].length;
n++;
if (n >= IPATH_SEGSZ) {
m++;
n = 0;
}
}
sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
sge->length = mr->map[sge->m]->segs[sge->n].length - off;
sge->mr = mr;
sge->vaddr = mr->map[m]->segs[n].vaddr + off;
sge->length = mr->map[m]->segs[n].length - off;
sge->sge_length = len;
sge->m = m;
sge->n = n;
ss->sg_list = NULL;
ss->num_sge = 1;

Expand Down
43 changes: 15 additions & 28 deletions drivers/infiniband/hw/ipath/ipath_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,11 @@ static void ipath_reset_qp(struct ipath_qp *qp)
qp->remote_qpn = 0;
qp->qkey = 0;
qp->qp_access_flags = 0;
clear_bit(IPATH_S_BUSY, &qp->s_flags);
qp->s_hdrwords = 0;
qp->s_psn = 0;
qp->r_psn = 0;
atomic_set(&qp->msn, 0);
qp->r_msn = 0;
if (qp->ibqp.qp_type == IB_QPT_RC) {
qp->s_state = IB_OPCODE_RC_SEND_LAST;
qp->r_state = IB_OPCODE_RC_SEND_LAST;
Expand All @@ -345,7 +346,8 @@ static void ipath_reset_qp(struct ipath_qp *qp)
qp->r_state = IB_OPCODE_UC_SEND_LAST;
}
qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
qp->s_nak_state = 0;
qp->r_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
qp->r_nak_state = 0;
qp->s_rnr_timeout = 0;
qp->s_head = 0;
qp->s_tail = 0;
Expand All @@ -363,10 +365,10 @@ static void ipath_reset_qp(struct ipath_qp *qp)
* @qp: the QP to put into an error state
*
* Flushes both send and receive work queues.
* QP r_rq.lock and s_lock should be held.
* QP s_lock should be held and interrupts disabled.
*/

static void ipath_error_qp(struct ipath_qp *qp)
void ipath_error_qp(struct ipath_qp *qp)
{
struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
struct ib_wc wc;
Expand Down Expand Up @@ -409,12 +411,14 @@ static void ipath_error_qp(struct ipath_qp *qp)
qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;

wc.opcode = IB_WC_RECV;
spin_lock(&qp->r_rq.lock);
while (qp->r_rq.tail != qp->r_rq.head) {
wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
if (++qp->r_rq.tail >= qp->r_rq.size)
qp->r_rq.tail = 0;
ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
}
spin_unlock(&qp->r_rq.lock);
}

/**
Expand All @@ -434,8 +438,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
unsigned long flags;
int ret;

spin_lock_irqsave(&qp->r_rq.lock, flags);
spin_lock(&qp->s_lock);
spin_lock_irqsave(&qp->s_lock, flags);

cur_state = attr_mask & IB_QP_CUR_STATE ?
attr->cur_qp_state : qp->state;
Expand Down Expand Up @@ -506,31 +509,19 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
}

if (attr_mask & IB_QP_MIN_RNR_TIMER)
qp->s_min_rnr_timer = attr->min_rnr_timer;
qp->r_min_rnr_timer = attr->min_rnr_timer;

if (attr_mask & IB_QP_QKEY)
qp->qkey = attr->qkey;

qp->state = new_state;
spin_unlock(&qp->s_lock);
spin_unlock_irqrestore(&qp->r_rq.lock, flags);

/*
* If QP1 changed to the RTS state, try to move to the link to INIT
* even if it was ACTIVE so the SM will reinitialize the SMA's
* state.
*/
if (qp->ibqp.qp_num == 1 && new_state == IB_QPS_RTS) {
struct ipath_ibdev *dev = to_idev(ibqp->device);
spin_unlock_irqrestore(&qp->s_lock, flags);

ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
}
ret = 0;
goto bail;

inval:
spin_unlock(&qp->s_lock);
spin_unlock_irqrestore(&qp->r_rq.lock, flags);
spin_unlock_irqrestore(&qp->s_lock, flags);
ret = -EINVAL;

bail:
Expand Down Expand Up @@ -564,7 +555,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
attr->sq_draining = 0;
attr->max_rd_atomic = 1;
attr->max_dest_rd_atomic = 1;
attr->min_rnr_timer = qp->s_min_rnr_timer;
attr->min_rnr_timer = qp->r_min_rnr_timer;
attr->port_num = 1;
attr->timeout = 0;
attr->retry_cnt = qp->s_retry_cnt;
Expand All @@ -591,16 +582,12 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
* @qp: the queue pair to compute the AETH for
*
* Returns the AETH.
*
* The QP s_lock should be held.
*/
__be32 ipath_compute_aeth(struct ipath_qp *qp)
{
u32 aeth = atomic_read(&qp->msn) & IPS_MSN_MASK;
u32 aeth = qp->r_msn & IPS_MSN_MASK;

if (qp->s_nak_state) {
aeth |= qp->s_nak_state << IPS_AETH_CREDIT_SHIFT;
} else if (qp->ibqp.srq) {
if (qp->ibqp.srq) {
/*
* Shared receive queues don't generate credits.
* Set the credit field to the invalid value.
Expand Down
Loading

0 comments on commit 12eef41

Please sign in to comment.