|
5 | 5 | #include <linux/types.h> |
6 | 6 | #include <linux/if_vlan.h> |
7 | 7 | #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> |
8 | 13 |
|
9 | 14 | #include "igc.h" |
10 | 15 | #include "igc_hw.h" |
@@ -790,8 +795,96 @@ static int igc_set_mac(struct net_device *netdev, void *p) |
790 | 795 | return 0; |
791 | 796 | } |
792 | 797 |
|
| 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 | + |
793 | 844 | static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first) |
794 | 845 | { |
| 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); |
795 | 888 | } |
796 | 889 |
|
797 | 890 | 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, |
4116 | 4209 | if (err) |
4117 | 4210 | goto err_sw_init; |
4118 | 4211 |
|
| 4212 | + /* Add supported features to the features list*/ |
| 4213 | + netdev->features |= NETIF_F_HW_CSUM; |
| 4214 | + |
4119 | 4215 | /* setup the private structure */ |
4120 | 4216 | err = igc_sw_init(adapter); |
4121 | 4217 | if (err) |
4122 | 4218 | goto err_sw_init; |
4123 | 4219 |
|
4124 | 4220 | /* copy netdev features into list of user selectable features */ |
4125 | 4221 | netdev->hw_features |= NETIF_F_NTUPLE; |
| 4222 | + netdev->hw_features |= netdev->features; |
4126 | 4223 |
|
4127 | 4224 | /* MTU range: 68 - 9216 */ |
4128 | 4225 | netdev->min_mtu = ETH_MIN_MTU; |
|
0 commit comments