]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/infiniband/hw/ipath/ipath_file_ops.c
IB/ipath: Misc changes to prepare for IB7220 introduction
[linux-2.6-omap-h63xx.git] / drivers / infiniband / hw / ipath / ipath_file_ops.c
index 5de3243a47c38bf023fc6fc0ee97dcdc69886fbb..b87d3126e4dc36aab63e26095adc2d22fc6e2843 100644 (file)
@@ -169,7 +169,7 @@ static int ipath_get_base_info(struct file *fp,
                kinfo->spi_piocnt = dd->ipath_pbufsport;
                kinfo->spi_piobufbase = (u64) pd->port_piobufs;
                kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
-                       dd->ipath_palign * pd->port_port;
+                       dd->ipath_ureg_align * pd->port_port;
        } else if (master) {
                kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
                                    (dd->ipath_pbufsport % subport_cnt);
@@ -184,9 +184,32 @@ static int ipath_get_base_info(struct file *fp,
                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_palign * pd->port_port;
+                       dd->ipath_ureg_align * pd->port_port;
                kinfo->spi_port_rcvegrbuf = kinfo->spi_rcv_egrbufs;
                kinfo->spi_port_rcvhdr_base = kinfo->spi_rcvhdr_base;
                kinfo->spi_port_rcvhdr_tailaddr = kinfo->spi_rcvhdr_tailaddr;
@@ -219,7 +242,12 @@ static int ipath_get_base_info(struct file *fp,
        kinfo->spi_pioalign = dd->ipath_palign;
 
        kinfo->spi_qpair = IPATH_KD_QP;
-       kinfo->spi_piosize = dd->ipath_ibmaxlen;
+       /*
+        * user mode PIO buffers are always 2KB, even when 4KB can
+        * be received, and sent via the kernel; this is ibmaxlen
+        * for 2K MTU.
+        */
+       kinfo->spi_piosize = dd->ipath_piosize2k - 2 * sizeof(u32);
        kinfo->spi_mtu = dd->ipath_ibmaxlen;    /* maxlen, not ibmtu */
        kinfo->spi_port = pd->port_port;
        kinfo->spi_subport = subport_fp(fp);
@@ -742,11 +770,12 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
                 * updated and correct itself, even in the face of software
                 * bugs.
                 */
-               *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
-               set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+               if (pd->port_rcvhdrtail_kvaddr)
+                       ipath_clear_rcvhdrtail(pd);
+               set_bit(dd->ipath_r_portenable_shift + pd->port_port,
                        &dd->ipath_rcvctrl);
        } else
-               clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+               clear_bit(dd->ipath_r_portenable_shift + pd->port_port,
                          &dd->ipath_rcvctrl);
        ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
                         dd->ipath_rcvctrl);
@@ -881,7 +910,7 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
 
        egrcnt = dd->ipath_rcvegrcnt;
        /* TID number offset for this port */
-       egroff = pd->port_port * egrcnt;
+       egroff = (pd->port_port - 1) * egrcnt + dd->ipath_p0_rcvegrcnt;
        egrsize = dd->ipath_rcvegrbufsize;
        ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
                   "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
@@ -1049,11 +1078,6 @@ static int mmap_piobufs(struct vm_area_struct *vma,
 
        phys = dd->ipath_physaddr + piobufs;
 
-       /*
-        * Don't mark this as non-cached, or we don't get the
-        * write combining behavior we want on the PIO buffers!
-        */
-
 #if defined(__powerpc__)
        /* There isn't a generic way to specify writethrough mappings */
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
@@ -1120,33 +1144,24 @@ bail:
 }
 
 /*
- * ipath_file_vma_nopage - handle a VMA page fault.
+ * ipath_file_vma_fault - handle a VMA page fault.
  */
-static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma,
-                                         unsigned long address, int *type)
+static int ipath_file_vma_fault(struct vm_area_struct *vma,
+                                       struct vm_fault *vmf)
 {
-       unsigned long offset = address - vma->vm_start;
-       struct page *page = NOPAGE_SIGBUS;
-       void *pageptr;
+       struct page *page;
 
-       /*
-        * Convert the vmalloc address into a struct page.
-        */
-       pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT));
-       page = vmalloc_to_page(pageptr);
+       page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT));
        if (!page)
