Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / drivers / xen / swiotlb-xen.c
index 060eeb0..4c89afc 100644 (file)
@@ -104,8 +104,7 @@ static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
        return 0;
 }
 
-static int
-xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs)
+static int xen_swiotlb_fixup(void *buf, unsigned long nslabs)
 {
        int i, rc;
        int dma_bits;
@@ -156,96 +155,106 @@ static const char *xen_swiotlb_error(enum xen_swiotlb_err err)
 
 #define DEFAULT_NSLABS         ALIGN(SZ_64M >> IO_TLB_SHIFT, IO_TLB_SEGSIZE)
 
-int __ref xen_swiotlb_init(int verbose, bool early)
+int __ref xen_swiotlb_init(void)
 {
-       unsigned long bytes, order;
-       int rc = -ENOMEM;
        enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN;
-       unsigned int repeat = 3;
+       unsigned long bytes = swiotlb_size_or_default();
+       unsigned long nslabs = bytes >> IO_TLB_SHIFT;
+       unsigned int order, repeat = 3;
+       int rc = -ENOMEM;
        char *start;
-       unsigned long nslabs;
 
-       nslabs = swiotlb_nr_tbl();
 retry:
-       if (!nslabs)
-               nslabs = DEFAULT_NSLABS;
-       bytes = nslabs << IO_TLB_SHIFT;
+       m_ret = XEN_SWIOTLB_ENOMEM;
        order = get_order(bytes);
 
        /*
         * Get IO TLB memory from any location.
         */
-       if (early) {
-               start = memblock_alloc(PAGE_ALIGN(bytes),
-                                                 PAGE_SIZE);
-               if (!start)
-                       panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
-                             __func__, PAGE_ALIGN(bytes), PAGE_SIZE);
-       } else {
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
-               while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
-                       start = (void *)xen_get_swiotlb_free_pages(order);
-                       if (start)
-                               break;
-                       order--;
-               }
-               if (order != get_order(bytes)) {
-                       pr_warn("Warning: only able to allocate %ld MB for software IO TLB\n",
-                               (PAGE_SIZE << order) >> 20);
-                       nslabs = SLABS_PER_PAGE << order;
-                       bytes = nslabs << IO_TLB_SHIFT;
-               }
+       while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
+               start = (void *)xen_get_swiotlb_free_pages(order);
+               if (start)
+                       break;
+               order--;
        }
-       if (!start) {
-               m_ret = XEN_SWIOTLB_ENOMEM;
+       if (!start)
                goto error;
+       if (order != get_order(bytes)) {
+               pr_warn("Warning: only able to allocate %ld MB for software IO TLB\n",
+                       (PAGE_SIZE << order) >> 20);
+               nslabs = SLABS_PER_PAGE << order;
+               bytes = nslabs << IO_TLB_SHIFT;
        }
+
        /*
         * And replace that memory with pages under 4GB.
         */
-       rc = xen_swiotlb_fixup(start,
-                              bytes,
-                              nslabs);
+       rc = xen_swiotlb_fixup(start, nslabs);
        if (rc) {
-               if (early)
-                       memblock_free(__pa(start),
-                                     PAGE_ALIGN(bytes));
-               else {
-                       free_pages((unsigned long)start, order);
-                       start = NULL;
-               }
+               free_pages((unsigned long)start, order);
                m_ret = XEN_SWIOTLB_EFIXUP;
                goto error;
        }
-       if (early) {
-               if (swiotlb_init_with_tbl(start, nslabs,
-                        verbose))
-                       panic("Cannot allocate SWIOTLB buffer");
-               rc = 0;
-       } else
-               rc = swiotlb_late_init_with_tbl(start, nslabs);
-
-       if (!rc)
-               swiotlb_set_max_segment(PAGE_SIZE);
-
-       return rc;
+       rc = swiotlb_late_init_with_tbl(start, nslabs);
+       if (rc)
+               return rc;
+       swiotlb_set_max_segment(PAGE_SIZE);
+       return 0;
 error:
        if (repeat--) {
-               nslabs = max(1024UL, /* Min is 2MB */
-                                       (nslabs >> 1));
+               /* Min is 2MB */
+               nslabs = max(1024UL, (nslabs >> 1));
                pr_info("Lowering to %luMB\n",
                        (nslabs << IO_TLB_SHIFT) >> 20);
                goto retry;
        }
        pr_err("%s (rc:%d)\n", xen_swiotlb_error(m_ret), rc);
-       if (early)
-               panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc);
-       else
-               free_pages((unsigned long)start, order);
+       free_pages((unsigned long)start, order);
        return rc;
 }
 
+#ifdef CONFIG_X86
+void __init xen_swiotlb_init_early(void)
+{
+       unsigned long bytes = swiotlb_size_or_default();
+       unsigned long nslabs = bytes >> IO_TLB_SHIFT;
+       unsigned int repeat = 3;
+       char *start;
+       int rc;
+
+retry:
+       /*
+        * Get IO TLB memory from any location.
+        */
+       start = memblock_alloc(PAGE_ALIGN(bytes), PAGE_SIZE);
+       if (!start)
+               panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+                     __func__, PAGE_ALIGN(bytes), PAGE_SIZE);
+
+       /*
+        * And replace that memory with pages under 4GB.
+        */
+       rc = xen_swiotlb_fixup(start, nslabs);
+       if (rc) {
+               memblock_free(__pa(start), PAGE_ALIGN(bytes));
+               if (repeat--) {
+                       /* Min is 2MB */
+                       nslabs = max(1024UL, (nslabs >> 1));
+                       bytes = nslabs << IO_TLB_SHIFT;
+                       pr_info("Lowering to %luMB\n", bytes >> 20);
+                       goto retry;
+               }
+               panic("%s (rc:%d)", xen_swiotlb_error(XEN_SWIOTLB_EFIXUP), rc);
+       }
+
+       if (swiotlb_init_with_tbl(start, nslabs, false))
+               panic("Cannot allocate SWIOTLB buffer");
+       swiotlb_set_max_segment(PAGE_SIZE);
+}
+#endif /* CONFIG_X86 */
+
 static void *
 xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                           dma_addr_t *dma_handle, gfp_t flags,
@@ -533,7 +542,7 @@ xen_swiotlb_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
 static int
 xen_swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-       return xen_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+       return xen_phys_to_dma(hwdev, io_tlb_default_mem->end - 1) <= mask;
 }
 
 const struct dma_map_ops xen_swiotlb_dma_ops = {