Commit a018e330 authored by shemminger@osdl.org's avatar shemminger@osdl.org Committed by Jeff Garzik

[PATCH] sky2: handle DMA boundary crossing

Handle the case of DMA spanning 32 bit boundary.
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 5a5b1ea0
...@@ -723,11 +723,17 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) ...@@ -723,11 +723,17 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
return le; 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 */ /* Build description to hardware about buffer */
static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re)
{ {
struct sky2_rx_le *le; struct sky2_rx_le *le;
u32 hi = (re->mapaddr >> 16) >> 16; u32 hi = high32(re->mapaddr);
re->idx = sky2->rx_put; re->idx = sky2->rx_put;
if (sky2->rx_addr64 != hi) { if (sky2->rx_addr64 != hi) {
...@@ -735,7 +741,7 @@ static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) ...@@ -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->addr = cpu_to_le32(hi);
le->ctrl = 0; le->ctrl = 0;
le->opcode = OP_ADDR64 | HW_OWNER; le->opcode = OP_ADDR64 | HW_OWNER;
sky2->rx_addr64 = hi; sky2->rx_addr64 = high32(re->mapaddr + re->maplen);
} }
le = sky2_next_rx(sky2); le = sky2_next_rx(sky2);
...@@ -1100,17 +1106,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -1100,17 +1106,17 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
len = skb_headlen(skb); len = skb_headlen(skb);
mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); 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; re = sky2->tx_ring + sky2->tx_prod;
/* Send high bits if changed */ /* Send high bits if changed or crosses boundary */
if (addr64 != sky2->tx_addr64) { if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
le = get_tx_le(sky2); le = get_tx_le(sky2);
le->tx.addr = cpu_to_le32(addr64); le->tx.addr = cpu_to_le32(addr64);
le->ctrl = 0; le->ctrl = 0;
le->opcode = OP_ADDR64 | HW_OWNER; le->opcode = OP_ADDR64 | HW_OWNER;
sky2->tx_addr64 = addr64; sky2->tx_addr64 = high32(mapping + len);
} }
/* Check for TCP Segmentation Offload */ /* Check for TCP Segmentation Offload */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment