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

Commit eacd73f7 authored by Yi Zou's avatar Yi Zou Committed by David S. Miller
Browse files

ixgbe: Implement FCoE Tx side offload features in base driver of 82599



This patch implements the FCoE Tx side offload features in ixgbe_main.c
to 82599 using the Tx offload infrastructure code added in the previous
patch. This is achieved by the calling the FCoE Sequence Offload (FSO)
function ixgbe_fso() on the transmit path of ixgbe.

This patch also includes an EEPROM check to make sure the NIC we're loading
on is an offload-enabled SKU.

Signed-off-by: default avatarYi Zou <yi.zou@intel.com>
Signed-off-by: default avatarPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bc079228
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -37,3 +37,5 @@ ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \


ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                              ixgbe_dcb_82599.o ixgbe_dcb_nl.o
                              ixgbe_dcb_82599.o ixgbe_dcb_nl.o

ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
+13 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,10 @@
#include "ixgbe_type.h"
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb.h"
#include "ixgbe_dcb.h"
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
#define IXGBE_FCOE
#include "ixgbe_fcoe.h"
#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
#ifdef CONFIG_IXGBE_DCA
#ifdef CONFIG_IXGBE_DCA
#include <linux/dca.h>
#include <linux/dca.h>
#endif
#endif
@@ -84,6 +88,8 @@
#define IXGBE_TX_FLAGS_VLAN		(u32)(1 << 1)
#define IXGBE_TX_FLAGS_VLAN		(u32)(1 << 1)
#define IXGBE_TX_FLAGS_TSO		(u32)(1 << 2)
#define IXGBE_TX_FLAGS_TSO		(u32)(1 << 2)
#define IXGBE_TX_FLAGS_IPV4		(u32)(1 << 3)
#define IXGBE_TX_FLAGS_IPV4		(u32)(1 << 3)
#define IXGBE_TX_FLAGS_FCOE		(u32)(1 << 4)
#define IXGBE_TX_FLAGS_FSO		(u32)(1 << 5)
#define IXGBE_TX_FLAGS_VLAN_MASK	0xffff0000
#define IXGBE_TX_FLAGS_VLAN_MASK	0xffff0000
#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
#define IXGBE_TX_FLAGS_VLAN_SHIFT	16
#define IXGBE_TX_FLAGS_VLAN_SHIFT	16
@@ -298,6 +304,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 25)
#define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 25)
#define IXGBE_FLAG_RSC_CAPABLE                  (u32)(1 << 26)
#define IXGBE_FLAG_RSC_CAPABLE                  (u32)(1 << 26)
#define IXGBE_FLAG_RSC_ENABLED                  (u32)(1 << 27)
#define IXGBE_FLAG_RSC_ENABLED                  (u32)(1 << 27)
#define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 29)


/* default to trying for four seconds */
/* default to trying for four seconds */
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
@@ -371,5 +378,11 @@ extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32);
extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32);
#ifdef IXGBE_FCOE
extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fso(struct ixgbe_adapter *adapter,
                     struct ixgbe_ring *tx_ring, struct sk_buff *skb,
                     u32 tx_flags, u8 *hdr_len);
#endif /* IXGBE_FCOE */


#endif /* _IXGBE_H_ */
#endif /* _IXGBE_H_ */
+0 −1
Original line number Original line Diff line number Diff line
@@ -1294,7 +1294,6 @@ s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps)
	return 0;
	return 0;
}
}



static struct ixgbe_mac_operations mac_ops_82599 = {
static struct ixgbe_mac_operations mac_ops_82599 = {
	.init_hw                = &ixgbe_init_hw_generic,
	.init_hw                = &ixgbe_init_hw_generic,
	.reset_hw               = &ixgbe_reset_hw_82599,
	.reset_hw               = &ixgbe_reset_hw_82599,
+85 −19
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@
#include <net/ip6_checksum.h>
#include <net/ip6_checksum.h>
#include <linux/ethtool.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/if_vlan.h>
#include <scsi/fc/fc_fcoe.h>


#include "ixgbe.h"
#include "ixgbe.h"
#include "ixgbe_common.h"
#include "ixgbe_common.h"
@@ -1810,6 +1811,11 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
	/* Decide whether to use packet split mode or not */
	/* Decide whether to use packet split mode or not */
	adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
	adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;


#ifdef IXGBE_FCOE
	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
		adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
#endif /* IXGBE_FCOE */

