diff options
author | shemminger@osdl.org <shemminger@osdl.org> | 2005-11-30 11:45:16 -0800 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-12-01 02:20:20 -0500 |
commit | a018e3305fe1e500e28830666b1757b75c6b4df5 (patch) | |
tree | c67e376ed636971dd9a1fb5fd0ace0228e6399c9 | |
parent | 5a5b1ea026572ac0e5e03d7322deb546d60f9e6e (diff) |
[PATCH] sky2: handle DMA boundary crossing
Handle the case of DMA spanning 32 bit boundary.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/net/sky2.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index aff347f1ea4b..2253140ff4dc 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -723,11 +723,17 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) return le; } +/* Return high part of DMA address (could be 32 or 64 bit) */ +static inline u32 high32(dma_addr_t a) +{ + return (a >> 16) >> 16; +} + /* Build description to hardware about buffer */ static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) { struct sky2_rx_le *le; - u32 hi = (re->mapaddr >> 16) >> 16; + u32 hi = high32(re->mapaddr); re->idx = sky2->rx_put; if (sky2->rx_addr64 != hi) { @@ -735,7 +741,7 @@ static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) le->addr = cpu_to_le32(hi); le->ctrl = 0; le->opcode = OP_ADDR64 | HW_OWNER; - sky2->rx_addr64 = hi; + sky2->rx_addr64 = high32(re->mapaddr + re->maplen); } le = sky2_next_rx(sky2); @@ -1100,17 +1106,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) len = skb_headlen(skb); mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - addr64 = (mapping >> 16) >> 16; + addr64 = high32(mapping); re = sky2->tx_ring + sky2->tx_prod; - /* Send high bits if changed */ - if (addr64 != sky2->tx_addr64) { + /* Send high bits if changed or crosses boundary */ + if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) { le = get_tx_le(sky2); le->tx.addr = cpu_to_le32(addr64); le->ctrl = 0; le->opcode = OP_ADDR64 | HW_OWNER; - sky2->tx_addr64 = addr64; + sky2->tx_addr64 = high32(mapping + len); } /* Check for TCP Segmentation Offload */ |