Skip to contentSkip to conversation

Linux Device Driver for Xilinx LL TEMAC 10/100/1000 Ethernet NIC

PATCH In review David H. Lynch Jr. 4 participants 7 messages Aug 19, 2008 – Sep 14, 2008 4 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Linux Device Driver for Xilinx LL TEMAC 10/100/1000 Ethernet NIC

Pass II

Linux Device Driver for Xilinx LL TEMAC 10/100/1000 Ethernet NIC

Original Author Yoshio Kashiwagi
Updated and Maintained by David Lynch

---

 drivers/net/Kconfig            |    5 
 drivers/net/Makefile           |    1 
 drivers/net/xps_lltemac.c      | 1562 ++++++++++++++++++++++++++++++++++++++++
 include/linux/xilinx_devices.h |    2 
 4 files changed, 1569 insertions(+), 1 deletions(-)
drivers/net/Kconfig +5 -0
index 033e13f..71b4c17 100644
@@ -2332,6 +2332,11 @@ config MV643XX_ETH
 	  Some boards that use the Discovery chipset are the Momenco
 	  Ocelot C and Jaguar ATX and Pegasos II.
 
+config XPS_LLTEMAC
+	tristate "Xilinx LLTEMAC 10/100/1000 Ethernet MAC driver"
+	help
+	  This driver supports the Xilinx 10/100/1000 LLTEMAC found in Virtex 4 FPGAs
+
 config QLA3XXX
 	tristate "QLogic QLA3XXX Network Driver Support"
 	depends on PCI
drivers/net/Makefile +1 -0
index 1f09934..9196bab 100644
@@ -126,6 +126,7 @@ obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_PICO_TEMAC) += pico_temac.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_XPS_LLTEMAC) += xps_lltemac.o
 obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o
drivers/net/xps_lltemac.c new file +1562 -0

1,562 lines not on this page · raw message

