Commit 56e94095 authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher
Browse files

ixgbevf: Add VF DCB + SR-IOV support



This change adds support for DCB and SR-IOV from the VF.  With this change
in place the VF will correctly use a traffic class other than 0 in the case
that the PF is configured with the default user priority belonging to a
traffic class other than 0.

Cc: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Tested-by: default avatarSibai Li <sibai.li@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent bffb3bc9
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -33,8 +33,11 @@
#define IXGBE_DEV_ID_X540_VF            0x1515

#define IXGBE_VF_IRQ_CLEAR_MASK         7
#define IXGBE_VF_MAX_TX_QUEUES          1
#define IXGBE_VF_MAX_RX_QUEUES          1
#define IXGBE_VF_MAX_TX_QUEUES          8
#define IXGBE_VF_MAX_RX_QUEUES          8

/* DCB define */
#define IXGBE_VF_MAX_TRAFFIC_CLASS	8

/* Link speed */
typedef u32 ixgbe_link_speed;
+2 −2
Original line number Diff line number Diff line
@@ -89,8 +89,8 @@ struct ixgbevf_ring {
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IXGBEVF_RX_BUFFER_WRITE	16	/* Must be power of 2 */

#define MAX_RX_QUEUES 1
#define MAX_TX_QUEUES 1
#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES
#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES

#define IXGBEVF_DEFAULT_TXD   1024
#define IXGBEVF_DEFAULT_RXD   512
+155 −4
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");

/* forward decls */
static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter);

static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
					   struct ixgbevf_ring *rx_ring,
@@ -1335,7 +1336,8 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	int api[] = { ixgbe_mbox_api_10,
	int api[] = { ixgbe_mbox_api_11,
		      ixgbe_mbox_api_10,
		      ixgbe_mbox_api_unknown };
	int err = 0, idx = 0;

@@ -1413,12 +1415,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
	mod_timer(&adapter->watchdog_timer, jiffies);
}

static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	struct ixgbevf_ring *rx_ring;
	unsigned int def_q = 0;
	unsigned int num_tcs = 0;
	unsigned int num_rx_queues = 1;
	int err, i;

	spin_lock(&adapter->mbx_lock);

	/* fetch queue configuration from the PF */
	err = ixgbevf_get_queues(hw, &num_tcs, &def_q);

	spin_unlock(&adapter->mbx_lock);

	if (err)
		return err;

	if (num_tcs > 1) {
		/* update default Tx ring register index */
		adapter->tx_ring[0].reg_idx = def_q;

		/* we need as many queues as traffic classes */
		num_rx_queues = num_tcs;
	}

	/* nothing to do if we have the correct number of queues */
	if (adapter->num_rx_queues == num_rx_queues)
		return 0;

	/* allocate new rings */
	rx_ring = kcalloc(num_rx_queues,
			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
	if (!rx_ring)
		return -ENOMEM;

	/* setup ring fields */
	for (i = 0; i < num_rx_queues; i++) {
		rx_ring[i].count = adapter->rx_ring_count;
		rx_ring[i].queue_index = i;
		rx_ring[i].reg_idx = i;
		rx_ring[i].dev = &adapter->pdev->dev;
		rx_ring[i].netdev = adapter->netdev;

		/* allocate resources on the ring */
		err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
		if (err) {
			while (i) {
				i--;
				ixgbevf_free_rx_resources(adapter, &rx_ring[i]);
			}
			kfree(rx_ring);
			return err;
		}
	}

	/* free the existing rings and queues */
	ixgbevf_free_all_rx_resources(adapter);
	adapter->num_rx_queues = 0;
	kfree(adapter->rx_ring);

	/* move new rings into position on the adapter struct */
	adapter->rx_ring = rx_ring;
	adapter->num_rx_queues = num_rx_queues;

	/* reset ring to vector mapping */
	ixgbevf_reset_q_vectors(adapter);
	ixgbevf_map_rings_to_vectors(adapter);

	return 0;
}

void ixgbevf_up(struct ixgbevf_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;

	ixgbevf_negotiate_api(adapter);

	ixgbevf_reset_queues(adapter);

	ixgbevf_configure(adapter);

	ixgbevf_up_complete(adapter);
@@ -1717,6 +1794,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter)
	for (i = 0; i < adapter->num_tx_queues; i++) {
		adapter->tx_ring[i].count = adapter->tx_ring_count;
		adapter->tx_ring[i].queue_index = i;
		/* reg_idx may be remapped later by DCB config */
		adapter->tx_ring[i].reg_idx = i;
		adapter->tx_ring[i].dev = &adapter->pdev->dev;
		adapter->tx_ring[i].netdev = adapter->netdev;
@@ -1950,8 +2028,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
	hw->subsystem_device_id = pdev->subsystem_device;

	hw->mbx.ops.init_params(hw);
	hw->mac.max_tx_queues = MAX_TX_QUEUES;
	hw->mac.max_rx_queues = MAX_RX_QUEUES;

	/* assume legacy case in which PF would only give VF 2 queues */
	hw->mac.max_tx_queues = 2;
	hw->mac.max_rx_queues = 2;

	err = hw->mac.ops.reset_hw(hw);
	if (err) {
		dev_info(&pdev->dev,
@@ -2377,6 +2458,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter)
						  &adapter->rx_ring[i]);
}

