diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igb/igb_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 312 |
1 files changed, 225 insertions, 87 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index c10cc716fde..ced544499f1 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -163,6 +163,12 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); static void igb_check_vf_rate_limit(struct igb_adapter *); +#ifdef CONFIG_PCI_IOV +static int igb_vf_configure(struct igb_adapter *adapter, int vf); +static int igb_find_enabled_vfs(struct igb_adapter *adapter); +static int igb_check_vf_assignment(struct igb_adapter *adapter); +#endif + #ifdef CONFIG_PM static int igb_suspend(struct pci_dev *, pm_message_t); static int igb_resume(struct pci_dev *); @@ -198,6 +204,7 @@ static struct pci_error_handlers igb_err_handler = { .resume = igb_io_resume, }; +static void igb_init_dmac(struct igb_adapter *adapter, u32 pba); static struct pci_driver igb_driver = { .name = igb_driver_name, @@ -1722,63 +1729,8 @@ void igb_reset(struct igb_adapter *adapter) if (hw->mac.ops.init_hw(hw)) dev_err(&pdev->dev, "Hardware Error\n"); - if (hw->mac.type > e1000_82580) { - if (adapter->flags & IGB_FLAG_DMAC) { - u32 reg; - - /* - * DMA Coalescing high water mark needs to be higher - * than * the * Rx threshold. The Rx threshold is - * currently * pba - 6, so we * should use a high water - * mark of pba * - 4. */ - hwm = (pba - 4) << 10; - - reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT) - & E1000_DMACR_DMACTHR_MASK); - - /* transition to L0x or L1 if available..*/ - reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); - - /* watchdog timer= +-1000 usec in 32usec intervals */ - reg |= (1000 >> 5); - wr32(E1000_DMACR, reg); - - /* no lower threshold to disable coalescing(smart fifb) - * -UTRESH=0*/ - wr32(E1000_DMCRTRH, 0); - /* set hwm to PBA - 2 * max frame size */ - wr32(E1000_FCRTC, hwm); - - /* - * This sets the time to wait before requesting tran- - * sition to * low power state to number of usecs needed - * to receive 1 512 * byte frame at gigabit line rate - */ - reg = rd32(E1000_DMCTLX); - reg |= IGB_DMCTLX_DCFLUSH_DIS; - - /* Delay 255 usec before entering Lx state. */ - reg |= 0xFF; - wr32(E1000_DMCTLX, reg); - - /* free space in Tx packet buffer to wake from DMAC */ - wr32(E1000_DMCTXTH, - (IGB_MIN_TXPBSIZE - - (IGB_TX_BUF_4096 + adapter->max_frame_size)) - >> 6); - - /* make low power state decision controlled by DMAC */ - reg = rd32(E1000_PCIEMISC); - reg |= E1000_PCIEMISC_LX_DECISION; - wr32(E1000_PCIEMISC, reg); - } /* end if IGB_FLAG_DMAC set */ - } - if (hw->mac.type == e1000_82580) { - u32 reg = rd32(E1000_PCIEMISC); - wr32(E1000_PCIEMISC, - reg & ~E1000_PCIEMISC_LX_DECISION); - } + igb_init_dmac(adapter, pba); if (!netif_running(adapter->netdev)) igb_power_down_link(adapter); @@ -2232,8 +2184,12 @@ static void __devexit igb_remove(struct pci_dev *pdev) /* reclaim resources allocated to VFs */ if (adapter->vf_data) { /* disable iov and allow time for transactions to clear */ - pci_disable_sriov(pdev); - msleep(500); + if (!igb_check_vf_assignment(adapter)) { + pci_disable_sriov(pdev); + msleep(500); + } else { + dev_info(&pdev->dev, "VF(s) assigned to guests!\n"); + } kfree(adapter->vf_data); adapter->vf_data = NULL; @@ -2250,6 +2206,7 @@ static void __devexit igb_remove(struct pci_dev *pdev) pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); + kfree(adapter->shadow_vfta); free_netdev(netdev); pci_disable_pcie_error_reporting(pdev); @@ -2270,42 +2227,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) { #ifdef CONFIG_PCI_IOV struct pci_dev *pdev = adapter->pdev; + int old_vfs = igb_find_enabled_vfs(adapter); + int i; - if (adapter->vfs_allocated_count) { - adapter->vf_data = kcalloc(adapter->vfs_allocated_count, - sizeof(struct vf_data_storage), - GFP_KERNEL); - /* if allocation failed then we do not support SR-IOV */ - if (!adapter->vf_data) { - adapter->vfs_allocated_count = 0; - dev_err(&pdev->dev, "Unable to allocate memory for VF " - "Data Storage\n"); - } + if (old_vfs) { + dev_info(&pdev->dev, "%d pre-allocated VFs found - override " + "max_vfs setting of %d\n", old_vfs, max_vfs); + adapter->vfs_allocated_count = old_vfs; } - if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) { - kfree(adapter->vf_data); - adapter->vf_data = NULL; -#endif /* CONFIG_PCI_IOV */ + if (!adapter->vfs_allocated_count) + return; + + adapter->vf_data = kcalloc(adapter->vfs_allocated_count, + sizeof(struct vf_data_storage), GFP_KERNEL); + /* if allocation failed then we do not support SR-IOV */ + if (!adapter->vf_data) { adapter->vfs_allocated_count = 0; -#ifdef CONFIG_PCI_IOV - } else { - unsigned char mac_addr[ETH_ALEN]; - int i; - dev_info(&pdev->dev, "%d vfs allocated\n", - adapter->vfs_allocated_count); - for (i = 0; i < adapter->vfs_allocated_count; i++) { - random_ether_addr(mac_addr); - igb_set_vf_mac(adapter, i, mac_addr); - } - /* DMA Coalescing is not supported in IOV mode. */ - if (adapter->flags & IGB_FLAG_DMAC) - adapter->flags &= ~IGB_FLAG_DMAC; + dev_err(&pdev->dev, "Unable to allocate memory for VF " + "Data Storage\n"); + goto out; } + + if (!old_vfs) { + if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) + goto err_out; + } + dev_info(&pdev->dev, "%d VFs allocated\n", + adapter->vfs_allocated_count); + for (i = 0; i < adapter->vfs_allocated_count; i++) + igb_vf_configure(adapter, i); + + /* DMA Coalescing is not supported in IOV mode. */ + adapter->flags &= ~IGB_FLAG_DMAC; + goto out; +err_out: + kfree(adapter->vf_data); + adapter->vf_data = NULL; + adapter->vfs_allocated_count = 0; +out: + return; #endif /* CONFIG_PCI_IOV */ } - /** * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp * @adapter: board private structure to initialize @@ -2475,6 +2439,11 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6))) adapter->flags |= IGB_FLAG_QUEUE_PAIRS; + /* Setup and initialize a copy of the hw vlan table array */ + adapter->shadow_vfta = kzalloc(sizeof(u32) * + E1000_VLAN_FILTER_TBL_SIZE, + GFP_ATOMIC); + /* This call may decrease the number of queues */ if (igb_init_interrupt_scheme(adapter)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); @@ -4254,7 +4223,7 @@ static void igb_tx_map(struct igb_ring *tx_ring, i = 0; } - size = frag->size; + size = skb_frag_size(frag); data_len -= size; dma = skb_frag_dma_map(tx_ring->dev, frag, 0, @@ -4917,6 +4886,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event, } #endif /* CONFIG_IGB_DCA */ +#ifdef CONFIG_PCI_IOV +static int igb_vf_configure(struct igb_adapter *adapter, int vf) +{ + unsigned char mac_addr[ETH_ALEN]; + struct pci_dev *pdev = adapter->pdev; + struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pvfdev; + unsigned int device_id; + u16 thisvf_devfn; + + random_ether_addr(mac_addr); + igb_set_vf_mac(adapter, vf, mac_addr); + + switch (adapter->hw.mac.type) { + case e1000_82576: + device_id = IGB_82576_VF_DEV_ID; + /* VF Stride for 82576 is 2 */ + thisvf_devfn = (pdev->devfn + 0x80 + (vf << 1)) | + (pdev->devfn & 1); + break; + case e1000_i350: + device_id = IGB_I350_VF_DEV_ID; + /* VF Stride for I350 is 4 */ + thisvf_devfn = (pdev->devfn + 0x80 + (vf << 2)) | + (pdev->devfn & 3); + break; + default: + device_id = 0; + thisvf_devfn = 0; + break; + } + + pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); + while (pvfdev) { + if (pvfdev->devfn == thisvf_devfn) + break; + pvfdev = pci_get_device(hw->vendor_id, + device_id, pvfdev); + } + + if (pvfdev) + adapter->vf_data[vf].vfdev = pvfdev; + else + dev_err(&pdev->dev, + "Couldn't find pci dev ptr for VF %4.4x\n", + thisvf_devfn); + return pvfdev != NULL; +} + +static int igb_find_enabled_vfs(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + struct pci_dev *pvfdev; + u16 vf_devfn = 0; + u16 vf_stride; + unsigned int device_id; + int vfs_found = 0; + + switch (adapter->hw.mac.type) { + case e1000_82576: + device_id = IGB_82576_VF_DEV_ID; + /* VF Stride for 82576 is 2 */ + vf_stride = 2; + break; + case e1000_i350: + device_id = IGB_I350_VF_DEV_ID; + /* VF Stride for I350 is 4 */ + vf_stride = 4; + break; + default: + device_id = 0; + vf_stride = 0; + break; + } + + vf_devfn = pdev->devfn + 0x80; + pvfdev = pci_get_device(hw->vendor_id, device_id, NULL); + while (pvfdev) { + if (pvfdev->devfn == vf_devfn) + vfs_found++; + vf_devfn += vf_stride; + pvfdev = pci_get_device(hw->vendor_id, + device_id, pvfdev); + } + + return vfs_found; +} + +static int igb_check_vf_assignment(struct igb_adapter *adapter) +{ + int i; + for (i = 0; i < adapter->vfs_allocated_count; i++) { + if (adapter->vf_data[i].vfdev) { + if (adapter->vf_data[i].vfdev->dev_flags & + PCI_DEV_FLAGS_ASSIGNED) + return true; + } + } + return false; +} + +#endif static void igb_ping_all_vfs(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; @@ -6978,4 +7050,70 @@ static void igb_vmm_control(struct igb_adapter *adapter) } } +static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) +{ + struct e1000_hw *hw = &adapter->hw; + u32 dmac_thr; + u16 hwm; + + if (hw->mac.type > e1000_82580) { + if (adapter->flags & IGB_FLAG_DMAC) { + u32 reg; + + /* force threshold to 0. */ + wr32(E1000_DMCTXTH, 0); + + /* + * DMA Coalescing high water mark needs to be higher + * than the RX threshold. set hwm to PBA - 2 * max + * frame size + */ + hwm = pba - (2 * adapter->max_frame_size); + reg = rd32(E1000_DMACR); + reg &= ~E1000_DMACR_DMACTHR_MASK; + dmac_thr = pba - 4; + + reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT) + & E1000_DMACR_DMACTHR_MASK); + + /* transition to L0x or L1 if available..*/ + reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); + + /* watchdog timer= +-1000 usec in 32usec intervals */ + reg |= (1000 >> 5); + wr32(E1000_DMACR, reg); + + /* + * no lower threshold to disable + * coalescing(smart fifb)-UTRESH=0 + */ + wr32(E1000_DMCRTRH, 0); + wr32(E1000_FCRTC, hwm); + + reg = (IGB_DMCTLX_DCFLUSH_DIS | 0x4); + + wr32(E1000_DMCTLX, reg); + + /* + * free space in tx packet buffer to wake from + * DMA coal + */ + wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE - + (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6); + + /* + * make low power state decision controlled + * by DMA coal + */ + reg = rd32(E1000_PCIEMISC); + reg &= ~E1000_PCIEMISC_LX_DECISION; + wr32(E1000_PCIEMISC, reg); + } /* endif adapter->dmac is not disabled */ + } else if (hw->mac.type == e1000_82580) { + u32 reg = rd32(E1000_PCIEMISC); + wr32(E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); + wr32(E1000_DMACR, 0); + } +} + /* igb_main.c */ |