Skip to content

Commit f4b2f07

Browse files
committed
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 <[email protected]>
1 parent 917e3e6 commit f4b2f07

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

drivers/xen/swiotlb-xen.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <xen/swiotlb-xen.h>
3939
#include <xen/page.h>
4040
#include <xen/xen-ops.h>
41+
#include <xen/hvc-console.h>
4142
/*
4243
* Used to do a quick range check in swiotlb_tbl_unmap_single and
4344
* 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)
146147
void __init xen_swiotlb_init(int verbose)
147148
{
148149
unsigned long bytes;
149-
int rc;
150+
int rc = -ENOMEM;
150151
unsigned long nr_tbl;
152+
char *m = NULL;
153+
unsigned int repeat = 3;
151154

152155
nr_tbl = swioltb_nr_tbl();
153156
if (nr_tbl)
@@ -156,34 +159,46 @@ void __init xen_swiotlb_init(int verbose)
156159
xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
157160
xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
158161
}
159-
162+
retry:
160163
bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT;
161164

162165
/*
163166
* Get IO TLB memory from any location.
164167
*/
165168
xen_io_tlb_start = alloc_bootmem(bytes);
166-
if (!xen_io_tlb_start)
167-
panic("Cannot allocate SWIOTLB buffer");
168-
169+
if (!xen_io_tlb_start) {
170+
m = "Cannot allocate Xen-SWIOTLB buffer!\n";
171+
goto error;
172+
}
169173
xen_io_tlb_end = xen_io_tlb_start + bytes;
170174
/*
171175
* And replace that memory with pages under 4GB.
172176
*/
173177
rc = xen_swiotlb_fixup(xen_io_tlb_start,
174178
bytes,
175179
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!";
177186
goto error;
178-
187+
}
179188
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
180189
swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose);
181190

182191
return;
183192
error:
184-
panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\
185-
"We either don't have the permission or you do not have enough"\
186-
"free memory under 4GB!\n", rc);
193+
if (repeat--) {
194+
xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */
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);
187202
}
188203

189204
void *

0 commit comments

Comments
 (0)