include/linux/xilinx_devices.h +1 -1
index 41ad421..40512d5 100755
@@ -94,7 +94,7 @@ struct xtemac_platform_data {
 #define XTEMAC_DMA_SGDMA	3	/* scatter gather DMA */
 #endif
 
-#if defined(CONFIG_XILINX_LLTEMAC)
+#if defined(CONFIG_XILINX_LLTEMAC) || defined(CONFIG_XPS_LLTEMAC)
 /* LLTEMAC platform data */
 struct xlltemac_platform_data {
 	u8 tx_csum;

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#5 lore raw

RE: [PATCH] Linux Device Driver for Xilinx LL TEMAC 10/100/1000 EthernetNIC

I screwed up and forgot to copy all on this previously.

Quoted 5 lines

-----Original Message-----
From: David H. Lynch Jr. [mailto:[email protected]]
Sent: Tuesday, August 19, 2008 3:19 PM
To: John Linn
Subject: Re: [PATCH] Linux Device Driver for Xilinx LL TEMAC

10/100/1000 EthernetNIC

Quoted 3 lines
Quoted 1 line · John Linn
Quoted 1 line

Stephen wants OF support -which is fine, but I can not test

that.

Quoted 3 lines
Quoted 3 lines
Quoted 1 line

I definitely agree with Stephen that OF support is needed since

arch/ppc

Quoted 3 lines
Quoted 3 lines

has gone away. We aren't doing any new work on arch/ppc.

Are you not planning to move to arch/powerpc anytime soon? I could

help

Quoted 6 lines
Quoted 4 lines

you with that transition which would be better in the long run. I'd rather do that than do testing for you as I think it would be more productive, but I've been wrong before.

We will move to powerpc, but not in the time-frame I am hoping for

this

Quoted 2 lines

driver.
In the context of Linux and Pico, "we" means me, and there is no time

to

Quoted 2 lines

do the work anytime soon.

<snip>

What about you getting all the review & testing done and then we (Xilinx) will add the OF support to the driver?

I doubt the powerpc mainline will take the driver without OF support. In fact, we had to remove the platform bus support from the last driver that we put into mainline for arch/powerpc.

Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

I would like
one and only one tag that can be used end-end.

Is there something xilinx will object to ? Prefer ? ....

xilinx_<device name>, (xilinx_lltemac or xilinx_ps2) is what we use

for

Quoted 1 line
Quoted 1 line

file names. The device tree does use "xlnx" to identify xilinx

devices,

Quoted 3 lines
Quoted 3 lines

but I don't think that should dictate file names.

We have a driver in out GIT tree that is not flat (as most know) for

the

Quoted 1 line
Quoted 1 line

LL TEMAC and we are working on creating flat drivers for future

devices.

Quoted 7 lines
Quoted 2 lines

Ideally this new driver would be a replacement for our driver.

Give me a name and I will go with it. the xps_lltemac name came from Yoshio,
It is not in stone.

Quoted 5 lines

If I name the module "xilinx_lltemac" and go with xilinx_lltemac.c for the file name,
is that going to cause problems with xilinx ?

I will use whatever you recomend.

xilinx_lltemac is the preferred.

I don't think using xilinx_lltemac should cause problems. Our Xilinx Git tree has a xilinx_lltemac subdir that contains the non-flat driver but that should be ok with your xilinx_lltemac.c file in the net directory.

Quoted 4 lines

--
Dave Lynch DLA Systems
Software Development:

Embedded Linux

Quoted 3 lines

717.627.3770 [email protected] http://www.dlasys.net
fax: 1.253.369.9244 Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies

too numerous to list.

Quoted 2 lines

"Any intelligent fool can make things bigger and more complex... It

takes a touch of genius - and a

Quoted 3 lines

lot of courage to move in the opposite direction." Albert Einstein

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

#6 lore raw

Re: [PATCH] Linux Device Driver for Xilinx LL TEMAC 10/100/1000 EthernetNIC

Quoted 8 lines · John Linn

What about you getting all the review & testing done and then we (Xilinx) will add the OF support to the driver?

I doubt the powerpc mainline will take the driver without OF support. In fact, we had to remove the platform bus support from the last driver that we put into mainline for arch/powerpc.

That is perfectly fine with me. i will try to pull the xilinx git tree and see how much closer I can make the probe so that converting will be easier.

Quoted 9 lines

xilinx_lltemac is the preferred.

I don't think using xilinx_lltemac should cause problems. Our Xilinx Git tree has a xilinx_lltemac subdir that contains the non-flat driver but that should be ok with your xilinx_lltemac.c file in the net directory.

The next patch incarnation will have everything as xilinx_lltemac - including the file as xilinx_lltemac.c

Signature · 8 lines
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       [email protected] 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein
#7 lore raw

RE: [PATCH] Linux Device Driver for Xilinx LL TEMAC 10/100/1000 EthernetNIC

In reply to David H. Lynch Jr.

I'm not claiming to be a Linux driver expert as I'm still learning. Some of the comments are nits.

Thanks for the effort you're putting in on this.

Quoted 5 lines

Linux Device Driver for Xilinx LL TEMAC 10/100/1000 Ethernet NIC

Original Author Yoshio Kashiwagi
Updated and Maintained by David Lynch

Quoted 7 lines

---

 drivers/net/Kconfig            |    5 
 drivers/net/Makefile           |    1 
 drivers/net/xps_lltemac.c      | 1562

++++++++++++++++++++++++++++++++++++++++

Quoted 8 lines
 include/linux/xilinx_devices.h |    2 
 4 files changed, 1569 insertions(+), 1 deletions(-)
drivers/net/Kconfig +0 -0
index 033e13f..71b4c17 100644

drivers/net/Kconfig config MV643XX_ETH · line 2338

Quoted 7 lines
drivers/net/Kconfig +4 -0
@@ -2332,6 +2332,11 @@ config MV643XX_ETH
 	  Some boards that use the Discovery chipset are the Momenco
 	  Ocelot C and Jaguar ATX and Pegasos II.
 
+config XPS_LLTEMAC
+	tristate "Xilinx LLTEMAC 10/100/1000 Ethernet MAC driver"
+	help
+	  This driver supports the Xilinx 10/100/1000 LLTEMAC found in

Virtex 4 FPGAs

It might be helpful to say only in DMA mode as our traditional drivers support FIFO mode and DMA.
Since the FPGA is pretty flexible people tend to do things different than I sometimes expect.

drivers/net/xps_lltemac.c

Quoted 23 lines
drivers/net/Kconfig +1 -0
+
 config QLA3XXX
 	tristate "QLogic QLA3XXX Network Driver Support"
 	depends on PCI
drivers/net/Makefile +1 -0
index 1f09934..9196bab 100644
@@ -126,6 +126,7 @@ obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_PICO_TEMAC) += pico_temac.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_XPS_LLTEMAC) += xps_lltemac.o
 obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o
