diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2008-01-10 19:14:12 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-12 17:49:10 -0500 |
commit | 86c6887e6fea0b395dc939174ac80ad0ae88288c (patch) | |
tree | a4159ed0ca36c44ce6738c1302cd038149f5f411 /drivers | |
parent | dfd9a421bed2325059fae04f810769b648fa1302 (diff) |
sky2: large memory workaround.
This patch might fix problems with 4G or more of memory.
It stops the driver from doing a small optimization for Tx and Rx,
and instead always sets the high-page on tx/rx descriptors.
Fixes-bug: http://bugzilla.kernel.org/show_bug.cgi?id=9725
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sky2.c | 24 | ||||
-rw-r--r-- | drivers/net/sky2.h | 4 |
2 files changed, 10 insertions, 18 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 52ec89b82f64..bc15940ce1bc 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -944,7 +944,6 @@ static void tx_init(struct sky2_port *sky2) | |||
944 | le = get_tx_le(sky2); | 944 | le = get_tx_le(sky2); |
945 | le->addr = 0; | 945 | le->addr = 0; |
946 | le->opcode = OP_ADDR64 | HW_OWNER; | 946 | le->opcode = OP_ADDR64 | HW_OWNER; |
947 | sky2->tx_addr64 = 0; | ||
948 | } | 947 | } |
949 | 948 | ||
950 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | 949 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, |
@@ -978,13 +977,11 @@ static void sky2_rx_add(struct sky2_port *sky2, u8 op, | |||
978 | dma_addr_t map, unsigned len) | 977 | dma_addr_t map, unsigned len) |
979 | { | 978 | { |
980 | struct sky2_rx_le *le; | 979 | struct sky2_rx_le *le; |
981 | u32 hi = upper_32_bits(map); | ||
982 | 980 | ||
983 | if (sky2->rx_addr64 != hi) { | 981 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
984 | le = sky2_next_rx(sky2); | 982 | le = sky2_next_rx(sky2); |
985 | le->addr = cpu_to_le32(hi); | 983 | le->addr = cpu_to_le32(upper_32_bits(map)); |
986 | le->opcode = OP_ADDR64 | HW_OWNER; | 984 | le->opcode = OP_ADDR64 | HW_OWNER; |
987 | sky2->rx_addr64 = upper_32_bits(map + len); | ||
988 | } | 985 | } |
989 | 986 | ||
990 | le = sky2_next_rx(sky2); | 987 | le = sky2_next_rx(sky2); |
@@ -1480,7 +1477,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1480 | struct tx_ring_info *re; | 1477 | struct tx_ring_info *re; |
1481 | unsigned i, len; | 1478 | unsigned i, len; |
1482 | dma_addr_t mapping; | 1479 | dma_addr_t mapping; |
1483 | u32 addr64; | ||
1484 | u16 mss; | 1480 | u16 mss; |
1485 | u8 ctrl; | 1481 | u8 ctrl; |
1486 | 1482 | ||
@@ -1493,15 +1489,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1493 | 1489 | ||
1494 | len = skb_headlen(skb); | 1490 | len = skb_headlen(skb); |
1495 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | 1491 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); |
1496 | addr64 = upper_32_bits(mapping); | ||
1497 | 1492 | ||
1498 | /* Send high bits if changed or crosses boundary */ | 1493 | /* Send high bits if needed */ |
1499 | if (addr64 != sky2->tx_addr64 || | 1494 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
1500 | upper_32_bits(mapping + len) != sky2->tx_addr64) { | ||
1501 | le = get_tx_le(sky2); | 1495 | le = get_tx_le(sky2); |
1502 | le->addr = cpu_to_le32(addr64); | 1496 | le->addr = cpu_to_le32(upper_32_bits(mapping)); |
1503 | le->opcode = OP_ADDR64 | HW_OWNER; | 1497 | le->opcode = OP_ADDR64 | HW_OWNER; |
1504 | sky2->tx_addr64 = upper_32_bits(mapping + len); | ||
1505 | } | 1498 | } |
1506 | 1499 | ||
1507 | /* Check for TCP Segmentation Offload */ | 1500 | /* Check for TCP Segmentation Offload */ |
@@ -1582,13 +1575,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1582 | 1575 | ||
1583 | mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, | 1576 | mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, |
1584 | frag->size, PCI_DMA_TODEVICE); | 1577 | frag->size, PCI_DMA_TODEVICE); |
1585 | addr64 = upper_32_bits(mapping); | 1578 | |
1586 | if (addr64 != sky2->tx_addr64) { | 1579 | if (sizeof(dma_addr_t) > sizeof(u32)) { |
1587 | le = get_tx_le(sky2); | 1580 | le = get_tx_le(sky2); |
1588 | le->addr = cpu_to_le32(addr64); | 1581 | le->addr = cpu_to_le32(upper_32_bits(mapping)); |
1589 | le->ctrl = 0; | 1582 | le->ctrl = 0; |
1590 | le->opcode = OP_ADDR64 | HW_OWNER; | 1583 | le->opcode = OP_ADDR64 | HW_OWNER; |
1591 | sky2->tx_addr64 = addr64; | ||
1592 | } | 1584 | } |
1593 | 1585 | ||
1594 | le = get_tx_le(sky2); | 1586 | le = get_tx_le(sky2); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index bc646a47edd2..ffe9b8a50a1b 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1991,14 +1991,14 @@ struct sky2_port { | |||
1991 | u16 tx_cons; /* next le to check */ | 1991 | u16 tx_cons; /* next le to check */ |
1992 | u16 tx_prod; /* next le to use */ | 1992 | u16 tx_prod; /* next le to use */ |
1993 | u16 tx_next; /* debug only */ | 1993 | u16 tx_next; /* debug only */ |
1994 | u32 tx_addr64; | 1994 | |
1995 | u16 tx_pending; | 1995 | u16 tx_pending; |
1996 | u16 tx_last_mss; | 1996 | u16 tx_last_mss; |
1997 | u32 tx_tcpsum; | 1997 | u32 tx_tcpsum; |
1998 | 1998 | ||
1999 | struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; | 1999 | struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; |
2000 | struct sky2_rx_le *rx_le; | 2000 | struct sky2_rx_le *rx_le; |
2001 | u32 rx_addr64; | 2001 | |
2002 | u16 rx_next; /* next re to check */ | 2002 | u16 rx_next; /* next re to check */ |
2003 | u16 rx_put; /* next le index to use */ | 2003 | u16 rx_put; /* next le index to use */ |
2004 | u16 rx_pending; | 2004 | u16 rx_pending; |