Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ebfd492 authored by Al Viro's avatar Al Viro Committed by Jeff Garzik
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 48f5fec5
Loading
Loading
Loading
Loading
+27 −20
Original line number Original line Diff line number Diff line
@@ -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;
}
}