Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 316513 Details for
Bug 453680
Error in the uhci code causes usb not to work with iommu=calgary boot option
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Fixed mapping_error, sync_for_foo, alloc_consistent
linux-2.6.18-96.el5-453680-5.diff (text/plain), 9.47 KB, created by
Pete Zaitcev
on 2008-09-12 03:19:56 UTC
(
hide
)
Description:
Fixed mapping_error, sync_for_foo, alloc_consistent
Filename:
MIME Type:
Creator:
Pete Zaitcev
Created:
2008-09-12 03:19:56 UTC
Size:
9.47 KB
patch
obsolete
>Differences with the IBM's original: > 1. calgary_mapping_error and the reservation of a page in > calgary_reserve_region (io_tlb_overflow_buffer) > 2. Bug in unmap_sg that Prarit noticed > 3. Pass and fallback for ->sync_for_foo > 4. Off-by-one with end_pfn > 5. Tests for NULL in fallback tables AND > undo a segment in alloc_consistent, incase of nommu and NULL fallback > >diff -urp -X dontdiff linux-2.6.18-96.el5/arch/x86_64/kernel/pci-calgary.c linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-calgary.c >--- linux-2.6.18-96.el5/arch/x86_64/kernel/pci-calgary.c 2008-07-11 13:27:08.000000000 -0600 >+++ linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-calgary.c 2008-09-11 18:59:53.000000000 -0600 >@@ -43,11 +43,16 @@ > #include <asm/dma.h> > #include <asm/rio.h> > >+#ifdef CONFIG_SWIOTLB >+extern void *io_tlb_overflow_buffer; >+#endif >+ > #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT > int use_calgary __read_mostly = 1; > #else > int use_calgary __read_mostly = 0; > #endif /* CONFIG_CALGARY_DEFAULT_ENABLED */ >+const struct dma_mapping_ops* fallback_dma_ops; > > #define PCI_DEVICE_ID_IBM_CALGARY 0x02a1 > #define PCI_DEVICE_ID_IBM_CALIOC2 0x0308 >@@ -384,13 +389,25 @@ static inline struct iommu_table *find_i > return tbl; > } > >+static int calgary_mapping_error(dma_addr_t dma_addr) >+{ >+#ifdef CONFIG_SWIOTLB >+ if (fallback_dma_ops->mapping_error != NULL) { /* SWIOTLB */ >+ if (fallback_dma_ops->mapping_error(dma_addr)) >+ return 1; >+ /* We're not in the clear yet. This may be a Calgary address. */ >+ } >+#endif >+ return (dma_addr == bad_dma_address); >+} >+ > static void calgary_unmap_sg(struct device *dev, > struct scatterlist *sglist, int nelems, int direction) > { > struct iommu_table *tbl = find_iommu_table(dev); > > if (!translation_enabled(tbl)) >- return; >+ return fallback_dma_ops->unmap_sg(dev, sglist, nelems, direction); > > while (nelems--) { > unsigned int npages; >@@ -406,20 +423,6 @@ static void calgary_unmap_sg(struct devi > } > } > >-static int calgary_nontranslate_map_sg(struct device* dev, >- struct scatterlist *sg, int nelems, int direction) >-{ >- int i; >- >- for (i = 0; i < nelems; i++ ) { >- struct scatterlist *s = &sg[i]; >- BUG_ON(!s->page); >- s->dma_address = virt_to_bus(page_address(s->page) +s->offset); >- s->dma_length = s->length; >- } >- return nelems; >-} >- > static int calgary_map_sg(struct device *dev, struct scatterlist *sg, > int nelems, int direction) > { >@@ -430,7 +433,7 @@ static int calgary_map_sg(struct device > int i; > > if (!translation_enabled(tbl)) >- return calgary_nontranslate_map_sg(dev, sg, nelems, direction); >+ return fallback_dma_ops->map_sg(dev, sg, nelems, direction); > > for (i = 0; i < nelems; i++ ) { > struct scatterlist *s = &sg[i]; >@@ -473,13 +476,13 @@ static dma_addr_t calgary_map_single(str > unsigned int npages; > struct iommu_table *tbl = find_iommu_table(dev); > >+ if (!translation_enabled(tbl)) >+ return fallback_dma_ops->map_single(dev, vaddr, size, direction); >+ > uaddr = (unsigned long)vaddr; > npages = num_dma_pages(uaddr, size); > >- if (translation_enabled(tbl)) >- dma_handle = iommu_alloc(tbl, vaddr, npages, direction); >- else >- dma_handle = virt_to_bus(vaddr); >+ dma_handle = iommu_alloc(tbl, vaddr, npages, direction); > > return dma_handle; > } >@@ -490,8 +493,10 @@ static void calgary_unmap_single(struct > struct iommu_table *tbl = find_iommu_table(dev); > unsigned int npages; > >- if (!translation_enabled(tbl)) >+ if (!translation_enabled(tbl)) { >+ fallback_dma_ops->unmap_single(dev, dma_handle, size, direction); > return; >+ } > > npages = num_dma_pages(dma_handle, size); > iommu_free(tbl, dma_handle, npages); >@@ -505,6 +510,9 @@ static void* calgary_alloc_coherent(stru > unsigned int npages, order; > struct iommu_table *tbl = find_iommu_table(dev); > >+ if (!translation_enabled(tbl) && fallback_dma_ops->alloc_coherent) >+ return fallback_dma_ops->alloc_coherent(dev, size, dma_handle, flag); >+ > size = PAGE_ALIGN(size); /* size rounded up to full pages */ > npages = size >> PAGE_SHIFT; > order = get_order(size); >@@ -534,10 +542,87 @@ error: > return ret; > } > >+static void calgary_free_coherent(struct device *dev, size_t size, void *vaddr, >+ dma_addr_t dma_addr) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) && fallback_dma_ops->free_coherent) >+ fallback_dma_ops->free_coherent(dev, size, vaddr, dma_addr); >+} >+ >+static void calgary_sync_single_for_cpu(struct device *dev, >+ dma_addr_t dma_addr, size_t size, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) && fallback_dma_ops->sync_single_for_cpu) >+ fallback_dma_ops->sync_single_for_cpu(dev, dma_addr, size, dir); >+} >+ >+static void calgary_sync_single_for_device(struct device *dev, >+ dma_addr_t dma_addr, size_t size, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) && fallback_dma_ops->sync_single_for_device) >+ fallback_dma_ops->sync_single_for_device(dev, dma_addr, size, dir); >+} >+ >+static void calgary_sync_single_range_for_cpu(struct device *dev, >+ dma_addr_t dma_addr, unsigned long offset, size_t size, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) >+ && fallback_dma_ops->sync_single_range_for_cpu) >+ fallback_dma_ops->sync_single_range_for_cpu(dev, >+ dma_addr, offset, size, dir); >+} >+ >+static void calgary_sync_single_range_for_device(struct device *dev, >+ dma_addr_t dma_addr, unsigned long offset, size_t size, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) >+ && fallback_dma_ops->sync_single_range_for_device) >+ fallback_dma_ops->sync_single_range_for_device(dev, >+ dma_addr, offset, size, dir); >+} >+ >+static void calgary_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, >+ int nelems, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) >+ && fallback_dma_ops->sync_sg_for_cpu) >+ fallback_dma_ops->sync_sg_for_cpu(dev, sg, nelems, dir); >+} >+ >+static void calgary_sync_sg_for_device(struct device *dev, struct scatterlist *sg, >+ int nelems, int dir) >+{ >+ struct iommu_table *tbl = find_iommu_table(dev); >+ >+ if (!translation_enabled(tbl) >+ && fallback_dma_ops->sync_sg_for_device) >+ fallback_dma_ops->sync_sg_for_device(dev, sg, nelems, dir); >+} >+ > static struct dma_mapping_ops calgary_dma_ops = { >+ .mapping_error = calgary_mapping_error, > .alloc_coherent = calgary_alloc_coherent, >+ .free_coherent = calgary_free_coherent, > .map_single = calgary_map_single, > .unmap_single = calgary_unmap_single, >+ .sync_single_for_cpu = calgary_sync_single_for_cpu, >+ .sync_single_for_device = calgary_sync_single_for_device, >+ .sync_single_range_for_cpu = calgary_sync_single_range_for_cpu, >+ .sync_single_range_for_device = calgary_sync_single_range_for_device, >+ .sync_sg_for_cpu = calgary_sync_sg_for_cpu, >+ .sync_sg_for_device = calgary_sync_sg_for_device, > .map_sg = calgary_map_sg, > .unmap_sg = calgary_unmap_sg, > }; >@@ -791,6 +876,12 @@ static void __init calgary_reserve_regio > > /* reserve EMERGENCY_PAGES from bad_dma_address and up */ > iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES); >+#ifdef CONFIG_SWIOTLB >+ if (fallback_dma_ops->mapping_error != NULL) { /* SWIOTLB */ >+ dma_addr_t addr = virt_to_phys(io_tlb_overflow_buffer); >+ iommu_range_reserve(tbl, addr, 1); /* Checks range */ >+ } >+#endif > > /* avoid the BIOS/VGA first 640KB-1MB region */ > /* for CalIOC2 - avoid the entire first MB */ >diff -urp -X dontdiff linux-2.6.18-96.el5/arch/x86_64/kernel/pci-nommu.c linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-nommu.c >--- linux-2.6.18-96.el5/arch/x86_64/kernel/pci-nommu.c 2006-09-19 21:42:06.000000000 -0600 >+++ linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-nommu.c 2008-08-27 12:57:51.000000000 -0600 >@@ -9,6 +9,7 @@ > #include <asm/proto.h> > #include <asm/processor.h> > #include <asm/dma.h> >+#include <asm/calgary.h> > > static int > check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size) >@@ -90,6 +91,11 @@ struct dma_mapping_ops nommu_dma_ops = { > > void __init no_iommu_init(void) > { >+#ifdef CONFIG_CALGARY_IOMMU >+ if (use_calgary && (end_pfn <= MAX_DMA32_PFN)) >+ fallback_dma_ops = &nommu_dma_ops; >+#endif >+ > if (dma_ops) > return; > >diff -urp -X dontdiff linux-2.6.18-96.el5/arch/x86_64/kernel/pci-swiotlb.c linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-swiotlb.c >--- linux-2.6.18-96.el5/arch/x86_64/kernel/pci-swiotlb.c 2006-09-19 21:42:06.000000000 -0600 >+++ linux-2.6.18-96.el5-453680/arch/x86_64/kernel/pci-swiotlb.c 2008-08-27 13:49:44.000000000 -0600 >@@ -7,6 +7,7 @@ > #include <asm/proto.h> > #include <asm/swiotlb.h> > #include <asm/dma.h> >+#include <asm/calgary.h> > > int swiotlb __read_mostly; > EXPORT_SYMBOL(swiotlb); >@@ -39,5 +40,12 @@ void pci_swiotlb_init(void) > printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); > swiotlb_init(); > dma_ops = &swiotlb_dma_ops; >+ } else { >+#ifdef CONFIG_CALGARY_IOMMU >+ if (use_calgary && (end_pfn > MAX_DMA32_PFN)) { >+ swiotlb_init(); >+ fallback_dma_ops = &swiotlb_dma_ops; >+ } >+#endif > } > } >diff -urp -X dontdiff linux-2.6.18-96.el5/include/asm-x86_64/calgary.h linux-2.6.18-96.el5-453680/include/asm-x86_64/calgary.h >--- linux-2.6.18-96.el5/include/asm-x86_64/calgary.h 2008-07-11 13:27:08.000000000 -0600 >+++ linux-2.6.18-96.el5-453680/include/asm-x86_64/calgary.h 2008-08-26 17:54:10.000000000 -0600 >@@ -60,6 +60,7 @@ struct cal_chipset_ops { > #define TCE_TABLE_SIZE_8M 7 > > extern int use_calgary; >+extern const struct dma_mapping_ops* fallback_dma_ops; > > #ifdef CONFIG_CALGARY_IOMMU > extern int calgary_iommu_init(void);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 453680
:
310722
|
310723
|
315160
| 316513 |
316864
|
324530