summaryrefslogtreecommitdiff
path: root/packages/linux/ixp4xx-kernel/2.6.15/91-maclist.patch
diff options
context:
space:
mode:
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.patch570
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*/