diff options
author | shemminger@osdl.org <shemminger@osdl.org> | 2005-11-30 14:45:16 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-12-01 02:20:20 -0500 |
commit | a018e3305fe1e500e28830666b1757b75c6b4df5 (patch) | |
tree | c67e376ed636971dd9a1fb5fd0ace0228e6399c9 /drivers/net/sky2.c | |
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>
Diffstat (limited to 'drivers/net/sky2.c')
-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) | |||
723 | return le; | 723 | return le; |
724 | } | 724 | } |
725 | 725 | ||
726 | /* Return high part of DMA address (could be 32 or 64 bit) */ | ||
727 | static inline u32 high32(dma_addr_t a) | ||
728 | { | ||
729 | return (a >> 16) >> 16; | ||
730 | } | ||
731 | |||
726 | /* Build description to hardware about buffer */ | 732 | /* Build description to hardware about buffer */ |
727 | static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) | 733 | static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) |
728 | { | 734 | { |
729 | struct sky2_rx_le *le; | 735 | struct sky2_rx_le *le; |
730 | u32 hi = (re->mapaddr >> 16) >> 16; | 736 | u32 hi = high32(re->mapaddr); |
731 | 737 | ||
732 | re->idx = sky2->rx_put; | 738 | re->idx = sky2->rx_put; |
733 | if (sky2->rx_addr64 != hi) { | 739 | if (sky2->rx_addr64 != hi) { |
@@ -735,7 +741,7 @@ static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) | |||
735 | le->addr = cpu_to_le32(hi); | 741 | le->addr = cpu_to_le32(hi); |
736 | le->ctrl = 0; | 742 | le->ctrl = 0; |
737 | le->opcode = OP_ADDR64 | HW_OWNER; | 743 | le->opcode = OP_ADDR64 | HW_OWNER; |
738 | sky2->rx_addr64 = hi; | 744 | sky2->rx_addr64 = high32(re->mapaddr + re->maplen); |
739 | } | 745 | } |
740 | 746 | ||
741 | le = sky2_next_rx(sky2); | 747 | le = sky2_next_rx(sky2); |
@@ -1100,17 +1106,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1100 | 1106 | ||
1101 | len = skb_headlen(skb); | 1107 | len = skb_headlen(skb); |
1102 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | 1108 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); |
1103 | addr64 = (mapping >> 16) >> 16; | 1109 | addr64 = high32(mapping); |
1104 | 1110 | ||
1105 | re = sky2->tx_ring + sky2->tx_prod; | 1111 | re = sky2->tx_ring + sky2->tx_prod; |
1106 | 1112 | ||
1107 | /* Send high bits if changed */ | 1113 | /* Send high bits if changed or crosses boundary */ |
1108 | if (addr64 != sky2->tx_addr64) { | 1114 | if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) { |
1109 | le = get_tx_le(sky2); | 1115 | le = get_tx_le(sky2); |
1110 | le->tx.addr = cpu_to_le32(addr64); | 1116 | le->tx.addr = cpu_to_le32(addr64); |
1111 | le->ctrl = 0; | 1117 | le->ctrl = 0; |
1112 | le->opcode = OP_ADDR64 | HW_OWNER; | 1118 | le->opcode = OP_ADDR64 | HW_OWNER; |
1113 | sky2->tx_addr64 = addr64; | 1119 | sky2->tx_addr64 = high32(mapping + len); |
1114 | } | 1120 | } |
1115 | 1121 | ||
1116 | /* Check for TCP Segmentation Offload */ | 1122 | /* Check for TCP Segmentation Offload */ |