From 409747f42cf8bb192ac9b69251654733f19420f5 Mon Sep 17 00:00:00 2001 From: Joseph Wong Date: Wed, 27 May 2026 22:45:59 -0700 Subject: [PATCH] [tg3] Use updated DMA APIs Replace malloc_phys with dma_alloc, free_phys with dma_free, alloc_iob with alloc_rx_iob, free_iob with free_rx_iob, virt_to_bus with dma or iob_dma. Replace dma_addr_t with physaddr_t. Signed-off-by: Joseph Wong --- src/drivers/net/tg3/tg3.c | 84 +++++++++++++++++++++++------------- src/drivers/net/tg3/tg3.h | 15 +++---- src/drivers/net/tg3/tg3_hw.c | 32 +++++++++----- 3 files changed, 84 insertions(+), 47 deletions(-) diff --git a/src/drivers/net/tg3/tg3.c b/src/drivers/net/tg3/tg3.c index a6736305c..cc5bc3022 100644 --- a/src/drivers/net/tg3/tg3.c +++ b/src/drivers/net/tg3/tg3.c @@ -39,11 +39,13 @@ static void tg3_refill_prod_ring(struct tg3 *tp); #define TG3_RX_STD_RING_BYTES(tp) \ (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700) -void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr) +void tg3_rx_prodring_fini(struct tg3 __unused *tp, + struct tg3_rx_prodring_set *tpr) { DBGP("%s\n", __func__); if (tpr->rx_std) { - free_phys(tpr->rx_std, TG3_RX_STD_RING_BYTES(tp)); + dma_free(&tpr->rx_std_map, tpr->rx_std, + TG3_RX_STD_RING_BYTES(tp)); tpr->rx_std = NULL; } } @@ -56,7 +58,7 @@ static void tg3_free_consistent(struct tg3 *tp) { DBGP("%s\n", __func__); if (tp->tx_ring) { - free_phys(tp->tx_ring, TG3_TX_RING_BYTES); + dma_free(&tp->tx_desc_map, tp->tx_ring, TG3_TX_RING_BYTES); tp->tx_ring = NULL; } @@ -64,16 +66,15 @@ static void tg3_free_consistent(struct tg3 *tp) tp->tx_buffers = NULL; if (tp->rx_rcb) { - free_phys(tp->rx_rcb, TG3_RX_RCB_RING_BYTES(tp)); - tp->rx_rcb_mapping = 0; + dma_free(&tp->rx_rcb_map, tp->rx_rcb, + TG3_RX_RCB_RING_BYTES(tp)); tp->rx_rcb = NULL; } - tg3_rx_prodring_fini(&tp->prodring); + tg3_rx_prodring_fini(tp, &tp->prodring); if (tp->hw_status) { - free_phys(tp->hw_status, TG3_HW_STATUS_SIZE); - tp->status_mapping = 0; + dma_free(&tp->status_map, tp->hw_status, TG3_HW_STATUS_SIZE); tp->hw_status = NULL; } } @@ -88,32 +89,32 @@ int tg3_alloc_consistent(struct tg3 *tp) struct tg3_hw_status *sblk; struct tg3_rx_prodring_set *tpr = &tp->prodring; - tp->hw_status = malloc_phys(TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT); + tp->hw_status = dma_alloc(tp->dma, &tp->status_map, + TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT); if (!tp->hw_status) { DBGC(tp->dev, "hw_status alloc failed\n"); goto err_out; } - tp->status_mapping = virt_to_bus(tp->hw_status); memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); sblk = tp->hw_status; - tpr->rx_std = malloc_phys(TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT); + tpr->rx_std = dma_alloc(tp->dma, &tpr->rx_std_map, + TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT); if (!tpr->rx_std) { DBGC(tp->dev, "rx prodring alloc failed\n"); goto err_out; } - tpr->rx_std_mapping = virt_to_bus(tpr->rx_std); memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp)); tp->tx_buffers = zalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE); if (!tp->tx_buffers) goto err_out; - tp->tx_ring = malloc_phys(TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT); + tp->tx_ring = dma_alloc(tp->dma, &tp->tx_desc_map, + TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT); if (!tp->tx_ring) goto err_out; - tp->tx_desc_mapping = virt_to_bus(tp->tx_ring); /* * When RSS is enabled, the status block format changes @@ -124,10 +125,10 @@ int tg3_alloc_consistent(struct tg3 *tp) tp->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; - tp->rx_rcb = malloc_phys(TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT); + tp->rx_rcb = dma_alloc(tp->dma, &tp->rx_rcb_map, + TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT); if (!tp->rx_rcb) goto err_out; - tp->rx_rcb_mapping = virt_to_bus(tp->rx_rcb); memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); @@ -182,7 +183,11 @@ static void tg3_rx_iob_free(struct io_buffer *iobs[], int i) if (iobs[i] == NULL) return; - free_iob(iobs[i]); + /* RX iobufs were allocated via alloc_rx_iob() and are therefore + * DMA-mapped through the platform DMA API; they must be released + * via free_rx_iob() so the mapping is torn down. + */ + free_rx_iob(iobs[i]); iobs[i] = NULL; } @@ -302,7 +307,7 @@ static int tg3_transmit(struct net_device *dev, struct io_buffer *iob) struct tg3 *tp = dev->priv; u32 len, entry; - dma_addr_t mapping; + physaddr_t mapping; if (tg3_tx_avail(tp) < 1) { DBGC(dev, "Transmit ring full\n"); @@ -312,7 +317,11 @@ static int tg3_transmit(struct net_device *dev, struct io_buffer *iob) entry = tp->tx_prod; iob_pad(iob, ETH_ZLEN); - mapping = virt_to_bus(iob->data); + /* The netdevice core has already called iob_map_tx() for this + * iobuf (because netdev->dma is set), so iob_dma() returns the + * platform-translated bus address suitable for the device. + */ + mapping = iob_dma(iob); len = iob_len(iob); tp->tx_buffers[entry].iob = iob; @@ -366,12 +375,13 @@ static void tg3_tx_complete(struct net_device *dev) * buffers the cpu only reads the last cacheline of the RX descriptor * (to fetch the error flags, vlan tag, checksum, and opaque cookie). */ -static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmasked) +static int tg3_alloc_rx_iob(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, + u32 dest_idx_unmasked) { DBGP("%s\n", __func__); struct tg3_rx_buffer_desc *desc; struct io_buffer *iob; - dma_addr_t mapping; + physaddr_t mapping; int dest_idx, iob_idx; dest_idx = dest_idx_unmasked & (TG3_RX_STD_MAX_SIZE_5700 - 1); @@ -382,15 +392,19 @@ static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmask * * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. + * + * Allocate the receive iobuf already DMA-mapped through the + * platform DMA API so the device may write into it under + * preboot DMA protection (IOMMU). */ - iob = alloc_iob(TG3_RX_STD_DMA_SZ); + iob = alloc_rx_iob(TG3_RX_STD_DMA_SZ, tp->dma); if (iob == NULL) return -ENOMEM; iob_idx = dest_idx % TG3_DEF_RX_RING_PENDING; tpr->rx_iobufs[iob_idx] = iob; - mapping = virt_to_bus(iob->data); + mapping = iob_dma(iob); desc->addr_hi = ((u64)mapping >> 32); desc->addr_lo = ((u64)mapping & 0xffffffff); @@ -408,7 +422,7 @@ static void tg3_refill_prod_ring(struct tg3 *tp) while (tpr->rx_std_iob_cnt < TG3_DEF_RX_RING_PENDING) { if (tpr->rx_iobufs[idx % TG3_DEF_RX_RING_PENDING] == NULL) { - if (tg3_alloc_rx_iob(tpr, idx) < 0) { + if (tg3_alloc_rx_iob(tp, tpr, idx) < 0) { DBGC(tp->dev, "alloc_iob() failed for descriptor %d\n", idx); break; } @@ -532,22 +546,24 @@ static struct net_device_operations tg3_netdev_ops = { #define TEST_BUFFER_SIZE 0x2000 -int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device); +int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, physaddr_t buf_dma, int size, int to_device); void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val); static int tg3_test_dma(struct tg3 *tp) { DBGP("%s\n", __func__); - dma_addr_t buf_dma; + struct dma_mapping buf_map; + physaddr_t buf_dma; u32 *buf; int ret = 0; - buf = malloc_phys(TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT); + memset(&buf_map, 0, sizeof(buf_map)); + buf = dma_alloc(tp->dma, &buf_map, TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT); if (!buf) { ret = -ENOMEM; goto out_nofree; } - buf_dma = virt_to_bus(buf); + buf_dma = dma(&buf_map, buf); DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#016lx\n", buf, buf_dma); if (tg3_flag(tp, 57765_PLUS)) { @@ -709,7 +725,7 @@ static int tg3_test_dma(struct tg3 *tp) } out: - free_phys(buf, TEST_BUFFER_SIZE); + dma_free(&buf_map, buf, TEST_BUFFER_SIZE); out_nofree: return ret; } @@ -742,6 +758,16 @@ static int tg3_init_one(struct pci_device *pdev) tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + /* Configure DMA. This must be done before any DMA allocation + * (including the self-test buffer in tg3_test_dma) so that + * buffers are mapped through the platform DMA implementation, + * which is required when preboot DMA protection (IOMMU) is + * active. + */ + tp->dma = &pdev->dma; + dev->dma = tp->dma; + dma_set_mask_64bit ( tp->dma ); + /* Subsystem IDs are required later */ pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor); pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device); diff --git a/src/drivers/net/tg3/tg3.h b/src/drivers/net/tg3/tg3.h index fa809c041..f24349bab 100644 --- a/src/drivers/net/tg3/tg3.h +++ b/src/drivers/net/tg3/tg3.h @@ -2809,8 +2809,6 @@ struct tg3_hw_stats { u8 __reserved4[0xb00-0x9c8]; }; -typedef unsigned long dma_addr_t; - /* 'mapping' is superfluous as the chip does not write into * the tx/rx post rings so we could just fetch it from there. * But the cache behavior is better how we are doing it now. @@ -2954,7 +2952,7 @@ struct tg3_rx_prodring_set { u32 rx_std_iob_cnt; struct tg3_rx_buffer_desc *rx_std; struct io_buffer *rx_iobufs[TG3_DEF_RX_RING_PENDING]; - dma_addr_t rx_std_mapping; + struct dma_mapping rx_std_map; }; #define TG3_IRQ_MAX_VECS_RSS 5 @@ -3090,6 +3088,7 @@ struct tg3 { void *regs; struct net_device *dev; struct pci_device *pdev; + struct dma_device *dma; u32 msg_enable; @@ -3125,9 +3124,9 @@ struct tg3 { struct tg3_tx_buffer_desc *tx_ring; struct ring_info *tx_buffers; - dma_addr_t status_mapping; - dma_addr_t rx_rcb_mapping; - dma_addr_t tx_desc_mapping; + struct dma_mapping status_map; + struct dma_mapping rx_rcb_map; + struct dma_mapping tx_desc_map; /* end tg3_napi */ /* begin "everything else" cacheline(s) section */ @@ -3371,7 +3370,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) /* tg3_main.c forward declarations */ int tg3_init_rings(struct tg3 *tp); -void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr); +void tg3_rx_prodring_fini(struct tg3 *tp, struct tg3_rx_prodring_set *tpr); ///int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr); /* tg3_phy.c forward declarations */ @@ -3390,7 +3389,7 @@ int tg3_get_invariants(struct tg3 *tp); void tg3_init_bufmgr_config(struct tg3 *tp); int tg3_get_device_address(struct tg3 *tp); int tg3_halt(struct tg3 *tp); -void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags); +void tg3_set_txd(struct tg3 *tp, int entry, physaddr_t mapping, int len, u32 flags); void tg3_set_power_state_0(struct tg3 *tp); int tg3_alloc_consistent(struct tg3 *tp); int tg3_init_hw(struct tg3 *tp, int reset_phy); diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c index 5c9506dce..664f14e76 100644 --- a/src/drivers/net/tg3/tg3_hw.c +++ b/src/drivers/net/tg3/tg3_hw.c @@ -1765,7 +1765,7 @@ static void __tg3_set_coalesce(struct tg3 *tp) } static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr, - dma_addr_t mapping, u32 maxlen_flags, + physaddr_t mapping, u32 maxlen_flags, u32 nic_addr) { DBGP("%s\n", __func__); @@ -1790,6 +1790,7 @@ static void tg3_rings_reset(struct tg3 *tp) int i; u32 txrcb, rxrcb, limit; + physaddr_t status_dma; /* Disable all transmit rings but the first. */ if (!tg3_flag(tp, 5705_PLUS)) @@ -1844,14 +1845,20 @@ static void tg3_rings_reset(struct tg3 *tp) /* Clear status block in ram. */ memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); - /* Set status block DMA address */ + /* Set status block DMA address. Use dma() so the platform DMA + * implementation (e.g. EFI PCI_IO Map) can translate the host + * virtual address into the bus address the device must use. + */ + status_dma = dma(&tp->status_map, tp->hw_status); + tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tp->status_mapping >> 32)); + ((u64) status_dma >> 32)); tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tp->status_mapping & 0xffffffff)); + ((u64) status_dma & 0xffffffff)); if (tp->tx_ring) { - tg3_set_bdinfo(tp, txrcb, tp->tx_desc_mapping, + tg3_set_bdinfo(tp, txrcb, + dma(&tp->tx_desc_map, tp->tx_ring), (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT), NIC_SRAM_TX_BUFFER_DESC); @@ -1860,7 +1867,8 @@ static void tg3_rings_reset(struct tg3 *tp) /* FIXME: will TG3_RX_RET_MAX_SIZE_5705 work on all cards? */ if (tp->rx_rcb) { - tg3_set_bdinfo(tp, rxrcb, tp->rx_rcb_mapping, + tg3_set_bdinfo(tp, rxrcb, + dma(&tp->rx_rcb_map, tp->rx_rcb), TG3_RX_RET_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT, 0); rxrcb += TG3_BDINFO_SIZE; @@ -1900,6 +1908,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) u32 val, rdmac_mode; int i, err, limit; struct tg3_rx_prodring_set *tpr = &tp->prodring; + physaddr_t rx_std_dma; tg3_stop_fw(tp); @@ -2123,10 +2132,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) * The size of each ring is fixed in the firmware, but the location is * configurable. */ + rx_std_dma = dma(&tpr->rx_std_map, tpr->rx_std); + tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, - ((u64) tpr->rx_std_mapping >> 32)); + ((u64) rx_std_dma >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, - ((u64) tpr->rx_std_mapping & 0xffffffff)); + ((u64) rx_std_dma & 0xffffffff)); + if (!tg3_flag(tp, 5717_PLUS)) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); @@ -2581,7 +2593,7 @@ int tg3_init_hw(struct tg3 *tp, int reset_phy) } void tg3_set_txd(struct tg3 *tp, int entry, - dma_addr_t mapping, int len, u32 flags) + physaddr_t mapping, int len, u32 flags) { DBGP("%s\n", __func__); struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; @@ -2592,7 +2604,7 @@ void tg3_set_txd(struct tg3 *tp, int entry, txd->vlan_tag = 0; } -int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device) +int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, physaddr_t buf_dma, int size, int to_device) { DBGP("%s\n", __func__); struct tg3_internal_buffer_desc test_desc;