*
*/
+#include <linux/delay.h>
+#include <linux/gfp.h>
+
#include "c2.h"
#include "c2_vq.h"
#include "c2_status.h"
int new_state = to_ib_state(c2_state);
pr_debug("%s: qp[%p] state modify %s --> %s\n",
- __FUNCTION__,
+ __func__,
qp,
to_ib_state_str(qp->state),
to_ib_state_str(new_state));
int err;
pr_debug("%s:%d qp=%p, %s --> %s\n",
- __FUNCTION__, __LINE__,
+ __func__, __LINE__,
qp,
to_ib_state_str(qp->state),
to_ib_state_str(attr->qp_state));
if (attr_mask & IB_QP_STATE) {
/* Ensure the state is valid */
- if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR)
- return -EINVAL;
+ if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) {
+ err = -EINVAL;
+ goto bail0;
+ }
wr.next_qp_state = cpu_to_be32(to_c2_state(attr->qp_state));
if (attr->cur_qp_state != IB_QPS_RTR &&
attr->cur_qp_state != IB_QPS_RTS &&
attr->cur_qp_state != IB_QPS_SQD &&
- attr->cur_qp_state != IB_QPS_SQE)
- return -EINVAL;
- else
+ attr->cur_qp_state != IB_QPS_SQE) {
+ err = -EINVAL;
+ goto bail0;
+ } else
wr.next_qp_state =
cpu_to_be32(to_c2_state(attr->cur_qp_state));
qp->state = next_state;
#ifdef DEBUG
else
- pr_debug("%s: c2_errno=%d\n", __FUNCTION__, err);
+ pr_debug("%s: c2_errno=%d\n", __func__, err);
#endif
/*
* If we're going to error and generating the event here, then
vq_req_free(c2dev, vq_req);
pr_debug("%s:%d qp=%p, cur_state=%s\n",
- __FUNCTION__, __LINE__,
+ __func__, __LINE__,
qp,
to_ib_state_str(qp->state));
return err;
qp->send_sgl_depth = qp_attrs->cap.max_send_sge;
qp->rdma_write_sgl_depth = qp_attrs->cap.max_send_sge;
qp->recv_sgl_depth = qp_attrs->cap.max_recv_sge;
+ init_waitqueue_head(&qp->wait);
/* Initialize the SQ MQ */
q_size = be32_to_cpu(reply->sq_depth);
return err;
}
+static inline void c2_lock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_lock_irq(&send_cq->lock);
+ else if (send_cq > recv_cq) {
+ 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 inline void c2_unlock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq)
+{
+ if (send_cq == recv_cq)
+ spin_unlock_irq(&send_cq->lock);
+ else if (send_cq > recv_cq) {
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
+ } else {
+ spin_unlock(&send_cq->lock);
+ spin_unlock_irq(&recv_cq->lock);
+ }
+}
+
void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp)
{
struct c2_cq *send_cq;
* Lock CQs here, so that CQ polling code can do QP lookup
* without taking a lock.
*/
- spin_lock_irq(&send_cq->lock);
- if (send_cq != recv_cq)
- spin_lock(&recv_cq->lock);
-
+ c2_lock_cqs(send_cq, recv_cq);
c2_free_qpn(c2dev, qp->qpn);
-
- if (send_cq != recv_cq)
- spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ c2_unlock_cqs(send_cq, recv_cq);
/*
* Destory qp in the rnic...
* cannot get on the bus and the card and system hang in a
* deadlock -- thus the need for this code. [TOT]
*/
- while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(0);
- }
+ while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000)
+ udelay(10);
__raw_writel(C2_HINT_MAKE(mq_index, shared),
c2dev->regs + PCI_BAR0_ADAPTER_HINT);
struct c2_dev *c2dev = to_c2dev(ibqp->device);
struct c2_qp *qp = to_c2qp(ibqp);
union c2wr wr;
+ unsigned long lock_flags;
int err = 0;
u32 flags;
u8 actual_sge_count;
u32 msg_size;
- if (qp->state > IB_QPS_RTS)
- return -EINVAL;
+ if (qp->state > IB_QPS_RTS) {
+ err = -EINVAL;
+ goto out;
+ }
while (ib_wr) {
switch (ib_wr->opcode) {
case IB_WR_SEND:
- if (ib_wr->send_flags & IB_SEND_SOLICITED) {
- c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
- msg_size = sizeof(struct c2wr_send_req);
+ case IB_WR_SEND_WITH_INV:
+ if (ib_wr->opcode == IB_WR_SEND) {
+ if (ib_wr->send_flags & IB_SEND_SOLICITED)
+ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
+ else
+ c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
+ wr.sqwr.send.remote_stag = 0;
} else {
- c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
- msg_size = sizeof(struct c2wr_send_req);
+ if (ib_wr->send_flags & IB_SEND_SOLICITED)
+ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE_INV);
+ else
+ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_INV);
+ wr.sqwr.send.remote_stag =
+ cpu_to_be32(ib_wr->ex.invalidate_rkey);
}
- wr.sqwr.send.remote_stag = 0;
- msg_size += sizeof(struct c2_data_addr) * ib_wr->num_sge;
+ msg_size = sizeof(struct c2wr_send_req) +
+ sizeof(struct c2_data_addr) * ib_wr->num_sge;
if (ib_wr->num_sge > qp->send_sgl_depth) {
err = -EINVAL;
break;
/*
* Post the puppy!
*/
+ spin_lock_irqsave(&qp->lock, lock_flags);
err = qp_wr_post(&qp->sq_mq, &wr, qp, msg_size);
if (err) {
+ spin_unlock_irqrestore(&qp->lock, lock_flags);
break;
}
* Enqueue mq index to activity FIFO.
*/
c2_activity(c2dev, qp->sq_mq.index, qp->sq_mq.hint_count);
+ spin_unlock_irqrestore(&qp->lock, lock_flags);
ib_wr = ib_wr->next;
}
+out:
if (err)
*bad_wr = ib_wr;
return err;
struct c2_dev *c2dev = to_c2dev(ibqp->device);
struct c2_qp *qp = to_c2qp(ibqp);
union c2wr wr;
+ unsigned long lock_flags;
int err = 0;
- if (qp->state > IB_QPS_RTS)
- return -EINVAL;
+ if (qp->state > IB_QPS_RTS) {
+ err = -EINVAL;
+ goto out;
+ }
/*
* Try and post each work request
break;
}
+ spin_lock_irqsave(&qp->lock, lock_flags);
err = qp_wr_post(&qp->rq_mq, &wr, qp, qp->rq_mq.msg_size);
if (err) {
+ spin_unlock_irqrestore(&qp->lock, lock_flags);
break;
}
* Enqueue mq index to activity FIFO
*/
c2_activity(c2dev, qp->rq_mq.index, qp->rq_mq.hint_count);
+ spin_unlock_irqrestore(&qp->lock, lock_flags);
ib_wr = ib_wr->next;
}
+out:
if (err)
*bad_wr = ib_wr;
return err;