Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5cb8db4a authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher
Browse files

fm10k: Add support for VF



This patch provides the functions necessary to configure the VF making use
of the same API pointers as the PF.

Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b651957c
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -28,5 +28,5 @@
obj-$(CONFIG_FM10K) += fm10k.o
obj-$(CONFIG_FM10K) += fm10k.o


fm10k-objs := fm10k_main.o fm10k_common.o fm10k_pci.o \
fm10k-objs := fm10k_main.o fm10k_common.o fm10k_pci.o \
	      fm10k_netdev.o fm10k_ethtool.o fm10k_pf.o \
	      fm10k_netdev.o fm10k_ethtool.o fm10k_pf.o fm10k_vf.o \
	      fm10k_mbx.o fm10k_tlv.o
	      fm10k_mbx.o fm10k_tlv.o
+3 −1
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/pci.h>


#include "fm10k_pf.h"
#include "fm10k_pf.h"
#include "fm10k_vf.h"


#define FM10K_MAX_JUMBO_FRAME_SIZE	15358	/* Maximum supported size 15K */
#define FM10K_MAX_JUMBO_FRAME_SIZE	15358	/* Maximum supported size 15K */


@@ -180,12 +181,13 @@ static inline struct netdev_queue *txring_txq(const struct fm10k_ring *ring)
#define MIN_Q_VECTORS	1
#define MIN_Q_VECTORS	1
enum fm10k_non_q_vectors {
enum fm10k_non_q_vectors {
	FM10K_MBX_VECTOR,
	FM10K_MBX_VECTOR,
#define NON_Q_VECTORS_VF NON_Q_VECTORS_PF
	NON_Q_VECTORS_PF
	NON_Q_VECTORS_PF
};
};


#define NON_Q_VECTORS(hw)	(((hw)->mac.type == fm10k_mac_pf) ? \
#define NON_Q_VECTORS(hw)	(((hw)->mac.type == fm10k_mac_pf) ? \
						NON_Q_VECTORS_PF : \
						NON_Q_VECTORS_PF : \
						0)
						NON_Q_VECTORS_VF)
#define MIN_MSIX_COUNT(hw)	(MIN_Q_VECTORS + NON_Q_VECTORS(hw))
#define MIN_MSIX_COUNT(hw)	(MIN_Q_VECTORS + NON_Q_VECTORS(hw))


struct fm10k_q_vector {
struct fm10k_q_vector {
+114 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,17 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = {
			 FM10K_NETDEV_STATS_LEN + \
			 FM10K_NETDEV_STATS_LEN + \
			 FM10K_QUEUE_STATS_LEN)
			 FM10K_QUEUE_STATS_LEN)


static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
	"Mailbox test (on/offline)"
};

#define FM10K_TEST_LEN (sizeof(fm10k_gstrings_test) / ETH_GSTRING_LEN)

enum fm10k_self_test_types {
	FM10K_TEST_MBX,
	FM10K_TEST_MAX = FM10K_TEST_LEN
};

