diff mbox

dnet: Dave DNET ethernet controller driver

Message ID 1236738549-16703-1-git-send-email-yanok@emcraft.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Ilya Yanok March 11, 2009, 2:29 a.m. UTC
Driver for Dave DNET ethernet controller found on Dave/DENX QongEVB-LITE
FPGA. Heavily based on Dave sources, I've just adopted it to current
kernel version and done some code cleanup.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
 drivers/net/Kconfig  |   11 +
 drivers/net/Makefile |    1 +
 drivers/net/dnet.c   | 1019 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dnet.h   |  226 +++++++++++
 4 files changed, 1257 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/dnet.c
 create mode 100644 drivers/net/dnet.h

Comments

Eric Dumazet March 11, 2009, 4 a.m. UTC | #1
Ilya Yanok a écrit :
> Driver for Dave DNET ethernet controller found on Dave/DENX QongEVB-LITE
> FPGA. Heavily based on Dave sources, I've just adopted it to current
> kernel version and done some code cleanup.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>

> +		skb = dev_alloc_skb(pkt_len + 5);
> +		if (skb != NULL) {


> +			skb->dev = dev;

minor nit : This is not necessary anymore
 
	eth_type_trans(skb, dev) does the skb->dev = dev; initialization
in recent kernels.

commit 4c13eb6657fe9ef7b4dc8f1a405c902e9e5234e0
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
Date:   Wed Apr 25 17:40:23 2007 -0700

    [ETH]: Make eth_type_trans set skb->dev like the other *_type_trans

    One less thing for drivers writers to worry about.

    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>


> +			/* Align IP on 16 byte boundaries */
> +			skb_reserve(skb, 2);
> +			/*
> +			 * 'skb_put()' points to the start of sk_buff
> +			 * data area.
> +			 */
> +			data_ptr = (unsigned int *)skb_put(skb, pkt_len);
> +			for (i = 0; i < (pkt_len + 3) >> 2; i++)
> +				*data_ptr++ = dnet_readl(bp, RX_DATA_FIFO);
> +			skb->protocol = eth_type_trans(skb, dev);
> +			netif_receive_skb(skb);
> +			bp->dev->last_rx = jiffies;


This last_rx init is not anymore needed :

commit babcda74e9d96bb58fd9c6c5112dbdbff169e695
Author: David S. Miller <davem@davemloft.net>
Date:   Mon Nov 3 21:11:17 2008 -0800

    drivers/net: Kill now superfluous ->last_rx stores.

    The generic packet receive code takes care of setting
    netdev->last_rx when necessary, for the sake of the
    bonding ARP monitor.

    Drivers need not do it any more.

    Some cases had to be skipped over because the drivers
    were making use of the ->last_rx value themselves.

    Signed-off-by: David S. Miller <davem@davemloft.net>



> +			npackets++;
> +		} else
> +			printk(KERN_NOTICE
> +			       "%s: No memory to allocate a sk_buff of "
> +			       "size %d.\n", dev->name, pkt_len);

pkt_len is an "unsigned int", so please use %u

> +	}
> +




+static struct ethtool_ops dnet_ethtool_ops = {
+	.get_settings		= dnet_get_settings,
+	.set_settings		= dnet_set_settings,
+	.get_drvinfo		= dnet_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+};
+

Please add a const qualifier to this.



struct dnet {
+	void __iomem			*regs;
+	spinlock_t			lock;
+	struct platform_device	*pdev;
+	struct net_device		*dev;
+	struct net_device_stats	stats;
+	struct dnet_stats		hw_stats;
+	unsigned int			capabilities; /* read from FPGA */
+	struct napi_struct		napi;


Are you sure you need a "struct net_device_stats stats;" in "struct dnet" ?
One is already included in "struct net_device", you probably can use it.

Thank you

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger March 11, 2009, 4:18 a.m. UTC | #2
On Wed, 11 Mar 2009 05:29:09 +0300
Ilya Yanok <yanok@emcraft.com> wrote:

> +static char ethaddr[18];
> +
> +module_param_string(ethaddr, ethaddr, sizeof(ethaddr), 0);
> +
> +static void get_mac_addr(struct net_device *nd, unsigned char *pmac)
> +{
> +	int i;
> +	char *p = ethaddr;
> +
> +	ethaddr[17] = 0;
> +	for (i = 0; i < ETH_ALEN; i++, p++) {
> +		pmac[i] = simple_strtoul(p, &p, 16);
> +		if (*p != ':')
> +			break;
> +	}
> +	if (i != ETH_ALEN - 1) {
> +		pr_err("Wrong MAC address format!\n");
> +		memset(pmac, 0, ETH_ALEN);
> +	}
> +}
> +

Do you still need this? Only works with one board, configuration via
module parameters is discouraged.  Same effect can be done by setting
mac address with regular tools.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 11, 2009, 8:44 a.m. UTC | #3
Hi,

On Tue, Mar 10, 2009 at 09:18:41PM -0700, Stephen Hemminger wrote:
> On Wed, 11 Mar 2009 05:29:09 +0300
> Ilya Yanok <yanok@emcraft.com> wrote:
> 
> > +static char ethaddr[18];
> > +
> > +module_param_string(ethaddr, ethaddr, sizeof(ethaddr), 0);
> > +
> > +static void get_mac_addr(struct net_device *nd, unsigned char *pmac)
> > +{
> > +	int i;
> > +	char *p = ethaddr;
> > +
> > +	ethaddr[17] = 0;
> > +	for (i = 0; i < ETH_ALEN; i++, p++) {
> > +		pmac[i] = simple_strtoul(p, &p, 16);
> > +		if (*p != ':')
> > +			break;
> > +	}
> > +	if (i != ETH_ALEN - 1) {
> > +		pr_err("Wrong MAC address format!\n");
> > +		memset(pmac, 0, ETH_ALEN);
> > +	}
> > +}
> > +
> 
> Do you still need this? Only works with one board, configuration via
> module parameters is discouraged.  Same effect can be done by setting
> mac address with regular tools.

Except for root over nfs. Ok, the answer to this is usually 'use
initrd', but this is still a pita on embedded systems.

Sascha
David Miller March 11, 2009, 8:49 a.m. UTC | #4
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Wed, 11 Mar 2009 09:44:30 +0100

> On Tue, Mar 10, 2009 at 09:18:41PM -0700, Stephen Hemminger wrote:
> > Do you still need this? Only works with one board, configuration via
> > module parameters is discouraged.  Same effect can be done by setting
> > mac address with regular tools.
> 
> Except for root over nfs. Ok, the answer to this is usually 'use
> initrd', but this is still a pita on embedded systems.

Please remove this code.  If we let you do it, we have to let everyone
else do it too, and that's something we don't want to do.

There are other ways you can handle this, for example have your board
firmware properly program the MAC address into the card at power-on,
and then have the driver here look in the MAC address registers to see
if a valid ethernet address has been left there.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 11, 2009, 8:57 a.m. UTC | #5
On Wed, Mar 11, 2009 at 01:49:57AM -0700, David Miller wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Wed, 11 Mar 2009 09:44:30 +0100
> 
> > On Tue, Mar 10, 2009 at 09:18:41PM -0700, Stephen Hemminger wrote:
> > > Do you still need this? Only works with one board, configuration via
> > > module parameters is discouraged.  Same effect can be done by setting
> > > mac address with regular tools.
> > 
> > Except for root over nfs. Ok, the answer to this is usually 'use
> > initrd', but this is still a pita on embedded systems.
> 
> Please remove this code.  If we let you do it, we have to let everyone
> else do it too, and that's something we don't want to do.
> 
> There are other ways you can handle this, for example have your board
> firmware properly program the MAC address into the card at power-on,
> and then have the driver here look in the MAC address registers to see
> if a valid ethernet address has been left there.

Cool, that's how I do it on many boards I have, but I always had the
feeling I was flying under the radar with it.

Sascha
Wolfgang Denk March 11, 2009, 9:09 a.m. UTC | #6
Dear David,

on Wed, Mar 11, 2009 at 01:49:57AM -0700, David Miller wrote:
> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Wed, 11 Mar 2009 09:44:30 +0100
> 
> > On Tue, Mar 10, 2009 at 09:18:41PM -0700, Stephen Hemminger wrote:
> > > Do you still need this? Only works with one board, configuration via
> > > module parameters is discouraged.  Same effect can be done by setting
> > > mac address with regular tools.
> > 
> > Except for root over nfs. Ok, the answer to this is usually 'use
> > initrd', but this is still a pita on embedded systems.
> 
> Please remove this code.  If we let you do it, we have to let everyone
> else do it too, and that's something we don't want to do.
> 
> There are other ways you can handle this, for example have your board
> firmware properly program the MAC address into the card at power-on,
> and then have the driver here look in the MAC address registers to see
> if a valid ethernet address has been left there.

How do you then handle situations where this is impossible? Say, when
the firmware cannot write to those registers for example because  the
ethernet  controller is not even powered on (to reduce power consump-
tion), but will get powered on only in Linux  when  the  driver  gets
loaded (i. e. on demand only, not always)?

Best regards,

Wolfgang Denk
Sascha Hauer March 11, 2009, 10:35 a.m. UTC | #7
Hi Wolfgang,

On Wed, Mar 11, 2009 at 10:09:38AM +0100, Wolfgang Denk wrote:
> Dear David,
> 
> on Wed, Mar 11, 2009 at 01:49:57AM -0700, David Miller wrote:
> > From: Sascha Hauer <s.hauer@pengutronix.de>
> > Date: Wed, 11 Mar 2009 09:44:30 +0100
> > 
> > > On Tue, Mar 10, 2009 at 09:18:41PM -0700, Stephen Hemminger wrote:
> > > > Do you still need this? Only works with one board, configuration via
> > > > module parameters is discouraged.  Same effect can be done by setting
> > > > mac address with regular tools.
> > > 
> > > Except for root over nfs. Ok, the answer to this is usually 'use
> > > initrd', but this is still a pita on embedded systems.
> > 
> > Please remove this code.  If we let you do it, we have to let everyone
> > else do it too, and that's something we don't want to do.
> > 
> > There are other ways you can handle this, for example have your board
> > firmware properly program the MAC address into the card at power-on,
> > and then have the driver here look in the MAC address registers to see
> > if a valid ethernet address has been left there.
> 
> How do you then handle situations where this is impossible? Say, when
> the firmware cannot write to those registers for example because  the
> ethernet  controller is not even powered on (to reduce power consump-
> tion), but will get powered on only in Linux  when  the  driver  gets
> loaded (i. e. on demand only, not always)?

I never had this situation, but I guess in this case I have a working
userspace and can use ifconfig to set the MAC address.

Sascha
David Miller March 11, 2009, 1:23 p.m. UTC | #8
From: Wolfgang Denk <wd@denx.de>
Date: Wed, 11 Mar 2009 10:09:38 +0100

> How do you then handle situations where this is impossible? Say, when
> the firmware cannot write to those registers for example because  the
> ethernet  controller is not even powered on (to reduce power consump-
> tion), but will get powered on only in Linux  when  the  driver  gets
> loaded (i. e. on demand only, not always)?

That's what NVRAM, CMOS, EEPROM's and other writable long-term
storage areas are for.

To be quite honest with you, any ethernet device that doesn't
have an EEPROM where the chip instance's ethernet address is
stored is completely broken.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dan Williams March 11, 2009, 2 p.m. UTC | #9
On Wed, 2009-03-11 at 06:23 -0700, David Miller wrote:
> From: Wolfgang Denk <wd@denx.de>
> Date: Wed, 11 Mar 2009 10:09:38 +0100
> 
> > How do you then handle situations where this is impossible? Say, when
> > the firmware cannot write to those registers for example because  the
> > ethernet  controller is not even powered on (to reduce power consump-
> > tion), but will get powered on only in Linux  when  the  driver  gets
> > loaded (i. e. on demand only, not always)?
> 
> That's what NVRAM, CMOS, EEPROM's and other writable long-term
> storage areas are for.
> 
> To be quite honest with you, any ethernet device that doesn't
> have an EEPROM where the chip instance's ethernet address is
> stored is completely broken.

Not having persistent MAC storage makes it quite hard from userspace to
tie specific network configuration to a specific device, because
(rightly so) kernel network interface names are *not* stable.  And since
most manufacturers don't bother to put serial numbers into things like
the USB descriptors, there is now way to uniquely identify if you plug
two in.  LOSE.

Save a kitten.  Add an EEPROM.

Dan


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Robert Schwebel March 11, 2009, 6:23 p.m. UTC | #10
On Wed, Mar 11, 2009 at 06:23:36AM -0700, David Miller wrote:
> From: Wolfgang Denk <wd@denx.de>
> Date: Wed, 11 Mar 2009 10:09:38 +0100
> 
> > How do you then handle situations where this is impossible? Say, when
> > the firmware cannot write to those registers for example because  the
> > ethernet  controller is not even powered on (to reduce power consump-
> > tion), but will get powered on only in Linux  when  the  driver  gets
> > loaded (i. e. on demand only, not always)?
> 
> That's what NVRAM, CMOS, EEPROM's and other writable long-term
> storage areas are for.
> 
> To be quite honest with you, any ethernet device that doesn't
> have an EEPROM where the chip instance's ethernet address is
> stored is completely broken.

However, it's quite common in embedded systems where eeprom chips cost
money and high quantity projects are cost optimized. So we cannot
neglect reality here. I know almost no ARM board that has a separate
eeprom for the network chip, and especially SoC-integrated MAC units
don't even have hardware interfaces for that.

rsc
Riku Voipio March 11, 2009, 7:15 p.m. UTC | #11
On Wed, Mar 11, 2009 at 06:23:36AM -0700, David Miller wrote:
> That's what NVRAM, CMOS, EEPROM's and other writable long-term
> storage areas are for.

> To be quite honest with you, any ethernet device that doesn't
> have an EEPROM where the chip instance's ethernet address is
> stored is completely broken.

If that is the case, pretty much every SOHO NAS device (running
linux + samba) being sold in your nearest IT shop is completly
broken.

In such machines, typically the mac address is stored in bootloader's
configuration area in NOR/NAND flash.
Christer Weinigel March 11, 2009, 8:56 p.m. UTC | #12
David Miller wrote:

> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Wed, 11 Mar 2009 09:44:30 +0100

 > > [some code to pass the MAC address as module parameters]

> Please remove this code.  If we let you do it, we have to let everyone
> else do it too, and that's something we don't want to do.
> 
> There are other ways you can handle this, for example have your board
> firmware properly program the MAC address into the card at power-on,
> and then have the driver here look in the MAC address registers to see
> if a valid ethernet address has been left there.


It's still a pain to have to do this.  Many embedded systems that I have 
seen have a bootloader which I can't modify to do that, but the 
bootloader allows me to save the kernel command line into some kind of 
volatile storage.  Så being able to set the MAC address with a:

     setenv cmdline foo.hwaddr=00:de:ad:be:ef:ed

is very nice because it allows me to use a NFS root without having to 
jump through hoops with initrds an such.

Actually, I wish we had a generic way of doing that, so that could set 
the mac address of any ethernet interface from the kernel command in a 
nice and supported way.

