diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-11-18 01:47:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-21 16:10:31 -0500 |
commit | 9205fd9ccab8ef51ad771c1917eed7b2f2225d45 (patch) | |
tree | 7566edecf8ad6edfb4affea5976b0176a316bbab /drivers/net/ethernet | |
parent | 37f07023d30708b5da091fe6d6be9b60783c6d82 (diff) |
tg3: switch to build_skb() infrastructure
This is very similar to bnx2x conversion, but simpler since no special
alignement is required, so goal was not to reduce skb truesize.
Using build_skb() reduces cache line misses in the driver, since we
use cache hot skb instead of cold ones. Number of in-flight sk_buff
structures is lower, they are more likely recycled in SLUB caches
while still hot.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Matt Carlson <mcarlson@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 115 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.h | 6 |
2 files changed, 66 insertions, 55 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 47c0e3a1f58d..d9e9c8c652c8 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -194,7 +194,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) | |||
194 | #if (NET_IP_ALIGN != 0) | 194 | #if (NET_IP_ALIGN != 0) |
195 | #define TG3_RX_OFFSET(tp) ((tp)->rx_offset) | 195 | #define TG3_RX_OFFSET(tp) ((tp)->rx_offset) |
196 | #else | 196 | #else |
197 | #define TG3_RX_OFFSET(tp) 0 | 197 | #define TG3_RX_OFFSET(tp) (NET_SKB_PAD) |
198 | #endif | 198 | #endif |
199 | 199 | ||
200 | /* minimum number of free TX descriptors required to wake up TX process */ | 200 | /* minimum number of free TX descriptors required to wake up TX process */ |
@@ -5370,15 +5370,15 @@ static void tg3_tx(struct tg3_napi *tnapi) | |||
5370 | } | 5370 | } |
5371 | } | 5371 | } |
5372 | 5372 | ||
5373 | static void tg3_rx_skb_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) | 5373 | static void tg3_rx_data_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) |
5374 | { | 5374 | { |
5375 | if (!ri->skb) | 5375 | if (!ri->data) |
5376 | return; | 5376 | return; |
5377 | 5377 | ||
5378 | pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping), | 5378 | pci_unmap_single(tp->pdev, dma_unmap_addr(ri, mapping), |
5379 | map_sz, PCI_DMA_FROMDEVICE); | 5379 | map_sz, PCI_DMA_FROMDEVICE); |
5380 | dev_kfree_skb_any(ri->skb); | 5380 | kfree(ri->data); |
5381 | ri->skb = NULL; | 5381 | ri->data = NULL; |
5382 | } | 5382 | } |
5383 | 5383 | ||
5384 | /* Returns size of skb allocated or < 0 on error. | 5384 | /* Returns size of skb allocated or < 0 on error. |
@@ -5392,28 +5392,28 @@ static void tg3_rx_skb_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz) | |||
5392 | * buffers the cpu only reads the last cacheline of the RX descriptor | 5392 | * buffers the cpu only reads the last cacheline of the RX descriptor |
5393 | * (to fetch the error flags, vlan tag, checksum, and opaque cookie). | 5393 | * (to fetch the error flags, vlan tag, checksum, and opaque cookie). |
5394 | */ | 5394 | */ |
5395 | static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, | 5395 | static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, |
5396 | u32 opaque_key, u32 dest_idx_unmasked) | 5396 | u32 opaque_key, u32 dest_idx_unmasked) |
5397 | { | 5397 | { |
5398 | struct tg3_rx_buffer_desc *desc; | 5398 | struct tg3_rx_buffer_desc *desc; |
5399 | struct ring_info *map; | 5399 | struct ring_info *map; |
5400 | struct sk_buff *skb; | 5400 | u8 *data; |
5401 | dma_addr_t mapping; | 5401 | dma_addr_t mapping; |
5402 | int skb_size, dest_idx; | 5402 | int skb_size, data_size, dest_idx; |
5403 | 5403 | ||
5404 | switch (opaque_key) { | 5404 | switch (opaque_key) { |
5405 | case RXD_OPAQUE_RING_STD: | 5405 | case RXD_OPAQUE_RING_STD: |
5406 | dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask; | 5406 | dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask; |
5407 | desc = &tpr->rx_std[dest_idx]; | 5407 | desc = &tpr->rx_std[dest_idx]; |
5408 | map = &tpr->rx_std_buffers[dest_idx]; | 5408 | map = &tpr->rx_std_buffers[dest_idx]; |
5409 | skb_size = tp->rx_pkt_map_sz; | 5409 | data_size = tp->rx_pkt_map_sz; |
5410 | break; | 5410 | break; |
5411 | 5411 | ||
5412 | case RXD_OPAQUE_RING_JUMBO: | 5412 | case RXD_OPAQUE_RING_JUMBO: |
5413 | dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask; | 5413 | dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask; |
5414 | desc = &tpr->rx_jmb[dest_idx].std; | 5414 | desc = &tpr->rx_jmb[dest_idx].std; |
5415 | map = &tpr->rx_jmb_buffers[dest_idx]; | 5415 | map = &tpr->rx_jmb_buffers[dest_idx]; |
5416 | skb_size = TG3_RX_JMB_MAP_SZ; | 5416 | data_size = TG3_RX_JMB_MAP_SZ; |
5417 | break; | 5417 | break; |
5418 | 5418 | ||
5419 | default: | 5419 | default: |
@@ -5426,31 +5426,33 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr, | |||
5426 | * Callers depend upon this behavior and assume that | 5426 | * Callers depend upon this behavior and assume that |
5427 | * we leave everything unchanged if we fail. | 5427 | * we leave everything unchanged if we fail. |
5428 | */ | 5428 | */ |
5429 | skb = netdev_alloc_skb(tp->dev, skb_size + TG3_RX_OFFSET(tp)); | 5429 | skb_size = SKB_DATA_ALIGN(data_size + TG3_RX_OFFSET(tp)) + |
5430 | if (skb == NULL) | 5430 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); |
5431 | data = kmalloc(skb_size, GFP_ATOMIC); | ||
5432 | if (!data) | ||
5431 | return -ENOMEM; | 5433 | return -ENOMEM; |
5432 | 5434 | ||
5433 | skb_reserve(skb, TG3_RX_OFFSET(tp)); | 5435 | mapping = pci_map_single(tp->pdev, |
5434 | 5436 | data + TG3_RX_OFFSET(tp), | |
5435 | mapping = pci_map_single(tp->pdev, skb->data, skb_size, | 5437 | data_size, |
5436 | PCI_DMA_FROMDEVICE); | 5438 | PCI_DMA_FROMDEVICE); |
5437 | if (pci_dma_mapping_error(tp->pdev, mapping)) { | 5439 | if (pci_dma_mapping_error(tp->pdev, mapping)) { |
5438 | dev_kfree_skb(skb); | 5440 | kfree(data); |
5439 | return -EIO; | 5441 | return -EIO; |
5440 | } | 5442 | } |
5441 | 5443 | ||
5442 | map->skb = skb; | 5444 | map->data = data; |
5443 | dma_unmap_addr_set(map, mapping, mapping); | 5445 | dma_unmap_addr_set(map, mapping, mapping); |
5444 | 5446 | ||
5445 | desc->addr_hi = ((u64)mapping >> 32); | 5447 | desc->addr_hi = ((u64)mapping >> 32); |
5446 | desc->addr_lo = ((u64)mapping & 0xffffffff); | 5448 | desc->addr_lo = ((u64)mapping & 0xffffffff); |
5447 | 5449 | ||
5448 | return skb_size; | 5450 | return data_size; |
5449 | } | 5451 | } |
5450 | 5452 | ||
5451 | /* We only need to move over in the address because the other | 5453 | /* We only need to move over in the address because the other |
5452 | * members of the RX descriptor are invariant. See notes above | 5454 | * members of the RX descriptor are invariant. See notes above |
5453 | * tg3_alloc_rx_skb for full details. | 5455 | * tg3_alloc_rx_data for full details. |
5454 | */ | 5456 | */ |
5455 | static void tg3_recycle_rx(struct tg3_napi *tnapi, | 5457 | static void tg3_recycle_rx(struct tg3_napi *tnapi, |
5456 | struct tg3_rx_prodring_set *dpr, | 5458 | struct tg3_rx_prodring_set *dpr, |
@@ -5484,7 +5486,7 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi, | |||
5484 | return; | 5486 | return; |
5485 | } | 5487 | } |
5486 | 5488 | ||
5487 | dest_map->skb = src_map->skb; | 5489 | dest_map->data = src_map->data; |
5488 | dma_unmap_addr_set(dest_map, mapping, | 5490 | dma_unmap_addr_set(dest_map, mapping, |
5489 | dma_unmap_addr(src_map, mapping)); | 5491 | dma_unmap_addr(src_map, mapping)); |
5490 | dest_desc->addr_hi = src_desc->addr_hi; | 5492 | dest_desc->addr_hi = src_desc->addr_hi; |
@@ -5495,7 +5497,7 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi, | |||
5495 | */ | 5497 | */ |
5496 | smp_wmb(); | 5498 | smp_wmb(); |
5497 | 5499 | ||
5498 | src_map->skb = NULL; | 5500 | src_map->data = NULL; |
5499 | } | 5501 | } |
5500 | 5502 | ||
5501 | /* The RX ring scheme is composed of multiple rings which post fresh | 5503 | /* The RX ring scheme is composed of multiple rings which post fresh |
@@ -5549,19 +5551,20 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) | |||
5549 | struct sk_buff *skb; | 5551 | struct sk_buff *skb; |
5550 | dma_addr_t dma_addr; | 5552 | dma_addr_t dma_addr; |
5551 | u32 opaque_key, desc_idx, *post_ptr; | 5553 | u32 opaque_key, desc_idx, *post_ptr; |
5554 | u8 *data; | ||
5552 | 5555 | ||
5553 | desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; | 5556 | desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; |
5554 | opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; | 5557 | opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; |
5555 | if (opaque_key == RXD_OPAQUE_RING_STD) { | 5558 | if (opaque_key == RXD_OPAQUE_RING_STD) { |
5556 | ri = &tp->napi[0].prodring.rx_std_buffers[desc_idx]; | 5559 | ri = &tp->napi[0].prodring.rx_std_buffers[desc_idx]; |
5557 | dma_addr = dma_unmap_addr(ri, mapping); | 5560 | dma_addr = dma_unmap_addr(ri, mapping); |
5558 | skb = ri->skb; | 5561 | data = ri->data; |
5559 | post_ptr = &std_prod_idx; | 5562 | post_ptr = &std_prod_idx; |
5560 | rx_std_posted++; | 5563 | rx_std_posted++; |
5561 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { | 5564 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { |
5562 | ri = &tp->napi[0].prodring.rx_jmb_buffers[desc_idx]; | 5565 | ri = &tp->napi[0].prodring.rx_jmb_buffers[desc_idx]; |
5563 | dma_addr = dma_unmap_addr(ri, mapping); | 5566 | dma_addr = dma_unmap_addr(ri, mapping); |
5564 | skb = ri->skb; | 5567 | data = ri->data; |
5565 | post_ptr = &jmb_prod_idx; | 5568 | post_ptr = &jmb_prod_idx; |
5566 | } else | 5569 | } else |
5567 | goto next_pkt_nopost; | 5570 | goto next_pkt_nopost; |
@@ -5579,13 +5582,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) | |||
5579 | goto next_pkt; | 5582 | goto next_pkt; |
5580 | } | 5583 | } |
5581 | 5584 | ||
5585 | prefetch(data + TG3_RX_OFFSET(tp)); | ||
5582 | len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - | 5586 | len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - |
5583 | ETH_FCS_LEN; | 5587 | ETH_FCS_LEN; |
5584 | 5588 | ||
5585 | if (len > TG3_RX_COPY_THRESH(tp)) { | 5589 | if (len > TG3_RX_COPY_THRESH(tp)) { |
5586 | int skb_size; | 5590 | int skb_size; |
5587 | 5591 | ||
5588 | skb_size = tg3_alloc_rx_skb(tp, tpr, opaque_key, | 5592 | skb_size = tg3_alloc_rx_data(tp, tpr, opaque_key, |
5589 | *post_ptr); | 5593 | *post_ptr); |
5590 | if (skb_size < 0) | 5594 | if (skb_size < 0) |
5591 | goto drop_it; | 5595 | goto drop_it; |
@@ -5593,35 +5597,37 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) | |||
5593 | pci_unmap_single(tp->pdev, dma_addr, skb_size, | 5597 | pci_unmap_single(tp->pdev, dma_addr, skb_size, |
5594 | PCI_DMA_FROMDEVICE); | 5598 | PCI_DMA_FROMDEVICE); |
5595 | 5599 | ||
5596 | /* Ensure that the update to the skb happens | 5600 | skb = build_skb(data); |
5601 | if (!skb) { | ||
5602 | kfree(data); | ||
5603 | goto drop_it_no_recycle; | ||
5604 | } | ||
5605 | skb_reserve(skb, TG3_RX_OFFSET(tp)); | ||
5606 | /* Ensure that the update to the data happens | ||
5597 | * after the usage of the old DMA mapping. | 5607 | * after the usage of the old DMA mapping. |
5598 | */ | 5608 | */ |
5599 | smp_wmb(); | 5609 | smp_wmb(); |
5600 | 5610 | ||
5601 | ri->skb = NULL; | 5611 | ri->data = NULL; |
5602 | 5612 | ||
5603 | skb_put(skb, len); | ||
5604 | } else { | 5613 | } else { |
5605 | struct sk_buff *copy_skb; | ||
5606 | |||
5607 | tg3_recycle_rx(tnapi, tpr, opaque_key, | 5614 | tg3_recycle_rx(tnapi, tpr, opaque_key, |
5608 | desc_idx, *post_ptr); | 5615 | desc_idx, *post_ptr); |
5609 | 5616 | ||
5610 | copy_skb = netdev_alloc_skb(tp->dev, len + | 5617 | skb = netdev_alloc_skb(tp->dev, |
5611 | TG3_RAW_IP_ALIGN); | 5618 | len + TG3_RAW_IP_ALIGN); |
5612 | if (copy_skb == NULL) | 5619 | if (skb == NULL) |
5613 | goto drop_it_no_recycle; | 5620 | goto drop_it_no_recycle; |
5614 | 5621 | ||
5615 | skb_reserve(copy_skb, TG3_RAW_IP_ALIGN); | 5622 | skb_reserve(skb, TG3_RAW_IP_ALIGN); |
5616 | skb_put(copy_skb, len); | ||
5617 | pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); | 5623 | pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); |
5618 | skb_copy_from_linear_data(skb, copy_skb->data, len); | 5624 | memcpy(skb->data, |
5625 | data + TG3_RX_OFFSET(tp), | ||
5626 | len); | ||
5619 | pci_dma_sync_single_for_device(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); | 5627 | pci_dma_sync_single_for_device(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); |
5620 | |||
5621 | /* We'll reuse the original ring buffer. */ | ||
5622 | skb = copy_skb; | ||
5623 | } | 5628 | } |
5624 | 5629 | ||
5630 | skb_put(skb, len); | ||
5625 | if ((tp->dev->features & NETIF_F_RXCSUM) && | 5631 | if ((tp->dev->features & NETIF_F_RXCSUM) && |
5626 | (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && | 5632 | (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) && |
5627 | (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) | 5633 | (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK) |
@@ -5760,7 +5766,7 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp, | |||
5760 | di = dpr->rx_std_prod_idx; | 5766 | di = dpr->rx_std_prod_idx; |
5761 | 5767 | ||
5762 | for (i = di; i < di + cpycnt; i++) { | 5768 | for (i = di; i < di + cpycnt; i++) { |
5763 | if (dpr->rx_std_buffers[i].skb) { | 5769 | if (dpr->rx_std_buffers[i].data) { |
5764 | cpycnt = i - di; | 5770 | cpycnt = i - di; |
5765 | err = -ENOSPC; | 5771 | err = -ENOSPC; |
5766 | break; | 5772 | break; |
@@ -5818,7 +5824,7 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp, | |||
5818 | di = dpr->rx_jmb_prod_idx; | 5824 | di = dpr->rx_jmb_prod_idx; |
5819 | 5825 | ||
5820 | for (i = di; i < di + cpycnt; i++) { | 5826 | for (i = di; i < di + cpycnt; i++) { |
5821 | if (dpr->rx_jmb_buffers[i].skb) { | 5827 | if (dpr->rx_jmb_buffers[i].data) { |
5822 | cpycnt = i - di; | 5828 | cpycnt = i - di; |
5823 | err = -ENOSPC; | 5829 | err = -ENOSPC; |
5824 | break; | 5830 | break; |
@@ -7056,14 +7062,14 @@ static void tg3_rx_prodring_free(struct tg3 *tp, | |||
7056 | if (tpr != &tp->napi[0].prodring) { | 7062 | if (tpr != &tp->napi[0].prodring) { |
7057 | for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx; | 7063 | for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx; |
7058 | i = (i + 1) & tp->rx_std_ring_mask) | 7064 | i = (i + 1) & tp->rx_std_ring_mask) |
7059 | tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], | 7065 | tg3_rx_data_free(tp, &tpr->rx_std_buffers[i], |
7060 | tp->rx_pkt_map_sz); | 7066 | tp->rx_pkt_map_sz); |
7061 | 7067 | ||
7062 | if (tg3_flag(tp, JUMBO_CAPABLE)) { | 7068 | if (tg3_flag(tp, JUMBO_CAPABLE)) { |
7063 | for (i = tpr->rx_jmb_cons_idx; | 7069 | for (i = tpr->rx_jmb_cons_idx; |
7064 | i != tpr->rx_jmb_prod_idx; | 7070 | i != tpr->rx_jmb_prod_idx; |
7065 | i = (i + 1) & tp->rx_jmb_ring_mask) { | 7071 | i = (i + 1) & tp->rx_jmb_ring_mask) { |
7066 | tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], | 7072 | tg3_rx_data_free(tp, &tpr->rx_jmb_buffers[i], |
7067 | TG3_RX_JMB_MAP_SZ); | 7073 | TG3_RX_JMB_MAP_SZ); |
7068 | } | 7074 | } |
7069 | } | 7075 | } |
@@ -7072,12 +7078,12 @@ static void tg3_rx_prodring_free(struct tg3 *tp, | |||
7072 | } | 7078 | } |
7073 | 7079 | ||
7074 | for (i = 0; i <= tp->rx_std_ring_mask; i++) | 7080 | for (i = 0; i <= tp->rx_std_ring_mask; i++) |
7075 | tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i], | 7081 | tg3_rx_data_free(tp, &tpr->rx_std_buffers[i], |
7076 | tp->rx_pkt_map_sz); | 7082 | tp->rx_pkt_map_sz); |
7077 | 7083 | ||
7078 | if (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS)) { | 7084 | if (tg3_flag(tp, JUMBO_CAPABLE) && !tg3_flag(tp, 5780_CLASS)) { |
7079 | for (i = 0; i <= tp->rx_jmb_ring_mask; i++) | 7085 | for (i = 0; i <= tp->rx_jmb_ring_mask; i++) |
7080 | tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i], | 7086 | tg3_rx_data_free(tp, &tpr->rx_jmb_buffers[i], |
7081 | TG3_RX_JMB_MAP_SZ); | 7087 | TG3_RX_JMB_MAP_SZ); |
7082 | } | 7088 | } |
7083 | } | 7089 | } |
@@ -7133,7 +7139,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, | |||
7133 | 7139 | ||
7134 | /* Now allocate fresh SKBs for each rx ring. */ | 7140 | /* Now allocate fresh SKBs for each rx ring. */ |
7135 | for (i = 0; i < tp->rx_pending; i++) { | 7141 | for (i = 0; i < tp->rx_pending; i++) { |
7136 | if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) { | 7142 | if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) { |
7137 | netdev_warn(tp->dev, | 7143 | netdev_warn(tp->dev, |
7138 | "Using a smaller RX standard ring. Only " | 7144 | "Using a smaller RX standard ring. Only " |
7139 | "%d out of %d buffers were allocated " | 7145 | "%d out of %d buffers were allocated " |
@@ -7165,7 +7171,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, | |||
7165 | } | 7171 | } |
7166 | 7172 | ||
7167 | for (i = 0; i < tp->rx_jumbo_pending; i++) { | 7173 | for (i = 0; i < tp->rx_jumbo_pending; i++) { |
7168 | if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) { | 7174 | if (tg3_alloc_rx_data(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) { |
7169 | netdev_warn(tp->dev, | 7175 | netdev_warn(tp->dev, |
7170 | "Using a smaller RX jumbo ring. Only %d " | 7176 | "Using a smaller RX jumbo ring. Only %d " |
7171 | "out of %d buffers were allocated " | 7177 | "out of %d buffers were allocated " |
@@ -11374,8 +11380,8 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) | |||
11374 | u32 rx_start_idx, rx_idx, tx_idx, opaque_key; | 11380 | u32 rx_start_idx, rx_idx, tx_idx, opaque_key; |
11375 | u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val; | 11381 | u32 base_flags = 0, mss = 0, desc_idx, coal_now, data_off, val; |
11376 | u32 budget; | 11382 | u32 budget; |
11377 | struct sk_buff *skb, *rx_skb; | 11383 | struct sk_buff *skb; |
11378 | u8 *tx_data; | 11384 | u8 *tx_data, *rx_data; |
11379 | dma_addr_t map; | 11385 | dma_addr_t map; |
11380 | int num_pkts, tx_len, rx_len, i, err; | 11386 | int num_pkts, tx_len, rx_len, i, err; |
11381 | struct tg3_rx_buffer_desc *desc; | 11387 | struct tg3_rx_buffer_desc *desc; |
@@ -11543,11 +11549,11 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) | |||
11543 | } | 11549 | } |
11544 | 11550 | ||
11545 | if (opaque_key == RXD_OPAQUE_RING_STD) { | 11551 | if (opaque_key == RXD_OPAQUE_RING_STD) { |
11546 | rx_skb = tpr->rx_std_buffers[desc_idx].skb; | 11552 | rx_data = tpr->rx_std_buffers[desc_idx].data; |
11547 | map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], | 11553 | map = dma_unmap_addr(&tpr->rx_std_buffers[desc_idx], |
11548 | mapping); | 11554 | mapping); |
11549 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { | 11555 | } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) { |
11550 | rx_skb = tpr->rx_jmb_buffers[desc_idx].skb; | 11556 | rx_data = tpr->rx_jmb_buffers[desc_idx].data; |
11551 | map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], | 11557 | map = dma_unmap_addr(&tpr->rx_jmb_buffers[desc_idx], |
11552 | mapping); | 11558 | mapping); |
11553 | } else | 11559 | } else |
@@ -11556,15 +11562,16 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, bool tso_loopback) | |||
11556 | pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, | 11562 | pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, |
11557 | PCI_DMA_FROMDEVICE); | 11563 | PCI_DMA_FROMDEVICE); |
11558 | 11564 | ||
11565 | rx_data += TG3_RX_OFFSET(tp); | ||
11559 | for (i = data_off; i < rx_len; i++, val++) { | 11566 | for (i = data_off; i < rx_len; i++, val++) { |
11560 | if (*(rx_skb->data + i) != (u8) (val & 0xff)) | 11567 | if (*(rx_data + i) != (u8) (val & 0xff)) |
11561 | goto out; | 11568 | goto out; |
11562 | } | 11569 | } |
11563 | } | 11570 | } |
11564 | 11571 | ||
11565 | err = 0; | 11572 | err = 0; |
11566 | 11573 | ||
11567 | /* tg3_free_rings will unmap and free the rx_skb */ | 11574 | /* tg3_free_rings will unmap and free the rx_data */ |
11568 | out: | 11575 | out: |
11569 | return err; | 11576 | return err; |
11570 | } | 11577 | } |
@@ -14522,11 +14529,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
14522 | else | 14529 | else |
14523 | tg3_flag_clear(tp, POLL_SERDES); | 14530 | tg3_flag_clear(tp, POLL_SERDES); |
14524 | 14531 | ||
14525 | tp->rx_offset = NET_IP_ALIGN; | 14532 | tp->rx_offset = NET_SKB_PAD + NET_IP_ALIGN; |
14526 | tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; | 14533 | tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; |
14527 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && | 14534 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && |
14528 | tg3_flag(tp, PCIX_MODE)) { | 14535 | tg3_flag(tp, PCIX_MODE)) { |
14529 | tp->rx_offset = 0; | 14536 | tp->rx_offset = NET_SKB_PAD; |
14530 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 14537 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
14531 | tp->rx_copy_thresh = ~(u16)0; | 14538 | tp->rx_copy_thresh = ~(u16)0; |
14532 | #endif | 14539 | #endif |
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 94b4bd049a33..8e2f380f893a 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h | |||
@@ -2662,9 +2662,13 @@ struct tg3_hw_stats { | |||
2662 | /* 'mapping' is superfluous as the chip does not write into | 2662 | /* 'mapping' is superfluous as the chip does not write into |
2663 | * the tx/rx post rings so we could just fetch it from there. | 2663 | * the tx/rx post rings so we could just fetch it from there. |
2664 | * But the cache behavior is better how we are doing it now. | 2664 | * But the cache behavior is better how we are doing it now. |
2665 | * | ||
2666 | * This driver uses new build_skb() API : | ||
2667 | * RX ring buffer contains pointer to kmalloc() data only, | ||
2668 | * skb are built only after Hardware filled the frame. | ||
2665 | */ | 2669 | */ |
2666 | struct ring_info { | 2670 | struct ring_info { |
2667 | struct sk_buff *skb; | 2671 | u8 *data; |
2668 | DEFINE_DMA_UNMAP_ADDR(mapping); | 2672 | DEFINE_DMA_UNMAP_ADDR(mapping); |
2669 | }; | 2673 | }; |
2670 | 2674 | ||