aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-09-22 20:01:16 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-09-22 20:01:24 -0400
commita5f95155709cb854e96aa27969d110668cdbda9d (patch)
treec9392d6871184838bf81a0b70900e28558e92870
parentc571898ffc24a1768e1b2dabeac0fc7dd4c14601 (diff)
parent2a3bce8f6afb9118a7ac3c360a5baf7cdaec87bc (diff)
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>
-rw-r--r--arch/x86/include/asm/xen/swiotlb-xen.h2
-rw-r--r--arch/x86/xen/pci-swiotlb-xen.c47
-rw-r--r--drivers/pci/xen-pcifront.c13
-rw-r--r--drivers/xen/swiotlb-xen.c101
-rw-r--r--include/linux/swiotlb.h1
-rw-r--r--include/xen/swiotlb-xen.h2
-rw-r--r--lib/swiotlb.c33
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 @@
5extern int xen_swiotlb; 5extern int xen_swiotlb;
6extern int __init pci_xen_swiotlb_detect(void); 6extern int __init pci_xen_swiotlb_detect(void);
7extern void __init pci_xen_swiotlb_init(void); 7extern void __init pci_xen_swiotlb_init(void);
8extern int pci_xen_swiotlb_init_late(void);
8#else 9#else
9#define xen_swiotlb (0) 10#define xen_swiotlb (0)
10static inline int __init pci_xen_swiotlb_detect(void) { return 0; } 11static inline int __init pci_xen_swiotlb_detect(void) { return 0; }
11static inline void __init pci_xen_swiotlb_init(void) { } 12static inline void __init pci_xen_swiotlb_init(void) { }
13static 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
12int xen_swiotlb __read_mostly; 19int xen_swiotlb __read_mostly;
13 20
14static struct dma_map_ops xen_swiotlb_dma_ops = { 21static struct dma_map_ops xen_swiotlb_dma_ops = {
@@ -35,33 +42,63 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
35int __init pci_xen_swiotlb_detect(void) 42int __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
55void __init pci_xen_swiotlb_init(void) 72void __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
83int 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}
100EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late);
101
65IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, 102IOMMU_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}
671static int pcifront_connect(struct pcifront_device *pdev) 672static 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}
147static 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
158enum xen_swiotlb_err {
159 XEN_SWIOTLB_UNKNOWN = 0,
160 XEN_SWIOTLB_ENOMEM,
161 XEN_SWIOTLB_EFIXUP
162};
147 163
148void __init xen_swiotlb_init(int verbose) 164static 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}
179int __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 }
163retry: 187retry:
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;
193error: 239error:
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
205void * 254void *
206xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, 255xen_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;
25extern void swiotlb_init(int verbose); 25extern void swiotlb_init(int verbose);
26extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); 26extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
27extern unsigned long swiotlb_nr_tbl(void); 27extern unsigned long swiotlb_nr_tbl(void);
28extern 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
6extern void xen_swiotlb_init(int verbose); 6extern int xen_swiotlb_init(int verbose, bool early);
7 7
8extern void 8extern 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 */
173void __init 173static void __init
174swiotlb_init_with_default_size(size_t default_size, int verbose) 174swiotlb_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)
206int 206int
207swiotlb_late_init_with_default_size(size_t default_size) 207swiotlb_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
248int
249swiotlb_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;
289cleanup2: 306cleanup2:
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;
293cleanup1: 309 io_tlb_nslabs = 0;
294 io_tlb_nslabs = req_nslabs;
295 return -ENOMEM; 310 return -ENOMEM;
296} 311}
297 312