18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/types.h> 58c2ecf20Sopenharmony_ci#include <linux/module.h> 68c2ecf20Sopenharmony_ci#include <linux/pci.h> 78c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 88c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 98c2ecf20Sopenharmony_ci#include <linux/string.h> 108c2ecf20Sopenharmony_ci#include <linux/in.h> 118c2ecf20Sopenharmony_ci#include <linux/ip.h> 128c2ecf20Sopenharmony_ci#include <linux/tcp.h> 138c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 148c2ecf20Sopenharmony_ci#include <linux/if_bridge.h> 158c2ecf20Sopenharmony_ci#ifdef NETIF_F_HW_VLAN_CTAG_TX 168c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "ixgbe.h" 208c2ecf20Sopenharmony_ci#include "ixgbe_type.h" 218c2ecf20Sopenharmony_ci#include "ixgbe_sriov.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 248c2ecf20Sopenharmony_cistatic inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter, 258c2ecf20Sopenharmony_ci unsigned int num_vfs) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 288c2ecf20Sopenharmony_ci struct vf_macvlans *mv_list; 298c2ecf20Sopenharmony_ci int num_vf_macvlans, i; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci /* Initialize list of VF macvlans */ 328c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&adapter->vf_mvs.l); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci num_vf_macvlans = hw->mac.num_rar_entries - 358c2ecf20Sopenharmony_ci (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs); 368c2ecf20Sopenharmony_ci if (!num_vf_macvlans) 378c2ecf20Sopenharmony_ci return; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci mv_list = kcalloc(num_vf_macvlans, sizeof(struct vf_macvlans), 408c2ecf20Sopenharmony_ci GFP_KERNEL); 418c2ecf20Sopenharmony_ci if (mv_list) { 428c2ecf20Sopenharmony_ci for (i = 0; i < num_vf_macvlans; i++) { 438c2ecf20Sopenharmony_ci mv_list[i].vf = -1; 448c2ecf20Sopenharmony_ci mv_list[i].free = true; 458c2ecf20Sopenharmony_ci list_add(&mv_list[i].l, &adapter->vf_mvs.l); 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci adapter->mv_list = mv_list; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter, 528c2ecf20Sopenharmony_ci unsigned int num_vfs) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 558c2ecf20Sopenharmony_ci int i; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci if (adapter->xdp_prog) { 588c2ecf20Sopenharmony_ci e_warn(probe, "SRIOV is not supported with XDP\n"); 598c2ecf20Sopenharmony_ci return -EINVAL; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* Enable VMDq flag so device will be set in VM mode */ 638c2ecf20Sopenharmony_ci adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED | 648c2ecf20Sopenharmony_ci IXGBE_FLAG_VMDQ_ENABLED; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Allocate memory for per VF control structures */ 678c2ecf20Sopenharmony_ci adapter->vfinfo = kcalloc(num_vfs, sizeof(struct vf_data_storage), 688c2ecf20Sopenharmony_ci GFP_KERNEL); 698c2ecf20Sopenharmony_ci if (!adapter->vfinfo) 708c2ecf20Sopenharmony_ci return -ENOMEM; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci adapter->num_vfs = num_vfs; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci ixgbe_alloc_vf_macvlans(adapter, num_vfs); 758c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].offset = num_vfs; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* Initialize default switching mode VEB */ 788c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); 798c2ecf20Sopenharmony_ci adapter->bridge_mode = BRIDGE_MODE_VEB; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* limit trafffic classes based on VFs enabled */ 828c2ecf20Sopenharmony_ci if ((adapter->hw.mac.type == ixgbe_mac_82599EB) && (num_vfs < 16)) { 838c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS; 848c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS; 858c2ecf20Sopenharmony_ci } else if (num_vfs < 32) { 868c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pg_tcs = 4; 878c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pfc_tcs = 4; 888c2ecf20Sopenharmony_ci } else { 898c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pg_tcs = 1; 908c2ecf20Sopenharmony_ci adapter->dcb_cfg.num_tcs.pfc_tcs = 1; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Disable RSC when in SR-IOV mode */ 948c2ecf20Sopenharmony_ci adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE | 958c2ecf20Sopenharmony_ci IXGBE_FLAG2_RSC_ENABLED); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci for (i = 0; i < num_vfs; i++) { 988c2ecf20Sopenharmony_ci /* enable spoof checking for all VFs */ 998c2ecf20Sopenharmony_ci adapter->vfinfo[i].spoofchk_enabled = true; 1008c2ecf20Sopenharmony_ci adapter->vfinfo[i].link_enable = true; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* We support VF RSS querying only for 82599 and x540 1038c2ecf20Sopenharmony_ci * devices at the moment. These devices share RSS 1048c2ecf20Sopenharmony_ci * indirection table and RSS hash key with PF therefore 1058c2ecf20Sopenharmony_ci * we want to disable the querying by default. 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci adapter->vfinfo[i].rss_query_enabled = false; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* Untrust all VFs */ 1108c2ecf20Sopenharmony_ci adapter->vfinfo[i].trusted = false; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* set the default xcast mode */ 1138c2ecf20Sopenharmony_ci adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci e_info(probe, "SR-IOV enabled with %d VFs\n", num_vfs); 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/** 1218c2ecf20Sopenharmony_ci * ixgbe_get_vfs - Find and take references to all vf devices 1228c2ecf20Sopenharmony_ci * @adapter: Pointer to adapter struct 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_cistatic void ixgbe_get_vfs(struct ixgbe_adapter *adapter) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 1278c2ecf20Sopenharmony_ci u16 vendor = pdev->vendor; 1288c2ecf20Sopenharmony_ci struct pci_dev *vfdev; 1298c2ecf20Sopenharmony_ci int vf = 0; 1308c2ecf20Sopenharmony_ci u16 vf_id; 1318c2ecf20Sopenharmony_ci int pos; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); 1348c2ecf20Sopenharmony_ci if (!pos) 1358c2ecf20Sopenharmony_ci return; 1368c2ecf20Sopenharmony_ci pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci vfdev = pci_get_device(vendor, vf_id, NULL); 1398c2ecf20Sopenharmony_ci for (; vfdev; vfdev = pci_get_device(vendor, vf_id, vfdev)) { 1408c2ecf20Sopenharmony_ci if (!vfdev->is_virtfn) 1418c2ecf20Sopenharmony_ci continue; 1428c2ecf20Sopenharmony_ci if (vfdev->physfn != pdev) 1438c2ecf20Sopenharmony_ci continue; 1448c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 1458c2ecf20Sopenharmony_ci continue; 1468c2ecf20Sopenharmony_ci pci_dev_get(vfdev); 1478c2ecf20Sopenharmony_ci adapter->vfinfo[vf].vfdev = vfdev; 1488c2ecf20Sopenharmony_ci ++vf; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci/* Note this function is called when the user wants to enable SR-IOV 1538c2ecf20Sopenharmony_ci * VFs using the now deprecated module parameter 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_civoid ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci int pre_existing_vfs = 0; 1588c2ecf20Sopenharmony_ci unsigned int num_vfs; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci pre_existing_vfs = pci_num_vf(adapter->pdev); 1618c2ecf20Sopenharmony_ci if (!pre_existing_vfs && !max_vfs) 1628c2ecf20Sopenharmony_ci return; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* If there are pre-existing VFs then we have to force 1658c2ecf20Sopenharmony_ci * use of that many - over ride any module parameter value. 1668c2ecf20Sopenharmony_ci * This may result from the user unloading the PF driver 1678c2ecf20Sopenharmony_ci * while VFs were assigned to guest VMs or because the VFs 1688c2ecf20Sopenharmony_ci * have been created via the new PCI SR-IOV sysfs interface. 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci if (pre_existing_vfs) { 1718c2ecf20Sopenharmony_ci num_vfs = pre_existing_vfs; 1728c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 1738c2ecf20Sopenharmony_ci "Virtual Functions already enabled for this device - Please reload all VF drivers to avoid spoofed packet errors\n"); 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci int err; 1768c2ecf20Sopenharmony_ci /* 1778c2ecf20Sopenharmony_ci * The 82599 supports up to 64 VFs per physical function 1788c2ecf20Sopenharmony_ci * but this implementation limits allocation to 63 so that 1798c2ecf20Sopenharmony_ci * basic networking resources are still available to the 1808c2ecf20Sopenharmony_ci * physical function. If the user requests greater than 1818c2ecf20Sopenharmony_ci * 63 VFs then it is an error - reset to default of zero. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci num_vfs = min_t(unsigned int, max_vfs, IXGBE_MAX_VFS_DRV_LIMIT); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci err = pci_enable_sriov(adapter->pdev, num_vfs); 1868c2ecf20Sopenharmony_ci if (err) { 1878c2ecf20Sopenharmony_ci e_err(probe, "Failed to enable PCI sriov: %d\n", err); 1888c2ecf20Sopenharmony_ci return; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (!__ixgbe_enable_sriov(adapter, num_vfs)) { 1938c2ecf20Sopenharmony_ci ixgbe_get_vfs(adapter); 1948c2ecf20Sopenharmony_ci return; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* If we have gotten to this point then there is no memory available 1988c2ecf20Sopenharmony_ci * to manage the VF devices - print message and bail. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci e_err(probe, "Unable to allocate memory for VF Data Storage - " 2018c2ecf20Sopenharmony_ci "SRIOV disabled\n"); 2028c2ecf20Sopenharmony_ci ixgbe_disable_sriov(adapter); 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#endif /* #ifdef CONFIG_PCI_IOV */ 2068c2ecf20Sopenharmony_ciint ixgbe_disable_sriov(struct ixgbe_adapter *adapter) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci unsigned int num_vfs = adapter->num_vfs, vf; 2098c2ecf20Sopenharmony_ci unsigned long flags; 2108c2ecf20Sopenharmony_ci int rss; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 2138c2ecf20Sopenharmony_ci /* set num VFs to 0 to prevent access to vfinfo */ 2148c2ecf20Sopenharmony_ci adapter->num_vfs = 0; 2158c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* put the reference to all of the vf devices */ 2188c2ecf20Sopenharmony_ci for (vf = 0; vf < num_vfs; ++vf) { 2198c2ecf20Sopenharmony_ci struct pci_dev *vfdev = adapter->vfinfo[vf].vfdev; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!vfdev) 2228c2ecf20Sopenharmony_ci continue; 2238c2ecf20Sopenharmony_ci adapter->vfinfo[vf].vfdev = NULL; 2248c2ecf20Sopenharmony_ci pci_dev_put(vfdev); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* free VF control structures */ 2288c2ecf20Sopenharmony_ci kfree(adapter->vfinfo); 2298c2ecf20Sopenharmony_ci adapter->vfinfo = NULL; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* free macvlan list */ 2328c2ecf20Sopenharmony_ci kfree(adapter->mv_list); 2338c2ecf20Sopenharmony_ci adapter->mv_list = NULL; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* if SR-IOV is already disabled then there is nothing to do */ 2368c2ecf20Sopenharmony_ci if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) 2378c2ecf20Sopenharmony_ci return 0; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * If our VFs are assigned we cannot shut down SR-IOV 2428c2ecf20Sopenharmony_ci * without causing issues, so just leave the hardware 2438c2ecf20Sopenharmony_ci * available but disabled 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci if (pci_vfs_assigned(adapter->pdev)) { 2468c2ecf20Sopenharmony_ci e_dev_warn("Unloading driver while VFs are assigned - VFs will not be deallocated\n"); 2478c2ecf20Sopenharmony_ci return -EPERM; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci /* disable iov and allow time for transactions to clear */ 2508c2ecf20Sopenharmony_ci pci_disable_sriov(adapter->pdev); 2518c2ecf20Sopenharmony_ci#endif 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Disable VMDq flag so device will be set in VM mode */ 2548c2ecf20Sopenharmony_ci if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) { 2558c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED; 2568c2ecf20Sopenharmony_ci adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; 2578c2ecf20Sopenharmony_ci rss = min_t(int, ixgbe_max_rss_indices(adapter), 2588c2ecf20Sopenharmony_ci num_online_cpus()); 2598c2ecf20Sopenharmony_ci } else { 2608c2ecf20Sopenharmony_ci rss = min_t(int, IXGBE_MAX_L2A_QUEUES, num_online_cpus()); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_VMDQ].offset = 0; 2648c2ecf20Sopenharmony_ci adapter->ring_feature[RING_F_RSS].limit = rss; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* take a breather then clean up driver data */ 2678c2ecf20Sopenharmony_ci msleep(100); 2688c2ecf20Sopenharmony_ci return 0; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 2748c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = pci_get_drvdata(dev); 2758c2ecf20Sopenharmony_ci int pre_existing_vfs = pci_num_vf(dev); 2768c2ecf20Sopenharmony_ci int err = 0, num_rx_pools, i, limit; 2778c2ecf20Sopenharmony_ci u8 num_tc; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (pre_existing_vfs && pre_existing_vfs != num_vfs) 2808c2ecf20Sopenharmony_ci err = ixgbe_disable_sriov(adapter); 2818c2ecf20Sopenharmony_ci else if (pre_existing_vfs && pre_existing_vfs == num_vfs) 2828c2ecf20Sopenharmony_ci return num_vfs; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (err) 2858c2ecf20Sopenharmony_ci return err; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* While the SR-IOV capability structure reports total VFs to be 64, 2888c2ecf20Sopenharmony_ci * we limit the actual number allocated as below based on two factors. 2898c2ecf20Sopenharmony_ci * Num_TCs MAX_VFs 2908c2ecf20Sopenharmony_ci * 1 63 2918c2ecf20Sopenharmony_ci * <=4 31 2928c2ecf20Sopenharmony_ci * >4 15 2938c2ecf20Sopenharmony_ci * First, we reserve some transmit/receive resources for the PF. 2948c2ecf20Sopenharmony_ci * Second, VMDQ also uses the same pools that SR-IOV does. We need to 2958c2ecf20Sopenharmony_ci * account for this, so that we don't accidentally allocate more VFs 2968c2ecf20Sopenharmony_ci * than we have available pools. The PCI bus driver already checks for 2978c2ecf20Sopenharmony_ci * other values out of range. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci num_tc = adapter->hw_tcs; 3008c2ecf20Sopenharmony_ci num_rx_pools = bitmap_weight(adapter->fwd_bitmask, 3018c2ecf20Sopenharmony_ci adapter->num_rx_pools); 3028c2ecf20Sopenharmony_ci limit = (num_tc > 4) ? IXGBE_MAX_VFS_8TC : 3038c2ecf20Sopenharmony_ci (num_tc > 1) ? IXGBE_MAX_VFS_4TC : IXGBE_MAX_VFS_1TC; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (num_vfs > (limit - num_rx_pools)) { 3068c2ecf20Sopenharmony_ci e_dev_err("Currently configured with %d TCs, and %d offloaded macvlans. Creating more than %d VFs is not allowed\n", 3078c2ecf20Sopenharmony_ci num_tc, num_rx_pools - 1, limit - num_rx_pools); 3088c2ecf20Sopenharmony_ci return -EPERM; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci err = __ixgbe_enable_sriov(adapter, num_vfs); 3128c2ecf20Sopenharmony_ci if (err) 3138c2ecf20Sopenharmony_ci return err; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci for (i = 0; i < num_vfs; i++) 3168c2ecf20Sopenharmony_ci ixgbe_vf_configuration(dev, (i | 0x10000000)); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* reset before enabling SRIOV to avoid mailbox issues */ 3198c2ecf20Sopenharmony_ci ixgbe_sriov_reinit(adapter); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci err = pci_enable_sriov(dev, num_vfs); 3228c2ecf20Sopenharmony_ci if (err) { 3238c2ecf20Sopenharmony_ci e_dev_warn("Failed to enable PCI sriov: %d\n", err); 3248c2ecf20Sopenharmony_ci return err; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci ixgbe_get_vfs(adapter); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return num_vfs; 3298c2ecf20Sopenharmony_ci#else 3308c2ecf20Sopenharmony_ci return 0; 3318c2ecf20Sopenharmony_ci#endif 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic int ixgbe_pci_sriov_disable(struct pci_dev *dev) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = pci_get_drvdata(dev); 3378c2ecf20Sopenharmony_ci int err; 3388c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 3398c2ecf20Sopenharmony_ci u32 current_flags = adapter->flags; 3408c2ecf20Sopenharmony_ci int prev_num_vf = pci_num_vf(dev); 3418c2ecf20Sopenharmony_ci#endif 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci err = ixgbe_disable_sriov(adapter); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* Only reinit if no error and state changed */ 3468c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 3478c2ecf20Sopenharmony_ci if (!err && (current_flags != adapter->flags || 3488c2ecf20Sopenharmony_ci prev_num_vf != pci_num_vf(dev))) 3498c2ecf20Sopenharmony_ci ixgbe_sriov_reinit(adapter); 3508c2ecf20Sopenharmony_ci#endif 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return err; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ciint ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci if (num_vfs == 0) 3588c2ecf20Sopenharmony_ci return ixgbe_pci_sriov_disable(dev); 3598c2ecf20Sopenharmony_ci else 3608c2ecf20Sopenharmony_ci return ixgbe_pci_sriov_enable(dev, num_vfs); 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, 3648c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) 3678c2ecf20Sopenharmony_ci >> IXGBE_VT_MSGINFO_SHIFT; 3688c2ecf20Sopenharmony_ci u16 *hash_list = (u16 *)&msgbuf[1]; 3698c2ecf20Sopenharmony_ci struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; 3708c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 3718c2ecf20Sopenharmony_ci int i; 3728c2ecf20Sopenharmony_ci u32 vector_bit; 3738c2ecf20Sopenharmony_ci u32 vector_reg; 3748c2ecf20Sopenharmony_ci u32 mta_reg; 3758c2ecf20Sopenharmony_ci u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* only so many hash values supported */ 3788c2ecf20Sopenharmony_ci entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* 3818c2ecf20Sopenharmony_ci * salt away the number of multi cast addresses assigned 3828c2ecf20Sopenharmony_ci * to this VF for later use to restore when the PF multi cast 3838c2ecf20Sopenharmony_ci * list changes 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_ci vfinfo->num_vf_mc_hashes = entries; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* 3888c2ecf20Sopenharmony_ci * VFs are limited to using the MTA hash table for their multicast 3898c2ecf20Sopenharmony_ci * addresses 3908c2ecf20Sopenharmony_ci */ 3918c2ecf20Sopenharmony_ci for (i = 0; i < entries; i++) { 3928c2ecf20Sopenharmony_ci vfinfo->vf_mc_hashes[i] = hash_list[i]; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { 3968c2ecf20Sopenharmony_ci vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; 3978c2ecf20Sopenharmony_ci vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; 3988c2ecf20Sopenharmony_ci mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); 3998c2ecf20Sopenharmony_ci mta_reg |= BIT(vector_bit); 4008c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci vmolr |= IXGBE_VMOLR_ROMPE; 4038c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci return 0; 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 4098c2ecf20Sopenharmony_civoid ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 4128c2ecf20Sopenharmony_ci struct vf_data_storage *vfinfo; 4138c2ecf20Sopenharmony_ci int i, j; 4148c2ecf20Sopenharmony_ci u32 vector_bit; 4158c2ecf20Sopenharmony_ci u32 vector_reg; 4168c2ecf20Sopenharmony_ci u32 mta_reg; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_vfs; i++) { 4198c2ecf20Sopenharmony_ci u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(i)); 4208c2ecf20Sopenharmony_ci vfinfo = &adapter->vfinfo[i]; 4218c2ecf20Sopenharmony_ci for (j = 0; j < vfinfo->num_vf_mc_hashes; j++) { 4228c2ecf20Sopenharmony_ci hw->addr_ctrl.mta_in_use++; 4238c2ecf20Sopenharmony_ci vector_reg = (vfinfo->vf_mc_hashes[j] >> 5) & 0x7F; 4248c2ecf20Sopenharmony_ci vector_bit = vfinfo->vf_mc_hashes[j] & 0x1F; 4258c2ecf20Sopenharmony_ci mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); 4268c2ecf20Sopenharmony_ci mta_reg |= BIT(vector_bit); 4278c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (vfinfo->num_vf_mc_hashes) 4318c2ecf20Sopenharmony_ci vmolr |= IXGBE_VMOLR_ROMPE; 4328c2ecf20Sopenharmony_ci else 4338c2ecf20Sopenharmony_ci vmolr &= ~IXGBE_VMOLR_ROMPE; 4348c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMOLR(i), vmolr); 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* Restore any VF macvlans */ 4388c2ecf20Sopenharmony_ci ixgbe_full_sync_mac_table(adapter); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci#endif 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, 4438c2ecf20Sopenharmony_ci u32 vf) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 4468c2ecf20Sopenharmony_ci int err; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci /* If VLAN overlaps with one the PF is currently monitoring make 4498c2ecf20Sopenharmony_ci * sure that we are able to allocate a VLVF entry. This may be 4508c2ecf20Sopenharmony_ci * redundant but it guarantees PF will maintain visibility to 4518c2ecf20Sopenharmony_ci * the VLAN. 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_ci if (add && test_bit(vid, adapter->active_vlans)) { 4548c2ecf20Sopenharmony_ci err = hw->mac.ops.set_vfta(hw, vid, VMDQ_P(0), true, false); 4558c2ecf20Sopenharmony_ci if (err) 4568c2ecf20Sopenharmony_ci return err; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci err = hw->mac.ops.set_vfta(hw, vid, vf, !!add, false); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (add && !err) 4628c2ecf20Sopenharmony_ci return err; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* If we failed to add the VF VLAN or we are removing the VF VLAN 4658c2ecf20Sopenharmony_ci * we may need to drop the PF pool bit in order to allow us to free 4668c2ecf20Sopenharmony_ci * up the VLVF resources. 4678c2ecf20Sopenharmony_ci */ 4688c2ecf20Sopenharmony_ci if (test_bit(vid, adapter->active_vlans) || 4698c2ecf20Sopenharmony_ci (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)) 4708c2ecf20Sopenharmony_ci ixgbe_update_pf_promisc_vlvf(adapter, vid); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci return err; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 max_frame, u32 vf) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 4788c2ecf20Sopenharmony_ci u32 max_frs; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (max_frame < ETH_MIN_MTU || max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) { 4818c2ecf20Sopenharmony_ci e_err(drv, "VF max_frame %d out of range\n", max_frame); 4828c2ecf20Sopenharmony_ci return -EINVAL; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* 4868c2ecf20Sopenharmony_ci * For 82599EB we have to keep all PFs and VFs operating with 4878c2ecf20Sopenharmony_ci * the same max_frame value in order to avoid sending an oversize 4888c2ecf20Sopenharmony_ci * frame to a VF. In order to guarantee this is handled correctly 4898c2ecf20Sopenharmony_ci * for all cases we have several special exceptions to take into 4908c2ecf20Sopenharmony_ci * account before we can enable the VF for receive 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82599EB) { 4938c2ecf20Sopenharmony_ci struct net_device *dev = adapter->netdev; 4948c2ecf20Sopenharmony_ci int pf_max_frame = dev->mtu + ETH_HLEN; 4958c2ecf20Sopenharmony_ci u32 reg_offset, vf_shift, vfre; 4968c2ecf20Sopenharmony_ci s32 err = 0; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci#ifdef CONFIG_FCOE 4998c2ecf20Sopenharmony_ci if (dev->features & NETIF_F_FCOE_MTU) 5008c2ecf20Sopenharmony_ci pf_max_frame = max_t(int, pf_max_frame, 5018c2ecf20Sopenharmony_ci IXGBE_FCOE_JUMBO_FRAME_SIZE); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci#endif /* CONFIG_FCOE */ 5048c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 5058c2ecf20Sopenharmony_ci case ixgbe_mbox_api_11: 5068c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 5078c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 5088c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 5098c2ecf20Sopenharmony_ci /* Version 1.1 supports jumbo frames on VFs if PF has 5108c2ecf20Sopenharmony_ci * jumbo frames enabled which means legacy VFs are 5118c2ecf20Sopenharmony_ci * disabled 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_ci if (pf_max_frame > ETH_FRAME_LEN) 5148c2ecf20Sopenharmony_ci break; 5158c2ecf20Sopenharmony_ci fallthrough; 5168c2ecf20Sopenharmony_ci default: 5178c2ecf20Sopenharmony_ci /* If the PF or VF are running w/ jumbo frames enabled 5188c2ecf20Sopenharmony_ci * we need to shut down the VF Rx path as we cannot 5198c2ecf20Sopenharmony_ci * support jumbo frames on legacy VFs 5208c2ecf20Sopenharmony_ci */ 5218c2ecf20Sopenharmony_ci if ((pf_max_frame > ETH_FRAME_LEN) || 5228c2ecf20Sopenharmony_ci (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN))) 5238c2ecf20Sopenharmony_ci err = -EINVAL; 5248c2ecf20Sopenharmony_ci break; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* determine VF receive enable location */ 5288c2ecf20Sopenharmony_ci vf_shift = vf % 32; 5298c2ecf20Sopenharmony_ci reg_offset = vf / 32; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci /* enable or disable receive depending on error */ 5328c2ecf20Sopenharmony_ci vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); 5338c2ecf20Sopenharmony_ci if (err) 5348c2ecf20Sopenharmony_ci vfre &= ~BIT(vf_shift); 5358c2ecf20Sopenharmony_ci else 5368c2ecf20Sopenharmony_ci vfre |= BIT(vf_shift); 5378c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci if (err) { 5408c2ecf20Sopenharmony_ci e_err(drv, "VF max_frame %d out of range\n", max_frame); 5418c2ecf20Sopenharmony_ci return err; 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* pull current max frame size from hardware */ 5468c2ecf20Sopenharmony_ci max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS); 5478c2ecf20Sopenharmony_ci max_frs &= IXGBE_MHADD_MFS_MASK; 5488c2ecf20Sopenharmony_ci max_frs >>= IXGBE_MHADD_MFS_SHIFT; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (max_frs < max_frame) { 5518c2ecf20Sopenharmony_ci max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT; 5528c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci e_info(hw, "VF requests change max MTU to %d\n", max_frame); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci return 0; 5588c2ecf20Sopenharmony_ci} 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_cistatic void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); 5638c2ecf20Sopenharmony_ci vmolr |= IXGBE_VMOLR_BAM; 5648c2ecf20Sopenharmony_ci if (aupe) 5658c2ecf20Sopenharmony_ci vmolr |= IXGBE_VMOLR_AUPE; 5668c2ecf20Sopenharmony_ci else 5678c2ecf20Sopenharmony_ci vmolr &= ~IXGBE_VMOLR_AUPE; 5688c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 5818c2ecf20Sopenharmony_ci u32 vlvfb_mask, pool_mask, i; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* create mask for VF and other pools */ 5848c2ecf20Sopenharmony_ci pool_mask = ~BIT(VMDQ_P(0) % 32); 5858c2ecf20Sopenharmony_ci vlvfb_mask = BIT(vf % 32); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci /* post increment loop, covers VLVF_ENTRIES - 1 to 0 */ 5888c2ecf20Sopenharmony_ci for (i = IXGBE_VLVF_ENTRIES; i--;) { 5898c2ecf20Sopenharmony_ci u32 bits[2], vlvfb, vid, vfta, vlvf; 5908c2ecf20Sopenharmony_ci u32 word = i * 2 + vf / 32; 5918c2ecf20Sopenharmony_ci u32 mask; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci vlvfb = IXGBE_READ_REG(hw, IXGBE_VLVFB(word)); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci /* if our bit isn't set we can skip it */ 5968c2ecf20Sopenharmony_ci if (!(vlvfb & vlvfb_mask)) 5978c2ecf20Sopenharmony_ci continue; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* clear our bit from vlvfb */ 6008c2ecf20Sopenharmony_ci vlvfb ^= vlvfb_mask; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci /* create 64b mask to chedk to see if we should clear VLVF */ 6038c2ecf20Sopenharmony_ci bits[word % 2] = vlvfb; 6048c2ecf20Sopenharmony_ci bits[~word % 2] = IXGBE_READ_REG(hw, IXGBE_VLVFB(word ^ 1)); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci /* if other pools are present, just remove ourselves */ 6078c2ecf20Sopenharmony_ci if (bits[(VMDQ_P(0) / 32) ^ 1] || 6088c2ecf20Sopenharmony_ci (bits[VMDQ_P(0) / 32] & pool_mask)) 6098c2ecf20Sopenharmony_ci goto update_vlvfb; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* if PF is present, leave VFTA */ 6128c2ecf20Sopenharmony_ci if (bits[0] || bits[1]) 6138c2ecf20Sopenharmony_ci goto update_vlvf; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* if we cannot determine VLAN just remove ourselves */ 6168c2ecf20Sopenharmony_ci vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(i)); 6178c2ecf20Sopenharmony_ci if (!vlvf) 6188c2ecf20Sopenharmony_ci goto update_vlvfb; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci vid = vlvf & VLAN_VID_MASK; 6218c2ecf20Sopenharmony_ci mask = BIT(vid % 32); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* clear bit from VFTA */ 6248c2ecf20Sopenharmony_ci vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(vid / 32)); 6258c2ecf20Sopenharmony_ci if (vfta & mask) 6268c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTA(vid / 32), vfta ^ mask); 6278c2ecf20Sopenharmony_ciupdate_vlvf: 6288c2ecf20Sopenharmony_ci /* clear POOL selection enable */ 6298c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), 0); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (!(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)) 6328c2ecf20Sopenharmony_ci vlvfb = 0; 6338c2ecf20Sopenharmony_ciupdate_vlvfb: 6348c2ecf20Sopenharmony_ci /* clear pool bits */ 6358c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VLVFB(word), vlvfb); 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, 6408c2ecf20Sopenharmony_ci int vf, int index, unsigned char *mac_addr) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct vf_macvlans *entry; 6438c2ecf20Sopenharmony_ci struct list_head *pos; 6448c2ecf20Sopenharmony_ci int retval = 0; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci if (index <= 1) { 6478c2ecf20Sopenharmony_ci list_for_each(pos, &adapter->vf_mvs.l) { 6488c2ecf20Sopenharmony_ci entry = list_entry(pos, struct vf_macvlans, l); 6498c2ecf20Sopenharmony_ci if (entry->vf == vf) { 6508c2ecf20Sopenharmony_ci entry->vf = -1; 6518c2ecf20Sopenharmony_ci entry->free = true; 6528c2ecf20Sopenharmony_ci entry->is_macvlan = false; 6538c2ecf20Sopenharmony_ci ixgbe_del_mac_filter(adapter, 6548c2ecf20Sopenharmony_ci entry->vf_macvlan, vf); 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* 6608c2ecf20Sopenharmony_ci * If index was zero then we were asked to clear the uc list 6618c2ecf20Sopenharmony_ci * for the VF. We're done. 6628c2ecf20Sopenharmony_ci */ 6638c2ecf20Sopenharmony_ci if (!index) 6648c2ecf20Sopenharmony_ci return 0; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci entry = NULL; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci list_for_each(pos, &adapter->vf_mvs.l) { 6698c2ecf20Sopenharmony_ci entry = list_entry(pos, struct vf_macvlans, l); 6708c2ecf20Sopenharmony_ci if (entry->free) 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci /* 6758c2ecf20Sopenharmony_ci * If we traversed the entire list and didn't find a free entry 6768c2ecf20Sopenharmony_ci * then we're out of space on the RAR table. Also entry may 6778c2ecf20Sopenharmony_ci * be NULL because the original memory allocation for the list 6788c2ecf20Sopenharmony_ci * failed, which is not fatal but does mean we can't support 6798c2ecf20Sopenharmony_ci * VF requests for MACVLAN because we couldn't allocate 6808c2ecf20Sopenharmony_ci * memory for the list management required. 6818c2ecf20Sopenharmony_ci */ 6828c2ecf20Sopenharmony_ci if (!entry || !entry->free) 6838c2ecf20Sopenharmony_ci return -ENOSPC; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci retval = ixgbe_add_mac_filter(adapter, mac_addr, vf); 6868c2ecf20Sopenharmony_ci if (retval < 0) 6878c2ecf20Sopenharmony_ci return retval; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci entry->free = false; 6908c2ecf20Sopenharmony_ci entry->is_macvlan = true; 6918c2ecf20Sopenharmony_ci entry->vf = vf; 6928c2ecf20Sopenharmony_ci memcpy(entry->vf_macvlan, mac_addr, ETH_ALEN); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_cistatic inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 7008c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 7018c2ecf20Sopenharmony_ci struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; 7028c2ecf20Sopenharmony_ci u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); 7038c2ecf20Sopenharmony_ci u8 num_tcs = adapter->hw_tcs; 7048c2ecf20Sopenharmony_ci u32 reg_val; 7058c2ecf20Sopenharmony_ci u32 queue; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci /* remove VLAN filters beloning to this VF */ 7088c2ecf20Sopenharmony_ci ixgbe_clear_vf_vlans(adapter, vf); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci /* add back PF assigned VLAN or VLAN 0 */ 7118c2ecf20Sopenharmony_ci ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci /* reset offloads to defaults */ 7148c2ecf20Sopenharmony_ci ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci /* set outgoing tags for VFs */ 7178c2ecf20Sopenharmony_ci if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) { 7188c2ecf20Sopenharmony_ci ixgbe_clear_vmvir(adapter, vf); 7198c2ecf20Sopenharmony_ci } else { 7208c2ecf20Sopenharmony_ci if (vfinfo->pf_qos || !num_tcs) 7218c2ecf20Sopenharmony_ci ixgbe_set_vmvir(adapter, vfinfo->pf_vlan, 7228c2ecf20Sopenharmony_ci vfinfo->pf_qos, vf); 7238c2ecf20Sopenharmony_ci else 7248c2ecf20Sopenharmony_ci ixgbe_set_vmvir(adapter, vfinfo->pf_vlan, 7258c2ecf20Sopenharmony_ci adapter->default_up, vf); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci if (vfinfo->spoofchk_enabled) { 7288c2ecf20Sopenharmony_ci hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); 7298c2ecf20Sopenharmony_ci hw->mac.ops.set_mac_anti_spoofing(hw, true, vf); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /* reset multicast table array for vf */ 7348c2ecf20Sopenharmony_ci adapter->vfinfo[vf].num_vf_mc_hashes = 0; 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci /* clear any ipsec table info */ 7378c2ecf20Sopenharmony_ci ixgbe_ipsec_vf_clear(adapter, vf); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* Flush and reset the mta with the new values */ 7408c2ecf20Sopenharmony_ci ixgbe_set_rx_mode(adapter->netdev); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf); 7438c2ecf20Sopenharmony_ci ixgbe_set_vf_macvlan(adapter, vf, 0, NULL); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* reset VF api back to unknown */ 7468c2ecf20Sopenharmony_ci adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* Restart each queue for given VF */ 7498c2ecf20Sopenharmony_ci for (queue = 0; queue < q_per_pool; queue++) { 7508c2ecf20Sopenharmony_ci unsigned int reg_idx = (vf * q_per_pool) + queue; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci reg_val = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(reg_idx)); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci /* Re-enabling only configured queues */ 7558c2ecf20Sopenharmony_ci if (reg_val) { 7568c2ecf20Sopenharmony_ci reg_val |= IXGBE_TXDCTL_ENABLE; 7578c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(reg_idx), reg_val); 7588c2ecf20Sopenharmony_ci reg_val &= ~IXGBE_TXDCTL_ENABLE; 7598c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(reg_idx), reg_val); 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_cistatic void ixgbe_vf_clear_mbx(struct ixgbe_adapter *adapter, u32 vf) 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 7698c2ecf20Sopenharmony_ci u32 word; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci /* Clear VF's mailbox memory */ 7728c2ecf20Sopenharmony_ci for (word = 0; word < IXGBE_VFMAILBOX_SIZE; word++) 7738c2ecf20Sopenharmony_ci IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf), word, 0); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, 7798c2ecf20Sopenharmony_ci int vf, unsigned char *mac_addr) 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci s32 retval; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf); 7848c2ecf20Sopenharmony_ci retval = ixgbe_add_mac_filter(adapter, mac_addr, vf); 7858c2ecf20Sopenharmony_ci if (retval >= 0) 7868c2ecf20Sopenharmony_ci memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, 7878c2ecf20Sopenharmony_ci ETH_ALEN); 7888c2ecf20Sopenharmony_ci else 7898c2ecf20Sopenharmony_ci eth_zero_addr(adapter->vfinfo[vf].vf_mac_addresses); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci return retval; 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ciint ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); 7978c2ecf20Sopenharmony_ci unsigned int vfn = (event_mask & 0x3f); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci bool enable = ((event_mask & 0x10000000U) != 0); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (enable) 8028c2ecf20Sopenharmony_ci eth_zero_addr(adapter->vfinfo[vfn].vf_mac_addresses); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci return 0; 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic inline void ixgbe_write_qde(struct ixgbe_adapter *adapter, u32 vf, 8088c2ecf20Sopenharmony_ci u32 qde) 8098c2ecf20Sopenharmony_ci{ 8108c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 8118c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 8128c2ecf20Sopenharmony_ci u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); 8138c2ecf20Sopenharmony_ci int i; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci for (i = vf * q_per_pool; i < ((vf + 1) * q_per_pool); i++) { 8168c2ecf20Sopenharmony_ci u32 reg; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci /* flush previous write */ 8198c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci /* indicate to hardware that we want to set drop enable */ 8228c2ecf20Sopenharmony_ci reg = IXGBE_QDE_WRITE | qde; 8238c2ecf20Sopenharmony_ci reg |= i << IXGBE_QDE_IDX_SHIFT; 8248c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_QDE, reg); 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci} 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci/** 8298c2ecf20Sopenharmony_ci * ixgbe_set_vf_rx_tx - Set VF rx tx 8308c2ecf20Sopenharmony_ci * @adapter: Pointer to adapter struct 8318c2ecf20Sopenharmony_ci * @vf: VF identifier 8328c2ecf20Sopenharmony_ci * 8338c2ecf20Sopenharmony_ci * Set or reset correct transmit and receive for vf 8348c2ecf20Sopenharmony_ci **/ 8358c2ecf20Sopenharmony_cistatic void ixgbe_set_vf_rx_tx(struct ixgbe_adapter *adapter, int vf) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci u32 reg_cur_tx, reg_cur_rx, reg_req_tx, reg_req_rx; 8388c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 8398c2ecf20Sopenharmony_ci u32 reg_offset, vf_shift; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci vf_shift = vf % 32; 8428c2ecf20Sopenharmony_ci reg_offset = vf / 32; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci reg_cur_tx = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset)); 8458c2ecf20Sopenharmony_ci reg_cur_rx = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].link_enable) { 8488c2ecf20Sopenharmony_ci reg_req_tx = reg_cur_tx | 1 << vf_shift; 8498c2ecf20Sopenharmony_ci reg_req_rx = reg_cur_rx | 1 << vf_shift; 8508c2ecf20Sopenharmony_ci } else { 8518c2ecf20Sopenharmony_ci reg_req_tx = reg_cur_tx & ~(1 << vf_shift); 8528c2ecf20Sopenharmony_ci reg_req_rx = reg_cur_rx & ~(1 << vf_shift); 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs. 8568c2ecf20Sopenharmony_ci * For more info take a look at ixgbe_set_vf_lpe 8578c2ecf20Sopenharmony_ci */ 8588c2ecf20Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82599EB) { 8598c2ecf20Sopenharmony_ci struct net_device *dev = adapter->netdev; 8608c2ecf20Sopenharmony_ci int pf_max_frame = dev->mtu + ETH_HLEN; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_FCOE) 8638c2ecf20Sopenharmony_ci if (dev->features & NETIF_F_FCOE_MTU) 8648c2ecf20Sopenharmony_ci pf_max_frame = max_t(int, pf_max_frame, 8658c2ecf20Sopenharmony_ci IXGBE_FCOE_JUMBO_FRAME_SIZE); 8668c2ecf20Sopenharmony_ci#endif /* CONFIG_FCOE */ 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci if (pf_max_frame > ETH_FRAME_LEN) 8698c2ecf20Sopenharmony_ci reg_req_rx = reg_cur_rx & ~(1 << vf_shift); 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci /* Enable/Disable particular VF */ 8738c2ecf20Sopenharmony_ci if (reg_cur_tx != reg_req_tx) 8748c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg_req_tx); 8758c2ecf20Sopenharmony_ci if (reg_cur_rx != reg_req_rx) 8768c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg_req_rx); 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 8828c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 8838c2ecf20Sopenharmony_ci unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; 8848c2ecf20Sopenharmony_ci u32 reg, reg_offset, vf_shift; 8858c2ecf20Sopenharmony_ci u32 msgbuf[4] = {0, 0, 0, 0}; 8868c2ecf20Sopenharmony_ci u8 *addr = (u8 *)(&msgbuf[1]); 8878c2ecf20Sopenharmony_ci u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); 8888c2ecf20Sopenharmony_ci int i; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci e_info(probe, "VF Reset msg received from vf %d\n", vf); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* reset the filters for the device */ 8938c2ecf20Sopenharmony_ci ixgbe_vf_reset_event(adapter, vf); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci ixgbe_vf_clear_mbx(adapter, vf); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* set vf mac address */ 8988c2ecf20Sopenharmony_ci if (!is_zero_ether_addr(vf_mac)) 8998c2ecf20Sopenharmony_ci ixgbe_set_vf_mac(adapter, vf, vf_mac); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci vf_shift = vf % 32; 9028c2ecf20Sopenharmony_ci reg_offset = vf / 32; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* force drop enable for all VF Rx queues */ 9058c2ecf20Sopenharmony_ci reg = IXGBE_QDE_ENABLE; 9068c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].pf_vlan) 9078c2ecf20Sopenharmony_ci reg |= IXGBE_QDE_HIDE_VLAN; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci ixgbe_write_qde(adapter, vf, reg); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci ixgbe_set_vf_rx_tx(adapter, vf); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci /* enable VF mailbox for further messages */ 9148c2ecf20Sopenharmony_ci adapter->vfinfo[vf].clear_to_send = true; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci /* Enable counting of spoofed packets in the SSVPC register */ 9178c2ecf20Sopenharmony_ci reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset)); 9188c2ecf20Sopenharmony_ci reg |= BIT(vf_shift); 9198c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* 9228c2ecf20Sopenharmony_ci * Reset the VFs TDWBAL and TDWBAH registers 9238c2ecf20Sopenharmony_ci * which are not cleared by an FLR 9248c2ecf20Sopenharmony_ci */ 9258c2ecf20Sopenharmony_ci for (i = 0; i < q_per_pool; i++) { 9268c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PVFTDWBAHn(q_per_pool, vf, i), 0); 9278c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_PVFTDWBALn(q_per_pool, vf, i), 0); 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci /* reply to reset with ack and vf mac address */ 9318c2ecf20Sopenharmony_ci msgbuf[0] = IXGBE_VF_RESET; 9328c2ecf20Sopenharmony_ci if (!is_zero_ether_addr(vf_mac) && adapter->vfinfo[vf].pf_set_mac) { 9338c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK; 9348c2ecf20Sopenharmony_ci memcpy(addr, vf_mac, ETH_ALEN); 9358c2ecf20Sopenharmony_ci } else { 9368c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* 9408c2ecf20Sopenharmony_ci * Piggyback the multicast filter type so VF can compute the 9418c2ecf20Sopenharmony_ci * correct vectors 9428c2ecf20Sopenharmony_ci */ 9438c2ecf20Sopenharmony_ci msgbuf[3] = hw->mac.mc_filter_type; 9448c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci return 0; 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter, 9508c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 9518c2ecf20Sopenharmony_ci{ 9528c2ecf20Sopenharmony_ci u8 *new_mac = ((u8 *)(&msgbuf[1])); 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(new_mac)) { 9558c2ecf20Sopenharmony_ci e_warn(drv, "VF %d attempted to set invalid mac\n", vf); 9568c2ecf20Sopenharmony_ci return -1; 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].pf_set_mac && !adapter->vfinfo[vf].trusted && 9608c2ecf20Sopenharmony_ci !ether_addr_equal(adapter->vfinfo[vf].vf_mac_addresses, new_mac)) { 9618c2ecf20Sopenharmony_ci e_warn(drv, 9628c2ecf20Sopenharmony_ci "VF %d attempted to override administratively set MAC address\n" 9638c2ecf20Sopenharmony_ci "Reload the VF driver to resume operations\n", 9648c2ecf20Sopenharmony_ci vf); 9658c2ecf20Sopenharmony_ci return -1; 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0; 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter, 9728c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 9738c2ecf20Sopenharmony_ci{ 9748c2ecf20Sopenharmony_ci u32 add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; 9758c2ecf20Sopenharmony_ci u32 vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); 9768c2ecf20Sopenharmony_ci u8 tcs = adapter->hw_tcs; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].pf_vlan || tcs) { 9798c2ecf20Sopenharmony_ci e_warn(drv, 9808c2ecf20Sopenharmony_ci "VF %d attempted to override administratively set VLAN configuration\n" 9818c2ecf20Sopenharmony_ci "Reload the VF driver to resume operations\n", 9828c2ecf20Sopenharmony_ci vf); 9838c2ecf20Sopenharmony_ci return -1; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci /* VLAN 0 is a special case, don't allow it to be removed */ 9878c2ecf20Sopenharmony_ci if (!vid && !add) 9888c2ecf20Sopenharmony_ci return 0; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci return ixgbe_set_vf_vlan(adapter, add, vid, vf); 9918c2ecf20Sopenharmony_ci} 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_cistatic int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter, 9948c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 9958c2ecf20Sopenharmony_ci{ 9968c2ecf20Sopenharmony_ci u8 *new_mac = ((u8 *)(&msgbuf[1])); 9978c2ecf20Sopenharmony_ci int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> 9988c2ecf20Sopenharmony_ci IXGBE_VT_MSGINFO_SHIFT; 9998c2ecf20Sopenharmony_ci int err; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].pf_set_mac && !adapter->vfinfo[vf].trusted && 10028c2ecf20Sopenharmony_ci index > 0) { 10038c2ecf20Sopenharmony_ci e_warn(drv, 10048c2ecf20Sopenharmony_ci "VF %d requested MACVLAN filter but is administratively denied\n", 10058c2ecf20Sopenharmony_ci vf); 10068c2ecf20Sopenharmony_ci return -1; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci /* An non-zero index indicates the VF is setting a filter */ 10108c2ecf20Sopenharmony_ci if (index) { 10118c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(new_mac)) { 10128c2ecf20Sopenharmony_ci e_warn(drv, "VF %d attempted to set invalid mac\n", vf); 10138c2ecf20Sopenharmony_ci return -1; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci /* 10178c2ecf20Sopenharmony_ci * If the VF is allowed to set MAC filters then turn off 10188c2ecf20Sopenharmony_ci * anti-spoofing to avoid false positives. 10198c2ecf20Sopenharmony_ci */ 10208c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].spoofchk_enabled) { 10218c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci hw->mac.ops.set_mac_anti_spoofing(hw, false, vf); 10248c2ecf20Sopenharmony_ci hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); 10258c2ecf20Sopenharmony_ci } 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac); 10298c2ecf20Sopenharmony_ci if (err == -ENOSPC) 10308c2ecf20Sopenharmony_ci e_warn(drv, 10318c2ecf20Sopenharmony_ci "VF %d has requested a MACVLAN filter but there is no space for it\n", 10328c2ecf20Sopenharmony_ci vf); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci return err < 0; 10358c2ecf20Sopenharmony_ci} 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter, 10388c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci int api = msgbuf[1]; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci switch (api) { 10438c2ecf20Sopenharmony_ci case ixgbe_mbox_api_10: 10448c2ecf20Sopenharmony_ci case ixgbe_mbox_api_11: 10458c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 10468c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 10478c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 10488c2ecf20Sopenharmony_ci adapter->vfinfo[vf].vf_api = api; 10498c2ecf20Sopenharmony_ci return 0; 10508c2ecf20Sopenharmony_ci default: 10518c2ecf20Sopenharmony_ci break; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci e_info(drv, "VF %d requested invalid api version %u\n", vf, api); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci return -1; 10578c2ecf20Sopenharmony_ci} 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_cistatic int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter, 10608c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci struct net_device *dev = adapter->netdev; 10638c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 10648c2ecf20Sopenharmony_ci unsigned int default_tc = 0; 10658c2ecf20Sopenharmony_ci u8 num_tcs = adapter->hw_tcs; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* verify the PF is supporting the correct APIs */ 10688c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 10698c2ecf20Sopenharmony_ci case ixgbe_mbox_api_20: 10708c2ecf20Sopenharmony_ci case ixgbe_mbox_api_11: 10718c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 10728c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 10738c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 10748c2ecf20Sopenharmony_ci break; 10758c2ecf20Sopenharmony_ci default: 10768c2ecf20Sopenharmony_ci return -1; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* only allow 1 Tx queue for bandwidth limiting */ 10808c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask); 10818c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask); 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci /* if TCs > 1 determine which TC belongs to default user priority */ 10848c2ecf20Sopenharmony_ci if (num_tcs > 1) 10858c2ecf20Sopenharmony_ci default_tc = netdev_get_prio_tc_map(dev, adapter->default_up); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci /* notify VF of need for VLAN tag stripping, and correct queue */ 10888c2ecf20Sopenharmony_ci if (num_tcs) 10898c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs; 10908c2ecf20Sopenharmony_ci else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos) 10918c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_TRANS_VLAN] = 1; 10928c2ecf20Sopenharmony_ci else 10938c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_TRANS_VLAN] = 0; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci /* notify VF of default queue */ 10968c2ecf20Sopenharmony_ci msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci return 0; 10998c2ecf20Sopenharmony_ci} 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_cistatic int ixgbe_get_vf_reta(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci u32 i, j; 11048c2ecf20Sopenharmony_ci u32 *out_buf = &msgbuf[1]; 11058c2ecf20Sopenharmony_ci const u8 *reta = adapter->rss_indir_tbl; 11068c2ecf20Sopenharmony_ci u32 reta_size = ixgbe_rss_indir_tbl_entries(adapter); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* Check if operation is permitted */ 11098c2ecf20Sopenharmony_ci if (!adapter->vfinfo[vf].rss_query_enabled) 11108c2ecf20Sopenharmony_ci return -EPERM; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci /* verify the PF is supporting the correct API */ 11138c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 11148c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 11158c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 11168c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 11178c2ecf20Sopenharmony_ci break; 11188c2ecf20Sopenharmony_ci default: 11198c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* This mailbox command is supported (required) only for 82599 and x540 11238c2ecf20Sopenharmony_ci * VFs which support up to 4 RSS queues. Therefore we will compress the 11248c2ecf20Sopenharmony_ci * RETA by saving only 2 bits from each entry. This way we will be able 11258c2ecf20Sopenharmony_ci * to transfer the whole RETA in a single mailbox operation. 11268c2ecf20Sopenharmony_ci */ 11278c2ecf20Sopenharmony_ci for (i = 0; i < reta_size / 16; i++) { 11288c2ecf20Sopenharmony_ci out_buf[i] = 0; 11298c2ecf20Sopenharmony_ci for (j = 0; j < 16; j++) 11308c2ecf20Sopenharmony_ci out_buf[i] |= (u32)(reta[16 * i + j] & 0x3) << (2 * j); 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci return 0; 11348c2ecf20Sopenharmony_ci} 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_cistatic int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter, 11378c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci u32 *rss_key = &msgbuf[1]; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci /* Check if the operation is permitted */ 11428c2ecf20Sopenharmony_ci if (!adapter->vfinfo[vf].rss_query_enabled) 11438c2ecf20Sopenharmony_ci return -EPERM; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci /* verify the PF is supporting the correct API */ 11468c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 11478c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 11488c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 11498c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 11508c2ecf20Sopenharmony_ci break; 11518c2ecf20Sopenharmony_ci default: 11528c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci memcpy(rss_key, adapter->rss_key, IXGBE_RSS_KEY_SIZE); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci return 0; 11588c2ecf20Sopenharmony_ci} 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_cistatic int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter, 11618c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 11648c2ecf20Sopenharmony_ci int xcast_mode = msgbuf[1]; 11658c2ecf20Sopenharmony_ci u32 vmolr, fctrl, disable, enable; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci /* verify the PF is supporting the correct APIs */ 11688c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 11698c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 11708c2ecf20Sopenharmony_ci /* promisc introduced in 1.3 version */ 11718c2ecf20Sopenharmony_ci if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC) 11728c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11738c2ecf20Sopenharmony_ci fallthrough; 11748c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 11758c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 11768c2ecf20Sopenharmony_ci break; 11778c2ecf20Sopenharmony_ci default: 11788c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (xcast_mode > IXGBEVF_XCAST_MODE_MULTI && 11828c2ecf20Sopenharmony_ci !adapter->vfinfo[vf].trusted) { 11838c2ecf20Sopenharmony_ci xcast_mode = IXGBEVF_XCAST_MODE_MULTI; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].xcast_mode == xcast_mode) 11878c2ecf20Sopenharmony_ci goto out; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci switch (xcast_mode) { 11908c2ecf20Sopenharmony_ci case IXGBEVF_XCAST_MODE_NONE: 11918c2ecf20Sopenharmony_ci disable = IXGBE_VMOLR_ROMPE | 11928c2ecf20Sopenharmony_ci IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; 11938c2ecf20Sopenharmony_ci enable = IXGBE_VMOLR_BAM; 11948c2ecf20Sopenharmony_ci break; 11958c2ecf20Sopenharmony_ci case IXGBEVF_XCAST_MODE_MULTI: 11968c2ecf20Sopenharmony_ci disable = IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; 11978c2ecf20Sopenharmony_ci enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE; 11988c2ecf20Sopenharmony_ci break; 11998c2ecf20Sopenharmony_ci case IXGBEVF_XCAST_MODE_ALLMULTI: 12008c2ecf20Sopenharmony_ci disable = IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; 12018c2ecf20Sopenharmony_ci enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE; 12028c2ecf20Sopenharmony_ci break; 12038c2ecf20Sopenharmony_ci case IXGBEVF_XCAST_MODE_PROMISC: 12048c2ecf20Sopenharmony_ci if (hw->mac.type <= ixgbe_mac_82599EB) 12058c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 12088c2ecf20Sopenharmony_ci if (!(fctrl & IXGBE_FCTRL_UPE)) { 12098c2ecf20Sopenharmony_ci /* VF promisc requires PF in promisc */ 12108c2ecf20Sopenharmony_ci e_warn(drv, 12118c2ecf20Sopenharmony_ci "Enabling VF promisc requires PF in promisc\n"); 12128c2ecf20Sopenharmony_ci return -EPERM; 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci disable = IXGBE_VMOLR_VPE; 12168c2ecf20Sopenharmony_ci enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | 12178c2ecf20Sopenharmony_ci IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE; 12188c2ecf20Sopenharmony_ci break; 12198c2ecf20Sopenharmony_ci default: 12208c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); 12248c2ecf20Sopenharmony_ci vmolr &= ~disable; 12258c2ecf20Sopenharmony_ci vmolr |= enable; 12268c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci adapter->vfinfo[vf].xcast_mode = xcast_mode; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ciout: 12318c2ecf20Sopenharmony_ci msgbuf[1] = xcast_mode; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci return 0; 12348c2ecf20Sopenharmony_ci} 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_cistatic int ixgbe_get_vf_link_state(struct ixgbe_adapter *adapter, 12378c2ecf20Sopenharmony_ci u32 *msgbuf, u32 vf) 12388c2ecf20Sopenharmony_ci{ 12398c2ecf20Sopenharmony_ci u32 *link_state = &msgbuf[1]; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci /* verify the PF is supporting the correct API */ 12428c2ecf20Sopenharmony_ci switch (adapter->vfinfo[vf].vf_api) { 12438c2ecf20Sopenharmony_ci case ixgbe_mbox_api_12: 12448c2ecf20Sopenharmony_ci case ixgbe_mbox_api_13: 12458c2ecf20Sopenharmony_ci case ixgbe_mbox_api_14: 12468c2ecf20Sopenharmony_ci break; 12478c2ecf20Sopenharmony_ci default: 12488c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12498c2ecf20Sopenharmony_ci } 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci *link_state = adapter->vfinfo[vf].link_enable; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci return 0; 12548c2ecf20Sopenharmony_ci} 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_cistatic int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci u32 mbx_size = IXGBE_VFMAILBOX_SIZE; 12598c2ecf20Sopenharmony_ci u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; 12608c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 12618c2ecf20Sopenharmony_ci s32 retval; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci if (retval) { 12668c2ecf20Sopenharmony_ci pr_err("Error receiving message from VF\n"); 12678c2ecf20Sopenharmony_ci return retval; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci /* this is a message we already processed, do nothing */ 12718c2ecf20Sopenharmony_ci if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK)) 12728c2ecf20Sopenharmony_ci return 0; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci /* flush the ack before we write any messages back */ 12758c2ecf20Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci if (msgbuf[0] == IXGBE_VF_RESET) 12788c2ecf20Sopenharmony_ci return ixgbe_vf_reset_msg(adapter, vf); 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci /* 12818c2ecf20Sopenharmony_ci * until the vf completes a virtual function reset it should not be 12828c2ecf20Sopenharmony_ci * allowed to start any configuration. 12838c2ecf20Sopenharmony_ci */ 12848c2ecf20Sopenharmony_ci if (!adapter->vfinfo[vf].clear_to_send) { 12858c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; 12868c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, msgbuf, 1, vf); 12878c2ecf20Sopenharmony_ci return 0; 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci switch ((msgbuf[0] & 0xFFFF)) { 12918c2ecf20Sopenharmony_ci case IXGBE_VF_SET_MAC_ADDR: 12928c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf); 12938c2ecf20Sopenharmony_ci break; 12948c2ecf20Sopenharmony_ci case IXGBE_VF_SET_MULTICAST: 12958c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf); 12968c2ecf20Sopenharmony_ci break; 12978c2ecf20Sopenharmony_ci case IXGBE_VF_SET_VLAN: 12988c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf); 12998c2ecf20Sopenharmony_ci break; 13008c2ecf20Sopenharmony_ci case IXGBE_VF_SET_LPE: 13018c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_lpe(adapter, msgbuf[1], vf); 13028c2ecf20Sopenharmony_ci break; 13038c2ecf20Sopenharmony_ci case IXGBE_VF_SET_MACVLAN: 13048c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf); 13058c2ecf20Sopenharmony_ci break; 13068c2ecf20Sopenharmony_ci case IXGBE_VF_API_NEGOTIATE: 13078c2ecf20Sopenharmony_ci retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf); 13088c2ecf20Sopenharmony_ci break; 13098c2ecf20Sopenharmony_ci case IXGBE_VF_GET_QUEUES: 13108c2ecf20Sopenharmony_ci retval = ixgbe_get_vf_queues(adapter, msgbuf, vf); 13118c2ecf20Sopenharmony_ci break; 13128c2ecf20Sopenharmony_ci case IXGBE_VF_GET_RETA: 13138c2ecf20Sopenharmony_ci retval = ixgbe_get_vf_reta(adapter, msgbuf, vf); 13148c2ecf20Sopenharmony_ci break; 13158c2ecf20Sopenharmony_ci case IXGBE_VF_GET_RSS_KEY: 13168c2ecf20Sopenharmony_ci retval = ixgbe_get_vf_rss_key(adapter, msgbuf, vf); 13178c2ecf20Sopenharmony_ci break; 13188c2ecf20Sopenharmony_ci case IXGBE_VF_UPDATE_XCAST_MODE: 13198c2ecf20Sopenharmony_ci retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf); 13208c2ecf20Sopenharmony_ci break; 13218c2ecf20Sopenharmony_ci case IXGBE_VF_GET_LINK_STATE: 13228c2ecf20Sopenharmony_ci retval = ixgbe_get_vf_link_state(adapter, msgbuf, vf); 13238c2ecf20Sopenharmony_ci break; 13248c2ecf20Sopenharmony_ci case IXGBE_VF_IPSEC_ADD: 13258c2ecf20Sopenharmony_ci retval = ixgbe_ipsec_vf_add_sa(adapter, msgbuf, vf); 13268c2ecf20Sopenharmony_ci break; 13278c2ecf20Sopenharmony_ci case IXGBE_VF_IPSEC_DEL: 13288c2ecf20Sopenharmony_ci retval = ixgbe_ipsec_vf_del_sa(adapter, msgbuf, vf); 13298c2ecf20Sopenharmony_ci break; 13308c2ecf20Sopenharmony_ci default: 13318c2ecf20Sopenharmony_ci e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); 13328c2ecf20Sopenharmony_ci retval = -EIO; 13338c2ecf20Sopenharmony_ci break; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* notify the VF of the results of what it sent us */ 13378c2ecf20Sopenharmony_ci if (retval) 13388c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; 13398c2ecf20Sopenharmony_ci else 13408c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, msgbuf, mbx_size, vf); 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci return retval; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_cistatic void ixgbe_rcv_ack_from_vf(struct ixgbe_adapter *adapter, u32 vf) 13508c2ecf20Sopenharmony_ci{ 13518c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 13528c2ecf20Sopenharmony_ci u32 msg = IXGBE_VT_MSGTYPE_NACK; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci /* if device isn't clear to send it shouldn't be reading either */ 13558c2ecf20Sopenharmony_ci if (!adapter->vfinfo[vf].clear_to_send) 13568c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, &msg, 1, vf); 13578c2ecf20Sopenharmony_ci} 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_civoid ixgbe_msg_task(struct ixgbe_adapter *adapter) 13608c2ecf20Sopenharmony_ci{ 13618c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 13628c2ecf20Sopenharmony_ci unsigned long flags; 13638c2ecf20Sopenharmony_ci u32 vf; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci spin_lock_irqsave(&adapter->vfs_lock, flags); 13668c2ecf20Sopenharmony_ci for (vf = 0; vf < adapter->num_vfs; vf++) { 13678c2ecf20Sopenharmony_ci /* process any reset requests */ 13688c2ecf20Sopenharmony_ci if (!ixgbe_check_for_rst(hw, vf)) 13698c2ecf20Sopenharmony_ci ixgbe_vf_reset_event(adapter, vf); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* process any messages pending */ 13728c2ecf20Sopenharmony_ci if (!ixgbe_check_for_msg(hw, vf)) 13738c2ecf20Sopenharmony_ci ixgbe_rcv_msg_from_vf(adapter, vf); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* process any acks */ 13768c2ecf20Sopenharmony_ci if (!ixgbe_check_for_ack(hw, vf)) 13778c2ecf20Sopenharmony_ci ixgbe_rcv_ack_from_vf(adapter, vf); 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&adapter->vfs_lock, flags); 13808c2ecf20Sopenharmony_ci} 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_cistatic inline void ixgbe_ping_vf(struct ixgbe_adapter *adapter, int vf) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 13858c2ecf20Sopenharmony_ci u32 ping; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci ping = IXGBE_PF_CONTROL_MSG; 13888c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].clear_to_send) 13898c2ecf20Sopenharmony_ci ping |= IXGBE_VT_MSGTYPE_CTS; 13908c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, &ping, 1, vf); 13918c2ecf20Sopenharmony_ci} 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_civoid ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 13968c2ecf20Sopenharmony_ci u32 ping; 13978c2ecf20Sopenharmony_ci int i; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci for (i = 0 ; i < adapter->num_vfs; i++) { 14008c2ecf20Sopenharmony_ci ping = IXGBE_PF_CONTROL_MSG; 14018c2ecf20Sopenharmony_ci if (adapter->vfinfo[i].clear_to_send) 14028c2ecf20Sopenharmony_ci ping |= IXGBE_VT_MSGTYPE_CTS; 14038c2ecf20Sopenharmony_ci ixgbe_write_mbx(hw, &ping, 1, i); 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci} 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci/** 14088c2ecf20Sopenharmony_ci * ixgbe_set_all_vfs - update vfs queues 14098c2ecf20Sopenharmony_ci * @adapter: Pointer to adapter struct 14108c2ecf20Sopenharmony_ci * 14118c2ecf20Sopenharmony_ci * Update setting transmit and receive queues for all vfs 14128c2ecf20Sopenharmony_ci **/ 14138c2ecf20Sopenharmony_civoid ixgbe_set_all_vfs(struct ixgbe_adapter *adapter) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci int i; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci for (i = 0 ; i < adapter->num_vfs; i++) 14188c2ecf20Sopenharmony_ci ixgbe_set_vf_link_state(adapter, i, 14198c2ecf20Sopenharmony_ci adapter->vfinfo[i].link_state); 14208c2ecf20Sopenharmony_ci} 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) 14238c2ecf20Sopenharmony_ci{ 14248c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 14258c2ecf20Sopenharmony_ci s32 retval; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 14288c2ecf20Sopenharmony_ci return -EINVAL; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci if (is_valid_ether_addr(mac)) { 14318c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", 14328c2ecf20Sopenharmony_ci mac, vf); 14338c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "Reload the VF driver to make this change effective."); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci retval = ixgbe_set_vf_mac(adapter, vf, mac); 14368c2ecf20Sopenharmony_ci if (retval >= 0) { 14378c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_set_mac = true; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci if (test_bit(__IXGBE_DOWN, &adapter->state)) { 14408c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, "The VF MAC address has been set, but the PF device is not up.\n"); 14418c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, "Bring the PF device up before attempting to use the VF device.\n"); 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci } else { 14448c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, "The VF MAC address was NOT set due to invalid or duplicate MAC address.\n"); 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci } else if (is_zero_ether_addr(mac)) { 14478c2ecf20Sopenharmony_ci unsigned char *vf_mac_addr = 14488c2ecf20Sopenharmony_ci adapter->vfinfo[vf].vf_mac_addresses; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci /* nothing to do */ 14518c2ecf20Sopenharmony_ci if (is_zero_ether_addr(vf_mac_addr)) 14528c2ecf20Sopenharmony_ci return 0; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, "removing MAC on VF %d\n", vf); 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci retval = ixgbe_del_mac_filter(adapter, vf_mac_addr, vf); 14578c2ecf20Sopenharmony_ci if (retval >= 0) { 14588c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_set_mac = false; 14598c2ecf20Sopenharmony_ci memcpy(vf_mac_addr, mac, ETH_ALEN); 14608c2ecf20Sopenharmony_ci } else { 14618c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, "Could NOT remove the VF MAC address.\n"); 14628c2ecf20Sopenharmony_ci } 14638c2ecf20Sopenharmony_ci } else { 14648c2ecf20Sopenharmony_ci retval = -EINVAL; 14658c2ecf20Sopenharmony_ci } 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci return retval; 14688c2ecf20Sopenharmony_ci} 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_cistatic int ixgbe_enable_port_vlan(struct ixgbe_adapter *adapter, int vf, 14718c2ecf20Sopenharmony_ci u16 vlan, u8 qos) 14728c2ecf20Sopenharmony_ci{ 14738c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 14748c2ecf20Sopenharmony_ci int err; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci err = ixgbe_set_vf_vlan(adapter, true, vlan, vf); 14778c2ecf20Sopenharmony_ci if (err) 14788c2ecf20Sopenharmony_ci goto out; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci /* Revoke tagless access via VLAN 0 */ 14818c2ecf20Sopenharmony_ci ixgbe_set_vf_vlan(adapter, false, 0, vf); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci ixgbe_set_vmvir(adapter, vlan, qos, vf); 14848c2ecf20Sopenharmony_ci ixgbe_set_vmolr(hw, vf, false); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* enable hide vlan on X550 */ 14878c2ecf20Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550) 14888c2ecf20Sopenharmony_ci ixgbe_write_qde(adapter, vf, IXGBE_QDE_ENABLE | 14898c2ecf20Sopenharmony_ci IXGBE_QDE_HIDE_VLAN); 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_vlan = vlan; 14928c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_qos = qos; 14938c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 14948c2ecf20Sopenharmony_ci "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); 14958c2ecf20Sopenharmony_ci if (test_bit(__IXGBE_DOWN, &adapter->state)) { 14968c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 14978c2ecf20Sopenharmony_ci "The VF VLAN has been set, but the PF device is not up.\n"); 14988c2ecf20Sopenharmony_ci dev_warn(&adapter->pdev->dev, 14998c2ecf20Sopenharmony_ci "Bring the PF device up before attempting to use the VF device.\n"); 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ciout: 15038c2ecf20Sopenharmony_ci return err; 15048c2ecf20Sopenharmony_ci} 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_cistatic int ixgbe_disable_port_vlan(struct ixgbe_adapter *adapter, int vf) 15078c2ecf20Sopenharmony_ci{ 15088c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 15098c2ecf20Sopenharmony_ci int err; 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci err = ixgbe_set_vf_vlan(adapter, false, 15128c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_vlan, vf); 15138c2ecf20Sopenharmony_ci /* Restore tagless access via VLAN 0 */ 15148c2ecf20Sopenharmony_ci ixgbe_set_vf_vlan(adapter, true, 0, vf); 15158c2ecf20Sopenharmony_ci ixgbe_clear_vmvir(adapter, vf); 15168c2ecf20Sopenharmony_ci ixgbe_set_vmolr(hw, vf, true); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci /* disable hide VLAN on X550 */ 15198c2ecf20Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550) 15208c2ecf20Sopenharmony_ci ixgbe_write_qde(adapter, vf, IXGBE_QDE_ENABLE); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_vlan = 0; 15238c2ecf20Sopenharmony_ci adapter->vfinfo[vf].pf_qos = 0; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci return err; 15268c2ecf20Sopenharmony_ci} 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, 15298c2ecf20Sopenharmony_ci u8 qos, __be16 vlan_proto) 15308c2ecf20Sopenharmony_ci{ 15318c2ecf20Sopenharmony_ci int err = 0; 15328c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7)) 15358c2ecf20Sopenharmony_ci return -EINVAL; 15368c2ecf20Sopenharmony_ci if (vlan_proto != htons(ETH_P_8021Q)) 15378c2ecf20Sopenharmony_ci return -EPROTONOSUPPORT; 15388c2ecf20Sopenharmony_ci if (vlan || qos) { 15398c2ecf20Sopenharmony_ci /* Check if there is already a port VLAN set, if so 15408c2ecf20Sopenharmony_ci * we have to delete the old one first before we 15418c2ecf20Sopenharmony_ci * can set the new one. The usage model had 15428c2ecf20Sopenharmony_ci * previously assumed the user would delete the 15438c2ecf20Sopenharmony_ci * old port VLAN before setting a new one but this 15448c2ecf20Sopenharmony_ci * is not necessarily the case. 15458c2ecf20Sopenharmony_ci */ 15468c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].pf_vlan) 15478c2ecf20Sopenharmony_ci err = ixgbe_disable_port_vlan(adapter, vf); 15488c2ecf20Sopenharmony_ci if (err) 15498c2ecf20Sopenharmony_ci goto out; 15508c2ecf20Sopenharmony_ci err = ixgbe_enable_port_vlan(adapter, vf, vlan, qos); 15518c2ecf20Sopenharmony_ci } else { 15528c2ecf20Sopenharmony_ci err = ixgbe_disable_port_vlan(adapter, vf); 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ciout: 15568c2ecf20Sopenharmony_ci return err; 15578c2ecf20Sopenharmony_ci} 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ciint ixgbe_link_mbps(struct ixgbe_adapter *adapter) 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci switch (adapter->link_speed) { 15628c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_100_FULL: 15638c2ecf20Sopenharmony_ci return 100; 15648c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_1GB_FULL: 15658c2ecf20Sopenharmony_ci return 1000; 15668c2ecf20Sopenharmony_ci case IXGBE_LINK_SPEED_10GB_FULL: 15678c2ecf20Sopenharmony_ci return 10000; 15688c2ecf20Sopenharmony_ci default: 15698c2ecf20Sopenharmony_ci return 0; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci} 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_cistatic void ixgbe_set_vf_rate_limit(struct ixgbe_adapter *adapter, int vf) 15748c2ecf20Sopenharmony_ci{ 15758c2ecf20Sopenharmony_ci struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 15768c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 15778c2ecf20Sopenharmony_ci u32 bcnrc_val = 0; 15788c2ecf20Sopenharmony_ci u16 queue, queues_per_pool; 15798c2ecf20Sopenharmony_ci u16 tx_rate = adapter->vfinfo[vf].tx_rate; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci if (tx_rate) { 15828c2ecf20Sopenharmony_ci /* start with base link speed value */ 15838c2ecf20Sopenharmony_ci bcnrc_val = adapter->vf_rate_link_speed; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci /* Calculate the rate factor values to set */ 15868c2ecf20Sopenharmony_ci bcnrc_val <<= IXGBE_RTTBCNRC_RF_INT_SHIFT; 15878c2ecf20Sopenharmony_ci bcnrc_val /= tx_rate; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci /* clear everything but the rate factor */ 15908c2ecf20Sopenharmony_ci bcnrc_val &= IXGBE_RTTBCNRC_RF_INT_MASK | 15918c2ecf20Sopenharmony_ci IXGBE_RTTBCNRC_RF_DEC_MASK; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci /* enable the rate scheduler */ 15948c2ecf20Sopenharmony_ci bcnrc_val |= IXGBE_RTTBCNRC_RS_ENA; 15958c2ecf20Sopenharmony_ci } 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci /* 15988c2ecf20Sopenharmony_ci * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM 15998c2ecf20Sopenharmony_ci * register. Typically MMW_SIZE=0x014 if 9728-byte jumbo is supported 16008c2ecf20Sopenharmony_ci * and 0x004 otherwise. 16018c2ecf20Sopenharmony_ci */ 16028c2ecf20Sopenharmony_ci switch (hw->mac.type) { 16038c2ecf20Sopenharmony_ci case ixgbe_mac_82599EB: 16048c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x4); 16058c2ecf20Sopenharmony_ci break; 16068c2ecf20Sopenharmony_ci case ixgbe_mac_X540: 16078c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, 0x14); 16088c2ecf20Sopenharmony_ci break; 16098c2ecf20Sopenharmony_ci default: 16108c2ecf20Sopenharmony_ci break; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci /* determine how many queues per pool based on VMDq mask */ 16148c2ecf20Sopenharmony_ci queues_per_pool = __ALIGN_MASK(1, ~vmdq->mask); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci /* write value for all Tx queues belonging to VF */ 16178c2ecf20Sopenharmony_ci for (queue = 0; queue < queues_per_pool; queue++) { 16188c2ecf20Sopenharmony_ci unsigned int reg_idx = (vf * queues_per_pool) + queue; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, reg_idx); 16218c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val); 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci} 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_civoid ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter) 16268c2ecf20Sopenharmony_ci{ 16278c2ecf20Sopenharmony_ci int i; 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci /* VF Tx rate limit was not set */ 16308c2ecf20Sopenharmony_ci if (!adapter->vf_rate_link_speed) 16318c2ecf20Sopenharmony_ci return; 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci if (ixgbe_link_mbps(adapter) != adapter->vf_rate_link_speed) { 16348c2ecf20Sopenharmony_ci adapter->vf_rate_link_speed = 0; 16358c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 16368c2ecf20Sopenharmony_ci "Link speed has been changed. VF Transmit rate is disabled\n"); 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci for (i = 0; i < adapter->num_vfs; i++) { 16408c2ecf20Sopenharmony_ci if (!adapter->vf_rate_link_speed) 16418c2ecf20Sopenharmony_ci adapter->vfinfo[i].tx_rate = 0; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci ixgbe_set_vf_rate_limit(adapter, i); 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci} 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, 16488c2ecf20Sopenharmony_ci int max_tx_rate) 16498c2ecf20Sopenharmony_ci{ 16508c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 16518c2ecf20Sopenharmony_ci int link_speed; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci /* verify VF is active */ 16548c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 16558c2ecf20Sopenharmony_ci return -EINVAL; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci /* verify link is up */ 16588c2ecf20Sopenharmony_ci if (!adapter->link_up) 16598c2ecf20Sopenharmony_ci return -EINVAL; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci /* verify we are linked at 10Gbps */ 16628c2ecf20Sopenharmony_ci link_speed = ixgbe_link_mbps(adapter); 16638c2ecf20Sopenharmony_ci if (link_speed != 10000) 16648c2ecf20Sopenharmony_ci return -EINVAL; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (min_tx_rate) 16678c2ecf20Sopenharmony_ci return -EINVAL; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* rate limit cannot be less than 10Mbs or greater than link speed */ 16708c2ecf20Sopenharmony_ci if (max_tx_rate && ((max_tx_rate <= 10) || (max_tx_rate > link_speed))) 16718c2ecf20Sopenharmony_ci return -EINVAL; 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci /* store values */ 16748c2ecf20Sopenharmony_ci adapter->vf_rate_link_speed = link_speed; 16758c2ecf20Sopenharmony_ci adapter->vfinfo[vf].tx_rate = max_tx_rate; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci /* update hardware configuration */ 16788c2ecf20Sopenharmony_ci ixgbe_set_vf_rate_limit(adapter, vf); 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci return 0; 16818c2ecf20Sopenharmony_ci} 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) 16848c2ecf20Sopenharmony_ci{ 16858c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 16868c2ecf20Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 16898c2ecf20Sopenharmony_ci return -EINVAL; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci adapter->vfinfo[vf].spoofchk_enabled = setting; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci /* configure MAC spoofing */ 16948c2ecf20Sopenharmony_ci hw->mac.ops.set_mac_anti_spoofing(hw, setting, vf); 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci /* configure VLAN spoofing */ 16978c2ecf20Sopenharmony_ci hw->mac.ops.set_vlan_anti_spoofing(hw, setting, vf); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be 17008c2ecf20Sopenharmony_ci * calling set_ethertype_anti_spoofing for each VF in loop below 17018c2ecf20Sopenharmony_ci */ 17028c2ecf20Sopenharmony_ci if (hw->mac.ops.set_ethertype_anti_spoofing) { 17038c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_LLDP), 17048c2ecf20Sopenharmony_ci (IXGBE_ETQF_FILTER_EN | 17058c2ecf20Sopenharmony_ci IXGBE_ETQF_TX_ANTISPOOF | 17068c2ecf20Sopenharmony_ci ETH_P_LLDP)); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FC), 17098c2ecf20Sopenharmony_ci (IXGBE_ETQF_FILTER_EN | 17108c2ecf20Sopenharmony_ci IXGBE_ETQF_TX_ANTISPOOF | 17118c2ecf20Sopenharmony_ci ETH_P_PAUSE)); 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci hw->mac.ops.set_ethertype_anti_spoofing(hw, setting, vf); 17148c2ecf20Sopenharmony_ci } 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci return 0; 17178c2ecf20Sopenharmony_ci} 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci/** 17208c2ecf20Sopenharmony_ci * ixgbe_set_vf_link_state - Set link state 17218c2ecf20Sopenharmony_ci * @adapter: Pointer to adapter struct 17228c2ecf20Sopenharmony_ci * @vf: VF identifier 17238c2ecf20Sopenharmony_ci * @state: required link state 17248c2ecf20Sopenharmony_ci * 17258c2ecf20Sopenharmony_ci * Set a link force state on/off a single vf 17268c2ecf20Sopenharmony_ci **/ 17278c2ecf20Sopenharmony_civoid ixgbe_set_vf_link_state(struct ixgbe_adapter *adapter, int vf, int state) 17288c2ecf20Sopenharmony_ci{ 17298c2ecf20Sopenharmony_ci adapter->vfinfo[vf].link_state = state; 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci switch (state) { 17328c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_AUTO: 17338c2ecf20Sopenharmony_ci if (test_bit(__IXGBE_DOWN, &adapter->state)) 17348c2ecf20Sopenharmony_ci adapter->vfinfo[vf].link_enable = false; 17358c2ecf20Sopenharmony_ci else 17368c2ecf20Sopenharmony_ci adapter->vfinfo[vf].link_enable = true; 17378c2ecf20Sopenharmony_ci break; 17388c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_ENABLE: 17398c2ecf20Sopenharmony_ci adapter->vfinfo[vf].link_enable = true; 17408c2ecf20Sopenharmony_ci break; 17418c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_DISABLE: 17428c2ecf20Sopenharmony_ci adapter->vfinfo[vf].link_enable = false; 17438c2ecf20Sopenharmony_ci break; 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci ixgbe_set_vf_rx_tx(adapter, vf); 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci /* restart the VF */ 17498c2ecf20Sopenharmony_ci adapter->vfinfo[vf].clear_to_send = false; 17508c2ecf20Sopenharmony_ci ixgbe_ping_vf(adapter, vf); 17518c2ecf20Sopenharmony_ci} 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci/** 17548c2ecf20Sopenharmony_ci * ixgbe_ndo_set_vf_link_state - Set link state 17558c2ecf20Sopenharmony_ci * @netdev: network interface device structure 17568c2ecf20Sopenharmony_ci * @vf: VF identifier 17578c2ecf20Sopenharmony_ci * @state: required link state 17588c2ecf20Sopenharmony_ci * 17598c2ecf20Sopenharmony_ci * Set the link state of a specified VF, regardless of physical link state 17608c2ecf20Sopenharmony_ci **/ 17618c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state) 17628c2ecf20Sopenharmony_ci{ 17638c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 17648c2ecf20Sopenharmony_ci int ret = 0; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (vf < 0 || vf >= adapter->num_vfs) { 17678c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, 17688c2ecf20Sopenharmony_ci "NDO set VF link - invalid VF identifier %d\n", vf); 17698c2ecf20Sopenharmony_ci return -EINVAL; 17708c2ecf20Sopenharmony_ci } 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci switch (state) { 17738c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_ENABLE: 17748c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 17758c2ecf20Sopenharmony_ci "NDO set VF %d link state %d - not supported\n", 17768c2ecf20Sopenharmony_ci vf, state); 17778c2ecf20Sopenharmony_ci break; 17788c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_DISABLE: 17798c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 17808c2ecf20Sopenharmony_ci "NDO set VF %d link state disable\n", vf); 17818c2ecf20Sopenharmony_ci ixgbe_set_vf_link_state(adapter, vf, state); 17828c2ecf20Sopenharmony_ci break; 17838c2ecf20Sopenharmony_ci case IFLA_VF_LINK_STATE_AUTO: 17848c2ecf20Sopenharmony_ci dev_info(&adapter->pdev->dev, 17858c2ecf20Sopenharmony_ci "NDO set VF %d link state auto\n", vf); 17868c2ecf20Sopenharmony_ci ixgbe_set_vf_link_state(adapter, vf, state); 17878c2ecf20Sopenharmony_ci break; 17888c2ecf20Sopenharmony_ci default: 17898c2ecf20Sopenharmony_ci dev_err(&adapter->pdev->dev, 17908c2ecf20Sopenharmony_ci "NDO set VF %d - invalid link state %d\n", vf, state); 17918c2ecf20Sopenharmony_ci ret = -EINVAL; 17928c2ecf20Sopenharmony_ci } 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci return ret; 17958c2ecf20Sopenharmony_ci} 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf, 17988c2ecf20Sopenharmony_ci bool setting) 17998c2ecf20Sopenharmony_ci{ 18008c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci /* This operation is currently supported only for 82599 and x540 18038c2ecf20Sopenharmony_ci * devices. 18048c2ecf20Sopenharmony_ci */ 18058c2ecf20Sopenharmony_ci if (adapter->hw.mac.type < ixgbe_mac_82599EB || 18068c2ecf20Sopenharmony_ci adapter->hw.mac.type >= ixgbe_mac_X550) 18078c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 18108c2ecf20Sopenharmony_ci return -EINVAL; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci adapter->vfinfo[vf].rss_query_enabled = setting; 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci return 0; 18158c2ecf20Sopenharmony_ci} 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ciint ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) 18188c2ecf20Sopenharmony_ci{ 18198c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 18228c2ecf20Sopenharmony_ci return -EINVAL; 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci /* nothing to do */ 18258c2ecf20Sopenharmony_ci if (adapter->vfinfo[vf].trusted == setting) 18268c2ecf20Sopenharmony_ci return 0; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci adapter->vfinfo[vf].trusted = setting; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci /* reset VF to reconfigure features */ 18318c2ecf20Sopenharmony_ci adapter->vfinfo[vf].clear_to_send = false; 18328c2ecf20Sopenharmony_ci ixgbe_ping_vf(adapter, vf); 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci e_info(drv, "VF %u is %strusted\n", vf, setting ? "" : "not "); 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci return 0; 18378c2ecf20Sopenharmony_ci} 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ciint ixgbe_ndo_get_vf_config(struct net_device *netdev, 18408c2ecf20Sopenharmony_ci int vf, struct ifla_vf_info *ivi) 18418c2ecf20Sopenharmony_ci{ 18428c2ecf20Sopenharmony_ci struct ixgbe_adapter *adapter = netdev_priv(netdev); 18438c2ecf20Sopenharmony_ci if (vf >= adapter->num_vfs) 18448c2ecf20Sopenharmony_ci return -EINVAL; 18458c2ecf20Sopenharmony_ci ivi->vf = vf; 18468c2ecf20Sopenharmony_ci memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN); 18478c2ecf20Sopenharmony_ci ivi->max_tx_rate = adapter->vfinfo[vf].tx_rate; 18488c2ecf20Sopenharmony_ci ivi->min_tx_rate = 0; 18498c2ecf20Sopenharmony_ci ivi->vlan = adapter->vfinfo[vf].pf_vlan; 18508c2ecf20Sopenharmony_ci ivi->qos = adapter->vfinfo[vf].pf_qos; 18518c2ecf20Sopenharmony_ci ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled; 18528c2ecf20Sopenharmony_ci ivi->rss_query_en = adapter->vfinfo[vf].rss_query_enabled; 18538c2ecf20Sopenharmony_ci ivi->trusted = adapter->vfinfo[vf].trusted; 18548c2ecf20Sopenharmony_ci return 0; 18558c2ecf20Sopenharmony_ci} 1856