	/* Set the RX buffer length according to the mode */
	/* Set the RX buffer length according to the mode */
	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
		rx_buf_len = IXGBE_RX_HDR_SIZE;
		rx_buf_len = IXGBE_RX_HDR_SIZE;
@@ -2241,6 +2247,11 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
	netif_set_gso_max_size(netdev, 65536);
	netif_set_gso_max_size(netdev, 65536);
#endif
#endif


#ifdef IXGBE_FCOE
	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
		ixgbe_configure_fcoe(adapter);

#endif /* IXGBE_FCOE */
	ixgbe_configure_tx(adapter);
	ixgbe_configure_tx(adapter);
	ixgbe_configure_rx(adapter);
	ixgbe_configure_rx(adapter);
	for (i = 0; i < adapter->num_rx_queues; i++)
	for (i = 0; i < adapter->num_rx_queues; i++)
@@ -3401,6 +3412,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
		adapter->flags |= IXGBE_FLAG_RSC_CAPABLE;
		adapter->flags |= IXGBE_FLAG_RSC_CAPABLE;
		adapter->flags |= IXGBE_FLAG_RSC_ENABLED;
		adapter->flags |= IXGBE_FLAG_RSC_ENABLED;
#ifdef IXGBE_FCOE
		adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
#endif /* IXGBE_FCOE */
	}
	}


#ifdef CONFIG_IXGBE_DCB
#ifdef CONFIG_IXGBE_DCB
@@ -4416,10 +4430,12 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter,


static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
                        struct ixgbe_ring *tx_ring,
                        struct ixgbe_ring *tx_ring,
                        struct sk_buff *skb, unsigned int first)
                        struct sk_buff *skb, u32 tx_flags,
                        unsigned int first)
{
{
	struct ixgbe_tx_buffer *tx_buffer_info;
	struct ixgbe_tx_buffer *tx_buffer_info;
	unsigned int len = skb_headlen(skb);
	unsigned int len;
	unsigned int total = skb->len;
	unsigned int offset = 0, size, count = 0, i;
	unsigned int offset = 0, size, count = 0, i;
	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
	unsigned int f;
	unsigned int f;
@@ -4434,6 +4450,11 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,


	map = skb_shinfo(skb)->dma_maps;
	map = skb_shinfo(skb)->dma_maps;


	if (tx_flags & IXGBE_TX_FLAGS_FCOE)
		/* excluding fcoe_crc_eof for FCoE */
		total -= sizeof(struct fcoe_crc_eof);

	len = min(skb_headlen(skb), total);
	while (len) {
	while (len) {
		tx_buffer_info = &tx_ring->tx_buffer_info[i];
		tx_buffer_info = &tx_ring->tx_buffer_info[i];
		size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
		size = min(len, (uint)IXGBE_MAX_DATA_PER_TXD);
@@ -4444,6 +4465,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
		tx_buffer_info->next_to_watch = i;
		tx_buffer_info->next_to_watch = i;


		len -= size;
		len -= size;
		total -= size;
		offset += size;
		offset += size;
		count++;
		count++;


@@ -4458,7 +4480,7 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
		struct skb_frag_struct *frag;
		struct skb_frag_struct *frag;


		frag = &skb_shinfo(skb)->frags[f];
		frag = &skb_shinfo(skb)->frags[f];
		len = frag->size;
		len = min((unsigned int)frag->size, total);
		offset = 0;
		offset = 0;


		while (len) {
		while (len) {
@@ -4475,9 +4497,12 @@ static int ixgbe_tx_map(struct ixgbe_adapter *adapter,
			tx_buffer_info->next_to_watch = i;
			tx_buffer_info->next_to_watch = i;


			len -= size;
			len -= size;
			total -= size;
			offset += size;
			offset += size;
			count++;
			count++;
		}
		}
		if (total == 0)
			break;
	}
	}


	tx_ring->tx_buffer_info[i].skb = skb;
	tx_ring->tx_buffer_info[i].skb = skb;
@@ -4519,6 +4544,13 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
		olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
		olinfo_status |= IXGBE_TXD_POPTS_TXSM <<
		                 IXGBE_ADVTXD_POPTS_SHIFT;
		                 IXGBE_ADVTXD_POPTS_SHIFT;


	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
		olinfo_status |= IXGBE_ADVTXD_CC;
		olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
		if (tx_flags & IXGBE_TX_FLAGS_FSO)
			cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
	}

	olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);
	olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT);


	i = tx_ring->next_to_use;
	i = tx_ring->next_to_use;
