tg3: 5701 DMA corruption fix
Herbert Xu's commit fb93134dfc
, 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>
This commit is contained in:
committed by
David S. Miller
parent
36ef408061
commit
41588ba1ae
@@ -64,8 +64,8 @@
|
|||||||
|
|
||||||
#define DRV_MODULE_NAME "tg3"
|
#define DRV_MODULE_NAME "tg3"
|
||||||
#define PFX DRV_MODULE_NAME ": "
|
#define PFX DRV_MODULE_NAME ": "
|
||||||
#define DRV_MODULE_VERSION "3.90"
|
#define DRV_MODULE_VERSION "3.91"
|
||||||
#define DRV_MODULE_RELDATE "April 12, 2008"
|
#define DRV_MODULE_RELDATE "April 18, 2008"
|
||||||
|
|
||||||
#define TG3_DEF_MAC_MODE 0
|
#define TG3_DEF_MAC_MODE 0
|
||||||
#define TG3_DEF_RX_MODE 0
|
#define TG3_DEF_RX_MODE 0
|
||||||
@@ -4135,11 +4135,21 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
|
|||||||
u32 last_plus_one, u32 *start,
|
u32 last_plus_one, u32 *start,
|
||||||
u32 base_flags, u32 mss)
|
u32 base_flags, u32 mss)
|
||||||
{
|
{
|
||||||
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
|
struct sk_buff *new_skb;
|
||||||
dma_addr_t new_addr = 0;
|
dma_addr_t new_addr = 0;
|
||||||
u32 entry = *start;
|
u32 entry = *start;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
|
||||||
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
|
||||||
|
new_skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
|
else {
|
||||||
|
int more_headroom = 4 - ((unsigned long)skb->data & 3);
|
||||||
|
|
||||||
|
new_skb = skb_copy_expand(skb,
|
||||||
|
skb_headroom(skb) + more_headroom,
|
||||||
|
skb_tailroom(skb), GFP_ATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
if (!new_skb) {
|
if (!new_skb) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
@@ -4462,7 +4472,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
|
|||||||
|
|
||||||
would_hit_hwbug = 0;
|
would_hit_hwbug = 0;
|
||||||
|
|
||||||
if (tg3_4g_overflow_test(mapping, len))
|
if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
|
||||||
|
would_hit_hwbug = 1;
|
||||||
|
else if (tg3_4g_overflow_test(mapping, len))
|
||||||
would_hit_hwbug = 1;
|
would_hit_hwbug = 1;
|
||||||
|
|
||||||
tg3_set_txd(tp, entry, mapping, len, base_flags,
|
tg3_set_txd(tp, entry, mapping, len, base_flags,
|
||||||
@@ -11339,6 +11351,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
|
||||||
|
static struct tg3_dev_id {
|
||||||
|
u32 vendor;
|
||||||
|
u32 device;
|
||||||
|
} bridge_chipsets[] = {
|
||||||
|
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 },
|
||||||
|
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
struct tg3_dev_id *pci_id = &bridge_chipsets[0];
|
||||||
|
struct pci_dev *bridge = NULL;
|
||||||
|
|
||||||
|
while (pci_id->vendor != 0) {
|
||||||
|
bridge = pci_get_device(pci_id->vendor,
|
||||||
|
pci_id->device,
|
||||||
|
bridge);
|
||||||
|
if (!bridge) {
|
||||||
|
pci_id++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (bridge->subordinate &&
|
||||||
|
(bridge->subordinate->number <=
|
||||||
|
tp->pdev->bus->number) &&
|
||||||
|
(bridge->subordinate->subordinate >=
|
||||||
|
tp->pdev->bus->number)) {
|
||||||
|
tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG;
|
||||||
|
pci_dev_put(bridge);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The EPB bridge inside 5714, 5715, and 5780 cannot support
|
/* The EPB bridge inside 5714, 5715, and 5780 cannot support
|
||||||
* DMA addresses > 40-bit. This bridge may have other additional
|
* DMA addresses > 40-bit. This bridge may have other additional
|
||||||
* 57xx devices behind it in some 4-port NIC designs for example.
|
* 57xx devices behind it in some 4-port NIC designs for example.
|
||||||
|
@@ -2476,6 +2476,7 @@ struct tg3 {
|
|||||||
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
|
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
|
||||||
#define TG3_FLG3_ENABLE_APE 0x00000002
|
#define TG3_FLG3_ENABLE_APE 0x00000002
|
||||||
#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
|
#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
|
||||||
|
#define TG3_FLG3_5701_DMA_BUG 0x00000008
|
||||||
|
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
u16 timer_counter;
|
u16 timer_counter;
|
||||||
|
Reference in New Issue
Block a user