diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_file_ops.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_file_ops.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 1b232b23dbfc..17d4e970abd9 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -1930,22 +1930,25 @@ static int ipath_do_user_init(struct file *fp, | |||
1930 | pd->port_hdrqfull_poll = pd->port_hdrqfull; | 1930 | pd->port_hdrqfull_poll = pd->port_hdrqfull; |
1931 | 1931 | ||
1932 | /* | 1932 | /* |
1933 | * now enable the port; the tail registers will be written to memory | 1933 | * Now enable the port for receive. |
1934 | * by the chip as soon as it sees the write to | 1934 | * For chips that are set to DMA the tail register to memory |
1935 | * dd->ipath_kregs->kr_rcvctrl. The update only happens on | 1935 | * when they change (and when the update bit transitions from |
1936 | * transition from 0 to 1, so clear it first, then set it as part of | 1936 | * 0 to 1. So for those chips, we turn it off and then back on. |
1937 | * enabling the port. This will (very briefly) affect any other | 1937 | * This will (very briefly) affect any other open ports, but the |
1938 | * open ports, but it shouldn't be long enough to be an issue. | 1938 | * duration is very short, and therefore isn't an issue. We |
1939 | * We explictly set the in-memory copy to 0 beforehand, so we don't | 1939 | * explictly set the in-memory tail copy to 0 beforehand, so we |
1940 | * have to wait to be sure the DMA update has happened. | 1940 | * don't have to wait to be sure the DMA update has happened |
1941 | * (chip resets head/tail to 0 on transition to enable). | ||
1941 | */ | 1942 | */ |
1942 | if (pd->port_rcvhdrtail_kvaddr) | ||
1943 | ipath_clear_rcvhdrtail(pd); | ||
1944 | set_bit(dd->ipath_r_portenable_shift + pd->port_port, | 1943 | set_bit(dd->ipath_r_portenable_shift + pd->port_port, |
1945 | &dd->ipath_rcvctrl); | 1944 | &dd->ipath_rcvctrl); |
1946 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1945 | if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) { |
1946 | if (pd->port_rcvhdrtail_kvaddr) | ||
1947 | ipath_clear_rcvhdrtail(pd); | ||
1948 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
1947 | dd->ipath_rcvctrl & | 1949 | dd->ipath_rcvctrl & |
1948 | ~(1ULL << dd->ipath_r_tailupd_shift)); | 1950 | ~(1ULL << dd->ipath_r_tailupd_shift)); |
1951 | } | ||
1949 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1952 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, |
1950 | dd->ipath_rcvctrl); | 1953 | dd->ipath_rcvctrl); |
1951 | /* Notify any waiting slaves */ | 1954 | /* Notify any waiting slaves */ |
@@ -1973,14 +1976,15 @@ static void unlock_expected_tids(struct ipath_portdata *pd) | |||
1973 | ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n", | 1976 | ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n", |
1974 | pd->port_port); | 1977 | pd->port_port); |
1975 | for (i = port_tidbase; i < maxtid; i++) { | 1978 | for (i = port_tidbase; i < maxtid; i++) { |
1976 | if (!dd->ipath_pageshadow[i]) | 1979 | struct page *ps = dd->ipath_pageshadow[i]; |
1980 | |||
1981 | if (!ps) | ||
1977 | continue; | 1982 | continue; |
1978 | 1983 | ||
1984 | dd->ipath_pageshadow[i] = NULL; | ||
1979 | pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i], | 1985 | pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i], |
1980 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | 1986 | PAGE_SIZE, PCI_DMA_FROMDEVICE); |
1981 | ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i], | 1987 | ipath_release_user_pages_on_close(&ps, 1); |
1982 | 1); | ||
1983 | dd->ipath_pageshadow[i] = NULL; | ||
1984 | cnt++; | 1988 | cnt++; |
1985 | ipath_stats.sps_pageunlocks++; | 1989 | ipath_stats.sps_pageunlocks++; |
1986 | } | 1990 | } |