diff options
author | Paul Mackerras <paulus@samba.org> | 2008-03-25 17:44:18 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-03-25 17:44:18 -0400 |
commit | 54f53f2b94feb72622bec7a8563fc487d9f97720 (patch) | |
tree | ab0c4e1dcadd25a00fa7a4febf41bc43b864cf73 /arch/powerpc/platforms/cell/iommu.c | |
parent | f61fb8a52cdf8b9b6a6badde84aefe58cb35d315 (diff) | |
parent | a4083c9271e0a697278e089f2c0b9a95363ada0a (diff) |
Merge branch 'linux-2.6'
Diffstat (limited to 'arch/powerpc/platforms/cell/iommu.c')
-rw-r--r-- | arch/powerpc/platforms/cell/iommu.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index d6a732503ea6..49fe641d4345 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -802,17 +802,24 @@ static int __init cell_iommu_init_disabled(void) | |||
802 | 802 | ||
803 | static u64 cell_iommu_get_fixed_address(struct device *dev) | 803 | static u64 cell_iommu_get_fixed_address(struct device *dev) |
804 | { | 804 | { |
805 | u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR; | 805 | u64 cpu_addr, size, best_size, dev_addr = OF_BAD_ADDR; |
806 | struct device_node *np; | 806 | struct device_node *np; |
807 | const u32 *ranges = NULL; | 807 | const u32 *ranges = NULL; |
808 | int i, len, best; | 808 | int i, len, best, naddr, nsize, pna, range_size; |
809 | 809 | ||
810 | np = of_node_get(dev->archdata.of_node); | 810 | np = of_node_get(dev->archdata.of_node); |
811 | while (np) { | 811 | while (1) { |
812 | naddr = of_n_addr_cells(np); | ||
813 | nsize = of_n_size_cells(np); | ||
814 | np = of_get_next_parent(np); | ||
815 | if (!np) | ||
816 | break; | ||
817 | |||
812 | ranges = of_get_property(np, "dma-ranges", &len); | 818 | ranges = of_get_property(np, "dma-ranges", &len); |
813 | if (ranges) | 819 | |
820 | /* Ignore empty ranges, they imply no translation required */ | ||
821 | if (ranges && len > 0) | ||
814 | break; | 822 | break; |
815 | np = of_get_next_parent(np); | ||
816 | } | 823 | } |
817 | 824 | ||
818 | if (!ranges) { | 825 | if (!ranges) { |
@@ -822,15 +829,17 @@ static u64 cell_iommu_get_fixed_address(struct device *dev) | |||
822 | 829 | ||
823 | len /= sizeof(u32); | 830 | len /= sizeof(u32); |
824 | 831 | ||
832 | pna = of_n_addr_cells(np); | ||
833 | range_size = naddr + nsize + pna; | ||
834 | |||
825 | /* dma-ranges format: | 835 | /* dma-ranges format: |
826 | * 1 cell: pci space | 836 | * child addr : naddr cells |
827 | * 2 cells: pci address | 837 | * parent addr : pna cells |
828 | * 2 cells: parent address | 838 | * size : nsize cells |
829 | * 2 cells: size | ||
830 | */ | 839 | */ |
831 | for (i = 0, best = -1, best_size = 0; i < len; i += 7) { | 840 | for (i = 0, best = -1, best_size = 0; i < len; i += range_size) { |
832 | cpu_addr = of_translate_dma_address(np, ranges +i + 3); | 841 | cpu_addr = of_translate_dma_address(np, ranges + i + naddr); |
833 | size = of_read_number(ranges + i + 5, 2); | 842 | size = of_read_number(ranges + i + naddr + pna, nsize); |
834 | 843 | ||
835 | if (cpu_addr == 0 && size > best_size) { | 844 | if (cpu_addr == 0 && size > best_size) { |
836 | best = i; | 845 | best = i; |
@@ -838,15 +847,15 @@ static u64 cell_iommu_get_fixed_address(struct device *dev) | |||
838 | } | 847 | } |
839 | } | 848 | } |
840 | 849 | ||
841 | if (best >= 0) | 850 | if (best >= 0) { |
842 | pci_addr = of_read_number(ranges + best + 1, 2); | 851 | dev_addr = of_read_number(ranges + best, naddr); |
843 | else | 852 | } else |
844 | dev_dbg(dev, "iommu: no suitable range found!\n"); | 853 | dev_dbg(dev, "iommu: no suitable range found!\n"); |
845 | 854 | ||
846 | out: | 855 | out: |
847 | of_node_put(np); | 856 | of_node_put(np); |
848 | 857 | ||
849 | return pci_addr; | 858 | return dev_addr; |
850 | } | 859 | } |
851 | 860 | ||
852 | static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) | 861 | static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask) |