static void fm10k_get_strings(struct net_device *dev, u32 stringset,
static void fm10k_get_strings(struct net_device *dev, u32 stringset,
			      u8 *data)
			      u8 *data)
{
{
@@ -109,6 +120,10 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
	int i;
	int i;


	switch (stringset) {
	switch (stringset) {
	case ETH_SS_TEST:
		memcpy(data, *fm10k_gstrings_test,
		       FM10K_TEST_LEN * ETH_GSTRING_LEN);
		break;
	case ETH_SS_STATS:
	case ETH_SS_STATS:
		for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) {
		for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) {
			memcpy(p, fm10k_gstrings_net_stats[i].stat_string,
			memcpy(p, fm10k_gstrings_net_stats[i].stat_string,
@@ -138,6 +153,8 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
static int fm10k_get_sset_count(struct net_device *dev, int sset)
static int fm10k_get_sset_count(struct net_device *dev, int sset)
{
{
	switch (sset) {
	switch (sset) {
	case ETH_SS_TEST:
		return FM10K_TEST_LEN;
	case ETH_SS_STATS:
	case ETH_SS_STATS:
		return FM10K_STATS_LEN;
		return FM10K_STATS_LEN;
	default:
	default:
@@ -287,6 +304,28 @@ static void fm10k_get_regs(struct net_device *netdev,
		for (i = 0; i < 130; i++)
		for (i = 0; i < 130; i++)
			*(buff++) = fm10k_read_reg(hw, FM10K_ITR(i));
			*(buff++) = fm10k_read_reg(hw, FM10K_ITR(i));


		break;
	case fm10k_mac_vf:
		/* General VF registers */
		*(buff++) = fm10k_read_reg(hw, FM10K_VFCTRL);
		*(buff++) = fm10k_read_reg(hw, FM10K_VFINT_MAP);
		*(buff++) = fm10k_read_reg(hw, FM10K_VFSYSTIME);

		/* Interrupt Throttling Registers */
		for (i = 0; i < 8; i++)
			*(buff++) = fm10k_read_reg(hw, FM10K_VFITR(i));

		fm10k_get_reg_vsi(hw, buff, 0);
		buff += FM10K_REGS_LEN_VSI;

		for (i = 0; i < FM10K_MAX_QUEUES_POOL; i++) {
			if (i < hw->mac.max_queues)
				fm10k_get_reg_q(hw, buff, i);
			else
				memset(buff, 0, sizeof(u32) * FM10K_REGS_LEN_Q);
			buff += FM10K_REGS_LEN_Q;
		}

		break;
		break;
	default:
	default:
		return;
		return;
@@ -296,6 +335,8 @@ static void fm10k_get_regs(struct net_device *netdev,
/* If function above adds more registers these define need to be updated */
/* If function above adds more registers these define need to be updated */
#define FM10K_REGS_LEN_PF \
#define FM10K_REGS_LEN_PF \
(162 + (65 * FM10K_REGS_LEN_VSI) + (FM10K_MAX_QUEUES_PF * FM10K_REGS_LEN_Q))
(162 + (65 * FM10K_REGS_LEN_VSI) + (FM10K_MAX_QUEUES_PF * FM10K_REGS_LEN_Q))
#define FM10K_REGS_LEN_VF \
(11 + FM10K_REGS_LEN_VSI + (FM10K_MAX_QUEUES_POOL * FM10K_REGS_LEN_Q))


static int fm10k_get_regs_len(struct net_device *netdev)
static int fm10k_get_regs_len(struct net_device *netdev)
{
{
@@ -305,6 +346,8 @@ static int fm10k_get_regs_len(struct net_device *netdev)
	switch (hw->mac.type) {
	switch (hw->mac.type) {
	case fm10k_mac_pf:
	case fm10k_mac_pf:
		return FM10K_REGS_LEN_PF * sizeof(u32);
		return FM10K_REGS_LEN_PF * sizeof(u32);
	case fm10k_mac_vf:
		return FM10K_REGS_LEN_VF * sizeof(u32);
	default:
	default:
		return 0;
		return 0;
	}
	}
@@ -734,6 +777,76 @@ static int fm10k_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
	return ret;
	return ret;
}
}


static int fm10k_mbx_test(struct fm10k_intfc *interface, u64 *data)
{
	struct fm10k_hw *hw = &interface->hw;
	struct fm10k_mbx_info *mbx = &hw->mbx;
	u32 attr_flag, test_msg[6];
	unsigned long timeout;
	int err;

	/* For now this is a VF only feature */
	if (hw->mac.type != fm10k_mac_vf)
		return 0;

	/* loop through both nested and unnested attribute types */
	for (attr_flag = (1 << FM10K_TEST_MSG_UNSET);
	     attr_flag < (1 << (2 * FM10K_TEST_MSG_NESTED));
	     attr_flag += attr_flag) {
		/* generate message to be tested */
		fm10k_tlv_msg_test_create(test_msg, attr_flag);

		fm10k_mbx_lock(interface);
		mbx->test_result = FM10K_NOT_IMPLEMENTED;
		err = mbx->ops.enqueue_tx(hw, mbx, test_msg);
		fm10k_mbx_unlock(interface);

		/* wait up to 1 second for response */
		timeout = jiffies + HZ;
		do {
			if (err < 0)
				goto err_out;

			usleep_range(500, 1000);

			fm10k_mbx_lock(interface);
			mbx->ops.process(hw, mbx);
			fm10k_mbx_unlock(interface);

			err = mbx->test_result;
			if (!err)
				break;
		} while (time_is_after_jiffies(timeout));

		/* reporting errors */
		if (err)
			goto err_out;
	}

err_out:
	*data = err < 0 ? (attr_flag) : (err > 0);
	return err;
}

static void fm10k_self_test(struct net_device *dev,
			    struct ethtool_test *eth_test, u64 *data)
{
	struct fm10k_intfc *interface = netdev_priv(dev);
	struct fm10k_hw *hw = &interface->hw;

	memset(data, 0, sizeof(*data) * FM10K_TEST_LEN);

	if (FM10K_REMOVED(hw)) {
		netif_err(interface, drv, dev,
			  "Interface removed - test blocked\n");
		eth_test->flags |= ETH_TEST_FL_FAILED;
		return;
	}

	if (fm10k_mbx_test(interface, &data[FM10K_TEST_MBX]))
		eth_test->flags |= ETH_TEST_FL_FAILED;
}

static u32 fm10k_get_reta_size(struct net_device *netdev)
static u32 fm10k_get_reta_size(struct net_device *netdev)
{
{
	return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
	return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
@@ -911,6 +1024,7 @@ static const struct ethtool_ops fm10k_ethtool_ops = {
	.set_rxnfc		= fm10k_set_rxnfc,
	.set_rxnfc		= fm10k_set_rxnfc,
	.get_regs               = fm10k_get_regs,
	.get_regs               = fm10k_get_regs,
	.get_regs_len           = fm10k_get_regs_len,
	.get_regs_len           = fm10k_get_regs_len,
	.self_test		= fm10k_self_test,
	.get_rxfh_indir_size	= fm10k_get_reta_size,
	.get_rxfh_indir_size	= fm10k_get_reta_size,
	.get_rxfh_key_size	= fm10k_get_rssrk_size,
	.get_rxfh_key_size	= fm10k_get_rssrk_size,
	.get_rxfh		= fm10k_get_rssh,
	.get_rxfh		= fm10k_get_rssh,
+4 −0
Original line number Original line Diff line number Diff line
@@ -1517,6 +1517,10 @@ s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
{
{
	/* initialize registers */
	/* initialize registers */
	switch (hw->mac.type) {
	switch (hw->mac.type) {
	case fm10k_mac_vf:
		mbx->mbx_reg = FM10K_VFMBX;
		mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
		break;
	case fm10k_mac_pf:
	case fm10k_mac_pf:
		/* there are only 64 VF <-> PF mailboxes */
		/* there are only 64 VF <-> PF mailboxes */
		if (id < 64) {
		if (id < 64) {
+15 −0
Original line number Original line Diff line number Diff line
@@ -976,6 +976,21 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
	int xcast_mode;
	int xcast_mode;
	u16 vid, glort;
	u16 vid, glort;


	/* restore our address if perm_addr is set */
	if (hw->mac.type == fm10k_mac_vf) {
		if (is_valid_ether_addr(hw->mac.perm_addr)) {
			ether_addr_copy(hw->mac.addr, hw->mac.perm_addr);
			ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr);
			ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr);
			netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
		}

		if (hw->mac.vlan_override)
			netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
		else
			netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
	}

	/* record glort for this interface */
	/* record glort for this interface */
	glort = interface->glort;
	glort = interface->glort;


Loading