drivers/net/xps_lltemac.c new file +0 -0
new file mode 100644
index 0000000..8af4e7a
@@ -0,0 +1,1562 @@

+/*===================================================================== =

drivers/net/xps_lltemac.c line 3

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+
+ Driver for Xilinx temac ethernet NIC's

Saying LL TEMAC would be clearer as we having older TEMACs that are yet different and not local link (LL).

It's definitely not a NIC in the traditional sense of a PCI card, but is an SOC core.

drivers/net/xps_lltemac.c line 10

Quoted 8 lines
drivers/net/xps_lltemac.c new file +7 -0
+
+ Author: Yoshio Kashiwagi
+ Copyright (c) 2008 Nissin Systems Co.,Ltd.
+
+ Revisons: David H. Lynch Jr. <[email protected]>
+ Copyright (C) 2005-2008 DLA Systems
+

+======================================================================*
/

Quoted 16 lines
drivers/net/xps_lltemac.c new file +16 -0
+/* DRV_NAME is for compatibility with existing xilinx ll temac driver
+ * also with  of/dtc object names */
+#define DRV_NAME        "xilinx_lltemac"
+#define DRV_AUTHOR      "Yoshio Kashiwagi"
+#define DRV_EMAIL       ""
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <linux/mii.h>
+#include <linux/in.h>

drivers/net/xps_lltemac.c line 37

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+#include <linux/pci.h>
+
+#include <linux/ip.h>
+#include <linux/tcp.h>      /* just needed for sizeof(tcphdr) */
+#include <linux/udp.h>      /* needed for sizeof(udphdr) */
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#define MII_ANI                     0x10
+#define PHY_NUM                     0

This phy number, (phy address), won't work for a number of Xilinx boards. It seems like this should be either pulled from the platform data (and device tree), or the driver should try to find the PHY address by trying each one.

Otherwise the users will have to edit the driver all the time when their phy is not address 0.

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+#define PHY_TIMEOUT                 10000
+

<snip>

drivers/net/xps_lltemac.c line 495

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+static unsigned int
+mdio_read(struct net_device *ndev, int phy_id, int reg_num)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout = PHY_TIMEOUT;
+	u32 rv = 0;
+	unsigned long flags;
+
+	if ((reg_num >  MII_REG_MAX) ||
+		(phy_id == PHY_ADDR_INVALID)) {

The phy_id never gets set to PHY_ADDR_INVALID, is there something I'm missing or should this be removed? Maybe this is related to the PHY_NUM hard coded value that could be set invalid.

drivers/net/xps_lltemac.c

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+		dev_err(&ndev->dev,
+			"mdio_read(%x, %x) invalid reg_num or invalid

phy_id\n",

drivers/net/xps_lltemac.c

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+			reg_num, phy_id);
+		return -1;

Returning a negative value for failure makes sense, but not when the return type is unsigned int, should it be an int instead?

I put in nits about return types and I realize their nits, but should make the driver better was my
hope.

drivers/net/xps_lltemac.c

Quoted 12 lines
drivers/net/xps_lltemac.c new file +12 -0
+	}
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	tiow(ndev, XTE_LSW0_OFFSET,
+			((phy_id << 5) | (reg_num)));
+	tiow(ndev, XTE_CTL0_OFFSET,
+			XTE_MIIMAI_OFFSET | (lp->emac_num << 10));
+	while (!(tior(ndev, XTE_RDY0_OFFSET) & XTE_RSE_MIIM_RR_MASK)) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev, "read_MII busy

