diff -uNr ./CREDITS ../linux-2.3-new/CREDITS --- ./CREDITS Mon Apr 24 23:39:33 2000 +++ ../linux-2.3-new/CREDITS Mon May 15 12:52:01 2000 @@ -2056,6 +2056,15 @@ S: 9725 GA Groningen S: The Netherlands +N: Pekka Riikonen +E: priikone@poseidon.pspt.fi +E: priikone@ssh.com +D: Random kernel hacking and bug fixes +D: International kernel patch project +S: Kasarmikatu 11 A4 +S: 70110 Kuopio +S: Finland + N: William E. Roadcap E: roadcapw@cfw.com W: http://www.cfw.com/~roadcapw diff -uNr ./drivers/net/net_init.c ../linux-2.3-new/drivers/net/net_init.c --- ./drivers/net/net_init.c Wed May 3 11:45:19 2000 +++ ../linux-2.3-new/drivers/net/net_init.c Mon May 15 09:01:08 2000 @@ -115,14 +115,17 @@ * Allocate a name */ - if (dev->name[0] == '\0' || dev->name[0] == ' ') - { - if(dev_alloc_name(dev, mask)<0) - { - if(new_device) - kfree(dev); - return NULL; + if (dev->name[0] == '\0' || dev->name[0] == ' ') { + strcpy(dev->name, mask); + if (!netdev_boot_setup_check(dev)) { + if (dev_alloc_name(dev, mask)<0) { + if (new_device) + kfree(dev); + return NULL; + } } + } else { + netdev_boot_setup_check(dev); } /* diff -uNr ./include/linux/netdevice.h ../linux-2.3-new/include/linux/netdevice.h --- ./include/linux/netdevice.h Fri May 12 22:17:12 2000 +++ ../linux-2.3-new/include/linux/netdevice.h Mon May 15 12:58:01 2000 @@ -13,6 +13,7 @@ * Donald J. Becker, * Alan Cox, * Bjorn Ekwall. + * Pekka Riikonen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -193,6 +194,17 @@ /* + * This structure holds at boot time configured netdevice settings. They + * are then used in the device probing. + */ +struct netdev_boot_setup { + char name[IFNAMSIZ]; + struct ifmap map; +}; +#define NETDEV_BOOT_SETUP_MAX 8 + + +/* * The DEVICE structure. * Actually, this whole structure is a big mistake. It mixes I/O * data with strictly "high-level" data, and it has to know about @@ -389,8 +401,11 @@ extern struct net_device loopback_dev; /* The loopback */ extern struct net_device *dev_base; /* All devices */ -extern rwlock_t dev_base_lock; /* Device list lock */ +extern rwlock_t dev_base_lock; /* Device list lock */ +extern struct netdev_boot_setup dev_boot_setup[]; +extern int netdev_boot_setup_add(char *name, struct ifmap *map); +extern int netdev_boot_setup_check(struct net_device *dev); extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr); extern void dev_add_pack(struct packet_type *pt); extern void dev_remove_pack(struct packet_type *pt); diff -uNr ./net/core/dev.c ../linux-2.3-new/net/core/dev.c --- ./net/core/dev.c Tue May 9 08:21:58 2000 +++ ../linux-2.3-new/net/core/dev.c Mon May 15 13:30:58 2000 @@ -17,6 +17,7 @@ * David Hinds * Alexey Kuznetsov * Adam Sulmicki + * Pekka Riikonen * * Changes: * Alan Cox : device private ioctl copies fields back. @@ -56,6 +57,7 @@ * A network device unload needs to purge * the backlog queue. * Paul Rusty Russell : SIOCSIFNAME + * Pekka Riikonen : Netdev boot-time settings code */ #include @@ -250,6 +252,120 @@ printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt); } +/****************************************************************************** + + Device Boot-time Settings Routines + +*******************************************************************************/ + +/* Boot time configuration table */ +struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX]; + +/** + * netdev_boot_setup_add - add new setup entry + * @name: name of the device + * @map: configured settings for the device + * + * Adds new setup entry to the dev_boot_setup list. The function + * returns 0 on error and 1 on success. This is a generic routine to + * all netdevices. + */ +int netdev_boot_setup_add(char *name, struct ifmap *map) +{ + struct netdev_boot_setup *s; + int i; + + s = dev_boot_setup; + for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) { + if (s[i].name[0] == '\0' || s[i].name[0] == ' ') { + memset(s[i].name, 0, sizeof(s[i].name)); + strcpy(s[i].name, name); + memcpy(&s[i].map, map, sizeof(s[i].map)); + break; + } + } + + if (i >= NETDEV_BOOT_SETUP_MAX) + return 0; + + return 1; +} + +/** + * netdev_boot_setup_check - check boot time settings + * @dev: the netdevice + * + * Check boot time settings for the device. If device's name is a + * mask (eg. eth%d) and settings are found then this will allocate + * name for the device. The found settings are set for the device + * to be used later in the device probing. Returns 0 if no settings + * found, 1 if they are. + */ +int netdev_boot_setup_check(struct net_device *dev) +{ + struct netdev_boot_setup *s; + char buf[IFNAMSIZ + 1]; + int i, mask = 0; + + memset(buf, 0, sizeof(buf)); + strcpy(buf, dev->name); + if (strchr(dev->name, '%')) { + *strchr(buf, '%') = '\0'; + mask = 1; + } + + s = dev_boot_setup; + for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) { + if (s[i].name[0] != '\0' && s[i].name[0] != ' ' && + !strncmp(buf, s[i].name, mask ? strlen(buf) : + strlen(s[i].name))) { + if (__dev_get_by_name(s[i].name)) { + if (!mask) + return 0; + continue; + } + memset(dev->name, 0, IFNAMSIZ); + strcpy(dev->name, s[i].name); + dev->irq = s[i].map.irq; + dev->base_addr = s[i].map.base_addr; + dev->mem_start = s[i].map.mem_start; + dev->mem_end = s[i].map.mem_end; + return 1; + } + } + + return 0; +} + +/* + * Saves at boot time configured settings for any netdevice. + */ +static int __init netdev_boot_setup(char *str) +{ + int ints[5]; + struct ifmap map; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (!str || !*str) + return 0; + + /* Save settings */ + memset(&map, -1, sizeof(map)); + if (ints[0] > 0) + map.irq = ints[1]; + if (ints[0] > 1) + map.base_addr = ints[2]; + if (ints[0] > 2) + map.mem_start = ints[3]; + if (ints[0] > 3) + map.mem_end = ints[4]; + + /* Add new entry to the list */ + return netdev_boot_setup_add(str, &map); +} + +__setup("netdev=", netdev_boot_setup); + /***************************************************************************************** Device Interface Subroutines @@ -2365,12 +2481,19 @@ dev->xmit_lock_owner = -1; dev->iflink = -1; dev_hold(dev); - /* - * We can allocate the name ahead of time. If the - * init fails the name will be reissued correctly. + + /* + * Check boot time settings for the device. */ - if (strchr(dev->name, '%')) - dev_alloc_name(dev, dev->name); + if (!netdev_boot_setup_check(dev)) { + /* + * No settings found - allocate name. If the init() + * fails the name will be reissued correctly. + */ + if (strchr(dev->name, '%')) + dev_alloc_name(dev, dev->name); + } + if (dev->init && dev->init(dev)) { /* * It failed to come up. Unhook it. diff -uNr ./net/ethernet/eth.c ../linux-2.3-new/net/ethernet/eth.c --- ./net/ethernet/eth.c Sat Jan 22 21:54:57 2000 +++ ../linux-2.3-new/net/ethernet/eth.c Mon May 15 13:19:21 2000 @@ -63,31 +63,25 @@ static int __init eth_setup(char *str) { int ints[5]; - struct net_device *d; + struct ifmap map; str = get_options(str, ARRAY_SIZE(ints), ints); - if (!str || !*str) return 0; - d = dev_base; - while (d) - { - if (!strcmp(str,d->name)) - { - if (ints[0] > 0) - d->irq=ints[1]; - if (ints[0] > 1) - d->base_addr=ints[2]; - if (ints[0] > 2) - d->mem_start=ints[3]; - if (ints[0] > 3) - d->mem_end=ints[4]; - break; - } - d=d->next; - } - return 1; + /* Save settings */ + memset(&map, -1, sizeof(map)); + if (ints[0] > 0) + map.irq = ints[1]; + if (ints[0] > 1) + map.base_addr = ints[2]; + if (ints[0] > 2) + map.mem_start = ints[3]; + if (ints[0] > 3) + map.mem_end = ints[4]; + + /* Add new entry to the list */ + return netdev_boot_setup_add(str, &map); } __setup("ether=", eth_setup);