Merge branch 'devel' into next
[pandora-kernel.git] / drivers / infiniband / hw / ipath / ipath_file_ops.c
index 1e627aa..35f301c 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/highmem.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
+#include <linux/smp_lock.h>
 #include <asm/pgtable.h>
 
 #include "ipath_kernel.h"
@@ -173,47 +174,25 @@ static int ipath_get_base_info(struct file *fp,
                (void *) dd->ipath_statusp -
                (void *) dd->ipath_pioavailregs_dma;
        if (!shared) {
-               kinfo->spi_piocnt = dd->ipath_pbufsport;
+               kinfo->spi_piocnt = pd->port_piocnt;
                kinfo->spi_piobufbase = (u64) pd->port_piobufs;
                kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
                        dd->ipath_ureg_align * pd->port_port;
        } else if (master) {
-               kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
-                                   (dd->ipath_pbufsport % subport_cnt);
+               kinfo->spi_piocnt = (pd->port_piocnt / subport_cnt) +
+                                   (pd->port_piocnt % subport_cnt);
                /* Master's PIO buffers are after all the slave's */
                kinfo->spi_piobufbase = (u64) pd->port_piobufs +
                        dd->ipath_palign *
-                       (dd->ipath_pbufsport - kinfo->spi_piocnt);
+                       (pd->port_piocnt - kinfo->spi_piocnt);
        } else {
                unsigned slave = subport_fp(fp) - 1;
 
-               kinfo->spi_piocnt = dd->ipath_pbufsport / subport_cnt;
+               kinfo->spi_piocnt = pd->port_piocnt / subport_cnt;
                kinfo->spi_piobufbase = (u64) pd->port_piobufs +
                        dd->ipath_palign * kinfo->spi_piocnt * slave;
        }
 
-       /*
-        * Set the PIO avail update threshold to no larger
-        * than the number of buffers per process. Note that
-        * we decrease it here, but won't ever increase it.
-        */
-       if (dd->ipath_pioupd_thresh &&
-           kinfo->spi_piocnt < dd->ipath_pioupd_thresh) {
-               unsigned long flags;
-
-               dd->ipath_pioupd_thresh = kinfo->spi_piocnt;
-               ipath_dbg("Decreased pio update threshold to %u\n",
-                       dd->ipath_pioupd_thresh);
-               spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-               dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK
-                       << INFINIPATH_S_UPDTHRESH_SHIFT);
-               dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
-                       << INFINIPATH_S_UPDTHRESH_SHIFT;
-               ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-                       dd->ipath_sendctrl);
-               spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
-       }
-
        if (shared) {
                kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
                        dd->ipath_ureg_align * pd->port_port;
@@ -577,7 +556,7 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport,
                        p = dd->ipath_pageshadow[porttid + tid];
                        dd->ipath_pageshadow[porttid + tid] = NULL;
                        ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
-                                  pd->port_pid, tid);
+                                  pid_nr(pd->port_pid), tid);
                        dd->ipath_f_put_tid(dd, &tidbase[tid],
                                            RCVHQ_RCV_TYPE_EXPECTED,
                                            dd->ipath_tidinvalid);
@@ -1309,19 +1288,19 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
        ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
        if (!pd->port_subport_cnt) {
                /* port is not shared */
-               piocnt = dd->ipath_pbufsport;
+               piocnt = pd->port_piocnt;
                piobufs = pd->port_piobufs;
        } else if (!subport_fp(fp)) {
                /* caller is the master */
-               piocnt = (dd->ipath_pbufsport / pd->port_subport_cnt) +
-                        (dd->ipath_pbufsport % pd->port_subport_cnt);
+               piocnt = (pd->port_piocnt / pd->port_subport_cnt) +
+                        (pd->port_piocnt % pd->port_subport_cnt);
                piobufs = pd->port_piobufs +
-                       dd->ipath_palign * (dd->ipath_pbufsport - piocnt);
+                       dd->ipath_palign * (pd->port_piocnt - piocnt);
        } else {
                unsigned slave = subport_fp(fp) - 1;
 
                /* caller is a slave */
-               piocnt = dd->ipath_pbufsport / pd->port_subport_cnt;
+               piocnt = pd->port_piocnt / pd->port_subport_cnt;
                piobufs = pd->port_piobufs + dd->ipath_palign * piocnt * slave;
        }
 
@@ -1631,11 +1610,8 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
                           port);
                pd->port_cnt = 1;
                port_fp(fp) = pd;
-               pd->port_pid = current->pid;
+               pd->port_pid = get_pid(task_pid(current));
                strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