static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	struct ixgbevf_ring *rx_ring;
	unsigned int def_q = 0;
	unsigned int num_tcs = 0;
	unsigned int num_rx_queues = 1;
	int err, i;

	spin_lock(&adapter->mbx_lock);

	/* fetch queue configuration from the PF */
	err = ixgbevf_get_queues(hw, &num_tcs, &def_q);

	spin_unlock(&adapter->mbx_lock);

	if (err)
		return err;

	if (num_tcs > 1) {
		/* update default Tx ring register index */
		adapter->tx_ring[0].reg_idx = def_q;

		/* we need as many queues as traffic classes */
		num_rx_queues = num_tcs;
	}

	/* nothing to do if we have the correct number of queues */
	if (adapter->num_rx_queues == num_rx_queues)
		return 0;

	/* allocate new rings */
	rx_ring = kcalloc(num_rx_queues,
			  sizeof(struct ixgbevf_ring), GFP_KERNEL);
	if (!rx_ring)
		return -ENOMEM;

	/* setup ring fields */
	for (i = 0; i < num_rx_queues; i++) {
		rx_ring[i].count = adapter->rx_ring_count;
		rx_ring[i].queue_index = i;
		rx_ring[i].reg_idx = i;
		rx_ring[i].dev = &adapter->pdev->dev;
		rx_ring[i].netdev = adapter->netdev;
	}

	/* free the existing ring and queues */
	adapter->num_rx_queues = 0;
	kfree(adapter->rx_ring);

	/* move new rings into position on the adapter struct */
	adapter->rx_ring = rx_ring;
	adapter->num_rx_queues = num_rx_queues;

	return 0;
}

/**
 * ixgbevf_open - Called when a network interface is made active
 * @netdev: network interface device structure
@@ -2413,6 +2551,11 @@ static int ixgbevf_open(struct net_device *netdev)

	ixgbevf_negotiate_api(adapter);

	/* setup queue reg_idx and Rx queue count */
	err = ixgbevf_setup_queues(adapter);
	if (err)
		goto err_setup_queues;

	/* allocate transmit descriptors */
	err = ixgbevf_setup_all_tx_resources(adapter);
	if (err)
@@ -2451,6 +2594,7 @@ err_setup_rx:
	ixgbevf_free_all_rx_resources(adapter);
err_setup_tx:
	ixgbevf_free_all_tx_resources(adapter);
err_setup_queues:
	ixgbevf_reset(adapter);

err_setup_reset:
@@ -2925,8 +3069,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;

	switch (adapter->hw.api_version) {
	case ixgbe_mbox_api_11:
		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
		break;
	default:
		if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
			max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
		break;
	}

	/* MTU < 68 is an error and causes problems on some kernels */
	if ((new_mtu < 68) || (max_frame > max_possible_frame))
+10 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@
enum ixgbe_pfvf_api_rev {
	ixgbe_mbox_api_10,	/* API version 1.0, linux/freebsd VF driver */
	ixgbe_mbox_api_20,	/* API version 2.0, solaris Phase1 VF driver */
	ixgbe_mbox_api_11,	/* API version 1.1, linux/freebsd VF driver */
	/* This value should always be last */
	ixgbe_mbox_api_unknown,	/* indicates that API version is not known */
};
@@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_SET_MACVLAN	0x06 /* VF requests PF for unicast filter */
#define IXGBE_VF_API_NEGOTIATE	0x08 /* negotiate API version */

/* mailbox API, version 1.1 VF requests */
#define IXGBE_VF_GET_QUEUE	0x09 /* get queue configuration */

/* GET_QUEUES return data indices within the mailbox */
#define IXGBE_VF_TX_QUEUES	1	/* number of Tx queues supported */
#define IXGBE_VF_RX_QUEUES	2	/* number of Rx queues supported */
#define IXGBE_VF_TRANS_VLAN	3	/* Indication of port vlan */
#define IXGBE_VF_DEF_QUEUE	4	/* Default queue offset */

/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
+58 −0
Original line number Diff line number Diff line
@@ -513,6 +513,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
	return err;
}

int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
		       unsigned int *default_tc)
{
	int err;
	u32 msg[5];

	/* do nothing if API doesn't support ixgbevf_get_queues */
	switch (hw->api_version) {
	case ixgbe_mbox_api_11:
		break;
	default:
		return 0;
	}

	/* Fetch queue configuration from the PF */
	msg[0] = IXGBE_VF_GET_QUEUE;
	msg[1] = msg[2] = msg[3] = msg[4] = 0;
	err = hw->mbx.ops.write_posted(hw, msg, 5);

	if (!err)
		err = hw->mbx.ops.read_posted(hw, msg, 5);

	if (!err) {
		msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;

		/*
		 * if we we didn't get an ACK there must have been
		 * some sort of mailbox error so we should treat it
		 * as such
		 */
		if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK))
			return IXGBE_ERR_MBX;

		/* record and validate values from message */
		hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES];
		if (hw->mac.max_tx_queues == 0 ||
		    hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES)
			hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;

		hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES];
		if (hw->mac.max_rx_queues == 0 ||
		    hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES)
			hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;

		*num_tcs = msg[IXGBE_VF_TRANS_VLAN];
		/* in case of unknown state assume we cannot tag frames */
		if (*num_tcs > hw->mac.max_rx_queues)
			*num_tcs = 1;

		*default_tc = msg[IXGBE_VF_DEF_QUEUE];
		/* default to queue 0 on out-of-bounds queue number */
		if (*default_tc >= hw->mac.max_tx_queues)
			*default_tc = 0;
	}

	return err;
}

static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
	.init_hw             = ixgbevf_init_hw_vf,
	.reset_hw            = ixgbevf_reset_hw_vf,
Loading