   /Christer


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux March 11, 2009, 9:33 p.m. UTC | #13
On Wed, Mar 11, 2009 at 09:56:06PM +0100, Christer Weinigel wrote:
> Actually, I wish we had a generic way of doing that, so that could set 
> the mac address of any ethernet interface from the kernel command in a 
> nice and supported way.

You're not the first to suggest that; that's precisely what I've
suggested in the past (though I probably couldn't find the postings if
I tried now.)  I've seen it all, from people trying to invent ATAGs to
pass ethernet addresses to the kernel, driver specific command lines,
and hard coded ethernet addresses in drivers.

I'm sure David would give full and proper consideration to a clean patch
adding such support in a generic way (even if the resulting answer is
still a 'no'.)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger March 12, 2009, 12:13 a.m. UTC | #14
On Wed, 11 Mar 2009 21:56:06 +0100
Christer Weinigel <christer@weinigel.se> wrote:

> David Miller wrote:
> 
> > From: Sascha Hauer <s.hauer@pengutronix.de>
> > Date: Wed, 11 Mar 2009 09:44:30 +0100
> 
>  > > [some code to pass the MAC address as module parameters]
> 
> > Please remove this code.  If we let you do it, we have to let everyone
> > else do it too, and that's something we don't want to do.
> > 
> > There are other ways you can handle this, for example have your board
> > firmware properly program the MAC address into the card at power-on,
> > and then have the driver here look in the MAC address registers to see
> > if a valid ethernet address has been left there.
> 
> 
> It's still a pain to have to do this.  Many embedded systems that I have 
> seen have a bootloader which I can't modify to do that, but the 
> bootloader allows me to save the kernel command line into some kind of 
> volatile storage.  Så being able to set the MAC address with a:
> 
>      setenv cmdline foo.hwaddr=00:de:ad:be:ef:ed
> 
> is very nice because it allows me to use a NFS root without having to 
> jump through hoops with initrds an such.
> 
> Actually, I wish we had a generic way of doing that, so that could set 
> the mac address of any ethernet interface from the kernel command in a 
> nice and supported way.
> 
>    /Christer

The problem is that usually users end up with all devices with the
same address, unless there is some other procedure to hand out addresses
during configuration. That is why the random_ether_addr is safer.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller March 12, 2009, 12:44 a.m. UTC | #15
From: Riku Voipio <riku.voipio@iki.fi>
Date: Wed, 11 Mar 2009 21:15:30 +0200

> In such machines, typically the mac address is stored in bootloader's
> configuration area in NOR/NAND flash.

That's a perfectly fine solution as well.

Anything that specifies a unique MAC address somewhere on
the board is OK.

It's this "generate a random MAC address every bootup" that
I am totally against.  A situation where there is no permanent
MAC address stored anywhere.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 10:41 a.m. UTC | #16
Stephen Hemminger wrote:
> On Wed, 11 Mar 2009 21:56:06 +0100
> Christer Weinigel <christer@weinigel.se> wrote:
>> It's still a pain to have to do this.  Many embedded systems that I have 
>> seen have a bootloader which I can't modify to do that, but the 
>> bootloader allows me to save the kernel command line into some kind of 
>> volatile storage.  Så being able to set the MAC address with a:
>>
>>      setenv cmdline foo.hwaddr=00:de:ad:be:ef:ed
>>
>> is very nice because it allows me to use a NFS root without having to 
>> jump through hoops with initrds an such.
>>
>> Actually, I wish we had a generic way of doing that, so that could set 
>> the mac address of any ethernet interface from the kernel command in a 
>> nice and supported way.
> 
> The problem is that usually users end up with all devices with the
> same address, unless there is some other procedure to hand out addresses
> during configuration. That is why the random_ether_addr is safer.

Random mac addresses, yuk! :-)  I'd much rather have something that I 
can make "do the right thing" than something I can't.  And as I said, 
what I've encountered many times is a reference board from some 
manufacturer where the following conditions are present:

1. The bootloader can pass a command line to the kernel and it is saved 
in non-volatile storage that can be changed from the bootloader

2. I can not modify the bootloader

3. I can modify the Linux kernel

4. The manufacturer has hardcoded a MAC address in the ethernet driver

5. I want to use NFS root to make it easy to develop on the platform

6. We get a second board so the hardcoded MAC addresses collide

In this situation I usually hack a hwaddr module param into the ethernet 
driver, so that I can actually make the devices have different, but 
stable, MAC addresses.  The alternatives are to hardcode the MAC address 
into the kernel and run different kernels on different boards, or to 
create an initrd with a tools that parses the kernel command line to 
extract the MAC address and then do ifconfig eth0 hwaddr $HWADDR, and 
then add a DCHP client which gets the NFS root from the DCHP response 
and finally mounts the NFS root and switches too it.  But I'm lazy so as 
I said usually just hack the driver.

    /Christer
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller March 12, 2009, 12:55 p.m. UTC | #17
From: Christer Weinigel <christer@weinigel.se>
Date: Thu, 12 Mar 2009 11:41:24 +0100

> 1. The bootloader can pass a command line to the kernel and it is saved in non-volatile storage that can be changed from the bootloader
> 
> 2. I can not modify the bootloader
> 
> 3. I can modify the Linux kernel
> 
> 4. The manufacturer has hardcoded a MAC address in the ethernet driver
> 
> 5. I want to use NFS root to make it easy to develop on the platform
> 
> 6. We get a second board so the hardcoded MAC addresses collide

This is getting rediculious.

If you can modify the kernel, you can have the kernel look in the
non-volatile storage for the MAC address and export that information
to the ethernet driver.

Or, you can parse the command line in your platform specific code
and program the MAC address into the chip.

In fact there are many reasonable ways to solve the problem in
your scenerio, and none of them require device driver command
line option handler.

None.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Cashwell March 12, 2009, 1:41 p.m. UTC | #18
On Mar 11, 2009, at 12:18 AM, Stephen Hemminger wrote:

> On Wed, 11 Mar 2009 05:29:09 +0300
> Ilya Yanok <yanok@emcraft.com> wrote:
>
>> +static char ethaddr[18];
>> +
>> +module_param_string(ethaddr, ethaddr, sizeof(ethaddr), 0);
>> +
>> +static void get_mac_addr(struct net_device *nd, unsigned char *pmac)
>> +{
>> +	int i;
>> +	char *p = ethaddr;
>> +
>> +	ethaddr[17] = 0;
>> +	for (i = 0; i < ETH_ALEN; i++, p++) {
>> +		pmac[i] = simple_strtoul(p, &p, 16);
>> +		if (*p != ':')
>> +			break;
>> +	}
>> +	if (i != ETH_ALEN - 1) {
>> +		pr_err("Wrong MAC address format!\n");
>> +		memset(pmac, 0, ETH_ALEN);
>> +	}
>> +}
>> +
>
> Do you still need this? Only works with one board, configuration via
> module parameters is discouraged.  Same effect can be done by setting
> mac address with regular tools.

I'm confused by this. If I'm NFS-booting the board then how do I get  
to those userland tools if I don't have a valid MAC address in place  
to do the root mount?

-Mike

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller March 12, 2009, 2:05 p.m. UTC | #19
From: Michael Cashwell <mboards@prograde.net>
Date: Thu, 12 Mar 2009 09:41:38 -0400

> I'm confused by this. If I'm NFS-booting the board then how do I get
> to those userland tools if I don't have a valid MAC address in place
> to do the root mount?

Initial ramdisk.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 2:21 p.m. UTC | #20
David Miller wrote:
> From: Christer Weinigel <christer@weinigel.se>
> Date: Thu, 12 Mar 2009 11:41:24 +0100
> 
>> 1. The bootloader can pass a command line to the kernel and it is saved in non-volatile storage that can be changed from the bootloader
>>
>> 2. I can not modify the bootloader
>>
>> 3. I can modify the Linux kernel
>>
>> 4. The manufacturer has hardcoded a MAC address in the ethernet driver
>>
>> 5. I want to use NFS root to make it easy to develop on the platform
>>
>> 6. We get a second board so the hardcoded MAC addresses collide
> 
> This is getting rediculious.

Yes, ridiculous in the complexity of the workarounds for not having a 
generic way to set the mac address from the command line.  :-/

> If you can modify the kernel, you can have the kernel look in the
> non-volatile storage for the MAC address and export that information
> to the ethernet driver.

Which means that the non-volatile storage must be available through a 
Linux driver before the MAC address is set.  AFAIK there is no guarantee 
that the MTD layer will be ready to use by that time.  And that is 
assuming that there actually is a MTD driver available, usually when I 
work on a Linux port for a reference board, the first thing I do is to 
get a NFS root up and running, then I can put a have a complete Debian 
system with all nice debugging tools available.  When I have that up and 
running I start porting the other drivers, such as the MTD driver.

Also, I don't really want to spend time on reverse engineering some 
random non-volatile storage format, that's quite fragile.

> Or, you can parse the command line in your platform specific code
> and program the MAC address into the chip.

Which is actually what I'm doing, except that it's easier to hack that 
into the ethernet driver each time it is needed.

> In fact there are many reasonable ways to solve the problem in
> your scenerio, and none of them require device driver command
> line option handler.

Yes, that why I'd want that in a generic piece of code instead of having 
to hack it into each device driver.  Would a generic command line 
option, something like "ethaddrs=eth0=00:de:ad:be:ef:01" which assigns 
addresses to network cards be acceptable?

Next time I have to port something to an embedded platform with this 
kind of problem, I might try to do something more generic instead of the 
simple hack I usually do now.

   /Christer

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 12, 2009, 2:26 p.m. UTC | #21
On Thu, Mar 12, 2009 at 07:05:54AM -0700, David Miller wrote:
> From: Michael Cashwell <mboards@prograde.net>
> Date: Thu, 12 Mar 2009 09:41:38 -0400
> 
> > I'm confused by this. If I'm NFS-booting the board then how do I get
> > to those userland tools if I don't have a valid MAC address in place
> > to do the root mount?
> 
> Initial ramdisk.

+1, the simple fact of the matter is that, when building networkable devices,
the design requirements must include:

1) The ability to store unit-unique data, like MAC addresses, in persistent
storage, in a manner that can be read at arbitrary times from the OS.

2) The abiltiy to access that data from the OS under all relevant operating
conditions.

You have (1) covered, in that the bootloader passes the MAC on the command line
to the kernel which can then be read via /proc/cmdline easily.

If you can't accomplish (2) with NFS root built into the kernel, then quite
simply using built in NFS root isn't an option, and you need to burn some extra
storage to add an initramfs.  Its easy to do, and small.  Cost minimization is
important, but you can't remove what you need, and you need an initramfs.  You
can build one in just a few hundred kb, if you use busybox with a minimal
toolset (you'd probably need the sed, ifconfig, and ash applets).  I would make
a bet that even if you did need to spring for a bit of extra ram, the
incremental cost to that is less than the savings of using linux over something
that would required a per seat license, like VxWorks.

Neil



> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 12, 2009, 2:34 p.m. UTC | #22
On Thu, Mar 12, 2009 at 03:21:47PM +0100, Christer Weinigel wrote:
> David Miller wrote:
>> From: Christer Weinigel <christer@weinigel.se>
>> Date: Thu, 12 Mar 2009 11:41:24 +0100
>>
>>> 1. The bootloader can pass a command line to the kernel and it is saved in non-volatile storage that can be changed from the bootloader
>>>
>>> 2. I can not modify the bootloader
>>>
>>> 3. I can modify the Linux kernel
>>>
>>> 4. The manufacturer has hardcoded a MAC address in the ethernet driver
>>>
>>> 5. I want to use NFS root to make it easy to develop on the platform
>>>
>>> 6. We get a second board so the hardcoded MAC addresses collide
>>
>> This is getting rediculious.
>
> Yes, ridiculous in the complexity of the workarounds for not having a  
> generic way to set the mac address from the command line.  :-/
>
>> If you can modify the kernel, you can have the kernel look in the
>> non-volatile storage for the MAC address and export that information
>> to the ethernet driver.
>
> Which means that the non-volatile storage must be available through a  
> Linux driver before the MAC address is set.  AFAIK there is no guarantee  
> that the MTD layer will be ready to use by that time.  And that is  
> assuming that there actually is a MTD driver available, usually when I  
> work on a Linux port for a reference board, the first thing I do is to  
> get a NFS root up and running, then I can put a have a complete Debian  
> system with all nice debugging tools available.  When I have that up and  
> running I start porting the other drivers, such as the MTD driver.
>
> Also, I don't really want to spend time on reverse engineering some  
> random non-volatile storage format, that's quite fragile.
>
>> Or, you can parse the command line in your platform specific code
>> and program the MAC address into the chip.
>
> Which is actually what I'm doing, except that it's easier to hack that  
> into the ethernet driver each time it is needed.
>
>> In fact there are many reasonable ways to solve the problem in
>> your scenerio, and none of them require device driver command
>> line option handler.
>
> Yes, that why I'd want that in a generic piece of code instead of having  
> to hack it into each device driver.  Would a generic command line  
> option, something like "ethaddrs=eth0=00:de:ad:be:ef:01" which assigns  
> addresses to network cards be acceptable?

Unfortunately it isn't this simple because network device names are not
stable (i.e. eth0 can become eth1 when you plug another network card)
Someone has already mentioned this and I think this is the real problem
why we still don't have such a mechanism.

Sascha
David Miller March 12, 2009, 3:01 p.m. UTC | #23
From: Christer Weinigel <christer@weinigel.se>
Date: Thu, 12 Mar 2009 15:21:47 +0100

> Yes, that why I'd want that in a generic piece of code instead of
> having to hack it into each device driver.  Would a generic command
> line option, something like "ethaddrs=eth0=00:de:ad:be:ef:01" which
> assigns addresses to network cards be acceptable?

Yep, and you can parse that and execute the appropriate
ifconfig command from userspace in your initial ramdisk.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 12, 2009, 3:12 p.m. UTC | #24
On Thu, Mar 12, 2009 at 03:21:47PM +0100, Christer Weinigel wrote:
> David Miller wrote:
>> From: Christer Weinigel <christer@weinigel.se>
>> Date: Thu, 12 Mar 2009 11:41:24 +0100
>>
>>> 1. The bootloader can pass a command line to the kernel and it is saved in non-volatile storage that can be changed from the bootloader
>>>
>>> 2. I can not modify the bootloader
>>>
>>> 3. I can modify the Linux kernel
>>>
>>> 4. The manufacturer has hardcoded a MAC address in the ethernet driver
>>>
>>> 5. I want to use NFS root to make it easy to develop on the platform
>>>
>>> 6. We get a second board so the hardcoded MAC addresses collide
>>
>> This is getting rediculious.
>
> Yes, ridiculous in the complexity of the workarounds for not having a  
> generic way to set the mac address from the command line.  :-/
>
You do have a generic way, via the initramfs.  Works great, every time.

>> If you can modify the kernel, you can have the kernel look in the
>> non-volatile storage for the MAC address and export that information
>> to the ethernet driver.
>
> Which means that the non-volatile storage must be available through a  
> Linux driver before the MAC address is set.  AFAIK there is no guarantee  
> that the MTD layer will be ready to use by that time.  And that is  
> assuming that there actually is a MTD driver available, usually when I  
> work on a Linux port for a reference board, the first thing I do is to  
> get a NFS root up and running, then I can put a have a complete Debian  
> system with all nice debugging tools available.  When I have that up and  
> running I start porting the other drivers, such as the MTD driver.
>
If you have an MTD driver ported, then it is available if you use an initramfs.
If you don't have an initramfs, you can still use your kernel command line
mechanism to set your network interface MAC address.

> Also, I don't really want to spend time on reverse engineering some  
> random non-volatile storage format, that's quite fragile.
>
Then dont, if you are only guaranteed one interface, use the kernel command
line to specify the mac and set it with ifconfig from an initramfs.

>> Or, you can parse the command line in your platform specific code
>> and program the MAC address into the chip.
>
> Which is actually what I'm doing, except that it's easier to hack that  
> into the ethernet driver each time it is needed.
>
What exactly is so difficult about cpio-ing up an initramfs to do this work with
sed and ifconfig? You make it sound like its an impossible barrier. Its really
quite simple

>> In fact there are many reasonable ways to solve the problem in
>> your scenerio, and none of them require device driver command
>> line option handler.
>
> Yes, that why I'd want that in a generic piece of code instead of having  
> to hack it into each device driver.  Would a generic command line  
> option, something like "ethaddrs=eth0=00:de:ad:be:ef:01" which assigns  
> addresses to network cards be acceptable?
>
> Next time I have to port something to an embedded platform with this  
> kind of problem, I might try to do something more generic instead of the  
> simple hack I usually do now.
>
You've convinced yourself that theres no other way to do this.  What exactly is
your opposition to an initramfs? I just built busybox with ifconfig, sed and ash
in a static binary.  The whole thing comes out at 800kb, and is compressed to
400kb.  You could probably save an extra hundred kb or so if you went with msh
instead or something.  Are you quite sure that your NV storage for your kernel
doesn't have an extra 400kb to spare for an initramfs?  I assume that it must,
since eventually you'll need an initramfs anyway to run the production variant
of the system your building (I imagine they won't all ship with an NFS server in
tow :) ).

