|
@@ -255,6 +255,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
struct ib_wc wc;
|
|
struct ib_wc wc;
|
|
u64 sdata;
|
|
u64 sdata;
|
|
|
|
+ atomic64_t *maddr;
|
|
|
|
|
|
qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
|
|
qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
|
|
if (!qp) {
|
|
if (!qp) {
|
|
@@ -311,7 +312,7 @@ again:
|
|
sqp->s_rnr_retry--;
|
|
sqp->s_rnr_retry--;
|
|
dev->n_rnr_naks++;
|
|
dev->n_rnr_naks++;
|
|
sqp->s_rnr_timeout =
|
|
sqp->s_rnr_timeout =
|
|
- ib_ipath_rnr_table[sqp->r_min_rnr_timer];
|
|
|
|
|
|
+ ib_ipath_rnr_table[qp->r_min_rnr_timer];
|
|
ipath_insert_rnr_queue(sqp);
|
|
ipath_insert_rnr_queue(sqp);
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -344,20 +345,22 @@ again:
|
|
wc.sl = sqp->remote_ah_attr.sl;
|
|
wc.sl = sqp->remote_ah_attr.sl;
|
|
wc.dlid_path_bits = 0;
|
|
wc.dlid_path_bits = 0;
|
|
wc.port_num = 0;
|
|
wc.port_num = 0;
|
|
|
|
+ spin_lock_irqsave(&sqp->s_lock, flags);
|
|
ipath_sqerror_qp(sqp, &wc);
|
|
ipath_sqerror_qp(sqp, &wc);
|
|
|
|
+ spin_unlock_irqrestore(&sqp->s_lock, flags);
|
|
goto done;
|
|
goto done;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
case IB_WR_RDMA_READ:
|
|
case IB_WR_RDMA_READ:
|
|
|
|
+ if (unlikely(!(qp->qp_access_flags &
|
|
|
|
+ IB_ACCESS_REMOTE_READ)))
|
|
|
|
+ goto acc_err;
|
|
if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
|
|
if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
|
|
wqe->wr.wr.rdma.remote_addr,
|
|
wqe->wr.wr.rdma.remote_addr,
|
|
wqe->wr.wr.rdma.rkey,
|
|
wqe->wr.wr.rdma.rkey,
|
|
IB_ACCESS_REMOTE_READ)))
|
|
IB_ACCESS_REMOTE_READ)))
|
|
goto acc_err;
|
|
goto acc_err;
|
|
- if (unlikely(!(qp->qp_access_flags &
|
|
|
|
- IB_ACCESS_REMOTE_READ)))
|
|
|
|
- goto acc_err;
|
|
|
|
qp->r_sge.sge = wqe->sg_list[0];
|
|
qp->r_sge.sge = wqe->sg_list[0];
|
|
qp->r_sge.sg_list = wqe->sg_list + 1;
|
|
qp->r_sge.sg_list = wqe->sg_list + 1;
|
|
qp->r_sge.num_sge = wqe->wr.num_sge;
|
|
qp->r_sge.num_sge = wqe->wr.num_sge;
|
|
@@ -365,22 +368,22 @@ again:
|
|
|
|
|
|
case IB_WR_ATOMIC_CMP_AND_SWP:
|
|
case IB_WR_ATOMIC_CMP_AND_SWP:
|
|
case IB_WR_ATOMIC_FETCH_AND_ADD:
|
|
case IB_WR_ATOMIC_FETCH_AND_ADD:
|
|
|
|
+ if (unlikely(!(qp->qp_access_flags &
|
|
|
|
+ IB_ACCESS_REMOTE_ATOMIC)))
|
|
|
|
+ goto acc_err;
|
|
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
|
|
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
|
|
- wqe->wr.wr.rdma.remote_addr,
|
|
|
|
- wqe->wr.wr.rdma.rkey,
|
|
|
|
|
|
+ wqe->wr.wr.atomic.remote_addr,
|
|
|
|
+ wqe->wr.wr.atomic.rkey,
|
|
IB_ACCESS_REMOTE_ATOMIC)))
|
|
IB_ACCESS_REMOTE_ATOMIC)))
|
|
goto acc_err;
|
|
goto acc_err;
|
|
/* Perform atomic OP and save result. */
|
|
/* Perform atomic OP and save result. */
|
|
- sdata = wqe->wr.wr.atomic.swap;
|
|
|
|
- spin_lock_irqsave(&dev->pending_lock, flags);
|
|
|
|
- qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
|
|
|
|
- if (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
|
|
|
|
- *(u64 *) qp->r_sge.sge.vaddr =
|
|
|
|
- qp->r_atomic_data + sdata;
|
|
|
|
- else if (qp->r_atomic_data == wqe->wr.wr.atomic.compare_add)
|
|
|
|
- *(u64 *) qp->r_sge.sge.vaddr = sdata;
|
|
|
|
- spin_unlock_irqrestore(&dev->pending_lock, flags);
|
|
|
|
- *(u64 *) sqp->s_sge.sge.vaddr = qp->r_atomic_data;
|
|
|
|
|
|
+ maddr = (atomic64_t *) qp->r_sge.sge.vaddr;
|
|
|
|
+ sdata = wqe->wr.wr.atomic.compare_add;
|
|
|
|
+ *(u64 *) sqp->s_sge.sge.vaddr =
|
|
|
|
+ (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ?
|
|
|
|
+ (u64) atomic64_add_return(sdata, maddr) - sdata :
|
|
|
|
+ (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr,
|
|
|
|
+ sdata, wqe->wr.wr.atomic.swap);
|
|
goto send_comp;
|
|
goto send_comp;
|
|
|
|
|
|
default:
|
|
default:
|
|
@@ -441,7 +444,7 @@ again:
|
|
send_comp:
|
|
send_comp:
|
|
sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
|
|
sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
|
|
|
|
|
|
- if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) ||
|
|
|
|
|
|
+ if (!(sqp->s_flags & IPATH_S_SIGNAL_REQ_WR) ||
|
|
(wqe->wr.send_flags & IB_SEND_SIGNALED)) {
|
|
(wqe->wr.send_flags & IB_SEND_SIGNALED)) {
|
|
wc.wr_id = wqe->wr.wr_id;
|
|
wc.wr_id = wqe->wr.wr_id;
|
|
wc.status = IB_WC_SUCCESS;
|
|
wc.status = IB_WC_SUCCESS;
|
|
@@ -503,7 +506,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
|
|
* We clear the tasklet flag now since we are committing to return
|
|
* We clear the tasklet flag now since we are committing to return
|
|
* from the tasklet function.
|
|
* from the tasklet function.
|
|
*/
|
|
*/
|
|
- clear_bit(IPATH_S_BUSY, &qp->s_flags);
|
|
|
|
|
|
+ clear_bit(IPATH_S_BUSY, &qp->s_busy);
|
|
tasklet_unlock(&qp->s_task);
|
|
tasklet_unlock(&qp->s_task);
|
|
want_buffer(dev->dd);
|
|
want_buffer(dev->dd);
|
|
dev->n_piowait++;
|
|
dev->n_piowait++;
|
|
@@ -542,6 +545,9 @@ int ipath_post_ruc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
|
|
wr->sg_list[0].addr & (sizeof(u64) - 1))) {
|
|
wr->sg_list[0].addr & (sizeof(u64) - 1))) {
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
goto bail;
|
|
goto bail;
|
|
|
|
+ } else if (wr->opcode >= IB_WR_RDMA_READ && !qp->s_max_rd_atomic) {
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto bail;
|
|
}
|
|
}
|
|
/* IB spec says that num_sge == 0 is OK. */
|
|
/* IB spec says that num_sge == 0 is OK. */
|
|
if (wr->num_sge > qp->s_max_sge) {
|
|
if (wr->num_sge > qp->s_max_sge) {
|
|
@@ -648,7 +654,7 @@ void ipath_do_ruc_send(unsigned long data)
|
|
u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
|
|
u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
|
|
struct ipath_other_headers *ohdr;
|
|
struct ipath_other_headers *ohdr;
|
|
|
|
|
|
- if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
|
|
|
|
|
|
+ if (test_and_set_bit(IPATH_S_BUSY, &qp->s_busy))
|
|
goto bail;
|
|
goto bail;
|
|
|
|
|
|
if (unlikely(qp->remote_ah_attr.dlid == dev->dd->ipath_lid)) {
|
|
if (unlikely(qp->remote_ah_attr.dlid == dev->dd->ipath_lid)) {
|
|
@@ -684,19 +690,15 @@ again:
|
|
*/
|
|
*/
|
|
spin_lock_irqsave(&qp->s_lock, flags);
|
|
spin_lock_irqsave(&qp->s_lock, flags);
|
|
|
|
|
|
- /* Sending responses has higher priority over sending requests. */
|
|
|
|
- if (qp->s_ack_state != IB_OPCODE_RC_ACKNOWLEDGE &&
|
|
|
|
- (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0)
|
|
|
|
- bth2 = qp->s_ack_psn++ & IPATH_PSN_MASK;
|
|
|
|
- else if (!((qp->ibqp.qp_type == IB_QPT_RC) ?
|
|
|
|
- ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2) :
|
|
|
|
- ipath_make_uc_req(qp, ohdr, pmtu, &bth0, &bth2))) {
|
|
|
|
|
|
+ if (!((qp->ibqp.qp_type == IB_QPT_RC) ?
|
|
|
|
+ ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2) :
|
|
|
|
+ ipath_make_uc_req(qp, ohdr, pmtu, &bth0, &bth2))) {
|
|
/*
|
|
/*
|
|
* Clear the busy bit before unlocking to avoid races with
|
|
* Clear the busy bit before unlocking to avoid races with
|
|
* adding new work queue items and then failing to process
|
|
* adding new work queue items and then failing to process
|
|
* them.
|
|
* them.
|
|
*/
|
|
*/
|
|
- clear_bit(IPATH_S_BUSY, &qp->s_flags);
|
|
|
|
|
|
+ clear_bit(IPATH_S_BUSY, &qp->s_busy);
|
|
spin_unlock_irqrestore(&qp->s_lock, flags);
|
|
spin_unlock_irqrestore(&qp->s_lock, flags);
|
|
goto bail;
|
|
goto bail;
|
|
}
|
|
}
|
|
@@ -729,7 +731,7 @@ again:
|
|
goto again;
|
|
goto again;
|
|
|
|
|
|
clear:
|
|
clear:
|
|
- clear_bit(IPATH_S_BUSY, &qp->s_flags);
|
|
|
|
|
|
+ clear_bit(IPATH_S_BUSY, &qp->s_busy);
|
|
bail:
|
|
bail:
|
|
return;
|
|
return;
|
|
}
|
|
}
|