-               goto out;
-
-       /* Increment the reference count. */
+               return VM_FAULT_SIGBUS;
        get_page(page);
-       if (type)
-               *type = VM_FAULT_MINOR;
-out:
-       return page;
+       vmf->page = page;
+
+       return 0;
 }
 
 static struct vm_operations_struct ipath_file_vm_ops = {
-       .nopage = ipath_file_vma_nopage,
+       .fault = ipath_file_vma_fault,
 };
 
 static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
@@ -1284,7 +1299,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
                goto bail;
        }
 
-       ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+       ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
        if (!pd->port_subport_cnt) {
                /* port is not shared */
                piocnt = dd->ipath_pbufsport;
@@ -1400,7 +1415,10 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
        pollflag = ipath_poll_hdrqfull(pd);
 
        head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
-       tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
+       if (pd->port_rcvhdrtail_kvaddr)
+               tail = ipath_get_rcvhdrtail(pd);
+       else
+               tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
 
        if (head != tail)
                pollflag |= POLLIN | POLLRDNORM;
@@ -1410,7 +1428,7 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
                /* flush waiting flag so we don't miss an event */
                wmb();
 
-               set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
+               set_bit(pd->port_port + dd->ipath_r_intravail_shift,
                        &dd->ipath_rcvctrl);
 
                ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
@@ -1608,6 +1626,9 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
                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);
                ipath_stats.sps_ports++;
                ret = 0;
        } else
@@ -1770,7 +1791,7 @@ static int find_shared_port(struct file *fp,
        for (ndev = 0; ndev < devmax; ndev++) {
                struct ipath_devdata *dd = ipath_lookup(ndev);
 
-               if (!dd)
+               if (!usable(dd))
                        continue;
                for (i = 1; i < dd->ipath_cfgports; i++) {
                        struct ipath_portdata *pd = dd->ipath_pd[i];
@@ -1790,6 +1811,7 @@ 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;
                        tidcursor_fp(fp) = 0;
                        pd->active_slaves |= 1 << subport_fp(fp);
                        ipath_cdbg(PROC,
@@ -1920,8 +1942,7 @@ static int ipath_do_user_init(struct file *fp,
         */
        head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
        ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
-       dd->ipath_lastegrheads[pd->port_port] = -1;
-       dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
+       pd->port_lastrcvhdrqtail = -1;
        ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
                pd->port_port, head32);
        pd->port_tidcursor = 0; /* start at beginning after open */
@@ -1932,20 +1953,25 @@ static int ipath_do_user_init(struct file *fp,
        pd->port_hdrqfull_poll = pd->port_hdrqfull;
 
        /*
-        * now enable the port; the tail registers will be written to memory
-        * by the chip as soon as it sees the write to
-        * dd->ipath_kregs->kr_rcvctrl.  The update only happens on
-        * transition from 0 to 1, so clear it first, then set it as part of
-        * enabling the port.  This will (very briefly) affect any other
-        * open ports, but it shouldn't be long enough to be an issue.
-        * We explictly set the in-memory copy to 0 beforehand, so we don't
-        * have to wait to be sure the DMA update has happened.
+        * Now enable the port for receive.
+        * For chips that are set to DMA the tail register to memory
+        * when they change (and when the update bit transitions from
+        * 0 to 1.  So for those chips, we turn it off and then back on.
+        * This will (very briefly) affect any other open ports, but the
+        * duration is very short, and therefore isn't an issue.  We
+        * explictly set the in-memory tail copy to 0 beforehand, so we
+        * don't have to wait to be sure the DMA update has happened
+        * (chip resets head/tail to 0 on transition to enable).
         */
-       *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
-       set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+       set_bit(dd->ipath_r_portenable_shift + pd->port_port,
                &dd->ipath_rcvctrl);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-                        dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
+       if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
+               if (pd->port_rcvhdrtail_kvaddr)
+                       ipath_clear_rcvhdrtail(pd);
+               ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+                       dd->ipath_rcvctrl &
+                       ~(1ULL << dd->ipath_r_tailupd_shift));
+       }
        ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
                         dd->ipath_rcvctrl);
        /* Notify any waiting slaves */
@@ -1973,14 +1999,15 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
        ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
                   pd->port_port);
        for (i = port_tidbase; i < maxtid; i++) {
-               if (!dd->ipath_pageshadow[i])
+               struct page *ps = dd->ipath_pageshadow[i];
+
+               if (!ps)
                        continue;
 
+               dd->ipath_pageshadow[i] = NULL;
                pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i],
                        PAGE_SIZE, PCI_DMA_FROMDEVICE);
