Skip to content

Commit d3ae3cf

Browse files
Sasha NeftinJeff Kirsher
authored andcommitted
igc: Add tx_csum offload functionality
Add IP generic TX checksum offload functionality. Signed-off-by: Sasha Neftin <[email protected]> Tested-by: Aaron Brown <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent e7ba676 commit d3ae3cf

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ extern char igc_driver_version[];
135135
/* How many Rx Buffers do we bundle into one write to the hardware ? */
136136
#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */
137137

138+
/* VLAN info */
139+
#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000
140+
138141
/* igc_test_staterr - tests bits within Rx descriptor status and error fields */
139142
static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc,
140143
const u32 stat_err_bits)
@@ -254,6 +257,7 @@ struct igc_ring {
254257
u16 count; /* number of desc. in the ring */
255258
u8 queue_index; /* logical index of the ring*/
256259
u8 reg_idx; /* physical index of the ring */
260+
bool launchtime_enable; /* true if LaunchTime is enabled */
257261

258262
/* everything past this point are written often */
259263
u16 next_to_clean;

drivers/net/ethernet/intel/igc/igc_base.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ union igc_adv_tx_desc {
2222
} wb;
2323
};
2424

25+
/* Context descriptors */
26+
struct igc_adv_tx_context_desc {
27+
__le32 vlan_macip_lens;
28+
__le32 launch_time;
29+
__le32 type_tucmd_mlhl;
30+
__le32 mss_l4len_idx;
31+
};
32+
2533
/* Adv Transmit Descriptor Config Masks */
2634
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
2735
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */

drivers/net/ethernet/intel/igc/igc_defines.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,9 @@
397397
#define IGC_VLAPQF_P_VALID(_n) (0x1 << (3 + (_n) * 4))
398398
#define IGC_VLAPQF_QUEUE_MASK 0x03
399399

400+
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
401+
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */
402+
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
403+
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
404+
400405
#endif /* _IGC_DEFINES_H_ */

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include <linux/types.h>
66
#include <linux/if_vlan.h>
77
#include <linux/aer.h>
8+
#include <linux/tcp.h>
9+
#include <linux/udp.h>
10+
#include <linux/ip.h>
11+
12+
#include <net/ipv6.h>
813

914
#include "igc.h"
1015
#include "igc_hw.h"
@@ -790,8 +795,96 @@ static int igc_set_mac(struct net_device *netdev, void *p)
790795
return 0;
791796
}
792797

798+
static void igc_tx_ctxtdesc(struct igc_ring *tx_ring,
799+
struct igc_tx_buffer *first,
800+
u32 vlan_macip_lens, u32 type_tucmd,
801+
u32 mss_l4len_idx)
802+
{
803+
struct igc_adv_tx_context_desc *context_desc;
804+
u16 i = tx_ring->next_to_use;
805+
struct timespec64 ts;
806+
807+
context_desc = IGC_TX_CTXTDESC(tx_ring, i);
808+
809+
i++;
810+
tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
811+
812+
/* set bits to identify this as an advanced context descriptor */
813+
type_tucmd |= IGC_TXD_CMD_DEXT | IGC_ADVTXD_DTYP_CTXT;
814+
815+
/* For 82575, context index must be unique per ring. */
816+
if (test_bit(IGC_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
817+
mss_l4len_idx |= tx_ring->reg_idx << 4;
818+
819+
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
820+
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
821+
context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
822+
823+
/* We assume there is always a valid Tx time available. Invalid times
824+
* should have been handled by the upper layers.
825+
*/
826+
if (tx_ring->launchtime_enable) {
827+
ts = ns_to_timespec64(first->skb->tstamp);
828+
first->skb->tstamp = 0;
829+
context_desc->launch_time = cpu_to_le32(ts.tv_nsec / 32);
830+
} else {
831+
context_desc->launch_time = 0;
832+
}
833+
}
834+
835+
static inline bool igc_ipv6_csum_is_sctp(struct sk_buff *skb)
836+
{
837+
unsigned int offset = 0;
838+
839+
ipv6_find_hdr(skb, &offset, IPPROTO_SCTP, NULL, NULL);
840+
841+
return offset == skb_checksum_start_offset(skb);
842+
}
843+
793844
static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first)
794845
{
846+
struct sk_buff *skb = first->skb;
847+
u32 vlan_macip_lens = 0;
848+
u32 type_tucmd = 0;
849+
850+
if (skb->ip_summed != CHECKSUM_PARTIAL) {
851+
csum_failed:
852+
if (!(first->tx_flags & IGC_TX_FLAGS_VLAN) &&
853+
!tx_ring->launchtime_enable)
854+
return;
855+
goto no_csum;
856+
}
857+
858+
switch (skb->csum_offset) {
859+
case offsetof(struct tcphdr, check):
860+
type_tucmd = IGC_ADVTXD_TUCMD_L4T_TCP;
861+
/* fall through */
862+
case offsetof(struct udphdr, check):
863+
break;
864+
case offsetof(struct sctphdr, checksum):
865+
/* validate that this is actually an SCTP request */
866+
if ((first->protocol == htons(ETH_P_IP) &&
867+
(ip_hdr(skb)->protocol == IPPROTO_SCTP)) ||
868+
(first->protocol == htons(ETH_P_IPV6) &&
869+
igc_ipv6_csum_is_sctp(skb))) {
870+
type_tucmd = IGC_ADVTXD_TUCMD_L4T_SCTP;
871+
break;
872+
}
873+
/* fall through */
874+
default:
875+
skb_checksum_help(skb);
876+
goto csum_failed;
877+
}
878+
879+
/* update TX checksum flag */
880+
first->tx_flags |= IGC_TX_FLAGS_CSUM;
881+
vlan_macip_lens = skb_checksum_start_offset(skb) -
882+
skb_network_offset(skb);
883+
no_csum:
884+
vlan_macip_lens |= skb_network_offset(skb) << IGC_ADVTXD_MACLEN_SHIFT;
885+
vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK;
886+
887+
igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0);
795888
}
796889

797890
static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size)
@@ -4116,13 +4209,17 @@ static int igc_probe(struct pci_dev *pdev,
41164209
if (err)
41174210
goto err_sw_init;
41184211

4212+
/* Add supported features to the features list*/
4213+
netdev->features |= NETIF_F_HW_CSUM;
4214+
41194215
/* setup the private structure */
41204216
err = igc_sw_init(adapter);
41214217
if (err)
41224218
goto err_sw_init;
41234219

41244220
/* copy netdev features into list of user selectable features */
41254221
netdev->hw_features |= NETIF_F_NTUPLE;
4222+
netdev->hw_features |= netdev->features;
41264223

41274224
/* MTU range: 68 - 9216 */
41284225
netdev->min_mtu = ETH_MIN_MTU;

0 commit comments

Comments
 (0)