Skip to content

Commit

Permalink
swiotlb: Add swiotlb=noforce debug option
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
  • Loading branch information
geertu authored and konradwilk committed Dec 19, 2016
1 parent ae7871b commit fff5d99
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 4 deletions.
3 changes: 2 additions & 1 deletion Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
1 change: 1 addition & 0 deletions include/linux/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion include/trace/events/swiotlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
18 changes: 16 additions & 2 deletions lib/swiotlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit fff5d99

Please sign in to comment.