llseek: automatically add .llseek fop
[linux-2.6.git] / drivers / infiniband / hw / ipath / ipath_file_ops.c
index d38ba29..6078992 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
 #include <linux/cdev.h>
 #include <linux/swap.h>
 #include <linux/vmalloc.h>
+#include <linux/slab.h>
 #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"
@@ -61,7 +63,8 @@ static const struct file_operations ipath_file_ops = {
        .open = ipath_open,
        .release = ipath_close,
        .poll = ipath_poll,
-       .mmap = ipath_mmap
+       .mmap = ipath_mmap,
+       .llseek = noop_llseek,
 };
 
 /*
@@ -173,47 +176,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;
@@ -244,8 +225,13 @@ static int ipath_get_base_info(struct file *fp,
                        (unsigned long long) kinfo->spi_subport_rcvhdr_base);
        }
 
-       kinfo->spi_pioindex = (kinfo->spi_piobufbase - dd->ipath_piobufbase) /
-               dd->ipath_palign;
+       /*
+        * All user buffers are 2KB buffers.  If we ever support
+        * giving 4KB buffers to user processes, this will need some
+        * work.
+        */
+       kinfo->spi_pioindex = (kinfo->spi_piobufbase -
+               (dd->ipath_piobufbase & 0xffffffff)) / dd->ipath_palign;
        kinfo->spi_pioalign = dd->ipath_palign;
 
        kinfo->spi_qpair = IPATH_KD_QP;
@@ -577,7 +563,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);
@@ -1167,7 +1153,7 @@ static int ipath_file_vma_fault(struct vm_area_struct *vma,
        return 0;
 }
 
-static struct vm_operations_struct ipath_file_vm_ops = {
+static const struct vm_operations_struct ipath_file_vm_ops = {
        .fault = ipath_file_vma_fault,
 };
 
@@ -1309,19 +1295,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 +1617,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;
-               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);
+               pd->port_pid = get_pid(task_pid(current));
+               strlcpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
                ipath_stats.sps_ports++;
                ret = 0;
        } else
@@ -1698,7 +1681,7 @@ static int find_best_unit(struct file *fp,
         * InfiniPath chip to that processor (we assume reasonable connectivity,
         * for now).  This code assumes that if affinity has been set
         * before this point, that at most one cpu is set; for now this
-        * is reasonable.  I check for both cpus_empty() and cpus_full(),
+        * is reasonable.  I check for both cpumask_empty() and cpumask_full(),
         * in case some kernel variant sets none of the bits when no
         * affinity is set.  2.6.11 and 12 kernels have all present
         * cpus set.  Some day we'll have to fix it up further to handle
@@ -1707,11 +1690,11 @@ static int find_best_unit(struct file *fp,
         * information.  There may be some issues with dual core numbering
         * as well.  This needs more work prior to release.
         */
-       if (!cpus_empty(current->cpus_allowed) &&
-           !cpus_full(current->cpus_allowed)) {
+       if (!cpumask_empty(&current->cpus_allowed) &&
+           !cpumask_full(&current->cpus_allowed)) {
                int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
                for (i = 0; i < ncpus; i++)
-                       if (cpu_isset(i, current->cpus_allowed)) {
+                       if (cpumask_test_cpu(i, &current->cpus_allowed)) {
                                ipath_cdbg(PROC, "%s[%u] affinity set for "
                                           "cpu %d/%d\n", current->comm,
                                           current->pid, i, ncpus);
@@ -1818,14 +1801,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;
@@ -1938,11 +1922,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
@@ -2049,14 +2047,16 @@ static int ipath_close(struct inode *in, struct file *fp)
        struct ipath_filedata *fd;
        struct ipath_portdata *pd;
        struct ipath_devdata *dd;
+       unsigned long flags;
        unsigned port;
+       struct pid *pid;
 
        ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n",
                   (long)in->i_rdev, fp->private_data);
 
        mutex_lock(&ipath_mutex);
 
-       fd = (struct ipath_filedata *) fp->private_data;
+       fd = fp->private_data;
        fp->private_data = NULL;
        pd = fd->pd;
        if (!pd) {
@@ -2077,18 +2077,18 @@ 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;
        }
+       /* early; no interrupt users after this */
+       spin_lock_irqsave(&dd->ipath_uctxt_lock, flags);
        port = pd->port_port;
-
-       if (pd->port_hdrqfull) {
-               ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
-                          "during run\n", pd->port_comm, pd->port_pid,
-                          pd->port_hdrqfull);
-               pd->port_hdrqfull = 0;
-       }
+       dd->ipath_pd[port] = NULL;
+       pid = pd->port_pid;
+       pd->port_pid = NULL;
+       spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags);
 
        if (pd->port_rcvwait_to || pd->port_piowait_to
            || pd->port_rcvnowait || pd->port_pionowait) {
@@ -2107,7 +2107,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 +2135,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,12 +2145,11 @@ 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(pid),
                           dd->ipath_unit, port);
        }
 
-       pd->port_pid = 0;
-       dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */
+       put_pid(pid);
        mutex_unlock(&ipath_mutex);
        ipath_free_pddata(dd, pd); /* after releasing the mutex */
 
@@ -2434,11 +2432,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 +2460,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, NULL, 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 +2479,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 +2511,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 +2574,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 +2587,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 +2602,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);