#include <linux/string.h>
#include <linux/slab.h>
-#include <asm/io.h>
-
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_pack.h>
MTHCA_QP_BIT_RSC = 1 << 3
};
-enum {
- MTHCA_SEND_DOORBELL_FENCE = 1 << 5
-};
-
struct mthca_qp_path {
__be32 port_pkey;
u8 rnr_retry;
(PAGE_SIZE - 1));
}
-static void mthca_wq_reset(struct mthca_wq *wq)
+static void mthca_wq_init(struct mthca_wq *wq)
{
+ spin_lock_init(&wq->lock);
wq->next_ind = 0;
wq->last_comp = wq->max - 1;
wq->head = 0;
struct mthca_qp_context *qp_context;
u32 sqd_event = 0;
u8 status;
- int err = -EINVAL;
-
- mutex_lock(&qp->mutex);
+ int err;
if (attr_mask & IB_QP_CUR_STATE) {
cur_state = attr->cur_qp_state;
"%d->%d with attr 0x%08x\n",
qp->transport, cur_state, new_state,
attr_mask);
- goto out;
+ return -EINVAL;
}
if ((attr_mask & IB_QP_PKEY_INDEX) &&
attr->pkey_index >= dev->limits.pkey_table_len) {
mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
attr->pkey_index, dev->limits.pkey_table_len-1);
- goto out;
+ return -EINVAL;
}
if ((attr_mask & IB_QP_PORT) &&
(attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
- goto out;
+ return -EINVAL;
}
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
- goto out;
+ return -EINVAL;
}
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
- goto out;
+ return -EINVAL;
}
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- goto out;
- }
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
qp_param = mailbox->buf;
qp_context = &qp_param->context;
memset(qp_param, 0, sizeof *qp_param);
if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) {
mthca_dbg(dev, "path MTU (%u) is invalid\n",
attr->path_mtu);
- goto out_mailbox;
+ return -EINVAL;
}
qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
}
if (attr_mask & IB_QP_AV) {
if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
- goto out_mailbox;
+ return -EINVAL;
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
}
if (attr->alt_pkey_index >= dev->limits.pkey_table_len) {
mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n",
attr->alt_pkey_index, dev->limits.pkey_table_len-1);
- goto out_mailbox;
+ return -EINVAL;
}
if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
attr->alt_port_num);
- goto out_mailbox;
+ return -EINVAL;
}
if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
attr->alt_ah_attr.port_num))
- goto out_mailbox;
+ return -EINVAL;
qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
attr->alt_port_num << 24);
err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
mailbox, sqd_event, &status);
if (err)
- goto out_mailbox;
+ goto out;
if (status) {
mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
cur_state, new_state, status);
err = -EINVAL;
- goto out_mailbox;
+ goto out;
}
qp->state = new_state;
mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
- mthca_wq_reset(&qp->sq);
+ mthca_wq_init(&qp->sq);
qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
- mthca_wq_reset(&qp->rq);
+ mthca_wq_init(&qp->rq);
qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1);
if (mthca_is_memfree(dev)) {
}
}
-out_mailbox:
- mthca_free_mailbox(dev, mailbox);
-
out:
- mutex_unlock(&qp->mutex);
+ mthca_free_mailbox(dev, mailbox);
return err;
}
qp->refcount = 1;
init_waitqueue_head(&qp->wait);
- mutex_init(&qp->mutex);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
qp->resp_depth = 0;
qp->sq_policy = send_policy;
- mthca_wq_reset(&qp->sq);
- mthca_wq_reset(&qp->rq);
-
- spin_lock_init(&qp->sq.lock);
- spin_lock_init(&qp->rq.lock);
+ mthca_wq_init(&qp->sq);
+ mthca_wq_init(&qp->rq);
ret = mthca_map_memfree(dev, qp);
if (ret)
return 0;
}
-static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
-{
- if (send_cq == recv_cq)
- spin_lock_irq(&send_cq->lock);
- else if (send_cq->cqn < recv_cq->cqn) {
- spin_lock_irq(&send_cq->lock);
- spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
- } else {
- spin_lock_irq(&recv_cq->lock);
- spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
- }
-}
-
-static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
-{
- if (send_cq == recv_cq)
- spin_unlock_irq(&send_cq->lock);
- else if (send_cq->cqn < recv_cq->cqn) {
- spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
- } else {
- spin_unlock(&send_cq->lock);
- spin_unlock_irq(&recv_cq->lock);
- }
-}
-
int mthca_alloc_sqp(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- mthca_lock_cqs(send_cq, recv_cq);
+ spin_lock_irq(&send_cq->lock);
+ if (send_cq != recv_cq)
+ spin_lock(&recv_cq->lock);
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp, mqpn);
spin_unlock(&dev->qp_table.lock);
- mthca_unlock_cqs(send_cq, recv_cq);
+ if (send_cq != recv_cq)
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
err_out:
dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- mthca_lock_cqs(send_cq, recv_cq);
+ spin_lock_irq(&send_cq->lock);
+ if (send_cq != recv_cq)
+ spin_lock(&recv_cq->lock);
spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp,
--qp->refcount;
spin_unlock(&dev->qp_table.lock);
- mthca_unlock_cqs(send_cq, recv_cq);
+ if (send_cq != recv_cq)
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
wait_event(qp->wait, !get_qp_refcount(dev, qp));
int i;
int size;
int size0 = 0;
- u32 f0;
+ u32 f0 = 0;
int ind;
u8 op0 = 0;
if (!size0) {
size0 = size;
op0 = mthca_opcode[wr->opcode];
- f0 = wr->send_flags & IB_SEND_FENCE ?
- MTHCA_SEND_DOORBELL_FENCE : 0;
}
++ind;
mthca_write64(doorbell,
dev->kar + MTHCA_SEND_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
- /*
- * Make sure doorbells don't leak out of SQ spinlock
- * and reach the HCA out of order:
- */
- mmiowb();
}
qp->sq.next_ind = ind;
qp->rq.next_ind = ind;
qp->rq.head += nreq;
- /*
- * Make sure doorbells don't leak out of RQ spinlock and reach
- * the HCA out of order:
- */
- mmiowb();
-
spin_unlock_irqrestore(&qp->rq.lock, flags);
return err;
}
int i;
int size;
int size0 = 0;
- u32 f0;
+ u32 f0 = 0;
int ind;
u8 op0 = 0;
if (!size0) {
size0 = size;
op0 = mthca_opcode[wr->opcode];
- f0 = wr->send_flags & IB_SEND_FENCE ?
- MTHCA_SEND_DOORBELL_FENCE : 0;
}
++ind;
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
- /*
- * Make sure doorbells don't leak out of SQ spinlock and reach
- * the HCA out of order:
- */
- mmiowb();
-
spin_unlock_irqrestore(&qp->sq.lock, flags);
return err;
}