Neil

>   /Christer
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 4:25 p.m. UTC | #25
Neil Horman wrote:
> What exactly is so difficult about cpio-ing up an initramfs to do this work with
> sed and ifconfig? You make it sound like its an impossible barrier. Its really
> quite simple

In theory, nothing.  In practice, well, where do I find an example 
initrd that I can build on that has a DHCP client that hands over the 
NFS root information from the DHCP response to a tool that mounts the 
NFS root file system?  So far I haven't seen anything like that and the 
infrastructure to build initrds (such as klibc) is still hard to find 
and use.  Every time I've tried to build an initrd that can do DCHP+NFS 
root it has turned out to be too much trouble and I've had to drop it as 
deadlines come closer.

> You've convinced yourself that theres no other way to do this.  What exactly is
> your opposition to an initramfs? I just built busybox with ifconfig, sed and ash
> in a static binary.  The whole thing comes out at 800kb, and is compressed to
> 400kb.  You could probably save an extra hundred kb or so if you went with msh
> instead or something.  Are you quite sure that your NV storage for your kernel
> doesn't have an extra 400kb to spare for an initramfs?  I assume that it must,
> since eventually you'll need an initramfs anyway to run the production variant
> of the system your building (I imagine they won't all ship with an NFS server in
> tow :) ).

No, I'm quite aware that there are other ways of doing this, it's just 
that all the other ways are _much_ more work for me.  The harsh reality 
is that if I can get a board working using a hack in the driver in half 
an hour, I'll do that rather than fussing around with an initrd. 
Patching the driver is no big deal, it's quick and fairly painless for 
me, it would just be nice if the kernel had a generic way of doing this 
so that I don't have to.  The kernel requires no userspace, no C library 
and all I have to be able to do is to compile the kernel itself.

It's exactly the same reason why people are still using the in kernel 
DHCP client and NFS root code instead of writing and initrd for it, it's 
  much easier to use and why spend time on something that is much more 
complicated for no gain since the in kernel code is sufficient?

I much prefer to spend time on working on the device drivers that I'm 
paid to work on (and spend more time to try try to get those patches 
into the kernel) than to spend time on rewriting everything for an 
initrd.  And the final product usually won't even have ethernet, so from 
a product perspective it would be wasted time.  Anyway, getting the 
system to boot from NFS is usually the absolutely first thing I have to 
do.  Making a product out of it comes months later, and only if we're 
able to do a proof-of-concept demo on a couple of reference platforms at 
an early stage.

Regarding the flash space, if I have a 1.6MByte kernel image (the size 
of a  compressed Linux 2.6.24 kernel for a Samsung S3C24A0 platform I'm 
working on), those 400kBytes can make the difference between things 
fitting into the 2MByte flash partition the bootloader has reserved for 
the kernel or not.

So it mostly boils down to me being lazy and not wanting to spend a lot 
of time on building new infrastructure.  I'd like something which is a 
bit better than what we have now and can spend some time on it, but I 
don't want to spend a lot of time on it since patching the driver works 
just fine for my purposes.  Perfect is the enemy of good.

   /Christer

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller March 12, 2009, 5:43 p.m. UTC | #26
From: Christer Weinigel <christer@weinigel.se>
Date: Thu, 12 Mar 2009 17:25:27 +0100

> In theory, nothing.  In practice, well, where do I find an example
> initrd that I can build on that has a DHCP client that hands over
> the NFS root information from the DHCP response to a tool that
> mounts the NFS root file system?  So far I haven't seen anything
> like that and the infrastructure to build initrds (such as klibc) is
> still hard to find and use.  Every time I've tried to build an
> initrd that can do DCHP+NFS root it has turned out to be too much
> trouble and I've had to drop it as deadlines come closer.

Just about every single distribution has to build a initrd
that has to be able to setup a network, and have the necessary
infrastructure to access things over NFS in order to implement
their installer.

You can start with the debian installer, that's probably the
easiest to hack on and extend.

Or you can just continue to list excuses, that might be easier.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 12, 2009, 5:49 p.m. UTC | #27
On Thu, Mar 12, 2009 at 05:25:27PM +0100, Christer Weinigel wrote:
> Neil Horman wrote:
>> What exactly is so difficult about cpio-ing up an initramfs to do this work with
>> sed and ifconfig? You make it sound like its an impossible barrier. Its really
>> quite simple
>
> In theory, nothing.  In practice, well, where do I find an example  
> initrd that I can build on that has a DHCP client that hands over the  
Well, for an example of an initrd, you can unpack just about any distribution
initramfs that you like.  If you want to use busybox, I'd personally recommend
either Debian (I think they use busybox normally), or you're welcome to get a
copy of the fedora kexec-tools package.  I put a script called mkdumprd that
generates initramfs files in there based on busybox for the purpose of capturing
core dumps.  As for the dhcp part of it, that depends on the dhcp client you
decide to use.  I use the udhcpc applet in busybox, the man page for which
describes how to extract the various options out of the dhcpoffer frame.  Its
pretty straightforward.  Other clients do it differently, but that one is both
small and easy to use.

> NFS root information from the DHCP response to a tool that mounts the  
> NFS root file system?  So far I haven't seen anything like that and the  
> infrastructure to build initrds (such as klibc) is still hard to find  
You don't need klibc, you can use regular glibc, and even build statically if
you like.  You'll have to use dig or host to do name lookups, but thats also
pretty easy to do.  This really is easier than you think it is :)

> and use.  Every time I've tried to build an initrd that can do DCHP+NFS  
> root it has turned out to be too much trouble and I've had to drop it as  
> deadlines come closer.
>

Seriously, most of what you need to do is embodied in my mkdumprd script.  Look
at that (or even just start with it an modify it), and you'll be 90% of the way
there.  After you get it working, you can strip out all the stuff you don't need
(which from mkdumprd will likely be substantial).

>> You've convinced yourself that theres no other way to do this.  What exactly is
>> your opposition to an initramfs? I just built busybox with ifconfig, sed and ash
>> in a static binary.  The whole thing comes out at 800kb, and is compressed to
>> 400kb.  You could probably save an extra hundred kb or so if you went with msh
>> instead or something.  Are you quite sure that your NV storage for your kernel
>> doesn't have an extra 400kb to spare for an initramfs?  I assume that it must,
>> since eventually you'll need an initramfs anyway to run the production variant
>> of the system your building (I imagine they won't all ship with an NFS server in
>> tow :) ).
>
> No, I'm quite aware that there are other ways of doing this, it's just  
> that all the other ways are _much_ more work for me.  The harsh reality  
Wheres all the extra work?  You've given a few examples here, and they're all
things that are easily overcome. 

> is that if I can get a board working using a hack in the driver in half  
> an hour, I'll do that rather than fussing around with an initrd.  
> Patching the driver is no big deal, it's quick and fairly painless for  
> me, it would just be nice if the kernel had a generic way of doing this  
> so that I don't have to.  The kernel requires no userspace, no C library  
> and all I have to be able to do is to compile the kernel itself.
>
Well, you've said it there yourself.  What you're proposing is a hack in the
driver.  This really isn't the place for hacks.  This is the place for doing
things in as consistent and maintainable a way as possible.  That way is using
an initramfs, which you will need at some point in time anyway, if you want any
userspace functionality.  So why not create one?  The small investment of your
time figuring out how to do it will pay off over and over again when you can
easily assign unit-specific data using well known and well documented tools to
do so.

> It's exactly the same reason why people are still using the in kernel  
> DHCP client and NFS root code instead of writing and initrd for it, it's  
>  much easier to use and why spend time on something that is much more  
> complicated for no gain since the in kernel code is sufficient?
>
You're last comment is in direct contradiction to what you are saying here.  As
you've discovered, the in kernel dhcp and nfs root client are useless unless
your ethernet interface has a mac on it, and if you don't have a mac stored in
eeprom that the driver can access, you can't assign one without introducing a
big hack, which no one here is going to support.  The solution is to do things
the right way.  Save some space in the kernel by turning the in-kernel dhcp
client and nfs root code off, and use that space to store an initrd that can do
everything you need to and more.

> I much prefer to spend time on working on the device drivers that I'm  
> paid to work on (and spend more time to try try to get those patches  
> into the kernel) than to spend time on rewriting everything for an  
> initrd.  And the final product usually won't even have ethernet, so from  
> a product perspective it would be wasted time.  Anyway, getting the  
> system to boot from NFS is usually the absolutely first thing I have to  
> do.  Making a product out of it comes months later, and only if we're  
> able to do a proof-of-concept demo on a couple of reference platforms at  
> an early stage.
>

Everyone has to invest some time on a tangent to their goal in order to reach
their goal.  This is simply a cost of doing business.  No one is going to accept
a hack to a driver just so that you don't have to learn how to do something a
bit differently.  And no amount of complaining about how difficult it is is
going to change that.  Its simply not true.  Theres a big document in the kernel
tree explaining how to create and use initramfs/initrd files.  I'll be happy to
help you figure out how to do it if you have questions.

> Regarding the flash space, if I have a 1.6MByte kernel image (the size  
> of a  compressed Linux 2.6.24 kernel for a Samsung S3C24A0 platform I'm  
> working on), those 400kBytes can make the difference between things  
> fitting into the 2MByte flash partition the bootloader has reserved for  
> the kernel or not.
>
It can, is that the the actual case?  How much space do you have if you turn off
the dhcp client and nfs root code in the kernel? Try hard, I bet you can make it
fit without much effort.

> So it mostly boils down to me being lazy and not wanting to spend a lot  
> of time on building new infrastructure.  I'd like something which is a  
> bit better than what we have now and can spend some time on it, but I  
> don't want to spend a lot of time on it since patching the driver works  
> just fine for my purposes.  Perfect is the enemy of good.
>
Well, that is your perogative.  I had to make those sorts of choices when I did
embedded too.  I tried to get upstream what was acceptible, and carried the rest
myself on occasion. But I promise you, this really isn't hard.  Spend some time,
and you'll find and onboard initramfs environment can make your life worlds
easier long term.
Neil

>   /Christer
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 5:52 p.m. UTC | #28
David Miller wrote:
> Just about every single distribution has to build a initrd
> that has to be able to setup a network, and have the necessary
> infrastructure to access things over NFS in order to implement
> their installer.
> 
> You can start with the debian installer, that's probably the
> easiest to hack on and extend.
> 
> Or you can just continue to list excuses, that might be easier.

Or I can keep patching the drivers, that's even easier.  No it's not 
something I expect to see in the official kernel, but who cares, I 
always have loads of debug patches that won't get into the official 
kernel either.  Keep the status quo.

   /Christer
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jamie Lokier March 12, 2009, 6:02 p.m. UTC | #29
David Miller wrote:
> > I'm confused by this. If I'm NFS-booting the board then how do I get
> > to those userland tools if I don't have a valid MAC address in place
> > to do the root mount?
> 
> Initial ramdisk.

Aren't you basically implying that the in-kernel DHCP client and NFS
mounting should be removed from the kernel too?

I'd agree with that; it's the trend.  But it seems pretty harsh to say
"you can do DHCP+NFS now, but if you want to set the MAC address too,
then you have to reimplement DHCP+NFS a completely different way from
scratch first".

-- Jamie
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jamie Lokier March 12, 2009, 6:06 p.m. UTC | #30
Christer Weinigel wrote:
> David Miller wrote:
> > You can start with the debian installer, that's probably the
> > easiest to hack on and extend.
> > 
> > Or you can just continue to list excuses, that might be easier.
> 
> Or I can keep patching the drivers, that's even easier.  No it's not 
> something I expect to see in the official kernel, but who cares, I 
> always have loads of debug patches that won't get into the official 
> kernel either.  Keep the status quo.

Yes.  Patching your own initrd or your own modified Debian initrd is
_also_ not in the official trees, so I can't see any reason why
anybody would follow Dave's suggestion.  Much more work, different
private tree, same behaviour, probably more bloated, probably Debian's
initrd doesn't work on nommu anyway.

However there was some attempt to get a reference initrd build into
the kernel.  Did that go anywhere?  It would actually be good to use
that if it exists.

-- Jamie
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 6:25 p.m. UTC | #31
Neil Horman wrote:
> You don't need klibc, you can use regular glibc, and even build statically if
> you like.  You'll have to use dig or host to do name lookups, but thats also
> pretty easy to do.  This really is easier than you think it is :)

Size, size, size.  The killer in the embedded world which rules out 
glibc.  And have you tried to link glibc statically with something that 
uses gethostbyname lately?  It is no longer possible since the 
introduction of all the introduction of the dynamic name lookup crap 
(ok, it's not really crap, I just feel like it's crap every time I try 
to link a networking application statically).  But that's a bit off 
topic since I don't need name lookups just to mount a NFS file system. 
uclibc also seems to have issues with networking and statically linked 
binaries, but I just haven't had time to figure out why yet.

> Well, you've said it there yourself.  What you're proposing is a hack in the
> driver.  This really isn't the place for hacks.  This is the place for doing
> things in as consistent and maintainable a way as possible.  

In my opion, having a "hwaddrs=eth0=00:de:ad:be:ef:01" would be 
consistent and maintainable.  But opinions differ.

> You're last comment is in direct contradiction to what you are saying here.  As
> you've discovered, the in kernel dhcp and nfs root client are useless unless
> your ethernet interface has a mac on it, and if you don't have a mac stored in
> eeprom that the driver can access, you can't assign one without introducing a
> big hack, which no one here is going to support.  

Once again, in your opinion it is a hack, I don't consider it more a 
hack than assigning the IP address on the command line.  And I wouldn't 
call the in kernel stuff useless.

