summaryrefslogtreecommitdiff
path: root/packages/linux/nslu2-kernel/2.6
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@nslu2-linux.org>2005-11-29 03:02:31 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2005-11-29 03:02:31 +0000
commit78d2ca44a8dd2bad6a4314772ad9c9ac6e30bf46 (patch)
tree9763b5ddd440f30e0a11ffa0f38ccce1bdc1d332 /packages/linux/nslu2-kernel/2.6
parent2765c17b474a765e31206b7a442ba1c9fc8301ea (diff)
nslu2-kernel: add maclist proc entry to 2.6.14.3 and 2.6.15-rc2
Diffstat (limited to 'packages/linux/nslu2-kernel/2.6')
-rw-r--r--packages/linux/nslu2-kernel/2.6/91-maclist.patch377
1 files changed, 377 insertions, 0 deletions
diff --git a/packages/linux/nslu2-kernel/2.6/91-maclist.patch b/packages/linux/nslu2-kernel/2.6/91-maclist.patch
new file mode 100644
index 0000000000..27af1ea639
--- /dev/null
+++ b/packages/linux/nslu2-kernel/2.6/91-maclist.patch
@@ -0,0 +1,377 @@
+--- 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,23 @@
++#ifndef _MACLIST_H
++#define _MACLIST_H 1
++/*
++ * Interfaces to the MAC repository
++ */
++/*
++ * Add a single entry, returns 0 on success else an error
++ * code. Must *not* be called from an interrupt handler.
++ */
++extern int maclist_add(const u8 id_to_add[6]);
++
++/*
++ * Return the current entry count (valid in any context).
++ */
++extern int maclist_count(void);
++
++/*
++ * Return the ID from the n'th entry (valid in any context),
++ * returns 0 on success, -EINVAL if 'n' is out of range.
++ */
++extern int maclist_read(u8 (*buffer_for_id)[6], int index_of_id_to_return);
++
++#endif /*_MACLIST_H*/
+--- 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,314 @@
++/*
++ * 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
++ * maclist_count: total number of MACs stored
++ * maclist_read: read a MAC 0..(maclist_count-1)
++ */
++#include <linux/module.h>
++#include <linux/moduleparam.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 */
++ u8 id[6]; /* 6 byte Ethernet MAC */
++} maclist_entry_t;
++
++/* Access to this list is possible at any time - entries in
++ * the list are never destroyed. Modification of the list is
++ * safe only from the init code (i.e. modification must be
++ * single threaded), but read from an interrupt at the same
++ * time is possible and safe.
++ */
++static maclist_entry_t *maclist_list = 0;
++
++/*
++ * External interfaces.
++ *
++ * Add a single entry, returns 0 on success else an error
++ * code. Must be single threaded.
++ */
++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;
++ memcpy(new_entry->id, new_id, sizeof new_entry->id);
++
++ tail = &maclist_list;
++ while (*tail != 0)
++ tail = &(*tail)->next;
++ *tail = new_entry;
++ return 0;
++}
++EXPORT_SYMBOL(maclist_add);
++
++/*
++ * Return the current entry count (valid in any context).
++ */
++int maclist_count(void) {
++ maclist_entry_t *tail = maclist_list;
++ int count = 0;
++
++ while (tail != 0) {
++ tail = tail->next;
++ ++count;
++ }
++
++ return count;
++}
++EXPORT_SYMBOL(maclist_count);
++
++/*
++ * Return the ID from the n'th entry (valid in any context),
++ * returns 0 on success, -EINVAL if 'n' is out of range.
++ */
++int maclist_read(u8 (*id)[6], int n) {
++ maclist_entry_t *entry = maclist_list;
++
++ while (n > 0 && entry != 0) {
++ --n;
++ entry = entry->next;
++ }
++
++ if (n == 0 && entry != 0) {
++ memcpy(id, entry->id, sizeof *id);
++ return 0;
++ }
++
++ printk(KERN_ERR MACLIST_NAME ": id does not exist\n");
++ return -EINVAL;
++}
++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(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 (rc)
++ return rc;
++ bytes = 0;
++ seen_a_digit = 0;
++ memset(id, 0, sizeof id);
++ if (*param == 0)
++ return 0;
++ }
++ ++param;
++ } while (1);
++
++ return 0;
++}
++
++/*
++ * procfs support, if compiled in.
++ */
++#ifdef CONFIG_PROC_FS
++/*
++ * 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 ':';
++ }
++}
++
++/*
++ * 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
++
++/*
++ * Finally, the init/exit functions.
++ */
++static void __exit maclist_exit(void)
++{
++ maclist_entry_t *list;
++
++ remove_proc_entry(MACLIST_NAME, proc_net);
++
++ list = maclist_list;
++ maclist_list = 0;
++
++ while (list != 0) {
++ maclist_entry_t *head = list;
++ list = head->next;
++ kfree(head);
++ }
++}
++
++#ifdef MODULE
++static char ids[256];
++module_param_string(ids, ids, sizeof ids, 0);
++MODULE_PARM_DESC(ids, "comma separated list of MAC ids\n");
++#else
++__setup("maclist_ids=", maclist_setup);
++#endif
++
++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);
+--- 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/
+
+--- 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