diff options
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch')
-rw-r--r-- | packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch | 570 |
1 files changed, 0 insertions, 570 deletions
diff --git a/packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch b/packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch deleted file mode 100644 index 72b9fa9a7d..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch +++ /dev/null @@ -1,570 +0,0 @@ -Ethernet MAC repository. - -Some ethernet controllers have no built-in way of obtaining an -appropriate Ethernet MAC address. Such controllers have to be -initialised in a board-specific way, depending on how the allocated -MAC is stored. The MAC repository provides a set of APIs and a -proc entry (/proc/net/maclist) to store MAC values from the board -so that such drivers can obtain a MAC address without board-specific -code. - -Signed-off-by: John Bowler <jbowler@acm.org> - -diff -rup linux-2.6.15.1/.pc/91-maclist.patch/drivers/net/Kconfig linux-2.6.15.1/drivers/net/Kconfig ---- linux-2.6.15/drivers/net/Kconfig 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/net/Kconfig 1970-01-01 00:00:00.000000000 +0000 -@@ -166,6 +166,21 @@ config NET_ETHERNET - kernel: saying N will just cause the configurator to skip all - the questions about Ethernet network cards. If unsure, say N. - -+config MACLIST -+ tristate "Ethernet MAC repository" -+ depends on NET_ETHERNET -+ help -+ Some ethernet controllers have no built-in way of obtaining an -+ appropriate Ethernet MAC address. Such controllers have to be -+ initialised in a board-specific way, depending on how the allocated -+ MAC is stored. The MAC repository provides a set of APIs and a -+ proc entry (/proc/net/maclist) to store MAC values from the board -+ so that such drivers can obtain a MAC address without board-specific -+ code. You do not need to enable this device - it will be selected -+ automatically by any device which requires it. It is only useful -+ to enable it manually when building a device driver independently -+ of the kernel build. -+ - config MII - tristate "Generic Media Independent Interface device support" - depends on NET_ETHERNET -diff -rup linux-2.6.15.1/.pc/91-maclist.patch/drivers/net/Makefile linux-2.6.15.1/drivers/net/Makefile ---- linux-2.6.15/drivers/net/Makefile 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/net/Makefile 1970-01-01 00:00:00.000000000 +0000 -@@ -70,6 +70,7 @@ obj-$(CONFIG_RIONET) += rionet.o - # end link order section - # - -+obj-$(CONFIG_MACLIST) += maclist.o - obj-$(CONFIG_MII) += mii.o - obj-$(CONFIG_PHYLIB) += phy/ - -diff -rup linux-2.6.15.1/.pc/91-maclist.patch/drivers/net/maclist.c linux-2.6.15.1/drivers/net/maclist.c ---- linux-2.6.15/drivers/net/maclist.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/net/maclist.c 1970-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,465 @@ -+/* -+ * drivers/net/maclist.c -+ * -+ * a simple driver to remember ethernet MAC values -+ * -+ * Some Ethernet hardware implementations have no built-in -+ * storage for allocated MAC values - an example is the Intel -+ * IXP420 chip which has support for Ethernet but no defined -+ * way of storing allocated MAC values. With such hardware -+ * different board level implementations store the allocated -+ * MAC (or MACs) in different ways. Rather than put board -+ * level code into a specific Ethernet driver this driver -+ * provides a generally accessible repository for the MACs -+ * which can be written by board level code and read by the -+ * driver. -+ * -+ * The implementation also allows user level programs to -+ * access the MAC information in /proc/net/maclist. This is -+ * useful as it allows user space code to use the MAC if it -+ * is not used by a built-in driver. -+ * -+ * Copyright (C) 2005 John Bowler -+ * Author: John Bowler <jbowler@acm.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ * 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. -+ */ -+ -+/* -+ * External interfaces: -+ * Interfaces to linux kernel (and modules) -+ * maclist_add: add a single MAC, sequenced with a single -+ * writer lock (reads may happen simultaneously -+ * because of the way the list is built) -+ * maclist_count: total number of MACs stored -+ * maclist_read: read a MAC 0..(maclist_count-1). Call this -+ * to get a specific MAC. If the argument is -+ * a new key and all the allocaed MACs have been -+ * assigned a random but valid MAC will be return -+ * (and this will be stored for later retrieval -+ * under the given key.) -+ * -+ * Sequencing: -+ * The MAC ids must be added before any driver tries to use them -+ * (this is obvious isn't it?) This can be made to happen by -+ * sequencing the initcalls correctly. The module or kernel -+ * parameters have been handled before any init call happens. -+ * The important trick here is to ensure that the platform -+ * initialises any devices with MAC ids *before* any devices -+ * which might use them. -+ * -+ * When this code is a module any other module which adds a -+ * MAC should be modprobed before modules for ethernet -+ * devices. -+ * -+ * The failure case is 'soft' - the device will get a valid, but -+ * random, MAC and the real allocated MACs will never get used. -+ * This can be seen by looking at the list of ids in sysfs (there -+ * will be extra, random, ones after the allocated ones). -+ * -+ * Recommendations: -+ * For ethernet drivers which are known to be the sole driver on -+ * the board (without a built in MAC) and where the number of -+ * devices driven is known simply use an index 0..(n-1) as a -+ * key for each of the n devices. -+ * -+ * This is the common case, it works where one driver handles -+ * multiple devices so long as the total number of devices can -+ * be determined reliably. It is sufficient merely to maintain -+ * a global count of the number of devices initialised so far, -+ * just so long as the initialisation order is consistent. -+ * -+ * When the driver is generic and the board may be populated with -+ * other devices which allocate MACs from the maclist pool and -+ * use different drivers create a random key and compile this into -+ * the code. Use this as the base for all devices from the driver -+ * (using a global device count for this driver if necessary). -+ * -+ * With the second strategy the assignment of MACs will depend on -+ * the order of initialisation of the different drivers. To avoid -+ * this provide a kernel (or module) command line parameter to -+ * specify a base index and (optional) count for each driver or -+ * pass in a (struct resource) with the start and end of the keys -+ * to pass to maclist_read. Either method allows the higher levels -+ * (boot loader or machine description) to specify which MACs in -+ * the list to assign to each device. -+ */ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/spinlock.h> -+#include <linux/etherdevice.h> -+#include <linux/proc_fs.h> -+#include <linux/errno.h> -+ -+#include <net/maclist.h> -+ -+#define MACLIST_NAME "maclist" -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("MAC list repository"); -+MODULE_LICENSE("GPL"); -+ -+typedef struct maclist_entry { -+ struct maclist_entry *next; /* Linked list, first first */ -+ u32 key; /* count or key for this entry */ -+ u16 flags; -+ u8 id[6]; /* 6 byte Ethernet MAC */ -+} maclist_entry_t; -+ -+/* -+ * flag definitions -+ */ -+#define MACLIST_ALLOCATED 1 -+#define MACLIST_RANDOM 2 -+ -+/* Access to this list is protected by a standard rwlock_t. */ -+static maclist_entry_t *maclist_list = 0; -+ -+static DEFINE_RWLOCK(maclist_lock); -+ -+/* -+ * External interfaces. -+ * -+ * Add a single entry, returns 0 on success else an error -+ * code. Checks for invalid addresses. -+ */ -+int maclist_add(const u8 new_id[6]) { -+ maclist_entry_t *new_entry, **tail; -+ -+ if (new_id == 0 || !is_valid_ether_addr(new_id)) { -+ printk(KERN_ERR MACLIST_NAME ": invalid ethernet address\n"); -+ return -EINVAL; -+ } -+ new_entry = kmalloc(sizeof *new_entry, GFP_KERNEL); -+ if (new_entry == 0) -+ return -ENOMEM; -+ new_entry->next = 0; -+ new_entry->key = 0; -+ new_entry->flags = 0; -+ memcpy(new_entry->id, new_id, sizeof new_entry->id); -+ -+ tail = &maclist_list; -+ -+ write_lock(&maclist_lock); -+ while (*tail != 0) -+ tail = &(*tail)->next; -+ *tail = new_entry; -+ write_unlock(&maclist_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL(maclist_add); -+ -+/* -+ * Return the current entry count. -+ */ -+static int maclist_count_unlocked(void) { -+ maclist_entry_t *tail = maclist_list; -+ int count = 0; -+ -+ while (tail != 0) { -+ tail = tail->next; -+ ++count; -+ } -+ -+ return count; -+} -+ -+int maclist_count(void) { -+ int count; -+ -+ read_lock(&maclist_lock); -+ count = maclist_count_unlocked(); -+ read_unlock(&maclist_lock); -+ -+ return count; -+} -+EXPORT_SYMBOL(maclist_count); -+ -+/* -+ * Return the ID with the given key (the key is allocated -+ * to an entry if not found). -+ */ -+void maclist_read(u8 (*id)[6], u32 key) { -+ int count, index; -+ maclist_entry_t *entry, *entry_to_allocate; -+ -+ /* Do this under a write lock to avoid the SMP race -+ * where we find the key isn't assigned, drop the lock, -+ * have another CPU assign it, then assign it on this -+ * CPU too - very bad... -+ */ -+ write_lock(&maclist_lock); -+ count = maclist_count_unlocked(); -+ index = key % count; /* index of entry to allocate */ -+ entry_to_allocate = 0; -+ -+ entry = maclist_list; -+ while (entry != 0) { -+ if ((entry->flags & MACLIST_ALLOCATED) != 0) { -+ if (entry->key == key) { -+ /* Found it, use this entry. */ -+ entry_to_allocate = entry; -+ break; -+ } -+ } else if (entry_to_allocate == 0 || count <= index) { -+ /* The algorithm is to try for entry -+ * (key % count), but if this isn't possible -+ * return the prior unallocated entry. -+ */ -+ entry_to_allocate = entry; -+ } -+ -+ ++count; -+ entry = entry->next; -+ } -+ -+ /* Use entry_to_allocate, allocating it if necessary. */ -+ if (entry_to_allocate != 0) { -+ if ((entry_to_allocate->flags & MACLIST_ALLOCATED) == 0) { -+ entry_to_allocate->key = key; -+ entry_to_allocate->flags |= MACLIST_ALLOCATED; -+ } -+ memcpy(id, entry_to_allocate->id, sizeof *id); -+ } -+ write_unlock(&maclist_lock); -+ -+ if (entry_to_allocate == 0) { -+ /* No unallocated entries. Make a new one and return it. */ -+ printk(KERN_INFO MACLIST_NAME ": adding random MAC for key 0x%x\n", key); -+ random_ether_addr(*id); -+ if (maclist_add(*id) == 0) -+ maclist_read(id, key); -+ } -+} -+EXPORT_SYMBOL(maclist_read); -+ -+/* -+ * Parameter parsing. The option string is a list of MAC -+ * addresses, comma separated. (The parsing really should -+ * be somewhere central...) -+ */ -+static int __init maclist_setup(const char *param) { -+ int bytes = 0, seen_a_digit = 0; -+ u8 id[6]; -+ -+ memset(id, 0, sizeof id); -+ -+ if (param) do { -+ int digit = -1; -+ switch (*param) { -+ case '0': digit = 0; break; -+ case '1': digit = 1; break; -+ case '2': digit = 2; break; -+ case '3': digit = 3; break; -+ case '4': digit = 4; break; -+ case '5': digit = 5; break; -+ case '6': digit = 6; break; -+ case '7': digit = 7; break; -+ case '8': digit = 8; break; -+ case '9': digit = 9; break; -+ case 'a': case 'A': digit = 10; break; -+ case 'b': case 'B': digit = 11; break; -+ case 'c': case 'C': digit = 12; break; -+ case 'd': case 'D': digit = 13; break; -+ case 'e': case 'E': digit = 14; break; -+ case 'f': case 'F': digit = 15; break; -+ case ':': -+ if (seen_a_digit) -+ bytes = (bytes+1) & ~1; -+ else -+ bytes += 2; /* i.e. ff::ff is ff:00:ff */ -+ seen_a_digit = 0; -+ break; -+ case 0: -+ if (bytes == 0) /* nothing new seen so far */ -+ return 0; -+ /*fall through*/ -+ case ',': case ';': -+ if (bytes > 0) -+ bytes = 12; /* i.e. all trailing bytes 0 */ -+ break; -+ default: -+ printk(KERN_ERR MACLIST_NAME ": invalid character <%c[%d]>\n", -+ *param, *param); -+ return -EINVAL; -+ } -+ -+ if (digit >= 0) { -+ id[bytes>>1] = (id[bytes>>1] << 4) + digit; break; -+ ++bytes; -+ seen_a_digit = 1; -+ } -+ -+ if (bytes >= 12) { -+ int rc = maclist_add(id); -+ if (unlikely(rc)) -+ return rc; -+ bytes = 0; -+ seen_a_digit = 0; -+ memset(id, 0, sizeof id); -+ if (*param == 0) -+ return 0; -+ } -+ ++param; -+ } while (1); -+ -+ return 0; -+} -+ -+#if (defined CONFIG_PROC_FS) || (defined MODULE) -+/* -+ * Character device read -+ */ -+static int maclist_getchar(off_t n) { -+ static char xdigit[16] = "0123456789abcdef"; -+ maclist_entry_t *head = maclist_list; -+ int b; -+ -+ do { -+ if (head == 0) -+ return -1; -+ if (n < 18) -+ break; -+ head = head->next; -+ n -= 18; -+ } while (1); -+ -+ if (n == 17) -+ return '\n'; -+ -+ b = n/3; -+ switch (n - b*3) { -+ case 0: return xdigit[head->id[b] >> 4]; -+ case 1: return xdigit[head->id[b] & 0xf]; -+ default: return ':'; -+ } -+} -+#endif -+ -+/* -+ * procfs support, if compiled in. -+ */ -+#ifdef CONFIG_PROC_FS -+/* -+ * The extensively undocumented proc_read_t callback is implemented here. -+ * Go look in fs/proc/generic.c: -+ * -+ * Prototype: -+ * int f(char *buffer, char **start, off_t offset, -+ * int count, int *peof, void *dat) -+ * -+ * Assume that the buffer is "count" bytes in size. -+ * -+ * 2) Set *start = an address within the buffer. -+ * Put the data of the requested offset at *start. -+ * Return the number of bytes of data placed there. -+ * If this number is greater than zero and you -+ * didn't signal eof and the reader is prepared to -+ * take more data you will be called again with the -+ * requested offset advanced by the number of bytes -+ * absorbed. -+ */ -+static int maclist_proc_read(char *buffer, char **start, off_t offset, -+ int count, int *peof, void *dat) { -+ int total; -+ -+ *start = buffer; -+ total = 0; -+ -+ while (total < count) { -+ int ch = maclist_getchar(offset++); -+ if (ch == -1) { -+ *peof = 1; -+ break; -+ } -+ *buffer++ = ch; -+ ++total; -+ } -+ -+ return total; -+} -+#endif -+ -+/* -+ * set works once, at init time (the param is set to 0444 below), -+ * get works any time. -+ */ -+static int param_set_maclist(const char *val, struct kernel_param *kp) -+{ -+ if (maclist_list == 0) -+ return maclist_setup(val); -+ -+ printk(KERN_ERR MACLIST_NAME ": call to set parameters too late\n"); -+ return -EINVAL; -+} -+ -+static int param_get_maclist(char *buffer, struct kernel_param *kp) -+{ -+#ifdef MODULE -+ off_t offset = 0; -+ -+ /* buffer is only 4k! */ -+ while (offset < 4096) { -+ int ch = maclist_getchar(offset++); -+ if (ch < 0) { -+ *buffer = 0; -+ return 0; -+ } -+ *buffer++ = ch; -+ } -+ -+ *--buffer = 0; -+ return -ENOMEM; -+#else -+ return -EINVAL; -+#endif -+} -+ -+/* -+ * module: the argument is ids=mac,mac,mac -+ * kernel command line: maclist.ids=mac,mac,mac -+ */ -+#define param_check_maclist(name, p) __param_check(name, p, maclist_entry_t*) -+module_param_named(ids, maclist_list, maclist, 0444); -+MODULE_PARM_DESC(ids, "comma separated list of MAC ids\n"); -+ -+/* -+ * Finally, the init/exit functions. -+ */ -+static void __exit maclist_exit(void) -+{ -+ maclist_entry_t *list; -+ -+ remove_proc_entry(MACLIST_NAME, proc_net); -+ -+ write_lock(&maclist_lock); -+ list = maclist_list; -+ maclist_list = 0; -+ write_unlock(&maclist_lock); -+ -+ while (list != 0) { -+ maclist_entry_t *head = list; -+ list = head->next; -+ kfree(head); -+ } -+} -+ -+static int __init maclist_init(void) -+{ -+# ifdef MODULE -+ if (ids[0]) -+ maclist_setup(ids); -+# endif -+ -+ /* Ignore failure, the module will still work. */ -+ (void)create_proc_read_entry(MACLIST_NAME, S_IRUGO, proc_net, maclist_proc_read, NULL); -+ -+ return 0; -+} -+ -+module_init(maclist_init); -+module_exit(maclist_exit); -diff -rup linux-2.6.15.1/.pc/91-maclist.patch/include/net/maclist.h linux-2.6.15.1/include/net/maclist.h ---- linux-2.6.15/include/net/maclist.h 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/include/net/maclist.h 1970-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,49 @@ -+#ifndef _MACLIST_H -+#define _MACLIST_H 1 -+/* -+ * Interfaces to the MAC repository -+ * -+ * Copyright (C) 2005 John Bowler -+ * Author: John Bowler <jbowler@acm.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ * 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. -+ */ -+ -+/* -+ * Add a single entry, returns 0 on success else an error -+ * code. Allocates memory, claims and releases a write -+ * lock. -+ */ -+extern int maclist_add(const u8 id_to_add[6]); -+ -+/* -+ * Return the current entry count, claims and releases a -+ * read lock. -+ */ -+extern int maclist_count(void); -+ -+/* -+ * Return the ID from the given entry. Always succeeds. -+ * Claims and releases a write lock. -+ * -+ * If any entry has not been allocated for this key one -+ * is allocated. If there are no remaining unallocated -+ * entries a new one is created. -+ * -+ * If the value of the key is less than maclist_count() -+ * the entry indexed by the key (i.e. for key 'n' the -+ * n'th entry starting at 0) will be returned if available. -+ * Otherwise the entry to be returned will be unpredictable -+ * but consistent for a given value of maclist_count(). -+ */ -+extern void maclist_read(u8 (*buffer_for_id)[6], -+ u32 key_of_entry_to_return); -+ -+/* -+ * See the implementation in drivers/net/maclist.c for -+ * more information. -+ */ -+#endif /*_MACLIST_H*/ |