diff options
Diffstat (limited to 'drivers/net/sfc/tx.c')
-rw-r--r-- | drivers/net/sfc/tx.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 0e9889ca68fc..a3a3eddd30b9 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c | |||
@@ -105,7 +105,7 @@ struct efx_tso_header { | |||
105 | }; | 105 | }; |
106 | 106 | ||
107 | static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, | 107 | static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, |
108 | const struct sk_buff *skb); | 108 | struct sk_buff *skb); |
109 | static void efx_fini_tso(struct efx_tx_queue *tx_queue); | 109 | static void efx_fini_tso(struct efx_tx_queue *tx_queue); |
110 | static void efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, | 110 | static void efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, |
111 | struct efx_tso_header *tsoh); | 111 | struct efx_tso_header *tsoh); |
@@ -139,7 +139,7 @@ static void efx_tsoh_free(struct efx_tx_queue *tx_queue, | |||
139 | * You must hold netif_tx_lock() to call this function. | 139 | * You must hold netif_tx_lock() to call this function. |
140 | */ | 140 | */ |
141 | static int efx_enqueue_skb(struct efx_tx_queue *tx_queue, | 141 | static int efx_enqueue_skb(struct efx_tx_queue *tx_queue, |
142 | const struct sk_buff *skb) | 142 | struct sk_buff *skb) |
143 | { | 143 | { |
144 | struct efx_nic *efx = tx_queue->efx; | 144 | struct efx_nic *efx = tx_queue->efx; |
145 | struct pci_dev *pci_dev = efx->pci_dev; | 145 | struct pci_dev *pci_dev = efx->pci_dev; |
@@ -578,11 +578,24 @@ struct tso_state { | |||
578 | * Verify that our various assumptions about sk_buffs and the conditions | 578 | * Verify that our various assumptions about sk_buffs and the conditions |
579 | * under which TSO will be attempted hold true. | 579 | * under which TSO will be attempted hold true. |
580 | */ | 580 | */ |
581 | static void efx_tso_check_safe(const struct sk_buff *skb) | 581 | static void efx_tso_check_safe(struct sk_buff *skb) |
582 | { | 582 | { |
583 | EFX_BUG_ON_PARANOID(skb->protocol != htons(ETH_P_IP)); | 583 | __be16 protocol = skb->protocol; |
584 | |||
584 | EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto != | 585 | EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto != |
585 | skb->protocol); | 586 | protocol); |
587 | if (protocol == htons(ETH_P_8021Q)) { | ||
588 | /* Find the encapsulated protocol; reset network header | ||
589 | * and transport header based on that. */ | ||
590 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | ||
591 | protocol = veh->h_vlan_encapsulated_proto; | ||
592 | skb_set_network_header(skb, sizeof(*veh)); | ||
593 | if (protocol == htons(ETH_P_IP)) | ||
594 | skb_set_transport_header(skb, sizeof(*veh) + | ||
595 | 4 * ip_hdr(skb)->ihl); | ||
596 | } | ||
597 | |||
598 | EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IP)); | ||
586 | EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP); | 599 | EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP); |
587 | EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data) | 600 | EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data) |
588 | + (tcp_hdr(skb)->doff << 2u)) > | 601 | + (tcp_hdr(skb)->doff << 2u)) > |
@@ -1020,7 +1033,7 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue, | |||
1020 | * %NETDEV_TX_OK or %NETDEV_TX_BUSY. | 1033 | * %NETDEV_TX_OK or %NETDEV_TX_BUSY. |
1021 | */ | 1034 | */ |
1022 | static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, | 1035 | static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, |
1023 | const struct sk_buff *skb) | 1036 | struct sk_buff *skb) |
1024 | { | 1037 | { |
1025 | struct efx_nic *efx = tx_queue->efx; | 1038 | struct efx_nic *efx = tx_queue->efx; |
1026 | int frag_i, rc, rc2 = NETDEV_TX_OK; | 1039 | int frag_i, rc, rc2 = NETDEV_TX_OK; |