]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_qp.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh64-2.6
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_qp.c
index 16db9ac0b40246ac0a4a64921b3a8b41588801f2..6a41fdbc8e57dfca779759de14137fe33b811015 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -336,8 +336,9 @@ static void ipath_reset_qp(struct ipath_qp *qp)
        qp->qkey = 0;
        qp->qp_access_flags = 0;
        qp->s_busy = 0;
-       qp->s_flags &= ~IPATH_S_SIGNAL_REQ_WR;
+       qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
        qp->s_hdrwords = 0;
+       qp->s_wqe = NULL;
        qp->s_psn = 0;
        qp->r_psn = 0;
        qp->r_msn = 0;
@@ -376,13 +377,15 @@ static void ipath_reset_qp(struct ipath_qp *qp)
  * @err: the receive completion error to signal if a RWQE is active
  *
  * Flushes both send and receive work queues.
+ * Returns true if last WQE event should be generated.
  * The QP s_lock should be held and interrupts disabled.
  */
 
-void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
+int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
 {
        struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
        struct ib_wc wc;
+       int ret = 0;
 
        ipath_dbg("QP%d/%d in error state\n",
                  qp->ibqp.qp_num, qp->remote_qpn);
@@ -453,7 +456,10 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
                wq->tail = tail;
 
                spin_unlock(&qp->r_rq.lock);
-       }
+       } else if (qp->ibqp.event_handler)
+               ret = 1;
+
+       return ret;
 }
 
 /**
@@ -472,6 +478,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        struct ipath_qp *qp = to_iqp(ibqp);
        enum ib_qp_state cur_state, new_state;
        unsigned long flags;
+       int lastwqe = 0;
        int ret;
 
        spin_lock_irqsave(&qp->s_lock, flags);
@@ -507,16 +514,13 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                    attr->port_num > ibqp->device->phys_port_cnt)
                        goto inval;
 
+       /*
+        * Note: the chips support a maximum MTU of 4096, but the driver
+        * hasn't implemented this feature yet, so don't allow Path MTU
+        * values greater than 2048.
+        */
        if (attr_mask & IB_QP_PATH_MTU)
-               if (attr->path_mtu > IB_MTU_4096)
-                       goto inval;
-
-       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
-               if (attr->max_dest_rd_atomic > 1)
-                       goto inval;
-
-       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
-               if (attr->max_rd_atomic > 1)
+               if (attr->path_mtu > IB_MTU_2048)
                        goto inval;
 
        if (attr_mask & IB_QP_PATH_MIG_STATE)
@@ -534,7 +538,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                break;
 
        case IB_QPS_ERR:
-               ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR);
+               lastwqe = ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR);
                break;
 
        default:
@@ -593,6 +597,14 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        qp->state = new_state;
        spin_unlock_irqrestore(&qp->s_lock, flags);
 
+       if (lastwqe) {
+               struct ib_event ev;
+
+               ev.device = qp->ibqp.device;
+               ev.element.qp = &qp->ibqp;
+               ev.event = IB_EVENT_QP_LAST_WQE_REACHED;
+               qp->ibqp.event_handler(&ev, qp->ibqp.qp_context);
+       }
        ret = 0;
        goto bail;
 
@@ -754,6 +766,9 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
        switch (init_attr->qp_type) {
        case IB_QPT_UC:
        case IB_QPT_RC:
+       case IB_QPT_UD:
+       case IB_QPT_SMI:
+       case IB_QPT_GSI:
                sz = sizeof(struct ipath_sge) *
                        init_attr->cap.max_send_sge +
                        sizeof(struct ipath_swqe);
@@ -762,10 +777,6 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
                        ret = ERR_PTR(-ENOMEM);
                        goto bail;
                }
-               /* FALLTHROUGH */
-       case IB_QPT_UD:
-       case IB_QPT_SMI:
-       case IB_QPT_GSI:
                sz = sizeof(*qp);
                if (init_attr->srq) {
                        struct ipath_srq *srq = to_isrq(init_attr->srq);
@@ -808,8 +819,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
                spin_lock_init(&qp->r_rq.lock);
                atomic_set(&qp->refcount, 0);
                init_waitqueue_head(&qp->wait);
-               tasklet_init(&qp->s_task, ipath_do_ruc_send,
-                            (unsigned long)qp);
+               tasklet_init(&qp->s_task, ipath_do_send, (unsigned long)qp);
                INIT_LIST_HEAD(&qp->piowait);
                INIT_LIST_HEAD(&qp->timerwait);
                qp->state = IB_QPS_RESET;
@@ -844,34 +854,36 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
         * See ipath_mmap() for details.
         */
        if (udata && udata->outlen >= sizeof(__u64)) {
-               struct ipath_mmap_info *ip;
-               __u64 offset = (__u64) qp->r_rq.wq;
                int err;
 
-               err = ib_copy_to_udata(udata, &offset, sizeof(offset));
-               if (err) {
-                       ret = ERR_PTR(err);
-                       goto bail_rwq;
-               }
+               if (!qp->r_rq.wq) {
+                       __u64 offset = 0;
 
-               if (qp->r_rq.wq) {
-                       /* Allocate info for ipath_mmap(). */
-                       ip = kmalloc(sizeof(*ip), GFP_KERNEL);
-                       if (!ip) {
+                       err = ib_copy_to_udata(udata, &offset,
+                                              sizeof(offset));
+                       if (err) {
+                               ret = ERR_PTR(err);
+                               goto bail_rwq;
+                       }
+               } else {
+                       u32 s = sizeof(struct ipath_rwq) +
+                               qp->r_rq.size * sz;
+
+                       qp->ip =
+                           ipath_create_mmap_info(dev, s,
+                                                  ibpd->uobject->context,
+                                                  qp->r_rq.wq);
+                       if (!qp->ip) {
                                ret = ERR_PTR(-ENOMEM);
                                goto bail_rwq;
                        }
-                       qp->ip = ip;
-                       ip->context = ibpd->uobject->context;
-                       ip->obj = qp->r_rq.wq;
-                       kref_init(&ip->ref);
-                       ip->mmap_cnt = 0;
-                       ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) +
-                                             qp->r_rq.size * sz);
-                       spin_lock_irq(&dev->pending_lock);
-                       ip->next = dev->pending_mmaps;
-                       dev->pending_mmaps = ip;
-                       spin_unlock_irq(&dev->pending_lock);
+
+                       err = ib_copy_to_udata(udata, &(qp->ip->offset),
+                                              sizeof(qp->ip->offset));
+                       if (err) {
+                               ret = ERR_PTR(err);
+                               goto bail_ip;
+                       }
                }
        }
 
@@ -885,6 +897,12 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
        dev->n_qps_allocated++;
        spin_unlock(&dev->n_qps_lock);
 
+       if (qp->ip) {
+               spin_lock_irq(&dev->pending_lock);
+               list_add(&qp->ip->pending_mmaps, &dev->pending_mmaps);
+               spin_unlock_irq(&dev->pending_lock);
+       }
+
        ret = &qp->ibqp;
        goto bail;