swiotlb: Add swiotlb=noforce debug option
On architectures like arm64, swiotlb is tied intimately to the core architecture DMA support. In addition, ZONE_DMA cannot be disabled. To aid debugging and catch devices not supporting DMA to memory outside the 32-bit address space, add a kernel command line option "swiotlb=noforce", which disables the use of bounce buffers. If specified, trying to map memory that cannot be used with DMA will fail, and a rate-limited warning will be printed. Note that io_tlb_nslabs is set to 1, which is the minimal supported value. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
This commit is contained in:
parent
ae7871be18
commit
fff5d99225
|
@ -3807,10 +3807,11 @@
|
|||
it if 0 is given (See Documentation/cgroup-v1/memory.txt)
|
||||
|
||||
swiotlb= [ARM,IA-64,PPC,MIPS,X86]
|
||||
Format: { <int> | force }
|
||||
Format: { <int> | force | noforce }
|
||||
<int> -- Number of I/O TLB slabs
|
||||
force -- force using of bounce buffers even if they
|
||||
wouldn't be automatically used by the kernel
|
||||
noforce -- Never use bounce buffers (for debugging)
|
||||
|
||||
switches= [HW,M68k]
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ struct scatterlist;
|
|||
enum swiotlb_force {
|
||||
SWIOTLB_NORMAL, /* Default - depending on HW DMA mask etc. */
|
||||
SWIOTLB_FORCE, /* swiotlb=force */
|
||||
SWIOTLB_NO_FORCE, /* swiotlb=noforce */
|
||||
};
|
||||
|
||||
extern enum swiotlb_force swiotlb_force;
|
||||
|
|
|
@ -39,7 +39,8 @@ TRACE_EVENT(swiotlb_bounced,
|
|||
__entry->size,
|
||||
__print_symbolic(__entry->swiotlb_force,
|
||||
{ SWIOTLB_NORMAL, "NORMAL" },
|
||||
{ SWIOTLB_FORCE, "FORCE" }))
|
||||
{ SWIOTLB_FORCE, "FORCE" },
|
||||
{ SWIOTLB_NO_FORCE, "NO_FORCE" }))
|
||||
);
|
||||
|
||||
#endif /* _TRACE_SWIOTLB_H */
|
||||
|
|
|
@ -106,8 +106,12 @@ setup_io_tlb_npages(char *str)
|
|||
}
|
||||
if (*str == ',')
|
||||
++str;
|
||||
if (!strcmp(str, "force"))
|
||||
if (!strcmp(str, "force")) {
|
||||
swiotlb_force = SWIOTLB_FORCE;
|
||||
} else if (!strcmp(str, "noforce")) {
|
||||
swiotlb_force = SWIOTLB_NO_FORCE;
|
||||
io_tlb_nslabs = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -543,8 +547,15 @@ static phys_addr_t
|
|||
map_single(struct device *hwdev, phys_addr_t phys, size_t size,
|
||||
enum dma_data_direction dir, unsigned long attrs)
|
||||
{
|
||||
dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
|
||||
dma_addr_t start_dma_addr;
|
||||
|
||||
if (swiotlb_force == SWIOTLB_NO_FORCE) {
|
||||
dev_warn_ratelimited(hwdev, "Cannot do DMA to address %pa\n",
|
||||
&phys);
|
||||
return SWIOTLB_MAP_ERROR;
|
||||
}
|
||||
|
||||
start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
|
||||
return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size,
|
||||
dir, attrs);
|
||||
}
|
||||
|
@ -721,6 +732,9 @@ static void
|
|||
swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
|
||||
int do_panic)
|
||||
{
|
||||
if (swiotlb_force == SWIOTLB_NO_FORCE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ran out of IOMMU space for this operation. This is very bad.
|
||||
* Unfortunately the drivers cannot handle this operation properly.
|
||||
|
|
Loading…
Reference in New Issue