From: Douglas Anderson Date: Mon, 6 Apr 2026 23:23:00 +0000 (-0700) Subject: driver core: Replace dev->dma_coherent with dev_dma_coherent() X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=3e2c1e213ac2bfc9068a2686ef380ee0d8bef949;p=thirdparty%2Fkernel%2Flinux.git driver core: Replace dev->dma_coherent with dev_dma_coherent() In C, bitfields are not necessarily safe to modify from multiple threads without locking. Switch "dma_coherent" over to the "flags" field so modifications are safe. Cc: Christoph Hellwig Reviewed-by: Rafael J. Wysocki (Intel) Reviewed-by: Danilo Krummrich Acked-by: Vinod Koul Acked-by: Greg Kroah-Hartman Acked-by: Marek Szyprowski Signed-off-by: Douglas Anderson Link: https://patch.msgid.link/20260406162231.v5.7.If839f6dde98979fce177f70c6c74689a1904ee76@changeid [ Since all DEV_FLAG_DMA_COHERENT accessors are exposed unconditionally, also drop the CONFIG guards around dev_assign_dma_coherent() in device_initialize() to ensure a correct default value. - Danilo ] Signed-off-by: Danilo Krummrich --- diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c index 6b85e94f32759..9b9adb02b4c5a 100644 --- a/arch/arc/mm/dma.c +++ b/arch/arc/mm/dma.c @@ -98,8 +98,8 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) * DMA buffers. */ if (is_isa_arcv2() && ioc_enable && coherent) - dev->dma_coherent = true; + dev_set_dma_coherent(dev); dev_info(dev, "use %scoherent DMA ops\n", - dev->dma_coherent ? "" : "non"); + dev_dma_coherent(dev) ? "" : "non"); } diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 47335c7dadf8d..8b7d0929dac47 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -98,7 +98,7 @@ static int highbank_platform_notifier(struct notifier_block *nb, if (of_property_read_bool(dev->of_node, "dma-coherent")) { val = readl(sregs_base + reg); writel(val | 0xff01, sregs_base + reg); - dev->dma_coherent = true; + dev_set_dma_coherent(dev); } return NOTIFY_OK; diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index fa2c1e1aeb96c..7234d487ff395 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -95,7 +95,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb, if (event != BUS_NOTIFY_ADD_DEVICE) return NOTIFY_DONE; - dev->dma_coherent = true; + dev_set_dma_coherent(dev); return NOTIFY_OK; } diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index fecac107fd0d1..c6a70686507b3 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c @@ -42,11 +42,11 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) * enough to check if MPU is in use or not since in absence of * MPU system memory map is used. */ - dev->dma_coherent = cacheid ? coherent : true; + dev_assign_dma_coherent(dev, cacheid ? coherent : true); } else { /* * Assume coherent DMA in case MMU/MPU has not been set up. */ - dev->dma_coherent = (get_cr() & CR_M) ? coherent : true; + dev_assign_dma_coherent(dev, (get_cr() & CR_M) ? coherent : true); } } diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f304037d1c34c..f9bc53b60f997 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1076,7 +1076,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); struct page **pages; void *addr = NULL; - int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL; + int coherent_flag = dev_dma_coherent(dev) ? COHERENT : NORMAL; *handle = DMA_MAPPING_ERROR; size = PAGE_ALIGN(size); @@ -1124,7 +1124,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, if (vma->vm_pgoff >= nr_pages) return -ENXIO; - if (!dev->dma_coherent) + if (!dev_dma_coherent(dev)) vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot); err = vm_map_pages(vma, pages, nr_pages); @@ -1141,7 +1141,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, static void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle, unsigned long attrs) { - int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL; + int coherent_flag = dev_dma_coherent(dev) ? COHERENT : NORMAL; struct page **pages; size = PAGE_ALIGN(size); @@ -1202,7 +1202,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, phys_addr_t phys = page_to_phys(sg_page(s)); unsigned int len = PAGE_ALIGN(s->offset + s->length); - if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + if (!dev_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) arch_sync_dma_for_device(sg_phys(s), s->length, dir); prot = __dma_info_to_prot(dir, attrs); @@ -1304,7 +1304,7 @@ static void arm_iommu_unmap_sg(struct device *dev, if (sg_dma_len(s)) __iommu_remove_mapping(dev, sg_dma_address(s), sg_dma_len(s)); - if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + if (!dev_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) arch_sync_dma_for_cpu(sg_phys(s), s->length, dir); } } @@ -1323,7 +1323,7 @@ static void arm_iommu_sync_sg_for_cpu(struct device *dev, struct scatterlist *s; int i; - if (dev->dma_coherent) + if (dev_dma_coherent(dev)) return; for_each_sg(sg, s, nents, i) @@ -1345,7 +1345,7 @@ static void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *s; int i; - if (dev->dma_coherent) + if (dev_dma_coherent(dev)) return; for_each_sg(sg, s, nents, i) @@ -1371,7 +1371,7 @@ static dma_addr_t arm_iommu_map_phys(struct device *dev, phys_addr_t phys, dma_addr_t dma_addr; int ret, prot; - if (!dev->dma_coherent && + if (!dev_dma_coherent(dev) && !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) arch_sync_dma_for_device(phys, size, dir); @@ -1412,7 +1412,7 @@ static void arm_iommu_unmap_phys(struct device *dev, dma_addr_t handle, if (!iova) return; - if (!dev->dma_coherent && + if (!dev_dma_coherent(dev) && !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) { phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova); @@ -1431,7 +1431,7 @@ static void arm_iommu_sync_single_for_cpu(struct device *dev, unsigned int offset = handle & ~PAGE_MASK; phys_addr_t phys; - if (dev->dma_coherent || !iova) + if (dev_dma_coherent(dev) || !iova) return; phys = iommu_iova_to_phys(mapping->domain, iova); @@ -1446,7 +1446,7 @@ static void arm_iommu_sync_single_for_device(struct device *dev, unsigned int offset = handle & ~PAGE_MASK; phys_addr_t phys; - if (dev->dma_coherent || !iova) + if (dev_dma_coherent(dev) || !iova) return; phys = iommu_iova_to_phys(mapping->domain, iova); @@ -1701,13 +1701,13 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { } void arch_setup_dma_ops(struct device *dev, bool coherent) { /* - * Due to legacy code that sets the ->dma_coherent flag from a bus - * notifier we can't just assign coherent to the ->dma_coherent flag + * Due to legacy code that sets the dma_coherent flag from a bus + * notifier we can't just assign coherent to the dma_coherent flag * here, but instead have to make sure we only set but never clear it * for now. */ if (coherent) - dev->dma_coherent = true; + dev_set_dma_coherent(dev); /* * Don't override the dma_ops if they have already been set. Ideally diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index ae1ae0280eef7..994b7b36e2b92 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -48,7 +48,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) dev_driver_string(dev), dev_name(dev), ARCH_DMA_MINALIGN, cls); - dev->dma_coherent = coherent; + dev_assign_dma_coherent(dev, coherent); xen_setup_dma_ops(dev); } diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c index ab4f2a75a7d01..30ef3e247eb7a 100644 --- a/arch/mips/mm/dma-noncoherent.c +++ b/arch/mips/mm/dma-noncoherent.c @@ -139,6 +139,6 @@ void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, #ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS void arch_setup_dma_ops(struct device *dev, bool coherent) { - dev->dma_coherent = coherent; + dev_assign_dma_coherent(dev, coherent); } #endif diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c index cb89d7e0ba88a..a1ec2d71d1c92 100644 --- a/arch/riscv/mm/dma-noncoherent.c +++ b/arch/riscv/mm/dma-noncoherent.c @@ -140,7 +140,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) "%s %s: device non-coherent but no non-coherent operations supported", dev_driver_string(dev), dev_name(dev)); - dev->dma_coherent = coherent; + dev_assign_dma_coherent(dev, coherent); } void riscv_noncoherent_supported(void) diff --git a/drivers/base/core.c b/drivers/base/core.c index 7517738dfcd23..ed5ec21edbea6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3170,11 +3170,7 @@ void device_initialize(struct device *dev) INIT_LIST_HEAD(&dev->links.suppliers); INIT_LIST_HEAD(&dev->links.defer_sync); dev->links.status = DL_DEV_NO_DRIVER; -#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) - dev->dma_coherent = dma_default_coherent; -#endif + dev_assign_dma_coherent(dev, dma_default_coherent); swiotlb_dev_init(dev); } EXPORT_SYMBOL_GPL(device_initialize); diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index f87d244cc2d67..686dc140293eb 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -312,7 +312,7 @@ k3_udma_glue_request_tx_chn_common(struct device *dev, if (xudma_is_pktdma(tx_chn->common.udmax)) { /* prepare the channel device as coherent */ - tx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&tx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev, DMA_BIT_MASK(48)); } @@ -1003,7 +1003,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, if (xudma_is_pktdma(rx_chn->common.udmax)) { /* prepare the channel device as coherent */ - rx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&rx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, DMA_BIT_MASK(48)); } @@ -1104,7 +1104,7 @@ k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn if (xudma_is_pktdma(rx_chn->common.udmax)) { /* prepare the channel device as coherent */ - rx_chn->common.chan_dev.dma_coherent = true; + dev_set_dma_coherent(&rx_chn->common.chan_dev); dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, DMA_BIT_MASK(48)); rx_chn->single_fdq = false; diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index c964ebfcf3b68..1cf158eb7bdb5 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -428,18 +428,18 @@ static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel) /* No special handling for the channel */ chan->dev->chan_dma_dev = false; - chan_dev->dma_coherent = false; + dev_clear_dma_coherent(chan_dev); chan_dev->dma_parms = NULL; } else if (asel == 14 || asel == 15) { chan->dev->chan_dma_dev = true; - chan_dev->dma_coherent = true; + dev_set_dma_coherent(chan_dev); dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48)); chan_dev->dma_parms = chan_dev->parent->dma_parms; } else { dev_warn(chan->device->dev, "Invalid ASEL value: %u\n", asel); - chan_dev->dma_coherent = false; + dev_clear_dma_coherent(chan_dev); chan_dev->dma_parms = NULL; } } diff --git a/include/linux/device.h b/include/linux/device.h index fc4334ff33519..bab4315f4f61a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -527,6 +527,8 @@ struct device_physical_location { * @DEV_FLAG_STATE_SYNCED: The hardware state of this device has been synced to * match the software state of this device by calling the * driver/bus sync_state() callback. + * @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the + * architecture supports non-coherent devices. * @DEV_FLAG_COUNT: Number of defined struct_device_flags. */ enum struct_device_flags { @@ -536,6 +538,7 @@ enum struct_device_flags { DEV_FLAG_DMA_SKIP_SYNC = 3, DEV_FLAG_DMA_OPS_BYPASS = 4, DEV_FLAG_STATE_SYNCED = 5, + DEV_FLAG_DMA_COHERENT = 6, DEV_FLAG_COUNT }; @@ -619,8 +622,6 @@ enum struct_device_flags { * @offline: Set after successful invocation of bus type's .offline(). * @of_node_reused: Set if the device-tree node is shared with an ancestor * device. - * @dma_coherent: this particular device is dma coherent, even if the - * architecture supports non-coherent devices. * @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify. * * At the lowest level, every device in a Linux system is represented by an @@ -728,11 +729,6 @@ struct device { bool offline_disabled:1; bool offline:1; bool of_node_reused:1; -#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) - bool dma_coherent:1; -#endif DECLARE_BITMAP(flags, DEV_FLAG_COUNT); }; @@ -765,6 +761,7 @@ __create_dev_flag_accessors(dma_iommu, DEV_FLAG_DMA_IOMMU); __create_dev_flag_accessors(dma_skip_sync, DEV_FLAG_DMA_SKIP_SYNC); __create_dev_flag_accessors(dma_ops_bypass, DEV_FLAG_DMA_OPS_BYPASS); __create_dev_flag_accessors(state_synced, DEV_FLAG_STATE_SYNCED); +__create_dev_flag_accessors(dma_coherent, DEV_FLAG_DMA_COHERENT); #undef __create_dev_flag_accessors diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h index 9e677a79f3a8f..bcb5b5428aea9 100644 --- a/include/linux/dma-map-ops.h +++ b/include/linux/dma-map-ops.h @@ -225,7 +225,7 @@ int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start, extern bool dma_default_coherent; static inline bool dev_is_dma_coherent(struct device *dev) { - return dev->dma_coherent; + return dev_dma_coherent(dev); } #else #define dma_default_coherent true