* [PATCH] ata: libata depends on HAS_DMA [not found] <20090511222702.352192505@arndb.de> @ 2009-05-11 22:38 ` Arnd Bergmann 2009-05-12 0:58 ` Jeff Garzik 2009-05-12 8:06 ` Alan Cox 0 siblings, 2 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-11 22:38 UTC (permalink / raw) To: linux-kernel, Jeff Garzik, linux-ide libata uses the DMA mapping API, so it cannot be built on architectures that don't have DMA support. Signed-off-by: Arnd Bergmann <arnd@arndb.de> --- drivers/ata/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 9120717..f076268 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -4,7 +4,7 @@ menuconfig ATA tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers" - depends on HAS_IOMEM + depends on HAS_IOMEM && HAS_DMA depends on BLOCK depends on !(M32R || M68K) || BROKEN select SCSI -- 1.6.0.4 -- ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-11 22:38 ` [PATCH] ata: libata depends on HAS_DMA Arnd Bergmann @ 2009-05-12 0:58 ` Jeff Garzik 2009-05-12 12:40 ` Arnd Bergmann 2009-05-12 8:06 ` Alan Cox 1 sibling, 1 reply; 39+ messages in thread From: Jeff Garzik @ 2009-05-12 0:58 UTC (permalink / raw) To: Arnd Bergmann; +Cc: linux-kernel, linux-ide Arnd Bergmann wrote: > libata uses the DMA mapping API, so it cannot be built > on architectures that don't have DMA support. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > drivers/ata/Kconfig | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig > index 9120717..f076268 100644 > --- a/drivers/ata/Kconfig > +++ b/drivers/ata/Kconfig > @@ -4,7 +4,7 @@ > > menuconfig ATA > tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers" > - depends on HAS_IOMEM > + depends on HAS_IOMEM && HAS_DMA > depends on BLOCK > depends on !(M32R || M68K) || BROKEN What specifically is breaking? Ideally we should be able to work with PIO-only... JEff ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-12 0:58 ` Jeff Garzik @ 2009-05-12 12:40 ` Arnd Bergmann 2009-05-12 13:05 ` Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-12 12:40 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, linux-ide On Tuesday 12 May 2009, Jeff Garzik wrote: > > --- a/drivers/ata/Kconfig > > +++ b/drivers/ata/Kconfig > > @@ -4,7 +4,7 @@ > > > > menuconfig ATA > > tristate "Serial ATA (prod) and Parallel ATA (experimental) drivers" > > - depends on HAS_IOMEM > > + depends on HAS_IOMEM && HAS_DMA > > depends on BLOCK > > depends on !(M32R || M68K) || BROKEN > > What specifically is breaking? > > Ideally we should be able to work with PIO-only... CONFIG_HAS_DMA is not set on architectures that are missing asm/dma-mapping.h or fall back to asm-generic/dma-mapping-broken.h. In the latter case, you get a link error: drivers/built-in.o: In function `sas_issue_ata_cmd': /home/arnd/linux/linux-2.6/drivers/scsi/libsas/sas_ata.c(.text+0x33c50): undefined reference to `dma_map_sg' /home/arnd/linux/linux-2.6/drivers/scsi/libsas/sas_ata.c(.text+0x33ef0): undefined reference to `dma_unmap_sg' drivers/built-in.o: In function `ata_sg_clean': /home/arnd/linux/linux-2.6/drivers/ata/libata-core.c(.text+0x37d18): undefined reference to `dma_unmap_sg' drivers/built-in.o: In function `ata_qc_issue': /home/arnd/linux/linux-2.6/drivers/ata/libata-core.c(.text+0x38774): undefined reference to `dma_map_sg' drivers/built-in.o: In function `ata_port_start': /home/arnd/linux/linux-2.6/drivers/ata/libata-core.c(.text+0x3bf0c): undefined reference to `dmam_alloc_coherent' A slightly less naive (but still suboptimal) fix would be the patch below. I could not find an easy way to force all devices to use PIO, this patch would simply fail if someone tried to set a DMA mode. Arnd <>< --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4629,6 +4629,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, */ void ata_sg_clean(struct ata_queued_cmd *qc) { +#ifdef CONFIG_HAS_DMA struct ata_port *ap = qc->ap; struct scatterlist *sg = qc->sg; int dir = qc->dma_dir; @@ -4642,6 +4643,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->sg = NULL; +#endif /* CONFIG_HAS_DMA */ } /** @@ -4743,6 +4745,7 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, */ static int ata_sg_setup(struct ata_queued_cmd *qc) { +#ifdef CONFIG_HAS_DMA struct ata_port *ap = qc->ap; unsigned int n_elem; @@ -4758,6 +4761,10 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_DMAMAP; return 0; +#else + DPRINTK("attempted to use DMA on incompatible architecture\n"); + return -EINVAL; +#endif /* CONFIG_HAS_DMA */ } /** @@ -5450,8 +5457,12 @@ int ata_port_start(struct ata_port *ap) { struct device *dev = ap->dev; +#ifdef CONFIG_HAS_DMA ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); +#else + ap->prd = devres_alloc(dev, ATA_PRD_TBL_SZ, GFP_KERNEL); +#endif /* CONFIG_HAS_DMA */ if (!ap->prd) return -ENOMEM; diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig index 59e00fa..e00271f 100644 --- a/drivers/scsi/libsas/Kconfig +++ b/drivers/scsi/libsas/Kconfig @@ -34,6 +34,7 @@ config SCSI_SAS_ATA bool "ATA support for libsas (requires libata)" depends on SCSI_SAS_LIBSAS depends on ATA = y || ATA = SCSI_SAS_LIBSAS + depends on HAS_DMA help Builds in ATA support into libsas. Will necessitate the loading of libata along with libsas. ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-12 12:40 ` Arnd Bergmann @ 2009-05-12 13:05 ` Arnd Bergmann 0 siblings, 0 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-12 13:05 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, linux-ide On Tuesday 12 May 2009, Arnd Bergmann wrote: > +#ifdef CONFIG_HAS_DMA > ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, > GFP_KERNEL); > +#else > + ap->prd = devres_alloc(dev, ATA_PRD_TBL_SZ, GFP_KERNEL); > +#endif /* CONFIG_HAS_DMA */ > if (!ap->prd) > return -ENOMEM; this should have been devm_kzalloc, not devres_alloc. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-11 22:38 ` [PATCH] ata: libata depends on HAS_DMA Arnd Bergmann 2009-05-12 0:58 ` Jeff Garzik @ 2009-05-12 8:06 ` Alan Cox 2009-05-12 9:23 ` Arnd Bergmann 1 sibling, 1 reply; 39+ messages in thread From: Alan Cox @ 2009-05-12 8:06 UTC (permalink / raw) To: Arnd Bergmann; +Cc: linux-kernel, Jeff Garzik, linux-ide On Mon, 11 May 2009 22:38:55 +0000 Arnd Bergmann <arnd@arndb.de> wrote: > libata uses the DMA mapping API, so it cannot be built > on architectures that don't have DMA support. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> Nakked-by: Alan Cox <alan@linux.intel.com> Almost every PATA adapter can fall back to PIO, many are PIO only. We need a rather cleaner way to sort this. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-12 8:06 ` Alan Cox @ 2009-05-12 9:23 ` Arnd Bergmann 2009-05-13 3:30 ` Brad Boyer 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-12 9:23 UTC (permalink / raw) To: Alan Cox Cc: linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato On Tuesday 12 May 2009, Alan Cox wrote: > Nakked-by: Alan Cox <alan@linux.intel.com> > > Almost every PATA adapter can fall back to PIO, many are PIO only. We > need a rather cleaner way to sort this. Currently, the only architectures that don't set HAS_DMA are h8300, m32r m68k (except SUN3 and Coldfire), microblaze and s390. s390 will never get it, microblaze is currently implementing dma-mapping.h. The other three are still using drivers/ide instead of drivers/ata. One way to fix this would be to implement dma-mapping.h in h8300, m32r and m68k and leave !HAS_DMA as the obscure s390 case (this one already can't use ATA because of !HAS_MMIO). The other way would be to add some #ifdef CONFIG_HAS_DMA in libata-core.c and sas_ata.c. Arnd <>< Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-12 9:23 ` Arnd Bergmann @ 2009-05-13 3:30 ` Brad Boyer 2009-05-13 4:12 ` Michael Schmitz 2009-05-13 10:39 ` Arnd Bergmann 0 siblings, 2 replies; 39+ messages in thread From: Brad Boyer @ 2009-05-13 3:30 UTC (permalink / raw) To: Arnd Bergmann Cc: Alan Cox, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato On Tue, May 12, 2009 at 11:23:20AM +0200, Arnd Bergmann wrote: > Currently, the only architectures that don't set HAS_DMA are h8300, m32r > m68k (except SUN3 and Coldfire), microblaze and s390. > s390 will never get it, microblaze is currently implementing dma-mapping.h. > > The other three are still using drivers/ide instead of drivers/ata. > > One way to fix this would be to implement dma-mapping.h in h8300, m32r and > m68k and leave !HAS_DMA as the obscure s390 case (this one already can't > use ATA because of !HAS_MMIO). If I'm reading the m68k code correctly, SUN3 is the one that doesn't have DMA. It is implemented on any m68k with a standard Motorola MMU. It might be possible to get the DMA code working on a sun3, but I doubt they ever have IDE hardware. Brad Boyer flar@allandria.com ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 3:30 ` Brad Boyer @ 2009-05-13 4:12 ` Michael Schmitz 2009-05-13 4:34 ` Brad Boyer 2009-05-13 10:39 ` Arnd Bergmann 1 sibling, 1 reply; 39+ messages in thread From: Michael Schmitz @ 2009-05-13 4:12 UTC (permalink / raw) To: Brad Boyer Cc: Arnd Bergmann, Alan Cox, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato Hi, > > Currently, the only architectures that don't set HAS_DMA are h8300, m32r > > m68k (except SUN3 and Coldfire), microblaze and s390. > > s390 will never get it, microblaze is currently implementing dma-mapping.h. > > > > The other three are still using drivers/ide instead of drivers/ata. > > > > One way to fix this would be to implement dma-mapping.h in h8300, m32r and > > m68k and leave !HAS_DMA as the obscure s390 case (this one already can't > > use ATA because of !HAS_MMIO). > > If I'm reading the m68k code correctly, SUN3 is the one that doesn't have > DMA. It is implemented on any m68k with a standard Motorola MMU. It might > be possible to get the DMA code working on a sun3, but I doubt they ever > have IDE hardware. The Atari IDE interface does not use DMA. I don't see what addition of DMA mapping for IDE would achieve. If it doesn't interfere with plain PIO mode, fine. Michael ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 4:12 ` Michael Schmitz @ 2009-05-13 4:34 ` Brad Boyer 2009-05-13 8:51 ` Alan Cox 0 siblings, 1 reply; 39+ messages in thread From: Brad Boyer @ 2009-05-13 4:34 UTC (permalink / raw) To: Michael Schmitz Cc: Arnd Bergmann, Alan Cox, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato On Wed, May 13, 2009 at 06:12:31AM +0200, Michael Schmitz wrote: > The Atari IDE interface does not use DMA. I don't see what addition of DMA > mapping for IDE would achieve. The macide driver doesn't support anything with DMA hardware either. In fact, no m68k Macintosh has both DMA capability and an IDE controller. However, we do support the basic DMA routines on the main m68k platforms. It's just not used for IDE. I think the proposed change was to require that the DMA routines be present, not that the IDE ports actually have to have a DMA capability. > If it doesn't interfere with plain PIO mode, fine. I agree. There definitely needs to still be support for IDE ports that don't have DMA capability. Brad Boyer flar@allandria.com ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 4:34 ` Brad Boyer @ 2009-05-13 8:51 ` Alan Cox 2009-05-13 8:55 ` Geert Uytterhoeven 2009-05-13 23:57 ` Robert Hancock 0 siblings, 2 replies; 39+ messages in thread From: Alan Cox @ 2009-05-13 8:51 UTC (permalink / raw) To: Brad Boyer Cc: Michael Schmitz, Arnd Bergmann, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato > > If it doesn't interfere with plain PIO mode, fine. > > I agree. There definitely needs to still be support for IDE ports that > don't have DMA capability. There is - it's just if the platform doesn't implement the dma_* APIs you get a problem. Alan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 8:51 ` Alan Cox @ 2009-05-13 8:55 ` Geert Uytterhoeven 2009-05-13 23:57 ` Robert Hancock 1 sibling, 0 replies; 39+ messages in thread From: Geert Uytterhoeven @ 2009-05-13 8:55 UTC (permalink / raw) To: Alan Cox Cc: Brad Boyer, Michael Schmitz, Arnd Bergmann, linux-kernel, Jeff Garzik, linux-ide, takata, linux-m68k, ysato On Wed, May 13, 2009 at 10:51, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: >> > If it doesn't interfere with plain PIO mode, fine. >> >> I agree. There definitely needs to still be support for IDE ports that >> don't have DMA capability. > > There is - it's just if the platform doesn't implement the dma_* APIs you > get a problem. Note that there are other things missing on m68k and m32r, that's why Al added the | depends on !(M32R || M68K) || BROKEN commit 9317fd4c60962d3a9423b5f9bb5d1b10cf8a0699 Author: Al Viro <viro@ftp.linux.org.uk> Date: Sun Sep 24 23:40:00 2006 +0100 [PATCH] libata won't build on m68k and m32r no ioread*(), for one thing Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 8:51 ` Alan Cox 2009-05-13 8:55 ` Geert Uytterhoeven @ 2009-05-13 23:57 ` Robert Hancock 2009-05-14 0:18 ` FUJITA Tomonori 1 sibling, 1 reply; 39+ messages in thread From: Robert Hancock @ 2009-05-13 23:57 UTC (permalink / raw) To: Alan Cox Cc: Brad Boyer, Michael Schmitz, Arnd Bergmann, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato Alan Cox wrote: >>> If it doesn't interfere with plain PIO mode, fine. >> I agree. There definitely needs to still be support for IDE ports that >> don't have DMA capability. > > There is - it's just if the platform doesn't implement the dma_* APIs you > get a problem. Wouldn't the easiest solution be to just dummy out the DMA API calls on this platform to always fail? That would fix these compile problems.. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 23:57 ` Robert Hancock @ 2009-05-14 0:18 ` FUJITA Tomonori 2009-05-15 5:31 ` Tejun Heo 0 siblings, 1 reply; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-14 0:18 UTC (permalink / raw) To: hancockrwd Cc: alan, flar, schmitz, arnd, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato On Wed, 13 May 2009 17:57:14 -0600 Robert Hancock <hancockrwd@gmail.com> wrote: > Alan Cox wrote: > >>> If it doesn't interfere with plain PIO mode, fine. > >> I agree. There definitely needs to still be support for IDE ports that > >> don't have DMA capability. > > > > There is - it's just if the platform doesn't implement the dma_* APIs you > > get a problem. > > Wouldn't the easiest solution be to just dummy out the DMA API calls on > this platform to always fail? That would fix these compile problems.. Can libata call dma_supported() per device to decide DMA or PIO mode? Then, we can solve this problem by add dummy DMA API (just calls BUG) on such architectures, without Kconfig magic or adding ifdef (like the old ide stack does), I think. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-14 0:18 ` FUJITA Tomonori @ 2009-05-15 5:31 ` Tejun Heo 2009-05-15 11:16 ` Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: Tejun Heo @ 2009-05-15 5:31 UTC (permalink / raw) To: FUJITA Tomonori Cc: hancockrwd, alan, flar, schmitz, arnd, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato FUJITA Tomonori wrote: > On Wed, 13 May 2009 17:57:14 -0600 > Robert Hancock <hancockrwd@gmail.com> wrote: > >> Alan Cox wrote: >>>>> If it doesn't interfere with plain PIO mode, fine. >>>> I agree. There definitely needs to still be support for IDE ports that >>>> don't have DMA capability. >>> There is - it's just if the platform doesn't implement the dma_* APIs you >>> get a problem. >> Wouldn't the easiest solution be to just dummy out the DMA API calls on >> this platform to always fail? That would fix these compile problems.. > > Can libata call dma_supported() per device to decide DMA or PIO mode? > Then, we can solve this problem by add dummy DMA API (just calls BUG) > on such architectures, without Kconfig magic or adding ifdef (like the > old ide stack does), I think. Sure it can. Which specific drivers are we talking about? Thanks. -- tejun ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-15 5:31 ` Tejun Heo @ 2009-05-15 11:16 ` Arnd Bergmann 2009-05-15 11:21 ` Tejun Heo 2009-05-18 10:45 ` [PATCH] ata: libata depends on HAS_DMA FUJITA Tomonori 0 siblings, 2 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-15 11:16 UTC (permalink / raw) To: Tejun Heo Cc: FUJITA Tomonori, hancockrwd, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato On Friday 15 May 2009, Tejun Heo wrote: > FUJITA Tomonori wrote: > > Can libata call dma_supported() per device to decide DMA or PIO mode? > > Then, we can solve this problem by add dummy DMA API (just calls BUG) > > on such architectures, without Kconfig magic or adding ifdef (like the > > old ide stack does), I think. That would be the !CONFIG_PCI half of the old include/asm-generic/dma-mapping.h file that you just removed, right? In general, I'd prefer keeping the asm-generic/dma-mapping-broken.h implementation that gives us a compile-time error, but maybe there is an even better option based on the mn10300 implementation which basically pretends everything works with just page_to_phys() mappings. > Sure it can. Which specific drivers are we talking about? The main problem is libata-core.c, which references DMA mapping API calls that are only implemented on architectures setting CONFIG_HAS_DMA. Arnd <>< -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-15 11:16 ` Arnd Bergmann @ 2009-05-15 11:21 ` Tejun Heo 2009-05-15 11:55 ` Arnd Bergmann 2009-05-18 10:45 ` [PATCH] ata: libata depends on HAS_DMA FUJITA Tomonori 1 sibling, 1 reply; 39+ messages in thread From: Tejun Heo @ 2009-05-15 11:21 UTC (permalink / raw) To: Arnd Bergmann Cc: FUJITA Tomonori, hancockrwd, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato Hello, Arnd Bergmann wrote: > On Friday 15 May 2009, Tejun Heo wrote: >> FUJITA Tomonori wrote: >>> Can libata call dma_supported() per device to decide DMA or PIO mode? >>> Then, we can solve this problem by add dummy DMA API (just calls BUG) >>> on such architectures, without Kconfig magic or adding ifdef (like the >>> old ide stack does), I think. > > That would be the !CONFIG_PCI half of the old > include/asm-generic/dma-mapping.h file that you just removed, > right? > > In general, I'd prefer keeping the asm-generic/dma-mapping-broken.h > implementation that gives us a compile-time error, but maybe there > is an even better option based on the mn10300 implementation which > basically pretends everything works with just page_to_phys() mappings. Don't know much history here but I don't wanna sprinkle ifdefs around in libata so I would much prefer dummy implementation which doesn't fail compile. >> Sure it can. Which specific drivers are we talking about? > > The main problem is libata-core.c, which references DMA mapping > API calls that are only implemented on architectures setting > CONFIG_HAS_DMA. Yeah, sure, libata-core is used by every driver but I was wondering whether only SFF drivers are of interest or there are others. Thanks. -- tejun ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-15 11:21 ` Tejun Heo @ 2009-05-15 11:55 ` Arnd Bergmann 2009-05-17 9:00 ` Robert Hancock 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-15 11:55 UTC (permalink / raw) To: Tejun Heo Cc: FUJITA Tomonori, hancockrwd, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato On Friday 15 May 2009, Tejun Heo wrote: > Don't know much history here but I don't wanna sprinkle ifdefs around > in libata so I would much prefer dummy implementation which doesn't > fail compile. My original patch did that by adding 'depends on HAS_DMA'. The only architectures that don't have that are m68k, m32r, h8300, s390 and microblaze. More research has shown that they all found a different way to disable the ATA drivers already, except microblaze. Alan, you objected the patch initially (and loudly), but maybe you can reconsider this. The only actual effect that my patch has is to allow an allyesconfig build on microblaze and that will implement dma-mapping.h in the next version. All existing architectures do not care at all about this change, unless I'm missing something. Besides, all the other users of the DMA mapping API also depend on CONFIG_HAS_DMA. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-15 11:55 ` Arnd Bergmann @ 2009-05-17 9:00 ` Robert Hancock 2009-05-17 19:38 ` Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: Robert Hancock @ 2009-05-17 9:00 UTC (permalink / raw) To: Arnd Bergmann Cc: Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato Arnd Bergmann wrote: > On Friday 15 May 2009, Tejun Heo wrote: >> Don't know much history here but I don't wanna sprinkle ifdefs around >> in libata so I would much prefer dummy implementation which doesn't >> fail compile. > > My original patch did that by adding 'depends on HAS_DMA'. > > The only architectures that don't have that are m68k, m32r, > h8300, s390 and microblaze. More research has shown that > they all found a different way to disable the ATA drivers > already, except microblaze. > > Alan, you objected the patch initially (and loudly), but > maybe you can reconsider this. The only actual effect > that my patch has is to allow an allyesconfig build on > microblaze and that will implement dma-mapping.h in the > next version. > > All existing architectures do not care at all about this > change, unless I'm missing something. > > Besides, all the other users of the DMA mapping API > also depend on CONFIG_HAS_DMA. Yes, it fixes the compile problem by preventing libata from being compiled at all. But the point is that libata should be able to work without DMA support. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-17 9:00 ` Robert Hancock @ 2009-05-17 19:38 ` Arnd Bergmann 2009-05-17 20:05 ` Jeff Garzik 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-17 19:38 UTC (permalink / raw) To: Robert Hancock Cc: Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato On Sunday 17 May 2009, Robert Hancock wrote: > Arnd Bergmann wrote: > > On Friday 15 May 2009, Tejun Heo wrote: > >> Don't know much history here but I don't wanna sprinkle ifdefs around > >> in libata so I would much prefer dummy implementation which doesn't > >> fail compile. > > > > My original patch did that by adding 'depends on HAS_DMA'. > > > > The only architectures that don't have that are m68k, m32r, > > h8300, s390 and microblaze. More research has shown that > > they all found a different way to disable the ATA drivers > > already, except microblaze. > > > > Alan, you objected the patch initially (and loudly), but > > maybe you can reconsider this. The only actual effect > > that my patch has is to allow an allyesconfig build on > > microblaze and that will implement dma-mapping.h in the > > next version. > > > > All existing architectures do not care at all about this > > change, unless I'm missing something. > > > > Besides, all the other users of the DMA mapping API > > also depend on CONFIG_HAS_DMA. > > Yes, it fixes the compile problem by preventing libata from being > compiled at all. But the point is that libata should be able to work > without DMA support. Please reread my explanations above and your own reply from last thursday. The case is entirely theoretical, as all platforms (except microblaze, which is getting fixed) either set HAS_DMA or don't allow building ATA drivers anyway. Platforms that don't support DMA can just define CONFIG_HAS_DMA and do what you suggested: On Thursday 14 May 2009, Robert Hancock wrote: > Wouldn't the easiest solution be to just dummy out the DMA API calls on > this platform to always fail? That would fix these compile problems.. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-17 19:38 ` Arnd Bergmann @ 2009-05-17 20:05 ` Jeff Garzik 2009-05-17 22:45 ` [PATCH] asm-generic: add a dma-mapping.h file Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: Jeff Garzik @ 2009-05-17 20:05 UTC (permalink / raw) To: Arnd Bergmann Cc: Robert Hancock, Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato Arnd Bergmann wrote: > On Sunday 17 May 2009, Robert Hancock wrote: > Please reread my explanations above and your own reply from > last thursday. The case is entirely theoretical, as all platforms > (except microblaze, which is getting fixed) either set HAS_DMA or > don't allow building ATA drivers anyway. Platforms that don't support > DMA can just define CONFIG_HAS_DMA and do what you suggested: > > On Thursday 14 May 2009, Robert Hancock wrote: >> Wouldn't the easiest solution be to just dummy out the DMA API calls on >> this platform to always fail? That would fix these compile problems.. That's what needs to happen. We provide no-op functions for e.g. PCI and x86 DMI, for platforms where this support does not exist. Pretty much all architectures support some form of ATA. m68k, m32r, h8300 and microblaze all have IDE interface, which means that libata needs to work on that platform. The only !ATA arch in the entire kernel is s390, AFAICT. Jeff ^ permalink raw reply [flat|nested] 39+ messages in thread
* [PATCH] asm-generic: add a dma-mapping.h file 2009-05-17 20:05 ` Jeff Garzik @ 2009-05-17 22:45 ` Arnd Bergmann 2009-05-18 6:03 ` Geert Uytterhoeven ` (2 more replies) 0 siblings, 3 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-17 22:45 UTC (permalink / raw) To: Jeff Garzik Cc: Robert Hancock, Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato h8300 and m32r currently do not provide a DMA mapping API and therefore cannot use the ATA drivers. This adds a generic version of dma-mapping.h for architectures that have none or very minimal actual support for DMA in hardware and makes the two architectures use it. Signed-off-by: Arnd Bergmann <arnd@arndb.de> --- On Sunday 17 May 2009 20:05:54 Jeff Garzik wrote: > That's what needs to happen. We provide no-op functions for e.g. PCI > and x86 DMI, for platforms where this support does not exist. > > Pretty much all architectures support some form of ATA. m68k, m32r, > h8300 and microblaze all have IDE interface, which means that libata > needs to work on that platform. > > The only !ATA arch in the entire kernel is s390, AFAICT. m68k only defines NO_DMA for Sun3 and Dragonball. Sun3 does not have ATA, Dragonball could probably just enable HAS_DMA. --- arch/h8300/Kconfig | 2 +- arch/h8300/include/asm/dma-mapping.h | 1 + arch/m32r/Kconfig | 2 +- arch/m32r/include/asm/dma-mapping.h | 1 + include/asm-generic/dma-mapping.h | 399 ++++++++++++++++++++++++++++++++++ 5 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 arch/h8300/include/asm/dma-mapping.h create mode 100644 arch/m32r/include/asm/dma-mapping.h create mode 100644 include/asm-generic/dma-mapping.h diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 9420648..36a037d 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -74,7 +74,7 @@ config NO_IOPORT def_bool y config NO_DMA - def_bool y + def_bool n config ISA bool diff --git a/arch/h8300/include/asm/dma-mapping.h b/arch/h8300/include/asm/dma-mapping.h new file mode 100644 index 0000000..e7e1690 --- /dev/null +++ b/arch/h8300/include/asm/dma-mapping.h @@ -0,0 +1 @@ +#include <asm-generic/dma-mapping.h> diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index cabba33..57ad603 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -35,7 +35,7 @@ config NO_IOPORT def_bool y config NO_DMA - def_bool y + def_bool n config HZ int diff --git a/arch/m32r/include/asm/dma-mapping.h b/arch/m32r/include/asm/dma-mapping.h new file mode 100644 index 0000000..e7e1690 --- /dev/null +++ b/arch/m32r/include/asm/dma-mapping.h @@ -0,0 +1 @@ +#include <asm-generic/dma-mapping.h> diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h new file mode 100644 index 0000000..5a14fed --- /dev/null +++ b/include/asm-generic/dma-mapping.h @@ -0,0 +1,399 @@ +#ifndef _ASM_GENERIC_DMA_MAPPING_H +#define _ASM_GENERIC_DMA_MAPPING_H +/* + * This provides a no-op variant of the DMA mapping API, + * for use by architectures that do not actually support + * DMA, or that are fully consistent and linear-mapped + * in their DMA implementation. + */ + +#include <asm/scatterlist.h> + +/* + * If any driver asks for DMA, it's not supported. + */ +#ifndef dma_supported +static inline int +dma_supported(struct device *dev, u64 mask) +{ + return 0; +} +#endif + +#ifndef dma_set_mask +static inline int +dma_set_mask(struct device *dev, u64 dma_mask) +{ + if (!dev->dma_mask || !dma_supported(dev, dma_mask)) + return -EIO; + + *dev->dma_mask = dma_mask; + return 0; +} +#endif + +/** + * dma_alloc_coherent - allocate consistent memory for DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: required memory size + * @handle: bus-specific DMA address + * + * Allocate some uncached, unbuffered memory for a device for + * performing DMA. This function allocates pages, and will + * return the CPU-viewed address, and sets @handle to be the + * device-viewed address. + */ +#ifndef dma_alloc_coherent +static inline void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag) +{ + void *virt = kmalloc(size, flag); + *dma_handle = virt_to_phys(virt); + + return virt; +} +#endif + +/** + * dma_free_coherent - free memory allocated by dma_alloc_coherent + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: size of memory originally requested in dma_alloc_coherent + * @cpu_addr: CPU-view address returned from dma_alloc_coherent + * @handle: device-view address returned from dma_alloc_coherent + * + * Free (and unmap) a DMA buffer previously allocated by + * dma_alloc_coherent(). + * + * References to memory and mappings associated with cpu_addr/handle + * during and after this call executing are illegal. + */ +#ifndef dma_free_coherent +static inline void +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) +{ + kfree(cpu_addr); +} +#endif + +#ifndef dma_alloc_noncoherent +static inline void * +dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag) +{ + return dma_alloc_coherent(dev, size, dma_handle, flag); +} +#endif + +#ifndef dma_free_noncoherent +static inline void +dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) +{ + return dma_free_coherent(dev, size, cpu_addr, dma_handle); +} +#endif + +/** + * dma_map_single - map a single buffer for streaming DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @cpu_addr: CPU direct mapped address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Ensure that any data held in the cache is appropriately discarded + * or written back. + * + * The device owns this memory once this call has completed. The CPU + * can regain ownership by calling dma_unmap_single() or dma_sync_single(). + */ +#ifndef dma_map_single +static inline dma_addr_t +dma_map_single(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + return virt_to_phys(cpu_addr); +} +#endif + +/** + * dma_unmap_single - unmap a single buffer previously mapped + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Unmap a single streaming mode DMA translation. The handle and size + * must match what was provided in the previous dma_map_single() call. + * All other usages are undefined. + * + * After this call, reads by the CPU to the buffer are guaranteed to see + * whatever the device wrote there. + */ +#ifndef dma_unmap_single +static inline void +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ +} +#endif + +/** + * dma_map_page - map a portion of a page for streaming DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @page: page that buffer resides in + * @offset: offset into page for start of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Ensure that any data held in the cache is appropriately discarded + * or written back. + * + * The device owns this memory once this call has completed. The CPU + * can regain ownership by calling dma_unmap_page() or dma_sync_single(). + */ +#ifndef dma_map_page +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + return dma_map_single(dev, page_to_virt(page), size, direction); +} +#endif + +/** + * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Unmap a single streaming mode DMA translation. The handle and size + * must match what was provided in the previous dma_map_single() call. + * All other usages are undefined. + * + * After this call, reads by the CPU to the buffer are guaranteed to see + * whatever the device wrote there. + */ +#ifndef dma_unmap_page +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + dma_unmap_single(dev, dma_address, size, direction); +} +#endif + +/** + * dma_map_sg - map a set of SG buffers for streaming mode DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scatter-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +#ifndef dma_map_sg +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents, + enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nents, i) { + sg->dma_address = sg_phys(sg); + sg->dma_length = sg->length; + } + + return nents; +} +#endif + +/** + * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Unmap a set of streaming mode DMA translations. + * Again, CPU read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +#ifndef dma_unmap_sg +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ +} +#endif + +/** + * dma_sync_single_for_cpu + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a single streaming mode DMA + * translation after a transfer. + * + * If you perform a dma_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the DMA mapping, + * you must call this function before doing so. At the next point you + * give the DMA address back to the card, you must first perform a + * dma_sync_single_for_device, and then the device again owns the + * buffer. + */ +#ifndef dma_sync_single_for_cpu +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ +} +#endif + +/** + * dma_sync_single_for_device + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a single streaming mode DMA + * translation before a transfer. + */ +#ifndef dma_sync_single_for_cpu +static inline void +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ + return dma_sync_single_for_cpu(dev, dma_handle, size, direction); +} +#endif + +#ifndef dma_sync_single_range_for_cpu +static inline void +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); +} +#endif + +#ifndef dma_sync_single_range_for_device +static inline void +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_device(dev, dma_handle, offset+size, direction); +} +#endif + +/** + * dma_sync_sg_for_cpu + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as dma_sync_single_for_cpu but for a + * scatter-gather list, same rules and usage. + */ +#ifndef dma_sync_sg_for_cpu +static inline void +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, + int nelems, enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nelems, i) { + dma_sync_single_for_cpu(dev, sg->dma_address, + sg->dma_length, direction); + } +} +#endif + +/** + * dma_sync_sg_for_device + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a set of streaming + * mode DMA translations before a transfer. + * + * The same as dma_sync_single_for_device but for a + * scatter-gather list, same rules and usage. + */ +#ifndef dma_sync_sg_for_device +static inline void +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl, + int nelems, enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + for_each_sg(sgl, sg, nelems, i) { + dma_sync_single_for_device(dev, sg->dma_address, + sg->dma_length, direction); + } +} +#endif + +#ifndef dma_is_consistent +static inline int +dma_is_consistent(struct device *dev, dma_addr_t dma_handle) +{ + return 1; +} +#endif + +#ifndef dma_get_cache_alignment +static inline int +dma_get_cache_alignment(void) +{ + return 1; +} +#endif + +#ifndef dma_mapping_error +static inline int +dma_mapping_error(struct device *dev, dma_addr_t dma_handle) +{ + return 0; +} +#endif + +#ifndef dma_cache_sync +static inline void +dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) +{ +} +#endif + +#endif -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-17 22:45 ` [PATCH] asm-generic: add a dma-mapping.h file Arnd Bergmann @ 2009-05-18 6:03 ` Geert Uytterhoeven 2009-05-18 8:28 ` Arnd Bergmann 2009-05-18 10:45 ` FUJITA Tomonori 2009-05-18 22:54 ` Jeff Garzik 2 siblings, 1 reply; 39+ messages in thread From: Geert Uytterhoeven @ 2009-05-18 6:03 UTC (permalink / raw) To: Arnd Bergmann Cc: Jeff Garzik, Robert Hancock, Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, linux-m68k, ysato On Mon, May 18, 2009 at 00:45, Arnd Bergmann <arnd@arndb.de> wrote: > --- /dev/null > +++ b/include/asm-generic/dma-mapping.h > @@ -0,0 +1,399 @@ > +#ifndef _ASM_GENERIC_DMA_MAPPING_H > +#define _ASM_GENERIC_DMA_MAPPING_H > +/* > + * This provides a no-op variant of the DMA mapping API, > + * for use by architectures that do not actually support > + * DMA, or that are fully consistent and linear-mapped > + * in their DMA implementation. > + */ > + > +#include <asm/scatterlist.h> > + > +/* > + * If any driver asks for DMA, it's not supported. > + */ > +#ifndef dma_supported > +static inline int > +dma_supported(struct device *dev, u64 mask) > +{ > + return 0; > +} > +#endif > + > +#ifndef dma_set_mask > +static inline int > +dma_set_mask(struct device *dev, u64 dma_mask) > +{ > + if (!dev->dma_mask || !dma_supported(dev, dma_mask)) > + return -EIO; > + > + *dev->dma_mask = dma_mask; > + return 0; > +} > +#endif > + > +/** > + * dma_alloc_coherent - allocate consistent memory for DMA > + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices > + * @size: required memory size > + * @handle: bus-specific DMA address > + * > + * Allocate some uncached, unbuffered memory for a device for > + * performing DMA. This function allocates pages, and will > + * return the CPU-viewed address, and sets @handle to be the > + * device-viewed address. > + */ > +#ifndef dma_alloc_coherent > +static inline void * > +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, > + gfp_t flag) > +{ > + void *virt = kmalloc(size, flag); kmalloc() may fail. > + *dma_handle = virt_to_phys(virt); Not all variants of virt_to_phys() may handle the NULL case very well. I took a statistically invalid sample: some just cast to unsigned long, other subtract PAGE_OFFSET. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-18 6:03 ` Geert Uytterhoeven @ 2009-05-18 8:28 ` Arnd Bergmann 0 siblings, 0 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-18 8:28 UTC (permalink / raw) To: Geert Uytterhoeven Cc: Jeff Garzik, Robert Hancock, Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, linux-m68k, ysato On Monday 18 May 2009, Geert Uytterhoeven wrote: > > +#ifndef dma_alloc_coherent > > +static inline void * > > +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, > > + gfp_t flag) > > +{ > > + void *virt = kmalloc(size, flag); > > kmalloc() may fail. > > > + *dma_handle = virt_to_phys(virt); > > Not all variants of virt_to_phys() may handle the NULL case very well. > I took a statistically invalid sample: some just cast to unsigned > long, other subtract PAGE_OFFSET. Right. It should not really hurt, because all users need to check virt before using dma_handle, but I can fix it just to be sure. I'll wait for comments from Fujita Tomonori and others before I repost. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-17 22:45 ` [PATCH] asm-generic: add a dma-mapping.h file Arnd Bergmann 2009-05-18 6:03 ` Geert Uytterhoeven @ 2009-05-18 10:45 ` FUJITA Tomonori 2009-05-18 14:45 ` Arnd Bergmann 2009-05-18 22:54 ` Jeff Garzik 2 siblings, 1 reply; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-18 10:45 UTC (permalink / raw) To: arnd Cc: jgarzik, hancockrwd, htejun, fujita.tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Sun, 17 May 2009 22:45:21 +0000 Arnd Bergmann <arnd@arndb.de> wrote: > h8300 and m32r currently do not provide a DMA mapping API > and therefore cannot use the ATA drivers. This adds a > generic version of dma-mapping.h for architectures that > have none or very minimal actual support for DMA in hardware > and makes the two architectures use it. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > On Sunday 17 May 2009 20:05:54 Jeff Garzik wrote: > > > That's what needs to happen. We provide no-op functions for e.g. PCI > > and x86 DMI, for platforms where this support does not exist. > > > > Pretty much all architectures support some form of ATA. m68k, m32r, > > h8300 and microblaze all have IDE interface, which means that libata > > needs to work on that platform. > > > > The only !ATA arch in the entire kernel is s390, AFAICT. > > m68k only defines NO_DMA for Sun3 and Dragonball. Sun3 does > not have ATA, Dragonball could probably just enable HAS_DMA. > > --- > arch/h8300/Kconfig | 2 +- > arch/h8300/include/asm/dma-mapping.h | 1 + > arch/m32r/Kconfig | 2 +- > arch/m32r/include/asm/dma-mapping.h | 1 + > include/asm-generic/dma-mapping.h | 399 ++++++++++++++++++++++++++++++++++ > 5 files changed, 403 insertions(+), 2 deletions(-) > create mode 100644 arch/h8300/include/asm/dma-mapping.h > create mode 100644 arch/m32r/include/asm/dma-mapping.h > create mode 100644 include/asm-generic/dma-mapping.h > > diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig > index 9420648..36a037d 100644 > --- a/arch/h8300/Kconfig > +++ b/arch/h8300/Kconfig > @@ -74,7 +74,7 @@ config NO_IOPORT > def_bool y > > config NO_DMA > - def_bool y > + def_bool n > > config ISA > bool > diff --git a/arch/h8300/include/asm/dma-mapping.h b/arch/h8300/include/asm/dma-mapping.h > new file mode 100644 > index 0000000..e7e1690 > --- /dev/null > +++ b/arch/h8300/include/asm/dma-mapping.h > @@ -0,0 +1 @@ > +#include <asm-generic/dma-mapping.h> > diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig > index cabba33..57ad603 100644 > --- a/arch/m32r/Kconfig > +++ b/arch/m32r/Kconfig > @@ -35,7 +35,7 @@ config NO_IOPORT > def_bool y > > config NO_DMA > - def_bool y > + def_bool n > > config HZ > int > diff --git a/arch/m32r/include/asm/dma-mapping.h b/arch/m32r/include/asm/dma-mapping.h > new file mode 100644 > index 0000000..e7e1690 > --- /dev/null > +++ b/arch/m32r/include/asm/dma-mapping.h > @@ -0,0 +1 @@ > +#include <asm-generic/dma-mapping.h> > diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h > new file mode 100644 > index 0000000..5a14fed > --- /dev/null > +++ b/include/asm-generic/dma-mapping.h > @@ -0,0 +1,399 @@ > +#ifndef _ASM_GENERIC_DMA_MAPPING_H > +#define _ASM_GENERIC_DMA_MAPPING_H > +/* > + * This provides a no-op variant of the DMA mapping API, > + * for use by architectures that do not actually support > + * DMA, or that are fully consistent and linear-mapped > + * in their DMA implementation. > + */ > + > +#include <asm/scatterlist.h> > + > +/* > + * If any driver asks for DMA, it's not supported. > + */ > +#ifndef dma_supported > +static inline int > +dma_supported(struct device *dev, u64 mask) > +{ > + return 0; > +} > +#endif NACK'ed, sorry. - these idndef tricks are really ugly and wrong. - these functions are not generic at all. - it's confusing to have two ways to handle this issue; dma-mapping-broken.h and dma-mapping.h. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-18 10:45 ` FUJITA Tomonori @ 2009-05-18 14:45 ` Arnd Bergmann 2009-05-18 22:44 ` FUJITA Tomonori 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-18 14:45 UTC (permalink / raw) To: FUJITA Tomonori Cc: jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Monday 18 May 2009, FUJITA Tomonori wrote: > > NACK'ed, sorry. I had no idea how hard it would get to fix a simple allyesconfig build error. This is the third time that a new approach to getting ATA to build on all platforms is gets a NAK... > - these idndef tricks are really ugly and wrong. > - these functions are not generic at all. I was trying to do two things at once: - provide a default implementation for each function that an architecture can override, therefore the #ifdef magic. - Have a minimal working implementation of the API that at least makes sense for architectures that do not support DMA, but want to share some of the code. Ten of the existing architectures simply try do a linear mapping, and that should easily be possible in a generic way not too different from what I posted. Would you agree to a patch that works with the same code on e.g. arm, microblaze, mn10300 and sh and uses only a few #ifdefs? > - it's confusing to have two ways to handle this issue; > dma-mapping-broken.h and dma-mapping.h. We actually already have three ways to handle this right now: - dma-mapping-broken.h: only used on Sun3 m68k, i.e. not interesting any more, plus it does not solve the question of how to build ATA drivers on architectures without DMA. - selecting NO_DMA: This works fine for everything except ATA. All other drivers using dma-mapping.h either depend on HAS_DMA or sprinkle their files with #ifdef. - adding a bogus dma-mapping.h: cris, um and microblaze currently set HAS_DMA but add a dma-mapping.h that allows stuff to compile but cannot actually work. I think that dma-mapping-broken.h has served its purpose and we should now have two implementations in asm-generic, the one you posted recently for ia64, x86, parisc, powerpc and sparc64 and one for all architectures that only have linear mappings. The version I posted is certainly not generic enough for those, but I can keep improving it. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-18 14:45 ` Arnd Bergmann @ 2009-05-18 22:44 ` FUJITA Tomonori 2009-05-19 16:22 ` Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-18 22:44 UTC (permalink / raw) To: arnd Cc: fujita.tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Mon, 18 May 2009 16:45:24 +0200 Arnd Bergmann <arnd@arndb.de> wrote: > On Monday 18 May 2009, FUJITA Tomonori wrote: > > > > NACK'ed, sorry. > > I had no idea how hard it would get to fix a simple > allyesconfig build error. This is the third time > that a new approach to getting ATA to build on all > platforms is gets a NAK... > > > - these idndef tricks are really ugly and wrong. > > - these functions are not generic at all. > > I was trying to do two things at once: > > - provide a default implementation for each function > that an architecture can override, therefore the > #ifdef magic. I know what you tried with #ifdef but having something like '#define dma_map_sg' in arch's dma-mapping.h is unacceptable. > - Have a minimal working implementation of the API > that at least makes sense for architectures that > do not support DMA, but want to share some of the > code. Well, it might make sense but we don't call architectures that don't support DMA 'generic'. > Ten of the existing architectures simply try do a > linear mapping, and that should easily be possible > in a generic way not too different from what I posted. Your proposal doesn't work with arch/x86/kernel/pci-nommu.c, which is trying a linear mapping, what you are talking about. > Would you agree to a patch that works with the same > code on e.g. arm, microblaze, mn10300 and sh and > uses only a few #ifdefs? Having such helper for a linear mapping might be helpful but your approach is wrong. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-18 22:44 ` FUJITA Tomonori @ 2009-05-19 16:22 ` Arnd Bergmann 2009-05-19 17:01 ` Grant Grundler 2009-05-22 12:12 ` FUJITA Tomonori 0 siblings, 2 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-19 16:22 UTC (permalink / raw) To: FUJITA Tomonori Cc: jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Tuesday 19 May 2009, FUJITA Tomonori wrote: > > Would you agree to a patch that works with the same > > code on e.g. arm, microblaze, mn10300 and sh and > > uses only a few #ifdefs? > > Having such helper for a linear mapping might be helpful but your > approach is wrong. Do you like this approach better? I've merged a few architectures that were relatively simple. This file should be usable by all architectures that have a linear mapping and are either fully coherent (like cris) or just require flushing the dcache when passing a buffer to the device. It's become pretty obvious where some of my bugs were in the previous code, I hopefully did better this time and maybe you find the rest. I've also added the dma debugging stuff in here and fixed a number of bugs in all the different architectures on the way, but I can send separate patches for those before doing the merge. I've also tried merging frv and m68k, but they have some peculiarities that made it slightly harder. Signed-off-by: Arnd Bergmann <arnd@arndb.de> include/asm-generic/dma-mapping-linear.h | 391 +++++++++++++++++++++++++++++ arch/avr32/include/asm/dma-mapping.h | 408 ++++--------------------------- arch/blackfin/include/asm/dma-mapping.h | 118 +------- arch/cris/include/asm/dma-mapping.h | 194 +------------- arch/mn10300/include/asm/dma-mapping.h | 266 ++------------------ arch/sh/include/asm/dma-mapping.h | 258 ++----------------- arch/xtensa/include/asm/dma-mapping.h | 220 +++------------- 7 files changed, 606 insertions(+), 1249 deletions(-) diff --git a/include/asm-generic/dma-mapping-linear.h b/include/asm-generic/dma-mapping-linear.h new file mode 100644 index 0000000..13f37db --- /dev/null +++ b/include/asm-generic/dma-mapping-linear.h @@ -0,0 +1,391 @@ +#ifndef __ASM_GENERIC_DMA_MAPPING_H +#define __ASM_GENERIC_DMA_MAPPING_H + +#include <linux/mm.h> +#include <linux/device.h> +#include <linux/dma-debug.h> +#include <linux/scatterlist.h> +#include <asm/cacheflush.h> +#include <asm/io.h> + +#ifdef CONFIG_DMA_COHERENT +/* + * An architecture should override these if it needs to + * perform cache flushes before passing bus addresses + * to a device. + * It can either do a full flush in dma_coherent_dev + * and return 1 from there, or implement more specific + * synchronization in dma_cache_sync, which will be + * applied separately to each sg element. + */ +static inline int +dma_coherent_dev(struct device *dev) +{ + return 1; +} + +static inline void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ +} + +/** + * dma_alloc_coherent - allocate consistent memory for DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: required memory size + * @handle: bus-specific DMA address + * + * Allocate some uncached, unbuffered memory for a device for + * performing DMA. This function allocates pages, and will + * return the CPU-viewed address, and sets @handle to be the + * device-viewed address. + */ +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *ret; + struct page *page; + int node = dev_to_node(dev); + + /* ignore region specifiers */ + flag &= ~(__GFP_HIGHMEM); + + page = alloc_pages_node(node, flag, get_order(size)); + if (page == NULL) + return NULL; + ret = page_address(page); + memset(ret, 0, size); + *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); + + return ret; +} + +/** + * dma_free_coherent - free memory allocated by dma_alloc_coherent + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: size of memory originally requested in dma_alloc_coherent + * @cpu_addr: CPU-view address returned from dma_alloc_coherent + * @handle: device-view address returned from dma_alloc_coherent + * + * Free (and unmap) a DMA buffer previously allocated by + * dma_alloc_coherent(). + * + * References to memory and mappings associated with cpu_addr/handle + * during and after this call executing are illegal. + */ +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} +#else +extern void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag); + +extern void +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle); +#endif + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) + +/** + * dma_map_single - map a single buffer for streaming DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @cpu_addr: CPU direct mapped address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Ensure that any data held in the cache is appropriately discarded + * or written back. + * + * The device owns this memory once this call has completed. The CPU + * can regain ownership by calling dma_unmap_single() or dma_sync_single(). + */ +static inline dma_addr_t +dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + dma_addr_t dma_addr = virt_to_bus(ptr); + BUG_ON(!valid_dma_direction(direction)); + + if (!dma_coherent_dev(dev)) + dma_cache_sync(dev, ptr, size, direction); + + debug_dma_map_page(dev, virt_to_page(ptr), + (unsigned long)ptr & ~PAGE_MASK, size, + direction, dma_addr, true); + + return dma_addr; +} + +/** + * dma_unmap_single - unmap a single buffer previously mapped + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Unmap a single streaming mode DMA translation. The handle and size + * must match what was provided in the previous dma_map_single() call. + * All other usages are undefined. + * + * After this call, reads by the CPU to the buffer are guaranteed to see + * whatever the device wrote there. + */ +static inline void +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + debug_dma_unmap_page(dev, dma_addr, size, direction, true); +} + +/** + * dma_map_sg - map a set of SG buffers for streaming mode DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scatter-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, + enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i, sync; + + BUG_ON(!valid_dma_direction(direction)); + WARN_ON(nents == 0 || sglist[0].length == 0); + + sync = !dma_coherent_dev(dev); + + for_each_sg(sglist, sg, nents, i) { + BUG_ON(!sg_page(sg)); + + sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset; + sg_dma_len(sg) = sg->length; + if (sync) + dma_cache_sync(dev, sg_virt(sg), sg->length, direction); + } + + debug_dma_map_sg(dev, sg, nents, i, direction); + + return nents; +} + +/** + * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Unmap a set of streaming mode DMA translations. + * Again, CPU read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + debug_dma_unmap_sg(dev, sg, nhwentries, direction); +} + +/** + * dma_map_page - map a portion of a page for streaming DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @page: page that buffer resides in + * @offset: offset into page for start of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Ensure that any data held in the cache is appropriately discarded + * or written back. + * + * The device owns this memory once this call has completed. The CPU + * can regain ownership by calling dma_unmap_page() or dma_sync_single(). + */ +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, unsigned long offset, + size_t size, enum dma_data_direction direction) +{ + return dma_map_single(dev, page_address(page) + offset, + size, direction); +} + +/** + * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Unmap a single streaming mode DMA translation. The handle and size + * must match what was provided in the previous dma_map_single() call. + * All other usages are undefined. + * + * After this call, reads by the CPU to the buffer are guaranteed to see + * whatever the device wrote there. + */ +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + dma_unmap_single(dev, dma_address, size, direction); +} + +/** + * dma_sync_single_for_cpu + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @handle: DMA address of buffer + * @size: size of buffer to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a single streaming mode DMA + * translation after a transfer. + * + * If you perform a dma_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the DMA mapping, + * you must call this function before doing so. At the next point you + * give the DMA address back to the card, you must first perform a + * dma_sync_single_for_device, and then the device again owns the + * buffer. + */ +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + debug_dma_sync_single_for_cpu(dev, dma_handle, size, direction); +} + +static inline void +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + debug_dma_sync_single_range_for_cpu(dev, dma_handle, + offset, size, direction); +} + +/** + * dma_sync_sg_for_cpu + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as dma_sync_single_for_* but for a scatter-gather list, + * same rules and usage. + */ +static inline void +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + debug_dma_sync_sg_for_cpu(dev, sg, nents, direction); +} + +static inline void +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ + if (!dma_coherent_dev(dev)) + dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); + debug_dma_sync_single_for_device(dev, dma_handle, size, direction); +} + +static inline void +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + if (!dma_coherent_dev(dev)) + dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); + debug_dma_sync_single_range_for_device(dev, dma_handle, + offset, size, direction); +} + +static inline void +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, + int nents, enum dma_data_direction direction) +{ + struct scatterlist *sg; + int i; + + if (!dma_coherent_dev(dev)) + for_each_sg(sglist, sg, nents, i) + dma_cache_sync(dev, sg_virt(sg), sg->length, direction); + + debug_dma_sync_sg_for_device(dev, sg, nents, direction); +} + +static inline int +dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} + +/* + * Return whether the given device DMA address mask can be supported + * properly. For example, if your device can only drive the low 24-bits + * during bus mastering, then you would pass 0x00ffffff as the mask + * to this function. + */ +static inline int +dma_supported(struct device *dev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + +static inline int +dma_set_mask(struct device *dev, u64 dma_mask) +{ + if (!dev->dma_mask || !dma_supported(dev, dma_mask)) + return -EIO; + + *dev->dma_mask = dma_mask; + + return 0; +} + +static inline int +dma_get_cache_alignment(void) +{ + return L1_CACHE_BYTES; +} + +static inline int +dma_is_consistent(struct device *dev, dma_addr_t dma_addr) +{ + return dma_coherent_dev(dev); +} + +#endif /* __ASM_GENERIC_DMA_MAPPING_H */ diff --git a/arch/avr32/include/asm/dma-mapping.h b/arch/avr32/include/asm/dma-mapping.h dissimilarity index 86% index 0399359..b1d73fb 100644 --- a/arch/avr32/include/asm/dma-mapping.h +++ b/arch/avr32/include/asm/dma-mapping.h @@ -1,349 +1,59 @@ -#ifndef __ASM_AVR32_DMA_MAPPING_H -#define __ASM_AVR32_DMA_MAPPING_H - -#include <linux/mm.h> -#include <linux/device.h> -#include <linux/scatterlist.h> -#include <asm/processor.h> -#include <asm/cacheflush.h> -#include <asm/io.h> - -extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - int direction); - -/* - * Return whether the given device DMA address mask can be supported - * properly. For example, if your device can only drive the low 24-bits - * during bus mastering, then you would pass 0x00ffffff as the mask - * to this function. - */ -static inline int dma_supported(struct device *dev, u64 mask) -{ - /* Fix when needed. I really don't know of any limitations */ - return 1; -} - -static inline int dma_set_mask(struct device *dev, u64 dma_mask) -{ - if (!dev->dma_mask || !dma_supported(dev, dma_mask)) - return -EIO; - - *dev->dma_mask = dma_mask; - return 0; -} - -/* - * dma_map_single can't fail as it is implemented now. - */ -static inline int dma_mapping_error(struct device *dev, dma_addr_t addr) -{ - return 0; -} - -/** - * dma_alloc_coherent - allocate consistent memory for DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @size: required memory size - * @handle: bus-specific DMA address - * - * Allocate some uncached, unbuffered memory for a device for - * performing DMA. This function allocates pages, and will - * return the CPU-viewed address, and sets @handle to be the - * device-viewed address. - */ -extern void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp); - -/** - * dma_free_coherent - free memory allocated by dma_alloc_coherent - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @size: size of memory originally requested in dma_alloc_coherent - * @cpu_addr: CPU-view address returned from dma_alloc_coherent - * @handle: device-view address returned from dma_alloc_coherent - * - * Free (and unmap) a DMA buffer previously allocated by - * dma_alloc_coherent(). - * - * References to memory and mappings associated with cpu_addr/handle - * during and after this call executing are illegal. - */ -extern void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle); - -/** - * dma_alloc_writecombine - allocate write-combining memory for DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @size: required memory size - * @handle: bus-specific DMA address - * - * Allocate some uncached, buffered memory for a device for - * performing DMA. This function allocates pages, and will - * return the CPU-viewed address, and sets @handle to be the - * device-viewed address. - */ -extern void *dma_alloc_writecombine(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp); - -/** - * dma_free_coherent - free memory allocated by dma_alloc_writecombine - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @size: size of memory originally requested in dma_alloc_writecombine - * @cpu_addr: CPU-view address returned from dma_alloc_writecombine - * @handle: device-view address returned from dma_alloc_writecombine - * - * Free (and unmap) a DMA buffer previously allocated by - * dma_alloc_writecombine(). - * - * References to memory and mappings associated with cpu_addr/handle - * during and after this call executing are illegal. - */ -extern void dma_free_writecombine(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle); - -/** - * dma_map_single - map a single buffer for streaming DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @cpu_addr: CPU direct mapped address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction - * - * Ensure that any data held in the cache is appropriately discarded - * or written back. - * - * The device owns this memory once this call has completed. The CPU - * can regain ownership by calling dma_unmap_single() or dma_sync_single(). - */ -static inline dma_addr_t -dma_map_single(struct device *dev, void *cpu_addr, size_t size, - enum dma_data_direction direction) -{ - dma_cache_sync(dev, cpu_addr, size, direction); - return virt_to_bus(cpu_addr); -} - -/** - * dma_unmap_single - unmap a single buffer previously mapped - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @handle: DMA address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction - * - * Unmap a single streaming mode DMA translation. The handle and size - * must match what was provided in the previous dma_map_single() call. - * All other usages are undefined. - * - * After this call, reads by the CPU to the buffer are guaranteed to see - * whatever the device wrote there. - */ -static inline void -dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction) -{ - -} - -/** - * dma_map_page - map a portion of a page for streaming DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @page: page that buffer resides in - * @offset: offset into page for start of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction - * - * Ensure that any data held in the cache is appropriately discarded - * or written back. - * - * The device owns this memory once this call has completed. The CPU - * can regain ownership by calling dma_unmap_page() or dma_sync_single(). - */ -static inline dma_addr_t -dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - return dma_map_single(dev, page_address(page) + offset, - size, direction); -} - -/** - * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @handle: DMA address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction - * - * Unmap a single streaming mode DMA translation. The handle and size - * must match what was provided in the previous dma_map_single() call. - * All other usages are undefined. - * - * After this call, reads by the CPU to the buffer are guaranteed to see - * whatever the device wrote there. - */ -static inline void -dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, - enum dma_data_direction direction) -{ - dma_unmap_single(dev, dma_address, size, direction); -} - -/** - * dma_map_sg - map a set of SG buffers for streaming mode DMA - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scatter-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ -static inline int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - int i; - - for (i = 0; i < nents; i++) { - char *virt; - - sg[i].dma_address = page_to_bus(sg_page(&sg[i])) + sg[i].offset; - virt = sg_virt(&sg[i]); - dma_cache_sync(dev, virt, sg[i].length, direction); - } - - return nents; -} - -/** - * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Unmap a set of streaming mode DMA translations. - * Again, CPU read rules concerning calls here are the same as for - * pci_unmap_single() above. - */ -static inline void -dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, - enum dma_data_direction direction) -{ - -} - -/** - * dma_sync_single_for_cpu - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @handle: DMA address of buffer - * @size: size of buffer to map - * @dir: DMA transfer direction - * - * Make physical memory consistent for a single streaming mode DMA - * translation after a transfer. - * - * If you perform a dma_map_single() but wish to interrogate the - * buffer using the cpu, yet do not wish to teardown the DMA mapping, - * you must call this function before doing so. At the next point you - * give the DMA address back to the card, you must first perform a - * dma_sync_single_for_device, and then the device again owns the - * buffer. - */ -static inline void -dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ - /* - * No need to do anything since the CPU isn't supposed to - * touch this memory after we flushed it at mapping- or - * sync-for-device time. - */ -} - -static inline void -dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ - dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); -} - -static inline void -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - /* just sync everything, that's all the pci API can do */ - dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); -} - -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - /* just sync everything, that's all the pci API can do */ - dma_sync_single_for_device(dev, dma_handle, offset+size, direction); -} - -/** - * dma_sync_sg_for_cpu - * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices - * @sg: list of buffers - * @nents: number of buffers to map - * @dir: DMA transfer direction - * - * Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - * - * The same as dma_sync_single_for_* but for a scatter-gather list, - * same rules and usage. - */ -static inline void -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - /* - * No need to do anything since the CPU isn't supposed to - * touch this memory after we flushed it at mapping- or - * sync-for-device time. - */ -} - -static inline void -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - int i; - - for (i = 0; i < nents; i++) { - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, direction); - } -} - -/* Now for the API extensions over the pci_ one */ - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) - -static inline int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) -{ - return 1; -} - -static inline int dma_get_cache_alignment(void) -{ - return boot_cpu_data.dcache.linesz; -} - -#endif /* __ASM_AVR32_DMA_MAPPING_H */ +#ifndef __ASM_AVR32_DMA_MAPPING_H +#define __ASM_AVR32_DMA_MAPPING_H + +#include <linux/mm.h> +#include <linux/device.h> +#include <linux/scatterlist.h> +#include <asm/processor.h> +#include <asm/cacheflush.h> +#include <asm/io.h> + +static inline int +dma_coherent_dev(struct device *dev) +{ + return 0; +} + +extern void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction); + +static inline int +dma_get_cache_alignment(void) +{ + return boot_cpu_data.dcache.linesz; +} + +/** + * dma_alloc_writecombine - allocate write-combining memory for DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: required memory size + * @handle: bus-specific DMA address + * + * Allocate some uncached, buffered memory for a device for + * performing DMA. This function allocates pages, and will + * return the CPU-viewed address, and sets @handle to be the + * device-viewed address. + */ +extern void *dma_alloc_writecombine(struct device *dev, size_t size, + dma_addr_t *handle, gfp_t gfp); + +/** + * dma_free_writecombine - free memory allocated by dma_alloc_writecombine + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @size: size of memory originally requested in dma_alloc_writecombine + * @cpu_addr: CPU-view address returned from dma_alloc_writecombine + * @handle: device-view address returned from dma_alloc_writecombine + * + * Free (and unmap) a DMA buffer previously allocated by + * dma_alloc_writecombine(). + * + * References to memory and mappings associated with cpu_addr/handle + * during and after this call executing are illegal. + */ +extern void dma_free_writecombine(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t handle); + +#include <asm-generic/dma-mapping-linear.h> + +#endif /* __ASM_AVR32_DMA_MAPPING_H */ diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h dissimilarity index 95% index d7d9148..169d82d 100644 --- a/arch/blackfin/include/asm/dma-mapping.h +++ b/arch/blackfin/include/asm/dma-mapping.h @@ -1,98 +1,20 @@ -#ifndef _BLACKFIN_DMA_MAPPING_H -#define _BLACKFIN_DMA_MAPPING_H - -#include <asm/scatterlist.h> - -void dma_alloc_init(unsigned long start, unsigned long end); -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp); -void dma_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle); - -/* - * Now for the API extensions over the pci_ one - */ -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) - -static inline -int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return 0; -} - -/* - * Map a single buffer of the indicated size for DMA in streaming mode. - * The 32-bit bus address to use is returned. - * - * Once the device is given the dma address, the device owns this memory - * until either pci_unmap_single or pci_dma_sync_single is performed. - */ -extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, - enum dma_data_direction direction); - -static inline dma_addr_t -dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ - return dma_map_single(dev, page_address(page) + offset, size, dir); -} - -/* - * Unmap a single streaming mode DMA translation. The dma_addr and size - * must match what was provided for in a previous pci_map_single call. All - * other usages are undefined. - * - * After this call, reads by the cpu to the buffer are guarenteed to see - * whatever the device wrote there. - */ -extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction); - -static inline void -dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction dir) -{ - dma_unmap_single(dev, dma_addr, size, dir); -} - -/* - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scather-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ -extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction); - -/* - * Unmap a set of streaming mode DMA translations. - * Again, cpu read rules concerning calls here are the same as for - * pci_unmap_single() above. - */ -extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, - int nhwentries, enum dma_data_direction direction); - -static inline void dma_sync_single_for_cpu(struct device *dev, - dma_addr_t handle, size_t size, - enum dma_data_direction dir) -{ -} - -static inline void dma_sync_single_for_device(struct device *dev, - dma_addr_t handle, size_t size, - enum dma_data_direction dir) -{ -} -#endif /* _BLACKFIN_DMA_MAPPING_H */ +#ifndef _BLACKFIN_DMA_MAPPING_H +#define _BLACKFIN_DMA_MAPPING_H + +static inline int +dma_coherent_dev(struct device *dev) +{ + return 0; +} + +static inline void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ +} + +extern void dma_alloc_init(unsigned long start, unsigned long end); + +#include <asm-generic/dma-mapping-linear.h> + +#endif /* _BLACKFIN_DMA_MAPPING_H */ diff --git a/arch/cris/include/asm/dma-mapping.h b/arch/cris/include/asm/dma-mapping.h dissimilarity index 91% index da8ef8e..75c837e 100644 --- a/arch/cris/include/asm/dma-mapping.h +++ b/arch/cris/include/asm/dma-mapping.h @@ -1,170 +1,24 @@ -/* DMA mapping. Nothing tricky here, just virt_to_phys */ - -#ifndef _ASM_CRIS_DMA_MAPPING_H -#define _ASM_CRIS_DMA_MAPPING_H - -#include <linux/mm.h> -#include <linux/kernel.h> - -#include <asm/cache.h> -#include <asm/io.h> -#include <asm/scatterlist.h> - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) - -#ifdef CONFIG_PCI -#include <asm-generic/dma-coherent.h> - -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); - -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); -#else -static inline void * -dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - gfp_t flag) -{ - BUG(); - return NULL; -} - -static inline void -dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, - dma_addr_t dma_handle) -{ - BUG(); -} -#endif -static inline dma_addr_t -dma_map_single(struct device *dev, void *ptr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - return virt_to_phys(ptr); -} - -static inline void -dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -static inline int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - printk("Map sg\n"); - return nents; -} - -static inline dma_addr_t -dma_map_page(struct device *dev, struct page *page, unsigned long offset, - size_t size, enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - return page_to_phys(page) + offset; -} - -static inline void -dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - - -static inline void -dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -static inline void -dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, - enum dma_data_direction direction) -{ -} - -static inline int -dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return 0; -} - -static inline int -dma_supported(struct device *dev, u64 mask) -{ - /* - * we fall back to GFP_DMA when the mask isn't all 1s, - * so we can't guarantee allocations that must be - * within a tighter range than GFP_DMA.. - */ - if(mask < 0x00ffffff) - return 0; - - return 1; -} - -static inline int -dma_set_mask(struct device *dev, u64 mask) -{ - if(!dev->dma_mask || !dma_supported(dev, mask)) - return -EIO; - - *dev->dma_mask = mask; - - return 0; -} - -static inline int -dma_get_cache_alignment(void) -{ - return (1 << INTERNODE_CACHE_SHIFT); -} - -#define dma_is_consistent(d, h) (1) - -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - - -#endif +#ifndef _ASM_CRIS_DMA_MAPPING_H +#define _ASM_CRIS_DMA_MAPPING_H + +#include <linux/mm.h> +#include <linux/kernel.h> + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/scatterlist.h> +#include <asm-generic/dma-mapping-linear.h> + +#ifdef CONFIG_PCI +#include <asm-generic/dma-coherent.h> +#endif + +static inline int +cris_dma_get_cache_alignment(void) +{ + return (1 << INTERNODE_CACHE_SHIFT); +} + +#define dma_get_cache_alignment cris_dma_get_cache_alignment + +#endif diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h dissimilarity index 90% index ccae8f6..d888fd1 100644 --- a/arch/mn10300/include/asm/dma-mapping.h +++ b/arch/mn10300/include/asm/dma-mapping.h @@ -1,234 +1,32 @@ -/* DMA mapping routines for the MN10300 arch - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ -#ifndef _ASM_DMA_MAPPING_H -#define _ASM_DMA_MAPPING_H - -#include <linux/mm.h> -#include <linux/scatterlist.h> - -#include <asm/cache.h> -#include <asm/io.h> - -extern void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, int flag); - -extern void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f)) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent((d), (s), (v), (h)) - -/* - * Map a single buffer of the indicated size for DMA in streaming mode. The - * 32-bit bus address to use is returned. - * - * Once the device is given the dma address, the device owns this memory until - * either pci_unmap_single or pci_dma_sync_single is performed. - */ -static inline -dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - mn10300_dcache_flush_inv(); - return virt_to_bus(ptr); -} - -/* - * Unmap a single streaming mode DMA translation. The dma_addr and size must - * match what was provided for in a previous pci_map_single call. All other - * usages are undefined. - * - * After this call, reads by the cpu to the buffer are guarenteed to see - * whatever the device wrote there. - */ -static inline -void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -/* - * Map a set of buffers described by scatterlist in streaming mode for DMA. - * This is the scather-gather version of the above pci_map_single interface. - * Here the scatter gather list elements are each tagged with the appropriate - * dma address and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of DMA - * address/length pairs than there are SG table elements. (for example - * via virtual mapping capabilities) The routine returns the number of - * addr/length pairs actually used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are the same - * here. - */ -static inline -int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, - enum dma_data_direction direction) -{ - struct scatterlist *sg; - int i; - - BUG_ON(!valid_dma_direction(direction)); - WARN_ON(nents == 0 || sglist[0].length == 0); - - for_each_sg(sglist, sg, nents, i) { - BUG_ON(!sg_page(sg)); - - sg->dma_address = sg_phys(sg); - } - - mn10300_dcache_flush_inv(); - return nents; -} - -/* - * Unmap a set of streaming mode DMA translations. - * Again, cpu read rules concerning calls here are the same as for - * pci_unmap_single() above. - */ -static inline -void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, - enum dma_data_direction direction) -{ - BUG_ON(!valid_dma_direction(direction)); -} - -/* - * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical - * to pci_map_single, but takes a struct page instead of a virtual address - */ -static inline -dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - return page_to_bus(page) + offset; -} - -static inline -void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -/* - * Make physical memory consistent for a single streaming mode DMA translation - * after a transfer. - * - * If you perform a pci_map_single() but wish to interrogate the buffer using - * the cpu, yet do not wish to teardown the PCI dma mapping, you must call this - * function before doing so. At the next point you give the PCI dma address - * back to the card, the device again owns the buffer. - */ -static inline -void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ -} - -static inline -void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction direction) -{ - mn10300_dcache_flush_inv(); -} - -static inline -void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ -} - -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - mn10300_dcache_flush_inv(); -} - - -/* - * Make physical memory consistent for a set of streaming mode DMA translations - * after a transfer. - * - * The same as pci_dma_sync_single but for a scatter-gather list, same rules - * and usage. - */ -static inline -void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction direction) -{ -} - -static inline -void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction direction) -{ - mn10300_dcache_flush_inv(); -} - -static inline -int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return 0; -} - -/* - * Return whether the given PCI device DMA address mask can be supported - * properly. For example, if your device can only drive the low 24-bits during - * PCI bus mastering, then you would pass 0x00ffffff as the mask to this - * function. - */ -static inline -int dma_supported(struct device *dev, u64 mask) -{ - /* - * we fall back to GFP_DMA when the mask isn't all 1s, so we can't - * guarantee allocations that must be within a tighter range than - * GFP_DMA - */ - if (mask < 0x00ffffff) - return 0; - return 1; -} - -static inline -int dma_set_mask(struct device *dev, u64 mask) -{ - if (!dev->dma_mask || !dma_supported(dev, mask)) - return -EIO; - - *dev->dma_mask = mask; - return 0; -} - -static inline -int dma_get_cache_alignment(void) -{ - return 1 << L1_CACHE_SHIFT; -} - -#define dma_is_consistent(d) (1) - -static inline -void dma_cache_sync(void *vaddr, size_t size, - enum dma_data_direction direction) -{ - mn10300_dcache_flush_inv(); -} - -#endif +/* DMA mapping routines for the MN10300 arch + * + * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#ifndef _ASM_DMA_MAPPING_H +#define _ASM_DMA_MAPPING_H + +#include <linux/mm.h> +#include <asm/cache.h> +#include <asm/io.h> +static inline int +dma_coherent_dev(struct device *dev) +{ + return 0; +} + +static inline void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + mn10300_dcache_flush_inv(); +} + +#include <asm-generic/dma-mapping-linear.h> + +#endif diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h dissimilarity index 87% index ea9d4f4..6b0361c 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -1,219 +1,39 @@ -#ifndef __ASM_SH_DMA_MAPPING_H -#define __ASM_SH_DMA_MAPPING_H - -#include <linux/mm.h> -#include <linux/scatterlist.h> -#include <linux/dma-debug.h> -#include <asm/cacheflush.h> -#include <asm/io.h> -#include <asm-generic/dma-coherent.h> - -extern struct bus_type pci_bus_type; - -#define dma_supported(dev, mask) (1) - -static inline int dma_set_mask(struct device *dev, u64 mask) -{ - if (!dev->dma_mask || !dma_supported(dev, mask)) - return -EIO; - - *dev->dma_mask = mask; - - return 0; -} - -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); - -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir); - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d, h) (1) - -static inline dma_addr_t dma_map_single(struct device *dev, - void *ptr, size_t size, - enum dma_data_direction dir) -{ - dma_addr_t addr = virt_to_phys(ptr); - -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return addr; -#endif - dma_cache_sync(dev, ptr, size, dir); - - debug_dma_map_page(dev, virt_to_page(ptr), - (unsigned long)ptr & ~PAGE_MASK, size, - dir, addr, true); - - return addr; -} - -static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, - size_t size, enum dma_data_direction dir) -{ - debug_dma_unmap_page(dev, addr, size, dir, true); -} - -static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); -#endif - sg[i].dma_address = sg_phys(&sg[i]); - sg[i].dma_length = sg[i].length; - } - - debug_dma_map_sg(dev, sg, nents, i, dir); - - return nents; -} - -static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir) -{ - debug_dma_unmap_sg(dev, sg, nents, dir); -} - -static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ - return dma_map_single(dev, page_address(page) + offset, size, dir); -} - -static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, - size_t size, enum dma_data_direction dir) -{ - dma_unmap_single(dev, dma_address, size, dir); -} - -static inline void dma_sync_single(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle), size, dir); -} - -static inline void dma_sync_single_range(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle) + offset, size, dir); -} - -static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nelems; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); -#endif - sg[i].dma_address = sg_phys(&sg[i]); - sg[i].dma_length = sg[i].length; - } -} - -static inline void dma_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); - debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir); -} - -static inline void dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, - size_t size, - enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); - debug_dma_sync_single_for_device(dev, dma_handle, size, dir); -} - -static inline void dma_sync_single_range_for_cpu(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); - debug_dma_sync_single_range_for_cpu(dev, dma_handle, - offset, size, direction); -} - -static inline void dma_sync_single_range_for_device(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, - size_t size, - enum dma_data_direction direction) -{ - dma_sync_single_for_device(dev, dma_handle+offset, size, direction); - debug_dma_sync_single_range_for_device(dev, dma_handle, - offset, size, direction); -} - - -static inline void dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); - debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir); -} - -static inline void dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); - debug_dma_sync_sg_for_device(dev, sg, nelems, dir); -} - -static inline int dma_get_cache_alignment(void) -{ - /* - * Each processor family will define its own L1_CACHE_SHIFT, - * L1_CACHE_BYTES wraps to this, so this is always safe. - */ - return L1_CACHE_BYTES; -} - -static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return dma_addr == 0; -} - -#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY - -extern int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, - dma_addr_t device_addr, size_t size, int flags); - -extern void -dma_release_declared_memory(struct device *dev); - -extern void * -dma_mark_declared_memory_occupied(struct device *dev, - dma_addr_t device_addr, size_t size); - -#endif /* __ASM_SH_DMA_MAPPING_H */ +#ifndef __ASM_SH_DMA_MAPPING_H +#define __ASM_SH_DMA_MAPPING_H + +#include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/dma-debug.h> +#include <asm/cacheflush.h> +#include <asm/io.h> +#include <asm-generic/dma-coherent.h> + +static inline int dma_coherent_dev(struct device *dev) +{ +#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) + if (dev->bus == &pci_bus_type) + return 1; +#endif + return 0; +} + +extern void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction); + +#include <asm-generic/dma-mapping-linear.h> + +extern void +dma_release_declared_memory(struct device *dev); + +extern void * +dma_mark_declared_memory_occupied(struct device *dev, + dma_addr_t device_addr, size_t size); + +#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY + +extern int +dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, + dma_addr_t device_addr, size_t size, int flags); + +#endif /* __ASM_SH_DMA_MAPPING_H */ diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h dissimilarity index 82% index 51882ae..4134617 100644 --- a/arch/xtensa/include/asm/dma-mapping.h +++ b/arch/xtensa/include/asm/dma-mapping.h @@ -1,179 +1,41 @@ -/* - * include/asm-xtensa/dma-mapping.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2003 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_DMA_MAPPING_H -#define _XTENSA_DMA_MAPPING_H - -#include <asm/cache.h> -#include <asm/io.h> -#include <linux/mm.h> -#include <linux/scatterlist.h> - -/* - * DMA-consistent mapping functions. - */ - -extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long); -extern void consistent_free(void*, size_t, dma_addr_t); -extern void consistent_sync(void*, size_t, int); - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) - -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag); - -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle); - -static inline dma_addr_t -dma_map_single(struct device *dev, void *ptr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - consistent_sync(ptr, size, direction); - return virt_to_phys(ptr); -} - -static inline void -dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -static inline int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction direction) -{ - int i; - - BUG_ON(direction == DMA_NONE); - - for (i = 0; i < nents; i++, sg++ ) { - BUG_ON(!sg_page(sg)); - - sg->dma_address = sg_phys(sg); - consistent_sync(sg_virt(sg), sg->length, direction); - } - - return nents; -} - -static inline dma_addr_t -dma_map_page(struct device *dev, struct page *page, unsigned long offset, - size_t size, enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); - return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset; -} - -static inline void -dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - - -static inline void -dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, - enum dma_data_direction direction) -{ - BUG_ON(direction == DMA_NONE); -} - -static inline void -dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, - enum dma_data_direction direction) -{ - consistent_sync((void *)bus_to_virt(dma_handle), size, direction); -} - -static inline void -dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, - enum dma_data_direction direction) -{ - consistent_sync((void *)bus_to_virt(dma_handle), size, direction); -} - -static inline void -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - - consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction); -} - -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - - consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction); -} -static inline void -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - int i; - for (i = 0; i < nelems; i++, sg++) - consistent_sync(sg_virt(sg), sg->length, dir); -} - -static inline void -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - int i; - for (i = 0; i < nelems; i++, sg++) - consistent_sync(sg_virt(sg), sg->length, dir); -} -static inline int -dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -{ - return 0; -} - -static inline int -dma_supported(struct device *dev, u64 mask) -{ - return 1; -} - -static inline int -dma_set_mask(struct device *dev, u64 mask) -{ - if(!dev->dma_mask || !dma_supported(dev, mask)) - return -EIO; - - *dev->dma_mask = mask; - - return 0; -} - -static inline int -dma_get_cache_alignment(void) -{ - return L1_CACHE_BYTES; -} - -#define dma_is_consistent(d, h) (1) - -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ - consistent_sync(vaddr, size, direction); -} - -#endif /* _XTENSA_DMA_MAPPING_H */ +/* + * include/asm-xtensa/dma-mapping.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 - 2005 Tensilica Inc. + */ + +#ifndef _XTENSA_DMA_MAPPING_H +#define _XTENSA_DMA_MAPPING_H + +#include <asm/cache.h> +#include <asm/io.h> +#include <linux/mm.h> + +/* + * DMA-consistent mapping functions. + */ + +extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long); +extern void consistent_free(void*, size_t, dma_addr_t); +extern void consistent_sync(void*, size_t, int); + +static inline int +dma_coherent_dev(struct device *dev) +{ + return 0; +} + +static inline void +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + consistent_sync(cpu_addr, size, direction); +} + +#include <asm-generic/dma-mapping-linear.h> + +#endif /* _XTENSA_DMA_MAPPING_H */ ^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-19 16:22 ` Arnd Bergmann @ 2009-05-19 17:01 ` Grant Grundler 2009-05-19 17:40 ` Arnd Bergmann 2009-05-22 12:12 ` FUJITA Tomonori 1 sibling, 1 reply; 39+ messages in thread From: Grant Grundler @ 2009-05-19 17:01 UTC (permalink / raw) To: Arnd Bergmann Cc: FUJITA Tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Tue, May 19, 2009 at 9:22 AM, Arnd Bergmann <arnd@arndb.de> wrote: > On Tuesday 19 May 2009, FUJITA Tomonori wrote: >> > Would you agree to a patch that works with the same >> > code on e.g. arm, microblaze, mn10300 and sh and >> > uses only a few #ifdefs? >> >> Having such helper for a linear mapping might be helpful but your >> approach is wrong. > > Do you like this approach better? I've merged a few architectures > that were relatively simple. This file should be usable by all > architectures that have a linear mapping and are either fully coherent > (like cris) or just require flushing the dcache when passing a > buffer to the device. I've reviewed the first bit and it looks fine (so far to me). Two related bugs: 1) dma_alloc_coherent() is not respecting the coherent_dma_mask field in device.h:struct device. 2) dma_map_single() is not respecting dma_mask in struct pci_dev (and pointer from struct device). ... > +/** > + * dma_alloc_coherent - allocate consistent memory for DMA > + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices > + * @size: required memory size > + * @handle: bus-specific DMA address > + * > + * Allocate some uncached, unbuffered memory for a device for > + * performing DMA. This function allocates pages, and will > + * return the CPU-viewed address, and sets @handle to be the > + * device-viewed address. Key here is the DMA is coherent, bi-directional, and the DMA address fit in the coherent_dma_mask. "uncached/unbuffered" is one way of doing this and is how we've implemented "DMA coherency" on parisc platforms that don't have an IOMMU (which all have PA1.1 CPUs) - see arch/parisc/kernel/pci-dma.c And I'll confess pci-dma.c doesn't implement support for coherent_dma_mask . AFAIK, the targeted platforms have < 4GB of RAM and only PCI devices. ISA support is completely missing and is the only case this class of machines need coherent_dma_mask support. More comments on how DMA works for PARISC in arch/parisc/include/asm/dma-mapping.h hth, grant ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-19 17:01 ` Grant Grundler @ 2009-05-19 17:40 ` Arnd Bergmann 2009-05-19 18:08 ` Grant Grundler 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-19 17:40 UTC (permalink / raw) To: Grant Grundler Cc: FUJITA Tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Tuesday 19 May 2009 17:01:27 Grant Grundler wrote: > On Tue, May 19, 2009 at 9:22 AM, Arnd Bergmann <arnd@arndb.de> wrote: > I've reviewed the first bit and it looks fine (so far to me). > Two related bugs: > 1) dma_alloc_coherent() is not respecting the coherent_dma_mask field > in device.h:struct device. Hmm, I've taken that function unchanged from powerpc. I guess that means that powerpc is broken here as well, right? > 2) dma_map_single() is not respecting dma_mask in struct pci_dev (and > pointer from struct device). What should it do with the mask? All the architectures I've looked at as well as arch/parisc/kernel/pci-dma.c ignore it. Should dma_map_* just fail in case of an address exceeding dma_mask? > > +/** > > + * dma_alloc_coherent - allocate consistent memory for DMA > > + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices > > + * @size: required memory size > > + * @handle: bus-specific DMA address > > + * > > + * Allocate some uncached, unbuffered memory for a device for > > + * performing DMA. This function allocates pages, and will > > + * return the CPU-viewed address, and sets @handle to be the > > + * device-viewed address. > > Key here is the DMA is coherent, bi-directional, and the DMA address fit in > the coherent_dma_mask. "uncached/unbuffered" is one way of doing this and > is how we've implemented "DMA coherency" on parisc platforms that don't > have an IOMMU (which all have PA1.1 CPUs) - see arch/parisc/kernel/pci-dma.c All the architectures I've looked at come with their own version of _alloc_coherent that works in similar ways to allocate an uncached mapping. Now that you mention this, I realize that there is a bug on cris, which after my patch either has two conflicting implementations of dma_{alloc,free}_coherent, or is missing the dma_coherent_dev() function that is hidden inside of the same #ifdef. The one in arch/cris/arch-v32/drivers/pci/dma.c does seem to be correct though. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-19 17:40 ` Arnd Bergmann @ 2009-05-19 18:08 ` Grant Grundler 0 siblings, 0 replies; 39+ messages in thread From: Grant Grundler @ 2009-05-19 18:08 UTC (permalink / raw) To: Arnd Bergmann Cc: FUJITA Tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Tue, May 19, 2009 at 10:40 AM, Arnd Bergmann <arnd@arndb.de> wrote: > On Tuesday 19 May 2009 17:01:27 Grant Grundler wrote: >> On Tue, May 19, 2009 at 9:22 AM, Arnd Bergmann <arnd@arndb.de> wrote: >> I've reviewed the first bit and it looks fine (so far to me). >> Two related bugs: >> 1) dma_alloc_coherent() is not respecting the coherent_dma_mask field >> in device.h:struct device. > > Hmm, I've taken that function unchanged from powerpc. I guess that means > that powerpc is broken here as well, right? Not necessarily. It might work fine for the subset of machines that use that code. But generic code should use the masks - even if they are set to ~0UL. >> 2) dma_map_single() is not respecting dma_mask in struct pci_dev (and >> pointer from struct device). > > What should it do with the mask? Verify or enforce that the physical memory is allocated from a memory pool suitable for use by that device. If any bits "stick out" from the address (vs the mask), the device won't be able to DMA to that address and very likely truncate the address. By default the PCI dma_mask is 32-bits. Drivers that can support more than 32-bits (some PCI, most PCI-X and all PCI-E devices) will be calling pci_set_dma_mask() and pci_set_coherent_dma_mask() or the equivalent DMA API call. > All the architectures I've looked > at as well as arch/parisc/kernel/pci-dma.c ignore it. pci-dma.c ignores it for the same reason it ignores coherent_dma_mask. None of those parisc machines have host memory at a physical address that is NOT reachable via DMA by *all* known/supported devices. Maybe it's ok and we just need a comment stating the constraints of the generic code. And there must be some way (e.g. dma_support()) to verify the highest physical memory location is reachable by the given device. So that would be another way to enforce the mask. > Should dma_map_* just fail in case of an address exceeding dma_mask? That would probably be correct behavior too. But my gut feeling is we don't want the device driver module to load unless we know the device can DMA to any possible host memory location handed to dma_map_single(). My preference is the initialization path fail first. dma_alloc_coherent() is generally in the initialization path after the drivers call pci_set*mask(). > >> > +/** >> > + * dma_alloc_coherent - allocate consistent memory for DMA >> > + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices >> > + * @size: required memory size >> > + * @handle: bus-specific DMA address >> > + * >> > + * Allocate some uncached, unbuffered memory for a device for >> > + * performing DMA. This function allocates pages, and will >> > + * return the CPU-viewed address, and sets @handle to be the >> > + * device-viewed address. >> >> Key here is the DMA is coherent, bi-directional, and the DMA address fit in >> the coherent_dma_mask. "uncached/unbuffered" is one way of doing this and >> is how we've implemented "DMA coherency" on parisc platforms that don't >> have an IOMMU (which all have PA1.1 CPUs) - see arch/parisc/kernel/pci-dma.c > > All the architectures I've looked at come with their own version of _alloc_coherent > that works in similar ways to allocate an uncached mapping. That's what I expected. I'm pretty sure parisc could use a generic implementation for PA7100LC and PA7300LC CPUs (other parisc CPUs/memory controllers don't support uncached mappings to host memory). So we would need run-time detection and set dma_ops appropriately. > Now that you > mention this, I realize that there is a bug on cris, which after my patch either > has two conflicting implementations of dma_{alloc,free}_coherent, or > is missing the dma_coherent_dev() function that is hidden inside of the > same #ifdef. The one in arch/cris/arch-v32/drivers/pci/dma.c does seem > to be correct though. Ok - cool! thanks, grant -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-19 16:22 ` Arnd Bergmann 2009-05-19 17:01 ` Grant Grundler @ 2009-05-22 12:12 ` FUJITA Tomonori 2009-05-22 14:07 ` Arnd Bergmann 1 sibling, 1 reply; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-22 12:12 UTC (permalink / raw) To: arnd Cc: fujita.tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Tue, 19 May 2009 18:22:47 +0200 Arnd Bergmann <arnd@arndb.de> wrote: > On Tuesday 19 May 2009, FUJITA Tomonori wrote: > > > Would you agree to a patch that works with the same > > > code on e.g. arm, microblaze, mn10300 and sh and > > > uses only a few #ifdefs? > > > > Having such helper for a linear mapping might be helpful but your > > approach is wrong. > > Do you like this approach better? I've merged a few architectures > that were relatively simple. This file should be usable by all > architectures that have a linear mapping and are either fully coherent > (like cris) or just require flushing the dcache when passing a > buffer to the device. > > It's become pretty obvious where some of my bugs were in the previous > code, I hopefully did better this time and maybe you find the rest. > I've also added the dma debugging stuff in here and fixed a number > of bugs in all the different architectures on the way, but I can > send separate patches for those before doing the merge. > > I've also tried merging frv and m68k, but they have some peculiarities > that made it slightly harder. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > > include/asm-generic/dma-mapping-linear.h | 391 +++++++++++++++++++++++++++++ > arch/avr32/include/asm/dma-mapping.h | 408 ++++--------------------------- > arch/blackfin/include/asm/dma-mapping.h | 118 +------- > arch/cris/include/asm/dma-mapping.h | 194 +------------- > arch/mn10300/include/asm/dma-mapping.h | 266 ++------------------ > arch/sh/include/asm/dma-mapping.h | 258 ++----------------- > arch/xtensa/include/asm/dma-mapping.h | 220 +++------------- > 7 files changed, 606 insertions(+), 1249 deletions(-) > > diff --git a/include/asm-generic/dma-mapping-linear.h b/include/asm-generic/dma-mapping-linear.h > new file mode 100644 > index 0000000..13f37db > --- /dev/null > +++ b/include/asm-generic/dma-mapping-linear.h > @@ -0,0 +1,391 @@ > +#ifndef __ASM_GENERIC_DMA_MAPPING_H > +#define __ASM_GENERIC_DMA_MAPPING_H > + > +#include <linux/mm.h> > +#include <linux/device.h> > +#include <linux/dma-debug.h> > +#include <linux/scatterlist.h> > +#include <asm/cacheflush.h> > +#include <asm/io.h> > + > +#ifdef CONFIG_DMA_COHERENT > +/* > + * An architecture should override these if it needs to > + * perform cache flushes before passing bus addresses > + * to a device. > + * It can either do a full flush in dma_coherent_dev > + * and return 1 from there, or implement more specific > + * synchronization in dma_cache_sync, which will be > + * applied separately to each sg element. > + */ > +static inline int > +dma_coherent_dev(struct device *dev) > +{ > + return 1; > +} > + > +static inline void > +dma_cache_sync(struct device *dev, void *cpu_addr, size_t size, > + enum dma_data_direction direction) > +{ > +} > + > +/** > + * dma_alloc_coherent - allocate consistent memory for DMA > + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices > + * @size: required memory size > + * @handle: bus-specific DMA address > + * > + * Allocate some uncached, unbuffered memory for a device for > + * performing DMA. This function allocates pages, and will > + * return the CPU-viewed address, and sets @handle to be the > + * device-viewed address. > + */ > +void *dma_alloc_coherent(struct device *dev, size_t size, > + dma_addr_t *dma_handle, gfp_t flag) > +{ > + void *ret; > + struct page *page; > + int node = dev_to_node(dev); > + > + /* ignore region specifiers */ > + flag &= ~(__GFP_HIGHMEM); > + > + page = alloc_pages_node(node, flag, get_order(size)); > + if (page == NULL) > + return NULL; > + ret = page_address(page); > + memset(ret, 0, size); > + *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); > + > + return ret; > +} I don't think that this works for all architectures because a returned buffer of alloc_pages_node might not be DMA-capable. Needs to use the coherent_dma_mask here. See x86's dma_alloc_coherent and Alpha's pci-noop.c (there might be other examples). I think that having a generic header for simple mapping functions (dma_map_single, dma_map_page, dma_map_sg, etc) would be useful but I'm not sure if we can't have a generic version of dma_alloc_coherent. There are lots of architectures that do architecture-specific things. For example, you replaced avr32 dma-mapping.h except for dma_alloc_coherent, which seems to be can't be generic. BTW, it looks odd to add dma_debug to dma_map_single, etc but not dma_alloc_coherent. ;) ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-22 12:12 ` FUJITA Tomonori @ 2009-05-22 14:07 ` Arnd Bergmann 2009-05-22 14:38 ` FUJITA Tomonori 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-22 14:07 UTC (permalink / raw) To: FUJITA Tomonori Cc: jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato, Grant Grundler On Friday 22 May 2009, FUJITA Tomonori wrote: > I don't think that this works for all architectures because a returned > buffer of alloc_pages_node might not be DMA-capable. Needs to use the > coherent_dma_mask here. See x86's dma_alloc_coherent and Alpha's > pci-noop.c (there might be other examples). Right, Grant also made the same comment. > I think that having a generic header for simple mapping functions > (dma_map_single, dma_map_page, dma_map_sg, etc) would be useful but > I'm not sure if we can't have a generic version of > dma_alloc_coherent. > > There are lots of architectures that do > architecture-specific things. For example, you replaced avr32 > dma-mapping.h except for dma_alloc_coherent, which seems to be can't > be generic. I agree that it won't be fully generic, because all architectures with non-coherent DMA will have to do architecture specific setup to get uncached mappings here. I believe that it can be generic enough to support all architectures that have a cache-coherent PCI bus, hence the #ifdef CONFIG_DMA_COHERENT around this function. E.g. cris could use a one-line redirect to asm-generic/dma-mapping-linear.h if it did not have the special dma_get_cache_alignment function. I still would like to find a better way to handle this one than to redefine the function. > BTW, it looks odd to add dma_debug to dma_map_single, etc but not > dma_alloc_coherent. ;) hehe, sure. I copied the dma_debug stuff from sh, the comments from avr32 and the dma_alloc_coherent implementation from powerpc, so I missed this one. Thanks for the review. Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-22 14:07 ` Arnd Bergmann @ 2009-05-22 14:38 ` FUJITA Tomonori 2009-05-22 15:05 ` Arnd Bergmann 0 siblings, 1 reply; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-22 14:38 UTC (permalink / raw) To: arnd Cc: fujita.tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato, grundler On Fri, 22 May 2009 16:07:32 +0200 Arnd Bergmann <arnd@arndb.de> wrote: > On Friday 22 May 2009, FUJITA Tomonori wrote: > > I don't think that this works for all architectures because a returned > > buffer of alloc_pages_node might not be DMA-capable. Needs to use the > > coherent_dma_mask here. See x86's dma_alloc_coherent and Alpha's > > pci-noop.c (there might be other examples). > > Right, Grant also made the same comment. > > > I think that having a generic header for simple mapping functions > > (dma_map_single, dma_map_page, dma_map_sg, etc) would be useful but > > I'm not sure if we can't have a generic version of > > dma_alloc_coherent. > > > > There are lots of architectures that do > > architecture-specific things. For example, you replaced avr32 > > dma-mapping.h except for dma_alloc_coherent, which seems to be can't > > be generic. > > I agree that it won't be fully generic, because all architectures > with non-coherent DMA will have to do architecture specific setup > to get uncached mappings here. I believe that it can be generic > enough to support all architectures that have a cache-coherent PCI > bus, hence the #ifdef CONFIG_DMA_COHERENT around this function. I'm not sure. And only mips internally uses CONFIG_DMA_COHERENT. The reason why many architectures need architecture-specific alloc_coherent() is not about coherent or not. I like a new helper header file having only generic functions without any ifdef. > E.g. cris could use a one-line redirect to > asm-generic/dma-mapping-linear.h if it did not have the > special dma_get_cache_alignment function. I still would > like to find a better way to handle this one than to > redefine the function. > > > BTW, it looks odd to add dma_debug to dma_map_single, etc but not > > dma_alloc_coherent. ;) > > hehe, sure. I copied the dma_debug stuff from sh, the comments > from avr32 and the dma_alloc_coherent implementation from powerpc, > so I missed this one. > > Thanks for the review. > > Arnd <>< > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-22 14:38 ` FUJITA Tomonori @ 2009-05-22 15:05 ` Arnd Bergmann 2009-05-26 4:36 ` FUJITA Tomonori 0 siblings, 1 reply; 39+ messages in thread From: Arnd Bergmann @ 2009-05-22 15:05 UTC (permalink / raw) To: FUJITA Tomonori Cc: jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato, grundler On Friday 22 May 2009, FUJITA Tomonori wrote: > I'm not sure. And only mips internally uses CONFIG_DMA_COHERENT. > > The reason why many architectures need architecture-specific > alloc_coherent() is not about coherent or not. > > I like a new helper header file having only generic functions without > any ifdef. Ok, fair enough. Fixing dma_alloc_coherent to handle coherent_dma_mask and debug_dma correctly would also make it even bigger, and it was already doing more than you'd want from a commonly used inline function. It may be useful to put it into kernel/dma-coherent.c under an #ifdef, but I'll leave this one alone for now. I'll leave dma_alloc_coherent and dma_free_coherent as extern declarations then, and leave out the simple dma_coherent_dev() and dma_cache_sync() that all architectures would need to override. dma_get_cache_alignment() is still less generic than the other functions, as this is still architecture specific. Should I leave that out as well then? One more idea I had was to rename all the functions in this file from dma_* to dma_linear_*. This would mean that all architectures using it would still need to do something like #define dma_map_sg dma_linear_map_sg for each function they want to use but can easily chose to provide their own ones for those they need different. It might also help architectures that work with dma_ops, which could then define their own struct dma_ops dma_ops_linear = { .map_single = dma_linear_map_single, .map_sg = dma_linear_map_sg, ... }; Would you prefer me to do it this way, or just keep the standard function names as in the current patch? Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-22 15:05 ` Arnd Bergmann @ 2009-05-26 4:36 ` FUJITA Tomonori 0 siblings, 0 replies; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-26 4:36 UTC (permalink / raw) To: arnd Cc: fujita.tomonori, jgarzik, hancockrwd, htejun, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato, grundler On Fri, 22 May 2009 17:05:53 +0200 Arnd Bergmann <arnd@arndb.de> wrote: > On Friday 22 May 2009, FUJITA Tomonori wrote: > > I'm not sure. And only mips internally uses CONFIG_DMA_COHERENT. > > > > The reason why many architectures need architecture-specific > > alloc_coherent() is not about coherent or not. > > > > I like a new helper header file having only generic functions without > > any ifdef. > > Ok, fair enough. Fixing dma_alloc_coherent to handle > coherent_dma_mask and debug_dma correctly would also > make it even bigger, and it was already doing more than > you'd want from a commonly used inline function. > It may be useful to put it into kernel/dma-coherent.c > under an #ifdef, but I'll leave this one alone for now. Adding #ifdef into kernel/dma-coherent.c is ugly. > I'll leave dma_alloc_coherent and dma_free_coherent > as extern declarations then, and leave out the > simple dma_coherent_dev() and dma_cache_sync() that > all architectures would need to override. Right, needs to leave the functions that architectures need to override. > dma_get_cache_alignment() is still less generic than > the other functions, as this is still architecture > specific. Should I leave that out as well then? Yes, I think that only adding generic functions is a better approach. Overriding with #ifdef is really ugly. > One more idea I had was to rename all the functions in > this file from dma_* to dma_linear_*. This would mean > that all architectures using it would still need to > do something like #define dma_map_sg dma_linear_map_sg > for each function they want to use but can easily chose > to provide their own ones for those they need different. > > It might also help architectures that work with dma_ops, > which could then define their own > struct dma_ops dma_ops_linear = { > .map_single = dma_linear_map_single, > .map_sg = dma_linear_map_sg, > ... > }; To me, looks like this just makes things complicated needlessly. But I'm not in a position to ACK or NACK this. it's better to ask architecture maintainers. > Would you prefer me to do it this way, or just keep the > standard function names as in the current patch? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-17 22:45 ` [PATCH] asm-generic: add a dma-mapping.h file Arnd Bergmann 2009-05-18 6:03 ` Geert Uytterhoeven 2009-05-18 10:45 ` FUJITA Tomonori @ 2009-05-18 22:54 ` Jeff Garzik 2009-05-18 23:22 ` FUJITA Tomonori 2 siblings, 1 reply; 39+ messages in thread From: Jeff Garzik @ 2009-05-18 22:54 UTC (permalink / raw) To: Arnd Bergmann Cc: Robert Hancock, Tejun Heo, FUJITA Tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato Arnd Bergmann wrote: > h8300 and m32r currently do not provide a DMA mapping API > and therefore cannot use the ATA drivers. This adds a > generic version of dma-mapping.h for architectures that > have none or very minimal actual support for DMA in hardware > and makes the two architectures use it. > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > On Sunday 17 May 2009 20:05:54 Jeff Garzik wrote: > >> That's what needs to happen. We provide no-op functions for e.g. PCI >> and x86 DMI, for platforms where this support does not exist. >> >> Pretty much all architectures support some form of ATA. m68k, m32r, >> h8300 and microblaze all have IDE interface, which means that libata >> needs to work on that platform. >> >> The only !ATA arch in the entire kernel is s390, AFAICT. > > m68k only defines NO_DMA for Sun3 and Dragonball. Sun3 does > not have ATA, Dragonball could probably just enable HAS_DMA. > > --- > arch/h8300/Kconfig | 2 +- > arch/h8300/include/asm/dma-mapping.h | 1 + > arch/m32r/Kconfig | 2 +- > arch/m32r/include/asm/dma-mapping.h | 1 + > include/asm-generic/dma-mapping.h | 399 ++++++++++++++++++++++++++++++++++ > 5 files changed, 403 insertions(+), 2 deletions(-) > create mode 100644 arch/h8300/include/asm/dma-mapping.h > create mode 100644 arch/m32r/include/asm/dma-mapping.h > create mode 100644 include/asm-generic/dma-mapping.h My main comment is a bit non-specific... I tend to think that all no-dma platforms should provide an API whose implementation always returns errors, e.g. an inlined version of dma-mapping-broken.h. That sort of setup permits the compiler's dead code elimination to work on these no-dma platforms, while not crapping up the libata code with a bunch of ifdefs. Jeff ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] asm-generic: add a dma-mapping.h file 2009-05-18 22:54 ` Jeff Garzik @ 2009-05-18 23:22 ` FUJITA Tomonori 0 siblings, 0 replies; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-18 23:22 UTC (permalink / raw) To: jgarzik Cc: arnd, hancockrwd, htejun, fujita.tomonori, alan, flar, schmitz, linux-kernel, linux-ide, takata, geert, linux-m68k, ysato On Mon, 18 May 2009 18:54:49 -0400 Jeff Garzik <jgarzik@pobox.com> wrote: > Arnd Bergmann wrote: > > h8300 and m32r currently do not provide a DMA mapping API > > and therefore cannot use the ATA drivers. This adds a > > generic version of dma-mapping.h for architectures that > > have none or very minimal actual support for DMA in hardware > > and makes the two architectures use it. > > > > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > > --- > > On Sunday 17 May 2009 20:05:54 Jeff Garzik wrote: > > > >> That's what needs to happen. We provide no-op functions for e.g. PCI > >> and x86 DMI, for platforms where this support does not exist. > >> > >> Pretty much all architectures support some form of ATA. m68k, m32r, > >> h8300 and microblaze all have IDE interface, which means that libata > >> needs to work on that platform. > >> > >> The only !ATA arch in the entire kernel is s390, AFAICT. > > > > m68k only defines NO_DMA for Sun3 and Dragonball. Sun3 does > > not have ATA, Dragonball could probably just enable HAS_DMA. > > > > --- > > arch/h8300/Kconfig | 2 +- > > arch/h8300/include/asm/dma-mapping.h | 1 + > > arch/m32r/Kconfig | 2 +- > > arch/m32r/include/asm/dma-mapping.h | 1 + > > include/asm-generic/dma-mapping.h | 399 ++++++++++++++++++++++++++++++++++ > > 5 files changed, 403 insertions(+), 2 deletions(-) > > create mode 100644 arch/h8300/include/asm/dma-mapping.h > > create mode 100644 arch/m32r/include/asm/dma-mapping.h > > create mode 100644 include/asm-generic/dma-mapping.h > > My main comment is a bit non-specific... I tend to think that all > no-dma platforms should provide an API whose implementation always > returns errors, e.g. an inlined version of dma-mapping-broken.h. > > That sort of setup permits the compiler's dead code elimination to work > on these no-dma platforms, while not crapping up the libata code with a > bunch of ifdefs. Just adding one ifdef to libata.h works? What libata needs is just wrapping dma_map_sg and dma_unmap_sg like the old ide stack does. I'm not against the idea of an inlined version of dma-mapping-broken.h but having two ways to handle this issue is a bit confusing; so far what we done to handle this problem is using NO_DMA, like SCSI-ml does, not putting the dma code in non-architecture code and having something like scsi_lib_dma.c. Is it theoretically correct that the dma mapping API lives in low level drivers instead of libata-core (like how SCSI-ml does)? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-15 11:16 ` Arnd Bergmann 2009-05-15 11:21 ` Tejun Heo @ 2009-05-18 10:45 ` FUJITA Tomonori 1 sibling, 0 replies; 39+ messages in thread From: FUJITA Tomonori @ 2009-05-18 10:45 UTC (permalink / raw) To: arnd Cc: htejun, fujita.tomonori, hancockrwd, alan, flar, schmitz, linux-kernel, jgarzik, linux-ide, takata, geert, linux-m68k, ysato On Fri, 15 May 2009 13:16:30 +0200 Arnd Bergmann <arnd@arndb.de> wrote: > On Friday 15 May 2009, Tejun Heo wrote: > > FUJITA Tomonori wrote: > > > Can libata call dma_supported() per device to decide DMA or PIO mode? > > > Then, we can solve this problem by add dummy DMA API (just calls BUG) > > > on such architectures, without Kconfig magic or adding ifdef (like the > > > old ide stack does), I think. > > That would be the !CONFIG_PCI half of the old > include/asm-generic/dma-mapping.h file that you just removed, > right? No. The old include/asm-generic/dma-mapping.h is a workaround for lazy architecture maintainers who have not converted pci_* API to dma_* API. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [PATCH] ata: libata depends on HAS_DMA 2009-05-13 3:30 ` Brad Boyer 2009-05-13 4:12 ` Michael Schmitz @ 2009-05-13 10:39 ` Arnd Bergmann 1 sibling, 0 replies; 39+ messages in thread From: Arnd Bergmann @ 2009-05-13 10:39 UTC (permalink / raw) To: Brad Boyer Cc: Alan Cox, linux-kernel, Jeff Garzik, linux-ide, takata, geert, linux-m68k, ysato On Wednesday 13 May 2009, Brad Boyer wrote: > If I'm reading the m68k code correctly, SUN3 is the one that doesn't have > DMA. It is implemented on any m68k with a standard Motorola MMU. It might > be possible to get the DMA code working on a sun3, but I doubt they ever > have IDE hardware. Yes, that's right, I misread the Kconfig logic. In m68nommu, there are also Dragonball and MC68360 that are supported but don't support the DMA API right now. Is that a real limitation, or could those potentially have ATA ports? Arnd <>< ^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2009-05-26 4:36 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20090511222702.352192505@arndb.de>
2009-05-11 22:38 ` [PATCH] ata: libata depends on HAS_DMA Arnd Bergmann
2009-05-12 0:58 ` Jeff Garzik
2009-05-12 12:40 ` Arnd Bergmann
2009-05-12 13:05 ` Arnd Bergmann
2009-05-12 8:06 ` Alan Cox
2009-05-12 9:23 ` Arnd Bergmann
2009-05-13 3:30 ` Brad Boyer
2009-05-13 4:12 ` Michael Schmitz
2009-05-13 4:34 ` Brad Boyer
2009-05-13 8:51 ` Alan Cox
2009-05-13 8:55 ` Geert Uytterhoeven
2009-05-13 23:57 ` Robert Hancock
2009-05-14 0:18 ` FUJITA Tomonori
2009-05-15 5:31 ` Tejun Heo
2009-05-15 11:16 ` Arnd Bergmann
2009-05-15 11:21 ` Tejun Heo
2009-05-15 11:55 ` Arnd Bergmann
2009-05-17 9:00 ` Robert Hancock
2009-05-17 19:38 ` Arnd Bergmann
2009-05-17 20:05 ` Jeff Garzik
2009-05-17 22:45 ` [PATCH] asm-generic: add a dma-mapping.h file Arnd Bergmann
2009-05-18 6:03 ` Geert Uytterhoeven
2009-05-18 8:28 ` Arnd Bergmann
2009-05-18 10:45 ` FUJITA Tomonori
2009-05-18 14:45 ` Arnd Bergmann
2009-05-18 22:44 ` FUJITA Tomonori
2009-05-19 16:22 ` Arnd Bergmann
2009-05-19 17:01 ` Grant Grundler
2009-05-19 17:40 ` Arnd Bergmann
2009-05-19 18:08 ` Grant Grundler
2009-05-22 12:12 ` FUJITA Tomonori
2009-05-22 14:07 ` Arnd Bergmann
2009-05-22 14:38 ` FUJITA Tomonori
2009-05-22 15:05 ` Arnd Bergmann
2009-05-26 4:36 ` FUJITA Tomonori
2009-05-18 22:54 ` Jeff Garzik
2009-05-18 23:22 ` FUJITA Tomonori
2009-05-18 10:45 ` [PATCH] ata: libata depends on HAS_DMA FUJITA Tomonori
2009-05-13 10:39 ` Arnd Bergmann
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).