timeout!!\n");

drivers/net/xps_lltemac.c

Quoted 11 lines
drivers/net/xps_lltemac.c new file +11 -0
+			return -1;
+		}
+	}
+	rv = tior(ndev, XTE_LSW0_OFFSET);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return rv;
+}
+
+static void
+mdio_write(struct net_device *ndev, int phy_id, int reg_num, int

reg_val)

drivers/net/xps_lltemac.c

Quoted 9 lines
drivers/net/xps_lltemac.c new file +9 -0
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout = PHY_TIMEOUT, status;
+	unsigned long flags;
+
+	if ((reg_num >  MII_REG_MAX) ||
+		(phy_id == PHY_ADDR_INVALID)) {
+		dev_err(&ndev->dev,
+			"mdio_write(%x, %x)invalid reg_num or invalid

phy_id\n",

drivers/net/xps_lltemac.c

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+			reg_num, phy_id);
+		return -1;

The return type is void yet it tries to return -1, should it be int return?

Quoted 5 lines
drivers/net/xps_lltemac.c new file +5 -0
+	}
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	tiow(ndev, XTE_LSW0_OFFSET,

drivers/net/xps_lltemac.c

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+			reg_val);
+	tiow(ndev, XTE_CTL0_OFFSET,
+			CNTLREG_WRITE_ENABLE_MASK | XTE_MGTDR_OFFSET);
+	tiow(ndev, XTE_LSW0_OFFSET,
+			((phy_id << 5) | (reg_num)));
+	tiow(ndev, XTE_CTL0_OFFSET,
+			CNTLREG_WRITE_ENABLE_MASK
+			| XTE_MIIMAI_OFFSET
+			| (lp->emac_num << 10));
+	while (!(status = tior(ndev, XTE_RDY0_OFFSET) &

XTE_RSE_MIIM_WR_MASK)) {

drivers/net/xps_lltemac.c

Quoted 3 lines
drivers/net/xps_lltemac.c new file +3 -0
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev, "write_MII busy

timeout!!\n");

drivers/net/xps_lltemac.c

Quoted 1 line
drivers/net/xps_lltemac.c new file +1 -0
+			return ;

Seems like this should return -1 as a failure and be consistent with read().

Quoted 9 lines
drivers/net/xps_lltemac.c new file +9 -0
+		}
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static u32
+emac_cfg_read(struct net_device *ndev, u16 reg_num)
+{

drivers/net/xps_lltemac.c line 571

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout = PHY_TIMEOUT;
+
+	if (reg_num > TEMAC_REG_MAX) {
+		dev_err(&ndev->dev,
+				"emac_cfg_read(%x) invalid reg_num\n",
+				reg_num);
+		return -1;
+	}
+

Can the register value read be -1 by accident such that a valid register return
looks like a failure?

drivers/net/xps_lltemac.c

Quoted 5 lines
drivers/net/xps_lltemac.c new file +5 -0
+	tiow(ndev, XTE_CTL0_OFFSET, (lp->emac_num << 10) | reg_num);
+	while (!(tior(ndev, XTE_RDY0_OFFSET) & XTE_RSE_CFG_RR_MASK)) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev, "read temac busy

timeout!!\n");

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+			return -1;
+		}
+	}
+	return (u32) tior(ndev, XTE_LSW0_OFFSET);
+
+}
+
+static void
+emac_cfg_write(struct net_device *ndev, u32 reg_num, u32 val)
+{

drivers/net/xps_lltemac.c line 596

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout = PHY_TIMEOUT;
+
+	if (reg_num > TEMAC_REG_MAX) {
+		dev_err(&ndev->dev,
+				"emac_cfg_write(%x) invalid reg_num\n",
+				reg_num);
+		return -1;
+	}
+

Same thing returning a value when void return, and timeout below again should
return failure? It would seem like these be compiler warnings?

drivers/net/xps_lltemac.c

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+	tiow(ndev, XTE_LSW0_OFFSET, val);
+	tiow(ndev,
+			XTE_CTL0_OFFSET,
+			(CNTLREG_WRITE_ENABLE_MASK
+			 | (lp->emac_num << 10)
+			 | reg_num));
+	while (!(tior(ndev, XTE_RDY0_OFFSET) & XTE_RSE_CFG_WR_MASK)) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev, "write temac busy

timeout!!\n");

drivers/net/xps_lltemac.c

Quoted 7 lines
drivers/net/xps_lltemac.c new file +7 -0
+			return ;
+		}
+	}
+}
+
+static u32
+emac_cfg_setclr(struct net_device *ndev, u32 reg_num, u32 val, int

flg)

