diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_txrx.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 104 |
1 files changed, 72 insertions, 32 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 04b441460bbd..cecb340898fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c | |||
@@ -658,6 +658,8 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring) | |||
658 | return le32_to_cpu(*(volatile __le32 *)head); | 658 | return le32_to_cpu(*(volatile __le32 *)head); |
659 | } | 659 | } |
660 | 660 | ||
661 | #define WB_STRIDE 0x3 | ||
662 | |||
661 | /** | 663 | /** |
662 | * i40e_clean_tx_irq - Reclaim resources after transmit completes | 664 | * i40e_clean_tx_irq - Reclaim resources after transmit completes |
663 | * @tx_ring: tx ring to clean | 665 | * @tx_ring: tx ring to clean |
@@ -759,6 +761,18 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
759 | tx_ring->q_vector->tx.total_bytes += total_bytes; | 761 | tx_ring->q_vector->tx.total_bytes += total_bytes; |
760 | tx_ring->q_vector->tx.total_packets += total_packets; | 762 | tx_ring->q_vector->tx.total_packets += total_packets; |
761 | 763 | ||
764 | /* check to see if there are any non-cache aligned descriptors | ||
765 | * waiting to be written back, and kick the hardware to force | ||
766 | * them to be written back in case of napi polling | ||
767 | */ | ||
768 | if (budget && | ||
769 | !((i & WB_STRIDE) == WB_STRIDE) && | ||
770 | !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && | ||
771 | (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) | ||
772 | tx_ring->arm_wb = true; | ||
773 | else | ||
774 | tx_ring->arm_wb = false; | ||
775 | |||
762 | if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) { | 776 | if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) { |
763 | /* schedule immediate reset if we believe we hung */ | 777 | /* schedule immediate reset if we believe we hung */ |
764 | dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" | 778 | dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" |
@@ -777,13 +791,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
777 | netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); | 791 | netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); |
778 | 792 | ||
779 | dev_info(tx_ring->dev, | 793 | dev_info(tx_ring->dev, |
780 | "tx hang detected on queue %d, resetting adapter\n", | 794 | "tx hang detected on queue %d, reset requested\n", |
781 | tx_ring->queue_index); | 795 | tx_ring->queue_index); |
782 | 796 | ||
783 | tx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev); | 797 | /* do not fire the reset immediately, wait for the stack to |
798 | * decide we are truly stuck, also prevents every queue from | ||
799 | * simultaneously requesting a reset | ||
800 | */ | ||
784 | 801 | ||
785 | /* the adapter is about to reset, no point in enabling stuff */ | 802 | /* the adapter is about to reset, no point in enabling polling */ |
786 | return true; | 803 | budget = 1; |
787 | } | 804 | } |
788 | 805 | ||
789 | netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, | 806 | netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, |
@@ -806,7 +823,25 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) | |||
806 | } | 823 | } |
807 | } | 824 | } |
808 | 825 | ||
809 | return budget > 0; | 826 | return !!budget; |
827 | } | ||
828 | |||
829 | /** | ||
830 | * i40e_force_wb - Arm hardware to do a wb on noncache aligned descriptors | ||
831 | * @vsi: the VSI we care about | ||
832 | * @q_vector: the vector on which to force writeback | ||
833 | * | ||
834 | **/ | ||
835 | static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) | ||
836 | { | ||
837 | u32 val = I40E_PFINT_DYN_CTLN_INTENA_MASK | | ||
838 | I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | | ||
839 | I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK | ||
840 | /* allow 00 to be written to the index */; | ||
841 | |||
842 | wr32(&vsi->back->hw, | ||
843 | I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1), | ||
844 | val); | ||
810 | } | 845 | } |
811 | 846 | ||
812 | /** | 847 | /** |
@@ -1290,9 +1325,7 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, | |||
1290 | * so the total length of IPv4 header is IHL*4 bytes | 1325 | * so the total length of IPv4 header is IHL*4 bytes |
1291 | * The UDP_0 bit *may* bet set if the *inner* header is UDP | 1326 | * The UDP_0 bit *may* bet set if the *inner* header is UDP |
1292 | */ | 1327 | */ |
1293 | if (ipv4_tunnel && | 1328 | if (ipv4_tunnel) { |
1294 | (decoded.inner_prot != I40E_RX_PTYPE_INNER_PROT_UDP) && | ||
1295 | !(rx_status & (1 << I40E_RX_DESC_STATUS_UDP_0_SHIFT))) { | ||
1296 | skb->transport_header = skb->mac_header + | 1329 | skb->transport_header = skb->mac_header + |
1297 | sizeof(struct ethhdr) + | 1330 | sizeof(struct ethhdr) + |
1298 | (ip_hdr(skb)->ihl * 4); | 1331 | (ip_hdr(skb)->ihl * 4); |
@@ -1302,15 +1335,19 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, | |||
1302 | skb->protocol == htons(ETH_P_8021AD)) | 1335 | skb->protocol == htons(ETH_P_8021AD)) |
1303 | ? VLAN_HLEN : 0; | 1336 | ? VLAN_HLEN : 0; |
1304 | 1337 | ||
1305 | rx_udp_csum = udp_csum(skb); | 1338 | if ((ip_hdr(skb)->protocol == IPPROTO_UDP) && |
1306 | iph = ip_hdr(skb); | 1339 | (udp_hdr(skb)->check != 0)) { |
1307 | csum = csum_tcpudp_magic( | 1340 | rx_udp_csum = udp_csum(skb); |
1308 | iph->saddr, iph->daddr, | 1341 | iph = ip_hdr(skb); |
1309 | (skb->len - skb_transport_offset(skb)), | 1342 | csum = csum_tcpudp_magic( |
1310 | IPPROTO_UDP, rx_udp_csum); | 1343 | iph->saddr, iph->daddr, |
1344 | (skb->len - skb_transport_offset(skb)), | ||
1345 | IPPROTO_UDP, rx_udp_csum); | ||
1311 | 1346 | ||
1312 | if (udp_hdr(skb)->check != csum) | 1347 | if (udp_hdr(skb)->check != csum) |
1313 | goto checksum_fail; | 1348 | goto checksum_fail; |
1349 | |||
1350 | } /* else its GRE and so no outer UDP header */ | ||
1314 | } | 1351 | } |
1315 | 1352 | ||
1316 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1353 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -1581,6 +1618,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) | |||
1581 | struct i40e_vsi *vsi = q_vector->vsi; | 1618 | struct i40e_vsi *vsi = q_vector->vsi; |
1582 | struct i40e_ring *ring; | 1619 | struct i40e_ring *ring; |
1583 | bool clean_complete = true; | 1620 | bool clean_complete = true; |
1621 | bool arm_wb = false; | ||
1584 | int budget_per_ring; | 1622 | int budget_per_ring; |
1585 | 1623 | ||
1586 | if (test_bit(__I40E_DOWN, &vsi->state)) { | 1624 | if (test_bit(__I40E_DOWN, &vsi->state)) { |
@@ -1591,8 +1629,10 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) | |||
1591 | /* Since the actual Tx work is minimal, we can give the Tx a larger | 1629 | /* Since the actual Tx work is minimal, we can give the Tx a larger |
1592 | * budget and be more aggressive about cleaning up the Tx descriptors. | 1630 | * budget and be more aggressive about cleaning up the Tx descriptors. |
1593 | */ | 1631 | */ |
1594 | i40e_for_each_ring(ring, q_vector->tx) | 1632 | i40e_for_each_ring(ring, q_vector->tx) { |
1595 | clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); | 1633 | clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); |
1634 | arm_wb |= ring->arm_wb; | ||
1635 | } | ||
1596 | 1636 | ||
1597 | /* We attempt to distribute budget to each Rx queue fairly, but don't | 1637 | /* We attempt to distribute budget to each Rx queue fairly, but don't |
1598 | * allow the budget to go below 1 because that would exit polling early. | 1638 | * allow the budget to go below 1 because that would exit polling early. |
@@ -1603,8 +1643,11 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) | |||
1603 | clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring); | 1643 | clean_complete &= i40e_clean_rx_irq(ring, budget_per_ring); |
1604 | 1644 | ||
1605 | /* If work not completed, return budget and polling will return */ | 1645 | /* If work not completed, return budget and polling will return */ |
1606 | if (!clean_complete) | 1646 | if (!clean_complete) { |
1647 | if (arm_wb) | ||
1648 | i40e_force_wb(vsi, q_vector); | ||
1607 | return budget; | 1649 | return budget; |
1650 | } | ||
1608 | 1651 | ||
1609 | /* Work is done so exit the polling mode and re-enable the interrupt */ | 1652 | /* Work is done so exit the polling mode and re-enable the interrupt */ |
1610 | napi_complete(napi); | 1653 | napi_complete(napi); |
@@ -1840,17 +1883,16 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, | |||
1840 | if (err < 0) | 1883 | if (err < 0) |
1841 | return err; | 1884 | return err; |
1842 | 1885 | ||
1843 | if (protocol == htons(ETH_P_IP)) { | 1886 | iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); |
1844 | iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); | 1887 | ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) : ipv6_hdr(skb); |
1888 | |||
1889 | if (iph->version == 4) { | ||
1845 | tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb); | 1890 | tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb); |
1846 | iph->tot_len = 0; | 1891 | iph->tot_len = 0; |
1847 | iph->check = 0; | 1892 | iph->check = 0; |
1848 | tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | 1893 | tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, |
1849 | 0, IPPROTO_TCP, 0); | 1894 | 0, IPPROTO_TCP, 0); |
1850 | } else if (skb_is_gso_v6(skb)) { | 1895 | } else if (ipv6h->version == 6) { |
1851 | |||
1852 | ipv6h = skb->encapsulation ? inner_ipv6_hdr(skb) | ||
1853 | : ipv6_hdr(skb); | ||
1854 | tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb); | 1896 | tcph = skb->encapsulation ? inner_tcp_hdr(skb) : tcp_hdr(skb); |
1855 | ipv6h->payload_len = 0; | 1897 | ipv6h->payload_len = 0; |
1856 | tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | 1898 | tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, |
@@ -1946,13 +1988,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 tx_flags, | |||
1946 | I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM; | 1988 | I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM; |
1947 | } | 1989 | } |
1948 | } else if (tx_flags & I40E_TX_FLAGS_IPV6) { | 1990 | } else if (tx_flags & I40E_TX_FLAGS_IPV6) { |
1949 | if (tx_flags & I40E_TX_FLAGS_TSO) { | 1991 | *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6; |
1950 | *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6; | 1992 | if (tx_flags & I40E_TX_FLAGS_TSO) |
1951 | ip_hdr(skb)->check = 0; | 1993 | ip_hdr(skb)->check = 0; |
1952 | } else { | ||
1953 | *cd_tunneling |= | ||
1954 | I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM; | ||
1955 | } | ||
1956 | } | 1994 | } |
1957 | 1995 | ||
1958 | /* Now set the ctx descriptor fields */ | 1996 | /* Now set the ctx descriptor fields */ |
@@ -1962,7 +2000,10 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 tx_flags, | |||
1962 | ((skb_inner_network_offset(skb) - | 2000 | ((skb_inner_network_offset(skb) - |
1963 | skb_transport_offset(skb)) >> 1) << | 2001 | skb_transport_offset(skb)) >> 1) << |
1964 | I40E_TXD_CTX_QW0_NATLEN_SHIFT; | 2002 | I40E_TXD_CTX_QW0_NATLEN_SHIFT; |
1965 | 2003 | if (this_ip_hdr->version == 6) { | |
2004 | tx_flags &= ~I40E_TX_FLAGS_IPV4; | ||
2005 | tx_flags |= I40E_TX_FLAGS_IPV6; | ||
2006 | } | ||
1966 | } else { | 2007 | } else { |
1967 | network_hdr_len = skb_network_header_len(skb); | 2008 | network_hdr_len = skb_network_header_len(skb); |
1968 | this_ip_hdr = ip_hdr(skb); | 2009 | this_ip_hdr = ip_hdr(skb); |
@@ -2198,7 +2239,6 @@ static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, | |||
2198 | /* Place RS bit on last descriptor of any packet that spans across the | 2239 | /* Place RS bit on last descriptor of any packet that spans across the |
2199 | * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline. | 2240 | * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline. |
2200 | */ | 2241 | */ |
2201 | #define WB_STRIDE 0x3 | ||
2202 | if (((i & WB_STRIDE) != WB_STRIDE) && | 2242 | if (((i & WB_STRIDE) != WB_STRIDE) && |
2203 | (first <= &tx_ring->tx_bi[i]) && | 2243 | (first <= &tx_ring->tx_bi[i]) && |
2204 | (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) { | 2244 | (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) { |