IB/ipath: merge ipath_core and ib_ipath drivers
[firefly-linux-kernel-4.4.55.git] / drivers / infiniband / hw / ipath / ipath_verbs.c
index 56ac336dd1ecb59560c2e018402dd82fd4201d83..15edec9227e430a68f6846c6728e5b05e84e73b4 100644 (file)
@@ -191,10 +191,6 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
 {
        struct ipath_sge *sge = &ss->sge;
 
-       while (length > sge->sge_length) {
-               length -= sge->sge_length;
-               ss->sge = *ss->sg_list++;
-       }
        while (length) {
                u32 len = sge->length;
 
@@ -281,11 +277,12 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                              struct ib_recv_wr **bad_wr)
 {
        struct ipath_qp *qp = to_iqp(ibqp);
+       struct ipath_rwq *wq = qp->r_rq.wq;
        unsigned long flags;
        int ret;
 
        /* Check that state is OK to post receive. */
-       if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK)) {
+       if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK) || !wq) {
                *bad_wr = wr;
                ret = -EINVAL;
                goto bail;
@@ -294,59 +291,31 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
        for (; wr; wr = wr->next) {
                struct ipath_rwqe *wqe;
                u32 next;
-               int i, j;
+               int i;
 
-               if (wr->num_sge > qp->r_rq.max_sge) {
+               if ((unsigned) wr->num_sge > qp->r_rq.max_sge) {
                        *bad_wr = wr;
                        ret = -ENOMEM;
                        goto bail;
                }
 
                spin_lock_irqsave(&qp->r_rq.lock, flags);
-               next = qp->r_rq.head + 1;
+               next = wq->head + 1;
                if (next >= qp->r_rq.size)
                        next = 0;
-               if (next == qp->r_rq.tail) {
+               if (next == wq->tail) {
                        spin_unlock_irqrestore(&qp->r_rq.lock, flags);
                        *bad_wr = wr;
                        ret = -ENOMEM;
                        goto bail;
                }
 
-               wqe = get_rwqe_ptr(&qp->r_rq, qp->r_rq.head);
+               wqe = get_rwqe_ptr(&qp->r_rq, wq->head);
                wqe->wr_id = wr->wr_id;
-               wqe->sg_list[0].mr = NULL;
-               wqe->sg_list[0].vaddr = NULL;
-               wqe->sg_list[0].length = 0;
-               wqe->sg_list[0].sge_length = 0;
-               wqe->length = 0;
-               for (i = 0, j = 0; i < wr->num_sge; i++) {
-                       /* Check LKEY */
-                       if (to_ipd(qp->ibqp.pd)->user &&
-                           wr->sg_list[i].lkey == 0) {
-                               spin_unlock_irqrestore(&qp->r_rq.lock,
-                                                      flags);
-                               *bad_wr = wr;
-                               ret = -EINVAL;
-                               goto bail;
-                       }
-                       if (wr->sg_list[i].length == 0)
-                               continue;
-                       if (!ipath_lkey_ok(
-                                   &to_idev(qp->ibqp.device)->lk_table,
-                                   &wqe->sg_list[j], &wr->sg_list[i],
-                                   IB_ACCESS_LOCAL_WRITE)) {
-                               spin_unlock_irqrestore(&qp->r_rq.lock,
-                                                      flags);
-                               *bad_wr = wr;
-                               ret = -EINVAL;
-                               goto bail;
-                       }
-                       wqe->length += wr->sg_list[i].length;
-                       j++;
-               }
-               wqe->num_sge = j;
-               qp->r_rq.head = next;
+               wqe->num_sge = wr->num_sge;
+               for (i = 0; i < wr->num_sge; i++)
+                       wqe->sg_list[i] = wr->sg_list[i];
+               wq->head = next;
                spin_unlock_irqrestore(&qp->r_rq.lock, flags);
        }
        ret = 0;
@@ -399,7 +368,7 @@ static void ipath_qp_rcv(struct ipath_ibdev *dev,
 }
 
 /**
- * ipath_ib_rcv - process and incoming packet
+ * ipath_ib_rcv - process an incoming packet
  * @arg: the device pointer
  * @rhdr: the header of the packet
  * @data: the packet data
@@ -408,9 +377,9 @@ static void ipath_qp_rcv(struct ipath_ibdev *dev,
  * This is called from ipath_kreceive() to process an incoming packet at
  * interrupt level. Tlen is the length of the header + data + CRC in bytes.
  */
-static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen)
+void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data,
+                 u32 tlen)
 {
-       struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
        struct ipath_ib_header *hdr = rhdr;
        struct ipath_other_headers *ohdr;
        struct ipath_qp *qp;
@@ -499,9 +468,8 @@ bail:;
  * This is called from ipath_do_rcv_timer() at interrupt level to check for
  * QPs which need retransmits and to collect performance numbers.
  */
-static void ipath_ib_timer(void *arg)
+void ipath_ib_timer(struct ipath_ibdev *dev)
 {
-       struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
        struct ipath_qp *resend = NULL;
        struct list_head *last;
        struct ipath_qp *qp;
@@ -595,9 +563,8 @@ static void ipath_ib_timer(void *arg)
  * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
  * return zero).
  */
-static int ipath_ib_piobufavail(void *arg)
+int ipath_ib_piobufavail(struct ipath_ibdev *dev)
 {
-       struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
        struct ipath_qp *qp;
        unsigned long flags;
 
@@ -627,6 +594,7 @@ static int ipath_query_device(struct ib_device *ibdev,
        props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
                IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
                IB_DEVICE_SYS_IMAGE_GUID;
+       props->page_size_cap = PAGE_SIZE;
        props->vendor_id = ipath_layer_get_vendorid(dev->dd);
        props->vendor_part_id = ipath_layer_get_deviceid(dev->dd);
        props->hw_ver = ipath_layer_get_pcirev(dev->dd);
@@ -806,18 +774,22 @@ static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev,
         * we allow allocations of more than we report for this value.
         */
 
-       if (dev->n_pds_allocated == ib_ipath_max_pds) {
+       pd = kmalloc(sizeof *pd, GFP_KERNEL);
+       if (!pd) {
                ret = ERR_PTR(-ENOMEM);
                goto bail;
        }
 
-       pd = kmalloc(sizeof *pd, GFP_KERNEL);
-       if (!pd) {
+       spin_lock(&dev->n_pds_lock);
+       if (dev->n_pds_allocated == ib_ipath_max_pds) {
+               spin_unlock(&dev->n_pds_lock);
+               kfree(pd);
                ret = ERR_PTR(-ENOMEM);
                goto bail;
        }
 
        dev->n_pds_allocated++;
+       spin_unlock(&dev->n_pds_lock);
 
        /* ib_alloc_pd() will initialize pd->ibpd. */
        pd->user = udata != NULL;
@@ -833,7 +805,9 @@ static int ipath_dealloc_pd(struct ib_pd *ibpd)
        struct ipath_pd *pd = to_ipd(ibpd);
        struct ipath_ibdev *dev = to_idev(ibpd->device);
 
+       spin_lock(&dev->n_pds_lock);
        dev->n_pds_allocated--;
+       spin_unlock(&dev->n_pds_lock);
 
        kfree(pd);
 
@@ -854,11 +828,6 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
        struct ib_ah *ret;
        struct ipath_ibdev *dev = to_idev(pd->device);
 
-       if (dev->n_ahs_allocated == ib_ipath_max_ahs) {
-               ret = ERR_PTR(-ENOMEM);
-               goto bail;
-       }
-
        /* A multicast address requires a GRH (see ch. 8.4.1). */
        if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE &&
            ah_attr->dlid != IPATH_PERMISSIVE_LID &&
@@ -884,7 +853,16 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
                goto bail;
        }
 
+       spin_lock(&dev->n_ahs_lock);
+       if (dev->n_ahs_allocated == ib_ipath_max_ahs) {
+               spin_unlock(&dev->n_ahs_lock);
+               kfree(ah);
+               ret = ERR_PTR(-ENOMEM);
+               goto bail;
+       }
+
        dev->n_ahs_allocated++;
+       spin_unlock(&dev->n_ahs_lock);
 
        /* ib_create_ah() will initialize ah->ibah. */
        ah->attr = *ah_attr;
@@ -906,7 +884,9 @@ static int ipath_destroy_ah(struct ib_ah *ibah)
        struct ipath_ibdev *dev = to_idev(ibah->device);
        struct ipath_ah *ah = to_iah(ibah);
 
+       spin_lock(&dev->n_ahs_lock);
        dev->n_ahs_allocated--;
+       spin_unlock(&dev->n_ahs_lock);
 
        kfree(ah);
 
@@ -975,11 +955,10 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev);
 
 /**
  * ipath_register_ib_device - register our device with the infiniband core
- * @unit: the device number to register
  * @dd: the device data structure
  * Return the allocated ipath_ibdev pointer or NULL on error.
  */
-static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
+int ipath_register_ib_device(struct ipath_devdata *dd)
 {
        struct ipath_layer_counters cntrs;
        struct ipath_ibdev *idev;
@@ -987,12 +966,20 @@ static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
        int ret;
 
        idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
-       if (idev == NULL)
+       if (idev == NULL) {
+               ret = -ENOMEM;
                goto bail;
+       }
 
        dev = &idev->ibdev;
 
        /* Only need to initialize non-zero fields. */
+       spin_lock_init(&idev->n_pds_lock);
+       spin_lock_init(&idev->n_ahs_lock);
+       spin_lock_init(&idev->n_cqs_lock);
+       spin_lock_init(&idev->n_srqs_lock);
+       spin_lock_init(&idev->n_mcast_grps_lock);
+
        spin_lock_init(&idev->qp_table.lock);
        spin_lock_init(&idev->lk_table.lock);
        idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);
@@ -1059,7 +1046,7 @@ static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
        if (!sys_image_guid)
                sys_image_guid = ipath_layer_get_guid(dd);
        idev->sys_image_guid = sys_image_guid;
-       idev->ib_unit = unit;
+       idev->ib_unit = dd->ipath_unit;
        idev->dd = dd;
 
        strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX);
@@ -1140,6 +1127,7 @@ static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
        dev->attach_mcast = ipath_multicast_attach;
        dev->detach_mcast = ipath_multicast_detach;
        dev->process_mad = ipath_process_mad;
+       dev->mmap = ipath_mmap;
 
        snprintf(dev->node_desc, sizeof(dev->node_desc),
                 IPATH_IDSTR " %s kernel_SMA", system_utsname.nodename);
@@ -1164,16 +1152,16 @@ err_lk:
 err_qp:
        ib_dealloc_device(dev);
        _VERBS_ERROR("ib_ipath%d cannot register verbs (%d)!\n",
-                    unit, -ret);
+                    dd->ipath_unit, -ret);
        idev = NULL;
 
 bail:
-       return idev;
+       dd->verbs_dev = idev;
+       return ret;
 }
 
-static void ipath_unregister_ib_device(void *arg)
+void ipath_unregister_ib_device(struct ipath_ibdev *dev)
 {
-       struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
        struct ib_device *ibdev = &dev->ibdev;
 
        ipath_layer_disable_timer(dev->dd);
@@ -1204,19 +1192,6 @@ static void ipath_unregister_ib_device(void *arg)
        ib_dealloc_device(ibdev);
 }
 
-static int __init ipath_verbs_init(void)
-{
-       return ipath_verbs_register(ipath_register_ib_device,
-                                   ipath_unregister_ib_device,
-                                   ipath_ib_piobufavail, ipath_ib_rcv,
-                                   ipath_ib_timer);
-}
-
-static void __exit ipath_verbs_cleanup(void)
-{
-       ipath_verbs_unregister();
-}
-
 static ssize_t show_rev(struct class_device *cdev, char *buf)
 {
        struct ipath_ibdev *dev =
@@ -1308,6 +1283,3 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev)
 bail:
        return ret;
 }
-
-module_init(ipath_verbs_init);
-module_exit(ipath_verbs_cleanup);