diff options
| -rw-r--r-- | arch/x86/include/asm/xen/swiotlb-xen.h | 2 | ||||
| -rw-r--r-- | arch/x86/xen/pci-swiotlb-xen.c | 47 | ||||
| -rw-r--r-- | drivers/pci/xen-pcifront.c | 13 | ||||
| -rw-r--r-- | drivers/xen/swiotlb-xen.c | 101 | ||||
| -rw-r--r-- | include/linux/swiotlb.h | 1 | ||||
| -rw-r--r-- | include/xen/swiotlb-xen.h | 2 | ||||
| -rw-r--r-- | lib/swiotlb.c | 33 |
7 files changed, 154 insertions, 45 deletions
diff --git a/arch/x86/include/asm/xen/swiotlb-xen.h b/arch/x86/include/asm/xen/swiotlb-xen.h index 1be1ab7d6a41..ee52fcac6f72 100644 --- a/arch/x86/include/asm/xen/swiotlb-xen.h +++ b/arch/x86/include/asm/xen/swiotlb-xen.h | |||
| @@ -5,10 +5,12 @@ | |||
| 5 | extern int xen_swiotlb; | 5 | extern int xen_swiotlb; |
| 6 | extern int __init pci_xen_swiotlb_detect(void); | 6 | extern int __init pci_xen_swiotlb_detect(void); |
| 7 | extern void __init pci_xen_swiotlb_init(void); | 7 | extern void __init pci_xen_swiotlb_init(void); |
| 8 | extern int pci_xen_swiotlb_init_late(void); | ||
| 8 | #else | 9 | #else |
| 9 | #define xen_swiotlb (0) | 10 | #define xen_swiotlb (0) |
| 10 | static inline int __init pci_xen_swiotlb_detect(void) { return 0; } | 11 | static inline int __init pci_xen_swiotlb_detect(void) { return 0; } |
| 11 | static inline void __init pci_xen_swiotlb_init(void) { } | 12 | static inline void __init pci_xen_swiotlb_init(void) { } |
| 13 | static inline int pci_xen_swiotlb_init_late(void) { return -ENXIO; } | ||
| 12 | #endif | 14 | #endif |
| 13 | 15 | ||
| 14 | #endif /* _ASM_X86_SWIOTLB_XEN_H */ | 16 | #endif /* _ASM_X86_SWIOTLB_XEN_H */ |
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c index 1ab45941502d..969570491c39 100644 --- a/arch/x86/xen/pci-swiotlb-xen.c +++ b/arch/x86/xen/pci-swiotlb-xen.c | |||
| @@ -8,7 +8,14 @@ | |||
| 8 | #include <xen/xen.h> | 8 | #include <xen/xen.h> |
| 9 | #include <asm/iommu_table.h> | 9 | #include <asm/iommu_table.h> |
| 10 | 10 | ||
| 11 | |||
| 11 | #include <asm/xen/swiotlb-xen.h> | 12 | #include <asm/xen/swiotlb-xen.h> |
| 13 | #ifdef CONFIG_X86_64 | ||
| 14 | #include <asm/iommu.h> | ||
| 15 | #include <asm/dma.h> | ||
| 16 | #endif | ||
| 17 | #include <linux/export.h> | ||
| 18 | |||
| 12 | int xen_swiotlb __read_mostly; | 19 | int xen_swiotlb __read_mostly; |
| 13 | 20 | ||
| 14 | static struct dma_map_ops xen_swiotlb_dma_ops = { | 21 | static struct dma_map_ops xen_swiotlb_dma_ops = { |
| @@ -35,33 +42,63 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { | |||
| 35 | int __init pci_xen_swiotlb_detect(void) | 42 | int __init pci_xen_swiotlb_detect(void) |
| 36 | { | 43 | { |
| 37 | 44 | ||
| 45 | if (!xen_pv_domain()) | ||
| 46 | return 0; | ||
| 47 | |||
| 38 | /* If running as PV guest, either iommu=soft, or swiotlb=force will | 48 | /* If running as PV guest, either iommu=soft, or swiotlb=force will |
| 39 | * activate this IOMMU. If running as PV privileged, activate it | 49 | * activate this IOMMU. If running as PV privileged, activate it |
| 40 | * irregardless. | 50 | * irregardless. |
| 41 | */ | 51 | */ |
| 42 | if ((xen_initial_domain() || swiotlb || swiotlb_force) && | 52 | if ((xen_initial_domain() || swiotlb || swiotlb_force)) |
| 43 | (xen_pv_domain())) | ||
| 44 | xen_swiotlb = 1; | 53 | xen_swiotlb = 1; |
| 45 | 54 | ||
| 46 | /* If we are running under Xen, we MUST disable the native SWIOTLB. | 55 | /* If we are running under Xen, we MUST disable the native SWIOTLB. |
| 47 | * Don't worry about swiotlb_force flag activating the native, as | 56 | * Don't worry about swiotlb_force flag activating the native, as |
| 48 | * the 'swiotlb' flag is the only one turning it on. */ | 57 | * the 'swiotlb' flag is the only one turning it on. */ |
| 49 | if (xen_pv_domain()) | 58 | swiotlb = 0; |
| 50 | swiotlb = 0; | ||
| 51 | 59 | ||
| 60 | #ifdef CONFIG_X86_64 | ||
| 61 | /* pci_swiotlb_detect_4gb turns on native SWIOTLB if no_iommu == 0 | ||
| 62 | * (so no iommu=X command line over-writes). | ||
| 63 | * Considering that PV guests do not want the *native SWIOTLB* but | ||
| 64 | * only Xen SWIOTLB it is not useful to us so set no_iommu=1 here. | ||
| 65 | */ | ||
| 66 | if (max_pfn > MAX_DMA32_PFN) | ||
| 67 | no_iommu = 1; | ||
| 68 | #endif | ||
| 52 | return xen_swiotlb; | 69 | return xen_swiotlb; |
| 53 | } | 70 | } |
| 54 | 71 | ||
| 55 | void __init pci_xen_swiotlb_init(void) | 72 | void __init pci_xen_swiotlb_init(void) |
| 56 | { | 73 | { |
| 57 | if (xen_swiotlb) { | 74 | if (xen_swiotlb) { |
| 58 | xen_swiotlb_init(1); | 75 | xen_swiotlb_init(1, true /* early */); |
| 59 | dma_ops = &xen_swiotlb_dma_ops; | 76 | dma_ops = &xen_swiotlb_dma_ops; |
| 60 | 77 | ||
| 61 | /* Make sure ACS will be enabled */ | 78 | /* Make sure ACS will be enabled */ |
| 62 | pci_request_acs(); | 79 | pci_request_acs(); |
| 63 | } | 80 | } |
| 64 | } | 81 | } |
| 82 | |||
| 83 | int pci_xen_swiotlb_init_late(void) | ||
| 84 | { | ||
| 85 | int rc; | ||
| 86 | |||
| 87 | if (xen_swiotlb) | ||
| 88 | return 0; | ||
| 89 | |||
| 90 | rc = xen_swiotlb_init(1, false /* late */); | ||
| 91 | if (rc) | ||
| 92 | return rc; | ||
| 93 | |||
| 94 | dma_ops = &xen_swiotlb_dma_ops; | ||
| 95 | /* Make sure ACS will be enabled */ | ||
| 96 | pci_request_acs(); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late); | ||
| 101 | |||
| 65 | IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, | 102 | IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, |
| 66 | NULL, | 103 | NULL, |
| 67 | pci_xen_swiotlb_init, | 104 | pci_xen_swiotlb_init, |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index a4d901def8f2..7d6773535b67 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| 22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
| 23 | 23 | ||
| 24 | #include <asm/xen/swiotlb-xen.h> | ||
| 24 | #define INVALID_GRANT_REF (0) | 25 | #define INVALID_GRANT_REF (0) |
| 25 | #define INVALID_EVTCHN (-1) | 26 | #define INVALID_EVTCHN (-1) |
| 26 | 27 | ||
| @@ -668,7 +669,7 @@ static irqreturn_t pcifront_handler_aer(int irq, void *dev) | |||
| 668 | schedule_pcifront_aer_op(pdev); | 669 | schedule_pcifront_aer_op(pdev); |
| 669 | return IRQ_HANDLED; | 670 | return IRQ_HANDLED; |
| 670 | } | 671 | } |
| 671 | static int pcifront_connect(struct pcifront_device *pdev) | 672 | static int pcifront_connect_and_init_dma(struct pcifront_device *pdev) |
| 672 | { | 673 | { |
| 673 | int err = 0; | 674 | int err = 0; |
| 674 | 675 | ||
| @@ -681,9 +682,13 @@ static int pcifront_connect(struct pcifront_device *pdev) | |||
| 681 | dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n"); | 682 | dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n"); |
| 682 | err = -EEXIST; | 683 | err = -EEXIST; |
| 683 | } | 684 | } |
| 684 | |||
| 685 | spin_unlock(&pcifront_dev_lock); | 685 | spin_unlock(&pcifront_dev_lock); |
| 686 | 686 | ||
| 687 | if (!err && !swiotlb_nr_tbl()) { | ||
| 688 | err = pci_xen_swiotlb_init_late(); | ||
| 689 | if (err) | ||
| 690 | dev_err(&pdev->xdev->dev, "Could not setup SWIOTLB!\n"); | ||
| 691 | } | ||
| 687 | return err; | 692 | return err; |
| 688 | } | 693 | } |
| 689 | 694 | ||
| @@ -842,10 +847,10 @@ static int __devinit pcifront_try_connect(struct pcifront_device *pdev) | |||
| 842 | XenbusStateInitialised) | 847 | XenbusStateInitialised) |
| 843 | goto out; | 848 | goto out; |
| 844 | 849 | ||
| 845 | err = pcifront_connect(pdev); | 850 | err = pcifront_connect_and_init_dma(pdev); |
| 846 | if (err) { | 851 | if (err) { |
| 847 | xenbus_dev_fatal(pdev->xdev, err, | 852 | xenbus_dev_fatal(pdev->xdev, err, |
| 848 | "Error connecting PCI Frontend"); | 853 | "Error setting up PCI Frontend"); |
| 849 | goto out; | 854 | goto out; |
| 850 | } | 855 | } |
| 851 | 856 | ||
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 2e74dba6a04d..58db6df866ef 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
| @@ -144,31 +144,72 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) | |||
| 144 | } while (i < nslabs); | 144 | } while (i < nslabs); |
| 145 | return 0; | 145 | return 0; |
| 146 | } | 146 | } |
| 147 | static unsigned long xen_set_nslabs(unsigned long nr_tbl) | ||
| 148 | { | ||
| 149 | if (!nr_tbl) { | ||
| 150 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
| 151 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
| 152 | } else | ||
| 153 | xen_io_tlb_nslabs = nr_tbl; | ||
| 154 | |||
| 155 | return xen_io_tlb_nslabs << IO_TLB_SHIFT; | ||
| 156 | } | ||
| 157 | |||
| 158 | enum xen_swiotlb_err { | ||
| 159 | XEN_SWIOTLB_UNKNOWN = 0, | ||
| 160 | XEN_SWIOTLB_ENOMEM, | ||
| 161 | XEN_SWIOTLB_EFIXUP | ||
| 162 | }; | ||
| 147 | 163 | ||
| 148 | void __init xen_swiotlb_init(int verbose) | 164 | static const char *xen_swiotlb_error(enum xen_swiotlb_err err) |
| 149 | { | 165 | { |
| 150 | unsigned long bytes; | 166 | switch (err) { |
| 167 | case XEN_SWIOTLB_ENOMEM: | ||
| 168 | return "Cannot allocate Xen-SWIOTLB buffer\n"; | ||
| 169 | case XEN_SWIOTLB_EFIXUP: | ||
| 170 | return "Failed to get contiguous memory for DMA from Xen!\n"\ | ||
| 171 | "You either: don't have the permissions, do not have"\ | ||
| 172 | " enough free memory under 4GB, or the hypervisor memory"\ | ||
| 173 | " is too fragmented!"; | ||
| 174 | default: | ||
| 175 | break; | ||
| 176 | } | ||
| 177 | return ""; | ||
| 178 | } | ||
| 179 | int __ref xen_swiotlb_init(int verbose, bool early) | ||
| 180 | { | ||
| 181 | unsigned long bytes, order; | ||
| 151 | int rc = -ENOMEM; | 182 | int rc = -ENOMEM; |
| 152 | unsigned long nr_tbl; | 183 | enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; |
| 153 | char *m = NULL; | ||
| 154 | unsigned int repeat = 3; | 184 | unsigned int repeat = 3; |
| 155 | 185 | ||
| 156 | nr_tbl = swiotlb_nr_tbl(); | 186 | xen_io_tlb_nslabs = swiotlb_nr_tbl(); |
| 157 | if (nr_tbl) | ||
| 158 | xen_io_tlb_nslabs = nr_tbl; | ||
| 159 | else { | ||
| 160 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
| 161 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
| 162 | } | ||
| 163 | retry: | 187 | retry: |
| 164 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | 188 | bytes = xen_set_nslabs(xen_io_tlb_nslabs); |
| 165 | 189 | order = get_order(xen_io_tlb_nslabs << IO_TLB_SHIFT); | |
| 166 | /* | 190 | /* |
| 167 | * Get IO TLB memory from any location. | 191 | * Get IO TLB memory from any location. |
| 168 | */ | 192 | */ |
| 169 | xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); | 193 | if (early) |
| 194 | xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); | ||
| 195 | else { | ||
| 196 | #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT)) | ||
| 197 | #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT) | ||
| 198 | while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { | ||
| 199 | xen_io_tlb_start = (void *)__get_free_pages(__GFP_NOWARN, order); | ||
| 200 | if (xen_io_tlb_start) | ||
| 201 | break; | ||
| 202 | order--; | ||
| 203 | } | ||
| 204 | if (order != get_order(bytes)) { | ||
| 205 | pr_warn("Warning: only able to allocate %ld MB " | ||
| 206 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); | ||
| 207 | xen_io_tlb_nslabs = SLABS_PER_PAGE << order; | ||
| 208 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | ||
| 209 | } | ||
| 210 | } | ||
| 170 | if (!xen_io_tlb_start) { | 211 | if (!xen_io_tlb_start) { |
| 171 | m = "Cannot allocate Xen-SWIOTLB buffer!\n"; | 212 | m_ret = XEN_SWIOTLB_ENOMEM; |
| 172 | goto error; | 213 | goto error; |
| 173 | } | 214 | } |
| 174 | xen_io_tlb_end = xen_io_tlb_start + bytes; | 215 | xen_io_tlb_end = xen_io_tlb_start + bytes; |
| @@ -179,17 +220,22 @@ retry: | |||
| 179 | bytes, | 220 | bytes, |
| 180 | xen_io_tlb_nslabs); | 221 | xen_io_tlb_nslabs); |
| 181 | if (rc) { | 222 | if (rc) { |
| 182 | free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); | 223 | if (early) |
| 183 | m = "Failed to get contiguous memory for DMA from Xen!\n"\ | 224 | free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); |
| 184 | "You either: don't have the permissions, do not have"\ | 225 | else { |
| 185 | " enough free memory under 4GB, or the hypervisor memory"\ | 226 | free_pages((unsigned long)xen_io_tlb_start, order); |
| 186 | "is too fragmented!"; | 227 | xen_io_tlb_start = NULL; |
| 228 | } | ||
| 229 | m_ret = XEN_SWIOTLB_EFIXUP; | ||
| 187 | goto error; | 230 | goto error; |
| 188 | } | 231 | } |
| 189 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | 232 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); |
| 190 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | 233 | if (early) { |
| 191 | 234 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | |
| 192 | return; | 235 | rc = 0; |
| 236 | } else | ||
| 237 | rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); | ||
| 238 | return rc; | ||
| 193 | error: | 239 | error: |
| 194 | if (repeat--) { | 240 | if (repeat--) { |
| 195 | xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ | 241 | xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ |
| @@ -198,10 +244,13 @@ error: | |||
| 198 | (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); | 244 | (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); |
| 199 | goto retry; | 245 | goto retry; |
| 200 | } | 246 | } |
| 201 | xen_raw_printk("%s (rc:%d)", m, rc); | 247 | pr_err("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); |
| 202 | panic("%s (rc:%d)", m, rc); | 248 | if (early) |
| 249 | panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); | ||
| 250 | else | ||
| 251 | free_pages((unsigned long)xen_io_tlb_start, order); | ||
| 252 | return rc; | ||
| 203 | } | 253 | } |
| 204 | |||
| 205 | void * | 254 | void * |
| 206 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 255 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
| 207 | dma_addr_t *dma_handle, gfp_t flags, | 256 | dma_addr_t *dma_handle, gfp_t flags, |
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index e872526fdc5f..8d08b3ed406d 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h | |||
| @@ -25,6 +25,7 @@ extern int swiotlb_force; | |||
| 25 | extern void swiotlb_init(int verbose); | 25 | extern void swiotlb_init(int verbose); |
| 26 | extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); | 26 | extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); |
| 27 | extern unsigned long swiotlb_nr_tbl(void); | 27 | extern unsigned long swiotlb_nr_tbl(void); |
| 28 | extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs); | ||
| 28 | 29 | ||
| 29 | /* | 30 | /* |
| 30 | * Enumeration for sync targets | 31 | * Enumeration for sync targets |
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index c050b6b9de38..de8bcc641c49 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/swiotlb.h> | 4 | #include <linux/swiotlb.h> |
| 5 | 5 | ||
| 6 | extern void xen_swiotlb_init(int verbose); | 6 | extern int xen_swiotlb_init(int verbose, bool early); |
| 7 | 7 | ||
| 8 | extern void | 8 | extern void |
| 9 | *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 9 | *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 45bc1f83a5ad..f114bf6a8e13 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
| @@ -170,7 +170,7 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
| 170 | * Statically reserve bounce buffer space and initialize bounce buffer data | 170 | * Statically reserve bounce buffer space and initialize bounce buffer data |
| 171 | * structures for the software IO TLB used to implement the DMA API. | 171 | * structures for the software IO TLB used to implement the DMA API. |
| 172 | */ | 172 | */ |
| 173 | void __init | 173 | static void __init |
| 174 | swiotlb_init_with_default_size(size_t default_size, int verbose) | 174 | swiotlb_init_with_default_size(size_t default_size, int verbose) |
| 175 | { | 175 | { |
| 176 | unsigned long bytes; | 176 | unsigned long bytes; |
| @@ -206,8 +206,9 @@ swiotlb_init(int verbose) | |||
| 206 | int | 206 | int |
| 207 | swiotlb_late_init_with_default_size(size_t default_size) | 207 | swiotlb_late_init_with_default_size(size_t default_size) |
| 208 | { | 208 | { |
| 209 | unsigned long i, bytes, req_nslabs = io_tlb_nslabs; | 209 | unsigned long bytes, req_nslabs = io_tlb_nslabs; |
| 210 | unsigned int order; | 210 | unsigned int order; |
| 211 | int rc = 0; | ||
| 211 | 212 | ||
| 212 | if (!io_tlb_nslabs) { | 213 | if (!io_tlb_nslabs) { |
| 213 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); | 214 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); |
| @@ -229,16 +230,32 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
| 229 | order--; | 230 | order--; |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 232 | if (!io_tlb_start) | 233 | if (!io_tlb_start) { |
| 233 | goto cleanup1; | 234 | io_tlb_nslabs = req_nslabs; |
| 234 | 235 | return -ENOMEM; | |
| 236 | } | ||
| 235 | if (order != get_order(bytes)) { | 237 | if (order != get_order(bytes)) { |
| 236 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " | 238 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " |
| 237 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); | 239 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); |
| 238 | io_tlb_nslabs = SLABS_PER_PAGE << order; | 240 | io_tlb_nslabs = SLABS_PER_PAGE << order; |
| 239 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
| 240 | } | 241 | } |
| 242 | rc = swiotlb_late_init_with_tbl(io_tlb_start, io_tlb_nslabs); | ||
| 243 | if (rc) | ||
| 244 | free_pages((unsigned long)io_tlb_start, order); | ||
| 245 | return rc; | ||
| 246 | } | ||
| 247 | |||
| 248 | int | ||
| 249 | swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs) | ||
| 250 | { | ||
| 251 | unsigned long i, bytes; | ||
| 252 | |||
| 253 | bytes = nslabs << IO_TLB_SHIFT; | ||
| 254 | |||
| 255 | io_tlb_nslabs = nslabs; | ||
| 256 | io_tlb_start = tlb; | ||
| 241 | io_tlb_end = io_tlb_start + bytes; | 257 | io_tlb_end = io_tlb_start + bytes; |
| 258 | |||
| 242 | memset(io_tlb_start, 0, bytes); | 259 | memset(io_tlb_start, 0, bytes); |
| 243 | 260 | ||
| 244 | /* | 261 | /* |
| @@ -288,10 +305,8 @@ cleanup3: | |||
| 288 | io_tlb_list = NULL; | 305 | io_tlb_list = NULL; |
| 289 | cleanup2: | 306 | cleanup2: |
| 290 | io_tlb_end = NULL; | 307 | io_tlb_end = NULL; |
| 291 | free_pages((unsigned long)io_tlb_start, order); | ||
| 292 | io_tlb_start = NULL; | 308 | io_tlb_start = NULL; |
| 293 | cleanup1: | 309 | io_tlb_nslabs = 0; |
| 294 | io_tlb_nslabs = req_nslabs; | ||
| 295 | return -ENOMEM; | 310 | return -ENOMEM; |
| 296 | } | 311 | } |
| 297 | 312 | ||