> Everyone has to invest some time on a tangent to their goal in order to reach
> their goal.  This is simply a cost of doing business.  No one is going to accept
> a hack to a driver just so that you don't have to learn how to do something a
> bit differently.  And no amount of complaining about how difficult it is is
> going to change that.  Its simply not true.  Theres a big document in the kernel
> tree explaining how to create and use initramfs/initrd files.  I'll be happy to
> help you figure out how to do it if you have questions.

I know how to build initrds and initramfs.  I've spent the hard time 
digging through the code in init/do_mounts.c trying to figure out what 
it is supposed to do.  I have used them for multiple embedded systems, 
zoo.weinigel.se/trac/public, both the Acer and the DNS323 use them, but 
those are hobby projects where I haven't had deadlines to meet.   It is 
a luxury I usually don't have when my boss drops an embedded system on 
my desk and tells me "we have to have our drivers working on this board 
for a demo next week".

>> Regarding the flash space, if I have a 1.6MByte kernel image (the size  
>> of a  compressed Linux 2.6.24 kernel for a Samsung S3C24A0 platform I'm  
>> working on), those 400kBytes can make the difference between things  
>> fitting into the 2MByte flash partition the bootloader has reserved for  
>> the kernel or not.
>>
> It can, is that the the actual case?  How much space do you have if you turn off
> the dhcp client and nfs root code in the kernel? Try hard, I bet you can make it
> fit without much effort.

Disabling IP_PNP and NFS_ROOT saves less than 8kBytes on an ARM9 (yeah, 
I just checked).  An initrd uses a lot more than that.  Maybe with 
klibc, but investing klibc is something that I've had on my TODO list 
since hpa first talked about it years ago.  I've sort of been putting it 
off until klibc would get into the kernel, but...

>> So it mostly boils down to me being lazy and not wanting to spend a lot  
>> of time on building new infrastructure.  I'd like something which is a  
>> bit better than what we have now and can spend some time on it, but I  
>> don't want to spend a lot of time on it since patching the driver works  
>> just fine for my purposes.  Perfect is the enemy of good.
>>
> Well, that is your perogative.  I had to make those sorts of choices when I did
> embedded too.  I tried to get upstream what was acceptible, and carried the rest
> myself on occasion. But I promise you, this really isn't hard.  Spend some time,
> and you'll find and onboard initramfs environment can make your life worlds
> easier long term.

Yes, and the next time I would have to fix this on an embedded board, I 
could probably have spent the time on figure out how to do something 
slightly more generic, but since it won't have a chance of getting into 
the kernel, I probably won't.

Anyway, I've spent more time on discussing this now than it would have 
taken me to hack the device drivers on half a dozen platforms, so I 
think I'll give up.  Maybe I'll take a look at some initrd+klibc+dhcp 
stuff when I have some free time next Christmas (that's when I usually 
get to play around with my hobby projects), maybe not. :-)

   /Christer

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dan Williams March 12, 2009, 6:39 p.m. UTC | #32
On Thu, 2009-03-12 at 18:06 +0000, Jamie Lokier wrote:
> Christer Weinigel wrote:
> > David Miller wrote:
> > > You can start with the debian installer, that's probably the
> > > easiest to hack on and extend.
> > > 
> > > Or you can just continue to list excuses, that might be easier.
> > 
> > Or I can keep patching the drivers, that's even easier.  No it's not 
> > something I expect to see in the official kernel, but who cares, I 
> > always have loads of debug patches that won't get into the official 
> > kernel either.  Keep the status quo.
> 
> Yes.  Patching your own initrd or your own modified Debian initrd is
> _also_ not in the official trees, so I can't see any reason why
> anybody would follow Dave's suggestion.  Much more work, different
> private tree, same behaviour, probably more bloated, probably Debian's
> initrd doesn't work on nommu anyway.
> 
> However there was some attempt to get a reference initrd build into
> the kernel.  Did that go anywhere?  It would actually be good to use
> that if it exists.

dracut : http://lwn.net/Articles/317793/

Dan

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 6:48 p.m. UTC | #33
Jamie Lokier wrote:
> However there was some attempt to get a reference initrd build into
> the kernel.  Did that go anywhere?  It would actually be good to use
> that if it exists.

That would be a very worthwhile project actually.  Create a package that 
uses klibc, does BOOTP/DCHP/NFS and parses the the ip=foo,bar options 
the same way the kernel does so that we can finally get rid of the in 
kernel stuff.  That, the code that reads an initrd from a floppy disk 
(nobody can really be using that code anymore, can they?), and the md 
setup are probably the last obstacles to doing a nice little cleanup of 
the mount_root code in the kernel.

I just wish I had more time.

   /Christer


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 12, 2009, 7:04 p.m. UTC | #34
On Thu, Mar 12, 2009 at 07:48:39PM +0100, Christer Weinigel wrote:
> Jamie Lokier wrote:
>> However there was some attempt to get a reference initrd build into
>> the kernel.  Did that go anywhere?  It would actually be good to use
>> that if it exists.
>
> That would be a very worthwhile project actually.  Create a package that  
> uses klibc, does BOOTP/DCHP/NFS and parses the the ip=foo,bar options  
> the same way the kernel does so that we can finally get rid of the in  
> kernel stuff.

Great, but how does this help in setting the MAC address? This would
just move this exact discussion to the dracut or whatever mailing list,
but we would still be searching for a generic way to say
eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.

Sascha
Neil Horman March 12, 2009, 7:05 p.m. UTC | #35
On Thu, Mar 12, 2009 at 07:25:10PM +0100, Christer Weinigel wrote:
> Neil Horman wrote:
>> You don't need klibc, you can use regular glibc, and even build statically if
>> you like.  You'll have to use dig or host to do name lookups, but thats also
>> pretty easy to do.  This really is easier than you think it is :)
>
> Size, size, size.  The killer in the embedded world which rules out  
> glibc.  And have you tried to link glibc statically with something that  
> uses gethostbyname lately?  It is no longer possible since the  
> introduction of all the introduction of the dynamic name lookup crap  
> (ok, it's not really crap, I just feel like it's crap every time I try  
> to link a networking application statically).  But that's a bit off  
> topic since I don't need name lookups just to mount a NFS file system.  
> uclibc also seems to have issues with networking and statically linked  
> binaries, but I just haven't had time to figure out why yet.
>

You didn't read what I wrote very closely, I specifically said you have to dig
or host to do name lookups, specifically because of the issues with getXbyY.
When I said I built busybox in 800k (400k compressed), That was with glibc
statically linked.  End of story.  You're making up problems here, its not that
big a deal.  I've not looked at the figures lately, but how much space does the
dhcp client and nfs root code take up in the kernel these days?  I imagine that
what you save there by turning those off will be a good start in offsetting the
space you need for an initramfs.

>> Well, you've said it there yourself.  What you're proposing is a hack in the
>> driver.  This really isn't the place for hacks.  This is the place for doing
>> things in as consistent and maintainable a way as possible.  
>
> In my opion, having a "hwaddrs=eth0=00:de:ad:be:ef:01" would be  
> consistent and maintainable.  But opinions differ.
>
I never said you can't still use that command line option to implement this
solution, you just have to parse it in userspace.

>> You're last comment is in direct contradiction to what you are saying here.  As
>> you've discovered, the in kernel dhcp and nfs root client are useless unless
>> your ethernet interface has a mac on it, and if you don't have a mac stored in
>> eeprom that the driver can access, you can't assign one without introducing a
>> big hack, which no one here is going to support.  
>
> Once again, in your opinion it is a hack, I don't consider it more a  
> hack than assigning the IP address on the command line.  And I wouldn't  
> call the in kernel stuff useless.
>
You yourself called it a hack in your last note (and I agree).  And, as you're
finding out, the DHCP and NFS code in the kernel is in fact useless if you can't
assign a mac address to your ethernet interface, which in turn you cant do
unless you introduce some unacceptable code to the kernel.

>> Everyone has to invest some time on a tangent to their goal in order to reach
>> their goal.  This is simply a cost of doing business.  No one is going to accept
>> a hack to a driver just so that you don't have to learn how to do something a
>> bit differently.  And no amount of complaining about how difficult it is is
>> going to change that.  Its simply not true.  Theres a big document in the kernel
>> tree explaining how to create and use initramfs/initrd files.  I'll be happy to
>> help you figure out how to do it if you have questions.
>
> I know how to build initrds and initramfs.  I've spent the hard time  
> digging through the code in init/do_mounts.c trying to figure out what  
> it is supposed to do.  I have used them for multiple embedded systems,  
> zoo.weinigel.se/trac/public, both the Acer and the DNS323 use them, but  
> those are hobby projects where I haven't had deadlines to meet.   It is  
> a luxury I usually don't have when my boss drops an embedded system on  
> my desk and tells me "we have to have our drivers working on this board  
> for a demo next week".
>
So, If I read this right:
1) You have undertaken hobby projects for which you have investigated,
implemented and learned how to implement an initramfs, and feel comfortable
doing so.

2) You have a work project for which an initramfs would be helpful and based on
this thread, required  (assuming you don't want to carry extra driver patches on
your own)

3) Your knoweldge from (1) is insufficient to implement the required initramfs in (2)
in (assuming your example time frame) 1 week?

Seriously?

>>> Regarding the flash space, if I have a 1.6MByte kernel image (the 
>>> size  of a  compressed Linux 2.6.24 kernel for a Samsung S3C24A0 
>>> platform I'm  working on), those 400kBytes can make the difference 
>>> between things  fitting into the 2MByte flash partition the 
>>> bootloader has reserved for  the kernel or not.
>>>
>> It can, is that the the actual case?  How much space do you have if you turn off
>> the dhcp client and nfs root code in the kernel? Try hard, I bet you can make it
>> fit without much effort.
>
> Disabling IP_PNP and NFS_ROOT saves less than 8kBytes on an ARM9 (yeah,  
> I just checked).  An initrd uses a lot more than that.  Maybe with  
> klibc, but investing klibc is something that I've had on my TODO list  
> since hpa first talked about it years ago.  I've sort of been putting it  
> off until klibc would get into the kernel, but...
>
Ok, well, thats a start.  Have you considered making some non-essential
functions modular, and storing those functions on your NFS root?  That would
give you the additional space to store an initramfs, which you can use to mout
and pivot to your nfs root, which then gives you access to the additional
modules.  Thats not hard to do at all.

>>> So it mostly boils down to me being lazy and not wanting to spend a 
>>> lot  of time on building new infrastructure.  I'd like something 
>>> which is a  bit better than what we have now and can spend some time 
>>> on it, but I  don't want to spend a lot of time on it since patching 
>>> the driver works  just fine for my purposes.  Perfect is the enemy of 
>>> good.
>>>
>> Well, that is your perogative.  I had to make those sorts of choices when I did
>> embedded too.  I tried to get upstream what was acceptible, and carried the rest
>> myself on occasion. But I promise you, this really isn't hard.  Spend some time,
>> and you'll find and onboard initramfs environment can make your life worlds
>> easier long term.
>
> Yes, and the next time I would have to fix this on an embedded board, I  
> could probably have spent the time on figure out how to do something  
> slightly more generic, but since it won't have a chance of getting into  
> the kernel, I probably won't.
>
> Anyway, I've spent more time on discussing this now than it would have  
> taken me to hack the device drivers on half a dozen platforms, so I  
> think I'll give up.  Maybe I'll take a look at some initrd+klibc+dhcp  
> stuff when I have some free time next Christmas (that's when I usually  
> get to play around with my hobby projects), maybe not. :-)
>
I sympathize with you.  This is exactly what soured me on embedded work a few
years back.  Embedded shops are forever compromising doing things correctly in
the name of time and schedules, never paying any heed to the possibility that
taking extra time to do things in an agreed upon, organized and standard fashion
might pay off for them in the long run.  I encourage you to tell your management
that taking the time to develop this would let you save this time over and over
again in subsequnt probjects.  Track how much time you take keeping up with
that mac address assignment patch as you update kernels.  I had to do that
several times on various projects, and sometimes it helped (although usually it
just made me mad :) )
Neil



   /Christer
>
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 12, 2009, 7:14 p.m. UTC | #36
On Thu, Mar 12, 2009 at 03:05:17PM -0400, Neil Horman wrote:
> On Thu, Mar 12, 2009 at 07:25:10PM +0100, Christer Weinigel wrote:
> > Neil Horman wrote:
> >> You don't need klibc, you can use regular glibc, and even build statically if
> >> you like.  You'll have to use dig or host to do name lookups, but thats also
> >> pretty easy to do.  This really is easier than you think it is :)
> >
> > Size, size, size.  The killer in the embedded world which rules out  
> > glibc.  And have you tried to link glibc statically with something that  
> > uses gethostbyname lately?  It is no longer possible since the  
> > introduction of all the introduction of the dynamic name lookup crap  
> > (ok, it's not really crap, I just feel like it's crap every time I try  
> > to link a networking application statically).  But that's a bit off  
> > topic since I don't need name lookups just to mount a NFS file system.  
> > uclibc also seems to have issues with networking and statically linked  
> > binaries, but I just haven't had time to figure out why yet.
> >
> 
> You didn't read what I wrote very closely, I specifically said you have to dig
> or host to do name lookups, specifically because of the issues with getXbyY.
> When I said I built busybox in 800k (400k compressed), That was with glibc
> statically linked.  End of story.  You're making up problems here, its not that
> big a deal.  I've not looked at the figures lately, but how much space does the
> dhcp client and nfs root code take up in the kernel these days?
 
just checked: disabling CONFIG_IP_PNP and CONFIG_IP_PNP_DHCP saves me
4456 bytes of zImage size on an ARM/PXA build

Sascha
Jamie Lokier March 12, 2009, 7:15 p.m. UTC | #37
Sascha Hauer wrote:
> Great, but how does this help in setting the MAC address? This would
> just move this exact discussion to the dracut or whatever mailing list,
> but we would still be searching for a generic way to say
> eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.

The objection "we're not taking that because it should go in initrd"
would go away.

-- Jamie
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 12, 2009, 7:16 p.m. UTC | #38
On Thu, Mar 12, 2009 at 08:04:16PM +0100, Sascha Hauer wrote:
> On Thu, Mar 12, 2009 at 07:48:39PM +0100, Christer Weinigel wrote:
> > Jamie Lokier wrote:
> >> However there was some attempt to get a reference initrd build into
> >> the kernel.  Did that go anywhere?  It would actually be good to use
> >> that if it exists.
> >
> > That would be a very worthwhile project actually.  Create a package that  
> > uses klibc, does BOOTP/DCHP/NFS and parses the the ip=foo,bar options  
> > the same way the kernel does so that we can finally get rid of the in  
> > kernel stuff.
> 
> Great, but how does this help in setting the MAC address? This would
> just move this exact discussion to the dracut or whatever mailing list,
> but we would still be searching for a generic way to say
> eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.
> 
You need to do that yourself.  the initramfs is where all your platform specific
bits go.  You're assuming that some tool is automatically going to do this thing
for you that is by definition non-standard.  Non-standard stuff needs manually
process to implement.
Neil

> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 7:21 p.m. UTC | #39
Sascha Hauer wrote:
>> That would be a very worthwhile project actually.  Create a package that  
>> uses klibc, does BOOTP/DCHP/NFS and parses the the ip=foo,bar options  
>> the same way the kernel does so that we can finally get rid of the in  
>> kernel stuff.
> 
> Great, but how does this help in setting the MAC address? This would
> just move this exact discussion to the dracut or whatever mailing list,
> but we would still be searching for a generic way to say
> eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.

Alternate answers:

