swiotlb: Return consistent SWIOTLB segments/nr_tbl
authorFlorian Fainelli <f.fainelli@gmail.com>
Tue, 11 Jun 2019 17:58:25 +0000 (10:58 -0700)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 11 Jun 2019 18:36:33 +0000 (14:36 -0400)
With a specifically contrived memory layout where there is no physical
memory available to the kernel below the 4GB boundary, we will fail to
perform the initial swiotlb_init() call and set no_iotlb_memory to true.

There are drivers out there that call into swiotlb_nr_tbl() to determine
whether they can use the SWIOTLB. With the right DMA_BIT_MASK() value
for these drivers (say 64-bit), they won't ever need to hit
swiotlb_tbl_map_single() so this can go unoticed and we would be
possibly lying about those drivers.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
kernel/dma/swiotlb.c

index 20f414f713e5c31a87a3b195dd2a66c1dc1c7828..72506085795c15f76bd38e8ec483cece96159ccc 100644 (file)
@@ -128,15 +128,17 @@ setup_io_tlb_npages(char *str)
 }
 early_param("swiotlb", setup_io_tlb_npages);
 
+static bool no_iotlb_memory;
+
 unsigned long swiotlb_nr_tbl(void)
 {
-       return io_tlb_nslabs;
+       return unlikely(no_iotlb_memory) ? 0 : io_tlb_nslabs;
 }
 EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
 
 unsigned int swiotlb_max_segment(void)
 {
-       return max_segment;
+       return unlikely(no_iotlb_memory) ? 0 : max_segment;
 }
 EXPORT_SYMBOL_GPL(swiotlb_max_segment);
 
@@ -159,8 +161,6 @@ unsigned long swiotlb_size_or_default(void)
        return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
-static bool no_iotlb_memory;
-
 void swiotlb_print_info(void)
 {
        unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;