diff options
Diffstat (limited to 'drivers/net/igb/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 6a1f23092099..aaee02e9e3f0 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
32 | #include <linux/pagemap.h> | 32 | #include <linux/pagemap.h> |
33 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
34 | #include <linux/tcp.h> | ||
35 | #include <linux/ipv6.h> | 34 | #include <linux/ipv6.h> |
36 | #include <net/checksum.h> | 35 | #include <net/checksum.h> |
37 | #include <net/ip6_checksum.h> | 36 | #include <net/ip6_checksum.h> |
@@ -2484,10 +2483,24 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter, | |||
2484 | tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT); | 2483 | tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT); |
2485 | 2484 | ||
2486 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 2485 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
2487 | if (skb->protocol == htons(ETH_P_IP)) | 2486 | switch (skb->protocol) { |
2487 | case __constant_htons(ETH_P_IP): | ||
2488 | tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; | 2488 | tu_cmd |= E1000_ADVTXD_TUCMD_IPV4; |
2489 | if (skb->sk && (skb->sk->sk_protocol == IPPROTO_TCP)) | 2489 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) |
2490 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; | 2490 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; |
2491 | break; | ||
2492 | case __constant_htons(ETH_P_IPV6): | ||
2493 | /* XXX what about other V6 headers?? */ | ||
2494 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) | ||
2495 | tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP; | ||
2496 | break; | ||
2497 | default: | ||
2498 | if (unlikely(net_ratelimit())) | ||
2499 | dev_warn(&adapter->pdev->dev, | ||
2500 | "partial checksum but proto=%x!\n", | ||
2501 | skb->protocol); | ||
2502 | break; | ||
2503 | } | ||
2491 | } | 2504 | } |
2492 | 2505 | ||
2493 | context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd); | 2506 | context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd); |
@@ -3241,6 +3254,13 @@ quit_polling: | |||
3241 | 3254 | ||
3242 | return 1; | 3255 | return 1; |
3243 | } | 3256 | } |
3257 | |||
3258 | static inline u32 get_head(struct igb_ring *tx_ring) | ||
3259 | { | ||
3260 | void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count; | ||
3261 | return le32_to_cpu(*(volatile __le32 *)end); | ||
3262 | } | ||
3263 | |||
3244 | /** | 3264 | /** |
3245 | * igb_clean_tx_irq - Reclaim resources after transmit completes | 3265 | * igb_clean_tx_irq - Reclaim resources after transmit completes |
3246 | * @adapter: board private structure | 3266 | * @adapter: board private structure |
@@ -3262,9 +3282,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter, | |||
3262 | unsigned int total_bytes = 0, total_packets = 0; | 3282 | unsigned int total_bytes = 0, total_packets = 0; |
3263 | 3283 | ||
3264 | rmb(); | 3284 | rmb(); |
3265 | head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc | 3285 | head = get_head(tx_ring); |
3266 | + tx_ring->count); | ||
3267 | head = le32_to_cpu(head); | ||
3268 | i = tx_ring->next_to_clean; | 3286 | i = tx_ring->next_to_clean; |
3269 | while (1) { | 3287 | while (1) { |
3270 | while (i != head) { | 3288 | while (i != head) { |
@@ -3299,9 +3317,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter, | |||
3299 | } | 3317 | } |
3300 | oldhead = head; | 3318 | oldhead = head; |
3301 | rmb(); | 3319 | rmb(); |
3302 | head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc | 3320 | head = get_head(tx_ring); |
3303 | + tx_ring->count); | ||
3304 | head = le32_to_cpu(head); | ||
3305 | if (head == oldhead) | 3321 | if (head == oldhead) |
3306 | goto done_cleaning; | 3322 | goto done_cleaning; |
3307 | } /* while (1) */ | 3323 | } /* while (1) */ |
@@ -3375,7 +3391,7 @@ done_cleaning: | |||
3375 | * @vlan: descriptor vlan field as written by hardware (no le/be conversion) | 3391 | * @vlan: descriptor vlan field as written by hardware (no le/be conversion) |
3376 | * @skb: pointer to sk_buff to be indicated to stack | 3392 | * @skb: pointer to sk_buff to be indicated to stack |
3377 | **/ | 3393 | **/ |
3378 | static void igb_receive_skb(struct igb_adapter *adapter, u8 status, u16 vlan, | 3394 | static void igb_receive_skb(struct igb_adapter *adapter, u8 status, __le16 vlan, |
3379 | struct sk_buff *skb) | 3395 | struct sk_buff *skb) |
3380 | { | 3396 | { |
3381 | if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) | 3397 | if (adapter->vlgrp && (status & E1000_RXD_STAT_VP)) |
@@ -3439,8 +3455,8 @@ static bool igb_clean_rx_irq_adv(struct igb_adapter *adapter, | |||
3439 | * that case, it fills the header buffer and spills the rest | 3455 | * that case, it fills the header buffer and spills the rest |
3440 | * into the page. | 3456 | * into the page. |
3441 | */ | 3457 | */ |
3442 | hlen = le16_to_cpu((rx_desc->wb.lower.lo_dword.hdr_info & | 3458 | hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & |
3443 | E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT); | 3459 | E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; |
3444 | if (hlen > adapter->rx_ps_hdr_size) | 3460 | if (hlen > adapter->rx_ps_hdr_size) |
3445 | hlen = adapter->rx_ps_hdr_size; | 3461 | hlen = adapter->rx_ps_hdr_size; |
3446 | 3462 | ||