a) It wouldn't.  But that doesn't stop me from liking the idea of 
actually having a working initrd/initramfs that people can build on.

b) It would.  With an easy to use initrd/initramfs infrastructure it 
would be trivial to add a small script that parses /proc/cmdline and 
runs "ifconfig eth0 hwaddr $FOO" based on it.

c) It would.  When the initrd/initramfs runs, it has access to all the 
normal device driver, so reading the first block of flash and parsing 
the non-volatile data (assuming there is a mts device driver and that 
the format is known) and then running ifconfig eth0 hwaddr is also much 
easier.

And personally, yes, if there was a working initrd+dhcp+nfs combination 
that doesn't require significantly more memory than the in kernel one, 
of course I would use it.  And that's what DaveM is suggesting, to keep 
it out of the kernel and move it to user space where it really belongs.

Short therm I'd still like to have the more generic thing in the kernel 
tough.

   /Christer



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jamie Lokier March 12, 2009, 7:25 p.m. UTC | #40
Christer Weinigel wrote:
> > You don't need klibc, you can use regular glibc, and even build
> > statically if you like.  You'll have to use dig or host to do name
> > lookups, but thats also pretty easy to do.  This really is easier
> > than you think it is :)
> 
> Size, size, size.  The killer in the embedded world which rules out 
> glibc.  And have you tried to link glibc statically with something that 
> uses gethostbyname lately?  It is no longer possible since the 
> introduction of all the introduction of the dynamic name lookup crap 
> (ok, it's not really crap, I just feel like it's crap every time I try 
> to link a networking application statically).

In other words, glibc doesn't work on some embedded targets even if
you have plenty of room: they don't support dynamic libs.

> uclibc also seems to have issues with networking and statically linked 
> binaries, but I just haven't had time to figure out why yet.

I've never had an issue with uclibc and networking.

> In my opion, having a "hwaddrs=eth0=00:de:ad:be:ef:01" would be 
> consistent and maintainable.  But opinions differ.

I believe the party line on such things is "use udev". 

Of course, realistically you can't use udev on little embedded systems
and you probably wouldn't use it inside initrd either.  Oh well!

To fix the device name with udev you often match on MAC address :-)

> Once again, in your opinion it is a hack, I don't consider it more a 
> hack than assigning the IP address on the command line.  And I wouldn't 
> call the in kernel stuff useless.

That's a good point.

If assigning the MAC to a particular device "eth0" is dubious -
someone said because device names aren't guaranteed.  Well, why is
assigning the IP address ok?

> Yes, and the next time I would have to fix this on an embedded board, I 
> could probably have spent the time on figure out how to do something 
> slightly more generic, but since it won't have a chance of getting into 
> the kernel, I probably won't.

Another good point: There have been complaints, of a sort, that
embedded developers don't feed back enough of their work upstream.

It's not surprising if this is typical of the objections.

I'm totally failing to see why _if_ setting the IP address on the
kernel command line, for the kernel to apply, is ok, but the MAC is
not.  Both or neither.  Fair enough that the IP option was put in a
long time ago, before policies changed.  But as long as that
capability is there and used and useful, it's ridiculous that it can't
be marginally improved.

-- Jamie

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 7:29 p.m. UTC | #41
Neil Horman wrote:
> You didn't read what I wrote very closely, I specifically said you have to dig
> or host to do name lookups, specifically because of the issues with getXbyY.

Did too.  :-)

> 3) Your knoweldge from (1) is insufficient to implement the required initramfs in (2)
> in (assuming your example time frame) 1 week?
> 
> Seriously?

Yup.  A week right now is a luxury I usually don't have right now.
I shouldn't even be spending time writing this mail, but I'm eh,
right, waiting for a compilation to finish.

>> Anyway, I've spent more time on discussing this now than it would have  
>> taken me to hack the device drivers on half a dozen platforms, so I  
>> think I'll give up.  Maybe I'll take a look at some initrd+klibc+dhcp  
>> stuff when I have some free time next Christmas (that's when I usually  
>> get to play around with my hobby projects), maybe not. :-)
>>
> I sympathize with you.  This is exactly what soured me on embedded work a few
> years back.  Embedded shops are forever compromising doing things correctly in
> the name of time and schedules, never paying any heed to the possibility that
> taking extra time to do things in an agreed upon, organized and standard fashion
> might pay off for them in the long run.  

Actually, I'm quite happy about work so far.  When worked on improving 
the Samsung S3C24A0 patches Sandeep Patil had made, I got approval from 
my boss to spend time on making them suitable for submission to the 
official kernel, so I was able to do a lot more than just "make things 
work now".  But the last few months have been kind of hectic.

   /Christer
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 7:43 p.m. UTC | #42
Jamie Lokier wrote:
> In other words, glibc doesn't work on some embedded targets even if
> you have plenty of room: they don't support dynamic libs.

It might be possible to build glibc to always use hosts+DNS for name 
lookup, but since I almost always use uclibc on embedded systems I 
haven't really tried to do it.  If I use glibc, it's on a NFS root and 
those systems are large enough anyway.

>> uclibc also seems to have issues with networking and statically linked 
>> binaries, but I just haven't had time to figure out why yet.
> 
> I've never had an issue with uclibc and networking.

I'm not sure what is happening, but a statically linked uclibc binary 
that does TCP networking will work happily with one userspace but not 
another.  It would seem to me that a statically linked binary should 
only depend on the kernel ABI and not on anything userspace (except the 
text files in /etc like resolv.conf), but that does not seem to match 
reality.  If I use Unix sockets instead it works fine, so belive it is 
something related to TCP.  But well, this is all very fuzzy because I 
haven't had time to look more closely at it yet.

   /Christer
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfgang Denk March 12, 2009, 8:14 p.m. UTC | #43
Dear Sascha Hauer,

In message <20090312190416.GS425@pengutronix.de> you wrote:
>
> Great, but how does this help in setting the MAC address? This would
> just move this exact discussion to the dracut or whatever mailing list,
> but we would still be searching for a generic way to say
> eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.

Well, PowerPC uses the device tree for such information.  As  far  as
I've been told work is underway to extend the device tree support for
ARM, too.  [And U-Boot supports the device tree, of course.]

Best regards,

Wolfgang Denk
Mike (mwester) March 12, 2009, 8:24 p.m. UTC | #44
Neil Horman wrote:

> What exactly is so difficult about cpio-ing up an initramfs to do this work with
> sed and ifconfig? You make it sound like its an impossible barrier. Its really
> quite simple

Can you share your scripts and tools for creating an initramfs so
easily?  I too run into this problem -- I've always used the
kernel-provided mechanism to DHCP and do the nfs mount of the rootfs,
but if the initramfs is the right way to do that, then I'll be happy to
change.

It always looked rather daunting to me, and a lot of extra effort
compared to letting the kernel do the job, but if it really is so easy,
then I'll be happy to change my practices.

Thanks!
Mike (mwester)
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer March 12, 2009, 8:27 p.m. UTC | #45
On Thu, Mar 12, 2009 at 09:14:49PM +0100, Wolfgang Denk wrote:
> Dear Sascha Hauer,
> 
> In message <20090312190416.GS425@pengutronix.de> you wrote:
> >
> > Great, but how does this help in setting the MAC address? This would
> > just move this exact discussion to the dracut or whatever mailing list,
> > but we would still be searching for a generic way to say
> > eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.
> 
> Well, PowerPC uses the device tree for such information.  As  far  as
> I've been told work is underway to extend the device tree support for
> ARM, too.  [And U-Boot supports the device tree, of course.]

I'm looking forward to the first patches on Linux Arm Kernel. That's
gonna be even more fun than this thread ;)

Sascha
Russell King - ARM Linux March 12, 2009, 8:35 p.m. UTC | #46
On Thu, Mar 12, 2009 at 09:14:49PM +0100, Wolfgang Denk wrote:
> Dear Sascha Hauer,
> 
> In message <20090312190416.GS425@pengutronix.de> you wrote:
> >
> > Great, but how does this help in setting the MAC address? This would
> > just move this exact discussion to the dracut or whatever mailing list,
> > but we would still be searching for a generic way to say
> > eth0addr=00:01:02:03:04:05 and I bet the arguments stay the same.
> 
> Well, PowerPC uses the device tree for such information.  As  far  as
> I've been told work is underway to extend the device tree support for
> ARM, too.

EWW.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jamie Lokier March 12, 2009, 9:59 p.m. UTC | #47
Neil Horman wrote:
> I've not looked at the figures lately, but how much space does the
> dhcp client and nfs root code take up in the kernel these days?

About 4k apparently.  See the difference from "400k compressed?".
Also, uncompressing that may add 0.5 second boot time on a slow CPU :-)

> I sympathize with you.  This is exactly what soured me on embedded
> work a few years back.  Embedded shops are forever compromising
> doing things correctly in the name of time and schedules, never
> paying any heed to the possibility that taking extra time to do
> things in an agreed upon, organized and standard fashion might pay
> off for them in the long run.

I must admit that a solution which makes the effective kernel size
800k larger (your figure) doesn't look like a good standard to me.

If that was the "standard", I'd be tempted to add a MAC address driver
hack to the kernel to save the space :-)

-- Jamie
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 12, 2009, 11:42 p.m. UTC | #48
Jamie Lokier wrote:

> Neil Horman wrote:
>> I've not looked at the figures lately, but how much space does the
>> dhcp client and nfs root code take up in the kernel these days?
> 
> About 4k apparently.  See the difference from "400k compressed?".
> Also, uncompressing that may add 0.5 second boot time on a slow CPU :-)


I just tried to get some actual numbers for the size increase by looking 
at an actual initrd I had lying around.  If I just look at some some of 
the largest files needed for a initrd, they use 800kBytes:

ls -l bin/busybox lib/ld-uClibc-0.9.28.so lib/libuClibc-0.9.28.so
-rwxr-xr-x 1 root root 499804 2007-01-21 18:17 bin/busybox*
-rwxr-xr-x 1 root root  19492 2005-12-27 12:15 lib/ld-uClibc-0.9.28.so*
-rw-r--r-- 1 root root 312136 2005-12-27 08:46 lib/libuClibc-0.9.28.so

All files are stripped ARM9 binaries and as you can see, the C library 
is uClibc.  And compressed it is roughly about 400kBytes:

tar cvfz - bin/busybox lib/ld-uClibc-0.9.28.so lib/libuClibc-0.9.28.so | wc -c

422789

The in kernel BOOT/DCHP client and NFS root code increases the size of
the compressed kernel by slighty less than 8kBytes.  The 4k number was
just for turning off BOOTP/DHCP (IP_PNP).

 > I must admit that a solution which makes the effective kernel size

> 800k larger (your figure) doesn't look like a good standard to me.
> 
> If that was the "standard", I'd be tempted to add a MAC address driver
> hack to the kernel to save the space :-)

So the numbers aren't quite as bad, but it is a 50 time increase in 
overhead to do things "right".  For a kernel which is 1.5Mbytes it is 
"only" a 27% increase in total size though.

Of course, using busybox is a bit of an overkill, it should be possible 
to just port the in kernel BOOTP/DHCP client and NFS root code so that 
it is statically linked with klibc and put in an initrd.  If we assume 
that the useful parts of the code stay the same size, it should compress 
to about 8kBytes of initrd instead of 8kBytes of compressed kernel 
image.  But code running from an initrd will need a stdio library with 
printf and a bunch of other library functions.  After taking a quick 
look at klibc it seems that it would add something like 10-20kBytes 
compressed size to a normal application.  So that would only be a 2-3 
time increase in size which is much more acceptable to me.

Actually, just looking at the filenames in the klibc source, it seems 
that it does have a DHCP client and some NFS root code already.  An ARM9 
"kinit" binary is about 75kBytes, and I'm not sure if it includes the 
DHCP client or the NFS root code.  But it means that it's probably 
possible to replace the in kernel code with klibc as is for only an 
extra 50kBytes or so of increased compressed size.

Looks interesting, any year now...

   /Christer














--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 13, 2009, 12:16 a.m. UTC | #49
On Thu, Mar 12, 2009 at 09:59:19PM +0000, Jamie Lokier wrote:
> Neil Horman wrote:
> > I've not looked at the figures lately, but how much space does the
> > dhcp client and nfs root code take up in the kernel these days?
> 
> About 4k apparently.  See the difference from "400k compressed?".
> Also, uncompressing that may add 0.5 second boot time on a slow CPU :-)
> 
> > I sympathize with you.  This is exactly what soured me on embedded
> > work a few years back.  Embedded shops are forever compromising
> > doing things correctly in the name of time and schedules, never
> > paying any heed to the possibility that taking extra time to do
> > things in an agreed upon, organized and standard fashion might pay
> > off for them in the long run.
> 
> I must admit that a solution which makes the effective kernel size
> 800k larger (your figure) doesn't look like a good standard to me.
> 
> If that was the "standard", I'd be tempted to add a MAC address driver
> hack to the kernel to save the space :-)
> 
> -- Jamie
> 
I agree that the simple 8k savings is less than stellar, but if you're setting
up a development environment over NFS root, your savings are really unbounded.
Need more space?  Carve out a config option in the kernel that you don't need
immediately, build it as a module, and store it on the NFS root, keeping only
the needed functionality for NFS root in the monolithic image.  Lather, rinse,
repeat until you have enough space.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 13, 2009, 12:21 a.m. UTC | #50
On Fri, Mar 13, 2009 at 12:42:41AM +0100, Christer Weinigel wrote:
> Jamie Lokier wrote:
>
>> Neil Horman wrote:
>>> I've not looked at the figures lately, but how much space does the
>>> dhcp client and nfs root code take up in the kernel these days?
>>
>> About 4k apparently.  See the difference from "400k compressed?".
>> Also, uncompressing that may add 0.5 second boot time on a slow CPU :-)
>
>
> I just tried to get some actual numbers for the size increase by looking  
> at an actual initrd I had lying around.  If I just look at some some of  
> the largest files needed for a initrd, they use 800kBytes:
>
> ls -l bin/busybox lib/ld-uClibc-0.9.28.so lib/libuClibc-0.9.28.so
> -rwxr-xr-x 1 root root 499804 2007-01-21 18:17 bin/busybox*
> -rwxr-xr-x 1 root root  19492 2005-12-27 12:15 lib/ld-uClibc-0.9.28.so*
> -rw-r--r-- 1 root root 312136 2005-12-27 08:46 lib/libuClibc-0.9.28.so
>
> All files are stripped ARM9 binaries and as you can see, the C library  
> is uClibc.  And compressed it is roughly about 400kBytes:
>
> tar cvfz - bin/busybox lib/ld-uClibc-0.9.28.so lib/libuClibc-0.9.28.so | wc -c
>
> 422789
>
> The in kernel BOOT/DCHP client and NFS root code increases the size of
> the compressed kernel by slighty less than 8kBytes.  The 4k number was
> just for turning off BOOTP/DHCP (IP_PNP).
>
> > I must admit that a solution which makes the effective kernel size
>
>> 800k larger (your figure) doesn't look like a good standard to me.
>>
>> If that was the "standard", I'd be tempted to add a MAC address driver
>> hack to the kernel to save the space :-)
>
> So the numbers aren't quite as bad, but it is a 50 time increase in  
> overhead to do things "right".  For a kernel which is 1.5Mbytes it is  
> "only" a 27% increase in total size though.
>
> Of course, using busybox is a bit of an overkill, it should be possible  
> to just port the in kernel BOOTP/DHCP client and NFS root code so that  
> it is statically linked with klibc and put in an initrd.  If we assume  
> that the useful parts of the code stay the same size, it should compress  
> to about 8kBytes of initrd instead of 8kBytes of compressed kernel  
> image.  But code running from an initrd will need a stdio library with  
> printf and a bunch of other library functions.  After taking a quick  
> look at klibc it seems that it would add something like 10-20kBytes  
> compressed size to a normal application.  So that would only be a 2-3  
> time increase in size which is much more acceptable to me.
>
> Actually, just looking at the filenames in the klibc source, it seems  
> that it does have a DHCP client and some NFS root code already.  An ARM9  
> "kinit" binary is about 75kBytes, and I'm not sure if it includes the  
> DHCP client or the NFS root code.  But it means that it's probably  
> possible to replace the in kernel code with klibc as is for only an  
> extra 50kBytes or so of increased compressed size.
>
> Looks interesting, any year now...
>
>   /Christer
>

