/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2015 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Linux NICS <linux.nics@intel.com>
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/ipv6.h>
#include <linux/if_bridge.h>
#ifdef NETIF_F_HW_VLAN_CTAG_TX
#include <linux/if_vlan.h>
#endif
#include "ixgbe.h"
#include "ixgbe_type.h"
#include "ixgbe_sriov.h"
#ifdef CONFIG_PCI_IOV
static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
int num_vf_macvlans, i;
struct vf_macvlans *mv_list;
adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED;
e_info(probe, "SR-IOV enabled with %d VFs\n", adapter->num_vfs);
/* Enable VMDq flag so device will be set in VM mode */
adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED;
if (!adapter->ring_feature[RING_F_VMDQ].limit)
adapter->ring_feature[RING_F_VMDQ].limit = 1;
adapter->ring_feature[RING_F_VMDQ].offset = adapter->num_vfs;
num_vf_macvlans = hw->mac.num_rar_entries -
(IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs);
adapter->mv_list = mv_list = kcalloc(num_vf_macvlans,
sizeof(struct vf_macvlans),
GFP_KERNEL);
if (mv_list) {
/* Initialize list of VF macvlans */
INIT_LIST_HEAD(&adapter->vf_mvs.l);
for (i = 0; i < num_vf_macvlans; i++) {
mv_list->vf = -1;
mv_list->free = true;
list_add(&mv_list->l, &adapter->vf_mvs.l);
mv_list++;
}
}
/* Initialize default switching mode VEB */
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
adapter->bridge_mode = BRIDGE_MODE_VEB;
/* If call to enable VFs succeeded then allocate memory
* for per VF control structures.
*/
adapter->vfinfo =
kcalloc(adapter->num_vfs,
sizeof(struct vf_data_storage), GFP_KERNEL);
if (adapter->vfinfo) {
/* limit trafffic classes based on VFs enabled */
if ((adapter->hw.mac.type == ixgbe_mac_82599EB) &&
(adapter->num_vfs < 16)) {
adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
} else if (adapter->num_vfs < 32) {
adapter->dcb_cfg.num_tcs.pg_tcs = 4;
adapter->dcb_cfg.num_tcs.pfc_tcs = 4;
} else {
adapter->dcb_cfg.num_tcs.pg_tcs = 1;
adapter->dcb_cfg.num_tcs.pfc_tcs = 1;
}
/* Disable RSC when in SR-IOV mode */
adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
IXGBE_FLAG2_RSC_ENABLED);
for (i = 0; i < adapter->num_vfs; i++) {
/* enable spoof checking for all VFs */
adapter->vfinfo[i].spoofchk_enabled = true;
/* We support VF RSS querying only for 82599 and x540
* devices at the moment. These devices share RSS
* indirection table and RSS hash key with PF therefore
* we want to disable the querying by default.
*/
adapter->vfinfo[i].rss_query_enabled = 0;
/* Untrust all VFs */
adapter->vfinfo[i].trusted = false;
/* set the default xcast mode */
adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE;
}
return 0;
}
return -ENOMEM;
}
/**
* ixgbe_get_vfs - Find and take references to all vf devices
* @adapter: Pointer to adapter struct
*/
static void ixgbe_get_vfs(struct ixgbe_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
u16 vendor = pdev->vendor;
struct pci_dev *vfdev;
int vf = 0;
u16 vf_id;
int pos;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
if (!pos)
return;
pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);
vfdev = pci_get_device(vendor, vf_id, NULL);
for (; vfdev; vfdev = pci_get_device(vendor, vf_id, vfdev)) {
if (!vfdev->is_virtfn)
continue;
if (vfdev->physfn != pdev)
continue;
if (vf >= adapter->num_vfs)
continue;
pci_dev_get(vfdev);
adapter->vfinfo[vf].vfdev = vfdev;
++vf;
}
}
/* Note this function is called when the user wants to enable SR-IOV
* VFs using the now deprecated module parameter
*/
void ixgbe_enable_sriov(struct ixgbe_adapter
|