-               ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
-                                                 1);
-               dd->ipath_pageshadow[i] = NULL;
+               ipath_release_user_pages_on_close(&ps, 1);
                cnt++;
                ipath_stats.sps_pageunlocks++;
        }
@@ -2022,6 +2049,7 @@ 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;
                mutex_unlock(&ipath_mutex);
                goto bail;
        }
@@ -2046,7 +2074,7 @@ static int ipath_close(struct inode *in, struct file *fp)
                        pd->port_rcvnowait = pd->port_pionowait = 0;
        }
        if (pd->port_flag) {
-               ipath_dbg("port %u port_flag still set to 0x%lx\n",
+               ipath_cdbg(PROC, "port %u port_flag set: 0x%lx\n",
                          pd->port_port, pd->port_flag);
                pd->port_flag = 0;
        }
@@ -2054,9 +2082,9 @@ 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(INFINIPATH_R_PORTENABLE_SHIFT + port,
+               clear_bit(dd->ipath_r_portenable_shift + port,
                          &dd->ipath_rcvctrl);
-               clear_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
+               clear_bit(pd->port_port + dd->ipath_r_intravail_shift,
                          &dd->ipath_rcvctrl);
                ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl,
                        dd->ipath_rcvctrl);
@@ -2083,6 +2111,7 @@ static int ipath_close(struct inode *in, struct file *fp)
 
                i = dd->ipath_pbufsport * (port - 1);
                ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
+               ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
 
                dd->ipath_f_clear_tids(dd, pd->port_port);
 
@@ -2147,17 +2176,6 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
        return ret;
 }
 
-static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
-{
-       u64 reg = dd->ipath_sendctrl;
-
-       clear_bit(IPATH_S_PIOBUFAVAILUPD, &reg);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, reg);
-       ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
-
-       return 0;
-}
-
 static ssize_t ipath_write(struct file *fp, const char __user *data,
                           size_t count, loff_t *off)
 {
@@ -2227,6 +2245,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
                dest = &cmd.cmd.poll_type;
                src = &ucmd->cmd.poll_type;
                break;
+       case IPATH_CMD_ARMLAUNCH_CTRL:
+               copy = sizeof(cmd.cmd.armlaunch_ctrl);
+               dest = &cmd.cmd.armlaunch_ctrl;
+               src = &ucmd->cmd.armlaunch_ctrl;
+               break;
        default:
                ret = -EINVAL;
                goto bail;
@@ -2297,11 +2320,17 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
                                           cmd.cmd.slave_mask_addr);
                break;
        case IPATH_CMD_PIOAVAILUPD:
-               ret = ipath_force_pio_avail_update(pd->port_dd);
+               ipath_force_pio_avail_update(pd->port_dd);
                break;
        case IPATH_CMD_POLL_TYPE:
                pd->poll_type = cmd.cmd.poll_type;
                break;
+       case IPATH_CMD_ARMLAUNCH_CTRL:
+               if (cmd.cmd.armlaunch_ctrl)
+                       ipath_enable_armlaunch(pd->port_dd);
+               else
+                       ipath_disable_armlaunch(pd->port_dd);
+               break;
        }
 
        if (ret >= 0)