aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2011-06-29 01:43:22 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-08-19 09:02:40 -0400
commit66f32a8b97f11ad73d2e7b8c192c55febb20b425 (patch)
tree9829fd858063f19fde90681c6ab15464240be339 /drivers
parent971060b1066fef53e0b2eacece2f6d092d716d15 (diff)
ixgbe: Cleanup FCOE and VLAN handling in xmit_frame_ring
This change is meant to further cleanup the transmit path by streamlining some of the VLAN and FCOE/DCB tasks in the transmit path. In addition it adds code for support software VLANs in the event that they are used in conjunction with DCB and/or FCOE. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h16
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c108
2 files changed, 73 insertions, 51 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index a12fd9f09c7d..378ce46a7f92 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -91,14 +91,16 @@
91#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */ 91#define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */
92 92
93#define IXGBE_TX_FLAGS_CSUM (u32)(1) 93#define IXGBE_TX_FLAGS_CSUM (u32)(1)
94#define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) 94#define IXGBE_TX_FLAGS_HW_VLAN (u32)(1 << 1)
95#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) 95#define IXGBE_TX_FLAGS_SW_VLAN (u32)(1 << 2)
96#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) 96#define IXGBE_TX_FLAGS_TSO (u32)(1 << 3)
97#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 4) 97#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 4)
98#define IXGBE_TX_FLAGS_FSO (u32)(1 << 5) 98#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 5)
99#define IXGBE_TX_FLAGS_MAPPED_AS_PAGE (u32)(1 << 6) 99#define IXGBE_TX_FLAGS_FSO (u32)(1 << 6)
100#define IXGBE_TX_FLAGS_MAPPED_AS_PAGE (u32)(1 << 7)
100#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 101#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
101#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 102#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
103#define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT 29
102#define IXGBE_TX_FLAGS_VLAN_SHIFT 16 104#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
103 105
104#define IXGBE_MAX_RSC_INT_RATE 162760 106#define IXGBE_MAX_RSC_INT_RATE 162760
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 9a2d2d48839d..44ded0c092da 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6369,7 +6369,7 @@ static bool ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
6369 u32 type_tucmd = 0; 6369 u32 type_tucmd = 0;
6370 6370
6371 if (skb->ip_summed != CHECKSUM_PARTIAL) { 6371 if (skb->ip_summed != CHECKSUM_PARTIAL) {
6372 if (!(tx_flags & IXGBE_TX_FLAGS_VLAN)) 6372 if (!(tx_flags & IXGBE_TX_FLAGS_HW_VLAN))
6373 return false; 6373 return false;
6374 } else { 6374 } else {
6375 u8 l4_hdr = 0; 6375 u8 l4_hdr = 0;
@@ -6434,7 +6434,7 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
6434 IXGBE_ADVTXD_DCMD_DEXT); 6434 IXGBE_ADVTXD_DCMD_DEXT);
6435 6435
6436 /* set HW vlan bit if vlan is present */ 6436 /* set HW vlan bit if vlan is present */
6437 if (tx_flags & IXGBE_TX_FLAGS_VLAN) 6437 if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
6438 cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE); 6438 cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
6439 6439
6440 /* set segmentation enable bits for TSO/FSO */ 6440 /* set segmentation enable bits for TSO/FSO */
@@ -6670,8 +6670,8 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
6670 6670
6671 th = tcp_hdr(skb); 6671 th = tcp_hdr(skb);
6672 6672
6673 /* skip this packet since the socket is closing */ 6673 /* skip this packet since it is invalid or the socket is closing */
6674 if (th->fin) 6674 if (!th || th->fin)
6675 return; 6675 return;
6676 6676
6677 /* sample on all syn packets or once every atr sample count */ 6677 /* sample on all syn packets or once every atr sample count */
@@ -6696,7 +6696,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct sk_buff *skb,
6696 * since src port and flex bytes occupy the same word XOR them together 6696 * since src port and flex bytes occupy the same word XOR them together
6697 * and write the value to source port portion of compressed dword 6697 * and write the value to source port portion of compressed dword
6698 */ 6698 */
6699 if (vlan_id) 6699 if (tx_flags & (IXGBE_TX_FLAGS_SW_VLAN | IXGBE_TX_FLAGS_HW_VLAN))
6700 common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q); 6700 common.port.src ^= th->dest ^ __constant_htons(ETH_P_8021Q);
6701 else 6701 else
6702 common.port.src ^= th->dest ^ protocol; 6702 common.port.src ^= th->dest ^ protocol;
@@ -6785,7 +6785,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
6785 unsigned short f; 6785 unsigned short f;
6786#endif 6786#endif
6787 u16 count = TXD_USE_COUNT(skb_headlen(skb)); 6787 u16 count = TXD_USE_COUNT(skb_headlen(skb));
6788 __be16 protocol; 6788 __be16 protocol = skb->protocol;
6789 u8 hdr_len = 0; 6789 u8 hdr_len = 0;
6790 6790
6791 /* 6791 /*
@@ -6806,59 +6806,79 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
6806 return NETDEV_TX_BUSY; 6806 return NETDEV_TX_BUSY;
6807 } 6807 }
6808 6808
6809 protocol = vlan_get_protocol(skb); 6809 /* if we have a HW VLAN tag being added default to the HW one */
6810
6811 if (vlan_tx_tag_present(skb)) { 6810 if (vlan_tx_tag_present(skb)) {
6812 tx_flags |= vlan_tx_tag_get(skb); 6811 tx_flags |= vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT;
6813 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { 6812 tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
6814 tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK; 6813 /* else if it is a SW VLAN check the next protocol and store the tag */
6815 tx_flags |= tx_ring->dcb_tc << 13; 6814 } else if (protocol == __constant_htons(ETH_P_8021Q)) {
6815 struct vlan_hdr *vhdr, _vhdr;
6816 vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr);
6817 if (!vhdr)
6818 goto out_drop;
6819
6820 protocol = vhdr->h_vlan_encapsulated_proto;
6821 tx_flags |= ntohs(vhdr->h_vlan_TCI) << IXGBE_TX_FLAGS_VLAN_SHIFT;
6822 tx_flags |= IXGBE_TX_FLAGS_SW_VLAN;
6823 }
6824
6825 if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
6826 skb->priority != TC_PRIO_CONTROL) {
6827 tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
6828 tx_flags |= tx_ring->dcb_tc <<
6829 IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT;
6830 if (tx_flags & IXGBE_TX_FLAGS_SW_VLAN) {
6831 struct vlan_ethhdr *vhdr;
6832 if (skb_header_cloned(skb) &&
6833 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
6834 goto out_drop;
6835 vhdr = (struct vlan_ethhdr *)skb->data;
6836 vhdr->h_vlan_TCI = htons(tx_flags >>
6837 IXGBE_TX_FLAGS_VLAN_SHIFT);
6838 } else {
6839 tx_flags |= IXGBE_TX_FLAGS_HW_VLAN;
6816 } 6840 }
6817 tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
6818 tx_flags |= IXGBE_TX_FLAGS_VLAN;
6819 } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED &&
6820 skb->priority != TC_PRIO_CONTROL) {
6821 tx_flags |= tx_ring->dcb_tc << 13;
6822 tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
6823 tx_flags |= IXGBE_TX_FLAGS_VLAN;
6824 } 6841 }
6825 6842
6826#ifdef IXGBE_FCOE
6827 /* for FCoE with DCB, we force the priority to what
6828 * was specified by the switch */
6829 if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
6830 (protocol == htons(ETH_P_FCOE)))
6831 tx_flags |= IXGBE_TX_FLAGS_FCOE;
6832
6833#endif
6834 /* record the location of the first descriptor for this packet */ 6843 /* record the location of the first descriptor for this packet */
6835 first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 6844 first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
6836 6845
6837 if (tx_flags & IXGBE_TX_FLAGS_FCOE) {
6838#ifdef IXGBE_FCOE 6846#ifdef IXGBE_FCOE
6839 /* setup tx offload for FCoE */ 6847 /* setup tx offload for FCoE */
6848 if ((protocol == __constant_htons(ETH_P_FCOE)) &&
6849 (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
6840 tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len); 6850 tso = ixgbe_fso(tx_ring, skb, tx_flags, &hdr_len);
6841 if (tso < 0) 6851 if (tso < 0)
6842 goto out_drop; 6852 goto out_drop;
6843 else if (tso) 6853 else if (tso)
6844 tx_flags |= IXGBE_TX_FLAGS_FSO; 6854 tx_flags |= IXGBE_TX_FLAGS_FSO |
6845#endif /* IXGBE_FCOE */ 6855 IXGBE_TX_FLAGS_FCOE;
6846 } else { 6856 else
6847 if (protocol == htons(ETH_P_IP)) 6857 tx_flags |= IXGBE_TX_FLAGS_FCOE;
6848 tx_flags |= IXGBE_TX_FLAGS_IPV4;
6849 tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
6850 if (tso < 0)
6851 goto out_drop;
6852 else if (tso)
6853 tx_flags |= IXGBE_TX_FLAGS_TSO;
6854 else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
6855 tx_flags |= IXGBE_TX_FLAGS_CSUM;
6856 6858
6857 /* add the ATR filter if ATR is on */ 6859 goto xmit_fcoe;
6858 if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
6859 ixgbe_atr(tx_ring, skb, tx_flags, protocol);
6860 } 6860 }
6861 6861
6862#endif /* IXGBE_FCOE */
6863 /* setup IPv4/IPv6 offloads */
6864 if (protocol == __constant_htons(ETH_P_IP))
6865 tx_flags |= IXGBE_TX_FLAGS_IPV4;
6866
6867 tso = ixgbe_tso(tx_ring, skb, tx_flags, protocol, &hdr_len);
6868 if (tso < 0)
6869 goto out_drop;
6870 else if (tso)
6871 tx_flags |= IXGBE_TX_FLAGS_TSO;
6872 else if (ixgbe_tx_csum(tx_ring, skb, tx_flags, protocol))
6873 tx_flags |= IXGBE_TX_FLAGS_CSUM;
6874
6875 /* add the ATR filter if ATR is on */
6876 if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))
6877 ixgbe_atr(tx_ring, skb, tx_flags, protocol);
6878
6879#ifdef IXGBE_FCOE
6880xmit_fcoe:
6881#endif /* IXGBE_FCOE */
6862 ixgbe_tx_map(tx_ring, skb, first, tx_flags, hdr_len); 6882 ixgbe_tx_map(tx_ring, skb, first, tx_flags, hdr_len);
6863 6883
6864 ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED); 6884 ixgbe_maybe_stop_tx(tx_ring, DESC_NEEDED);