diff options
author | Bryan O'Sullivan <bos@pathscale.com> | 2006-09-28 12:00:13 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-28 14:16:53 -0400 |
commit | 1fd3b40fde3bfacdf742cadfe99cfd47ffd05219 (patch) | |
tree | 5f08e8046319dc31d5abdec16764b7889feb9b74 | |
parent | 076fafcdee37c87564abd1ad993e17d77fc32daa (diff) |
IB/ipath: Improved support for PowerPC
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 60 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_file_ops.c | 55 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 56 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 20 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_user_pages.c | 56 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_wc_ppc64.c | 20 |
8 files changed, 198 insertions, 73 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 467816043d10..68fc9b5a4ad8 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -755,8 +755,8 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len) | |||
755 | static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum, | 755 | static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum, |
756 | int err) | 756 | int err) |
757 | { | 757 | { |
758 | return dd->ipath_port0_skbs ? | 758 | return dd->ipath_port0_skbinfo ? |
759 | (void *)dd->ipath_port0_skbs[bufnum]->data : NULL; | 759 | (void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL; |
760 | } | 760 | } |
761 | 761 | ||
762 | /** | 762 | /** |
@@ -778,31 +778,34 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, | |||
778 | */ | 778 | */ |
779 | 779 | ||
780 | /* | 780 | /* |
781 | * We need 4 extra bytes for unaligned transfer copying | 781 | * We need 2 extra bytes for ipath_ether data sent in the |
782 | * key header. In order to keep everything dword aligned, | ||
783 | * we'll reserve 4 bytes. | ||
782 | */ | 784 | */ |
785 | len = dd->ipath_ibmaxlen + 4; | ||
786 | |||
783 | if (dd->ipath_flags & IPATH_4BYTE_TID) { | 787 | if (dd->ipath_flags & IPATH_4BYTE_TID) { |
784 | /* we need a 4KB multiple alignment, and there is no way | 788 | /* We need a 2KB multiple alignment, and there is no way |
785 | * to do it except to allocate extra and then skb_reserve | 789 | * to do it except to allocate extra and then skb_reserve |
786 | * enough to bring it up to the right alignment. | 790 | * enough to bring it up to the right alignment. |
787 | */ | 791 | */ |
788 | len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1; | 792 | len += 2047; |
789 | } | 793 | } |
790 | else | 794 | |
791 | len = dd->ipath_ibmaxlen + 4; | ||
792 | skb = __dev_alloc_skb(len, gfp_mask); | 795 | skb = __dev_alloc_skb(len, gfp_mask); |
793 | if (!skb) { | 796 | if (!skb) { |
794 | ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n", | 797 | ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n", |
795 | len); | 798 | len); |
796 | goto bail; | 799 | goto bail; |
797 | } | 800 | } |
801 | |||
802 | skb_reserve(skb, 4); | ||
803 | |||
798 | if (dd->ipath_flags & IPATH_4BYTE_TID) { | 804 | if (dd->ipath_flags & IPATH_4BYTE_TID) { |
799 | u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4); | 805 | u32 una = (unsigned long)skb->data & 2047; |
800 | if (una) | 806 | if (una) |
801 | skb_reserve(skb, 4 + (1 << 11) - una); | 807 | skb_reserve(skb, 2048 - una); |
802 | else | 808 | } |
803 | skb_reserve(skb, 4); | ||
804 | } else | ||
805 | skb_reserve(skb, 4); | ||
806 | 809 | ||
807 | bail: | 810 | bail: |
808 | return skb; | 811 | return skb; |
@@ -1345,8 +1348,9 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1345 | ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " | 1348 | ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " |
1346 | "hdrtailaddr@%p %llx physical\n", | 1349 | "hdrtailaddr@%p %llx physical\n", |
1347 | pd->port_port, pd->port_rcvhdrq, | 1350 | pd->port_port, pd->port_rcvhdrq, |
1348 | pd->port_rcvhdrq_phys, pd->port_rcvhdrtail_kvaddr, | 1351 | (unsigned long long) pd->port_rcvhdrq_phys, |
1349 | (unsigned long long)pd->port_rcvhdrqtailaddr_phys); | 1352 | pd->port_rcvhdrtail_kvaddr, (unsigned long long) |
1353 | pd->port_rcvhdrqtailaddr_phys); | ||
1350 | 1354 | ||
1351 | /* clear for security and sanity on each use */ | 1355 | /* clear for security and sanity on each use */ |
1352 | memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size); | 1356 | memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size); |
@@ -1827,17 +1831,22 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) | |||
1827 | kfree(pd->port_rcvegrbuf_phys); | 1831 | kfree(pd->port_rcvegrbuf_phys); |
1828 | pd->port_rcvegrbuf_phys = NULL; | 1832 | pd->port_rcvegrbuf_phys = NULL; |
1829 | pd->port_rcvegrbuf_chunks = 0; | 1833 | pd->port_rcvegrbuf_chunks = 0; |
1830 | } else if (pd->port_port == 0 && dd->ipath_port0_skbs) { | 1834 | } else if (pd->port_port == 0 && dd->ipath_port0_skbinfo) { |
1831 | unsigned e; | 1835 | unsigned e; |
1832 | struct sk_buff **skbs = dd->ipath_port0_skbs; | 1836 | struct ipath_skbinfo *skbinfo = dd->ipath_port0_skbinfo; |
1833 | 1837 | ||
1834 | dd->ipath_port0_skbs = NULL; | 1838 | dd->ipath_port0_skbinfo = NULL; |
1835 | ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs " | 1839 | ipath_cdbg(VERBOSE, "free closed port %d " |
1836 | "@ %p\n", pd->port_port, skbs); | 1840 | "ipath_port0_skbinfo @ %p\n", pd->port_port, |
1841 | skbinfo); | ||
1837 | for (e = 0; e < dd->ipath_rcvegrcnt; e++) | 1842 | for (e = 0; e < dd->ipath_rcvegrcnt; e++) |
1838 | if (skbs[e]) | 1843 | if (skbinfo[e].skb) { |
1839 | dev_kfree_skb(skbs[e]); | 1844 | pci_unmap_single(dd->pcidev, skbinfo[e].phys, |
1840 | vfree(skbs); | 1845 | dd->ipath_ibmaxlen, |
1846 | PCI_DMA_FROMDEVICE); | ||
1847 | dev_kfree_skb(skbinfo[e].skb); | ||
1848 | } | ||
1849 | vfree(skbinfo); | ||
1841 | } | 1850 | } |
1842 | kfree(pd->port_tid_pg_list); | 1851 | kfree(pd->port_tid_pg_list); |
1843 | vfree(pd->subport_uregbase); | 1852 | vfree(pd->subport_uregbase); |
@@ -1934,7 +1943,7 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1934 | 1943 | ||
1935 | if (dd->ipath_pioavailregs_dma) { | 1944 | if (dd->ipath_pioavailregs_dma) { |
1936 | dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, | 1945 | dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, |
1937 | dd->ipath_pioavailregs_dma, | 1946 | (void *) dd->ipath_pioavailregs_dma, |
1938 | dd->ipath_pioavailregs_phys); | 1947 | dd->ipath_pioavailregs_phys); |
1939 | dd->ipath_pioavailregs_dma = NULL; | 1948 | dd->ipath_pioavailregs_dma = NULL; |
1940 | } | 1949 | } |
@@ -1947,6 +1956,7 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1947 | 1956 | ||
1948 | if (dd->ipath_pageshadow) { | 1957 | if (dd->ipath_pageshadow) { |
1949 | struct page **tmpp = dd->ipath_pageshadow; | 1958 | struct page **tmpp = dd->ipath_pageshadow; |
1959 | dma_addr_t *tmpd = dd->ipath_physshadow; | ||
1950 | int i, cnt = 0; | 1960 | int i, cnt = 0; |
1951 | 1961 | ||
1952 | ipath_cdbg(VERBOSE, "Unlocking any expTID pages still " | 1962 | ipath_cdbg(VERBOSE, "Unlocking any expTID pages still " |
@@ -1957,6 +1967,8 @@ static void cleanup_device(struct ipath_devdata *dd) | |||
1957 | for (i = port_tidbase; i < maxtid; i++) { | 1967 | for (i = port_tidbase; i < maxtid; i++) { |
1958 | if (!tmpp[i]) | 1968 | if (!tmpp[i]) |
1959 | continue; | 1969 | continue; |
1970 | pci_unmap_page(dd->pcidev, tmpd[i], | ||
1971 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
1960 | ipath_release_user_pages(&tmpp[i], 1); | 1972 | ipath_release_user_pages(&tmpp[i], 1); |
1961 | tmpp[i] = NULL; | 1973 | tmpp[i] = NULL; |
1962 | cnt++; | 1974 | cnt++; |
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index d4fc4118ddd5..64221b937762 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -364,11 +364,14 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp, | |||
364 | "vaddr %lx\n", i, tid + tidoff, vaddr); | 364 | "vaddr %lx\n", i, tid + tidoff, vaddr); |
365 | /* we "know" system pages and TID pages are same size */ | 365 | /* we "know" system pages and TID pages are same size */ |
366 | dd->ipath_pageshadow[porttid + tid] = pagep[i]; | 366 | dd->ipath_pageshadow[porttid + tid] = pagep[i]; |
367 | dd->ipath_physshadow[porttid + tid] = ipath_map_page( | ||
368 | dd->pcidev, pagep[i], 0, PAGE_SIZE, | ||
369 | PCI_DMA_FROMDEVICE); | ||
367 | /* | 370 | /* |
368 | * don't need atomic or it's overhead | 371 | * don't need atomic or it's overhead |
369 | */ | 372 | */ |
370 | __set_bit(tid, tidmap); | 373 | __set_bit(tid, tidmap); |
371 | physaddr = page_to_phys(pagep[i]); | 374 | physaddr = dd->ipath_physshadow[porttid + tid]; |
372 | ipath_stats.sps_pagelocks++; | 375 | ipath_stats.sps_pagelocks++; |
373 | ipath_cdbg(VERBOSE, | 376 | ipath_cdbg(VERBOSE, |
374 | "TID %u, vaddr %lx, physaddr %llx pgp %p\n", | 377 | "TID %u, vaddr %lx, physaddr %llx pgp %p\n", |
@@ -402,6 +405,9 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp, | |||
402 | tid); | 405 | tid); |
403 | dd->ipath_f_put_tid(dd, &tidbase[tid], 1, | 406 | dd->ipath_f_put_tid(dd, &tidbase[tid], 1, |
404 | dd->ipath_tidinvalid); | 407 | dd->ipath_tidinvalid); |
408 | pci_unmap_page(dd->pcidev, | ||
409 | dd->ipath_physshadow[porttid + tid], | ||
410 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
405 | dd->ipath_pageshadow[porttid + tid] = NULL; | 411 | dd->ipath_pageshadow[porttid + tid] = NULL; |
406 | ipath_stats.sps_pageunlocks++; | 412 | ipath_stats.sps_pageunlocks++; |
407 | } | 413 | } |
@@ -515,6 +521,9 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport, | |||
515 | pd->port_pid, tid); | 521 | pd->port_pid, tid); |
516 | dd->ipath_f_put_tid(dd, &tidbase[tid], 1, | 522 | dd->ipath_f_put_tid(dd, &tidbase[tid], 1, |
517 | dd->ipath_tidinvalid); | 523 | dd->ipath_tidinvalid); |
524 | pci_unmap_page(dd->pcidev, | ||
525 | dd->ipath_physshadow[porttid + tid], | ||
526 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
518 | ipath_release_user_pages( | 527 | ipath_release_user_pages( |
519 | &dd->ipath_pageshadow[porttid + tid], 1); | 528 | &dd->ipath_pageshadow[porttid + tid], 1); |
520 | dd->ipath_pageshadow[porttid + tid] = NULL; | 529 | dd->ipath_pageshadow[porttid + tid] = NULL; |
@@ -711,7 +720,7 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport, | |||
711 | * updated and correct itself, even in the face of software | 720 | * updated and correct itself, even in the face of software |
712 | * bugs. | 721 | * bugs. |
713 | */ | 722 | */ |
714 | *pd->port_rcvhdrtail_kvaddr = 0; | 723 | *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0; |
715 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | 724 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, |
716 | &dd->ipath_rcvctrl); | 725 | &dd->ipath_rcvctrl); |
717 | } else | 726 | } else |
@@ -923,11 +932,11 @@ bail: | |||
923 | 932 | ||
924 | /* common code for the mappings on dma_alloc_coherent mem */ | 933 | /* common code for the mappings on dma_alloc_coherent mem */ |
925 | static int ipath_mmap_mem(struct vm_area_struct *vma, | 934 | static int ipath_mmap_mem(struct vm_area_struct *vma, |
926 | struct ipath_portdata *pd, unsigned len, | 935 | struct ipath_portdata *pd, unsigned len, int write_ok, |
927 | int write_ok, dma_addr_t addr, char *what) | 936 | void *kvaddr, char *what) |
928 | { | 937 | { |
929 | struct ipath_devdata *dd = pd->port_dd; | 938 | struct ipath_devdata *dd = pd->port_dd; |
930 | unsigned pfn = (unsigned long)addr >> PAGE_SHIFT; | 939 | unsigned long pfn; |
931 | int ret; | 940 | int ret; |
932 | 941 | ||
933 | if ((vma->vm_end - vma->vm_start) > len) { | 942 | if ((vma->vm_end - vma->vm_start) > len) { |
@@ -950,17 +959,17 @@ static int ipath_mmap_mem(struct vm_area_struct *vma, | |||
950 | vma->vm_flags &= ~VM_MAYWRITE; | 959 | vma->vm_flags &= ~VM_MAYWRITE; |
951 | } | 960 | } |
952 | 961 | ||
962 | pfn = virt_to_phys(kvaddr) >> PAGE_SHIFT; | ||
953 | ret = remap_pfn_range(vma, vma->vm_start, pfn, | 963 | ret = remap_pfn_range(vma, vma->vm_start, pfn, |
954 | len, vma->vm_page_prot); | 964 | len, vma->vm_page_prot); |
955 | if (ret) | 965 | if (ret) |
956 | dev_info(&dd->pcidev->dev, | 966 | dev_info(&dd->pcidev->dev, "%s port%u mmap of %lx, %x " |
957 | "%s port%u mmap of %lx, %x bytes r%c failed: %d\n", | 967 | "bytes r%c failed: %d\n", what, pd->port_port, |
958 | what, pd->port_port, (unsigned long)addr, len, | 968 | pfn, len, write_ok?'w':'o', ret); |
959 | write_ok?'w':'o', ret); | ||
960 | else | 969 | else |
961 | ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes r%c\n", | 970 | ipath_cdbg(VERBOSE, "%s port%u mmaped %lx, %x bytes " |
962 | what, pd->port_port, (unsigned long)addr, len, | 971 | "r%c\n", what, pd->port_port, pfn, len, |
963 | write_ok?'w':'o'); | 972 | write_ok?'w':'o'); |
964 | bail: | 973 | bail: |
965 | return ret; | 974 | return ret; |
966 | } | 975 | } |
@@ -1049,7 +1058,7 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma, | |||
1049 | struct ipath_devdata *dd = pd->port_dd; | 1058 | struct ipath_devdata *dd = pd->port_dd; |
1050 | unsigned long start, size; | 1059 | unsigned long start, size; |
1051 | size_t total_size, i; | 1060 | size_t total_size, i; |
1052 | dma_addr_t *phys; | 1061 | unsigned long pfn; |
1053 | int ret; | 1062 | int ret; |
1054 | 1063 | ||
1055 | size = pd->port_rcvegrbuf_size; | 1064 | size = pd->port_rcvegrbuf_size; |
@@ -1073,11 +1082,11 @@ static int mmap_rcvegrbufs(struct vm_area_struct *vma, | |||
1073 | vma->vm_flags &= ~VM_MAYWRITE; | 1082 | vma->vm_flags &= ~VM_MAYWRITE; |
1074 | 1083 | ||
1075 | start = vma->vm_start; | 1084 | start = vma->vm_start; |
1076 | phys = pd->port_rcvegrbuf_phys; | ||
1077 | 1085 | ||
1078 | for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) { | 1086 | for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) { |
1079 | ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT, | 1087 | pfn = virt_to_phys(pd->port_rcvegrbuf[i]) >> PAGE_SHIFT; |
1080 | size, vma->vm_page_prot); | 1088 | ret = remap_pfn_range(vma, start, pfn, size, |
1089 | vma->vm_page_prot); | ||
1081 | if (ret < 0) | 1090 | if (ret < 0) |
1082 | goto bail; | 1091 | goto bail; |
1083 | } | 1092 | } |
@@ -1290,7 +1299,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1290 | else if (pgaddr == dd->ipath_pioavailregs_phys) | 1299 | else if (pgaddr == dd->ipath_pioavailregs_phys) |
1291 | /* in-memory copy of pioavail registers */ | 1300 | /* in-memory copy of pioavail registers */ |
1292 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | 1301 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, |
1293 | dd->ipath_pioavailregs_phys, | 1302 | (void *) dd->ipath_pioavailregs_dma, |
1294 | "pioavail registers"); | 1303 | "pioavail registers"); |
1295 | else if (subport_fp(fp)) | 1304 | else if (subport_fp(fp)) |
1296 | /* Subports don't mmap the physical receive buffers */ | 1305 | /* Subports don't mmap the physical receive buffers */ |
@@ -1304,12 +1313,12 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) | |||
1304 | * from an i/o perspective. | 1313 | * from an i/o perspective. |
1305 | */ | 1314 | */ |
1306 | ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1, | 1315 | ret = ipath_mmap_mem(vma, pd, pd->port_rcvhdrq_size, 1, |
1307 | pd->port_rcvhdrq_phys, | 1316 | pd->port_rcvhdrq, |
1308 | "rcvhdrq"); | 1317 | "rcvhdrq"); |
1309 | else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys) | 1318 | else if (pgaddr == (u64) pd->port_rcvhdrqtailaddr_phys) |
1310 | /* in-memory copy of rcvhdrq tail register */ | 1319 | /* in-memory copy of rcvhdrq tail register */ |
1311 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, | 1320 | ret = ipath_mmap_mem(vma, pd, PAGE_SIZE, 0, |
1312 | pd->port_rcvhdrqtailaddr_phys, | 1321 | pd->port_rcvhdrtail_kvaddr, |
1313 | "rcvhdrq tail"); | 1322 | "rcvhdrq tail"); |
1314 | else | 1323 | else |
1315 | ret = -EINVAL; | 1324 | ret = -EINVAL; |
@@ -1802,7 +1811,7 @@ static int ipath_do_user_init(struct file *fp, | |||
1802 | * We explictly set the in-memory copy to 0 beforehand, so we don't | 1811 | * We explictly set the in-memory copy to 0 beforehand, so we don't |
1803 | * have to wait to be sure the DMA update has happened. | 1812 | * have to wait to be sure the DMA update has happened. |
1804 | */ | 1813 | */ |
1805 | *pd->port_rcvhdrtail_kvaddr = 0ULL; | 1814 | *(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL; |
1806 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, | 1815 | set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port, |
1807 | &dd->ipath_rcvctrl); | 1816 | &dd->ipath_rcvctrl); |
1808 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1817 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, |
@@ -1832,6 +1841,8 @@ static void unlock_expected_tids(struct ipath_portdata *pd) | |||
1832 | if (!dd->ipath_pageshadow[i]) | 1841 | if (!dd->ipath_pageshadow[i]) |
1833 | continue; | 1842 | continue; |
1834 | 1843 | ||
1844 | pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i], | ||
1845 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
1835 | ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i], | 1846 | ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i], |
1836 | 1); | 1847 | 1); |
1837 | dd->ipath_pageshadow[i] = NULL; | 1848 | dd->ipath_pageshadow[i] = NULL; |
@@ -1936,14 +1947,14 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
1936 | i = dd->ipath_pbufsport * (port - 1); | 1947 | i = dd->ipath_pbufsport * (port - 1); |
1937 | ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport); | 1948 | ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport); |
1938 | 1949 | ||
1950 | dd->ipath_f_clear_tids(dd, pd->port_port); | ||
1951 | |||
1939 | if (dd->ipath_pageshadow) | 1952 | if (dd->ipath_pageshadow) |
1940 | unlock_expected_tids(pd); | 1953 | unlock_expected_tids(pd); |
1941 | ipath_stats.sps_ports--; | 1954 | ipath_stats.sps_ports--; |
1942 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", | 1955 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", |
1943 | pd->port_comm, pd->port_pid, | 1956 | pd->port_comm, pd->port_pid, |
1944 | dd->ipath_unit, port); | 1957 | dd->ipath_unit, port); |
1945 | |||
1946 | dd->ipath_f_clear_tids(dd, pd->port_port); | ||
1947 | } | 1958 | } |
1948 | 1959 | ||
1949 | pd->port_pid = 0; | 1960 | pd->port_pid = 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index ac5cbe27c068..08a44dd9ed6f 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
@@ -1113,7 +1113,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr, | |||
1113 | if (pa != dd->ipath_tidinvalid) { | 1113 | if (pa != dd->ipath_tidinvalid) { |
1114 | if (pa & ((1U << 11) - 1)) { | 1114 | if (pa & ((1U << 11) - 1)) { |
1115 | dev_info(&dd->pcidev->dev, "BUG: physaddr %lx " | 1115 | dev_info(&dd->pcidev->dev, "BUG: physaddr %lx " |
1116 | "not 4KB aligned!\n", pa); | 1116 | "not 2KB aligned!\n", pa); |
1117 | return; | 1117 | return; |
1118 | } | 1118 | } |
1119 | pa >>= 11; | 1119 | pa >>= 11; |
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 44669dc2e22d..d819cca524cd 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -88,13 +88,13 @@ MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); | |||
88 | static int create_port0_egr(struct ipath_devdata *dd) | 88 | static int create_port0_egr(struct ipath_devdata *dd) |
89 | { | 89 | { |
90 | unsigned e, egrcnt; | 90 | unsigned e, egrcnt; |
91 | struct sk_buff **skbs; | 91 | struct ipath_skbinfo *skbinfo; |
92 | int ret; | 92 | int ret; |
93 | 93 | ||
94 | egrcnt = dd->ipath_rcvegrcnt; | 94 | egrcnt = dd->ipath_rcvegrcnt; |
95 | 95 | ||
96 | skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt); | 96 | skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt); |
97 | if (skbs == NULL) { | 97 | if (skbinfo == NULL) { |
98 | ipath_dev_err(dd, "allocation error for eager TID " | 98 | ipath_dev_err(dd, "allocation error for eager TID " |
99 | "skb array\n"); | 99 | "skb array\n"); |
100 | ret = -ENOMEM; | 100 | ret = -ENOMEM; |
@@ -109,13 +109,13 @@ static int create_port0_egr(struct ipath_devdata *dd) | |||
109 | * 4 bytes so that the data buffer stays word aligned. | 109 | * 4 bytes so that the data buffer stays word aligned. |
110 | * See ipath_kreceive() for more details. | 110 | * See ipath_kreceive() for more details. |
111 | */ | 111 | */ |
112 | skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL); | 112 | skbinfo[e].skb = ipath_alloc_skb(dd, GFP_KERNEL); |
113 | if (!skbs[e]) { | 113 | if (!skbinfo[e].skb) { |
114 | ipath_dev_err(dd, "SKB allocation error for " | 114 | ipath_dev_err(dd, "SKB allocation error for " |
115 | "eager TID %u\n", e); | 115 | "eager TID %u\n", e); |
116 | while (e != 0) | 116 | while (e != 0) |
117 | dev_kfree_skb(skbs[--e]); | 117 | dev_kfree_skb(skbinfo[--e].skb); |
118 | vfree(skbs); | 118 | vfree(skbinfo); |
119 | ret = -ENOMEM; | 119 | ret = -ENOMEM; |
120 | goto bail; | 120 | goto bail; |
121 | } | 121 | } |
@@ -124,14 +124,17 @@ static int create_port0_egr(struct ipath_devdata *dd) | |||
124 | * After loop above, so we can test non-NULL to see if ready | 124 | * After loop above, so we can test non-NULL to see if ready |
125 | * to use at receive, etc. | 125 | * to use at receive, etc. |
126 | */ | 126 | */ |
127 | dd->ipath_port0_skbs = skbs; | 127 | dd->ipath_port0_skbinfo = skbinfo; |
128 | 128 | ||
129 | for (e = 0; e < egrcnt; e++) { | 129 | for (e = 0; e < egrcnt; e++) { |
130 | unsigned long phys = | 130 | dd->ipath_port0_skbinfo[e].phys = |
131 | virt_to_phys(dd->ipath_port0_skbs[e]->data); | 131 | ipath_map_single(dd->pcidev, |
132 | dd->ipath_port0_skbinfo[e].skb->data, | ||
133 | dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE); | ||
132 | dd->ipath_f_put_tid(dd, e + (u64 __iomem *) | 134 | dd->ipath_f_put_tid(dd, e + (u64 __iomem *) |
133 | ((char __iomem *) dd->ipath_kregbase + | 135 | ((char __iomem *) dd->ipath_kregbase + |
134 | dd->ipath_rcvegrbase), 0, phys); | 136 | dd->ipath_rcvegrbase), 0, |
137 | dd->ipath_port0_skbinfo[e].phys); | ||
135 | } | 138 | } |
136 | 139 | ||
137 | ret = 0; | 140 | ret = 0; |
@@ -432,16 +435,33 @@ done: | |||
432 | */ | 435 | */ |
433 | static void init_shadow_tids(struct ipath_devdata *dd) | 436 | static void init_shadow_tids(struct ipath_devdata *dd) |
434 | { | 437 | { |
435 | dd->ipath_pageshadow = (struct page **) | 438 | struct page **pages; |
436 | vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * | 439 | dma_addr_t *addrs; |
440 | |||
441 | pages = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
437 | sizeof(struct page *)); | 442 | sizeof(struct page *)); |
438 | if (!dd->ipath_pageshadow) | 443 | if (!pages) { |
439 | ipath_dev_err(dd, "failed to allocate shadow page * " | 444 | ipath_dev_err(dd, "failed to allocate shadow page * " |
440 | "array, no expected sends!\n"); | 445 | "array, no expected sends!\n"); |
441 | else | 446 | dd->ipath_pageshadow = NULL; |
442 | memset(dd->ipath_pageshadow, 0, | 447 | return; |
443 | dd->ipath_cfgports * dd->ipath_rcvtidcnt * | 448 | } |
444 | sizeof(struct page *)); | 449 | |
450 | addrs = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
451 | sizeof(dma_addr_t)); | ||
452 | if (!addrs) { | ||
453 | ipath_dev_err(dd, "failed to allocate shadow dma handle " | ||
454 | "array, no expected sends!\n"); | ||
455 | vfree(dd->ipath_pageshadow); | ||
456 | dd->ipath_pageshadow = NULL; | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | memset(pages, 0, dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
461 | sizeof(struct page *)); | ||
462 | |||
463 | dd->ipath_pageshadow = pages; | ||
464 | dd->ipath_physshadow = addrs; | ||
445 | } | 465 | } |
446 | 466 | ||
447 | static void enable_chip(struct ipath_devdata *dd, | 467 | static void enable_chip(struct ipath_devdata *dd, |
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 54b3dbc8195a..f4d8aafc6306 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -605,7 +605,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
605 | * don't report same point multiple times, | 605 | * don't report same point multiple times, |
606 | * except kernel | 606 | * except kernel |
607 | */ | 607 | */ |
608 | tl = (u32) * pd->port_rcvhdrtail_kvaddr; | 608 | tl = *(u64 *) pd->port_rcvhdrtail_kvaddr; |
609 | if (tl == dd->ipath_lastrcvhdrqtails[i]) | 609 | if (tl == dd->ipath_lastrcvhdrqtails[i]) |
610 | continue; | 610 | continue; |
611 | hd = ipath_read_ureg32(dd, ur_rcvhdrhead, | 611 | hd = ipath_read_ureg32(dd, ur_rcvhdrhead, |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 96e2bd8fb5f8..2a0e9a430634 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -39,6 +39,8 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/pci.h> | ||
43 | #include <linux/dma-mapping.h> | ||
42 | #include <asm/io.h> | 44 | #include <asm/io.h> |
43 | 45 | ||
44 | #include "ipath_common.h" | 46 | #include "ipath_common.h" |
@@ -62,7 +64,7 @@ struct ipath_portdata { | |||
62 | /* rcvhdrq base, needs mmap before useful */ | 64 | /* rcvhdrq base, needs mmap before useful */ |
63 | void *port_rcvhdrq; | 65 | void *port_rcvhdrq; |
64 | /* kernel virtual address where hdrqtail is updated */ | 66 | /* kernel virtual address where hdrqtail is updated */ |
65 | volatile __le64 *port_rcvhdrtail_kvaddr; | 67 | void *port_rcvhdrtail_kvaddr; |
66 | /* | 68 | /* |
67 | * temp buffer for expected send setup, allocated at open, instead | 69 | * temp buffer for expected send setup, allocated at open, instead |
68 | * of each setup call | 70 | * of each setup call |
@@ -146,6 +148,11 @@ struct _ipath_layer { | |||
146 | void *l_arg; | 148 | void *l_arg; |
147 | }; | 149 | }; |
148 | 150 | ||
151 | struct ipath_skbinfo { | ||
152 | struct sk_buff *skb; | ||
153 | dma_addr_t phys; | ||
154 | }; | ||
155 | |||
149 | struct ipath_devdata { | 156 | struct ipath_devdata { |
150 | struct list_head ipath_list; | 157 | struct list_head ipath_list; |
151 | 158 | ||
@@ -168,7 +175,7 @@ struct ipath_devdata { | |||
168 | /* ipath_cfgports pointers */ | 175 | /* ipath_cfgports pointers */ |
169 | struct ipath_portdata **ipath_pd; | 176 | struct ipath_portdata **ipath_pd; |
170 | /* sk_buffs used by port 0 eager receive queue */ | 177 | /* sk_buffs used by port 0 eager receive queue */ |
171 | struct sk_buff **ipath_port0_skbs; | 178 | struct ipath_skbinfo *ipath_port0_skbinfo; |
172 | /* kvirt address of 1st 2k pio buffer */ | 179 | /* kvirt address of 1st 2k pio buffer */ |
173 | void __iomem *ipath_pio2kbase; | 180 | void __iomem *ipath_pio2kbase; |
174 | /* kvirt address of 1st 4k pio buffer */ | 181 | /* kvirt address of 1st 4k pio buffer */ |
@@ -335,6 +342,8 @@ struct ipath_devdata { | |||
335 | u64 *ipath_tidsimshadow; | 342 | u64 *ipath_tidsimshadow; |
336 | /* shadow copy of struct page *'s for exp tid pages */ | 343 | /* shadow copy of struct page *'s for exp tid pages */ |
337 | struct page **ipath_pageshadow; | 344 | struct page **ipath_pageshadow; |
345 | /* shadow copy of dma handles for exp tid pages */ | ||
346 | dma_addr_t *ipath_physshadow; | ||
338 | /* lock to workaround chip bug 9437 */ | 347 | /* lock to workaround chip bug 9437 */ |
339 | spinlock_t ipath_tid_lock; | 348 | spinlock_t ipath_tid_lock; |
340 | 349 | ||
@@ -865,6 +874,13 @@ int ipathfs_add_device(struct ipath_devdata *); | |||
865 | int ipathfs_remove_device(struct ipath_devdata *); | 874 | int ipathfs_remove_device(struct ipath_devdata *); |
866 | 875 | ||
867 | /* | 876 | /* |
877 | * dma_addr wrappers - all 0's invalid for hw | ||
878 | */ | ||
879 | dma_addr_t ipath_map_page(struct pci_dev *, struct page *, unsigned long, | ||
880 | size_t, int); | ||
881 | dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int); | ||
882 | |||
883 | /* | ||
868 | * Flush write combining store buffers (if present) and perform a write | 884 | * Flush write combining store buffers (if present) and perform a write |
869 | * barrier. | 885 | * barrier. |
870 | */ | 886 | */ |
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index e32fca9faf80..413754b1d8a2 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c | |||
@@ -90,6 +90,62 @@ bail: | |||
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * ipath_map_page - a safety wrapper around pci_map_page() | ||
94 | * | ||
95 | * A dma_addr of all 0's is interpreted by the chip as "disabled". | ||
96 | * Unfortunately, it can also be a valid dma_addr returned on some | ||
97 | * architectures. | ||
98 | * | ||
99 | * The powerpc iommu assigns dma_addrs in ascending order, so we don't | ||
100 | * have to bother with retries or mapping a dummy page to insure we | ||
101 | * don't just get the same mapping again. | ||
102 | * | ||
103 | * I'm sure we won't be so lucky with other iommu's, so FIXME. | ||
104 | */ | ||
105 | dma_addr_t ipath_map_page(struct pci_dev *hwdev, struct page *page, | ||
106 | unsigned long offset, size_t size, int direction) | ||
107 | { | ||
108 | dma_addr_t phys; | ||
109 | |||
110 | phys = pci_map_page(hwdev, page, offset, size, direction); | ||
111 | |||
112 | if (phys == 0) { | ||
113 | pci_unmap_page(hwdev, phys, size, direction); | ||
114 | phys = pci_map_page(hwdev, page, offset, size, direction); | ||
115 | /* | ||
116 | * FIXME: If we get 0 again, we should keep this page, | ||
117 | * map another, then free the 0 page. | ||
118 | */ | ||
119 | } | ||
120 | |||
121 | return phys; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * ipath_map_single - a safety wrapper around pci_map_single() | ||
126 | * | ||
127 | * Same idea as ipath_map_page(). | ||
128 | */ | ||
129 | dma_addr_t ipath_map_single(struct pci_dev *hwdev, void *ptr, size_t size, | ||
130 | int direction) | ||
131 | { | ||
132 | dma_addr_t phys; | ||
133 | |||
134 | phys = pci_map_single(hwdev, ptr, size, direction); | ||
135 | |||
136 | if (phys == 0) { | ||
137 | pci_unmap_single(hwdev, phys, size, direction); | ||
138 | phys = pci_map_single(hwdev, ptr, size, direction); | ||
139 | /* | ||
140 | * FIXME: If we get 0 again, we should keep this page, | ||
141 | * map another, then free the 0 page. | ||
142 | */ | ||
143 | } | ||
144 | |||
145 | return phys; | ||
146 | } | ||
147 | |||
148 | /** | ||
93 | * ipath_get_user_pages - lock user pages into memory | 149 | * ipath_get_user_pages - lock user pages into memory |
94 | * @start_page: the start page | 150 | * @start_page: the start page |
95 | * @num_pages: the number of pages | 151 | * @num_pages: the number of pages |
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c index 036fde662aa9..0095bb70f34e 100644 --- a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c +++ b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c | |||
@@ -38,13 +38,23 @@ | |||
38 | #include "ipath_kernel.h" | 38 | #include "ipath_kernel.h" |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * ipath_unordered_wc - indicate whether write combining is ordered | 41 | * ipath_enable_wc - enable write combining for MMIO writes to the device |
42 | * @dd: infinipath device | ||
42 | * | 43 | * |
43 | * PowerPC systems (at least those in the 970 processor family) | 44 | * Nothing to do on PowerPC, so just return without error. |
44 | * write partially filled store buffers in address order, but will write | 45 | */ |
45 | * completely filled store buffers in "random" order, and therefore must | 46 | int ipath_enable_wc(struct ipath_devdata *dd) |
46 | * have serialization for correctness with current InfiniPath chips. | 47 | { |
48 | return 0; | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * ipath_unordered_wc - indicate whether write combining is unordered | ||
47 | * | 53 | * |
54 | * Because our performance depends on our ability to do write | ||
55 | * combining mmio writes in the most efficient way, we need to | ||
56 | * know if we are on a processor that may reorder stores when | ||
57 | * write combining. | ||
48 | */ | 58 | */ |
49 | int ipath_unordered_wc(void) | 59 | int ipath_unordered_wc(void) |
50 | { | 60 | { |