* Problems with dma_alloc_coherent()
@ 2004-04-01 15:59 John Whitney
2004-04-01 16:30 ` John Whitney
` (3 more replies)
0 siblings, 4 replies; 36+ messages in thread
From: John Whitney @ 2004-04-01 15:59 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1465 bytes --]
In the process of reworking my Generic DMA core for the 2.6 kernel, I
noticed that dma_alloc_coherent() returns NULL in all cases on a
cache-coherent platform. Instead, I think it would be better if this
routine returned a block of contiguous memory (not cache-inhibited), as
pci_alloc_consistent() does.
To that end, I am submitting the attached patch which modifies
dma_alloc_coherent() and dma_free_coherent() to do just this for
cache-coherent platforms.
I was going to add a check for dev->dma_mask in dma_alloc_coherent()
(to add GFP_DMA to the flags), but the dma_supported() macro always
returns 1, which would indicate that this is superfluous.
John
--- dma-mapping.h.orig 2004-04-01 10:38:33.000000000 -0500
+++ dma-mapping.h 2004-04-01 10:49:32.000000000 -0500
@@ -35,7 +35,18 @@
return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
#endif
- return consistent_alloc(flag, size, dma_handle);
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ return consistent_alloc(flag, size, dma_handle);
+#else
+ void *ret;
+
+ ret = (void *)__get_free_pages(flag, get_order(size));
+ if (ret != NULL) {
+ *dma_handle = virt_to_bus(ret);
+ }
+
+ return ret;
+#endif /* CONFIG_NOT_COHERENT_CACHE */
}
static inline void
@@ -49,7 +60,11 @@
}
#endif
- consistent_free(vaddr);
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ consistent_free(vaddr, size);
+#else
+ free_pages((unsigned long)vaddr, get_order(size));
+#endif
}
static inline dma_addr_t
[-- Attachment #2: dma-mapping.h.patch --]
[-- Type: application/octet-stream, Size: 791 bytes --]
--- dma-mapping.h.orig 2004-04-01 10:38:33.000000000 -0500
+++ dma-mapping.h 2004-04-01 10:49:32.000000000 -0500
@@ -35,7 +35,18 @@
return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
#endif
- return consistent_alloc(flag, size, dma_handle);
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ return consistent_alloc(flag, size, dma_handle);
+#else
+ void *ret;
+
+ ret = (void *)__get_free_pages(flag, get_order(size));
+ if (ret != NULL) {
+ *dma_handle = virt_to_bus(ret);
+ }
+
+ return ret;
+#endif /* CONFIG_NOT_COHERENT_CACHE */
}
static inline void
@@ -49,7 +60,11 @@
}
#endif
- consistent_free(vaddr);
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ consistent_free(vaddr, size);
+#else
+ free_pages((unsigned long)vaddr, get_order(size));
+#endif
}
static inline dma_addr_t
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: Problems with dma_alloc_coherent() 2004-04-01 15:59 Problems with dma_alloc_coherent() John Whitney @ 2004-04-01 16:30 ` John Whitney 2004-04-01 16:51 ` Dan Malek ` (2 subsequent siblings) 3 siblings, 0 replies; 36+ messages in thread From: John Whitney @ 2004-04-01 16:30 UTC (permalink / raw) To: linuxppc-dev [-- Attachment #1: Type: text/plain, Size: 827 bytes --] Whoops. I accidentally had some previous changes in the patch I submitted. Here is the cleaned up version. --- dma-mapping.h.orig 2004-04-01 10:38:33.000000000 -0500 +++ dma-mapping.h 2004-04-01 11:27:44.000000000 -0500 @@ -35,7 +35,18 @@ return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); #endif +#ifdef CONFIG_NOT_COHERENT_CACHE return consistent_alloc(flag, size, dma_handle); +#else + void *ret; + + ret = (void *)__get_free_pages(flag, get_order(size)); + if (ret != NULL) { + *dma_handle = virt_to_bus(ret); + } + + return ret; +#endif /* CONFIG_NOT_COHERENT_CACHE */ } static inline void @@ -49,7 +60,11 @@ } #endif +#ifdef CONFIG_NOT_COHERENT_CACHE consistent_free(vaddr); +#else + free_pages((unsigned long)vaddr, get_order(size)); +#endif } static inline dma_addr_t [-- Attachment #2: dma-mapping.h.patch --] [-- Type: application/octet-stream, Size: 705 bytes --] --- dma-mapping.h.orig 2004-04-01 10:38:33.000000000 -0500 +++ dma-mapping.h 2004-04-01 11:27:44.000000000 -0500 @@ -35,7 +35,18 @@ return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); #endif +#ifdef CONFIG_NOT_COHERENT_CACHE return consistent_alloc(flag, size, dma_handle); +#else + void *ret; + + ret = (void *)__get_free_pages(flag, get_order(size)); + if (ret != NULL) { + *dma_handle = virt_to_bus(ret); + } + + return ret; +#endif /* CONFIG_NOT_COHERENT_CACHE */ } static inline void @@ -49,7 +60,11 @@ } #endif +#ifdef CONFIG_NOT_COHERENT_CACHE consistent_free(vaddr); +#else + free_pages((unsigned long)vaddr, get_order(size)); +#endif } static inline dma_addr_t ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 15:59 Problems with dma_alloc_coherent() John Whitney 2004-04-01 16:30 ` John Whitney @ 2004-04-01 16:51 ` Dan Malek 2004-04-01 17:01 ` Tom Rini 2004-04-01 17:05 ` Matt Porter 3 siblings, 0 replies; 36+ messages in thread From: Dan Malek @ 2004-04-01 16:51 UTC (permalink / raw) To: John Whitney; +Cc: linuxppc-dev John Whitney wrote: > To that end, I am submitting the attached patch which modifies > dma_alloc_coherent() and dma_free_coherent() to do just this for > cache-coherent platforms. I think you should change/implement consistent_alloc()/free() to do the right thing rather that use the #ifdef here. Also, ensure the ancillary function (like the dma sync/sg functions) work properly as well. They are probably no-ops (well, not the sg functions) but look for those anyway. There are also reasons to allocate un-cached DMA regions on cache coherent platforms (but I will not debate the value in doing so), so keep that under consideration. Thanks. -- Dan ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 15:59 Problems with dma_alloc_coherent() John Whitney 2004-04-01 16:30 ` John Whitney 2004-04-01 16:51 ` Dan Malek @ 2004-04-01 17:01 ` Tom Rini 2004-04-01 17:05 ` Matt Porter 3 siblings, 0 replies; 36+ messages in thread From: Tom Rini @ 2004-04-01 17:01 UTC (permalink / raw) To: John Whitney; +Cc: linuxppc-dev On Thu, Apr 01, 2004 at 10:59:56AM -0500, John Whitney wrote: > In the process of reworking my Generic DMA core for the 2.6 kernel, I > noticed that dma_alloc_coherent() returns NULL in all cases on a > cache-coherent platform. Instead, I think it would be better if this > routine returned a block of contiguous memory (not cache-inhibited), as > pci_alloc_consistent() does. > > To that end, I am submitting the attached patch which modifies > dma_alloc_coherent() and dma_free_coherent() to do just this for > cache-coherent platforms. > I was going to add a check for dev->dma_mask in dma_alloc_coherent() > (to add GFP_DMA to the flags), but the dma_supported() macro always > returns 1, which would indicate that this is superfluous. I'd like to suggest that what we do is make dma_alloc_coherent and dma_free_coherent steal the logic of pci_alloc/free_consistent outright, moving us one step closer to using <asm-generic/pci-dma-compat.h> (PCI DMA API implemented in terms of the generic DMA API). -- Tom Rini http://gate.crashing.org/~trini/ ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 15:59 Problems with dma_alloc_coherent() John Whitney ` (2 preceding siblings ...) 2004-04-01 17:01 ` Tom Rini @ 2004-04-01 17:05 ` Matt Porter 2004-04-01 17:51 ` John Whitney 3 siblings, 1 reply; 36+ messages in thread From: Matt Porter @ 2004-04-01 17:05 UTC (permalink / raw) To: John Whitney; +Cc: linuxppc-dev On Thu, Apr 01, 2004 at 10:59:56AM -0500, John Whitney wrote: > In the process of reworking my Generic DMA core for the 2.6 kernel, I > noticed that dma_alloc_coherent() returns NULL in all cases on a > cache-coherent platform. Instead, I think it would be better if this > routine returned a block of contiguous memory (not cache-inhibited), as > pci_alloc_consistent() does. Yeah, that's really broken. The changeover to dma-mapping.h is incomplete. Tom and I were just talking about this because I think it exposes a bigger problem. What I originally wanted was the PCI DMA API defined in terms of the generic DMA API on ppc32. He just pointed out asm-generic/pci-dma-compat.h that we can leverage to do that. > To that end, I am submitting the attached patch which modifies > dma_alloc_coherent() and dma_free_coherent() to do just this for > cache-coherent platforms. Your patch fixes the problem but exposes the bigger issue that we are starting to duplicate code since on ppc32 PCI DMA API and DMA API are handled the same on the backend. In the meantime (I think Tom volunteered to clean this up!), I think this needs to go in so we are at least functional. -Matt ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 17:05 ` Matt Porter @ 2004-04-01 17:51 ` John Whitney 2004-04-01 18:16 ` Matt Porter 2004-04-01 18:19 ` Eugene Surovegin 0 siblings, 2 replies; 36+ messages in thread From: John Whitney @ 2004-04-01 17:51 UTC (permalink / raw) To: Matt Porter; +Cc: linuxppc-dev > > Yeah, that's really broken. The changeover to dma-mapping.h is > incomplete. Tom and I were just talking about this because I > think it exposes a bigger problem. What I originally wanted > was the PCI DMA API defined in terms of the generic DMA API > on ppc32. He just pointed out asm-generic/pci-dma-compat.h that > we can leverage to do that. > I noticed that all the PCI and DMA coherency routines seem to assume that DMA will occur between memory and a bus device (all physical addresses returned are converted to a bus address). Is this really the desired action? I would have prefered to have the PCI routines return bus-correct physical addresses, and the DMA routines return processor physical addresses (so they can be used for non-bus-related DMA, to a direct memory-mapped encryption chip, for example). Is this the eventual implementation of those functions, or are all DMA transactions expected to be to or from a PCI-based device? John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 17:51 ` John Whitney @ 2004-04-01 18:16 ` Matt Porter 2004-04-01 18:19 ` Eugene Surovegin 1 sibling, 0 replies; 36+ messages in thread From: Matt Porter @ 2004-04-01 18:16 UTC (permalink / raw) To: John Whitney; +Cc: Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 12:51:54PM -0500, John Whitney wrote: > > > > Yeah, that's really broken. The changeover to dma-mapping.h is > > incomplete. Tom and I were just talking about this because I > > think it exposes a bigger problem. What I originally wanted > > was the PCI DMA API defined in terms of the generic DMA API > > on ppc32. He just pointed out asm-generic/pci-dma-compat.h that > > we can leverage to do that. > > > > I noticed that all the PCI and DMA coherency routines seem to assume > that DMA will occur between memory and a bus device (all physical > addresses returned are converted to a bus address). Is this really the > desired action? I would have prefered to have the PCI routines return > bus-correct physical addresses, and the DMA routines return processor > physical addresses (so they can be used for non-bus-related DMA, to a > direct memory-mapped encryption chip, for example). Is this the > eventual implementation of those functions, or are all DMA transactions > expected to be to or from a PCI-based device? Yes, the DMA API and PCI DMA API have been stated (repeatedly) to be _only_ for [system memory]<->[device]. Trying to use them otherwise is incorrect. I believe DaveM's suggestion was, "If you want a device-to-device DMA API then create a separate one". It's another thing that embedded people will have to take the time to introduce...but most embedded Linux people are too busy with their apps on 2.4, maintaining boards, etc. to fix kernel APIs. Don't expect the desktop/server folks to care. :) -Matt ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 17:51 ` John Whitney 2004-04-01 18:16 ` Matt Porter @ 2004-04-01 18:19 ` Eugene Surovegin 2004-04-01 18:33 ` Eugene Surovegin ` (2 more replies) 1 sibling, 3 replies; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 18:19 UTC (permalink / raw) To: John Whitney; +Cc: Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 12:51:54PM -0500, John Whitney wrote: > I noticed that all the PCI and DMA coherency routines seem to assume > that DMA will occur between memory and a bus device (all physical > addresses returned are converted to a bus address). Is this really the > desired action? I would have prefered to have the PCI routines return > bus-correct physical addresses, and the DMA routines return processor > physical addresses (so they can be used for non-bus-related DMA, to a > direct memory-mapped encryption chip, for example). Is this the > eventual implementation of those functions, or are all DMA transactions > expected to be to or from a PCI-based device? Hmm, I don't understand this, bus != PCI bus. All devices sit on some kind of bus, even your encryption chip. As far as I understand, DMA API was added exactly because we may have different (from PCI) buses. Current implementation just relies on the fact that PCI devices view system memory the same way as other-bus devices (e.g. OCP devices which sit on OPB). In more general case, yes, "views" can be different for each bus type or even for each bus... Eugene. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:19 ` Eugene Surovegin @ 2004-04-01 18:33 ` Eugene Surovegin 2004-04-01 18:33 ` John Whitney 2004-04-01 18:55 ` Dan Malek 2 siblings, 0 replies; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 18:33 UTC (permalink / raw) To: John Whitney; +Cc: Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 10:19:26AM -0800, Eugene Surovegin wrote: > On Thu, Apr 01, 2004 at 12:51:54PM -0500, John Whitney wrote: > > I noticed that all the PCI and DMA coherency routines seem to assume > > that DMA will occur between memory and a bus device (all physical > > addresses returned are converted to a bus address). Is this really the > > desired action? I would have prefered to have the PCI routines return > > bus-correct physical addresses, and the DMA routines return processor > > physical addresses (so they can be used for non-bus-related DMA, to a > > direct memory-mapped encryption chip, for example). Is this the > > eventual implementation of those functions, or are all DMA transactions > > expected to be to or from a PCI-based device? > > Hmm, I don't understand this, bus != PCI bus. All devices sit on some kind of > bus, even your encryption chip. > > As far as I understand, DMA API was added exactly because we may have different > (from PCI) buses. > > Current implementation just relies on the fact that PCI devices view system > memory the same way as other-bus devices (e.g. OCP devices which sit on OPB). > > In more general case, yes, "views" can be different for each bus type or even > for each bus... Let me clarify my point. You are right that returning PCI-bus address _may_ not be very good. I think it's OK for now, because it should work for the reason I pointed earlier. In future, implementation may change... What you are proposing isn't better than the current PCI-bus addresses. Phys address is just an address on processor local bus, so changing PCI-bus as a default to PLB as a default doesn't seem wise. Correct implementation should devise DMA-addresses (and actual bus) from the _device_ passed to DMA API function... Eugene. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:19 ` Eugene Surovegin 2004-04-01 18:33 ` Eugene Surovegin @ 2004-04-01 18:33 ` John Whitney 2004-04-01 18:40 ` Eugene Surovegin 2004-04-01 18:55 ` Dan Malek 2 siblings, 1 reply; 36+ messages in thread From: John Whitney @ 2004-04-01 18:33 UTC (permalink / raw) To: Eugene Surovegin; +Cc: linuxppc-dev, Matt Porter > Hmm, I don't understand this, bus != PCI bus. All devices sit on some > kind of > bus, even your encryption chip. > Yes, but both pci_alloc_consistent() and dma_alloc_coherent() return physical addresses made with virt_to_bus() (at least they do in the PowerPC tree). This routine specifically adds the PCI-bus view of the address space to the physical address produced. I don't understand why two different APIs are needed, if they both do the same thing. This means that the address produced by pci_alloc_... and dma_alloc_... are incorrect for a device like a direct memory-mapped encryption chip, or in my case a northbridge DMA controller. John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:33 ` John Whitney @ 2004-04-01 18:40 ` Eugene Surovegin 2004-04-01 18:48 ` John Whitney 0 siblings, 1 reply; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 18:40 UTC (permalink / raw) To: John Whitney; +Cc: linuxppc-dev, Matt Porter On Thu, Apr 01, 2004 at 01:33:42PM -0500, John Whitney wrote: > Yes, but both pci_alloc_consistent() and dma_alloc_coherent() return > physical addresses made with virt_to_bus() (at least they do in the > PowerPC tree). This routine specifically adds the PCI-bus view of the > address space to the physical address produced. I don't understand why > two different APIs are needed, if they both do the same thing. They do the same thing _now_, because it's a _new_ API. This _may_ change in future. DMA API is needed, because generic code uses it, most archs have default generic implementation which use PCI DMA API and I don't see _any_ problems with that. Some archs may have _different_ implementations which DON'T use PCI DMA API. > > This means that the address produced by pci_alloc_... and dma_alloc_... > are incorrect for a device like a direct memory-mapped encryption chip, > or in my case a northbridge DMA controller. It depends, on all systems I use PCI view == phys address, so it'll work. Eugene ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:40 ` Eugene Surovegin @ 2004-04-01 18:48 ` John Whitney 0 siblings, 0 replies; 36+ messages in thread From: John Whitney @ 2004-04-01 18:48 UTC (permalink / raw) To: Eugene Surovegin; +Cc: linuxppc-dev, Matt Porter > They do the same thing _now_, because it's a _new_ API. This _may_ > change in > future. > > DMA API is needed, because generic code uses it, most archs have > default generic > implementation which use PCI DMA API and I don't see _any_ problems > with that. > > Some archs may have _different_ implementations which DON'T use PCI > DMA API. > >> >> This means that the address produced by pci_alloc_... and >> dma_alloc_... >> are incorrect for a device like a direct memory-mapped encryption >> chip, >> or in my case a northbridge DMA controller. > > It depends, on all systems I use PCI view == phys address, so it'll > work. > And in actuality, it will work in my case as well. However, it won't work for some single-board computers I've worked on, so I'd like to have an API that works for everything. It would be nice if there was a dma_bus_offset field in the device structure that got set by the device creator. PCI devices would get PCI_DRAM_OFFSET, PLB devices would get 0, OCP devices would get whatever they need. Then the API could add the appropriate offset for the device passed in, rather than relying on the static virt_to_bus() mapping, which is PCI specific. As a default, with a NULL device given, I think it should return a PLB physical address. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:19 ` Eugene Surovegin 2004-04-01 18:33 ` Eugene Surovegin 2004-04-01 18:33 ` John Whitney @ 2004-04-01 18:55 ` Dan Malek 2004-04-01 18:59 ` Eugene Surovegin 2 siblings, 1 reply; 36+ messages in thread From: Dan Malek @ 2004-04-01 18:55 UTC (permalink / raw) To: Eugene Surovegin; +Cc: John Whitney, Matt Porter, linuxppc-dev Eugene Surovegin wrote: > Hmm, I don't understand this, bus != PCI bus. Isn't that necessary due to bridge windows? If != PCI bus I guess we assume OCP that are connected to a 1:1 mapped internal bus, which may not be a valid assumption either. > Current implementation just relies on the fact that PCI devices view system > memory the same way as other-bus devices (e.g. OCP devices which sit on OPB). I don't think so. PCI devices are known to go through bridges, while others are assumed to not. > In more general case, yes, "views" can be different for each bus type or even > for each bus... So, we should always have some kind of 'bus type' device handle, that provides this information. It's clear that all Linux APIs are designed from the viewpoint of PC-like workstations. They have always fallen very short when pressed into the more prevalent embedded computing space :-) -- Dan ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:55 ` Dan Malek @ 2004-04-01 18:59 ` Eugene Surovegin 2004-04-01 19:10 ` John Whitney 2004-04-01 20:49 ` Matt Porter 0 siblings, 2 replies; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 18:59 UTC (permalink / raw) To: Dan Malek; +Cc: John Whitney, Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 01:55:10PM -0500, Dan Malek wrote: > >Current implementation just relies on the fact that PCI devices view system > >memory the same way as other-bus devices (e.g. OCP devices which sit on > >OPB). > > I don't think so. PCI devices are known to go through bridges, while > others are assumed to not. Well, bridge doesn't necessarily mean there is an address translation :). Currently 4xx systems (not sure all, at least ones I use) use PCI == phys address mapping, and yes, bridge is setup so this is the case. Although, I understand in more general case, bridge will translate address. > >In more general case, yes, "views" can be different for each bus type or > >even > >for each bus... > > So, we should always have some kind of 'bus type' device handle, that > provides > this information. It's clear that all Linux APIs are designed from the > viewpoint of PC-like workstations. They have always fallen very short when > pressed into the more prevalent embedded computing space :-) I think we should use "device" parameter passed to DMA API for such stuff, it already has a member "struct bus_type* bus". Eugene ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:59 ` Eugene Surovegin @ 2004-04-01 19:10 ` John Whitney 2004-04-01 19:17 ` Eugene Surovegin 2004-04-02 5:45 ` Christoph Hellwig 2004-04-01 20:49 ` Matt Porter 1 sibling, 2 replies; 36+ messages in thread From: John Whitney @ 2004-04-01 19:10 UTC (permalink / raw) To: Eugene Surovegin; +Cc: Dan Malek, Matt Porter, linuxppc-dev > I think we should use "device" parameter passed to DMA API for such > stuff, it > already has a member "struct bus_type* bus". > This effectively makes the DMA API a superset of the PCI DMA API (the DMA API would recognize a PCI device, and handle it accordingly)? It sounds like a good solution to me, although I'd like to see the "device" structure get that DMA offset I mentioned, so the DMA API wouldn't have to have a special case for each new bus-type added (PLB, PCI, OCP, CPM, whatever), as it does now for PCI vs. non-PCI. (That assumes bus offset is the only difference that needs to be handled...) ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 19:10 ` John Whitney @ 2004-04-01 19:17 ` Eugene Surovegin 2004-04-01 19:35 ` John Whitney 2004-04-01 20:52 ` Michael R. Zucca 2004-04-02 5:45 ` Christoph Hellwig 1 sibling, 2 replies; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 19:17 UTC (permalink / raw) To: John Whitney; +Cc: Dan Malek, Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 02:10:00PM -0500, John Whitney wrote: > >I think we should use "device" parameter passed to DMA API for such > >stuff, it > >already has a member "struct bus_type* bus". > > > > This effectively makes the DMA API a superset of the PCI DMA API (the > DMA API would recognize a PCI device, and handle it accordingly)? Yes, I think it's a goal. > It > sounds like a good solution to me, although I'd like to see the > "device" structure get that DMA offset I mentioned, so the DMA API > wouldn't have to have a special case for each new bus-type added (PLB, > PCI, OCP, CPM, whatever), as it does now for PCI vs. non-PCI. (That > assumes bus offset is the only difference that needs to be handled...) I think we should add such info to a structure which describes the _bus_, not _device_. I'm not "new-device-model" guru, so I cannot comment _how_ this can be implemented though :) Eugene. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 19:17 ` Eugene Surovegin @ 2004-04-01 19:35 ` John Whitney 2004-04-01 20:52 ` Michael R. Zucca 1 sibling, 0 replies; 36+ messages in thread From: John Whitney @ 2004-04-01 19:35 UTC (permalink / raw) To: Eugene Surovegin; +Cc: Dan Malek, Matt Porter, linuxppc-dev > I think we should add such info to a structure which describes the > _bus_, not > _device_. > I'm not "new-device-model" guru, so I cannot comment _how_ this can be > implemented though :) Yes, after thinking about it, it made more sense to modify the "struct bus_type" structure to have the bus memory map offset. We could then have an OCP bus type, PLB bus type, etc. However, that would be a core kernel change, and I don't know how easy it is to get those pushed back into the mainline. Also, after looking at the kernel code more (I'm fairly new to 2.6, which I'm sure you've deduced), it looks like most routines expect instances of type "bus_type" to be enumeratable/hot-swappable, and many of the busses I'd use in the embedded world wouldn't fit. I don't know how easy or difficult it would be to use the bus_type code construct in this fashion. John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 19:17 ` Eugene Surovegin 2004-04-01 19:35 ` John Whitney @ 2004-04-01 20:52 ` Michael R. Zucca 2004-04-01 22:00 ` Eugene Surovegin 1 sibling, 1 reply; 36+ messages in thread From: Michael R. Zucca @ 2004-04-01 20:52 UTC (permalink / raw) To: Eugene Surovegin; +Cc: John Whitney, Dan Malek, Matt Porter, linuxppc-dev Eugene Surovegin wrote: > On Thu, Apr 01, 2004 at 02:10:00PM -0500, John Whitney wrote: > I think we should add such info to a structure which describes the _bus_, not > _device_. > I'm not "new-device-model" guru, so I cannot comment _how_ this can be > implemented though :) A bus description alone is not sufficient. A generic DMA API should take both a source and destination device. Between any two sources and destinations there may be several intervening bridges, which potentially means programming those bridges and/or doing several address translations. -- ---------------------------------------------- Michael Zucca - mrz5149@acm.org ---------------------------------------------- "I'm too old to use Emacs." -- Rod MacDonald ---------------------------------------------- ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 20:52 ` Michael R. Zucca @ 2004-04-01 22:00 ` Eugene Surovegin 2004-04-01 22:39 ` Michael R. Zucca 2004-04-02 16:50 ` John Whitney 0 siblings, 2 replies; 36+ messages in thread From: Eugene Surovegin @ 2004-04-01 22:00 UTC (permalink / raw) To: Michael R. Zucca; +Cc: John Whitney, Dan Malek, Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 03:52:20PM -0500, Michael R. Zucca wrote: > > >I think we should add such info to a structure which describes the _bus_, > >not > >_device_. > >I'm not "new-device-model" guru, so I cannot comment _how_ this can be > >implemented though :) > > A bus description alone is not sufficient. A generic DMA API should take > both a source and destination device. well, DMA API we are talking about handles only device <-> system memory, so only _one_ device (which is currently done) is need. > Between any two sources and > destinations there may be several intervening bridges, which potentially > means programming those bridges and/or doing several address translations. In case of several bridges, I think it's simpler just to assign _different_ buses for each bus connected by a bridge. Eugene. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 22:00 ` Eugene Surovegin @ 2004-04-01 22:39 ` Michael R. Zucca 2004-04-02 16:50 ` John Whitney 1 sibling, 0 replies; 36+ messages in thread From: Michael R. Zucca @ 2004-04-01 22:39 UTC (permalink / raw) To: Eugene Surovegin; +Cc: John Whitney, Dan Malek, Matt Porter, linuxppc-dev Eugene Surovegin wrote: > On Thu, Apr 01, 2004 at 03:52:20PM -0500, Michael R. Zucca wrote: ? > In case of several bridges, I think it's simpler just to assign _different_ > buses for each bus connected by a bridge. Ok, I see. So if you assume the CPU is a target/source, you can infer any intervening bridges/busses. I assume the bridge/bus hierarchy is stored somewhere so you can do the appropriate programming/translation for each bridge. -- ---------------------------------------------- Michael Zucca - mrz5149@acm.org ---------------------------------------------- "I'm too old to use Emacs." -- Rod MacDonald ---------------------------------------------- ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 22:00 ` Eugene Surovegin 2004-04-01 22:39 ` Michael R. Zucca @ 2004-04-02 16:50 ` John Whitney 2004-04-02 18:50 ` Michael R. Zucca 2004-04-02 22:54 ` Paul Mackerras 1 sibling, 2 replies; 36+ messages in thread From: John Whitney @ 2004-04-02 16:50 UTC (permalink / raw) To: Linux/PPC Development As an exemplification of the problem I am having with the current DMA/PCI API: I am developing a Generic DMA driver. DMA providers register themselves with it. Clients ask the DMA core driver to please have a registered driver transfer the data from one location to another, and call them back when it is complete. Now, let's look at my options: 1. The DMA-core API accepts physical addresses only for source and destination. This technically can't be done. The virt_to_phys() API, I am told, is deprecated and shouldn't be used by the kernel. However, the client code can't call dma_map_single() or dma_alloc_coherent(), because it doesn't KNOW which providers are available and will be servicing the request. 2. Okay, we'll make the DMA-core API accept only virtual addresses, which it can map itself to the final driver. Okay... this works well for the local memory (__get_free_pages() and all), but the client has a physical address of a device it wants to write to... how does it get a virtual address? ioremap(). Bzzt! The address returned by ioremap is fully virtual, which dma_map_single() can't accept (as it calls virt_to_bus(), which doesn't handle fully-virtual addresses). 3. Well, darn. How about the client calls dma_map_single/dma_alloc_coherent with a NULL device, to get a physical address for allocated local memory to pass to the DMA core? Well, that sort of works. However, do ALL platforms add the PCI bus address-map-offset to the value? How does the core (processor independent) code know what to subract off to get back to the base physical address? There is no bus_to_phys() to phys_to_bus() routines, and these would be deprecated even if they did exist. How does it know what to add to get back a bus-offset-phys-address suitable for the DMA controller? I guess the DMA core COULD call bus_to_virt() (although it is deprecated), and then call dma_map_single() for the appropriate device... 4. I suppose I COULD have a far more complicated dma_mem_to_dev() and dma_dev_to_mem() and dma_dev_to_dev() and dma_mem_to_mem() kind of interface, which mixed virtual and physical addresses. Ugh. Am I missing anything that should have made this all simpler? If the DMA/PCI API routines simply accepted ANY virtual address (fully-virtual or semi-virtual), I wouldn't have this problem. I'd simply accept virtual addresses for the source and destination. John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 16:50 ` John Whitney @ 2004-04-02 18:50 ` Michael R. Zucca 2004-04-02 19:27 ` John Whitney 2004-04-02 22:54 ` Paul Mackerras 1 sibling, 1 reply; 36+ messages in thread From: Michael R. Zucca @ 2004-04-02 18:50 UTC (permalink / raw) To: John Whitney; +Cc: Linux/PPC Development John Whitney wrote: > > As an exemplification of the problem I am having with the current > DMA/PCI API: > > I am developing a Generic DMA driver. DMA providers register > themselves with it. Clients ask the DMA core driver to please have a > registered driver transfer the data from one location to another, and > call them back when it is complete. If CPU memory is assumed to be a source/target and the other source/target is the device, then you should take a DMA direction, a virtual address, a device or bus, and a bus-local address. If CPU memory isn't the only target or the DMA engine is between a bunch of bridges, you might need to take a source bus and bus-local address, and a destination bus and bus-local address. If you have the bus and the bus-local address you should be able to deduce what bridges you have to program/translate-through to do the transfer with the DMA engine. Once you know that you should be able to translate a bus-local address to whatever address is appropriate for the DMA engine and program any intervening bridges appropriately. Does Linux currently have the smarts to do this? Beats me, but it should if it's ever going to hope to deal with the crazy array of busses and bridges coming out of the minds of hardware engineers these days. :-) -- ---------------------------------------------- Michael Zucca - mrz5149@acm.org ---------------------------------------------- "I'm too old to use Emacs." -- Rod MacDonald ---------------------------------------------- ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 18:50 ` Michael R. Zucca @ 2004-04-02 19:27 ` John Whitney 2004-04-02 20:20 ` Michael R. Zucca 0 siblings, 1 reply; 36+ messages in thread From: John Whitney @ 2004-04-02 19:27 UTC (permalink / raw) To: Michael R. Zucca; +Cc: Linux/PPC Development On Apr 2, 2004, at 1:50 PM, Michael R. Zucca wrote: > John Whitney wrote: >> As an exemplification of the problem I am having with the current >> DMA/PCI API: >> I am developing a Generic DMA driver. DMA providers register >> themselves with it. Clients ask the DMA core driver to please have a >> registered driver transfer the data from one location to another, and >> call them back when it is complete. > > If CPU memory is assumed to be a source/target and the other > source/target is the device, then you should take a DMA direction, a > virtual address, a device or bus, and a bus-local address. If CPU > memory isn't the only target or the DMA engine is between a bunch of > bridges, you might need to take a source bus and bus-local address, > and a destination bus and bus-local address. > The "device" will always be the DMA controller (since it is moving data from one place to another), and all physical addresses should be from the controller's perspective. However, the client does not know what DMA controller might be used (or even which ones exists), as it has been abstracted. Direction is not needed to be specified. The source will ALWAYS be "to device" the destination will always be "from device". The DMA controller device just needs source and destination physical addresses (adjusted for its memory space). I'm not trying to handle wierd bus scenarios... I'm just trying to figure out how to go from a virtual address to a DMA-controller specific one, with the constraints I have been told about with the LinuxPPC kernel, in an abstracted interface. As I outlined in the previous message, I can't see a way to do this. Heck, let's make it simple. Let's say I have a high-speed serial port, and I want to DMA data to it with a known DMA controller (not abstracted) with a standard "device" structure associated with it. The serial driver has the physical address of the 1-byte transmit register of the serial port that it wants to DMA to. How does he make this into a physical address the known DMA controller device can use? There is no phys_to_bus() macro, and it would be deprecated if it existed. There is no DMA/PCI API for taking a physical address and converting it to a dma_addr_t for a specific device (the DMA controller). I can't ioremap() the device, and pass that virtual address to the DMA API, as it will produce a bad physical address and I have been told this is the desired way for the API to work. What's generic method is left, that doesn't require platform-specific code? John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 19:27 ` John Whitney @ 2004-04-02 20:20 ` Michael R. Zucca 2004-04-02 21:01 ` John Whitney 0 siblings, 1 reply; 36+ messages in thread From: Michael R. Zucca @ 2004-04-02 20:20 UTC (permalink / raw) To: John Whitney; +Cc: Linux/PPC Development John Whitney wrote: > I'm not trying to handle wierd bus scenarios... I'm just trying to > figure out how to go from a virtual address to a DMA-controller specific > one, with the constraints I have been told about with the LinuxPPC > kernel, in an abstracted interface. As I outlined in the previous > message, I can't see a way to do this. This is an approach that might have been good a number of years ago, but I don't think it's going to cut it these days. DMA engines can be anywhere and there can be a lot of intervening bridges. You can't always assume that programming a DMA engine is just a matter of doing virt_to_phys() and, voila, you're done. These days, you might have lots of bridges in the way that might need to have mappings setup, and there might be limited mapping resources so you can't just statically map the world with the intention that the source or destination will have a permanent address on the bus the DMA engine sits on. A generic DMA API might do something like: dma_move(main_memory_device, virtual_address, serial_port_device, pci_address, length) ; or dma_move(bulk_memory_card, pci_address, serial_port, pci_address, length) ; A generic DMA API could then pick the best DMA controller at it's disposal to push data from one bus to another. Once it has picked the right DMA engine it would know what bridges lie between the DMA engine and the source and destination devices. At that point it could translate each of the given addresses so that they can be programmed into the DMA engine. > Heck, let's make it simple. Let's say I have a high-speed serial port, > and I want to DMA data to it with a known DMA controller (not > abstracted) with a standard "device" structure associated with it. The > serial driver has the physical address of the 1-byte transmit register > of the serial port that it wants to DMA to. How does he make this into > a physical address the known DMA controller device can use? There is no > phys_to_bus() macro, and it would be deprecated if it existed. There is > no DMA/PCI API for taking a physical address and converting it to a > dma_addr_t for a specific device (the DMA controller). I can't > ioremap() the device, and pass that virtual address to the DMA API, as > it will produce a bad physical address and I have been told this is the > desired way for the API to work. On 2.4, at least, I believe you are supposed to pci_map_* the item if it's on PCI, take the address, slam in the DMA engine, and when the transfer is complete, pci_unamp_* the item. I think, though, that this might even be some hackery since I think the address you get from pci_map may or may not be appropriate for the DMA engine depending on where it lives. Good bus support is kind of lacking in Linux :( It would be nice if Linux had something more like NetBSD's bus_space/bus_dma stuff, or something even better. If what you need is generic address translation, I don't think that exists yet in Linux. If you need it, you may have to cook it up yourself. -- ---------------------------------------------- Michael Zucca - mrz5149@acm.org ---------------------------------------------- "I'm too old to use Emacs." -- Rod MacDonald ---------------------------------------------- ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 20:20 ` Michael R. Zucca @ 2004-04-02 21:01 ` John Whitney 2004-04-03 7:54 ` Adrian Cox 0 siblings, 1 reply; 36+ messages in thread From: John Whitney @ 2004-04-02 21:01 UTC (permalink / raw) To: Michael R. Zucca; +Cc: Linux/PPC Development > This is an approach that might have been good a number of years ago, > but I don't think it's going to cut it these days. DMA engines can be > anywhere and there can be a lot of intervening bridges. You can't > always assume that programming a DMA engine is just a matter of doing > virt_to_phys() and, voila, you're done. These days, you might have > lots of bridges in the way that might need to have mappings setup, and > there might be limited mapping resources so you can't just statically > map the world with the intention that the source or destination will > have a permanent address on the bus the DMA engine sits on. > > A generic DMA API might do something like: > > dma_move(main_memory_device, virtual_address, > serial_port_device, pci_address, length) ; > > or > > dma_move(bulk_memory_card, pci_address, > serial_port, pci_address, length) ; > A generic DMA API could then pick the best DMA controller at it's > disposal to push data from one bus to another. Once it has picked the > right DMA engine it would know what bridges lie between the DMA engine > and the source and destination devices. At that point it could > translate each of the given addresses so that they can be programmed > into the DMA engine. In fact, there is only one address translation that is important: the processor's view of the end-points' physical address to the DMA controller's view. The bridges should handle all other necessary translations transparently (I won't swear to that, but I can't think of any example that contradicts that, although you might not be able to "get there" from the DMA controller if it is on a different bus...). However, I'm not trying to come up with a good interface, really. I'm trying to show "you can't get there from here" with the current DMA API implementation. > On 2.4, at least, I believe you are supposed to pci_map_* the item if > it's on PCI, take the address, slam in the DMA engine, and when the > transfer is complete, pci_unamp_* the item. I think, though, that this > might even be some hackery since I think the address you get from > pci_map may or may not be appropriate for the DMA engine depending on > where it lives. That's the problem. pci_map_* and dma_map_* are not ALLOWED to take fully-virtual addresses, the kind that ioremap() produces (they produce totally bogus DMA addresses, as they just subtract off PCI_DRAM_OFFSET currently). Without that being allowed, how do I convert the processor-local-bus physical address I have for a direct memory mapped device, and generically translate it to the DMA controller's address space? I've been thinking about changes to the API that would help this, and have come up with the following (for the lists' consideration, with possible submission to the kernel mailing list): 1. dma_addr_t should be changed from a flat physical address variable to a structure, containing both the physical address and the device it corresponds to. 2. A macro should exist to convert this to a flat physical address: unsigned long dma_addr_to_phys (dma_addr_t *address); 3. A macro should exist to convert it from one device's address space to another's: dma_convert_addr (device *to_dev, dma_addr_t *to_address, dma_addr_t *from_address); If, due to dma_mask reasons the address is not valid for the requested device, this could return an error indicator, indicating the caller would have to allocate new memory and copy the contents over. 4. The processor should have a "device" associated with it, and this should be assumed to be the device when it is specified as NULL to the DMA API routines: dma_alloc_coherent (NULL, ...) would mean "allocate contiguous/coherent memory for me, with the processor's address space used for the physical address". 5. There should be a way of taking a local bus physical address, and converting it to the device's address space (dma_addr_t): dma_convert_phys (device *to_dev, dma_addr_t *address, unsigned long phys_addr). Again, this could return an error indicator if the dma_mask shows the address won't work. 6. With the above changes, the device or bus objects would have to include their address-space offset from the PLB address space. This would handle non-PCI buses, and allow you to convert from one to another (device1->PLB->device2). 7. It would also be REALLY nice if the DMA/PCI API could take fully virtual addresses with the ..._map_single()/_map_sg() calls. They are implemented in architecture-specific areas that know how to walk their own page tables, so why NOT allow them? I understand the dangers of having contiguous pages mapped to non-contiguous physical addresses, but that's a lot easier to explain than "virtual addresses from here will work, but not from there, and also not from THERE if your platform is not cache-coherent). The problem I see is that the current API assumes sysmem<->dev, with the device itself doing the transfer. I'm wanting to add a generic address-space-translation API to it that will allow other kinds of DMA transfers, and handle busses other than the PCI bus. The main impact I see this having on drivers written with the current API is that they need to call dma_addr_to_phys() instead of just using the dma_addr_t as a physical address. Comments? John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 21:01 ` John Whitney @ 2004-04-03 7:54 ` Adrian Cox 2004-04-03 12:43 ` John Whitney 2004-04-03 17:33 ` Brad Boyer 0 siblings, 2 replies; 36+ messages in thread From: Adrian Cox @ 2004-04-03 7:54 UTC (permalink / raw) To: John Whitney; +Cc: Michael R. Zucca, Linux/PPC Development On Fri, 2004-04-02 at 22:01, John Whitney wrote: > I've been thinking about changes to the API that would help this, and > have come up with the following (for the lists' consideration, with > possible submission to the kernel mailing list): > > 1. dma_addr_t should be changed from a flat physical address variable > to a structure, containing both the physical address and the device it > corresponds to. Why not leave dma_addr_t alone, and create a new type for this class of DMA engine. The new type would be a structure. The API then would be: dma_move(struct gen_dma *src, struct gen_dma *dest, unsigned len); Then struct gen_dma contains a union, to allow it to refer to memory (using the current DMA api), PCI devices, or on-chip peripherals: struct gen_dma { int bus_type; union { dma_addr_t memory_address; unsigned long bus_address; } } #define DMA_BUS_TYPE_MEM 0 #define DMA_BUS_TYPE_PCI 1 And each platform can define extra bus types #define DMA_BUS_TYPE_ODDBUS 2 > 2. A macro should exist to convert this to a flat physical address: > unsigned long dma_addr_to_phys (dma_addr_t *address); The macro to convert a struct gen_dma to a flat address would be specific to the platform. It wouldn't be in any global header. The conversion would only happen one line of code before writing the flat address into the DMA engine's register. > 3. A macro should exist to convert it from one device's address space > to another's: dma_convert_addr (device *to_dev, dma_addr_t *to_address, > dma_addr_t *from_address); If, due to dma_mask reasons the address is > not valid for the requested device, this could return an error > indicator, indicating the caller would have to allocate new memory and > copy the contents over. Again, easiest to implement inside the platform specific DMA controller code. > 4. The processor should have a "device" associated with it, and this > should be assumed to be the device when it is specified as NULL to the > DMA API routines: dma_alloc_coherent (NULL, ...) would mean "allocate > contiguous/coherent memory for me, with the processor's address space > used for the physical address". Actually, what might be useful would be a NULL device to indicate the platform DMA engine. > 5. There should be a way of taking a local bus physical address, and > converting it to the device's address space (dma_addr_t): > dma_convert_phys (device *to_dev, dma_addr_t *address, unsigned long > phys_addr). Again, this could return an error indicator if the > dma_mask shows the address won't work. I don't really see why we need this. > The problem I see is that the current API assumes sysmem<->dev, with > the device itself doing the transfer. I'm wanting to add a generic > address-space-translation API to it that will allow other kinds of DMA > transfers, and handle busses other than the PCI bus. I think that this generic API can live inside the platform specific implementation of the DMA controller. There are three important sorts of address: local memory - the DMA api gives us a handle to this PCI devices - addresses found through struct pci_dev on-chip peripherals, platform buses - addresses defined in platform header files > The main impact I see this having on drivers written with the current > API is that they need to call dma_addr_to_phys() instead of just using > the dma_addr_t as a physical address. > > Comments? Leave the current API alone. It's fine for the common class of peripherals. This is a completely new API for embedded devices. I've not encountered a chip with more than one platform DMA controller. Rather than having a top level API with low-level providers, consider picking the implementation at Kconfig time. - Adrian Cox ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 7:54 ` Adrian Cox @ 2004-04-03 12:43 ` John Whitney 2004-04-05 9:05 ` Adrian Cox 2004-04-03 17:33 ` Brad Boyer 1 sibling, 1 reply; 36+ messages in thread From: John Whitney @ 2004-04-03 12:43 UTC (permalink / raw) To: Adrian Cox; +Cc: Linux/PPC Development >> 1. dma_addr_t should be changed from a flat physical address variable >> to a structure, containing both the physical address and the device it >> corresponds to. > > Why not leave dma_addr_t alone, and create a new type for this class of > DMA engine. The new type would be a structure. The API then would be: > One reason I wanted them to be in the same system was for the following scenario: I created a standard DMA memory area, passed the dma_addr_t to an ethernet controller, and received a packet. Now I want to pass that packet to a decryption engine via an onboard DMA controller. If I could convert the DMA address suitable for the ethernet controller to one suitable for the DMA controller, nothing else would be necessary. Otherwise, I'll possibly have to walk the page table to convert the virtual address to the area they got back to a physical address suitable for the DMA controller. > dma_move(struct gen_dma *src, struct gen_dma *dest, unsigned len); > > Then struct gen_dma contains a union, to allow it to refer to memory > (using the current DMA api), PCI devices, or on-chip peripherals: > struct gen_dma { > int bus_type; > union { > dma_addr_t memory_address; > unsigned long bus_address; > } > } This is effectively my interface, although I take an array of src/dst/length/flag entries for scatter-gather type DMAs. Flags allow specification of special transfers such as "destination-held 1 byte". > #define DMA_BUS_TYPE_MEM 0 > #define DMA_BUS_TYPE_PCI 1 > > And each platform can define extra bus types > #define DMA_BUS_TYPE_ODDBUS 2 > You used dma_addr_t in your gen_dma struct type. From what I have seen, a dma_addr_t is ALWAYS in the PCI-bus address space. Perhaps just an "unsigned long" to contain a physical address in the local-bus memory space, and the DMA driver converts this to its own address space (more on this below)? >> 2. A macro should exist to convert this to a flat physical address: >> unsigned long dma_addr_to_phys (dma_addr_t *address); > > The macro to convert a struct gen_dma to a flat address would be > specific to the platform. It wouldn't be in any global header. The > conversion would only happen one line of code before writing the flat > address into the DMA engine's register. Are there any multi-platform DMA controllers that might make this difficult, I wonder? >> 5. There should be a way of taking a local bus physical address, and >> converting it to the device's address space (dma_addr_t): >> dma_convert_phys (device *to_dev, dma_addr_t *address, unsigned long >> phys_addr). Again, this could return an error indicator if the >> dma_mask shows the address won't work. > > I don't really see why we need this. To convert a PLB specific address to another device's address-space. With the current DMA API, you can't do this without the address being in RAM (otherwise, it wouldn't have a semi-virtual address). On the PowerPC side, this would usualy have been a no-op, or an addition of PCI_DRAM_OFFSET to the given address. Whether this is needed for the "new" API we are discussing is another matter. > Leave the current API alone. It's fine for the common class of > peripherals. This is a completely new API for embedded devices. > > I've not encountered a chip with more than one platform DMA controller. > Rather than having a top level API with low-level providers, consider > picking the implementation at Kconfig time. > As long as each driver has a common interface, so that I could write a module that uses that interface, and works with different DMA controllers on different platforms, I don't have a problem with doing it this way. One of the nice things about having the DMA-core, however, was that it accepted virtual addresses and handled cache consistency. If the driver is accepting physical addresses only, it can't do that. This means the client would have to allocate space using the DMA/PCI to get the same coherency, which means all addresses will be PCI-address-space. Should the individual drivers accept this and just subtract off PCI_DRAM_OFFSET (or equivalent) to get back to a physical address? This is what would make life hell for a cross-platform DMA controller. Good suggestions, thanks! John ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 12:43 ` John Whitney @ 2004-04-05 9:05 ` Adrian Cox 0 siblings, 0 replies; 36+ messages in thread From: Adrian Cox @ 2004-04-05 9:05 UTC (permalink / raw) To: John Whitney; +Cc: Linux/PPC Development On Sat, 2004-04-03 at 13:43, John Whitney wrote: > One of the nice things about having the DMA-core, however, was that it > accepted virtual addresses and handled cache consistency. If the > driver is accepting physical addresses only, it can't do that. This > means the client would have to allocate space using the DMA/PCI to get > the same coherency, which means all addresses will be > PCI-address-space. Should the individual drivers accept this and just > subtract off PCI_DRAM_OFFSET (or equivalent) to get back to a physical > address? This is what would make life hell for a cross-platform DMA > controller. What I would like is a general API for a block move between memory and a dumb PCI peripheral. Something like mempcy_toio() but with the expectation of it sleeping. Your local bus peripheral might benefit from a standard API, but I'm still not convinced that there will be many cross-platform DMA controllers. All the ones I've seen are tightly coupled to the northbridge or system-on-a-chip internal bus. I'd still prefer a shared interface rather than implementation, and I'd suggest taking an interface proposal to the linux-arm-kernel and linuxppc-embedded lists. - Adrian Cox ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 7:54 ` Adrian Cox 2004-04-03 12:43 ` John Whitney @ 2004-04-03 17:33 ` Brad Boyer 2004-04-03 23:17 ` Paul Mackerras 2004-04-04 8:15 ` Adrian Cox 1 sibling, 2 replies; 36+ messages in thread From: Brad Boyer @ 2004-04-03 17:33 UTC (permalink / raw) To: Adrian Cox; +Cc: John Whitney, Michael R. Zucca, Linux/PPC Development On Sat, Apr 03, 2004 at 08:54:18AM +0100, Adrian Cox wrote: > I've not encountered a chip with more than one platform DMA controller. > Rather than having a top level API with low-level providers, consider > picking the implementation at Kconfig time. It's generally better not to decide this sort of thing at compile time if you want it to be portable. If you want an example of a kernel that can do everything, try compiling Linux for m68k sometime. You can have one kernel that can support Amigas, Ataris, Macs, and a few others all at once. I'm sure it goes without saying that pretty much everything other than the base CPU is different on each platform. In fact, even just with 68k based Macs, Apple changed stuff so often that any two models may have almost nothing in common. Brad Boyer flar@allandria.com ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 17:33 ` Brad Boyer @ 2004-04-03 23:17 ` Paul Mackerras 2004-04-04 8:15 ` Adrian Cox 1 sibling, 0 replies; 36+ messages in thread From: Paul Mackerras @ 2004-04-03 23:17 UTC (permalink / raw) To: Brad Boyer; +Cc: Linux/PPC Development Brad Boyer writes: > It's generally better not to decide this sort of thing at compile time > if you want it to be portable. If you want an example of a kernel that > can do everything, try compiling Linux for m68k sometime. You can have > one kernel that can support Amigas, Ataris, Macs, and a few others all > at once. I'm sure it goes without saying that pretty much everything > other than the base CPU is different on each platform. In fact, even > just with 68k based Macs, Apple changed stuff so often that any two > models may have almost nothing in common. We tend not to do that with kernels for embedded systems, mainly because memory is at a premium and people developing embedded systems don't want to include any code that isn't going to get used. Paul. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 17:33 ` Brad Boyer 2004-04-03 23:17 ` Paul Mackerras @ 2004-04-04 8:15 ` Adrian Cox 1 sibling, 0 replies; 36+ messages in thread From: Adrian Cox @ 2004-04-04 8:15 UTC (permalink / raw) To: Brad Boyer; +Cc: John Whitney, Michael R. Zucca, Linux/PPC Development On Sat, 2004-04-03 at 18:33, Brad Boyer wrote: > It's generally better not to decide this sort of thing at compile time > if you want it to be portable. If you want an example of a kernel that > can do everything, try compiling Linux for m68k sometime. You can have > one kernel that can support Amigas, Ataris, Macs, and a few others all > at once. I'm sure it goes without saying that pretty much everything > other than the base CPU is different on each platform. In fact, even > just with 68k based Macs, Apple changed stuff so often that any two > models may have almost nothing in common. In the sort of embedded systems which have these DMA controllers, there is generally no way for Linux to tell which hardware it is running on. For example, there is no way to tell that this MPC8260 board was made by North American Veeblefetzer, or that GPIO 15 is the MII clock and GPIO 21 is the MII data, or that those two lines were reassigned on the next revision of the board. We're already stuck with compiling for a very specific model, and we're frequently trying to save space in the boot flash. - Adrian Cox ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 16:50 ` John Whitney 2004-04-02 18:50 ` Michael R. Zucca @ 2004-04-02 22:54 ` Paul Mackerras 2004-04-03 7:33 ` Adrian Cox 1 sibling, 1 reply; 36+ messages in thread From: Paul Mackerras @ 2004-04-02 22:54 UTC (permalink / raw) To: John Whitney; +Cc: Linux/PPC Development John Whitney writes: > As an exemplification of the problem I am having with the current > DMA/PCI API: > > I am developing a Generic DMA driver. DMA providers register > themselves with it. Clients ask the DMA core driver to please have a > registered driver transfer the data from one location to another, and > call them back when it is complete. It sounds like you have the model of a DMA controller that is separate from any I/O device that needs to transfer data to/from memory, and you want to use it to transfer data from one memory location to another. Just like in the bad old days of the PC/XT. :) That is not the model that PCI/DMA API is designed for. The model it is designed for is one where you have a bridge, often with an IOMMU that remaps bus addresses to memory addresses on a page granularity, and behind that you have a bus-master capable device. Thus the PCI/DMA API takes care of setting up an appropriate translation in the IOMMU (if any) and returning the bus address that the driver should use. The way that the driver gives the bus address to the device is very device-dependent and isn't handled by the API. If you want to write code to handle a separate DMA controller, go ahead. You will need to design your own separate API for it. I wouldn't try to make it too general, though, since there are very few systems these days that have DMA controllers (as distinct from bus-master capable I/O devices). Paul. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-02 22:54 ` Paul Mackerras @ 2004-04-03 7:33 ` Adrian Cox 2004-04-04 22:56 ` Benjamin Herrenschmidt 0 siblings, 1 reply; 36+ messages in thread From: Adrian Cox @ 2004-04-03 7:33 UTC (permalink / raw) To: Paul Mackerras; +Cc: John Whitney, Linux/PPC Development On Fri, 2004-04-02 at 23:54, Paul Mackerras wrote: > If you want to write code to handle a separate DMA controller, go > ahead. You will need to design your own separate API for it. I > wouldn't try to make it too general, though, since there are very few > systems these days that have DMA controllers (as distinct from > bus-master capable I/O devices). Actually, they are extremely common in the embedded market. On my desk I have three Linux systems with this class of DMA engine: an MPC107/7410, an ARM9 from Cirrus, and an ARM9 from TI. Most system-on-a-chip processors have DMA engines which can move between any two of memory, PCI, and internal peripherals. - Adrian Cox ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-03 7:33 ` Adrian Cox @ 2004-04-04 22:56 ` Benjamin Herrenschmidt 0 siblings, 0 replies; 36+ messages in thread From: Benjamin Herrenschmidt @ 2004-04-04 22:56 UTC (permalink / raw) To: Adrian Cox; +Cc: Paul Mackerras, John Whitney, Linux/PPC Development > Actually, they are extremely common in the embedded market. On my desk I > have three Linux systems with this class of DMA engine: an MPC107/7410, > an ARM9 from Cirrus, and an ARM9 from TI. Most system-on-a-chip > processors have DMA engines which can move between any two of memory, > PCI, and internal peripherals. Right, but in this case, those systems also usually don't have an iommu and usually provide a simple 1:1 mapping between memory and bus addresses ;) Ben. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 19:10 ` John Whitney 2004-04-01 19:17 ` Eugene Surovegin @ 2004-04-02 5:45 ` Christoph Hellwig 1 sibling, 0 replies; 36+ messages in thread From: Christoph Hellwig @ 2004-04-02 5:45 UTC (permalink / raw) To: John Whitney; +Cc: Eugene Surovegin, Dan Malek, Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 02:10:00PM -0500, John Whitney wrote: > sounds like a good solution to me, although I'd like to see the > "device" structure get that DMA offset I mentioned, so the DMA API > wouldn't have to have a special case for each new bus-type added (PLB, That doesn't work because there's much more complex bridges that do complicated remapping of the bus addresses and it's not a simple offset. ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Problems with dma_alloc_coherent() 2004-04-01 18:59 ` Eugene Surovegin 2004-04-01 19:10 ` John Whitney @ 2004-04-01 20:49 ` Matt Porter 1 sibling, 0 replies; 36+ messages in thread From: Matt Porter @ 2004-04-01 20:49 UTC (permalink / raw) To: Dan Malek, John Whitney, Matt Porter, linuxppc-dev On Thu, Apr 01, 2004 at 10:59:56AM -0800, Eugene Surovegin wrote: > On Thu, Apr 01, 2004 at 01:55:10PM -0500, Dan Malek wrote: > > >Current implementation just relies on the fact that PCI devices view system > > >memory the same way as other-bus devices (e.g. OCP devices which sit on > > >OPB). > > > > I don't think so. PCI devices are known to go through bridges, while > > others are assumed to not. > > Well, bridge doesn't necessarily mean there is an address translation :). > Currently 4xx systems (not sure all, at least ones I use) use PCI == phys > address mapping, and yes, bridge is setup so this is the case. Just FYI, not all 4xx systems, just the ones in the kernel tree today. -Matt ** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/ ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2004-04-05 9:05 UTC | newest] Thread overview: 36+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-04-01 15:59 Problems with dma_alloc_coherent() John Whitney 2004-04-01 16:30 ` John Whitney 2004-04-01 16:51 ` Dan Malek 2004-04-01 17:01 ` Tom Rini 2004-04-01 17:05 ` Matt Porter 2004-04-01 17:51 ` John Whitney 2004-04-01 18:16 ` Matt Porter 2004-04-01 18:19 ` Eugene Surovegin 2004-04-01 18:33 ` Eugene Surovegin 2004-04-01 18:33 ` John Whitney 2004-04-01 18:40 ` Eugene Surovegin 2004-04-01 18:48 ` John Whitney 2004-04-01 18:55 ` Dan Malek 2004-04-01 18:59 ` Eugene Surovegin 2004-04-01 19:10 ` John Whitney 2004-04-01 19:17 ` Eugene Surovegin 2004-04-01 19:35 ` John Whitney 2004-04-01 20:52 ` Michael R. Zucca 2004-04-01 22:00 ` Eugene Surovegin 2004-04-01 22:39 ` Michael R. Zucca 2004-04-02 16:50 ` John Whitney 2004-04-02 18:50 ` Michael R. Zucca 2004-04-02 19:27 ` John Whitney 2004-04-02 20:20 ` Michael R. Zucca 2004-04-02 21:01 ` John Whitney 2004-04-03 7:54 ` Adrian Cox 2004-04-03 12:43 ` John Whitney 2004-04-05 9:05 ` Adrian Cox 2004-04-03 17:33 ` Brad Boyer 2004-04-03 23:17 ` Paul Mackerras 2004-04-04 8:15 ` Adrian Cox 2004-04-02 22:54 ` Paul Mackerras 2004-04-03 7:33 ` Adrian Cox 2004-04-04 22:56 ` Benjamin Herrenschmidt 2004-04-02 5:45 ` Christoph Hellwig 2004-04-01 20:49 ` Matt Porter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).