drivers/net/xps_lltemac.c line 621

Quoted 8 lines
drivers/net/xps_lltemac.c new file +8 -0
+{
+	u32 Reg;
+	if (reg_num > TEMAC_REG_MAX) {
+		dev_err(&ndev->dev,
+				"emac_cfg_setclr(%x) invalid reg_num\n",
+				reg_num);
+		return -1;
+	}

Nit.

Sorry to pick on return values so much, but they seem real inconsistent. seems like an int would be more appropriate here as there's no register value
to be returned.

Quoted 8 lines
drivers/net/xps_lltemac.c new file +8 -0
+
+	Reg = emac_cfg_read(ndev, reg_num) & ~val;
+	if (flg)
+		Reg |= val;
+	emac_cfg_write(ndev, reg_num, Reg);
+	return 0;
+}
+

<snip>

drivers/net/xps_lltemac.c

Quoted 8 lines
drivers/net/xps_lltemac.c new file +8 -0
+static int
+temac_bd_init(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct sk_buff *skb;
+	int ii;
+
+	lp->rx_skb = kzalloc(sizeof(struct sk_buff)*RX_BD_NUM,

GFP_KERNEL);

drivers/net/xps_lltemac.c line 805

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+	/* allocate the tx and rx ring buffer descriptors. */
+	/* returns a virtual addres and a physical address. */
+	lp->tx_bd_v = dma_alloc_coherent(NULL,
+			sizeof(struct cdmac_bd) * TX_BD_NUM,
+			(dma_addr_t *)&lp->tx_bd_p,
+			GFP_KERNEL);
+	lp->rx_bd_v = dma_alloc_coherent(NULL,
+			sizeof(struct cdmac_bd) * RX_BD_NUM,
+			(dma_addr_t *)&lp->rx_bd_p,
+			GFP_KERNEL);

Not sure this is a big deal, BDs have to be cacheline aligned, but since there are 8 words for each, it's not a problem on 405 and 440 (32 byte cacheline). Other powerpc processors might be a problem. A more specific dependency on 4xx might be useful?

drivers/net/xps_lltemac.c

Quoted 3 lines
drivers/net/xps_lltemac.c new file +3 -0
+
+	for (ii = 0; ii < TX_BD_NUM; ii++) {
+		memset((char *)&lp->tx_bd_v[ii], 0, sizeof(struct

cdmac_bd));

Quoted 6 lines
drivers/net/xps_lltemac.c new file +6 -0
+		if (ii == (TX_BD_NUM - 1))
+			lp->tx_bd_v[ii].next = &lp->tx_bd_p[0];
+		else
+			lp->tx_bd_v[ii].next = &lp->tx_bd_p[ii + 1];
+
+	}

<snip>

drivers/net/xps_lltemac.c line 996

Quoted 13 lines
drivers/net/xps_lltemac.c new file +13 -0
+
+/* Initilize temac */
+static void
+temac_device_reset(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	u32 timeout = 1000;
+
+	/* Perform a software reset */
+
+	/* 0x300 host enable bit ? */
+	/* reset PHY through control register ?:1 */
+

Seems like the above comments should be removed.

drivers/net/xps_lltemac.c

Quoted 4 lines
drivers/net/xps_lltemac.c new file +4 -0
+	/* Reset the device */
+	emac_cfg_write(ndev, XTE_RXC1_OFFSET, XTE_RXC1_RXRST_MASK);
+	/* Wait for the receiver to finish reset */
+	while (emac_cfg_read(ndev, XTE_RXC1_OFFSET) &

XTE_RXC1_RXRST_MASK) {

drivers/net/xps_lltemac.c

Quoted 4 lines
drivers/net/xps_lltemac.c new file +4 -0
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset RX reset

timeout!!\n");

drivers/net/xps_lltemac.c

Quoted 8 lines
drivers/net/xps_lltemac.c new file +8 -0
+			break;
+		}
+	}
+
+	emac_cfg_write(ndev, XTE_TXC_OFFSET, XTE_TXC_TXRST_MASK);
+	/* Wait for the transmitter to finish reset */
+	timeout = 1000;
+	while (emac_cfg_read(ndev, XTE_TXC_OFFSET) & XTE_TXC_TXRST_MASK)

{

drivers/net/xps_lltemac.c

Quoted 4 lines
drivers/net/xps_lltemac.c new file +4 -0
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset TX reset

timeout!!\n");

Quoted 9 lines
drivers/net/xps_lltemac.c new file +9 -0
+			break;
+		}
+	}
+
+	/* Disable the receiver */
+	emac_cfg_write(ndev,
+			XTE_RXC1_OFFSET,
+			emac_cfg_read(ndev, XTE_RXC1_OFFSET)
+			& ~XTE_RXC1_RXEN_MASK);

