aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2008-04-19 21:12:33 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-19 21:12:33 -0400
commit41588ba1ae166eaba0a70abf2d7ff064ad9331d3 (patch)
tree4ec3ef51db69aa0f9b6446435580115aa68098f7 /drivers/net
parent36ef408061da9e012375547d69b27cc1f537b044 (diff)
tg3: 5701 DMA corruption fix
Herbert Xu's commit fb93134dfc2a6e6fbedc7c270a31da03fce88db9, entitled "[TCP]: Fix size calculation in sk_stream_alloc_pskb", has triggered a bug in the 5701 where the 5701 DMA engine will corrupt outgoing packets. This problem only happens when the starting address of the packet matches a certain range of offsets and only when the 5701 is placed downstream of a particular Intel bridge. This patch detects the problematic bridge and if present, readjusts the starting address of the packet data to a dword aligned boundary. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/tg3.c52
-rw-r--r--drivers/net/tg3.h1
2 files changed, 49 insertions, 4 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 96043c5746d0..bc4c62b8e81a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
64 64
65#define DRV_MODULE_NAME "tg3" 65#define DRV_MODULE_NAME "tg3"
66#define PFX DRV_MODULE_NAME ": " 66#define PFX DRV_MODULE_NAME ": "
67#define DRV_MODULE_VERSION "3.90" 67#define DRV_MODULE_VERSION "3.91"
68#define DRV_MODULE_RELDATE "April 12, 2008" 68#define DRV_MODULE_RELDATE "April 18, 2008"
69 69
70#define TG3_DEF_MAC_MODE 0 70#define TG3_DEF_MAC_MODE 0
71#define TG3_DEF_RX_MODE 0 71#define TG3_DEF_RX_MODE 0
@@ -4135,11 +4135,21 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
4135 u32 last_plus_one, u32 *start, 4135 u32 last_plus_one, u32 *start,
4136 u32 base_flags, u32 mss) 4136 u32 base_flags, u32 mss)
4137{ 4137{
4138 struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); 4138 struct sk_buff *new_skb;
4139 dma_addr_t new_addr = 0; 4139 dma_addr_t new_addr = 0;
4140 u32 entry = *start; 4140 u32 entry = *start;
4141 int i, ret = 0; 4141 int i, ret = 0;
4142 4142
4143 if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
4144 new_skb = skb_copy(skb, GFP_ATOMIC);
4145 else {
4146 int more_headroom = 4 - ((unsigned long)skb->data & 3);
4147
4148 new_skb = skb_copy_expand(skb,
4149 skb_headroom(skb) + more_headroom,
4150 skb_tailroom(skb), GFP_ATOMIC);
4151 }
4152
4143 if (!new_skb) { 4153 if (!new_skb) {
4144 ret = -1; 4154 ret = -1;
4145 } else { 4155 } else {
@@ -4462,7 +4472,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
4462 4472
4463 would_hit_hwbug = 0; 4473 would_hit_hwbug = 0;
4464 4474
4465 if (tg3_4g_overflow_test(mapping, len)) 4475 if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
4476 would_hit_hwbug = 1;
4477 else if (tg3_4g_overflow_test(mapping, len))
4466 would_hit_hwbug = 1; 4478 would_hit_hwbug = 1;
4467 4479
4468 tg3_set_txd(tp, entry, mapping, len, base_flags, 4480 tg3_set_txd(tp, entry, mapping, len, base_flags,
@@ -11339,6 +11351,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
11339 } 11351 }
11340 } 11352 }
11341 11353
11354 if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
11355 static struct tg3_dev_id {
11356 u32 vendor;
11357 u32 device;
11358 } bridge_chipsets[] = {
11359 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 },
11360 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 },
11361 { },
11362 };
11363 struct tg3_dev_id *pci_id = &bridge_chipsets[0];
11364 struct pci_dev *bridge = NULL;
11365
11366 while (pci_id->vendor != 0) {
11367 bridge = pci_get_device(pci_id->vendor,
11368 pci_id->device,
11369 bridge);
11370 if (!bridge) {
11371 pci_id++;
11372 continue;
11373 }
11374 if (bridge->subordinate &&
11375 (bridge->subordinate->number <=
11376 tp->pdev->bus->number) &&
11377 (bridge->subordinate->subordinate >=
11378 tp->pdev->bus->number)) {
11379 tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG;
11380 pci_dev_put(bridge);
11381 break;
11382 }
11383 }
11384 }
11385
11342 /* The EPB bridge inside 5714, 5715, and 5780 cannot support 11386 /* The EPB bridge inside 5714, 5715, and 5780 cannot support
11343 * DMA addresses > 40-bit. This bridge may have other additional 11387 * DMA addresses > 40-bit. This bridge may have other additional
11344 * 57xx devices behind it in some 4-port NIC designs for example. 11388 * 57xx devices behind it in some 4-port NIC designs for example.
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c1075a73d66c..c688c3ac5035 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2476,6 +2476,7 @@ struct tg3 {
2476#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 2476#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
2477#define TG3_FLG3_ENABLE_APE 0x00000002 2477#define TG3_FLG3_ENABLE_APE 0x00000002
2478#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 2478#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
2479#define TG3_FLG3_5701_DMA_BUG 0x00000008
2479 2480
2480 struct timer_list timer; 2481 struct timer_list timer;
2481 u16 timer_counter; 2482 u16 timer_counter;