From 5e4f5ad8563b793b79a48e0eb52ee31beb585fff Mon Sep 17 00:00:00 2001 From: xiaotianxt Date: Tue, 11 Aug 2026 19:07:13 -0400 Subject: [PATCH] Fix DMA page lookup for IOMMU allocations --- modules/exanic/exanic-dev.c | 4 ++-- modules/exanic/exanic-main.c | 9 ++++++--- modules/exanic/exanic.h | 8 ++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/exanic/exanic-dev.c b/modules/exanic/exanic-dev.c index 8bf985f..edbaf40 100644 --- a/modules/exanic/exanic-dev.c +++ b/modules/exanic/exanic-dev.c @@ -350,7 +350,7 @@ static int exanic_map_tx_feedback(struct exanic *exanic, for (off = 0; off < map_size; off += PAGE_SIZE) { err = vm_insert_page(vma, vma->vm_start + off, - virt_to_page(exanic->tx_feedback_virt + off)); + exanic_virt_to_page(exanic->tx_feedback_virt + off)); if (err) { phys_addr = virt_to_phys(exanic->tx_feedback_virt + off); @@ -488,7 +488,7 @@ static int exanic_map_rx_region(struct exanic *exanic, struct vm_area_struct *vm for (off = 0; off < map_size; off += PAGE_SIZE) { err = vm_insert_page(vma, vma->vm_start + off, - virt_to_page(rx_region_virt + off)); + exanic_virt_to_page(rx_region_virt + off)); if (err) { phys_addr = virt_to_phys(rx_region_virt + off); diff --git a/modules/exanic/exanic-main.c b/modules/exanic/exanic-main.c index 14b7d55..eecfc17 100644 --- a/modules/exanic/exanic-main.c +++ b/modules/exanic/exanic-main.c @@ -132,7 +132,8 @@ bool exanic_rx_in_use(struct exanic *exanic, unsigned port_num) if (exanic->port[port_num].rx_region_virt) { /* Check if the region is mapped */ - if (page_count(virt_to_page(exanic->port[port_num].rx_region_virt)) > 1) + if (page_count(exanic_virt_to_page( + exanic->port[port_num].rx_region_virt)) > 1) return true; } @@ -158,7 +159,8 @@ int exanic_count_tx_feedback_users(struct exanic *exanic) { for (i = 0; i < EXANIC_TX_FEEDBACK_NUM_PAGES; i++) /* subtract 1 since we have a mapping */ - count += page_count(virt_to_page(exanic->tx_feedback_virt + i * PAGE_SIZE)) - 1; + count += page_count(exanic_virt_to_page( + exanic->tx_feedback_virt + i * PAGE_SIZE)) - 1; return count; } @@ -178,7 +180,8 @@ int exanic_count_rx_users(struct exanic *exanic) { if (exanic->port[i].rx_region_virt) /* subtract 1 since we have a mapping */ - count += page_count(virt_to_page(exanic->port[i].rx_region_virt)) - 1; + count += page_count(exanic_virt_to_page( + exanic->port[i].rx_region_virt)) - 1; for (buf = 0; buf < exanic->max_filter_buffers; buf++) count += exanic->port[i].filter_buffers[buf].refcount; diff --git a/modules/exanic/exanic.h b/modules/exanic/exanic.h index 457a770..3c0c13a 100644 --- a/modules/exanic/exanic.h +++ b/modules/exanic/exanic.h @@ -6,6 +6,8 @@ #ifndef _EXANIC_H_ #define _EXANIC_H_ +#include + #include "../../include/exanic_version.h" #define DRV_VERSION EXANIC_VERSION_TEXT @@ -69,6 +71,12 @@ struct exanic_ate_regdump /* exanic.c */ struct exanic; +/* dma_alloc_coherent() may return an address in vmalloc space. */ +static inline struct page *exanic_virt_to_page(const void *addr) +{ + return is_vmalloc_addr(addr) ? vmalloc_to_page(addr) : virt_to_page(addr); +} + struct exanic *exanic_find_by_minor(unsigned minor); void exanic_netdev_get_id_and_port(struct net_device *ndev,