| From: "hpreg@vmware.com" <hpreg@vmware.com> |
| Date: Mon, 14 May 2018 08:14:34 -0400 |
| Subject: vmxnet3: set the DMA mask before the first DMA map operation |
| |
| commit 61aeecea40afb2b89933e27cd4adb10fc2e75cfd upstream. |
| |
| The DMA mask must be set before, not after, the first DMA map operation, or |
| the first DMA map operation could in theory fail on some systems. |
| |
| Fixes: b0eb57cb97e78 ("VMXNET3: Add support for virtual IOMMU") |
| Signed-off-by: Regis Duchesne <hpreg@vmware.com> |
| Acked-by: Ronak Doshi <doshir@vmware.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| [bwh: Backported to 3.16: Bump version from 1.2.1.0-k to 1.2.2.0-k, which |
| wasn't used in mainline] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/net/vmxnet3/vmxnet3_drv.c | 50 +++++++++++++++---------------- |
| drivers/net/vmxnet3/vmxnet3_int.h | 8 +++-- |
| 2 files changed, 30 insertions(+), 28 deletions(-) |
| |
| --- a/drivers/net/vmxnet3/vmxnet3_drv.c |
| +++ b/drivers/net/vmxnet3/vmxnet3_drv.c |
| @@ -2445,7 +2445,7 @@ vmxnet3_set_mac_addr(struct net_device * |
| /* ==================== initialization and cleanup routines ============ */ |
| |
| static int |
| -vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64) |
| +vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter) |
| { |
| int err; |
| unsigned long mmio_start, mmio_len; |
| @@ -2457,30 +2457,12 @@ vmxnet3_alloc_pci_resources(struct vmxne |
| return err; |
| } |
| |
| - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) { |
| - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { |
| - dev_err(&pdev->dev, |
| - "pci_set_consistent_dma_mask failed\n"); |
| - err = -EIO; |
| - goto err_set_mask; |
| - } |
| - *dma64 = true; |
| - } else { |
| - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { |
| - dev_err(&pdev->dev, |
| - "pci_set_dma_mask failed\n"); |
| - err = -EIO; |
| - goto err_set_mask; |
| - } |
| - *dma64 = false; |
| - } |
| - |
| err = pci_request_selected_regions(pdev, (1 << 2) - 1, |
| vmxnet3_driver_name); |
| if (err) { |
| dev_err(&pdev->dev, |
| "Failed to request region for adapter: error %d\n", err); |
| - goto err_set_mask; |
| + goto err_enable_device; |
| } |
| |
| pci_set_master(pdev); |
| @@ -2508,7 +2490,7 @@ err_bar1: |
| iounmap(adapter->hw_addr0); |
| err_ioremap: |
| pci_release_selected_regions(pdev, (1 << 2) - 1); |
| -err_set_mask: |
| +err_enable_device: |
| pci_disable_device(pdev); |
| return err; |
| } |
| @@ -2973,7 +2955,7 @@ vmxnet3_probe_device(struct pci_dev *pde |
| #endif |
| }; |
| int err; |
| - bool dma64 = false; /* stupid gcc */ |
| + bool dma64; |
| u32 ver; |
| struct net_device *netdev; |
| struct vmxnet3_adapter *adapter; |
| @@ -3018,6 +3000,24 @@ vmxnet3_probe_device(struct pci_dev *pde |
| adapter->tx_ring_size = VMXNET3_DEF_TX_RING_SIZE; |
| adapter->rx_ring_size = VMXNET3_DEF_RX_RING_SIZE; |
| |
| + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) { |
| + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { |
| + dev_err(&pdev->dev, |
| + "pci_set_consistent_dma_mask failed\n"); |
| + err = -EIO; |
| + goto err_set_mask; |
| + } |
| + dma64 = true; |
| + } else { |
| + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { |
| + dev_err(&pdev->dev, |
| + "pci_set_dma_mask failed\n"); |
| + err = -EIO; |
| + goto err_set_mask; |
| + } |
| + dma64 = false; |
| + } |
| + |
| spin_lock_init(&adapter->cmd_lock); |
| adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter, |
| sizeof(struct vmxnet3_adapter), |
| @@ -3025,7 +3025,7 @@ vmxnet3_probe_device(struct pci_dev *pde |
| if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) { |
| dev_err(&pdev->dev, "Failed to map dma\n"); |
| err = -EFAULT; |
| - goto err_dma_map; |
| + goto err_set_mask; |
| } |
| adapter->shared = dma_alloc_coherent( |
| &adapter->pdev->dev, |
| @@ -3076,7 +3076,7 @@ vmxnet3_probe_device(struct pci_dev *pde |
| } |
| #endif /* VMXNET3_RSS */ |
| |
| - err = vmxnet3_alloc_pci_resources(adapter, &dma64); |
| + err = vmxnet3_alloc_pci_resources(adapter); |
| if (err < 0) |
| goto err_alloc_pci; |
| |
| @@ -3180,7 +3180,7 @@ err_alloc_queue_desc: |
| err_alloc_shared: |
| dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa, |
| sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE); |
| -err_dma_map: |
| +err_set_mask: |
| free_netdev(netdev); |
| return err; |
| } |
| --- a/drivers/net/vmxnet3/vmxnet3_int.h |
| +++ b/drivers/net/vmxnet3/vmxnet3_int.h |
| @@ -69,10 +69,12 @@ |
| /* |
| * Version numbers |
| */ |
| -#define VMXNET3_DRIVER_VERSION_STRING "1.2.1.0-k" |
| +#define VMXNET3_DRIVER_VERSION_STRING "1.2.2.0-k" |
| |
| -/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ |
| -#define VMXNET3_DRIVER_VERSION_NUM 0x01020100 |
| +/* Each byte of this 32-bit integer encodes a version number in |
| + * VMXNET3_DRIVER_VERSION_STRING. |
| + */ |
| +#define VMXNET3_DRIVER_VERSION_NUM 0x01020200 |
| |
| #if defined(CONFIG_PCI_MSI) |
| /* RSS only makes sense if MSI-X is supported. */ |