So, I've avoided asking this question, because I didn't want to get off topic,
but since it appears we're winding up here, I have to ask what your long term
plan is for your final application.  I can understand being hesitant to invest
in an initramfs when its solely for your intermediate development (even though I
think that will pay off for you in the long run), but when your development
ends, and you ship a product, how do you plan to implement your application?  I
would imagine you at least need an initramfs to store, load and run your final
application don't you?  How do you plan on executing it?

Neil

>
>
>
>
>
>
>
>
>
>
>
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 13, 2009, 12:29 a.m. UTC | #51
On Thu, Mar 12, 2009 at 03:24:20PM -0500, Mike (mwester) wrote:
> Neil Horman wrote:
> 
> > What exactly is so difficult about cpio-ing up an initramfs to do this work with
> > sed and ifconfig? You make it sound like its an impossible barrier. Its really
> > quite simple
> 
> Can you share your scripts and tools for creating an initramfs so
> easily?  I too run into this problem -- I've always used the
> kernel-provided mechanism to DHCP and do the nfs mount of the rootfs,
> but if the initramfs is the right way to do that, then I'll be happy to
> change.
> 
> It always looked rather daunting to me, and a lot of extra effort
> compared to letting the kernel do the job, but if it really is so easy,
> then I'll be happy to change my practices.
> 
> Thanks!
> Mike (mwester)
Sure, you'll find my mkduprd script in the kexec-tools package for fedora,
you're welcome to tear it up to suit your needs.

By way of precaution, I'll tell you that the script is much larger than it needs
to be, since its purpose is to copy a vmcore to several various locations.

In short summary, all you need to make an initramfs is:

1) create a rootfs directory tree somewhere, call it $INITRD_ROOT
2) populate the initrd with any applications you need for your purpose
3) create an executable file , called $INITRD_ROOT/init
4) $INITRD_ROOT/init should do whatever you want the initramfs to do, in
mkdumprd I make it a shell script that does various and sunry things, although
you could do something as simple as making it run /bin/sh to give you a shell
prompt.
5)cd $INITRD_ROOT; cpio --quiet -c -o /tmp/initramfs; gzip -9 /tmp/initramfs

thats it.
Neil

> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christer Weinigel March 13, 2009, 1:29 a.m. UTC | #52
Neil Horman wrote:

> So, I've avoided asking this question, because I didn't want to get off topic,
> but since it appears we're winding up here, I have to ask what your long term
> plan is for your final application.  I can understand being hesitant to invest
> in an initramfs when its solely for your intermediate development (even though I
> think that will pay off for you in the long run), but when your development
> ends, and you ship a product, how do you plan to implement your application?  I
> would imagine you at least need an initramfs to store, load and run your final
> application don't you?  How do you plan on executing it?

Most probably no ramdisk at all, just the mtd driver and flash file 
system driver compiled into the kernel and then "root=/dev/mtdblock4".

For one old product the bootloader programs the mac address into the 
ethernet chip before the kernel boots.  For another embedded system 
thats out in production the bootloader is really dumb and it's up to 
early userspace to extract the mac address from nonvolatile memory and 
do ifconfig hwaddr.

And as I wrote in a different post, most systems I'm working on now 
won't even have ethernet.

   /Christer

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Neil Horman March 13, 2009, 10:30 a.m. UTC | #53
On Fri, Mar 13, 2009 at 02:29:58AM +0100, Christer Weinigel wrote:
> Neil Horman wrote:
>
>> So, I've avoided asking this question, because I didn't want to get off topic,
>> but since it appears we're winding up here, I have to ask what your long term
>> plan is for your final application.  I can understand being hesitant to invest
>> in an initramfs when its solely for your intermediate development (even though I
>> think that will pay off for you in the long run), but when your development
>> ends, and you ship a product, how do you plan to implement your application?  I
>> would imagine you at least need an initramfs to store, load and run your final
>> application don't you?  How do you plan on executing it?
>
> Most probably no ramdisk at all, just the mtd driver and flash file  
> system driver compiled into the kernel and then "root=/dev/mtdblock4".
>
Ok, thanks, so you have a place to store user space images.  This thread got me
wondering what you were going to do long term about user space.  I was starting
to think as a space saving measure, that you were building your app into the
kernel or something.

FWIW, I think Uboot has a pretty robust mtd infrastructure that would allow you
to store a initramfs image there for use if you were interested in exploring
that route.

Neil

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Robert Schwebel March 13, 2009, 7:49 p.m. UTC | #54
On Thu, Mar 12, 2009 at 07:05:54AM -0700, David Miller wrote:
> From: Michael Cashwell <mboards@prograde.net>
> Date: Thu, 12 Mar 2009 09:41:38 -0400
> 
> > I'm confused by this. If I'm NFS-booting the board then how do I get
> > to those userland tools if I don't have a valid MAC address in place
> > to do the root mount?
> 
> Initial ramdisk.

That's maybe the right solution for big machines, but for small embedded
systems it's absolutely overkill. We have used Linux on several ten ARM
and PowerPC boards, and the only reason we ever needed an initrd was
on an IXP425 who needed a strange firmware which had a license.

Embedded boxes are often short on RAM, so wasting megabytes of space on
a box that maybe has 8...16 MB RAM just because of a mac address doesn't
sound like a good solution.

rsc
David Miller March 13, 2009, 8:12 p.m. UTC | #55
From: Robert Schwebel <r.schwebel@pengutronix.de>
Date: Fri, 13 Mar 2009 20:49:41 +0100

> On Thu, Mar 12, 2009 at 07:05:54AM -0700, David Miller wrote:
> > From: Michael Cashwell <mboards@prograde.net>
> > Date: Thu, 12 Mar 2009 09:41:38 -0400
> > 
> > > I'm confused by this. If I'm NFS-booting the board then how do I get
> > > to those userland tools if I don't have a valid MAC address in place
> > > to do the root mount?
> > 
> > Initial ramdisk.
> 
> That's maybe the right solution for big machines, but for small embedded
> systems it's absolutely overkill. We have used Linux on several ten ARM
> and PowerPC boards, and the only reason we ever needed an initrd was
> on an IXP425 who needed a strange firmware which had a license.
> 
> Embedded boxes are often short on RAM, so wasting megabytes of space on
> a box that maybe has 8...16 MB RAM just because of a mac address doesn't
> sound like a good solution.

Slipping every odd feature into the kernel on the basis that it might
be useful to some small group of people doesn't sound like good system
design to me.

And I know for a fact that with all of the effort people have been
investing into this stupid thread, they could have implemented the
necessary initrd they needed 10 times over.

I can't believe they have so much time, there must not be one of
those dreaded "deadline"'s approaching.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a2f185f..5c28b06 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1040,6 +1040,17 @@  config NI65
 	  To compile this driver as a module, choose M here. The module
 	  will be called ni65.
 
+config DNET
+	tristate "Dave ethernet support (DNET)"
+	depends on NET_ETHERNET
+	select PHYLIB
+	help
+	  The Dave ethernet interface (DNET) is found on Qong Board FPGA.
+	  Say Y to include support for the DNET chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called dnet.
+
 source "drivers/net/tulip/Kconfig"
 
 config AT1700
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index aca8492..6d9bba5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -231,6 +231,7 @@  obj-$(CONFIG_ENC28J60) += enc28j60.o
 
 obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
 
+obj-$(CONFIG_DNET) += dnet.o
 obj-$(CONFIG_MACB) += macb.o
 
 obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
