epic100 endianness annotations and fixes
* "powerpc or sparc" is not the same as "big-endian", fix the ifdef * since we tell the card to byteswap the descriptors on big-endian, we ought to leave them host-endian... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
48f5fec548
commit
9ebfd4929d
1 changed files with 27 additions and 20 deletions
|
@ -131,8 +131,8 @@ IIIa. Ring buffers
|
||||||
|
|
||||||
IVb. References
|
IVb. References
|
||||||
|
|
||||||
http://www.smsc.com/main/datasheets/83c171.pdf
|
http://www.smsc.com/main/tools/discontinued/83c171.pdf
|
||||||
http://www.smsc.com/main/datasheets/83c175.pdf
|
http://www.smsc.com/main/tools/discontinued/83c175.pdf
|
||||||
http://scyld.com/expert/NWay.html
|
http://scyld.com/expert/NWay.html
|
||||||
http://www.national.com/pf/DP/DP83840A.html
|
http://www.national.com/pf/DP/DP83840A.html
|
||||||
|
|
||||||
|
@ -227,7 +227,12 @@ static const u16 media2miictl[16] = {
|
||||||
0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0,
|
0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0 };
|
0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
/* The EPIC100 Rx and Tx buffer descriptors. */
|
/*
|
||||||
|
* The EPIC100 Rx and Tx buffer descriptors. Note that these
|
||||||
|
* really ARE host-endian; it's not a misannotation. We tell
|
||||||
|
* the card to byteswap them internally on big-endian hosts -
|
||||||
|
* look for #ifdef CONFIG_BIG_ENDIAN in epic_open().
|
||||||
|
*/
|
||||||
|
|
||||||
struct epic_tx_desc {
|
struct epic_tx_desc {
|
||||||
u32 txstatus;
|
u32 txstatus;
|
||||||
|
@ -418,7 +423,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
|
||||||
|
|
||||||
/* Note: the '175 does not have a serial EEPROM. */
|
/* Note: the '175 does not have a serial EEPROM. */
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
|
((__le16 *)dev->dev_addr)[i] = cpu_to_le16(inw(ioaddr + LAN0 + i*4));
|
||||||
|
|
||||||
if (debug > 2) {
|
if (debug > 2) {
|
||||||
dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
|
dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
|
||||||
|
@ -682,7 +687,8 @@ static int epic_open(struct net_device *dev)
|
||||||
if (ep->chip_flags & MII_PWRDWN)
|
if (ep->chip_flags & MII_PWRDWN)
|
||||||
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
|
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
|
||||||
|
|
||||||
#if defined(__powerpc__) || defined(__sparc__) /* Big endian */
|
/* Tell the chip to byteswap descriptors on big-endian hosts */
|
||||||
|
#ifdef CONFIG_BIG_ENDIAN
|
||||||
outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||||
inl(ioaddr + GENCTL);
|
inl(ioaddr + GENCTL);
|
||||||
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||||
|
@ -695,7 +701,7 @@ static int epic_open(struct net_device *dev)
|
||||||
udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
|
udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
|
outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
|
||||||
|
|
||||||
ep->tx_threshold = TX_FIFO_THRESH;
|
ep->tx_threshold = TX_FIFO_THRESH;
|
||||||
outl(ep->tx_threshold, ioaddr + TxThresh);
|
outl(ep->tx_threshold, ioaddr + TxThresh);
|
||||||
|
@ -798,7 +804,7 @@ static void epic_restart(struct net_device *dev)
|
||||||
for (i = 16; i > 0; i--)
|
for (i = 16; i > 0; i--)
|
||||||
outl(0x0008, ioaddr + TEST1);
|
outl(0x0008, ioaddr + TEST1);
|
||||||
|
|
||||||
#if defined(__powerpc__) || defined(__sparc__) /* Big endian */
|
#ifdef CONFIG_BIG_ENDIAN
|
||||||
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||||
#else
|
#else
|
||||||
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
|
||||||
|
@ -808,7 +814,7 @@ static void epic_restart(struct net_device *dev)
|
||||||
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
|
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
|
outl(le16_to_cpu(((__le16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
|
||||||
|
|
||||||
ep->tx_threshold = TX_FIFO_THRESH;
|
ep->tx_threshold = TX_FIFO_THRESH;
|
||||||
outl(ep->tx_threshold, ioaddr + TxThresh);
|
outl(ep->tx_threshold, ioaddr + TxThresh);
|
||||||
|
@ -919,7 +925,7 @@ static void epic_init_ring(struct net_device *dev)
|
||||||
/* Initialize all Rx descriptors. */
|
/* Initialize all Rx descriptors. */
|
||||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||||
ep->rx_ring[i].rxstatus = 0;
|
ep->rx_ring[i].rxstatus = 0;
|
||||||
ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz);
|
ep->rx_ring[i].buflength = ep->rx_buf_sz;
|
||||||
ep->rx_ring[i].next = ep->rx_ring_dma +
|
ep->rx_ring[i].next = ep->rx_ring_dma +
|
||||||
(i+1)*sizeof(struct epic_rx_desc);
|
(i+1)*sizeof(struct epic_rx_desc);
|
||||||
ep->rx_skbuff[i] = NULL;
|
ep->rx_skbuff[i] = NULL;
|
||||||
|
@ -936,7 +942,7 @@ static void epic_init_ring(struct net_device *dev)
|
||||||
skb_reserve(skb, 2); /* 16 byte align the IP header. */
|
skb_reserve(skb, 2); /* 16 byte align the IP header. */
|
||||||
ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
|
ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
|
||||||
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||||
ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
|
ep->rx_ring[i].rxstatus = DescOwn;
|
||||||
}
|
}
|
||||||
ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
|
ep->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
|
||||||
|
|
||||||
|
@ -974,20 +980,20 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
|
ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
|
||||||
skb->len, PCI_DMA_TODEVICE);
|
skb->len, PCI_DMA_TODEVICE);
|
||||||
if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
|
if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
|
||||||
ctrl_word = cpu_to_le32(0x100000); /* No interrupt */
|
ctrl_word = 0x100000; /* No interrupt */
|
||||||
} else if (free_count == TX_QUEUE_LEN/2) {
|
} else if (free_count == TX_QUEUE_LEN/2) {
|
||||||
ctrl_word = cpu_to_le32(0x140000); /* Tx-done intr. */
|
ctrl_word = 0x140000; /* Tx-done intr. */
|
||||||
} else if (free_count < TX_QUEUE_LEN - 1) {
|
} else if (free_count < TX_QUEUE_LEN - 1) {
|
||||||
ctrl_word = cpu_to_le32(0x100000); /* No Tx-done intr. */
|
ctrl_word = 0x100000; /* No Tx-done intr. */
|
||||||
} else {
|
} else {
|
||||||
/* Leave room for an additional entry. */
|
/* Leave room for an additional entry. */
|
||||||
ctrl_word = cpu_to_le32(0x140000); /* Tx-done intr. */
|
ctrl_word = 0x140000; /* Tx-done intr. */
|
||||||
ep->tx_full = 1;
|
ep->tx_full = 1;
|
||||||
}
|
}
|
||||||
ep->tx_ring[entry].buflength = ctrl_word | cpu_to_le32(skb->len);
|
ep->tx_ring[entry].buflength = ctrl_word | skb->len;
|
||||||
ep->tx_ring[entry].txstatus =
|
ep->tx_ring[entry].txstatus =
|
||||||
((skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN) << 16)
|
((skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN) << 16)
|
||||||
| cpu_to_le32(DescOwn);
|
| DescOwn;
|
||||||
|
|
||||||
ep->cur_tx++;
|
ep->cur_tx++;
|
||||||
if (ep->tx_full)
|
if (ep->tx_full)
|
||||||
|
@ -1041,7 +1047,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
|
||||||
for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
|
for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int entry = dirty_tx % TX_RING_SIZE;
|
int entry = dirty_tx % TX_RING_SIZE;
|
||||||
int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
|
int txstatus = ep->tx_ring[entry].txstatus;
|
||||||
|
|
||||||
if (txstatus & DescOwn)
|
if (txstatus & DescOwn)
|
||||||
break; /* It still hasn't been Txed */
|
break; /* It still hasn't been Txed */
|
||||||
|
@ -1163,8 +1169,8 @@ static int epic_rx(struct net_device *dev, int budget)
|
||||||
rx_work_limit = budget;
|
rx_work_limit = budget;
|
||||||
|
|
||||||
/* If we own the next entry, it's a new packet. Send it up. */
|
/* If we own the next entry, it's a new packet. Send it up. */
|
||||||
while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) {
|
while ((ep->rx_ring[entry].rxstatus & DescOwn) == 0) {
|
||||||
int status = le32_to_cpu(ep->rx_ring[entry].rxstatus);
|
int status = ep->rx_ring[entry].rxstatus;
|
||||||
|
|
||||||
if (debug > 4)
|
if (debug > 4)
|
||||||
printk(KERN_DEBUG " epic_rx() status was %8.8x.\n", status);
|
printk(KERN_DEBUG " epic_rx() status was %8.8x.\n", status);
|
||||||
|
@ -1238,7 +1244,8 @@ static int epic_rx(struct net_device *dev, int budget)
|
||||||
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||||
work_done++;
|
work_done++;
|
||||||
}
|
}
|
||||||
ep->rx_ring[entry].rxstatus = cpu_to_le32(DescOwn);
|
/* AV: shouldn't we add a barrier here? */
|
||||||
|
ep->rx_ring[entry].rxstatus = DescOwn;
|
||||||
}
|
}
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue