Message ID | 20220830030139.29899-3-lvjianmin@loongson.cn (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | DMA: update acpi_dma_get_range to return dma map regions | expand |
Hi, Jianmin, The title can be "LoongArch: Use acpi_arch_dma_setup() and remove ARCH_HAS_PHYS_TO_DMA", and please use resource_size() as arm64. Acked-by: Huacai Chen <chenhuacai@loongson.cn> Huacai On Tue, Aug 30, 2022 at 11:01 AM Jianmin Lv <lvjianmin@loongson.cn> wrote: > > Use _DMA defined in ACPI spec for translation between > DMA address and CPU address, and implement acpi_arch_dma_setup > for initializing dev->dma_range_map, where acpi_dma_get_range > is called for parsing _DMA. > > e.g. > If we have two dma ranges: > cpu address dma address size offset > 0x200080000000 0x2080000000 0x400000000 0x1fe000000000 > 0x400080000000 0x4080000000 0x400000000 0x3fc000000000 > > _DMA for pci devices should be declared in host bridge as > flowing: > > Name (_DMA, ResourceTemplate() { > QWordMemory (ResourceProducer, > PosDecode, > MinFixed, > MaxFixed, > NonCacheable, > ReadWrite, > 0x0, > 0x4080000000, > 0x447fffffff, > 0x3fc000000000, > 0x400000000, > , > , > ) > > QWordMemory (ResourceProducer, > PosDecode, > MinFixed, > MaxFixed, > NonCacheable, > ReadWrite, > 0x0, > 0x2080000000, > 0x247fffffff, > 0x1fe000000000, > 0x400000000, > , > , > ) > }) > > Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn> > --- > arch/loongarch/Kconfig | 1 - > arch/loongarch/kernel/dma.c | 52 +++++++++++++++++-------------------------- > arch/loongarch/kernel/setup.c | 2 +- > include/linux/acpi.h | 9 +++++--- > 4 files changed, 28 insertions(+), 36 deletions(-) > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > index b57daee..9dedcf9 100644 > --- a/arch/loongarch/Kconfig > +++ b/arch/loongarch/Kconfig > @@ -7,7 +7,6 @@ config LOONGARCH > select ARCH_ENABLE_MEMORY_HOTPLUG > select ARCH_ENABLE_MEMORY_HOTREMOVE > select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI > - select ARCH_HAS_PHYS_TO_DMA > select ARCH_HAS_PTE_SPECIAL > select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST > select ARCH_INLINE_READ_LOCK if !PREEMPTION > diff --git a/arch/loongarch/kernel/dma.c b/arch/loongarch/kernel/dma.c > index 8c9b531..7a9c6a9 100644 > --- a/arch/loongarch/kernel/dma.c > +++ b/arch/loongarch/kernel/dma.c > @@ -2,39 +2,29 @@ > /* > * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > */ > -#include <linux/init.h> > +#include <linux/acpi.h> > #include <linux/dma-direct.h> > -#include <linux/dma-mapping.h> > -#include <linux/dma-map-ops.h> > -#include <linux/swiotlb.h> > > -#include <asm/bootinfo.h> > -#include <asm/dma.h> > -#include <asm/loongson.h> > - > -/* > - * We extract 4bit node id (bit 44~47) from Loongson-3's > - * 48bit physical address space and embed it into 40bit. > - */ > - > -static int node_id_offset; > - > -dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) > -{ > - long nid = (paddr >> 44) & 0xf; > - > - return ((nid << 44) ^ paddr) | (nid << node_id_offset); > -} > - > -phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) > +void acpi_arch_dma_setup(struct device *dev) > { > - long nid = (daddr >> node_id_offset) & 0xf; > + int ret; > + u64 mask, end = 0; > + const struct bus_dma_region *map = NULL; > + > + ret = acpi_dma_get_range(dev, &map); > + if (!ret && map) { > + const struct bus_dma_region *r = map; > + > + for (end = 0; r->size; r++) { > + if (r->dma_start + r->size - 1 > end) > + end = r->dma_start + r->size - 1; > + } > + > + mask = DMA_BIT_MASK(ilog2(end) + 1); > + dev->bus_dma_limit = end; > + dev->dma_range_map = map; > + dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); > + *dev->dma_mask = min(*dev->dma_mask, mask); > + } > > - return ((nid << node_id_offset) ^ daddr) | (nid << 44); > -} > - > -void __init plat_swiotlb_setup(void) > -{ > - swiotlb_init(true, SWIOTLB_VERBOSE); > - node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36; > } > diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c > index c74860b..974f085 100644 > --- a/arch/loongarch/kernel/setup.c > +++ b/arch/loongarch/kernel/setup.c > @@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p) > sparse_init(); > memblock_set_bottom_up(true); > > - plat_swiotlb_setup(); > + swiotlb_init(true, SWIOTLB_VERBOSE); > > dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); > > diff --git a/include/linux/acpi.h b/include/linux/acpi.h > index 34e0545..33977b87 100644 > --- a/include/linux/acpi.h > +++ b/include/linux/acpi.h > @@ -278,14 +278,17 @@ int acpi_table_parse_madt(enum acpi_madt_type id, > > void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); > > +#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) > +void acpi_arch_dma_setup(struct device *dev); > +#else > +static inline void acpi_arch_dma_setup(struct device *dev) { } > +#endif > + > #ifdef CONFIG_ARM64 > void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa); > -void acpi_arch_dma_setup(struct device *dev); > #else > static inline void > acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { } > -static inline void > -acpi_arch_dma_setup(struct device *dev) { } > #endif > > int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); > -- > 1.8.3.1 > >
Hi, Huacai Ok, thanks, I'll change title in V4. There is *not* size calculation in this patch, so the patch does not need resource_size() as in acpi_dma_get_range(). On 2022/9/5 下午10:42, Huacai Chen wrote: > Hi, Jianmin, > > The title can be "LoongArch: Use acpi_arch_dma_setup() and remove > ARCH_HAS_PHYS_TO_DMA", and please use resource_size() as arm64. > > Acked-by: Huacai Chen <chenhuacai@loongson.cn> > > > Huacai > > > On Tue, Aug 30, 2022 at 11:01 AM Jianmin Lv <lvjianmin@loongson.cn> wrote: >> >> Use _DMA defined in ACPI spec for translation between >> DMA address and CPU address, and implement acpi_arch_dma_setup >> for initializing dev->dma_range_map, where acpi_dma_get_range >> is called for parsing _DMA. >> >> e.g. >> If we have two dma ranges: >> cpu address dma address size offset >> 0x200080000000 0x2080000000 0x400000000 0x1fe000000000 >> 0x400080000000 0x4080000000 0x400000000 0x3fc000000000 >> >> _DMA for pci devices should be declared in host bridge as >> flowing: >> >> Name (_DMA, ResourceTemplate() { >> QWordMemory (ResourceProducer, >> PosDecode, >> MinFixed, >> MaxFixed, >> NonCacheable, >> ReadWrite, >> 0x0, >> 0x4080000000, >> 0x447fffffff, >> 0x3fc000000000, >> 0x400000000, >> , >> , >> ) >> >> QWordMemory (ResourceProducer, >> PosDecode, >> MinFixed, >> MaxFixed, >> NonCacheable, >> ReadWrite, >> 0x0, >> 0x2080000000, >> 0x247fffffff, >> 0x1fe000000000, >> 0x400000000, >> , >> , >> ) >> }) >> >> Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn> >> --- >> arch/loongarch/Kconfig | 1 - >> arch/loongarch/kernel/dma.c | 52 +++++++++++++++++-------------------------- >> arch/loongarch/kernel/setup.c | 2 +- >> include/linux/acpi.h | 9 +++++--- >> 4 files changed, 28 insertions(+), 36 deletions(-) >> >> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig >> index b57daee..9dedcf9 100644 >> --- a/arch/loongarch/Kconfig >> +++ b/arch/loongarch/Kconfig >> @@ -7,7 +7,6 @@ config LOONGARCH >> select ARCH_ENABLE_MEMORY_HOTPLUG >> select ARCH_ENABLE_MEMORY_HOTREMOVE >> select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI >> - select ARCH_HAS_PHYS_TO_DMA >> select ARCH_HAS_PTE_SPECIAL >> select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST >> select ARCH_INLINE_READ_LOCK if !PREEMPTION >> diff --git a/arch/loongarch/kernel/dma.c b/arch/loongarch/kernel/dma.c >> index 8c9b531..7a9c6a9 100644 >> --- a/arch/loongarch/kernel/dma.c >> +++ b/arch/loongarch/kernel/dma.c >> @@ -2,39 +2,29 @@ >> /* >> * Copyright (C) 2020-2022 Loongson Technology Corporation Limited >> */ >> -#include <linux/init.h> >> +#include <linux/acpi.h> >> #include <linux/dma-direct.h> >> -#include <linux/dma-mapping.h> >> -#include <linux/dma-map-ops.h> >> -#include <linux/swiotlb.h> >> >> -#include <asm/bootinfo.h> >> -#include <asm/dma.h> >> -#include <asm/loongson.h> >> - >> -/* >> - * We extract 4bit node id (bit 44~47) from Loongson-3's >> - * 48bit physical address space and embed it into 40bit. >> - */ >> - >> -static int node_id_offset; >> - >> -dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) >> -{ >> - long nid = (paddr >> 44) & 0xf; >> - >> - return ((nid << 44) ^ paddr) | (nid << node_id_offset); >> -} >> - >> -phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) >> +void acpi_arch_dma_setup(struct device *dev) >> { >> - long nid = (daddr >> node_id_offset) & 0xf; >> + int ret; >> + u64 mask, end = 0; >> + const struct bus_dma_region *map = NULL; >> + >> + ret = acpi_dma_get_range(dev, &map); >> + if (!ret && map) { >> + const struct bus_dma_region *r = map; >> + >> + for (end = 0; r->size; r++) { >> + if (r->dma_start + r->size - 1 > end) >> + end = r->dma_start + r->size - 1; >> + } >> + >> + mask = DMA_BIT_MASK(ilog2(end) + 1); >> + dev->bus_dma_limit = end; >> + dev->dma_range_map = map; >> + dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); >> + *dev->dma_mask = min(*dev->dma_mask, mask); >> + } >> >> - return ((nid << node_id_offset) ^ daddr) | (nid << 44); >> -} >> - >> -void __init plat_swiotlb_setup(void) >> -{ >> - swiotlb_init(true, SWIOTLB_VERBOSE); >> - node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36; >> } >> diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c >> index c74860b..974f085 100644 >> --- a/arch/loongarch/kernel/setup.c >> +++ b/arch/loongarch/kernel/setup.c >> @@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p) >> sparse_init(); >> memblock_set_bottom_up(true); >> >> - plat_swiotlb_setup(); >> + swiotlb_init(true, SWIOTLB_VERBOSE); >> >> dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); >> >> diff --git a/include/linux/acpi.h b/include/linux/acpi.h >> index 34e0545..33977b87 100644 >> --- a/include/linux/acpi.h >> +++ b/include/linux/acpi.h >> @@ -278,14 +278,17 @@ int acpi_table_parse_madt(enum acpi_madt_type id, >> >> void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); >> >> +#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) >> +void acpi_arch_dma_setup(struct device *dev); >> +#else >> +static inline void acpi_arch_dma_setup(struct device *dev) { } >> +#endif >> + >> #ifdef CONFIG_ARM64 >> void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa); >> -void acpi_arch_dma_setup(struct device *dev); >> #else >> static inline void >> acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { } >> -static inline void >> -acpi_arch_dma_setup(struct device *dev) { } >> #endif >> >> int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); >> -- >> 1.8.3.1 >> >>
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index b57daee..9dedcf9 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -7,7 +7,6 @@ config LOONGARCH select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI - select ARCH_HAS_PHYS_TO_DMA select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_INLINE_READ_LOCK if !PREEMPTION diff --git a/arch/loongarch/kernel/dma.c b/arch/loongarch/kernel/dma.c index 8c9b531..7a9c6a9 100644 --- a/arch/loongarch/kernel/dma.c +++ b/arch/loongarch/kernel/dma.c @@ -2,39 +2,29 @@ /* * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ -#include <linux/init.h> +#include <linux/acpi.h> #include <linux/dma-direct.h> -#include <linux/dma-mapping.h> -#include <linux/dma-map-ops.h> -#include <linux/swiotlb.h> -#include <asm/bootinfo.h> -#include <asm/dma.h> -#include <asm/loongson.h> - -/* - * We extract 4bit node id (bit 44~47) from Loongson-3's - * 48bit physical address space and embed it into 40bit. - */ - -static int node_id_offset; - -dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -{ - long nid = (paddr >> 44) & 0xf; - - return ((nid << 44) ^ paddr) | (nid << node_id_offset); -} - -phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) +void acpi_arch_dma_setup(struct device *dev) { - long nid = (daddr >> node_id_offset) & 0xf; + int ret; + u64 mask, end = 0; + const struct bus_dma_region *map = NULL; + + ret = acpi_dma_get_range(dev, &map); + if (!ret && map) { + const struct bus_dma_region *r = map; + + for (end = 0; r->size; r++) { + if (r->dma_start + r->size - 1 > end) + end = r->dma_start + r->size - 1; + } + + mask = DMA_BIT_MASK(ilog2(end) + 1); + dev->bus_dma_limit = end; + dev->dma_range_map = map; + dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask); + *dev->dma_mask = min(*dev->dma_mask, mask); + } - return ((nid << node_id_offset) ^ daddr) | (nid << 44); -} - -void __init plat_swiotlb_setup(void) -{ - swiotlb_init(true, SWIOTLB_VERBOSE); - node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36; } diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index c74860b..974f085 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p) sparse_init(); memblock_set_bottom_up(true); - plat_swiotlb_setup(); + swiotlb_init(true, SWIOTLB_VERBOSE); dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 34e0545..33977b87 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -278,14 +278,17 @@ int acpi_table_parse_madt(enum acpi_madt_type id, void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); +#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) +void acpi_arch_dma_setup(struct device *dev); +#else +static inline void acpi_arch_dma_setup(struct device *dev) { } +#endif + #ifdef CONFIG_ARM64 void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa); -void acpi_arch_dma_setup(struct device *dev); #else static inline void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { } -static inline void -acpi_arch_dma_setup(struct device *dev) { } #endif int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
Use _DMA defined in ACPI spec for translation between DMA address and CPU address, and implement acpi_arch_dma_setup for initializing dev->dma_range_map, where acpi_dma_get_range is called for parsing _DMA. e.g. If we have two dma ranges: cpu address dma address size offset 0x200080000000 0x2080000000 0x400000000 0x1fe000000000 0x400080000000 0x4080000000 0x400000000 0x3fc000000000 _DMA for pci devices should be declared in host bridge as flowing: Name (_DMA, ResourceTemplate() { QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, 0x0, 0x4080000000, 0x447fffffff, 0x3fc000000000, 0x400000000, , , ) QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, 0x0, 0x2080000000, 0x247fffffff, 0x1fe000000000, 0x400000000, , , ) }) Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn> --- arch/loongarch/Kconfig | 1 - arch/loongarch/kernel/dma.c | 52 +++++++++++++++++-------------------------- arch/loongarch/kernel/setup.c | 2 +- include/linux/acpi.h | 9 +++++--- 4 files changed, 28 insertions(+), 36 deletions(-)