drivers/net/xps_lltemac.c

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+
+	/* reset */
+	tiow(ndev, XTE_RAF0_OFFSET, 1);
+	/* wait for reset */
+	timeout = 1000;
+	while (tior(ndev, XTE_RAF0_OFFSET) & 1) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset RAF reset

timeout!!\n");

Quoted 9 lines
drivers/net/xps_lltemac.c new file +9 -0
+			break;
+		}
+	}
+
+	/* ISR0/IER0/IPR0 bits */
+	/* b1         autoneg complete */
+	/* b2         receive complete */
+	/* b5         transmit complete */
+	/* b0       = interrupts from TIS/TIE registers */

drivers/net/xps_lltemac.c

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+
+
+	/* Reset */
+	sd_iow(ndev, DMA_CONTROL_REG, DMA_CONTROL_RST);
+	timeout = 1000;
+	while (sd_ior(ndev, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
+		udelay(1);
+		if (--timeout == 0) {
+			dev_err(&ndev->dev,
+				"temac_device_reset DMA reset

timeout!!\n");

drivers/net/xps_lltemac.c

Quoted 6 lines
drivers/net/xps_lltemac.c new file +6 -0
+			break;
+		}
+	}
+
+	dev_info(&ndev->dev,
+			"%s: Xilinx Embedded Tri-Mode Ethernet MAC %s

%s\n",

Quoted 8 lines
drivers/net/xps_lltemac.c new file +8 -0
+			ndev->name,
+			__DATE__,
+			__TIME__);
+	dev_info(&ndev->dev, "temac %08x sdma %08x\n",
+			lp->regs.addr,
+			lp->sdma.addr);
+
+	temac_bd_init(ndev);

drivers/net/xps_lltemac.c

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+
+	emac_cfg_write(ndev, XTE_RXC0_OFFSET, 0);
+	emac_cfg_write(ndev, XTE_RXC1_OFFSET, 0);
+	emac_cfg_write(ndev, XTE_TXC_OFFSET, 0);
+	emac_cfg_write(ndev, XTE_FCC_OFFSET, XTE_FCC_RXFLO_MASK);
+
+	/* Sync default options with HW
+	 * but leave receiver and transmitter disabled.  */
+	temac_setoptions(ndev,
+			lp->options & ~(XTE_OPTION_TXEN |

XTE_OPTION_RXEN));

Quoted 20 lines
drivers/net/xps_lltemac.c new file +20 -0
+
+	temac_phy_init(ndev);
+
+	temac_set_mac_address(ndev, 0);
+	/* Set address filter table */
+	temac_set_multicast_list(ndev);
+	if (temac_setoptions(ndev, lp->options))
+		dev_err(&ndev->dev, "Error setting TEMAC options\n");
+
+	/* Init Driver variable */
+	ndev->trans_start = 0;
+	spin_lock_init(&lp->lock);
+	spin_lock_init(&lp->rx_lock);
+}
+
+static void
+temac_hard_start_xmit_done(struct net_device *ndev)
+{
+	struct temac_local *lp = netdev_priv(ndev);
+	struct cdmac_bd *cur_p;

drivers/net/xps_lltemac.c line 1108

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+	unsigned int stat = 0;
+
+	cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+	stat = cur_p->app0;
+
+	while (stat & STS_CTRL_APP0_CMPLT) {
+		pci_unmap_single(NULL,
+				(unsigned long)cur_p->phys,
+				cur_p->len,
+				PCI_DMA_TODEVICE);

It seems like the PCI calls would be better replaced with dma_unmap_single()
and dma_map_single to be more accurate and probably less overhead?

The dma functions, not sure on the pci, should handle when we change the driver
to cache the BDs as that will be needed eventually for good performance.

drivers/net/xps_lltemac.c

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+		if (cur_p->app4)
+			dev_kfree_skb_irq((struct sk_buff

*)cur_p->app4);

Quoted 16 lines
drivers/net/xps_lltemac.c new file +16 -0
+		cur_p->app0 = 0;
+
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes += cur_p->len;
+
+		lp->tx_bd_ci++;
+		if (lp->tx_bd_ci >= TX_BD_NUM)
+			lp->tx_bd_ci = 0;
+
+		cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+		stat = cur_p->app0;
+	}
+
+	netif_wake_queue(ndev);
+}
+

<snip>

drivers/net/xps_lltemac.c

Quoted 2 lines
drivers/net/xps_lltemac.c new file +2 -0
+static int __init
+temac_device_map(struct platform_device *pdev, struct net_device

*ndev,

Quoted 11 lines
drivers/net/xps_lltemac.c new file +11 -0
+		int num, struct temac_region *reg)
+{
+	struct resource *res;
+	int erC = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, num);
+	if (res == 0) {
+		erC = -ENODEV;
+		goto fail;
+	}
+	if (request_mem_region(res->start, res->end - res->start,

drivers/net/xps_lltemac.c line 1396

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+				pdev->name) == 0) {
+		dev_err(&pdev->dev,
+				"%s: failed to request registers\n",
+				pdev->name);
+		erC = -ENXIO;
+		goto fail;
+	}
+
+	reg->base = (uintptr_t)res->start;
+	reg->len  = res->end - res->start;

Should this really be res->end - res->start + 1 to include the memory region? It's also used up above in the mem_region call.

Quoted 13 lines
drivers/net/xps_lltemac.c new file +13 -0
+	reg->addr = ioremap_nocache((uintptr_t)reg->base, reg->len);
+	if (reg->addr == 0) {
+		dev_err(&pdev->dev,
+			"%s: failed to remap registers\n", pdev->name);
+		erC = -ENXIO;
+		goto fail_remap;
+	}
+	return 0;
+fail_remap:
+	release_region((u32)reg->addr, reg->len);
+fail:
+	return erC;
+}

