Re: [PATCH] VMXNET3: Add support for virtual IOMMU
From: Andy King ack...@vmware.com Date: Fri, 23 Aug 2013 09:33:49 -0700 This patch adds support for virtual IOMMU to the vmxnet3 module. We switch to DMA consistent mappings for anything we pass to the device. There were a few places where we already did this, but using pci_blah(); these have been fixed to use dma_blah(), along with all new occurrences where we've replaced kmalloc() and friends. Also fix two small bugs: 1) use after free of rq-buf_info in vmxnet3_rq_destroy() 2) a cpu_to_le32() that should have been a cpu_to_le64() Acked-by: George Zhang georgezh...@vmware.com Acked-by: Aditya Sarwade asarw...@vmware.com Signed-off-by: Andy King ack...@vmware.com Applied, thanks. ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH] VMXNET3: Add support for virtual IOMMU
This patch adds support for virtual IOMMU to the vmxnet3 module. We switch to DMA consistent mappings for anything we pass to the device. There were a few places where we already did this, but using pci_blah(); these have been fixed to use dma_blah(), along with all new occurrences where we've replaced kmalloc() and friends. Also fix two small bugs: 1) use after free of rq-buf_info in vmxnet3_rq_destroy() 2) a cpu_to_le32() that should have been a cpu_to_le64() Acked-by: George Zhang georgezh...@vmware.com Acked-by: Aditya Sarwade asarw...@vmware.com Signed-off-by: Andy King ack...@vmware.com --- drivers/net/vmxnet3/vmxnet3_drv.c | 211 +++-- drivers/net/vmxnet3/vmxnet3_int.h | 10 ++- 2 files changed, 138 insertions(+), 83 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 55a62ca..7e2788c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -313,10 +313,10 @@ vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi, struct pci_dev *pdev) { if (tbi-map_type == VMXNET3_MAP_SINGLE) - pci_unmap_single(pdev, tbi-dma_addr, tbi-len, + dma_unmap_single(pdev-dev, tbi-dma_addr, tbi-len, PCI_DMA_TODEVICE); else if (tbi-map_type == VMXNET3_MAP_PAGE) - pci_unmap_page(pdev, tbi-dma_addr, tbi-len, + dma_unmap_page(pdev-dev, tbi-dma_addr, tbi-len, PCI_DMA_TODEVICE); else BUG_ON(tbi-map_type != VMXNET3_MAP_NONE); @@ -429,25 +429,29 @@ vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { if (tq-tx_ring.base) { - pci_free_consistent(adapter-pdev, tq-tx_ring.size * - sizeof(struct Vmxnet3_TxDesc), - tq-tx_ring.base, tq-tx_ring.basePA); + dma_free_coherent(adapter-pdev-dev, tq-tx_ring.size * + sizeof(struct Vmxnet3_TxDesc), + tq-tx_ring.base, tq-tx_ring.basePA); tq-tx_ring.base = NULL; } if (tq-data_ring.base) { - pci_free_consistent(adapter-pdev, tq-data_ring.size * - sizeof(struct Vmxnet3_TxDataDesc), - tq-data_ring.base, tq-data_ring.basePA); + dma_free_coherent(adapter-pdev-dev, tq-data_ring.size * + sizeof(struct Vmxnet3_TxDataDesc), + tq-data_ring.base, tq-data_ring.basePA); tq-data_ring.base = NULL; } if (tq-comp_ring.base) { - pci_free_consistent(adapter-pdev, tq-comp_ring.size * - sizeof(struct Vmxnet3_TxCompDesc), - tq-comp_ring.base, tq-comp_ring.basePA); + dma_free_coherent(adapter-pdev-dev, tq-comp_ring.size * + sizeof(struct Vmxnet3_TxCompDesc), + tq-comp_ring.base, tq-comp_ring.basePA); tq-comp_ring.base = NULL; } - kfree(tq-buf_info); - tq-buf_info = NULL; + if (tq-buf_info) { + dma_free_coherent(adapter-pdev-dev, + tq-tx_ring.size * sizeof(tq-buf_info[0]), + tq-buf_info, tq-buf_info_pa); + tq-buf_info = NULL; + } } @@ -496,37 +500,38 @@ static int vmxnet3_tq_create(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { + size_t sz; + BUG_ON(tq-tx_ring.base || tq-data_ring.base || tq-comp_ring.base || tq-buf_info); - tq-tx_ring.base = pci_alloc_consistent(adapter-pdev, tq-tx_ring.size - * sizeof(struct Vmxnet3_TxDesc), - tq-tx_ring.basePA); + tq-tx_ring.base = dma_alloc_coherent(adapter-pdev-dev, + tq-tx_ring.size * sizeof(struct Vmxnet3_TxDesc), + tq-tx_ring.basePA, GFP_KERNEL); if (!tq-tx_ring.base) { netdev_err(adapter-netdev, failed to allocate tx ring\n); goto err; } - tq-data_ring.base = pci_alloc_consistent(adapter-pdev, -tq-data_ring.size * -sizeof(struct Vmxnet3_TxDataDesc), -tq-data_ring.basePA); + tq-data_ring.base = dma_alloc_coherent(adapter-pdev-dev, + tq-data_ring.size * sizeof(struct Vmxnet3_TxDataDesc), + tq-data_ring.basePA, GFP_KERNEL); if (!tq-data_ring.base) { netdev_err(adapter-netdev, failed to allocate data ring\n); goto err; } - tq-comp_ring.base
Re: [PATCH] VMXNET3: Add support for virtual IOMMU
Adding Greg, since this will apply to a similar patchset I sent out for VMCI. - Original Message - From: Andy King ack...@vmware.com Date: Tue, 20 Aug 2013 10:33:32 -0700 We can't just do virt_to_phys() on memory that we pass to the device and expect it to work in presence of a virtual IOMMU. We need to add IOMMU mappings for such DMAs to work correctly. Fix that with pci_alloc_consistent() where possible, or pci_map_single() where the mapping is short-lived or we don't control the allocation (netdev). Please use dma_alloc_coherent() (or in fact dma_zalloc_coherent()), dma_map_single() et al., because they are preferred and in particular allow specification of GFP_* flags Sorry about that, I'll fix that and send out a new patch. Thanks! - Andy ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH] VMXNET3: Add support for virtual IOMMU
We can't just do virt_to_phys() on memory that we pass to the device and expect it to work in presence of a virtual IOMMU. We need to add IOMMU mappings for such DMAs to work correctly. Fix that with pci_alloc_consistent() where possible, or pci_map_single() where the mapping is short-lived or we don't control the allocation (netdev). Also fix two small bugs: 1) use after free of rq-buf_info in vmxnet3_rq_destroy() 2) a cpu_to_le32() that should have been a cpu_to_le64() Acked-by: George Zhang georgezh...@vmware.com Acked-by: Aditya Sarwade asarw...@vmware.com Signed-off-by: Andy King ack...@vmware.com --- drivers/net/vmxnet3/vmxnet3_drv.c | 89 ++--- drivers/net/vmxnet3/vmxnet3_int.h | 10 +++- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 55a62ca..7ca9ec9 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -446,8 +446,12 @@ vmxnet3_tq_destroy(struct vmxnet3_tx_queue *tq, tq-comp_ring.base, tq-comp_ring.basePA); tq-comp_ring.base = NULL; } - kfree(tq-buf_info); - tq-buf_info = NULL; + if (tq-buf_info) { + pci_free_consistent(adapter-pdev, + tq-tx_ring.size * sizeof(tq-buf_info[0]), + tq-buf_info, tq-buf_info_pa); + tq-buf_info = NULL; + } } @@ -496,6 +500,8 @@ static int vmxnet3_tq_create(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter) { + size_t sz; + BUG_ON(tq-tx_ring.base || tq-data_ring.base || tq-comp_ring.base || tq-buf_info); @@ -525,10 +531,12 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq, goto err; } - tq-buf_info = kcalloc(tq-tx_ring.size, sizeof(tq-buf_info[0]), - GFP_KERNEL); + sz = tq-tx_ring.size * sizeof(tq-buf_info[0]); + tq-buf_info = pci_alloc_consistent(adapter-pdev, sz, + tq-buf_info_pa); if (!tq-buf_info) goto err; + memset(tq-buf_info, 0, sz); return 0; @@ -1400,8 +1408,6 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, } - kfree(rq-buf_info[0]); - for (i = 0; i 2; i++) { if (rq-rx_ring[i].base) { pci_free_consistent(adapter-pdev, rq-rx_ring[i].size @@ -1419,6 +1425,13 @@ static void vmxnet3_rq_destroy(struct vmxnet3_rx_queue *rq, rq-comp_ring.base, rq-comp_ring.basePA); rq-comp_ring.base = NULL; } + + if (rq-buf_info[0]) { + size_t sz = sizeof(struct vmxnet3_rx_buf_info) * + (rq-rx_ring[0].size + rq-rx_ring[1].size); + pci_free_consistent(adapter-pdev, sz, rq-buf_info[0], + rq-buf_info_pa); + } } @@ -1522,10 +1535,11 @@ vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter) sz = sizeof(struct vmxnet3_rx_buf_info) * (rq-rx_ring[0].size + rq-rx_ring[1].size); - bi = kzalloc(sz, GFP_KERNEL); + bi = pci_alloc_consistent(adapter-pdev, sz, rq-buf_info_pa); if (!bi) goto err; + memset(bi, 0, sz); rq-buf_info[0] = bi; rq-buf_info[1] = bi + rq-rx_ring[0].size; @@ -2005,6 +2019,7 @@ vmxnet3_set_mc(struct net_device *netdev) struct Vmxnet3_RxFilterConf *rxConf = adapter-shared-devRead.rxFilterConf; u8 *new_table = NULL; + dma_addr_t new_table_pa = 0; u32 new_mode = VMXNET3_RXM_UCAST; if (netdev-flags IFF_PROMISC) { @@ -2028,8 +2043,11 @@ vmxnet3_set_mc(struct net_device *netdev) new_mode |= VMXNET3_RXM_MCAST; rxConf-mfTableLen = cpu_to_le16( netdev_mc_count(netdev) * ETH_ALEN); - rxConf-mfTablePA = cpu_to_le64(virt_to_phys( - new_table)); + new_table_pa = pci_map_single(adapter-pdev, + new_table, + rxConf-mfTableLen, + PCI_DMA_TODEVICE); + rxConf-mfTablePA = cpu_to_le64(new_table_pa); } else { netdev_info(netdev, failed to copy mcast list , setting ALL_MULTI\n); @@ -2056,7 +2074,11 @@ vmxnet3_set_mc(struct net_device *netdev)