new file mode 100644
index 0000000..e6fbd59
--- /dev/null
+++ b/drivers/net/dnet.c
@@ -0,0 +1,1019 @@ 
+/*
+ * Dave DNET Ethernet Controller driver
+ *
+ * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
+ * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+
+#include "dnet.h"
+
+#undef DEBUG
+
+static char ethaddr[18];
+
+module_param_string(ethaddr, ethaddr, sizeof(ethaddr), 0);
+
+static void get_mac_addr(struct net_device *nd, unsigned char *pmac)
+{
+	int i;
+	char *p = ethaddr;
+
+	ethaddr[17] = 0;
+	for (i = 0; i < ETH_ALEN; i++, p++) {
+		pmac[i] = simple_strtoul(p, &p, 16);
+		if (*p != ':')
+			break;
+	}
+	if (i != ETH_ALEN - 1) {
+		pr_err("Wrong MAC address format!\n");
+		memset(pmac, 0, ETH_ALEN);
+	}
+}
+
+/* function for reading internal MAC register */
+u16 dnet_readw_mac(struct dnet *bp, u16 reg)
+{
+	u16 data_read;
+
+	/* issue a read */
+	dnet_writel(bp, reg, MACREG_ADDR);
+
+	/* since a read/write op to the MAC is very slow,
+	 * we must wait before reading the data */
+	ndelay(500);
+
+	/* read data read from the MAC register */
+	data_read = dnet_readl(bp, MACREG_DATA);
+
+	/* all done */
+	return data_read;
+}
+
+/* function for writing internal MAC register */
+void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val)
+{
+	/* load data to write */
+	dnet_writel(bp, val, MACREG_DATA);
+
+	/* issue a write */
+	dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR);
+
+	/* since a read/write op to the MAC is very slow,
+	 * we must wait before exiting */
+	ndelay(500);
+}
+
+static void __dnet_set_hwaddr(struct dnet *bp)
+{
+	u16 tmp;
+
+	tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr));
+	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
+	tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2)));
+	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
+	tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4)));
+	dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
+}
+
+static void __devinit dnet_get_hwaddr(struct dnet *bp)
+{
+	u16 tmp;
+	u8 addr[6];
+
+	/*
+	 * from MAC docs:
+	 * "Note that the MAC address is stored in the registers in Hexadecimal
+	 * form. For example, to set the MAC Address to: AC-DE-48-00-00-80
+	 * would require writing 0xAC (octet 0) to address 0x0B (high byte of
+	 * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of
+	 * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of
+	 * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of
+	 * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of
+	 * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of
+	 * Mac_addr[15:0]).
+	 */
+	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG);
+	*((u16 *) addr) = be16_to_cpu(tmp);
+	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG);
+	*((u16 *) (addr + 2)) = be16_to_cpu(tmp);
+	tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG);
+	*((u16 *) (addr + 4)) = be16_to_cpu(tmp);
+
+	if (is_valid_ether_addr(addr))
+		memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+}
+
+static int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct dnet *bp = bus->priv;
+	u16 value;
+
+	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
+				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
+		cpu_relax();
+
+	/* only 5 bits allowed for phy-addr and reg_offset */
+	mii_id &= 0x1f;
+	regnum &= 0x1f;
+
+	/* prepare reg_value for a read */
+	value = (mii_id << 8);
+	value |= regnum;
+
+	/* write control word */
+	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
+
+	/* wait for end of transfer */
+	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
+				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
+		cpu_relax();
+
+	value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG);
+
+	pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value);
+
+	return value;
+}
+
+static int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+			   u16 value)
+{
+	struct dnet *bp = bus->priv;
+	u16 tmp;
+
+	pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value);
+
+	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
+				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
+		cpu_relax();
+
+	/* prepare for a write operation */
+	tmp = (1 << 13);
+
+	/* only 5 bits allowed for phy-addr and reg_offset */
+	mii_id &= 0x1f;
+	regnum &= 0x1f;
+
+	/* only 16 bits on data */
+	value &= 0xffff;
+
+	/* prepare reg_value for a write */
+	tmp |= (mii_id << 8);
+	tmp |= regnum;
+
+	/* write data to write first */
+	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value);
+
+	/* write control word */
+	dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp);
+
+	while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG)
+				& DNET_INTERNAL_GMII_MNG_CMD_FIN))
+		cpu_relax();
+
+	return 0;
+}
+
+static int dnet_mdio_reset(struct mii_bus *bus)
+{
+	return 0;
+}
+
+static void dnet_handle_link_change(struct net_device *dev)
+{
+	struct dnet *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+	unsigned long flags;
+	u32 mode_reg, ctl_reg;
+
+	int status_change = 0;
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG);
+	ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG);
+
+	if (phydev->link) {
+		if (bp->duplex != phydev->duplex) {
+			if (phydev->duplex)
+				ctl_reg &=
+				    ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP);
+			else
+				ctl_reg |=
+				    DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP;
+
+			bp->duplex = phydev->duplex;
+			status_change = 1;
+		}
+
+		if (bp->speed != phydev->speed) {
+			status_change = 1;
+			switch (phydev->speed) {
+			case 1000:
+				mode_reg |= DNET_INTERNAL_MODE_GBITEN;
+				break;
+			case 100:
+			case 10:
+				mode_reg &= ~DNET_INTERNAL_MODE_GBITEN;
+				break;
+			default:
+				printk(KERN_WARNING
+				       "%s: Ack!  Speed (%d) is not "
+				       "10/100/1000!\n", dev->name,
+				       phydev->speed);
+				break;
+			}
+			bp->speed = phydev->speed;
+		}
+	}
+
+	if (phydev->link != bp->link) {
+		if (phydev->link) {
+			mode_reg |=
+			    (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN);
+		} else {
+			mode_reg &=
+			    ~(DNET_INTERNAL_MODE_RXEN |
+			      DNET_INTERNAL_MODE_TXEN);
+			bp->speed = 0;
+			bp->duplex = -1;
+		}
+		bp->link = phydev->link;
+
+		status_change = 1;
+	}
+
+	if (status_change) {
+		dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg);
+		dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg);
+	}
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			printk(KERN_INFO "%s: link up (%d/%s)\n",
+			       dev->name, phydev->speed,
+			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+		else
+			printk(KERN_INFO "%s: link down\n", dev->name);
+	}
+}
+
+static int dnet_mii_probe(struct net_device *dev)
+{
+	struct dnet *bp = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	int phy_addr;
+
+	/* find the first phy */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (bp->mii_bus->phy_map[phy_addr]) {
+			phydev = bp->mii_bus->phy_map[phy_addr];
+			break;
+		}
+	}
+
+	if (!phydev) {
+		printk(KERN_ERR "%s: no PHY found\n", dev->name);
+		return -ENODEV;
+	}
+
+	/* TODO : add pin_irq */
+
+	/* attach the mac to the phy */
+	if (bp->capabilities & DNET_HAS_RMII) {
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+				     &dnet_handle_link_change, 0,
+				     PHY_INTERFACE_MODE_RMII);
+	} else {
+		phydev = phy_connect(dev, phydev->dev.bus_id,
+				     &dnet_handle_link_change, 0,
+				     PHY_INTERFACE_MODE_MII);
+	}
+
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
+
+	/* mask with MAC supported features */
+	if (bp->capabilities & DNET_HAS_GIGABIT)
+		phydev->supported &= PHY_GBIT_FEATURES;
+	else
+		phydev->supported &= PHY_BASIC_FEATURES;
+
+	phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;
+
+	phydev->advertising = phydev->supported;
+
+	bp->link = 0;
+	bp->speed = 0;
+	bp->duplex = -1;
+	bp->phy_dev = phydev;
+
+	return 0;
+}
+
+static int dnet_mii_init(struct dnet *bp)
+{
+	int err, i;
+
+	bp->mii_bus = mdiobus_alloc();
+	if (bp->mii_bus == NULL)
+		return -ENOMEM;
+
+	bp->mii_bus->name = "dnet_mii_bus";
+	bp->mii_bus->read = &dnet_mdio_read;
+	bp->mii_bus->write = &dnet_mdio_write;
+	bp->mii_bus->reset = &dnet_mdio_reset;
+
+	snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+
+	bp->mii_bus->priv = bp;
+
+	bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!bp->mii_bus->irq) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		bp->mii_bus->irq[i] = PHY_POLL;
+
+	platform_set_drvdata(bp->dev, bp->mii_bus);
+
+	if (mdiobus_register(bp->mii_bus)) {
+		err = -ENXIO;
+		goto err_out_free_mdio_irq;
+	}
+
+	if (dnet_mii_probe(bp->dev) != 0) {
+		err = -ENXIO;
+		goto err_out_unregister_bus;
+	}
+
+	return 0;
+
+err_out_unregister_bus:
+	mdiobus_unregister(bp->mii_bus);
+err_out_free_mdio_irq:
+	kfree(bp->mii_bus->irq);
+err_out:
+	mdiobus_free(bp->mii_bus);
+	return err;
+}
+
+/* For Neptune board: LINK1000 as Link LED and TX as activity LED */
+int dnet_phy_marvell_fixup(struct phy_device *phydev)
+{
+	return phy_write(phydev, 0x18, 0x4148);
+}
+
+static void dnet_update_stats(struct dnet *bp)
+{
+	u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT;
+	u32 *p = &bp->hw_stats.rx_pkt_ignr;
+	u32 *end = &bp->hw_stats.rx_byte + 1;
+
+	WARN_ON((unsigned long)(end - p - 1) !=
+		(DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4);
+
+	for (; p < end; p++, reg++)
+		*p += readl(reg);
+
+	reg = bp->regs + DNET_TX_UNICAST_CNT;
+	p = &bp->hw_stats.tx_unicast;
+	end = &bp->hw_stats.tx_byte + 1;
+
+	WARN_ON((unsigned long)(end - p - 1) !=
+		(DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4);
+
+	for (; p < end; p++, reg++)
+		*p += readl(reg);
+}
+
+static int dnet_poll(struct napi_struct *napi, int budget)
+{
+	struct dnet *bp = container_of(napi, struct dnet, napi);
+	struct net_device *dev = bp->dev;
+	int npackets = 0;
+	unsigned int pkt_len;
+	struct sk_buff *skb;
+	unsigned int *data_ptr;
+	u32 int_enable;
+	u32 cmd_word;
+	int i;
+
+	while (npackets < budget) {
+		/*
+		 * break out of while loop if there are no more
+		 * packets waiting
+		 */
+		if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) {
+			netif_rx_complete(napi);
+			int_enable = dnet_readl(bp, INTR_ENB);
+			int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF;
+			dnet_writel(bp, int_enable, INTR_ENB);
+			return 0;
+		}
+
+		cmd_word = dnet_readl(bp, RX_LEN_FIFO);
+		pkt_len = cmd_word & 0xFFFF;
+
+		if (cmd_word & 0xDF180000)
+			printk(KERN_ERR "%s packet receive error %x\n",
+			       __func__, cmd_word);
+
+		skb = dev_alloc_skb(pkt_len + 5);
+		if (skb != NULL) {
+			skb->dev = dev;
+			/* Align IP on 16 byte boundaries */
+			skb_reserve(skb, 2);
+			/*
+			 * 'skb_put()' points to the start of sk_buff
+			 * data area.
+			 */
+			data_ptr = (unsigned int *)skb_put(skb, pkt_len);
+			for (i = 0; i < (pkt_len + 3) >> 2; i++)
+				*data_ptr++ = dnet_readl(bp, RX_DATA_FIFO);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_receive_skb(skb);
+			bp->dev->last_rx = jiffies;
+			npackets++;
+		} else
+			printk(KERN_NOTICE
+			       "%s: No memory to allocate a sk_buff of "
+			       "size %d.\n", dev->name, pkt_len);
+	}
+
+	budget -= npackets;
+
+	if (npackets < budget) {
+		/* We processed all packets available.  Tell NAPI it can
+		 * stop polling then re-enable rx interrupts */
+		netif_rx_complete(napi);
+		int_enable = dnet_readl(bp, INTR_ENB);
+		int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF;
+		dnet_writel(bp, int_enable, INTR_ENB);
+		return 0;
+	}
+
+	/* There are still packets waiting */
+	return 1;
+}
+
+static irqreturn_t dnet_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct dnet *bp = netdev_priv(dev);
+	u32 int_src, int_enable, int_current;
+	unsigned long flags;
+	unsigned int handled = 0;
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	/* read and clear the DNET irq (clear on read) */
+	int_src = dnet_readl(bp, INTR_SRC);
+	int_enable = dnet_readl(bp, INTR_ENB);
+	int_current = int_src & int_enable;
+
+	/* restart the queue if we had stopped it for TX fifo almost full */
+	if (int_current & DNET_INTR_SRC_TX_FIFOAE) {
+		int_enable = dnet_readl(bp, INTR_ENB);
+		int_enable &= ~DNET_INTR_ENB_TX_FIFOAE;
+		dnet_writel(bp, int_enable, INTR_ENB);
+		netif_wake_queue(dev);
+		handled = 1;
+	}
+
+	/* RX FIFO error checking */
+	if (int_current &
+	    (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) {
+		printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__,
+		       dnet_readl(bp, RX_STATUS), int_current);
+		/* we can only flush the RX FIFOs */
+		dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL);
+		ndelay(500);
+		dnet_writel(bp, 0, SYS_CTL);
+		handled = 1;
+	}
+
+	/* TX FIFO error checking */
+	if (int_current &
+	    (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) {
+		printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__,
+		       dnet_readl(bp, TX_STATUS), int_current);
+		/* we can only flush the TX FIFOs */
+		dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL);
+		ndelay(500);
+		dnet_writel(bp, 0, SYS_CTL);
+		handled = 1;
+	}
+
+	if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) {
+		if (netif_rx_schedule_prep(&bp->napi)) {
+			/*
+			 * There's no point taking any more interrupts
+			 * until we have processed the buffers
+			 */
+			/* Disable Rx interrupts and schedule NAPI poll */
+			int_enable = dnet_readl(bp, INTR_ENB);
+			int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF;
+			dnet_writel(bp, int_enable, INTR_ENB);
+			__netif_rx_schedule(&bp->napi);
+		}
+		handled = 1;
+	}
+
+	if (!handled)
+		pr_debug("%s: irq %x remains\n", __func__, int_current);
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	return IRQ_RETVAL(handled);
+}
+
+#ifdef DEBUG
+static inline void dnet_print_skb(struct sk_buff *skb)
+{
+	int k;
+	printk(KERN_DEBUG PFX "data:");
+	for (k = 0; k < skb->len; k++)
+		printk(" %02x", (unsigned int)skb->data[k]);
+	printk("\n");
+}
+#else
+#define dnet_print_skb(skb)	do {} while (0)
+#endif
+
+static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+
+	struct dnet *bp = netdev_priv(dev);
+	u32 tx_status, irq_enable;
+	unsigned int len, i, tx_cmd, wrsz;
+	unsigned long flags;
+	unsigned int *bufp;
+
+	tx_status = dnet_readl(bp, TX_STATUS);
+
+	pr_debug("start_xmit: len %u head %p data %p tail %p end %p\n",
+	       skb->len, skb->head, skb->data, skb->tail, skb->end);
+	dnet_print_skb(skb);
+
+	/* frame size (words) */
+	len = (skb->len + 3) >> 2;
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	tx_status = dnet_readl(bp, TX_STATUS);
+
+	bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC);
+	wrsz = (u32) skb->len + 3;
+	wrsz += ((u32) skb->data) & 0x3;
+	wrsz >>= 2;
+	tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len;
+
+	/* check if there is enough room for the current frame */
+	if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) {
+		for (i = 0; i < wrsz; i++)
+			dnet_writel(bp, *bufp++, TX_DATA_FIFO);
+
+		/*
+		 * inform MAC that a packet's written and ready to be
+		 * shipped out
+		 */
+		dnet_writel(bp, tx_cmd, TX_LEN_FIFO);
+	}
+
+	if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) {
+		netif_stop_queue(dev);
+		tx_status = dnet_readl(bp, INTR_SRC);
+		irq_enable = dnet_readl(bp, INTR_ENB);
+		irq_enable |= DNET_INTR_ENB_TX_FIFOAE;
+		dnet_writel(bp, irq_enable, INTR_ENB);
+	}
+
+	/* free the buffer */
+	dev_kfree_skb(skb);
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+static void dnet_reset_hw(struct dnet *bp)
+{
+	/* put ts_mac in IDLE state i.e. disable rx/tx */
+	dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN);
+
+	/*
+	 * RX FIFO almost full threshold: only cmd FIFO almost full is
+	 * implemented for RX side
+	 */
+	dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH);
+	/*
+	 * TX FIFO almost empty threshold: only data FIFO almost empty
+	 * is implemented for TX side
+	 */
+	dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH);
+
+	/* flush rx/tx fifos */
+	dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH,
+			SYS_CTL);
+	msleep(1);
+	dnet_writel(bp, 0, SYS_CTL);
+}
+
+static void dnet_init_hw(struct dnet *bp)
+{
+	u32 config;
+
+	dnet_reset_hw(bp);
+	__dnet_set_hwaddr(bp);
+
+	config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG);
+
+	if (bp->dev->flags & IFF_PROMISC)
+		/* Copy All Frames */
+		config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC;
+	if (!(bp->dev->flags & IFF_BROADCAST))
+		/* No BroadCast */
+		config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST;
+
+	config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE |
+	    DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST |
+	    DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL |
+	    DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS;
+
+	dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config);
+
+	/* clear irq before enabling them */
+	config = dnet_readl(bp, INTR_SRC);
+
+	/* enable RX/TX interrupt, recv packet ready interrupt */
+	dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY |
+			DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR |
+			DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL |
+			DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM |
+			DNET_INTR_ENB_RX_PKTRDY, INTR_ENB);
+}
+
+static int dnet_open(struct net_device *dev)
+{
+	struct dnet *bp = netdev_priv(dev);
+
+	/* if the phy is not yet register, retry later */
+	if (!bp->phy_dev)
+		return -EAGAIN;
+
+	if (!is_valid_ether_addr(dev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	napi_enable(&bp->napi);
+	dnet_init_hw(bp);
+
+	phy_start_aneg(bp->phy_dev);
+
+	/* schedule a link state check */
+	phy_start(bp->phy_dev);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int dnet_close(struct net_device *dev)
+{
+	struct dnet *bp = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&bp->napi);
+
+	if (bp->phy_dev)
+		phy_stop(bp->phy_dev);
+
+	dnet_reset_hw(bp);
+	netif_carrier_off(dev);
+
+	return 0;
+}
+
+static inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat)
+{
+	pr_debug("%s\n", __func__);
+	pr_debug("----------------------------- RX statistics "
+		 "-------------------------------\n");
+	pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr);
+	pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err);
+	pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm);
+	pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm);
+	pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol);
+	pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err);
+	pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt);
+	pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm);
+	pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm);
+	pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast);
+	pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast);
+	pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag);
+	pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink);
+	pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib);
+	pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd);
+	pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte);
+	pr_debug("----------------------------- TX statistics "
+		 "-------------------------------\n");
+	pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast);
+	pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm);
+	pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast);
+	pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast);
+	pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag);
+	pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs);
+	pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo);
+	pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte);
+}
+
+static struct net_device_stats *dnet_get_stats(struct net_device *dev)
+{
+
+	struct dnet *bp = netdev_priv(dev);
+	struct net_device_stats *nstat = &bp->stats;
+	struct dnet_stats *hwstat = &bp->hw_stats;
+
+	/* read stats from hardware */
+	dnet_update_stats(bp);
+
+	/* Convert HW stats into netdevice stats */
+	nstat->rx_errors = (hwstat->rx_len_chk_err +
+			    hwstat->rx_lng_frm + hwstat->rx_shrt_frm +
+			    /* ignore IGP violation error
+			    hwstat->rx_ipg_viol + */
+			    hwstat->rx_crc_err +
+			    hwstat->rx_pre_shrink +
+			    hwstat->rx_drib_nib + hwstat->rx_unsup_opcd);
+	nstat->tx_errors = hwstat->tx_bad_fcs;
+	nstat->rx_length_errors = (hwstat->rx_len_chk_err +
+				   hwstat->rx_lng_frm +
+				   hwstat->rx_shrt_frm + hwstat->rx_pre_shrink);
+	nstat->rx_crc_errors = hwstat->rx_crc_err;
+	nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib;
+	nstat->rx_packets = hwstat->rx_ok_pkt;
+	nstat->tx_packets = (hwstat->tx_unicast +
+			     hwstat->tx_multicast + hwstat->tx_brdcast);
+	nstat->rx_bytes = hwstat->rx_byte;
+	nstat->tx_bytes = hwstat->tx_byte;
+	nstat->multicast = hwstat->rx_multicast;
+	nstat->rx_missed_errors = hwstat->rx_pkt_ignr;
+
+	dnet_print_pretty_hwstats(hwstat);
+
+	return nstat;
+}
+
+static int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct dnet *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_gset(phydev, cmd);
+}
+
+static int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct dnet *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_ethtool_sset(phydev, cmd);
+}
+
+static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct dnet *bp = netdev_priv(dev);
+	struct phy_device *phydev = bp->phy_dev;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+}
+
+static void dnet_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, "0");
+}
+
+static struct ethtool_ops dnet_ethtool_ops = {
+	.get_settings		= dnet_get_settings,
+	.set_settings		= dnet_set_settings,
+	.get_drvinfo		= dnet_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+};
+
+static const struct net_device_ops dnet_netdev_ops = {
+	.ndo_open		= dnet_open,
+	.ndo_stop		= dnet_close,
+	.ndo_get_stats		= dnet_get_stats,
+	.ndo_start_xmit		= dnet_start_xmit,
+	.ndo_do_ioctl		= dnet_ioctl,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+};
+
+static int __devinit dnet_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct net_device *dev;
+	struct dnet *bp;
+	struct phy_device *phydev;
+	int err = -ENXIO;
+	unsigned int mem_base, mem_size, irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no mmio resource defined\n");
+		goto err_out;
+	}
+	mem_base = res->start;
+	mem_size = resource_size(res);
+	irq = platform_get_irq(pdev, 0);
+
+	if (!request_mem_region(mem_base, mem_size, DRV_NAME)) {
+		dev_err(&pdev->dev, "no memory region available\n");
+		err = -EBUSY;
+		goto err_out;
+	}
+
+	err = -ENOMEM;
+	dev = alloc_etherdev(sizeof(*bp));
+	if (!dev) {
+		dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");
+		goto err_out;
+	}
+
+	/* TODO: Actually, we have some interesting features... */
+	dev->features |= 0;
+
+	bp = netdev_priv(dev);
+	bp->dev = dev;
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	spin_lock_init(&bp->lock);
+
+	bp->regs = ioremap(mem_base, mem_size);
+	if (!bp->regs) {
+		dev_err(&pdev->dev, "failed to map registers, aborting.\n");
+		err = -ENOMEM;
+		goto err_out_free_dev;
+	}
+
+	dev->irq = irq;
+	err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
+		       irq, err);
+		goto err_out_iounmap;
+	}
+
+	dev->netdev_ops = &dnet_netdev_ops;
+	netif_napi_add(dev, &bp->napi, dnet_poll, 64);
+	dev->ethtool_ops = &dnet_ethtool_ops;
+
+	dev->base_addr = (unsigned long)bp->regs;
+
+	bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK;
+
+	get_mac_addr(dev, dev->dev_addr);
+	__dnet_set_hwaddr(bp);
+	dnet_get_hwaddr(bp);
+
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		/* choose a random ethernet address */
+		random_ether_addr(dev->dev_addr);
+		__dnet_set_hwaddr(bp);
+	}
+
+	err = register_netdev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
+		goto err_out_free_irq;
+	}
+
+	/* register the PHY board fixup (for Marvell 88E1111) */
+	err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0,
+					 dnet_phy_marvell_fixup);
+	/* we can live without it, so just issue a warning */
+	if (err)
+		dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n");
+
+	if (dnet_mii_init(bp) != 0)
+		goto err_out_unregister_netdev;
+
+	dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n",
+	       bp->regs, mem_base, dev->irq, dev->dev_addr);
+	dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma \n",
+	       (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ",
+	       (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ",
+	       (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ",
+	       (bp->capabilities & DNET_HAS_DMA) ? "" : "no ");
+	phydev = bp->phy_dev;
+	dev_info(&pdev->dev, "attached PHY driver [%s] "
+	       "(mii_bus:phy_addr=%s, irq=%d)\n",
+	       phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
+	return 0;
+
+err_out_unregister_netdev:
+	unregister_netdev(dev);
+err_out_free_irq:
+	free_irq(dev->irq, dev);
+err_out_iounmap:
+	iounmap(bp->regs);
+err_out_free_dev:
+	free_netdev(dev);
+err_out:
+	return err;
+}
+
+static int __devexit dnet_remove(struct platform_device *pdev)
+{
+
+	struct net_device *dev;
+	struct dnet *bp;
+
+	dev = platform_get_drvdata(pdev);
+
+	if (dev) {
+		bp = netdev_priv(dev);
+		if (bp->phy_dev)
+			phy_disconnect(bp->phy_dev);
+		mdiobus_unregister(bp->mii_bus);
+		kfree(bp->mii_bus->irq);
+		mdiobus_free(bp->mii_bus);
+		unregister_netdev(dev);
+		free_irq(dev->irq, dev);
+		iounmap(bp->regs);
+		free_netdev(dev);
+	}
+
+	return 0;
+}
+
+static struct platform_driver dnet_driver = {
+	.probe		= dnet_probe,
+	.remove		= __devexit_p(dnet_remove),
+	.driver		= {
+		.name		= "dnet",
+	},
+};
+
+static int __init dnet_init(void)
+{
+	return platform_driver_register(&dnet_driver);
+}
+
+static void __exit dnet_exit(void)
+{
+	platform_driver_unregister(&dnet_driver);
+}
+
+module_init(dnet_init);
+module_exit(dnet_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Dave DNET Ethernet driver");
+MODULE_AUTHOR("Ilya Yanok <yanok@emcraft.com>, "
+	      "Matteo Vit <matteo.vit@dave.eu>");
diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h
new file mode 100644
index 0000000..494c2f9
--- /dev/null
+++ b/drivers/net/dnet.h
@@ -0,0 +1,226 @@ 
+/*
+ * Dave DNET Ethernet Controller driver
+ *
+ * Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _DNET_H
+#define _DNET_H
+
+#define DRV_NAME		"dnet"
+#define DRV_VERSION		"0.9.1"
+#define PFX				DRV_NAME ": "
+
+/* Register access macros */
+#define dnet_writel(port, value, reg)	\
+	writel((value), (port)->regs + DNET_##reg)
+#define dnet_readl(port, reg)	readl((port)->regs + DNET_##reg)
+
+/* ALL DNET FIFO REGISTERS */
+#define DNET_RX_LEN_FIFO		0x000	/* RX_LEN_FIFO */
+#define DNET_RX_DATA_FIFO		0x004	/* RX_DATA_FIFO */
+#define DNET_TX_LEN_FIFO		0x008	/* TX_LEN_FIFO */
+#define DNET_TX_DATA_FIFO		0x00C	/* TX_DATA_FIFO */
+
+/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */
+#define DNET_VERCAPS			0x100	/* VERCAPS */
+#define DNET_INTR_SRC			0x104	/* INTR_SRC */
+#define DNET_INTR_ENB			0x108	/* INTR_ENB */
+#define DNET_RX_STATUS			0x10C	/* RX_STATUS */
+#define DNET_TX_STATUS			0x110	/* TX_STATUS */
+#define DNET_RX_FRAMES_CNT		0x114	/* RX_FRAMES_CNT */
+#define DNET_TX_FRAMES_CNT		0x118	/* TX_FRAMES_CNT */
+#define DNET_RX_FIFO_TH			0x11C	/* RX_FIFO_TH */
+#define DNET_TX_FIFO_TH			0x120	/* TX_FIFO_TH */
+#define DNET_SYS_CTL			0x124	/* SYS_CTL */
+#define DNET_PAUSE_TMR			0x128	/* PAUSE_TMR */
+#define DNET_RX_FIFO_WCNT		0x12C	/* RX_FIFO_WCNT */
+#define DNET_TX_FIFO_WCNT		0x130	/* TX_FIFO_WCNT */
+
+/* ALL DNET MAC REGISTERS */
+#define DNET_MACREG_DATA		0x200	/* Mac-Reg Data */
+#define DNET_MACREG_ADDR		0x204	/* Mac-Reg Addr  */
+
+/* ALL DNET RX STATISTICS COUNTERS  */
+#define DNET_RX_PKT_IGNR_CNT		0x300
+#define DNET_RX_LEN_CHK_ERR_CNT		0x304
+#define DNET_RX_LNG_FRM_CNT		0x308
+#define DNET_RX_SHRT_FRM_CNT		0x30C
+#define DNET_RX_IPG_VIOL_CNT		0x310
+#define DNET_RX_CRC_ERR_CNT		0x314
+#define DNET_RX_OK_PKT_CNT		0x318
+#define DNET_RX_CTL_FRM_CNT		0x31C
+#define DNET_RX_PAUSE_FRM_CNT		0x320
+#define DNET_RX_MULTICAST_CNT		0x324
+#define DNET_RX_BROADCAST_CNT		0x328
+#define DNET_RX_VLAN_TAG_CNT		0x32C
+#define DNET_RX_PRE_SHRINK_CNT		0x330
+#define DNET_RX_DRIB_NIB_CNT		0x334
+#define DNET_RX_UNSUP_OPCD_CNT		0x338
+#define DNET_RX_BYTE_CNT		0x33C
+
+/* DNET TX STATISTICS COUNTERS */
+#define DNET_TX_UNICAST_CNT		0x400
+#define DNET_TX_PAUSE_FRM_CNT		0x404
+#define DNET_TX_MULTICAST_CNT		0x408
+#define DNET_TX_BRDCAST_CNT		0x40C
+#define DNET_TX_VLAN_TAG_CNT		0x410
+#define DNET_TX_BAD_FCS_CNT		0x414
+#define DNET_TX_JUMBO_CNT		0x418
+#define DNET_TX_BYTE_CNT		0x41C
+
+/* SOME INTERNAL MAC-CORE REGISTER */
+#define DNET_INTERNAL_MODE_REG		0x0
+#define DNET_INTERNAL_RXTX_CONTROL_REG	0x2
+#define DNET_INTERNAL_MAX_PKT_SIZE_REG	0x4
+#define DNET_INTERNAL_IGP_REG		0x8
+#define DNET_INTERNAL_MAC_ADDR_0_REG	0xa
+#define DNET_INTERNAL_MAC_ADDR_1_REG	0xc
+#define DNET_INTERNAL_MAC_ADDR_2_REG	0xe
+#define DNET_INTERNAL_TX_RX_STS_REG	0x12
+#define DNET_INTERNAL_GMII_MNG_CTL_REG	0x14
+#define DNET_INTERNAL_GMII_MNG_DAT_REG	0x16
+
+#define DNET_INTERNAL_GMII_MNG_CMD_FIN	(1 << 14)
+
+#define DNET_INTERNAL_WRITE		(1 << 31)
+
+/* MAC-CORE REGISTER FIELDS */
+
+/* MAC-CORE MODE REGISTER FIELDS */
+#define DNET_INTERNAL_MODE_GBITEN			(1 << 0)
+#define DNET_INTERNAL_MODE_FCEN				(1 << 1)
+#define DNET_INTERNAL_MODE_RXEN				(1 << 2)
+#define DNET_INTERNAL_MODE_TXEN				(1 << 3)
+
+/* MAC-CORE RXTX CONTROL REGISTER FIELDS */
+#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME		(1 << 8)
+#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST		(1 << 7)
+#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST		(1 << 4)
+#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE		(1 << 3)
+#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS		(1 << 2)
+#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS		(1 << 1)
+#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC		(1 << 0)
+#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL		(1 << 6)
+#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP	(1 << 5)
+
+/* SYSTEM CONTROL REGISTER FIELDS */
+#define DNET_SYS_CTL_IGNORENEXTPKT			(1 << 0)
+#define DNET_SYS_CTL_SENDPAUSE				(1 << 2)
+#define DNET_SYS_CTL_RXFIFOFLUSH			(1 << 3)
+#define DNET_SYS_CTL_TXFIFOFLUSH			(1 << 4)
+
+/* TX STATUS REGISTER FIELDS */
+#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY		(1 << 2)
+#define DNET_TX_STATUS_FIFO_ALMOST_FULL			(1 << 1)
+
+/* INTERRUPT SOURCE REGISTER FIELDS */
+#define DNET_INTR_SRC_TX_PKTSENT			(1 << 0)
+#define DNET_INTR_SRC_TX_FIFOAF				(1 << 1)
+#define DNET_INTR_SRC_TX_FIFOAE				(1 << 2)
+#define DNET_INTR_SRC_TX_DISCFRM			(1 << 3)
+#define DNET_INTR_SRC_TX_FIFOFULL			(1 << 4)
+#define DNET_INTR_SRC_RX_CMDFIFOAF			(1 << 8)
+#define DNET_INTR_SRC_RX_CMDFIFOFF			(1 << 9)
+#define DNET_INTR_SRC_RX_DATAFIFOFF			(1 << 10)
+#define DNET_INTR_SRC_TX_SUMMARY			(1 << 16)
+#define DNET_INTR_SRC_RX_SUMMARY			(1 << 17)
+#define DNET_INTR_SRC_PHY				(1 << 19)
+
+/* INTERRUPT ENABLE REGISTER FIELDS */
+#define DNET_INTR_ENB_TX_PKTSENT			(1 << 0)
+#define DNET_INTR_ENB_TX_FIFOAF				(1 << 1)
+#define DNET_INTR_ENB_TX_FIFOAE				(1 << 2)
+#define DNET_INTR_ENB_TX_DISCFRM			(1 << 3)
+#define DNET_INTR_ENB_TX_FIFOFULL			(1 << 4)
+#define DNET_INTR_ENB_RX_PKTRDY				(1 << 8)
+#define DNET_INTR_ENB_RX_FIFOAF				(1 << 9)
+#define DNET_INTR_ENB_RX_FIFOERR			(1 << 10)
+#define DNET_INTR_ENB_RX_ERROR				(1 << 11)
+#define DNET_INTR_ENB_RX_FIFOFULL			(1 << 12)
+#define DNET_INTR_ENB_RX_FIFOAE				(1 << 13)
+#define DNET_INTR_ENB_TX_SUMMARY			(1 << 16)
+#define DNET_INTR_ENB_RX_SUMMARY			(1 << 17)
+#define DNET_INTR_ENB_GLOBAL_ENABLE			(1 << 18)
+
+/* default values:
+ * almost empty = less than one full sized ethernet frame (no jumbo) inside
+ * the fifo almost full = can write less than one full sized ethernet frame
+ * (no jumbo) inside the fifo
+ */
+#define DNET_CFG_TX_FIFO_FULL_THRES	25
+#define DNET_CFG_RX_FIFO_FULL_THRES	20
+
+/*
+ * Capabilities. Used by the driver to know the capabilities that the ethernet
+ * controller inside the FPGA have.
+ */
+
+#define DNET_HAS_MDIO		(1 << 0)
+#define DNET_HAS_IRQ		(1 << 1)
+#define DNET_HAS_GIGABIT	(1 << 2)
+#define DNET_HAS_DMA		(1 << 3)
+
+#define DNET_HAS_MII		(1 << 4) /* or GMII */
+#define DNET_HAS_RMII		(1 << 5) /* or RGMII */
+
+#define DNET_CAPS_MASK		0xFFFF
+
+#define DNET_FIFO_SIZE		1024 /* 1K x 32 bit */
+#define DNET_FIFO_TX_DATA_AF_TH	(DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */
+#define DNET_FIFO_TX_DATA_AE_TH	384
+
+#define DNET_FIFO_RX_CMD_AF_TH	(1 << 16) /* just one frame inside the FIFO */
+
+/*
+ * Hardware-collected statistics.
+ */
+struct dnet_stats {
+	u32 rx_pkt_ignr;
+	u32 rx_len_chk_err;
+	u32 rx_lng_frm;
+	u32 rx_shrt_frm;
+	u32 rx_ipg_viol;
+	u32 rx_crc_err;
+	u32 rx_ok_pkt;
+	u32 rx_ctl_frm;
+	u32 rx_pause_frm;
+	u32 rx_multicast;
+	u32 rx_broadcast;
+	u32 rx_vlan_tag;
+	u32 rx_pre_shrink;
+	u32 rx_drib_nib;
+	u32 rx_unsup_opcd;
+	u32 rx_byte;
+	u32 tx_unicast;
+	u32 tx_pause_frm;
+	u32 tx_multicast;
+	u32 tx_brdcast;
+	u32 tx_vlan_tag;
+	u32 tx_bad_fcs;
+	u32 tx_jumbo;
+	u32 tx_byte;
+};
+
+struct dnet {
+	void __iomem			*regs;
+	spinlock_t			lock;
+	struct platform_device	*pdev;
+	struct net_device		*dev;
+	struct net_device_stats	stats;
+	struct dnet_stats		hw_stats;
+	unsigned int			capabilities; /* read from FPGA */
+	struct napi_struct		napi;
+
+	/* PHY stuff */
+	struct mii_bus			*mii_bus;
+	struct phy_device		*phy_dev;
+	unsigned int			link;
+	unsigned int			speed;
+	unsigned int			duplex;
+};
+
+#endif /* _DNET_H */