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 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 ...
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>
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.
+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
--
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 | 994 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/dnet.h | 225 ++++++++++++ 4 files changed, 1231 insertions(+), 0 deletions(-) create mode 100644 drivers/net/dnet.c create mode 100644 drivers/net/dnet.h 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..92c3bd3 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,994 @@ +/* + * 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 ...
From: Ilya Yanok <yanok@emcraft.com>
Applied, but I had to add the following patch to fix warnings
and actual errors on 64-bit.
dnet: Fix warnings on 64-bit.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dnet.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c
index 92c3bd3..4b96974 100644
--- a/drivers/net/dnet.c
+++ b/drivers/net/dnet.c
@@ -553,8 +553,8 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
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);
+ pr_debug("start_xmit: len %u head %p data %p\n",
+ skb->len, skb->head, skb->data);
dnet_print_skb(skb);
/* frame size (words) */
@@ -564,11 +564,11 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_status = dnet_readl(bp, TX_STATUS);
- bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC);
+ bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL);
wrsz = (u32) skb->len + 3;
- wrsz += ((u32) skb->data) & 0x3;
+ wrsz += ((unsigned long) skb->data) & 0x3;
wrsz >>= 2;
- tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len;
+ tx_cmd = ((((unsigned long)(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))) {
--
1.6.2
--
On Wed, 11 Mar 2009 05:29:09 +0300 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. --
Hi, Except for root over nfs. Ok, the answer to this is usually 'use initrd', but this is still a pita on embedded systems. 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 | --
From: Sascha Hauer <s.hauer@pengutronix.de> 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 -- 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 | --
Dear David, 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 -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de "If God had wanted us to use the metric system, Jesus would have had 10 apostles." --
Hi Wolfgang, 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 -- 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 | --
From: Wolfgang Denk <wd@denx.de> 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 --
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 -- 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 | --
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. --=20 "rm -rf" only sounds scary if you don't have backups
From: Riku Voipio <riku.voipio@iki.fi> 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. --
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
--
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'.) --
On Wed, 11 Mar 2009 21:56:06 +0100 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
--
From: Christer Weinigel <christer@weinigel.se> 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. --
Yes, ridiculous in the complexity of the workarounds for not having a 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 Which is actually what I'm doing, except that it's easier to hack that 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 --
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 -- 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 | --
From: Christer Weinigel <christer@weinigel.se> Yep, and you can parse that and execute the appropriate ifconfig command from userspace in your initial ramdisk. --
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 Then dont, if you are only guaranteed one interface, use the kernel command 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 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 :) ). --
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 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 ...
From: Christer Weinigel <christer@weinigel.se> 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 --
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 --
dracut : http://lwn.net/Articles/317793/ Dan --
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 --
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 -- 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 | --
The objection "we're not taking that because it should go in initrd" would go away. -- Jamie --
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. --
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 --
Dear Sascha Hauer, 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 -- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Any sufficiently advanced technology is indistinguishable from magic. - Arthur C. Clarke --
I'm looking forward to the first patches on Linux Arm Kernel. That's gonna be even more fun than this thread ;) 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 | --
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 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 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 Wheres all the extra work? You've given a few examples here, and they're all 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 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 ...
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 In my opion, having a "hwaddrs=eth0=00:de:ad:be:ef:01" would be 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 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 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 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 ...
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 I never said you can't still use that command line option to implement this 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 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? 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 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 ...
just checked: disabling CONFIG_IP_PNP and CONFIG_IP_PNP_DHCP saves me 4456 bytes of zImage size on an ARM/PXA build 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 | --
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, 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 --
About 4k apparently. See the difference from "400k compressed?". 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 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). 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 ...
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 --
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 --
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. --
In other words, glibc doesn't work on some embedded targets even if 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! 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 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 --
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 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 --
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. --
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 --
From: Michael Cashwell <mboards@prograde.net> 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. --
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 --
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 -- 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 | --
From: Robert Schwebel <r.schwebel@pengutronix.de> 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. --