@@ -4615,10 +4647,16 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
		tx_flags |= IXGBE_TX_FLAGS_VLAN;
		tx_flags |= IXGBE_TX_FLAGS_VLAN;
	}
	}
	/* three things can cause us to need a context descriptor */

	if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
	    (skb->protocol == htons(ETH_P_FCOE)))
		tx_flags |= IXGBE_TX_FLAGS_FCOE;

	/* four things can cause us to need a context descriptor */
	if (skb_is_gso(skb) ||
	if (skb_is_gso(skb) ||
	    (skb->ip_summed == CHECKSUM_PARTIAL) ||
	    (skb->ip_summed == CHECKSUM_PARTIAL) ||
	    (tx_flags & IXGBE_TX_FLAGS_VLAN))
	    (tx_flags & IXGBE_TX_FLAGS_VLAN) ||
	    (tx_flags & IXGBE_TX_FLAGS_FCOE))
		count++;
		count++;


	count += TXD_USE_COUNT(skb_headlen(skb));
	count += TXD_USE_COUNT(skb_headlen(skb));
@@ -4630,9 +4668,21 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
		return NETDEV_TX_BUSY;
		return NETDEV_TX_BUSY;
	}
	}


	first = tx_ring->next_to_use;
	if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
#ifdef IXGBE_FCOE
		/* setup tx offload for FCoE */
		tso = ixgbe_fso(adapter, tx_ring, skb, tx_flags, &hdr_len);
		if (tso < 0) {
			dev_kfree_skb_any(skb);
			return NETDEV_TX_OK;
		}
		if (tso)
			tx_flags |= IXGBE_TX_FLAGS_FSO;
#endif /* IXGBE_FCOE */
	} else {
		if (skb->protocol == htons(ETH_P_IP))
		if (skb->protocol == htons(ETH_P_IP))
			tx_flags |= IXGBE_TX_FLAGS_IPV4;
			tx_flags |= IXGBE_TX_FLAGS_IPV4;
	first = tx_ring->next_to_use;
		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len);
		tso = ixgbe_tso(adapter, tx_ring, skb, tx_flags, &hdr_len);
		if (tso < 0) {
		if (tso < 0) {
			dev_kfree_skb_any(skb);
			dev_kfree_skb_any(skb);
@@ -4644,9 +4694,9 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
		else if (ixgbe_tx_csum(adapter, tx_ring, skb, tx_flags) &&
			 (skb->ip_summed == CHECKSUM_PARTIAL))
			 (skb->ip_summed == CHECKSUM_PARTIAL))
			tx_flags |= IXGBE_TX_FLAGS_CSUM;
			tx_flags |= IXGBE_TX_FLAGS_CSUM;
	}


	count = ixgbe_tx_map(adapter, tx_ring, skb, first);
	count = ixgbe_tx_map(adapter, tx_ring, skb, tx_flags, first);

	if (count) {
	if (count) {
		ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
		ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
		               hdr_len);
		               hdr_len);
@@ -4794,6 +4844,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
	const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data];
	static int cards_found;
	static int cards_found;
	int i, err, pci_using_dac;
	int i, err, pci_using_dac;
#ifdef IXGBE_FCOE
	u16 device_caps;
#endif
	u32 part_num, eec;
	u32 part_num, eec;


	err = pci_enable_device_mem(pdev);
	err = pci_enable_device_mem(pdev);
@@ -4976,6 +5029,19 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
	netdev->dcbnl_ops = &dcbnl_ops;
	netdev->dcbnl_ops = &dcbnl_ops;
#endif
#endif


#ifdef IXGBE_FCOE
	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
		if (hw->mac.ops.get_device_caps) {
			hw->mac.ops.get_device_caps(hw, &device_caps);
			if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) {
				netdev->features |= NETIF_F_FCOE_CRC;
				netdev->features |= NETIF_F_FSO;
			} else {
				adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
			}
		}
	}
#endif /* IXGBE_FCOE */
	if (pci_using_dac)
	if (pci_using_dac)
		netdev->features |= NETIF_F_HIGHDMA;
		netdev->features |= NETIF_F_HIGHDMA;


+1 −0
Original line number Original line Diff line number Diff line
@@ -1483,6 +1483,7 @@
#endif
#endif


#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP  0x1
#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP  0x1
#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS  0x2


/* PCI Bus Info */
/* PCI Bus Info */
#define IXGBE_PCI_LINK_STATUS     0xB2
#define IXGBE_PCI_LINK_STATUS     0xB2