2026-01-29 22:25:33 +08:00

1568 lines
40 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2022 - 2024 Mucse Corporation. */
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/ipv6.h>
#include <linux/if_vlan.h>
#include "rnpgbe.h"
#include "rnpgbe_type.h"
#include "rnpgbe_sriov.h"
int rnpgbe_msg_post_status_signle(struct rnpgbe_adapter *adapter,
enum PF_STATUS status, int vf);
#if IS_ENABLED(CONFIG_PCI_IOV)
static int __rnpgbe_enable_sriov(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
int num_vf_macvlans, i, num_vebvlans;
struct vf_macvlans *mv_list;
struct vf_vebvlans *vv_list = NULL;
/* sriov and dcb cannot open together */
/* reset numtc */
adapter->flags &= (~RNP_FLAG_DCB_ENABLED);
netdev_reset_tc(adapter->netdev);
e_info(probe, "SR-IOV enabled with %d VFs\n", adapter->num_vfs);
/* Enable VMDq flag so device will be set in VM mode */
adapter->flags |= RNP_FLAG_VMDQ_ENABLED;
if (!adapter->ring_feature[RING_F_VMDQ].limit)
adapter->ring_feature[RING_F_VMDQ].limit = 1;
adapter->ring_feature[RING_F_VMDQ].offset = hw->max_vfs - 1;
num_vf_macvlans = hw->num_rar_entries -
(hw->max_pf_macvlans + 1 + adapter->num_vfs);
num_vebvlans = hw->num_vebvlan_entries;
mv_list = kcalloc(num_vf_macvlans,
sizeof(struct vf_macvlans), GFP_KERNEL);
adapter->mv_list = mv_list;
if (num_vebvlans) {
vv_list = kcalloc(num_vebvlans,
sizeof(struct vf_vebvlans), GFP_KERNEL);
hw->vv_list = vv_list;
}
if (mv_list) {
/* Initialize list of VF macvlans */
INIT_LIST_HEAD(&adapter->vf_mvs.l);
for (i = 0; i < num_vf_macvlans; i++) {
mv_list->vf = -1;
mv_list->free = true;
mv_list->rar_entry = hw->mac.num_rar_entries -
(i + adapter->num_vfs + 1);
list_add(&mv_list->l, &adapter->vf_mvs.l);
mv_list++;
}
}
if (vv_list) {
/* Initialize list of VF macvlans */
INIT_LIST_HEAD(&hw->vf_vas.l);
for (i = 0; i < num_vebvlans; i++) {
vv_list->vid = -1;
vv_list->vid = 0;
vv_list->free = true;
vv_list->veb_entry = i;
list_add(&vv_list->l, &hw->vf_vas.l);
vv_list++;
}
}
adapter->flags2 |= RNP_FLAG2_BRIDGE_MODE_VEB;
hw->ops.set_sriov_status(hw, true);
adapter->vfinfo = kcalloc(adapter->num_vfs,
sizeof(struct vf_data_storage), GFP_KERNEL);
if (adapter->vfinfo) {
/* limit trafffic classes based on VFs enabled */
/* TODO analyze VF need support pfc or traffic classes */
/* We do not support RSS w/ SR-IOV */
adapter->ring_feature[RING_F_RSS].limit = hw->sriov_ring_limit;
/* Disable RSC when in SR-IOV mode */
adapter->flags2 &=
~(RNP_FLAG2_RSC_CAPABLE | RNP_FLAG2_RSC_ENABLED);
adapter->flags |= RNP_FLAG_SRIOV_ENABLED;
/* force close eee if open sriov */
adapter->eee_enabled = 0;
return 0;
}
return -ENOMEM;
}
void rnpgbe_enable_sriov_true(struct rnpgbe_adapter *adapter)
{
int err = 0;
if (!(adapter->flags & RNP_FLAG_SRIOV_ENABLED))
return;
adapter->flags |= RNP_FLAG_SRIOV_INIT_DONE;
err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
if (err) {
e_err(drv, "Failed to enable PCI sriov: %d num %d\n", err,
adapter->num_vfs);
e_err(drv, "We cannot handle this error\n");
}
adapter->flags |= RNP_FLAG_VF_INIT_DONE;
}
/* Note this function is called when the user wants to enable SR-IOV
* VFs using the now deprecated module parameter
* never used
*/
void rnpgbe_enable_sriov(struct rnpgbe_adapter *adapter)
{
int pre_existing_vfs = 0;
struct rnpgbe_hw *hw = &adapter->hw;
pre_existing_vfs = pci_num_vf(adapter->pdev);
if (!pre_existing_vfs && !adapter->num_vfs)
return;
if (!pre_existing_vfs) {
dev_warn(&adapter->pdev->dev,
"Enabling SR-IOV VFs using the module parameter is deprecated");
dev_warn(&adapter->pdev->dev,
"- please use the pci sysfs interface.\n");
}
/* If there are pre-existing VFs then we have to force
* use of that many - over ride any module parameter value.
* This may result from the user unloading the PF driver
* while VFs were assigned to guest VMs or because the VFs
* have been created via the new PCI SR-IOV sysfs interface.
*/
if (pre_existing_vfs) {
adapter->num_vfs = pre_existing_vfs;
dev_warn(&adapter->pdev->dev,
"Virtual Functions already enabled for this device - Please");
dev_warn(&adapter->pdev->dev,
"reload all VF drivers to avoid spoofed packet errors\n");
} else {
int i;
/* The rnpgbe supports up to 64 VFs per physical function
* but this implementation limits allocation to 126 so that
* basic networking resources are still available to the
* physical function. If the user requests greater than
* 64 VFs then it is an error - reset to default of zero.
*/
adapter->num_vfs =
min_t(unsigned int, adapter->num_vfs, hw->max_vfs - 1);
if (__rnpgbe_enable_sriov(adapter)) {
e_err(probe, "Failed to alloc memory for sriov\n");
adapter->num_vfs = 0;
}
for (i = 0; i < adapter->num_vfs; i++)
rnpgbe_vf_configuration(adapter->pdev,
(i | 0x10000000));
}
}
static bool rnpgbe_vfs_are_assigned(struct rnpgbe_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct pci_dev *vfdev;
unsigned int dev_id = RNP_DEV_ID_N10_PF0_VF_N;
unsigned int vendor_id = PCI_VENDOR_ID_MUCSE;
switch (adapter->pdev->device) {
case RNP_DEV_ID_N10_PF0:
case RNP_DEV_ID_N10_PF1:
vendor_id = 0x1dab;
if (rnpgbe_is_pf1(pdev))
dev_id = RNP_DEV_ID_N10_PF1_VF;
else
dev_id = RNP_DEV_ID_N10_PF0_VF;
break;
case PCI_DEVICE_ID_N10_PF0:
case PCI_DEVICE_ID_N10_PF1:
vendor_id = PCI_VENDOR_ID_MUCSE;
if (rnpgbe_is_pf1(pdev))
dev_id = RNP_DEV_ID_N10_PF1_VF_N;
else
dev_id = RNP_DEV_ID_N10_PF0_VF_N;
break;
case PCI_DEVICE_ID_N500_QUAD_PORT:
case PCI_DEVICE_ID_N500_DUAL_PORT:
vendor_id = PCI_VENDOR_ID_MUCSE;
dev_id = PCI_DEVICE_ID_N500_VF;
break;
}
/* loop through all the VFs to see if we own any that are assigned */
vfdev = pci_get_device(vendor_id, dev_id, NULL);
while (vfdev) {
/* if we don't own it we don't care */
if (vfdev->is_virtfn && vfdev->physfn == pdev) {
/* if it is assigned we cannot release it */
if (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
return true;
}
vfdev = pci_get_device(vendor_id, dev_id, vfdev);
}
return false;
}
#endif /* CONFIG_PCI_IOV */
int rnpgbe_disable_sriov(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
int rss;
int time = 0;
if (!(adapter->flags & RNP_FLAG_SRIOV_ENABLED))
return 0;
adapter->num_vfs = 0;
adapter->flags &= ~RNP_FLAG_SRIOV_ENABLED;
adapter->flags &= ~RNP_FLAG_SRIOV_INIT_DONE;
adapter->flags &= ~RNP_FLAG_VF_INIT_DONE;
adapter->vlan_count = 0;
msleep(100);
hw->ops.set_mac_rx(hw, false);
hw->ops.set_sriov_status(hw, false);
/* set num VFs to 0 to prevent access to vfinfo */
while (test_and_set_bit(__RNP_USE_VFINFI, &adapter->state)) {
msleep(100);
time++;
if (time > 100) {
e_err(drv, "wait flags timeout\n");
break;
}
}
if (time < 100)
clear_bit(__RNP_USE_VFINFI, &adapter->state);
/* free VF control structures */
kfree(adapter->vfinfo);
adapter->vfinfo = NULL;
/* free macvlan list */
kfree(hw->vv_list);
hw->vv_list = NULL;
kfree(adapter->mv_list);
adapter->mv_list = NULL;
#if IS_ENABLED(CONFIG_PCI_IOV)
/* If our VFs are assigned we cannot shut down SR-IOV
* without causing issues, so just leave the hardware
* available but disabled
*/
if (rnpgbe_vfs_are_assigned(adapter)) {
e_dev_warn("Unloading driver while VFs are assigned - VFs will not be");
e_dev_warn(" deallocated\n");
return -EPERM;
}
/* disable iov and allow time for transactions to clear */
pci_disable_sriov(adapter->pdev);
#endif /* CONFIG_PCI_IOV */
/* set default pool back to 0 */
/* Disable VMDq flag so device will be set in VM mode */
if (adapter->ring_feature[RING_F_VMDQ].limit == 1)
adapter->flags &= ~RNP_FLAG_VMDQ_ENABLED;
adapter->ring_feature[RING_F_VMDQ].offset = 0;
rss = min_t(int, adapter->max_ring_pair_counts, num_online_cpus());
rss = min_t(int, rss,
hw->mac.max_msix_vectors - adapter->num_other_vectors);
adapter->ring_feature[RING_F_RSS].limit = rss;
/* take a breather then clean up driver data */
msleep(100);
return 0;
}
static bool check_ari_mode(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
return bus->self && bus->self->ari_enabled;
}
static int rnpgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
{
#if IS_ENABLED(CONFIG_PCI_IOV)
struct rnpgbe_adapter *adapter = pci_get_drvdata(dev);
struct rnpgbe_hw *hw = &adapter->hw;
int err = 0;
int i;
int pre_existing_vfs = pci_num_vf(dev);
if (pre_existing_vfs && pre_existing_vfs != num_vfs)
err = rnpgbe_disable_sriov(adapter);
else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
goto out;
if (hw->feature_flags & RNP_VEB_VLAN_MASK_EN) {
if (adapter->vlan_count > hw->max_vfs - 1) {
dev_err(&adapter->pdev->dev,
"vlans is too much, delete less than %d vlans\n",
hw->max_vfs - 1);
err = -EOPNOTSUPP;
goto err_out;
}
} else if (adapter->vlan_count > 1) {
dev_err(&adapter->pdev->dev,
"only 1 vlan in sriov mode, delete other vlans\n");
dev_err(&adapter->pdev->dev, "please delete all vlans first\n");
err = -EOPNOTSUPP;
goto err_out;
}
adapter->vlan_count = 0;
if (err)
goto err_out;
/* While the SR-IOV capability structure reports total VFs to be
* 64 we limit the actual number that can be allocated to 63 so
* that some transmit/receive resources can be reserved to the
* PF. The PCI bus driver already checks for other values out of
* range.
*/
if (check_ari_mode(dev)) {
if (num_vfs > (hw->max_vfs - 1)) {
err = -EPERM;
goto err_out;
}
} else {
if (num_vfs > hw->max_vfs_noari) {
err = -EPERM;
goto err_out;
}
}
/* maybe to early */
adapter->num_vfs = num_vfs;
err = __rnpgbe_enable_sriov(adapter);
if (err)
goto err_out;
for (i = 0; i < adapter->num_vfs; i++)
rnpgbe_vf_configuration(dev, (i | 0x10000000));
if (hw->ops.clr_rar_all)
hw->ops.clr_rar_all(hw);
rnpgbe_sriov_reinit(adapter);
adapter->flags |= RNP_FLAG_SRIOV_INIT_DONE;
err = pci_enable_sriov(dev, num_vfs);
if (err) {
e_dev_warn("Failed to enable PCI sriov: %d num %d\n", err,
num_vfs);
rnpgbe_disable_sriov(adapter);
rnpgbe_sriov_reinit(adapter);
goto err_out;
}
adapter->flags |= RNP_FLAG_VF_INIT_DONE;
out:
return num_vfs;
err_out:
return err;
#endif /* CONFIG_PCI_IOV */
return 0;
}
static int rnpgbe_pci_sriov_disable(struct pci_dev *dev)
{
struct rnpgbe_adapter *adapter = pci_get_drvdata(dev);
int err;
u32 current_flags = adapter->flags;
err = rnpgbe_disable_sriov(adapter);
/* Only reinit if no error and state changed */
if (!err && current_flags != adapter->flags) {
adapter->flags &= ~RNP_FLAG_VMDQ_ENABLED;
#if IS_ENABLED(CONFIG_PCI_IOV)
rnpgbe_sriov_reinit(adapter);
#endif /* CONFIG_PCI_IOV */
}
return err;
}
static int rnpgbe_set_vf_multicasts(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
int entries = (msgbuf[0] & RNP_VT_MSGINFO_MASK) >> RNP_VT_MSGINFO_SHIFT;
u16 *hash_list = (u16 *)&msgbuf[1];
struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
struct rnpgbe_hw *hw = &adapter->hw;
int i;
/* only so many hash values supported */
entries = min(entries, RNP_MAX_VF_MC_ENTRIES);
/* salt away the number of multi cast addresses assigned
* to this VF for later use to restore when the PF multi cast
* list changes
*/
vfinfo->num_vf_mc_hashes = entries;
/* VFs are limited to using the MTA hash table for their multicast
* addresses
*/
for (i = 0; i < entries; i++)
vfinfo->vf_mc_hashes[i] = hash_list[i];
for (i = 0; i < vfinfo->num_vf_mc_hashes; i++)
hw->ops.set_sriov_vf_mc(hw, vfinfo->vf_mc_hashes[i]);
return 0;
}
void rnpgbe_restore_vf_macs(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
int vf;
u8 *mac_addr;
int rar_entry;
for (vf = 0; vf < adapter->num_vfs; vf++) {
mac_addr = adapter->vfinfo[vf].vf_mac_addresses;
rar_entry = hw->mac.num_rar_entries - (vf + 1);
hw->ops.set_rar_with_vf(hw, mac_addr, rar_entry, vf, true);
}
}
void rnpgbe_restore_vf_macvlans(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
struct list_head *pos;
struct vf_macvlans *entry;
list_for_each(pos, &adapter->vf_mvs.l) {
entry = list_entry(pos, struct vf_macvlans, l);
if (!entry->free) {
hw_dbg(hw, " vf:%d MACVLAN: RAR[%d] <= %pM\n",
entry->vf, entry->rar_entry, entry->vf_macvlan);
hw->ops.set_rar_with_vf(hw, entry->vf_macvlan,
entry->rar_entry, entry->vf,
true);
}
}
}
void rnpgbe_restore_vf_multicasts(struct rnpgbe_adapter *adapter)
{
/* Restore any VF macvlans */
rnpgbe_restore_vf_macvlans(adapter);
}
static int rnpgbe_set_vf_vlan(struct rnpgbe_adapter *adapter, int add, int vid,
u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
int true_handle = 1;
int i;
/* VLAN 0 is a special case, don't allow it to be removed */
if (!vid && !add)
return 0;
/* should check other vf */
if ((adapter->flags & RNP_FLAG_SRIOV_ENABLED)) {
/* if other vf use this vlan, don't true remove */
if (add)
goto skip_check;
/* check equal pf_vlan? */
if (vid == adapter->vf_vlan)
true_handle = 0;
if (!test_and_set_bit(__RNP_USE_VFINFI, &adapter->state)) {
for (i = 0; i < adapter->num_vfs; i++) {
/* check if other vf_vlan still valid */
if (i != vf &&
vid == adapter->vfinfo[i].vf_vlan)
true_handle = 0;
/* check if other pf_vlan still valid */
if (i != vf &&
vid == adapter->vfinfo[i].pf_vlan)
true_handle = 0;
}
clear_bit(__RNP_USE_VFINFI, &adapter->state);
}
}
skip_check:
if (true_handle)
hw->ops.set_vf_vlan_filter(hw, vid, vf, (bool)add, false);
if (adapter->priv_flags & RNP_PRIV_FLAG_SRIOV_VLAN_MODE) {
if (hw->ops.set_vf_vlan_mode)
hw->ops.set_vf_vlan_mode(hw, vid, vf, (bool)add);
}
return 0;
}
static inline void rnpgbe_vf_reset_event(struct rnpgbe_adapter *adapter, u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
int rar_entry = hw->mac.num_rar_entries - (vf + 1);
int i;
/* reset multicast table array for vf */
adapter->vfinfo[vf].num_vf_mc_hashes = 0;
/* Flush and reset the mta with the new values */
rnpgbe_set_rx_mode(adapter->netdev);
/* clear this rar_entry */
hw->ops.clr_rar(hw, rar_entry);
/* reset VF api back to unknown */
adapter->vfinfo[vf].vf_api = 0;
/* clear vf multicast */
for (i = 0; i < RNP_MAX_VF_MC_ENTRIES; i++)
adapter->vfinfo[vf].vf_mc_hashes[i] = 0;
/* clear vf vlan setup */
adapter->vfinfo[vf].vf_vlan = 0;
adapter->vfinfo[vf].vlan_count = 0;
}
static int rnpgbe_set_vf_mac(struct rnpgbe_adapter *adapter, int vf,
unsigned char *mac_addr)
{
struct rnpgbe_hw *hw = &adapter->hw;
/* this rar_entry may be cofict with mac vlan with pf */
int rar_entry = hw->mac.num_rar_entries - (vf + 1);
memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, 6);
/* setup to the hw */
hw->ops.set_rar_with_vf(hw, mac_addr, rar_entry, vf, true);
return 0;
}
static int rnpgbe_set_vf_macvlan(struct rnpgbe_adapter *adapter, int vf,
int index, unsigned char *mac_addr)
{
struct rnpgbe_hw *hw = &adapter->hw;
struct list_head *pos;
struct vf_macvlans *entry;
/* index = 0 , only earase */
/* index = 1 , earase and then set */
if (index <= 1) {
list_for_each(pos, &adapter->vf_mvs.l) {
entry = list_entry(pos, struct vf_macvlans, l);
if (entry->vf == vf) {
entry->vf = -1;
entry->free = true;
entry->is_macvlan = false;
hw->ops.clr_rar(hw, entry->rar_entry);
}
}
}
/* If index was zero then we were asked to clear the uc list
* for the VF. We're done.
*/
if (!index)
return 0;
entry = NULL;
list_for_each(pos, &adapter->vf_mvs.l) {
entry = list_entry(pos, struct vf_macvlans, l);
if (entry->free)
break;
}
/* If we traversed the entire list and didn't find a free entry
* then we're out of space on the RAR table. Also entry may
* be NULL because the original memory allocation for the list
* failed, which is not fatal but does mean we can't support
* VF requests for MACVLAN because we couldn't allocate
* memory for the list management required.
*/
if (!entry || !entry->free)
return -ENOSPC;
entry->free = false;
entry->is_macvlan = true;
entry->vf = vf;
memcpy(entry->vf_macvlan, mac_addr, ETH_ALEN);
hw->ops.set_rar_with_vf(hw, entry->vf_macvlan, entry->rar_entry,
entry->vf, true);
return 0;
}
int rnpgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
{
unsigned char vf_mac_addr[6];
struct rnpgbe_adapter *adapter = pci_get_drvdata(pdev);
unsigned int vfn = (event_mask & 0x3f);
bool enable = ((event_mask & 0x10000000U) != 0);
if (enable) {
eth_zero_addr(vf_mac_addr);
memcpy(vf_mac_addr, adapter->hw.mac.perm_addr, 6);
vf_mac_addr[5] = vf_mac_addr[5] + (0x80 | vfn);
vf_mac_addr[4] = vf_mac_addr[4] + (pdev->devfn);
memcpy(adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr, 6);
}
return 0;
}
static int rnpgbe_vf_reset_msg(struct rnpgbe_adapter *adapter, u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
u32 msgbuf[RNP_VF_PERMADDR_MSG_LEN];
u8 *addr = (u8 *)(&msgbuf[1]);
/* reset the filters for the device */
rnpgbe_vf_reset_event(adapter, vf);
/* set vf mac address */
if (!is_zero_ether_addr(vf_mac))
rnpgbe_set_vf_mac(adapter, vf, vf_mac);
/* enable VF mailbox for further messages */
adapter->vfinfo[vf].clear_to_send = true;
/* Enable counting of spoofed packets in the SSVPC register */
/* reply to reset with ack and vf mac address */
msgbuf[0] = RNP_VF_RESET;
if (!is_zero_ether_addr(vf_mac)) {
msgbuf[0] |= RNP_VT_MSGTYPE_ACK;
memcpy(addr, vf_mac, ETH_ALEN);
} else {
msgbuf[0] |= RNP_VT_MSGTYPE_NACK;
dev_warn(&adapter->pdev->dev,
"VF %d has no MAC address assigned, you may have to assign",
vf);
dev_warn(&adapter->pdev->dev, "one manually\n");
}
/* Piggyback the multicast filter type so VF can compute the
* correct vectors
*/
msgbuf[RNP_VF_MC_TYPE_WORD] = 0;
/* setup link status , pause mode, ft padding mode */
/* link status */
/* pause mode */
msgbuf[RNP_VF_MC_TYPE_WORD] |= (0xff & hw->fc.current_mode) << 16;
if (adapter->priv_flags & RNP_PRIV_FLAG_FT_PADDING)
msgbuf[RNP_VF_MC_TYPE_WORD] |= (0x01 << 8);
else
msgbuf[RNP_VF_MC_TYPE_WORD] |= (0x00 << 8);
/* mc_type */
msgbuf[RNP_VF_MC_TYPE_WORD] |= rd32(hw, RNP_ETH_DMAC_MCSTCTRL) & 0x03;
msgbuf[RNP_VF_DMA_VERSION_WORD] = rd32(hw, RNP_DMA_VERSION);
msgbuf[RNP_VF_VLAN_WORD] = adapter->vfinfo[vf].pf_vlan;
/* fixme tx fetch to be added here */
msgbuf[RNP_VF_PHY_TYPE_WORD] = (hw->mac_type << 16) | hw->phy_type;
msgbuf[RNP_VF_FW_VERSION_WORD] = (hw->fw_version);
if (adapter->vfinfo[vf].link_state == rnpgbe_link_state_auto) {
msgbuf[RNP_VF_LINK_STATUS_WORD] =
(adapter->link_up ? RNP_PF_LINK_UP : 0) |
adapter->link_speed;
} else if (adapter->vfinfo[vf].link_state == rnpgbe_link_state_on) {
msgbuf[RNP_VF_LINK_STATUS_WORD] = RNP_PF_LINK_UP |
adapter->link_speed;
} else {
msgbuf[RNP_VF_LINK_STATUS_WORD] = 0;
}
msgbuf[RNP_VF_AXI_MHZ] = hw->usecstocount;
if (adapter->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
msgbuf[RNP_VF_FEATURE] |= PF_FEATRURE_VLAN_FILTER;
if (hw->ncsi_en)
msgbuf[RNP_VF_FEATURE] |= PF_NCSI_EN;
/* now vf maybe has no irq handler if it is the first reset*/
rnpgbe_write_mbx(hw, msgbuf, RNP_VF_PERMADDR_MSG_LEN, vf);
return 0;
}
static int rnpgbe_get_vf_mac_addr(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
u8 *mac = ((u8 *)(&msgbuf[1]));
memcpy(mac, adapter->vfinfo[vf].vf_mac_addresses, 6);
return 0;
}
/* vf call setup a new mac */
static int rnpgbe_set_vf_mac_addr(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
u8 *new_mac = ((u8 *)(&msgbuf[1]));
if (!is_valid_ether_addr(new_mac)) {
e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
return -1;
}
if (adapter->vfinfo[vf].pf_set_mac &&
memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac, ETH_ALEN)) {
e_warn(drv,
"VF %d attempted to override administratively set MAC address\n",
vf);
e_warn(drv, "Reload the VF driver to resume operations\n");
return -1;
}
rnpgbe_set_vf_mac(adapter, vf, new_mac);
return 0;
}
static int rnpgbe_set_vf_vlan_msg(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
int add = ((msgbuf[0] & RNP_VT_MSGINFO_MASK) >> RNP_VT_MSGINFO_SHIFT);
int vid = (msgbuf[1] & RNP_VLVF_VLANID_MASK);
int err;
if (adapter->vfinfo[vf].pf_vlan) {
e_warn(drv,
"VF %d attempted to override administratively set VLAN ",
vf);
e_warn(drv, "configuration\n");
e_warn(drv, "Reload the VF driver to resume operations\n");
return -1;
}
if ((add) && adapter->vfinfo[vf].vlan_count) {
e_warn(drv, "VF %d attempted to set more than 1 vlan", vf);
e_warn(drv, " vlan now %d, try to set %d\n",
adapter->vfinfo[vf].vf_vlan, vid);
return -1;
}
/* vlan 0 has no work todo */
if (!vid)
return 0;
if (add) {
adapter->vfinfo[vf].vlan_count++;
/* store vf vlan setup */
adapter->vfinfo[vf].vf_vlan = vid;
} else if (adapter->vfinfo[vf].vlan_count) {
adapter->vfinfo[vf].vf_vlan = 0;
adapter->vfinfo[vf].vlan_count--;
}
err = rnpgbe_set_vf_vlan(adapter, add, vid, vf);
return err;
}
static int rnpgbe_set_vf_vlan_strip_msg(struct rnpgbe_adapter *adapter,
u32 *msgbuf, u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
int vlan_strip_on = !!(msgbuf[1] >> 31);
int queue_cnt = msgbuf[1] & 0xffff;
int err = 0, i;
for (i = 0; i < queue_cnt; i++) {
if (vlan_strip_on)
hw->ops.set_vlan_strip(hw, msgbuf[2 + i], true);
else
hw->ops.set_vlan_strip(hw, msgbuf[2 + i], false);
}
return err;
}
static int rnpgbe_set_vf_macvlan_msg(struct rnpgbe_adapter *adapter,
u32 *msgbuf, u32 vf)
{
u8 *new_mac = ((u8 *)(&msgbuf[1]));
int index = (msgbuf[0] & RNP_VT_MSGINFO_MASK) >> RNP_VT_MSGINFO_SHIFT;
int err;
if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
e_warn(drv,
"VF %d requested MACVLAN filter but is administratively denied\n",
vf);
return -1;
}
/* An non-zero index indicates the VF is setting a filter */
if (index) {
if (!is_valid_ether_addr(new_mac)) {
e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
return -1;
}
}
err = rnpgbe_set_vf_macvlan(adapter, vf, index, new_mac);
if (err == -ENOSPC)
e_warn(drv,
"VF %d has requested a MACVLAN filter but there is no space\n",
vf);
return err;
}
static int rnpgbe_negotiate_vf_api(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
adapter->vfinfo[vf].vf_api = 0;
return 0;
}
static int rnpgbe_get_vf_reg(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
u32 reg = msgbuf[1];
msgbuf[1] = rd32(&adapter->hw, reg);
return 0;
}
static int rnpgbe_set_vf_mtu(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
struct net_device *netdev = adapter->netdev;
if (msgbuf[1] > netdev->mtu) {
e_dev_warn("vf %d try to change mtu large than pf limit\n",
vf);
return -1;
} else {
return 0;
}
}
static int rnpgbe_get_vf_mtu(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
struct net_device *netdev = adapter->netdev;
msgbuf[1] = netdev->mtu;
return 0;
}
static int rnpgbe_get_vf_fw(struct rnpgbe_adapter *adapter, u32 *msgbuf, u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
msgbuf[1] = hw->fw_version;
return 0;
}
static int rnpgbe_get_vf_link(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
if (adapter->vfinfo[vf].link_state == rnpgbe_link_state_auto) {
msgbuf[1] = (adapter->link_up ? RNP_PF_LINK_UP : 0) |
adapter->link_speed;
} else if (adapter->vfinfo[vf].link_state == rnpgbe_link_state_on) {
msgbuf[1] = RNP_PF_LINK_UP | adapter->link_speed;
} else {
msgbuf[1] = 0;
}
return 0;
}
static int rnpgbe_get_vf_dma_frag(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
/* we fixed 1536 bytes */
msgbuf[1] = 1536;
return 0;
}
static int rnpgbe_vf_get_stats_clr(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
struct rnpgbe_dma_info *dma = &hw->dma;
if (dma_rd32(dma, RNP500_STATISTIC_CRL(vf)))
msgbuf[1] = 1;
else
msgbuf[1] = 0;
return 0;
}
static int rnpgbe_vf_set_stats_clr(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
struct rnpgbe_dma_info *dma = &hw->dma;
if (msgbuf[1])
dma_wr32(dma, RNP500_STATISTIC_CRL(vf), 1);
else
dma_wr32(dma, RNP500_STATISTIC_CRL(vf), 0);
return 0;
}
static int rnpgbe_get_vf_queues(struct rnpgbe_adapter *adapter, u32 *msgbuf,
u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
msgbuf[RNP_VF_TX_QUEUES] = hw->sriov_ring_limit;
msgbuf[RNP_VF_RX_QUEUES] = hw->sriov_ring_limit;
msgbuf[RNP_VF_TRANS_VLAN] = adapter->vfinfo[vf].pf_vlan;
msgbuf[RNP_VF_DEF_QUEUE] = 0;
if (hw->hw_type == rnpgbe_hw_n400) {
/* n400, we use */
/* vf0 use ring4 */
/* vf1 use ring8 */
msgbuf[RNP_VF_QUEUE_START] = vf * 4 + 4;
} else {
msgbuf[RNP_VF_QUEUE_START] = vf * hw->sriov_ring_limit;
}
msgbuf[RNP_VF_QUEUE_DEPTH] = (adapter->tx_ring_item_count << 16) |
adapter->rx_ring_item_count;
return 0;
}
static int rnpgbe_rcv_msg_from_vf(struct rnpgbe_adapter *adapter, u32 vf)
{
u32 mbx_size = RNP_VFMAILBOX_SIZE;
u32 msgbuf[RNP_VFMAILBOX_SIZE];
struct rnpgbe_hw *hw = &adapter->hw;
s32 retval;
vf_dbg("msg from vf:%d\n", vf);
retval = rnpgbe_read_mbx(hw, msgbuf, mbx_size, vf);
if (retval) {
pr_err("Error receiving message from VF\n");
return retval;
}
vf_dbg("msg[0]=0x%08x\n", msgbuf[0]);
/* this is a message we already processed, do nothing */
if (msgbuf[0] & (RNP_VT_MSGTYPE_ACK | RNP_VT_MSGTYPE_NACK))
return retval;
/* flush the ack before we write any messages back */
/* clear vf_num */
msgbuf[0] &= (~RNP_VF_MASK);
/* this is a vf reset irq */
if ((msgbuf[0] & RNP_MAIL_CMD_MASK) == RNP_VF_RESET) {
vf_dbg("vf %d up\n", vf);
return rnpgbe_vf_reset_msg(adapter, vf);
}
/* until the vf completes a virtual function reset it should not be
* allowed to start any configuration.
*/
if (!adapter->vfinfo[vf].clear_to_send) {
vf_dbg("wait vf clear to send\n");
msgbuf[0] |= RNP_VT_MSGTYPE_NACK;
rnpgbe_write_mbx(hw, msgbuf, 1, vf);
return retval;
}
switch ((msgbuf[0] & RNP_MAIL_CMD_MASK)) {
case RNP_VF_SET_MAC_ADDR:
retval = rnpgbe_set_vf_mac_addr(adapter, msgbuf, vf);
break;
case RNP_VF_SET_MULTICAST:
retval = rnpgbe_set_vf_multicasts(adapter, msgbuf, vf);
break;
case RNP_VF_SET_VLAN:
retval = rnpgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
break;
case RNP_VF_SET_VLAN_STRIP:
retval = rnpgbe_set_vf_vlan_strip_msg(adapter, msgbuf, vf);
break;
case RNP_VF_GET_MACADDR:
retval = rnpgbe_get_vf_mac_addr(adapter, msgbuf, vf);
break;
case RNP_VF_SET_MACVLAN:
retval = rnpgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
break;
case RNP_VF_API_NEGOTIATE:
retval = rnpgbe_negotiate_vf_api(adapter, msgbuf, vf);
break;
case RNP_VF_GET_QUEUES:
retval = rnpgbe_get_vf_queues(adapter, msgbuf, vf);
break;
case RNP_VF_REG_RD:
retval = rnpgbe_get_vf_reg(adapter, msgbuf, vf);
break;
case RNP_VF_GET_MTU:
retval = rnpgbe_get_vf_mtu(adapter, msgbuf, vf);
break;
case RNP_VF_SET_MTU:
retval = rnpgbe_set_vf_mtu(adapter, msgbuf, vf);
break;
case RNP_VF_GET_FW:
retval = rnpgbe_get_vf_fw(adapter, msgbuf, vf);
break;
case RNP_VF_GET_LINK:
retval = rnpgbe_get_vf_link(adapter, msgbuf, vf);
break;
case RNP_PF_REMOVE:
vf_dbg("vf %d removed\n", vf);
adapter->vfinfo[vf].clear_to_send = false;
adapter->vfinfo[vf].vf_vlan = 0;
retval = 1;
break;
case RNP_VF_RESET_PF:
adapter->flags2 |= RNP_FLAG2_RESET_PF;
retval = 1;
break;
case RNP_VF_GET_DMA_FRAG:
retval = rnpgbe_get_vf_dma_frag(adapter, msgbuf, vf);
break;
case RNP_VF_SET_STATS_CLR:
retval = rnpgbe_vf_set_stats_clr(adapter, msgbuf, vf);
break;
case RNP_VF_GET_STATS_CLR:
retval = rnpgbe_vf_get_stats_clr(adapter, msgbuf, vf);
break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
retval = RNP_ERR_MBX;
break;
}
/* notify the VF of the results of what it sent us */
if (retval)
msgbuf[0] |= RNP_VT_MSGTYPE_NACK;
else
msgbuf[0] |= RNP_VT_MSGTYPE_ACK;
/* write vf_num */
msgbuf[0] |= (vf << 21);
msgbuf[0] |= RNP_VT_MSGTYPE_CTS;
if ((msgbuf[0] & RNP_MAIL_CMD_MASK) != RNP_PF_REMOVE)
rnpgbe_write_mbx(hw, msgbuf, mbx_size, vf);
return retval;
}
static void rnpgbe_rcv_ack_from_vf(struct rnpgbe_adapter *adapter, u32 vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
u32 msg = RNP_VT_MSGTYPE_NACK;
/* if device isn't clear to send it shouldn't be reading either */
if (!adapter->vfinfo[vf].clear_to_send)
rnpgbe_write_mbx(hw, &msg, 1, vf);
}
void rnpgbe_msg_task(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
u32 vf;
rnpgbe_fw_msg_handler(adapter);
if (!(adapter->flags & RNP_FLAG_SRIOV_INIT_DONE))
return;
for (vf = 0; vf < adapter->num_vfs; vf++) {
if (test_and_set_bit(__VF_MBX_USED,
&adapter->vfinfo[vf].status)) {
adapter->miss_time++;
e_info(drv, "we missed some irqs %d\n", vf);
continue;
}
/* process any messages pending */
if (!rnpgbe_check_for_msg(hw, vf))
rnpgbe_rcv_msg_from_vf(adapter, vf);
/* process any acks */
if (!rnpgbe_check_for_ack(hw, vf))
rnpgbe_rcv_ack_from_vf(adapter, vf);
clear_bit(__VF_MBX_USED, &adapter->vfinfo[vf].status);
}
}
static int rnpgbe_msg_post_status_signle_link(struct rnpgbe_adapter *adapter,
int vf,
int link_state)
{
u32 msgbuf[RNP_VFMAILBOX_SIZE];
struct rnpgbe_hw *hw = &adapter->hw;
struct rnpgbe_mbx_info *mbx = &hw->mbx;
msgbuf[0] = RNP_PF_SET_LINK | (vf << RNP_VNUM_OFFSET);
switch (link_state) {
case rnpgbe_link_state_on:
msgbuf[1] = RNP_PF_LINK_UP | adapter->link_speed;
break;
case rnpgbe_link_state_off:
msgbuf[1] = 0;
break;
case rnpgbe_link_state_auto:
if (adapter->link_up)
msgbuf[1] = RNP_PF_LINK_UP | adapter->link_speed;
else
msgbuf[1] = 0;
break;
}
return mbx->ops.write(hw, msgbuf, 2, vf);
}
int rnpgbe_msg_post_status_signle(struct rnpgbe_adapter *adapter,
enum PF_STATUS status, int vf)
{
u32 msgbuf[RNP_VFMAILBOX_SIZE];
struct rnpgbe_hw *hw = &adapter->hw;
struct rnpgbe_mbx_info *mbx = &hw->mbx;
switch (status) {
case PF_FCS_STATUS:
msgbuf[0] = RNP_PF_SET_FCS | (vf << RNP_VNUM_OFFSET);
if (adapter->netdev->features & NETIF_F_RXFCS)
msgbuf[1] = 1;
else
msgbuf[1] = 0;
break;
case PF_PAUSE_STATUS:
msgbuf[0] = RNP_PF_SET_PAUSE | (vf << RNP_VNUM_OFFSET);
msgbuf[1] = hw->fc.requested_mode;
break;
case PF_FT_PADDING_STATUS:
msgbuf[0] = RNP_PF_SET_FT_PADDING | (vf << RNP_VNUM_OFFSET);
if (adapter->priv_flags & RNP_PRIV_FLAG_FT_PADDING)
msgbuf[1] = 1;
else
msgbuf[1] = 0;
break;
case PF_VLAN_FILTER_STATUS:
msgbuf[0] = RNP_PF_SET_VLAN_FILTER | (vf << RNP_VNUM_OFFSET);
if (adapter->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
msgbuf[1] = 1;
else
msgbuf[1] = 0;
break;
case PF_SET_VLAN_STATUS:
msgbuf[0] = RNP_PF_SET_VLAN | (vf << RNP_VNUM_OFFSET);
msgbuf[1] = adapter->vfinfo[vf].pf_vlan;
break;
case PF_SET_LINK_STATUS:
if (adapter->vfinfo[vf].link_state != rnpgbe_link_state_auto)
return 0;
/* only update link state if in auto mode */
msgbuf[0] = RNP_PF_SET_LINK | (vf << RNP_VNUM_OFFSET);
if (adapter->link_up)
msgbuf[1] = RNP_PF_LINK_UP | adapter->link_speed;
else
msgbuf[1] = 0;
break;
case PF_SET_MTU:
msgbuf[0] = RNP_PF_SET_MTU | (vf << RNP_VNUM_OFFSET);
msgbuf[1] = adapter->netdev->mtu;
break;
case PF_SET_RESET:
msgbuf[0] = RNP_PF_SET_RESET | (vf << RNP_VNUM_OFFSET);
msgbuf[1] = 0;
break;
}
return mbx->ops.write_posted(hw, msgbuf, 2, vf);
}
/* try to send mailbox to all active vf */
int rnpgbe_msg_post_status(struct rnpgbe_adapter *adapter,
enum PF_STATUS status)
{
u32 vf;
int err = 0;
if (!(adapter->flags & RNP_FLAG_SRIOV_ENABLED))
return 0;
/* broadcast */
for (vf = 0; vf < adapter->num_vfs; vf++) {
if (!(adapter->vfinfo[vf].clear_to_send))
continue;
if (!test_bit(__RNP_IN_IRQ, &adapter->state)) {
if (test_and_set_bit(__VF_MBX_USED,
&adapter->vfinfo[vf].status)) {
adapter->miss_time++;
return -1;
}
err |= rnpgbe_msg_post_status_signle(adapter, status,
vf);
clear_bit(__VF_MBX_USED, &adapter->vfinfo[vf].status);
}
}
return err;
}
void rnpgbe_ping_all_vfs(struct rnpgbe_adapter *adapter)
{
struct rnpgbe_hw *hw = &adapter->hw;
u32 ping;
int i;
for (i = 0; i < adapter->num_vfs; i++) {
ping = RNP_PF_CONTROL_PRING_MSG;
/* only send to active vf */
ping |= RNP_VT_MSGTYPE_CTS;
rnpgbe_write_mbx(hw, &ping, 1, i);
}
}
int rnpgbe_get_vf_ringnum(struct rnpgbe_hw *hw, int vf, int num)
{
return vf;
}
int rnpgbe_setup_ring_maxrate(struct rnpgbe_adapter *adapter, int ring,
u64 max_rate)
{
struct rnpgbe_hw *hw = &adapter->hw;
struct rnpgbe_dma_info *dma = &hw->dma;
int samples_1sec = adapter->hw.usecstocount * 1000000;
dma_ring_wr32(dma, RING_OFFSET(ring) + RNP_DMA_REG_TX_FLOW_CTRL_TM,
samples_1sec);
dma_ring_wr32(dma, RING_OFFSET(ring) + RNP_DMA_REG_TX_FLOW_CTRL_TH,
max_rate);
return 0;
}
static int rnpgbe_disable_port_vlan(struct rnpgbe_adapter *adapter, int vf)
{
struct rnpgbe_hw *hw = &adapter->hw;
int err;
err = rnpgbe_set_vf_vlan(adapter, false, adapter->vfinfo[vf].pf_vlan,
vf);
if (adapter->priv_flags & RNP_PRIV_FLAG_SRIOV_VLAN_MODE) {
if (hw->ops.set_vf_vlan_mode) {
hw->ops.set_vf_vlan_mode(hw,
adapter->vfinfo[vf].pf_vlan, vf, false);
}
}
adapter->vfinfo[vf].pf_vlan = 0;
adapter->vfinfo[vf].pf_qos = 0;
/* clear veb */
hw->ops.set_vf_vlan_filter(hw, 0, vf, false, true);
return err;
}
static int rnpgbe_enable_port_vlan(struct rnpgbe_adapter *adapter, int vf,
u16 vlan, u8 qos)
{
struct rnpgbe_hw *hw = &adapter->hw;
int err;
err = rnpgbe_set_vf_vlan(adapter, true, vlan, vf);
if (err)
goto out;
adapter->vfinfo[vf].pf_vlan = vlan;
adapter->vfinfo[vf].pf_qos = qos;
dev_info(&adapter->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
vlan, qos, vf);
if (test_bit(__RNP_DOWN, &adapter->state)) {
dev_warn(&adapter->pdev->dev,
"The VF VLAN has been set, but the PF device is not up.\n");
dev_warn(&adapter->pdev->dev,
"Bring the PF device up before attempting to use the VF device.\n");
}
hw->ops.set_vf_vlan_filter(hw, vlan, vf, true, true);
/* if in sriov vlan mode should setup pfvlvf table */
if (adapter->priv_flags & RNP_PRIV_FLAG_SRIOV_VLAN_MODE) {
if (hw->ops.set_vf_vlan_mode)
hw->ops.set_vf_vlan_mode(hw, vlan, vf, true);
}
out:
return err;
}
int rnpgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
__be16 vlan_proto)
{
int err = 0;
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
/* VLAN IDs accepted range 0-4094 */
if (vf < 0 || vf >= adapter->num_vfs || vlan > VLAN_VID_MASK - 1 ||
qos > 7)
return -EINVAL;
if (vlan_proto != htons(ETH_P_8021Q))
return -EPROTONOSUPPORT;
if (vlan || qos) {
/* Check if there is already a port VLAN set, if so
* we have to delete the old one first before we
* can set the new one. The usage model had
* previously assumed the user would delete the
* old port VLAN before setting a new one but this
* is not necessarily the case.
*/
if (adapter->vfinfo[vf].vf_vlan) {
dev_err(&adapter->pdev->dev,
"vf set vlan before, delete it before add new\n");
err = -EINVAL;
goto out;
}
if (adapter->vfinfo[vf].pf_vlan)
err = rnpgbe_disable_port_vlan(adapter, vf);
if (err)
goto out;
err = rnpgbe_enable_port_vlan(adapter, vf, vlan, qos);
} else {
/* if vf set vlan, return error */
if (!adapter->vfinfo[vf].pf_vlan &&
adapter->vfinfo[vf].vf_vlan) {
dev_err(&adapter->pdev->dev,
"pf can't delete vf set vlan\n");
err = -EINVAL;
goto out;
} else if (adapter->vfinfo[vf].pf_vlan) {
err = rnpgbe_disable_port_vlan(adapter, vf);
}
}
/* send mbx to vf */
if (adapter->vfinfo[vf].clear_to_send)
rnpgbe_msg_post_status_signle(adapter, PF_SET_VLAN_STATUS, vf);
out:
return err;
}
int rnpgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
if (vf < 0 || vf >= adapter->num_vfs)
return -EINVAL;
/* maybe we not support this in hw */
adapter->vfinfo[vf].spoofchk_enabled = setting;
return 0;
}
int rnpgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
if (vf < 0 || vf >= adapter->num_vfs)
return -EINVAL;
/* nothing to do */
if (adapter->vfinfo[vf].trusted == setting)
return 0;
adapter->vfinfo[vf].trusted = setting;
e_info(drv, "VF %u is %strusted\n", vf, setting ? "" : "not ");
return 0;
}
int rnpgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
int ret = 0;
if (vf < 0 || vf >= adapter->num_vfs) {
dev_err(&adapter->pdev->dev,
"NDO set VF link - invalid VF identifier %d\n", vf);
ret = -EINVAL;
goto out;
}
switch (state) {
case IFLA_VF_LINK_STATE_ENABLE:
dev_info(&adapter->pdev->dev, "NDO set VF %d link state %d\n",
vf, state);
adapter->vfinfo[vf].link_state = rnpgbe_link_state_on;
rnpgbe_msg_post_status_signle_link(adapter, vf,
rnpgbe_link_state_on);
break;
case IFLA_VF_LINK_STATE_DISABLE:
dev_info(&adapter->pdev->dev,
"NDO set VF %d link state disable\n", vf);
adapter->vfinfo[vf].link_state = rnpgbe_link_state_off;
rnpgbe_msg_post_status_signle_link(adapter, vf,
rnpgbe_link_state_off);
break;
case IFLA_VF_LINK_STATE_AUTO:
dev_info(&adapter->pdev->dev, "NDO set VF %d link state auto\n",
vf);
adapter->vfinfo[vf].link_state = rnpgbe_link_state_auto;
rnpgbe_msg_post_status_signle_link(adapter, vf,
rnpgbe_link_state_auto);
break;
default:
dev_err(&adapter->pdev->dev,
"NDO set VF %d - invalid link state %d\n", vf, state);
ret = -EINVAL;
}
out:
return ret;
}
int rnpgbe_ndo_set_vf_bw(struct net_device *netdev, int vf,
int __always_unused min_tx_rate, int max_tx_rate)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
struct rnpgbe_hw *hw = &adapter->hw;
/* limit vf ring rate */
int ring_max_rate;
int vf_ring;
int link_speed = 0;
u64 real_rate = 0;
if (vf >= hw->max_vfs - 1)
return -EINVAL;
switch (adapter->link_speed) {
case RNP_LINK_SPEED_40GB_FULL:
link_speed = 40000;
break;
case RNP_LINK_SPEED_25GB_FULL:
link_speed = 25000;
break;
case RNP_LINK_SPEED_10GB_FULL:
link_speed = 10000;
break;
case RNP_LINK_SPEED_1GB_FULL:
link_speed = 1000;
break;
case RNP_LINK_SPEED_100_FULL:
link_speed = 100;
break;
}
/* rate limit cannot be less than 1Mbs or greater than link speed */
if (max_tx_rate && (max_tx_rate <= 1 || max_tx_rate > link_speed))
return -EINVAL;
adapter->vfinfo[vf].tx_rate = max_tx_rate;
ring_max_rate = max_tx_rate / hw->sriov_ring_limit;
real_rate = (ring_max_rate * 1024 * 128);
vf_ring = rnpgbe_get_vf_ringnum(hw, vf, 0);
rnpgbe_setup_ring_maxrate(adapter, vf_ring, real_rate);
return 0;
}
int rnpgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
return -EINVAL;
adapter->vfinfo[vf].pf_set_mac = true;
dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf);
dev_info(&adapter->pdev->dev, "Reload the VF driver to make this");
dev_info(&adapter->pdev->dev, "change effective.");
if (test_bit(__RNP_DOWN, &adapter->state)) {
dev_warn(&adapter->pdev->dev,
"The VF MAC address has been set,");
dev_warn(&adapter->pdev->dev,
" but the PF device is not up.\n");
dev_warn(&adapter->pdev->dev, "Bring the PF device up before");
dev_warn(&adapter->pdev->dev,
" attempting to use the VF device.\n");
}
rnpgbe_set_vf_mac(adapter, vf, mac);
/* send reset to vf only vf is up */
if (adapter->vfinfo[vf].clear_to_send)
rnpgbe_msg_post_status_signle(adapter, PF_SET_RESET, vf);
return 0;
}
int rnpgbe_ndo_get_vf_config(struct net_device *netdev, int vf,
struct ifla_vf_info *ivi)
{
struct rnpgbe_adapter *adapter = netdev_priv(netdev);
if (vf >= adapter->num_vfs)
return -EINVAL;
ivi->vf = vf;
memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN);
ivi->max_tx_rate = adapter->vfinfo[vf].tx_rate;
ivi->min_tx_rate = 0;
if (adapter->vfinfo[vf].pf_vlan)
ivi->vlan = adapter->vfinfo[vf].pf_vlan;
else
ivi->vlan = adapter->vfinfo[vf].vf_vlan;
ivi->qos = adapter->vfinfo[vf].pf_qos;
ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled;
ivi->linkstate = adapter->vfinfo[vf].link_state;
ivi->trusted = adapter->vfinfo[vf].trusted;
return 0;
}
int rnpgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
{
if (num_vfs == 0)
return rnpgbe_pci_sriov_disable(dev);
else
return rnpgbe_pci_sriov_enable(dev, num_vfs);
}