-               ipath_chg_pioavailkernel(dd,
-                       dd->ipath_pbufsport * (pd->port_port - 1),
-                       dd->ipath_pbufsport, 0);
                ipath_stats.sps_ports++;
                ret = 0;
        } else
@@ -1818,14 +1794,15 @@ static int find_shared_port(struct file *fp,
                        }
                        port_fp(fp) = pd;
                        subport_fp(fp) = pd->port_cnt++;
-                       pd->port_subpid[subport_fp(fp)] = current->pid;
+                       pd->port_subpid[subport_fp(fp)] =
+                               get_pid(task_pid(current));
                        tidcursor_fp(fp) = 0;
                        pd->active_slaves |= 1 << subport_fp(fp);
                        ipath_cdbg(PROC,
                                   "%s[%u] %u sharing %s[%u] unit:port %u:%u\n",
                                   current->comm, current->pid,
                                   subport_fp(fp),
-                                  pd->port_comm, pd->port_pid,
+                                  pd->port_comm, pid_nr(pd->port_pid),
                                   dd->ipath_unit, pd->port_port);
                        ret = 1;
                        goto done;
@@ -1839,6 +1816,7 @@ done:
 static int ipath_open(struct inode *in, struct file *fp)
 {
        /* The real work is performed later in ipath_assign_port() */
+       cycle_kernel_lock();
        fp->private_data = kzalloc(sizeof(struct ipath_filedata), GFP_KERNEL);
        return fp->private_data ? 0 : -ENOMEM;
 }
@@ -1938,11 +1916,25 @@ static int ipath_do_user_init(struct file *fp,
 
        /* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
 
+       /* some ports may get extra buffers, calculate that here */
+       if (pd->port_port <= dd->ipath_ports_extrabuf)
+               pd->port_piocnt = dd->ipath_pbufsport + 1;
+       else
+               pd->port_piocnt = dd->ipath_pbufsport;
+
        /* for right now, kernel piobufs are at end, so port 1 is at 0 */
+       if (pd->port_port <= dd->ipath_ports_extrabuf)
+               pd->port_pio_base = (dd->ipath_pbufsport + 1)
+                       * (pd->port_port - 1);
+       else
+               pd->port_pio_base = dd->ipath_ports_extrabuf +
+                       dd->ipath_pbufsport * (pd->port_port - 1);
        pd->port_piobufs = dd->ipath_piobufbase +
-               dd->ipath_pbufsport * (pd->port_port - 1) * dd->ipath_palign;
-       ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
-                  pd->port_port, pd->port_piobufs);
+               pd->port_pio_base * dd->ipath_palign;
+       ipath_cdbg(VERBOSE, "piobuf base for port %u is 0x%x, piocnt %u,"
+               " first pio %u\n", pd->port_port, pd->port_piobufs,
+               pd->port_piocnt, pd->port_pio_base);
+       ipath_chg_pioavailkernel(dd, pd->port_pio_base, pd->port_piocnt, 0);
 
        /*
         * Now allocate the rcvhdr Q and eager TIDs; skip the TID
@@ -2077,7 +2069,8 @@ static int ipath_close(struct inode *in, struct file *fp)
                 * the slave(s) don't wait for receive data forever.
                 */
                pd->active_slaves &= ~(1 << fd->subport);
-               pd->port_subpid[fd->subport] = 0;
+               put_pid(pd->port_subpid[fd->subport]);
+               pd->port_subpid[fd->subport] = NULL;
                mutex_unlock(&ipath_mutex);
                goto bail;
        }
@@ -2085,7 +2078,7 @@ static int ipath_close(struct inode *in, struct file *fp)
 
        if (pd->port_hdrqfull) {
                ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
-                          "during run\n", pd->port_comm, pd->port_pid,
+                          "during run\n", pd->port_comm, pid_nr(pd->port_pid),
                           pd->port_hdrqfull);
                pd->port_hdrqfull = 0;
        }
@@ -2107,7 +2100,6 @@ static int ipath_close(struct inode *in, struct file *fp)
        }
 
        if (dd->ipath_kregbase) {
-               int i;
                /* atomically clear receive enable port and intr avail. */
                clear_bit(dd->ipath_r_portenable_shift + port,
                          &dd->ipath_rcvctrl);
@@ -2136,9 +2128,9 @@ static int ipath_close(struct inode *in, struct file *fp)
                ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
                        pd->port_port, dd->ipath_dummy_hdrq_phys);
 
-               i = dd->ipath_pbufsport * (port - 1);
-               ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
-               ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
+               ipath_disarm_piobufs(dd, pd->port_pio_base, pd->port_piocnt);
+               ipath_chg_pioavailkernel(dd, pd->port_pio_base,
+                       pd->port_piocnt, 1);
 
                dd->ipath_f_clear_tids(dd, pd->port_port);
 