<snip>

Quoted 2 lines

-----Original Message-----
From: [email protected]

[mailto:linuxppc-embedded-

Quoted 1 line

[email protected]] On Behalf Of David H. Lynch

Jr.

Quoted 3 lines

Sent: Tuesday, August 19, 2008 3:34 AM
To: linuxppc-embedded; [email protected]
Subject: [PATCH] Linux Device Driver for Xilinx LL TEMAC 10/100/1000

EthernetNIC

Quoted 2 lines

Pass II

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

#8 lore raw
In reply to David H. Lynch Jr.
Quoted 8 lines · On Tuesday 19 August 2008 13:34:04 David H. Lynch Jr. wrote:

Pass II

drivers/net/xps_lltemac.c new file +6 -0
+       cur_p->phys = (unsigned char *)pci_map_single(NULL,
+                       skb->data, skb->len,
+                       PCI_DMA_TODEVICE);
+       cur_p->app4 = (unsigned long)skb;
+
+       for (ii = 0; ii < num_frag; ii++) {

drivers/net/xps_lltemac.c line 1200

Quoted 10 lines
drivers/net/xps_lltemac.c new file +10 -0
+               lp->tx_bd_tail++;
+               if (lp->tx_bd_tail >= TX_BD_NUM)
+                       lp->tx_bd_tail = 0;
+
+               cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+               cur_p->phys = (unsigned char *)pci_map_single(NULL,
+                               (void *)page_address(frag->page)
+                               + frag->page_offset,
+                               frag->size,
+                               PCI_DMA_TODEVICE);

1. Why is pci_* API is used instead of dma_*?
2. Why pci_map_single() in skb_shinfo(skb)->frags processing instead of dma_map_page()?

drivers/net/xps_lltemac.c line 812

Quoted 4 lines
drivers/net/xps_lltemac.c new file +4 -0
+               if (ii == (TX_BD_NUM - 1))
+                       lp->tx_bd_v[ii].next = &lp->tx_bd_p[0];
+               else
+                       lp->tx_bd_v[ii].next = &lp->tx_bd_p[ii + 1];

3. It would be much simpler to use masking by (TX_BD_NUM - 1) instead of "if (ii == (TX_BD_NUM - 1))" constructs.

4. There is a need of global locking mechanism for indirect registers access, as according to Xilinx documentation only one hard core at a a time can be accessed.

#9 lore raw
In reply to David H. Lynch Jr.

T24gVHVlc2RheSAxOSBBdWd1c3QgMjAwOCAxMzozNDowNCBEYXZpZCBILiBMeW5jaCBKci4gd3Jv dGU6Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHN3aXRjaCAoaXAtPnByb3RvY29s KSB7Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGNhc2UgSVBQUk9UT19UQ1A6Cj4g K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBzdGFydCA9IHNp emVvZihzdHJ1Y3QgaXBoZHIpICsgRVRIX0hMRU47Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBpbnNlcnQgPSBzaXplb2Yoc3RydWN0IGlwaGRyKSArIEVU SF9ITEVOICsgMTY7Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqBsZW5ndGggPSBpcC0+dG90X2xlbiAtIHNpemVvZihzdHJ1Y3QgaXBoZHIpOwo+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgaGVhZGxlbiA9IEVUSF9I TEVOCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgKyBzaXplb2Yoc3RydWN0IGlwaGRyKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCsgc2l6ZW9mKHN0cnVj dCB0Y3BoZHIpOwo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgYnJlYWs7Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGNhc2UgSVBQUk9UT19V RFA6Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBzdGFy dCA9IHNpemVvZihzdHJ1Y3QgaXBoZHIpICsgRVRIX0hMRU47Cj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBpbnNlcnQgPSBzaXplb2Yoc3RydWN0IGlwaGRy KSArIEVUSF9ITEVOICsgNjsKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoGxlbmd0aCA9IGlwLT50b3RfbGVuIC0gc2l6ZW9mKHN0cnVjdCBpcGhkcik7Cj4g K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqBoZWFkbGVuID0g RVRIX0hMRU4KPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqArIHNpemVvZihzdHJ1Y3QgaXBoZHIpCj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgKyBzaXplb2Yo c3RydWN0IHVkcGhkcik7Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqBicmVhazsKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgZGVmYXVsdDoK PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoGJyZWFrOwo+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB9CgpXaHkgYWxsIHRoZXNlIGNhbGN1bGF0 aW9ucyBpbnN0ZWFkIG9mIHNrYl90cmFuc3BvcnRfb2Zmc2V0KHNrYikgYW5kIApza2ItPmNzdW1f b2Zmc2V0IHVzYWdlPwoK