diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-07-22 12:46:43 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-08-26 12:10:15 -0400 |
commit | f4b2f07b2ed9b469ead87e06fc2fc3d12663a725 (patch) | |
tree | 242eca67acfa3e53b698a92031d4e8ec928f9b7f /drivers/xen/swiotlb-xen.c | |
parent | 917e3e65c35459d52f0d0b890aa5df0cad07a051 (diff) |
xen-swiotlb: Retry up three times to allocate Xen-SWIOTLB
We can fail seting up Xen-SWIOTLB if:
- The host does not have enough contiguous DMA32 memory available
(can happen on a machine that has fragmented memory from starting,
stopping many guests).
- Not enough low memory (almost never happens).
We retry allocating and exchanging the swath of contiguous memory
up to three times. Each time we decrease the amount we need - the
minimum being of 2MB.
If we compleltly fail, we will print the reason for failure on the Xen
console on top of doing it to earlyprintk=xen console.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/swiotlb-xen.c')
-rw-r--r-- | drivers/xen/swiotlb-xen.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 6e8c15a23201..d45cbacaf6ff 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <xen/swiotlb-xen.h> | 38 | #include <xen/swiotlb-xen.h> |
39 | #include <xen/page.h> | 39 | #include <xen/page.h> |
40 | #include <xen/xen-ops.h> | 40 | #include <xen/xen-ops.h> |
41 | #include <xen/hvc-console.h> | ||
41 | /* | 42 | /* |
42 | * Used to do a quick range check in swiotlb_tbl_unmap_single and | 43 | * Used to do a quick range check in swiotlb_tbl_unmap_single and |
43 | * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this | 44 | * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this |
@@ -146,8 +147,10 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) | |||
146 | void __init xen_swiotlb_init(int verbose) | 147 | void __init xen_swiotlb_init(int verbose) |
147 | { | 148 | { |
148 | unsigned long bytes; | 149 | unsigned long bytes; |
149 | int rc; | 150 | int rc = -ENOMEM; |
150 | unsigned long nr_tbl; | 151 | unsigned long nr_tbl; |
152 | char *m = NULL; | ||
153 | unsigned int repeat = 3; | ||
151 | 154 | ||
152 | nr_tbl = swioltb_nr_tbl(); | 155 | nr_tbl = swioltb_nr_tbl(); |
153 | if (nr_tbl) | 156 | if (nr_tbl) |
@@ -156,16 +159,17 @@ void __init xen_swiotlb_init(int verbose) | |||
156 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | 159 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); |
157 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | 160 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); |
158 | } | 161 | } |
159 | 162 | retry: | |
160 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | 163 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; |
161 | 164 | ||
162 | /* | 165 | /* |
163 | * Get IO TLB memory from any location. | 166 | * Get IO TLB memory from any location. |
164 | */ | 167 | */ |
165 | xen_io_tlb_start = alloc_bootmem(bytes); | 168 | xen_io_tlb_start = alloc_bootmem(bytes); |
166 | if (!xen_io_tlb_start) | 169 | if (!xen_io_tlb_start) { |
167 | panic("Cannot allocate SWIOTLB buffer"); | 170 | m = "Cannot allocate Xen-SWIOTLB buffer!\n"; |
168 | 171 | goto error; | |
172 | } | ||
169 | xen_io_tlb_end = xen_io_tlb_start + bytes; | 173 | xen_io_tlb_end = xen_io_tlb_start + bytes; |
170 | /* | 174 | /* |
171 | * And replace that memory with pages under 4GB. | 175 | * And replace that memory with pages under 4GB. |
@@ -173,17 +177,28 @@ void __init xen_swiotlb_init(int verbose) | |||
173 | rc = xen_swiotlb_fixup(xen_io_tlb_start, | 177 | rc = xen_swiotlb_fixup(xen_io_tlb_start, |
174 | bytes, | 178 | bytes, |
175 | xen_io_tlb_nslabs); | 179 | xen_io_tlb_nslabs); |
176 | if (rc) | 180 | if (rc) { |
181 | free_bootmem(__pa(xen_io_tlb_start), bytes); | ||
182 | m = "Failed to get contiguous memory for DMA from Xen!\n"\ | ||
183 | "You either: don't have the permissions, do not have"\ | ||
184 | " enough free memory under 4GB, or the hypervisor memory"\ | ||
185 | "is too fragmented!"; | ||
177 | goto error; | 186 | goto error; |
178 | 187 | } | |
179 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | 188 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); |
180 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | 189 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); |
181 | 190 | ||
182 | return; | 191 | return; |
183 | error: | 192 | error: |
184 | panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\ | 193 | if (repeat--) { |
185 | "We either don't have the permission or you do not have enough"\ | 194 | xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ |
186 | "free memory under 4GB!\n", rc); | 195 | (xen_io_tlb_nslabs >> 1)); |
196 | printk(KERN_INFO "Xen-SWIOTLB: Lowering to %luMB\n", | ||
197 | (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); | ||
198 | goto retry; | ||
199 | } | ||
200 | xen_raw_printk("%s (rc:%d)", rc, m); | ||
201 | panic("%s (rc:%d)", rc, m); | ||
187 | } | 202 | } |
188 | 203 | ||
189 | void * | 204 | void * |