swiotlb: add the late swiotlb initialization function with iotlb memory
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Sat, 28 Jul 2012 00:55:27 +0000 (20:55 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 21 Aug 2012 18:47:25 +0000 (14:47 -0400)
This enables the caller to initialize swiotlb with its own iotlb
memory late in the bootup.

See git commit eb605a5754d050a25a9f00d718fb173f24c486ef
"swiotlb: add swiotlb_tbl_map_single library function" which will
explain the full details of what it can be used for.

CC: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
[v1: Fold in smatch warning]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
include/linux/swiotlb.h
lib/swiotlb.c

index e872526fdc5fbb371ca0e420a961aec4738fdfa2..8d08b3ed406db688c6fa8c1cfe10d921870d2e72 100644 (file)
@@ -25,6 +25,7 @@ extern int swiotlb_force;
 extern void swiotlb_init(int verbose);
 extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
+extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
 
 /*
  * Enumeration for sync targets
index 45bc1f83a5ada665297bc0b9dcd3a6ad72e2ec72..f114bf6a8e1363dc812cfa4fd8e6ae66a1411575 100644 (file)
@@ -170,7 +170,7 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
  * Statically reserve bounce buffer space and initialize bounce buffer data
  * structures for the software IO TLB used to implement the DMA API.
  */
-void __init
+static void __init
 swiotlb_init_with_default_size(size_t default_size, int verbose)
 {
        unsigned long bytes;
@@ -206,8 +206,9 @@ swiotlb_init(int verbose)
 int
 swiotlb_late_init_with_default_size(size_t default_size)
 {
-       unsigned long i, bytes, req_nslabs = io_tlb_nslabs;
+       unsigned long bytes, req_nslabs = io_tlb_nslabs;
        unsigned int order;
+       int rc = 0;
 
        if (!io_tlb_nslabs) {
                io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
@@ -229,16 +230,32 @@ swiotlb_late_init_with_default_size(size_t default_size)
                order--;
        }
 
-       if (!io_tlb_start)
-               goto cleanup1;
-
+       if (!io_tlb_start) {
+               io_tlb_nslabs = req_nslabs;
+               return -ENOMEM;
+       }
        if (order != get_order(bytes)) {
                printk(KERN_WARNING "Warning: only able to allocate %ld MB "
                       "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
                io_tlb_nslabs = SLABS_PER_PAGE << order;
-               bytes = io_tlb_nslabs << IO_TLB_SHIFT;
        }
+       rc = swiotlb_late_init_with_tbl(io_tlb_start, io_tlb_nslabs);
+       if (rc)
+               free_pages((unsigned long)io_tlb_start, order);
+       return rc;
+}
+
+int
+swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
+{
+       unsigned long i, bytes;
+
+       bytes = nslabs << IO_TLB_SHIFT;
+
+       io_tlb_nslabs = nslabs;
+       io_tlb_start = tlb;
        io_tlb_end = io_tlb_start + bytes;
+
        memset(io_tlb_start, 0, bytes);
 
        /*
@@ -288,10 +305,8 @@ cleanup3:
        io_tlb_list = NULL;
 cleanup2:
        io_tlb_end = NULL;
-       free_pages((unsigned long)io_tlb_start, order);
        io_tlb_start = NULL;
-cleanup1:
-       io_tlb_nslabs = req_nslabs;
+       io_tlb_nslabs = 0;
        return -ENOMEM;
 }