Skip to content

Commit 1915626

Browse files
rleonChristoph Hellwig
authored andcommitted
dma-mapping: use IOMMU DMA calls for common alloc/free page calls
Common alloca and free pages routines are called when IOMMU DMA is used, and internally it calls to DMA ops structure which is not available for default IOMMU. This patch adds necessary if checks to call IOMMU DMA. It fixes the following crash: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000040 Mem abort info: ESR = 0x0000000096000006 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x06: level 2 translation fault Data abort info: ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=00000000d20bb000 [0000000000000040] pgd=08000000d20c1003 , p4d=08000000d20c1003 , pud=08000000d20c2003, pmd=0000000000000000 Internal error: Oops: 0000000096000006 [#1] PREEMPT SMP Modules linked in: ipv6 hci_uart venus_core btqca v4l2_mem2mem btrtl qcom_spmi_adc5 sbs_battery btbcm qcom_vadc_common cros_ec_typec videobuf2_v4l2 leds_cros_ec cros_kbd_led_backlight cros_ec_chardev videodev elan_i2c videobuf2_common qcom_stats mc bluetooth coresight_stm stm_core ecdh_generic ecc pwrseq_core panel_edp icc_bwmon ath10k_snoc ath10k_core ath mac80211 phy_qcom_qmp_combo aux_bridge libarc4 coresight_replicator coresight_etm4x coresight_tmc coresight_funnel cfg80211 rfkill coresight qcom_wdt cbmem ramoops reed_solomon pwm_bl coreboot_table backlight crct10dif_ce CPU: 7 UID: 0 PID: 70 Comm: kworker/u32:4 Not tainted 6.11.0-rc6-next-20240903-00003-gdfc6015d0711 #660 Hardware name: Google Lazor Limozeen without Touchscreen (rev5 - rev8) (DT) Workqueue: events_unbound deferred_probe_work_func hub 2-1:1.0: 4 ports detected pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : dma_common_alloc_pages+0x54/0x1b4 lr : dma_common_alloc_pages+0x4c/0x1b4 sp : ffff8000807d3730 x29: ffff8000807d3730 x28: ffff02a7d312f880 x27: 0000000000000001 x26: 000000000000c000 x25: 0000000000000000 x24: 0000000000000001 x23: ffff02a7d23b6898 x22: 0000000000006cc0 x21: 000000000000c000 x20: ffff02a7858bf410 x19: fffffe0a60006000 x18: 0000000000000001 x17: 00000000000000d5 x16: 1fffe054f0bcc261 x15: 0000000000000001 x14: ffff02a7844dc680 x13: 0000000000100180 x12: dead000000000100 x11: dead000000000122 x10: 00000000001001ff x9 : ffff02a87f7b7b00 x8 : ffff02a87f7b7b00 x7 : ffff405977d6b000 x6 : ffff8000807d3310 x5 : ffff02a87f6b6398 x4 : 0000000000000001 x3 : ffff405977d6b000 x2 : ffff02a7844dc600 x1 : 0000000100000000 x0 : fffffe0a60006000 Call trace: dma_common_alloc_pages+0x54/0x1b4 __dma_alloc_pages+0x68/0x90 dma_alloc_pages+0x10/0x1c snd_dma_noncoherent_alloc+0x28/0x8c __snd_dma_alloc_pages+0x30/0x50 snd_dma_alloc_dir_pages+0x40/0x80 do_alloc_pages+0xb8/0x13c preallocate_pcm_pages+0x6c/0xf8 preallocate_pages+0x160/0x1a4 snd_pcm_set_managed_buffer_all+0x64/0xb0 lpass_platform_pcm_new+0xc0/0xe8 snd_soc_pcm_component_new+0x3c/0xc8 soc_new_pcm+0x4fc/0x668 snd_soc_bind_card+0xabc/0xbac snd_soc_register_card+0xf0/0x108 devm_snd_soc_register_card+0x4c/0xa4 sc7180_snd_platform_probe+0x180/0x224 platform_probe+0x68/0xc0 really_probe+0xbc/0x298 __driver_probe_device+0x78/0x12c driver_probe_device+0x3c/0x15c __device_attach_driver+0xb8/0x134 bus_for_each_drv+0x84/0xe0 __device_attach+0x9c/0x188 device_initial_probe+0x14/0x20 bus_probe_device+0xac/0xb0 deferred_probe_work_func+0x88/0xc0 process_one_work+0x14c/0x28c worker_thread+0x2cc/0x3d4 kthread+0x114/0x118 ret_from_fork+0x10/0x20 Code: f9411c19 940000c9 aa0003f3 b4000460 (f9402326) ---[ end trace 0000000000000000 ]--- Fixes: b5c58b2 ("dma-mapping: direct calls for dma-iommu") Closes: https://lore.kernel.org/all/10431dfd-ce04-4e0f-973b-c78477303c18@notapiano Reported-by: Nícolas F. R. A. Prado <[email protected]> #KernelCI Signed-off-by: Leon Romanovsky <[email protected]> Tested-by: Nícolas F. R. A. Prado <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent f689a3a commit 1915626

File tree

3 files changed

+19
-15
lines changed

3 files changed

+19
-15
lines changed

include/linux/iommu-dma.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include <linux/dma-direction.h>
1111

1212
#ifdef CONFIG_IOMMU_DMA
13+
static inline bool use_dma_iommu(struct device *dev)
14+
{
15+
return dev->dma_iommu;
16+
}
1317
dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
1418
unsigned long offset, size_t size, enum dma_data_direction dir,
1519
unsigned long attrs);
@@ -49,6 +53,10 @@ void iommu_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
4953
void iommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
5054
int nelems, enum dma_data_direction dir);
5155
#else
56+
static inline bool use_dma_iommu(struct device *dev)
57+
{
58+
return false;
59+
}
5260
static inline dma_addr_t iommu_dma_map_page(struct device *dev,
5361
struct page *page, unsigned long offset, size_t size,
5462
enum dma_data_direction dir, unsigned long attrs)

