mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 22:02:02 +00:00
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>
This commit is contained in:
parent
917e3e65c3
commit
f4b2f07b2e
1 changed files with 25 additions and 10 deletions
|
@ -38,6 +38,7 @@
|
||||||
#include <xen/swiotlb-xen.h>
|
#include <xen/swiotlb-xen.h>
|
||||||
#include <xen/page.h>
|
#include <xen/page.h>
|
||||||
#include <xen/xen-ops.h>
|
#include <xen/xen-ops.h>
|
||||||
|
#include <xen/hvc-console.h>
|
||||||
/*
|
/*
|
||||||
* Used to do a quick range check in swiotlb_tbl_unmap_single and
|
* Used to do a quick range check in swiotlb_tbl_unmap_single and
|
||||||
* swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
|
* 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)
|
||||||
void __init xen_swiotlb_init(int verbose)
|
void __init xen_swiotlb_init(int verbose)
|
||||||
{
|
{
|
||||||
unsigned long bytes;
|
unsigned long bytes;
|
||||||
int rc;
|
int rc = -ENOMEM;
|
||||||
unsigned long nr_tbl;
|
unsigned long nr_tbl;
|
||||||
|
char *m = NULL;
|
||||||
|
unsigned int repeat = 3;
|
||||||
|
|
||||||
nr_tbl = swioltb_nr_tbl();
|
nr_tbl = swioltb_nr_tbl();
|
||||||
if (nr_tbl)
|
if (nr_tbl)
|
||||||
|
@ -156,16 +159,17 @@ void __init xen_swiotlb_init(int verbose)
|
||||||
xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
|
xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
|
||||||
xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
|
xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
|
||||||
}
|
}
|
||||||
|
retry:
|
||||||
bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT;
|
bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get IO TLB memory from any location.
|
* Get IO TLB memory from any location.
|
||||||
*/
|
*/
|
||||||
xen_io_tlb_start = alloc_bootmem(bytes);
|
xen_io_tlb_start = alloc_bootmem(bytes);
|
||||||
if (!xen_io_tlb_start)
|
if (!xen_io_tlb_start) {
|
||||||
panic("Cannot allocate SWIOTLB buffer");
|
m = "Cannot allocate Xen-SWIOTLB buffer!\n";
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
xen_io_tlb_end = xen_io_tlb_start + bytes;
|
xen_io_tlb_end = xen_io_tlb_start + bytes;
|
||||||
/*
|
/*
|
||||||
* And replace that memory with pages under 4GB.
|
* And replace that memory with pages under 4GB.
|
||||||
|
@ -173,17 +177,28 @@ void __init xen_swiotlb_init(int verbose)
|
||||||
rc = xen_swiotlb_fixup(xen_io_tlb_start,
|
rc = xen_swiotlb_fixup(xen_io_tlb_start,
|
||||||
bytes,
|
bytes,
|
||||||
xen_io_tlb_nslabs);
|
xen_io_tlb_nslabs);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
free_bootmem(__pa(xen_io_tlb_start), bytes);
|
||||||
|
m = "Failed to get contiguous memory for DMA from Xen!\n"\
|
||||||
|
"You either: don't have the permissions, do not have"\
|
||||||
|
" enough free memory under 4GB, or the hypervisor memory"\
|
||||||
|
"is too fragmented!";
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
|
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
|
||||||
swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose);
|
swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\
|
if (repeat--) {
|
||||||
"We either don't have the permission or you do not have enough"\
|
xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */
|
||||||
"free memory under 4GB!\n", rc);
|
(xen_io_tlb_nslabs >> 1));
|
||||||
|
printk(KERN_INFO "Xen-SWIOTLB: Lowering to %luMB\n",
|
||||||
|
(xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
xen_raw_printk("%s (rc:%d)", rc, m);
|
||||||
|
panic("%s (rc:%d)", rc, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
|
|
Loading…
Reference in a new issue