@@ -2146,11 +2138,12 @@ static int ipath_close(struct inode *in, struct file *fp)
                        unlock_expected_tids(pd);
                ipath_stats.sps_ports--;
                ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
-                          pd->port_comm, pd->port_pid,
+                          pd->port_comm, pid_nr(pd->port_pid),
                           dd->ipath_unit, port);
        }
 
-       pd->port_pid = 0;
+       put_pid(pd->port_pid);
+       pd->port_pid = NULL;
        dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */
        mutex_unlock(&ipath_mutex);
        ipath_free_pddata(dd, pd); /* after releasing the mutex */
@@ -2434,11 +2427,11 @@ static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov,
 static struct class *ipath_class;
 
 static int init_cdev(int minor, char *name, const struct file_operations *fops,
-                    struct cdev **cdevp, struct class_device **class_devp)
+                    struct cdev **cdevp, struct device **devp)
 {
        const dev_t dev = MKDEV(IPATH_MAJOR, minor);
        struct cdev *cdev = NULL;
-       struct class_device *class_dev = NULL;
+       struct device *device = NULL;
        int ret;
 
        cdev = cdev_alloc();
@@ -2462,12 +2455,12 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
                goto err_cdev;
        }
 
-       class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
+       device = device_create(ipath_class, NULL, dev, name);
 
-       if (IS_ERR(class_dev)) {
-               ret = PTR_ERR(class_dev);
+       if (IS_ERR(device)) {
+               ret = PTR_ERR(device);
                printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
-                      "class_dev for minor %d, %s (err %d)\n",
+                      "device for minor %d, %s (err %d)\n",
                       minor, name, -ret);
                goto err_cdev;
        }
@@ -2481,29 +2474,29 @@ err_cdev:
 done:
        if (ret >= 0) {
                *cdevp = cdev;
-               *class_devp = class_dev;
+               *devp = device;
        } else {
                *cdevp = NULL;
-               *class_devp = NULL;
+               *devp = NULL;
        }
 
        return ret;
 }
 
 int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
-                   struct cdev **cdevp, struct class_device **class_devp)
+                   struct cdev **cdevp, struct device **devp)
 {
-       return init_cdev(minor, name, fops, cdevp, class_devp);
+       return init_cdev(minor, name, fops, cdevp, devp);
 }
 
 static void cleanup_cdev(struct cdev **cdevp,
-                        struct class_device **class_devp)
+                        struct device **devp)
 {
-       struct class_device *class_dev = *class_devp;
+       struct device *dev = *devp;
 
-       if (class_dev) {
-               class_device_unregister(class_dev);
-               *class_devp = NULL;
+       if (dev) {
+               device_unregister(dev);
+               *devp = NULL;
        }
 
        if (*cdevp) {
@@ -2513,13 +2506,13 @@ static void cleanup_cdev(struct cdev **cdevp,
 }
 
 void ipath_cdev_cleanup(struct cdev **cdevp,
-                       struct class_device **class_devp)
+                       struct device **devp)
 {
-       cleanup_cdev(cdevp, class_devp);
+       cleanup_cdev(cdevp, devp);
 }
 
 static struct cdev *wildcard_cdev;
-static struct class_device *wildcard_class_dev;
+static struct device *wildcard_dev;
 
 static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
 
@@ -2576,7 +2569,7 @@ int ipath_user_add(struct ipath_devdata *dd)
                        goto bail;
                }
                ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
-                               &wildcard_class_dev);
+                               &wildcard_dev);
                if (ret < 0) {
                        ipath_dev_err(dd, "Could not create wildcard "
                                      "minor: error %d\n", -ret);
@@ -2589,7 +2582,7 @@ int ipath_user_add(struct ipath_devdata *dd)
        snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
 
        ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
-                       &dd->user_cdev, &dd->user_class_dev);
+                       &dd->user_cdev, &dd->user_dev);
        if (ret < 0)
                ipath_dev_err(dd, "Could not create user minor %d, %s\n",
                              dd->ipath_unit + 1, name);
@@ -2604,13 +2597,13 @@ bail:
 
 void ipath_user_remove(struct ipath_devdata *dd)
 {
-       cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
+       cleanup_cdev(&dd->user_cdev, &dd->user_dev);
 
        if (atomic_dec_return(&user_count) == 0) {
                if (atomic_read(&user_setup) == 0)
                        goto bail;
 
-               cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
+               cleanup_cdev(&wildcard_cdev, &wildcard_dev);
                user_cleanup();
 
                atomic_set(&user_setup, 0);