kernel/dma/mapping.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,6 @@ void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
114114
}
115115
EXPORT_SYMBOL(dmam_alloc_attrs);
116116

117-
#ifdef CONFIG_IOMMU_DMA
118-
static bool use_dma_iommu(struct device *dev)
119-
{
120-
return dev->dma_iommu;
121-
}
122-
#else
123-
static bool use_dma_iommu(struct device *dev)
124-
{
125-
return false;
126-
}
127-
#endif
128-
129117
static bool dma_go_direct(struct device *dev, dma_addr_t mask,
130118
const struct dma_map_ops *ops)
131119
{

kernel/dma/ops_helpers.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* the allocated memory contains normal pages in the direct kernel mapping.
55
*/
66
#include <linux/dma-map-ops.h>
7+
#include <linux/iommu-dma.h>
78

89
static struct page *dma_common_vaddr_to_page(void *cpu_addr)
910
{
@@ -70,8 +71,12 @@ struct page *dma_common_alloc_pages(struct device *dev, size_t size,
7071
if (!page)
7172
return NULL;
7273

73-
*dma_handle = ops->map_page(dev, page, 0, size, dir,
74-
DMA_ATTR_SKIP_CPU_SYNC);
74+
if (use_dma_iommu(dev))
75+
*dma_handle = iommu_dma_map_page(dev, page, 0, size, dir,
76+
DMA_ATTR_SKIP_CPU_SYNC);
77+
else
78+
*dma_handle = ops->map_page(dev, page, 0, size, dir,
79+
DMA_ATTR_SKIP_CPU_SYNC);
7580
if (*dma_handle == DMA_MAPPING_ERROR) {
7681
dma_free_contiguous(dev, page, size);
7782
return NULL;
@@ -86,7 +91,10 @@ void dma_common_free_pages(struct device *dev, size_t size, struct page *page,
8691
{
8792
const struct dma_map_ops *ops = get_dma_ops(dev);
8893

89-
if (ops->unmap_page)
94+
if (use_dma_iommu(dev))
95+
iommu_dma_unmap_page(dev, dma_handle, size, dir,
96+
DMA_ATTR_SKIP_CPU_SYNC);
97+
else if (ops->unmap_page)
9098
ops->unmap_page(dev, dma_handle, size, dir,
9199
DMA_ATTR_SKIP_CPU_SYNC);
92100
dma_free_contiguous(dev, page, size);

0 commit comments

Comments
 (0)