diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/cell/iommu.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/iommu.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/iommu.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 42 |
4 files changed, 38 insertions, 13 deletions
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 031124a8e37b..e06420af5fe9 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -172,7 +172,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, | |||
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | static void tce_build_cell(struct iommu_table *tbl, long index, long npages, | 175 | static int tce_build_cell(struct iommu_table *tbl, long index, long npages, |
176 | unsigned long uaddr, enum dma_data_direction direction, | 176 | unsigned long uaddr, enum dma_data_direction direction, |
177 | struct dma_attrs *attrs) | 177 | struct dma_attrs *attrs) |
178 | { | 178 | { |
@@ -213,6 +213,7 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages, | |||
213 | 213 | ||
214 | pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", | 214 | pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", |
215 | index, npages, direction, base_pte); | 215 | index, npages, direction, base_pte); |
216 | return 0; | ||
216 | } | 217 | } |
217 | 218 | ||
218 | static void tce_free_cell(struct iommu_table *tbl, long index, long npages) | 219 | static void tce_free_cell(struct iommu_table *tbl, long index, long npages) |
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bc818e4e2033..bb464d1211b2 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <asm/iseries/hv_call_event.h> | 41 | #include <asm/iseries/hv_call_event.h> |
42 | #include <asm/iseries/iommu.h> | 42 | #include <asm/iseries/iommu.h> |
43 | 43 | ||
44 | static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, | 44 | static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages, |
45 | unsigned long uaddr, enum dma_data_direction direction, | 45 | unsigned long uaddr, enum dma_data_direction direction, |
46 | struct dma_attrs *attrs) | 46 | struct dma_attrs *attrs) |
47 | { | 47 | { |
@@ -71,6 +71,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, | |||
71 | index++; | 71 | index++; |
72 | uaddr += TCE_PAGE_SIZE; | 72 | uaddr += TCE_PAGE_SIZE; |
73 | } | 73 | } |
74 | return 0; | ||
74 | } | 75 | } |
75 | 76 | ||
76 | static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) | 77 | static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 70541b7a5013..a0ff03a3d8da 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -83,7 +83,7 @@ static u32 *iob_l2_base; | |||
83 | static struct iommu_table iommu_table_iobmap; | 83 | static struct iommu_table iommu_table_iobmap; |
84 | static int iommu_table_iobmap_inited; | 84 | static int iommu_table_iobmap_inited; |
85 | 85 | ||
86 | static void iobmap_build(struct iommu_table *tbl, long index, | 86 | static int iobmap_build(struct iommu_table *tbl, long index, |
87 | long npages, unsigned long uaddr, | 87 | long npages, unsigned long uaddr, |
88 | enum dma_data_direction direction, | 88 | enum dma_data_direction direction, |
89 | struct dma_attrs *attrs) | 89 | struct dma_attrs *attrs) |
@@ -108,6 +108,7 @@ static void iobmap_build(struct iommu_table *tbl, long index, | |||
108 | uaddr += IOBMAP_PAGE_SIZE; | 108 | uaddr += IOBMAP_PAGE_SIZE; |
109 | bus_addr += IOBMAP_PAGE_SIZE; | 109 | bus_addr += IOBMAP_PAGE_SIZE; |
110 | } | 110 | } |
111 | return 0; | ||
111 | } | 112 | } |
112 | 113 | ||
113 | 114 | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 5377dd4b849a..a8c446697f9e 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -48,7 +48,7 @@ | |||
48 | #include "plpar_wrappers.h" | 48 | #include "plpar_wrappers.h" |
49 | 49 | ||
50 | 50 | ||
51 | static void tce_build_pSeries(struct iommu_table *tbl, long index, | 51 | static int tce_build_pSeries(struct iommu_table *tbl, long index, |
52 | long npages, unsigned long uaddr, | 52 | long npages, unsigned long uaddr, |
53 | enum dma_data_direction direction, | 53 | enum dma_data_direction direction, |
54 | struct dma_attrs *attrs) | 54 | struct dma_attrs *attrs) |
@@ -72,6 +72,7 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index, | |||
72 | uaddr += TCE_PAGE_SIZE; | 72 | uaddr += TCE_PAGE_SIZE; |
73 | tcep++; | 73 | tcep++; |
74 | } | 74 | } |
75 | return 0; | ||
75 | } | 76 | } |
76 | 77 | ||
77 | 78 | ||
@@ -94,14 +95,19 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) | |||
94 | return *tcep; | 95 | return *tcep; |
95 | } | 96 | } |
96 | 97 | ||
97 | static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | 98 | static void tce_free_pSeriesLP(struct iommu_table*, long, long); |
99 | static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long); | ||
100 | |||
101 | static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | ||
98 | long npages, unsigned long uaddr, | 102 | long npages, unsigned long uaddr, |
99 | enum dma_data_direction direction, | 103 | enum dma_data_direction direction, |
100 | struct dma_attrs *attrs) | 104 | struct dma_attrs *attrs) |
101 | { | 105 | { |
102 | u64 rc; | 106 | u64 rc = 0; |
103 | u64 proto_tce, tce; | 107 | u64 proto_tce, tce; |
104 | u64 rpn; | 108 | u64 rpn; |
109 | int ret = 0; | ||
110 | long tcenum_start = tcenum, npages_start = npages; | ||
105 | 111 | ||
106 | rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; | 112 | rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; |
107 | proto_tce = TCE_PCI_READ; | 113 | proto_tce = TCE_PCI_READ; |
@@ -112,6 +118,13 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
112 | tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; | 118 | tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; |
113 | rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); | 119 | rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); |
114 | 120 | ||
121 | if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { | ||
122 | ret = (int)rc; | ||
123 | tce_free_pSeriesLP(tbl, tcenum_start, | ||
124 | (npages_start - (npages + 1))); | ||
125 | break; | ||
126 | } | ||
127 | |||
115 | if (rc && printk_ratelimit()) { | 128 | if (rc && printk_ratelimit()) { |
116 | printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); | 129 | printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); |
117 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); | 130 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); |
@@ -123,25 +136,27 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
123 | tcenum++; | 136 | tcenum++; |
124 | rpn++; | 137 | rpn++; |
125 | } | 138 | } |
139 | return ret; | ||
126 | } | 140 | } |
127 | 141 | ||
128 | static DEFINE_PER_CPU(u64 *, tce_page) = NULL; | 142 | static DEFINE_PER_CPU(u64 *, tce_page) = NULL; |
129 | 143 | ||
130 | static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | 144 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, |
131 | long npages, unsigned long uaddr, | 145 | long npages, unsigned long uaddr, |
132 | enum dma_data_direction direction, | 146 | enum dma_data_direction direction, |
133 | struct dma_attrs *attrs) | 147 | struct dma_attrs *attrs) |
134 | { | 148 | { |
135 | u64 rc; | 149 | u64 rc = 0; |
136 | u64 proto_tce; | 150 | u64 proto_tce; |
137 | u64 *tcep; | 151 | u64 *tcep; |
138 | u64 rpn; | 152 | u64 rpn; |
139 | long l, limit; | 153 | long l, limit; |
154 | long tcenum_start = tcenum, npages_start = npages; | ||
155 | int ret = 0; | ||
140 | 156 | ||
141 | if (npages == 1) { | 157 | if (npages == 1) { |
142 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 158 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
143 | direction, attrs); | 159 | direction, attrs); |
144 | return; | ||
145 | } | 160 | } |
146 | 161 | ||
147 | tcep = __get_cpu_var(tce_page); | 162 | tcep = __get_cpu_var(tce_page); |
@@ -153,9 +168,8 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
153 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); | 168 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); |
154 | /* If allocation fails, fall back to the loop implementation */ | 169 | /* If allocation fails, fall back to the loop implementation */ |
155 | if (!tcep) { | 170 | if (!tcep) { |
156 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 171 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
157 | direction, attrs); | 172 | direction, attrs); |
158 | return; | ||
159 | } | 173 | } |
160 | __get_cpu_var(tce_page) = tcep; | 174 | __get_cpu_var(tce_page) = tcep; |
161 | } | 175 | } |
@@ -187,6 +201,13 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
187 | tcenum += limit; | 201 | tcenum += limit; |
188 | } while (npages > 0 && !rc); | 202 | } while (npages > 0 && !rc); |
189 | 203 | ||
204 | if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { | ||
205 | ret = (int)rc; | ||
206 | tce_freemulti_pSeriesLP(tbl, tcenum_start, | ||
207 | (npages_start - (npages + limit))); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
190 | if (rc && printk_ratelimit()) { | 211 | if (rc && printk_ratelimit()) { |
191 | printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); | 212 | printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); |
192 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); | 213 | printk("\tindex = 0x%lx\n", (u64)tbl->it_index); |
@@ -194,6 +215,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
194 | printk("\ttce[0] val = 0x%lx\n", tcep[0]); | 215 | printk("\ttce[0] val = 0x%lx\n", tcep[0]); |
195 | show_stack(current, (unsigned long *)__get_SP()); | 216 | show_stack(current, (unsigned long *)__get_SP()); |
196 | } | 217 | } |
218 | return ret; | ||
197 | } | 219 | } |
198 | 220 | ||
199 | static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) | 221 | static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) |