Re: [PATCH] VMXNET3: Add support for virtual IOMMU

2013-08-27 Thread David Miller
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

2013-08-23 Thread Andy King
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

2013-08-21 Thread Andy King
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

2013-08-20 Thread Andy King
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)