Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'stable/late-swiotlb.v3.3' into stable/for-linus-3.7

* stable/late-swiotlb.v3.3:
xen/swiotlb: Fix compile warnings when using plain integer instead of NULL pointer.
xen/swiotlb: Remove functions not needed anymore.
xen/pcifront: Use Xen-SWIOTLB when initting if required.
xen/swiotlb: For early initialization, return zero on success.
xen/swiotlb: Use the swiotlb_late_init_with_tbl to init Xen-SWIOTLB late when PV PCI is used.
xen/swiotlb: Move the error strings to its own function.
xen/swiotlb: Move the nr_tbl determination in its own function.
swiotlb: add the late swiotlb initialization function with iotlb memory
xen/swiotlb: With more than 4GB on 64-bit, disable the native SWIOTLB.
xen/swiotlb: Simplify the logic.

Conflicts:
arch/x86/xen/pci-swiotlb-xen.c

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

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