diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/ixp425-eth | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/ixp425-eth')
54 files changed, 4765 insertions, 0 deletions
diff --git a/recipes/ixp425-eth/files/2.6.13.patch b/recipes/ixp425-eth/files/2.6.13.patch new file mode 100644 index 0000000000..7e8bea1b5d --- /dev/null +++ b/recipes/ixp425-eth/files/2.6.13.patch @@ -0,0 +1,41 @@ +# Patches for compilation with 2.6.13.2 +# +--- dir/ixp425_eth.c 2005-09-23 18:34:54.753729121 -0700 ++++ dir/ixp425_eth.c 2005-09-23 18:37:48.908688002 -0700 +@@ -659,7 +659,9 @@ + skb->pkt_type = PACKET_HOST; /* Default type */ + skb->ip_summed = 0; + skb->priority = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + skb->security = 0; ++#endif + + /* Some packets may get incorrectly process by netfilter firewall software + * if CONFIG_NETFILTER is enabled and filtering is in use. The solution is to +@@ -2358,8 +2362,14 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { ++#else ++static int set_mac_address(struct net_device *dev, void *saddrIn) ++{ ++ struct sockaddr *saddr = saddrIn; ++#endif + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +@@ -2476,7 +2486,11 @@ + ndev->poll_controller = ixp425eth_poll_controller; + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + ndev->set_mac_address = dev_set_mac_address; ++#else ++ ndev->set_mac_address = set_mac_address; ++#endif + + memcpy(ndev->dev_addr, &default_mac_addr[priv->port_id].macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); diff --git a/recipes/ixp425-eth/files/2.6.14.patch b/recipes/ixp425-eth/files/2.6.14.patch new file mode 100644 index 0000000000..e93edb6e9b --- /dev/null +++ b/recipes/ixp425-eth/files/2.6.14.patch @@ -0,0 +1,28 @@ +# change in field semantic in 2.6.14 +--- dir/ixp425_eth.c 2005-09-24 17:50:57.828607113 -0700 ++++ dir/ixp425_eth.c 2005-09-24 17:54:19.593303365 -0700 +@@ -668,7 +668,11 @@ + * reset the following fields in the skbuff before re-using it on the Rx-path + */ + #ifdef CONFIG_NETFILTER ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->nfmark = skb->nfcache = 0; ++#else ++ skb->nfmark = 0; ++#endif + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #ifdef CONFIG_NETFILTER_DEBUG +@@ -1300,8 +1300,12 @@ + skb->len -= header_len; + + /* fill the pkt arrival time (set at the irq callback entry) */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->stamp.tv_sec = irq_stamp.tv_sec; + skb->stamp.tv_usec = irq_stamp.tv_usec; ++#else ++ skb_set_timestamp(skb, &irq_stamp); ++#endif + + /* fill the input device field */ + skb->dev = dev; diff --git a/recipes/ixp425-eth/files/ethhdr.patch b/recipes/ixp425-eth/files/ethhdr.patch new file mode 100644 index 0000000000..79c9fef34f --- /dev/null +++ b/recipes/ixp425-eth/files/ethhdr.patch @@ -0,0 +1,25 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- ixp425-eth-1.1-r0/ixp425_eth.c~ethhdr ++++ ixp425-eth-1.1-r0/ixp425_eth.c +@@ -1307,7 +1307,7 @@ + * and its constants are taken from the eth_type_trans() + * function. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned short hproto = ntohs(eth->h_proto); + + if (hproto >= 1536) +@@ -1349,7 +1349,7 @@ + * mode is set This costs + * a lookup inside the packet payload. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned char *hdest = eth->h_dest; + + if (memcmp(hdest, dev->dev_addr, ETH_ALEN)!=0) diff --git a/recipes/ixp425-eth/files/intdriven.patch b/recipes/ixp425-eth/files/intdriven.patch new file mode 100644 index 0000000000..88b2444b5e --- /dev/null +++ b/recipes/ixp425-eth/files/intdriven.patch @@ -0,0 +1,98 @@ +--- ixp425-eth-1.1-r4/ixp425_eth.c 2005-06-16 00:47:55.360598896 -0700 ++++ ixp425-eth-1.1-r4/ixp425_eth.c 2005-06-16 18:42:09.840377651 -0700 +@@ -1028,6 +1030,7 @@ + */ + + /* PMU Timer reload : this should be done at each interrupt */ ++#if 0 /* UNUSED - used for polling */ + static void dev_pmu_timer_restart(void) + { + __asm__(" mcr p14,0,%0,c1,c1,0\n" /* write current counter */ +@@ -1039,6 +1042,7 @@ + " mcr p14,0,r1,c4,c1,0\n" /* enable interrupts */ + : : : "r1"); + } ++#endif + + /* Internal ISR : run a few thousand times per second and calls + * the queue manager dispatcher entry point. +@@ -1086,6 +1088,7 @@ + /* Internal ISR : run a few thousand times per second and calls + * the ethernet entry point. + */ ++#if 0 /* UNUSED - used for polling */ + static irqreturn_t dev_poll_os_isr(int irg, void *dev_id, struct pt_regs *regs) + { + int qlevel = __get_cpu_var(softnet_data).input_pkt_queue.qlen; +@@ -1127,8 +1130,10 @@ + ixEthTxFrameDoneQMCallback(0,0); + return IRQ_HANDLED; + } ++#endif + + /* initialize the PMU timer */ ++#if 0 /* UNUSED - used for polling */ + static int dev_pmu_timer_init(void) + { + UINT32 controlRegisterMask = +@@ -1164,6 +1169,7 @@ + + return 0; + } ++#endif + + /* stops the timer when the module terminates */ + static void dev_pmu_timer_disable(void) +@@ -1636,6 +1636,7 @@ + return 0; + } + ++#if 0 /* UNUSED - used for polling */ + /* The QMgr dispatch entry point can be called from the + * IXP425_INT_LVL_QM1 irq (which will trigger + * an interrupt for every packet) or a timer (which will +@@ -1686,7 +1687,7 @@ + */ + if (request_irq(IXP425_INT_LVL_QM1, + dev_qmgr_os_isr, +- SA_SHIRQ, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, + DRV_NAME, + (void *)IRQ_ANY_PARAMETER)) + { +@@ -1710,6 +1711,7 @@ + } + return 0; + } ++#endif + + /* Enable the MAC port. + * Called on do_dev_open, dev_tx_timeout and mtu size changes +@@ -2234,7 +2236,7 @@ + */ + if (request_irq(IXP425_INT_LVL_QM1, + dev_qmgr_os_isr, +- SA_SHIRQ, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, + DRV_NAME, + (void *)IRQ_ANY_PARAMETER)) + { +@@ -2669,6 +2671,10 @@ + + TRACE; + ++#if 0 /* DISABLE polling */ ++ /* Enable Interrupt driven driver ++ * see http://www.nslu2-linux.org/wiki/OpenSlug/StabilizeEthernetDriver ++ */ + if (no_csr_init == 0) /* module parameter */ + { + /* The QMgr dispatch entry point is called from the IXP425_INT_LVL_QM1 irq +@@ -2681,6 +2687,7 @@ + return res; + } + } ++#endif + + TRACE; + diff --git a/recipes/ixp425-eth/files/ixp400_pollcontroller.patch b/recipes/ixp425-eth/files/ixp400_pollcontroller.patch new file mode 100644 index 0000000000..b6fe10a5c6 --- /dev/null +++ b/recipes/ixp425-eth/files/ixp400_pollcontroller.patch @@ -0,0 +1,50 @@ +*** ixp400-eth-1.4-r4/ixp400_eth.c.orig Mon Oct 31 22:45:46 2005 +--- ixp400-eth-1.4-r4/ixp400_eth.c Mon Oct 31 22:47:48 2005 +*************** +*** 306,311 **** +--- 306,316 ---- + ixEthRxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId); + extern void + ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId); ++ #ifdef CONFIG_NET_POLL_CONTROLLER ++ /* poll controller (needed for netconsole et al) */ ++ static void ++ ixp425eth_poll_controller(struct net_device *dev); ++ #endif + + /* Private device data */ + typedef struct { +*************** +*** 3082,3087 **** +--- 3087,3095 ---- + ndev->get_stats = dev_get_stats; + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; ++ #ifdef CONFIG_NET_POLL_CONTROLLER ++ ndev->poll_controller = ixp425eth_poll_controller; ++ #endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + ndev->set_mac_address = dev_set_mac_address; + #else +*************** +*** 3172,3177 **** +--- 3180,3198 ---- + return res; + } + ++ #ifdef CONFIG_NET_POLL_CONTROLLER ++ /* ++ * Polling receive - used by netconsole and other diagnostic tools ++ * to allow network i/o with interrupts disabled. ++ * (stolen from 8139too.c by siddy) ++ */ ++ static void ixp425eth_poll_controller(struct net_device *dev) ++ { ++ disable_irq(dev->irq); ++ dev_qmgr_os_isr(dev->irq, dev, NULL); ++ enable_irq(dev->irq); ++ } ++ #endif + + static int __devinit npe_eth_init_device(struct device *dev) + { diff --git a/recipes/ixp425-eth/files/makefile.patch b/recipes/ixp425-eth/files/makefile.patch new file mode 100644 index 0000000000..2e47972995 --- /dev/null +++ b/recipes/ixp425-eth/files/makefile.patch @@ -0,0 +1,18 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- /dev/null ++++ ixp425-eth-1.1-r0/Makefile +@@ -0,0 +1,10 @@ ++ifneq ($(KERNELRELEASE),) ++obj-m := ixp425_eth.o ++ ++else ++KDIR := /lib/modules/$(shell uname -r)/build ++PWD := $(shell pwd) ++ ++default modules: ++ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules ++endif diff --git a/recipes/ixp425-eth/files/mm4.patch b/recipes/ixp425-eth/files/mm4.patch new file mode 100644 index 0000000000..c40aaca998 --- /dev/null +++ b/recipes/ixp425-eth/files/mm4.patch @@ -0,0 +1,19 @@ +# This corrects the type of dev_set_mac_address. The definition (prototype) +# was *added* to include/linux/netdevice.h in the 2.6.11 mm patches, so the +# change should not harm older builds +--- ixp425-eth-1.1-r1/ixp425_eth.c.pre-mm4 2005-03-19 14:02:32.883601440 -0800 ++++ ixp425-eth-1.1-r1/ixp425_eth.c 2005-03-19 14:03:25.849549392 -0800 +@@ -2347,12 +2347,11 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ +-int dev_set_mac_address(struct net_device *dev, void *addr) ++int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +- struct sockaddr *saddr = (struct sockaddr *)addr; + + /* Set MAC addr in h/w */ + memcpy(&npeMacAddr.macAddress, diff --git a/recipes/ixp425-eth/files/modprobe.conf b/recipes/ixp425-eth/files/modprobe.conf new file mode 100644 index 0000000000..bfcbf916cf --- /dev/null +++ b/recipes/ixp425-eth/files/modprobe.conf @@ -0,0 +1,3 @@ +# Add an alias for eth0 to ixp425_eth to cause the S40networking +# init script to load the ixp425_eth driver on the first boot +alias eth0 ixp425_eth diff --git a/recipes/ixp425-eth/files/pollcontroller.patch b/recipes/ixp425-eth/files/pollcontroller.patch new file mode 100644 index 0000000000..f95db28977 --- /dev/null +++ b/recipes/ixp425-eth/files/pollcontroller.patch @@ -0,0 +1,50 @@ +# Add a poll controller to the interface - required for netconsole +--- ixp425-eth-1.1-r1/ixp425_eth.c.pre-pollcontroller 2005-03-19 14:02:32.883601440 -0800 ++++ ixp425-eth-1.1-r1/ixp425_eth.c 2005-03-19 14:03:25.849549392 -0800 +@@ -273,6 +273,11 @@ + extern void + ixEthTxFrameDoneQMCallback(IxQMgrQId? qId, IxQMgrCallbackId? callbackId); + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* poll controller (needed for netconsole et al) */ ++static void ixp425eth_poll_controller(struct net_device *dev); ++#endif ++ + /* Private device data */ + typedef struct { + unsigned int msdu_size; +@@ -2462,6 +2467,10 @@ + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ ndev->poll_controller = ixp425eth_poll_controller; ++#endif ++ + ndev->set_mac_address = dev_set_mac_address; + + memcpy(ndev->dev_addr, &default_mac_addr[priv->port_id].macAddress, +@@ -2491,6 +2500,23 @@ + return res; + } + ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling receive - used by netconsole and other diagnostic tools ++ * to allow network i/o with interrupts disabled. ++ * (stolen from 8139too.c by siddy) ++ */ ++static void ixp425eth_poll_controller(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ dev_qmgr_os_isr(dev->irq, dev, NULL); ++ enable_irq(dev->irq); ++} ++#endif ++ ++ ++ + static int __devinit npe_eth_init_device(struct device *dev) + { + int res = -ENOMEM; diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/2.6.13.patch b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.13.patch new file mode 100644 index 0000000000..376bb3b03b --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.13.patch @@ -0,0 +1,39 @@ +--- ./ixp400_eth.c.orig 2005-10-02 18:55:03.998477844 -0700 ++++ ./ixp400_eth.c 2005-10-02 19:00:43.187821684 -0700 +@@ -848,7 +848,9 @@ + skb->pkt_type = PACKET_HOST; /* Default type */ + skb->ip_summed = 0; + skb->priority = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + skb->security = 0; ++#endif + #ifdef CONFIG_NET_SCHED + skb->tc_index = 0; + #endif +@@ -2922,8 +2924,14 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { ++#else ++static int set_mac_address(struct net_device *dev, void *saddrIn) ++{ ++ struct sockaddr *saddr = saddrIn; ++#endif + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +@@ -3073,7 +3081,11 @@ + ndev->get_stats = dev_get_stats; + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + ndev->set_mac_address = dev_set_mac_address; ++#else ++ ndev->set_mac_address = set_mac_address; ++#endif + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14-mm.patch b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14-mm.patch new file mode 100644 index 0000000000..b2dfaaa4fe --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14-mm.patch @@ -0,0 +1,44 @@ +--- ./ixp400_eth.c.orig 2005-11-13 16:17:57.943717806 -0800 ++++ ./ixp400_eth.c 2005-11-13 16:29:00.829430574 -0800 +@@ -65,6 +65,10 @@ + #include <linux/sysctl.h> + #include <linux/unistd.h> + ++#ifndef to_platform_device ++#include <linux/platform_device.h> ++#endif ++ + /* + * Intel IXP400 Software specific header files + */ +@@ -2410,7 +2414,7 @@ dev_tx_timeout_work(void* arg) + } + + +- ++#if 0 + static void + dev_tx_timeout_task(void *dev_id) + { +@@ -2444,6 +2448,7 @@ dev_tx_timeout_task(void *dev_id) + + up(maintenance_mutex); + } ++#endif + + + /* This function is called when kernel thinks that TX is stuck */ +@@ -3274,9 +3279,12 @@ static struct net_device ixp400_devices[ + + int init_module(void) + { +- int res, dev_count; ++ int res; ++#if 0 ++ int dev_count; + IxEthAccPortId portId; + struct net_device *dev; ++#endif + int i; + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14.patch b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14.patch new file mode 100644 index 0000000000..c4c19db795 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/2.6.14.patch @@ -0,0 +1,24 @@ +--- ./ixp400_eth.c 2005-10-01 00:50:45.179775259 -0700 ++++ ./ixp400_eth.c 2005-10-01 00:54:10.976725245 -0700 +@@ -777,7 +777,9 @@ + * before re-using it on the Rx-path + */ + skb->nfmark = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->nfcache = 0; ++#endif + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #ifdef CONFIG_NETFILTER_DEBUG +@@ -1451,7 +1453,11 @@ + skb->len -= header_len; + + /* fill the pkt arrival time (set at the irq callback entry) */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->stamp = irq_stamp; ++#else ++ skb_set_timestamp(skb, &irq_stamp); ++#endif + + /* fill the input device field */ + skb->dev = dev; diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch b/recipes/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch new file mode 100644 index 0000000000..87d4337eb3 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch @@ -0,0 +1,948 @@ +--- ./.pc/ixp400-le-be.patch/ixp400_eth.c 2005-04-19 22:58:18.000000000 -0700 ++++ ./ixp400_eth.c 2005-10-23 23:29:06.760778566 -0700 +@@ -57,6 +57,7 @@ + #include <linux/mii.h> + #include <linux/socket.h> + #include <linux/cache.h> ++#include <linux/interrupt.h> + #include <asm/io.h> + #include <asm/errno.h> + #include <net/pkt_sched.h> +@@ -95,7 +96,7 @@ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Intel Corporation"); + #define MODULE_NAME "ixp400_eth" +-#define MODULE_VERSION "1.4" ++#define MODULE_VERSION_IXP400_ETH "1.4B" + + /* Module parameters */ + static int npe_learning = 1; /* default : NPE learning & filtering enable */ +@@ -358,8 +359,13 @@ + /* Used to stop the kernel thread for link monitoring. */ + volatile BOOL maintenanceCheckStopped; + ++ struct work_struct mii_job; ++ ++ + /* used for tx timeout */ +- struct tq_struct tq_timeout; ++ struct work_struct tx_timeout_job; ++ ++ + + /* used to control the message output */ + UINT32 devFlags; +@@ -557,6 +563,8 @@ + #endif + }; + ++static struct workqueue_struct *npe_eth_workqueue; ++ + /* Mutex lock used to coordinate access to IxEthAcc functions + * which manipulate the MII registers on the PHYs + */ +@@ -565,6 +573,11 @@ + /* mutex locked when maintenance is being performed */ + static struct semaphore *maintenance_mutex; + ++/* Flags which is set when corresponding NPE is running, ++ * cleared when NPE is stopped ++ */ ++static int npeRunning[IX_ETH_ACC_NUMBER_OF_PORTS]; ++ + /* Flags which is set when the corresponding IRQ is running, + */ + static int irq_pmu_used = 0; +@@ -1070,6 +1083,117 @@ + return 0; + } + ++/* ++ * WORKQUEUE JOBS ++ */ ++ ++/* This workqueue job will check the PHY for the link duplex and ++ * update the MAC accordingly. It also executes some buffer ++ * maintenance to release mbuf in excess or replenish after ++ * a severe starvation ++ * ++ * This function loops and wake up every 3 seconds. ++ */ ++static void dev_media_check_work(void* arg) ++{ ++ struct net_device *dev = (struct net_device *) arg; ++ priv_data_t *priv = dev->priv; ++ ++ TRACE; ++ ++ /* ++ * Determine the link status ++ */ ++ ++ if (default_phy_cfg[priv->port_id].linkMonitor) ++ { ++ int linkUp; ++ int speed100; ++ int fullDuplex = -1; /* unknown duplex mode */ ++ int newDuplex; ++ int autonegotiate; ++ unsigned phyNum = phyAddresses[priv->port_id]; ++ int res; ++ ++ TRACE; ++ ++ /* lock the MII register access mutex */ ++ down(miiAccessMutex); ++ ++ res = ixEthMiiLinkStatus(phyNum, ++ &linkUp, ++ &speed100, ++ &newDuplex, ++ &autonegotiate); ++ /* release the MII register access mutex */ ++ up(miiAccessMutex); ++ ++ if (res != IX_ETH_ACC_SUCCESS) ++ { ++ P_WARN("ixEthMiiLinkStatus failed on PHY%d.\n" ++ "\tCan't determine\nthe auto negotiated parameters. " ++ "Using default values.\n", ++ phyNum); ++ ++ /* this shouldn't happen. exit the thread if it does */ ++ goto out; ++ } ++ ++ if (linkUp) ++ { ++ if (! netif_carrier_ok(dev)) ++ { ++ /* inform the kernel of a change in link state */ ++ netif_carrier_on(dev); ++ } ++ ++ /* ++ * Update the MAC mode to match the PHY mode if ++ * there is a phy mode change. ++ */ ++ if (newDuplex != fullDuplex) ++ { ++ fullDuplex = newDuplex; ++ if (fullDuplex) ++ { ++ ixEthAccPortDuplexModeSet(priv->port_id, ++ IX_ETH_ACC_FULL_DUPLEX); ++ } ++ else ++ { ++ ixEthAccPortDuplexModeSet(priv->port_id, ++ IX_ETH_ACC_HALF_DUPLEX); ++ } ++ } ++ } ++ else ++ { ++ fullDuplex = -1; ++ if (netif_carrier_ok(dev)) ++ { ++ /* inform the kernel of a change in link state */ ++ netif_carrier_off(dev); ++ } ++ } ++ } ++ ++ TRACE; ++ ++ /* this is to prevent the rx pool from emptying when ++ * there's not enough memory for a long time ++ * It prevents also from holding the memory for too ++ * long ++ */ ++ dev_buff_maintenance(dev); ++ ++ /* reschedule to run in 3 seconds */ ++ queue_delayed_work(npe_eth_workqueue, &priv->mii_job, 3*HZ); ++ out: ++ return; ++} ++ ++ ++#define sigmask_lock sighand->siglock + + /* + * KERNEL THREADS +@@ -1122,11 +1246,11 @@ + */ + down (priv->maintenanceCheckThreadComplete); + +- daemonize(); +- reparent_to_init(); ++ daemonize("dev_media"); ++ // reparent_to_init(); + spin_lock_irq(¤t->sigmask_lock); + sigemptyset(¤t->blocked); +- recalc_sigpending(current); ++ recalc_sigpending(); + spin_unlock_irq(¤t->sigmask_lock); + + snprintf(current->comm, sizeof(current->comm), "ixp400 %s", dev->name); +@@ -1285,7 +1409,7 @@ + static void dev_pmu_timer_restart(void) + { + unsigned long flags; +- save_flags_cli(flags); ++ local_irq_save(flags); + __asm__(" mcr p14,0,%0,c1,c1,0\n" /* write current counter */ + : : "r" (timer_countup_ticks)); + +@@ -1294,13 +1418,13 @@ + " mcr p14,0,r1,c5,c1,0; " /* clear overflow */ + " mcr p14,0,r1,c4,c1,0\n" /* enable interrupts */ + : : : "r1"); +- restore_flags(flags); ++ local_irq_restore(flags); + } + + /* Internal ISR : run a few thousand times per second and calls + * the queue manager dispatcher entry point. + */ +-static void dev_qmgr_os_isr(int irg, void *dev_id, struct pt_regs *regs) ++static irqreturn_t dev_qmgr_os_isr(int irg, void *dev_id, struct pt_regs *regs) + { + /* get the time of this interrupt : all buffers received during this + * interrupt will be assigned the same time */ +@@ -1308,22 +1432,32 @@ + + /* call the queue manager entry point */ + dispatcherFunc(IX_QMGR_QUELOW_GROUP); ++ return IRQ_HANDLED; + } + + /* Internal ISR : run a few thousand times per second and calls + * the ethernet entry point. + */ +-static void dev_poll_os_isr(int irg, void *dev_id, struct pt_regs *regs) ++int icount = 2; ++static irqreturn_t dev_poll_os_isr(int irg, void *dev_id, struct pt_regs *regs) + { +- dev_pmu_timer_restart(); /* set up the timer for the next interrupt */ ++ if (icount > 0) { ++ icount--; ++ TRACE; ++ } + + /* get the time of this interrupt : all buffers received during this + * interrupt will be assigned the same time */ + do_gettimeofday(&irq_stamp); +- ++ if (icount) TRACE; + ixEthRxFrameQMCallback(rx_queue_id,0); ++ if (icount) TRACE; + ixEthTxFrameDoneQMCallback(0,0); +- ++ if (icount) TRACE; ++ /* here surely */ ++ dev_pmu_timer_restart(); /* set up the timer for the next interrupt */ ++ return IRQ_HANDLED; ++ + } + + /* initialize the PMU timer */ +@@ -1370,17 +1504,18 @@ + static void dev_pmu_timer_disable(void) + { + unsigned long flags; +- save_flags_cli(flags); ++ local_irq_save(flags); + __asm__(" mrc p14,0,r1,c4,c1,0; " /* get int enable register */ + " and r1,r1,#0x1e; " + " mcr p14,0,r1,c4,c1,0\n" /* disable interrupts */ + : : : "r1"); +- restore_flags(flags); ++ local_irq_restore(flags); + } + + /* This timer will call ixEthDBDatabaseMaintenance every + * IX_ETH_DB_MAINTENANCE_TIME jiffies + */ ++#if 0 + static void maintenance_timer_cb(unsigned long data); + + static struct timer_list maintenance_timer = { +@@ -1418,6 +1553,34 @@ + + maintenance_timer_set(); + } ++#endif ++static void db_maintenance_code(void *data); ++static DECLARE_WORK(db_maintenance_job, db_maintenance_code, NULL); ++ ++static inline ++void schedule_db_maintenance(void) ++{ ++ TRACE; ++ queue_delayed_work(npe_eth_workqueue, &db_maintenance_job, ++ DB_MAINTENANCE_TIME); ++} ++ ++static inline ++void cancel_db_maintenance(void) ++{ ++ TRACE; ++ cancel_delayed_work(&db_maintenance_job); ++} ++ ++static void db_maintenance_code(void *data) ++{ ++ TRACE; ++ down(maintenance_mutex); ++ ixEthDBDatabaseMaintenance(); ++ up(maintenance_mutex); ++ schedule_db_maintenance(); ++} ++ + + /* + * DATAPLANE +@@ -1531,7 +1694,7 @@ + * and its constants are taken from the eth_type_trans() + * function. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned short hproto = ntohs(eth->h_proto); + + if (hproto >= 1536) +@@ -1573,7 +1736,7 @@ + * mode is set This costs + * a lookup inside the packet payload. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned char *hdest = eth->h_dest; + + if (memcmp(hdest, dev->dev_addr, ETH_ALEN)!=0) +@@ -1632,7 +1795,7 @@ + dev = (struct net_device *)callbackTag; + priv = dev->priv; + +- qlevel = softnet_data[0].input_pkt_queue.qlen; ++ qlevel = __get_cpu_var(softnet_data).input_pkt_queue.qlen; + /* check if the system accepts more traffic and + * against chained mbufs + */ +@@ -1674,10 +1837,21 @@ + /* set the length of the received skb from the mbuf length */ + skb->tail = skb->data + len; + skb->len = len; ++ ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif + + #ifdef DEBUG_DUMP + skb_dump("rx", skb); + #endif ++ + /* Set the skb protocol and set mcast/bcast flags */ + dev_eth_type_trans(mcastFlags, skb, dev); + +@@ -1821,6 +1995,39 @@ + spin_unlock_irq(&priv->lock); + } + ++/* start the NPEs */ ++static int npe_start(IxEthAccPortId port_id) ++{ ++ int res; ++ UINT32 npeImageId; ++ ++ switch (port_id) ++ { ++ case IX_ETH_PORT_1: ++ npeImageId = IX_ETH_NPE_B_IMAGE_ID; ++ break; ++ case IX_ETH_PORT_2: ++ npeImageId = IX_ETH_NPE_C_IMAGE_ID; ++ break; ++ default: ++ P_ERROR("Invalid port specified. IXP Ethernet NPE not started\n"); ++ return -ENODEV; ++ } ++ ++ /* Initialise and Start NPEs */ ++ if ((res = ixNpeDlNpeInitAndStart(npeImageId))) ++ { ++ P_ERROR("Error starting NPE for Ethernet port %d!\n", port_id); ++ return -1; ++ } ++ ++ /* set this flag to indicate that NPE is running */ ++ npeRunning[port_id] = 1; ++ ++ return 0; ++} ++ ++ + /* The QMgr dispatch entry point can be called from the + * IX_OSAL_IXP400_QM1_IRQ_LVL irq (which will trigger + * an interrupt for every packet) or a timer (which will +@@ -1906,7 +2113,16 @@ + IxEthAccMacAddr npeMacAddr; + priv_data_t *priv = dev->priv; + +- P_DEBUG("port_enable(%s)\n", dev->name); ++ P_DEBUG("port_enable(%s) %d\n", dev->name, priv->port_id); ++ ++ if (!npeRunning[priv->port_id]) ++ { ++ if ((res = npe_start(priv->port_id))) ++ { ++ TRACE; ++ return res; ++ } ++ } + + /* Set MAC addr in h/w (ethAcc checks for MAC address to be valid) */ + memcpy(&npeMacAddr.macAddress, +@@ -2085,6 +2301,16 @@ + return 0; + } + ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif ++ + #ifdef DEBUG_DUMP + skb_dump("tx", skb); + #endif +@@ -2120,6 +2346,7 @@ + static int do_dev_open(struct net_device *dev) + { + int res; ++ TRACE; + + /* prevent the maintenance task from running while bringing up port */ + down(maintenance_mutex); +@@ -2151,6 +2378,27 @@ + } + + static void ++dev_tx_timeout_work(void* arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ priv_data_t *priv = dev->priv; ++ ++ P_ERROR("%s: Tx Timeout for port %d\n", dev->name, priv->port_id); ++ ++ down(maintenance_mutex); ++ port_disable(dev); ++ ++ /* Note to user: Consider performing other reset operations here (such as ++ * PHY reset), if it is known to help the Tx Flow to become "unstuck" ++ */ ++ ++ port_enable(dev); ++ up(maintenance_mutex); ++} ++ ++ ++ ++static void + dev_tx_timeout_task(void *dev_id) + { + struct net_device *dev = (struct net_device *)dev_id; +@@ -2191,7 +2439,7 @@ + priv_data_t *priv = dev->priv; + + TRACE; +- schedule_task(&priv->tq_timeout); ++ queue_work(npe_eth_workqueue, &priv->tx_timeout_job); + + } + +@@ -2352,7 +2600,8 @@ + + TRACE; + +- invalidate_dcache_range((unsigned int)ðStats, sizeof(ethStats)); ++ // invalidate_dcache_range((unsigned int)ðStats, sizeof(ethStats)); ++ IX_ACC_DATA_CACHE_INVALIDATE((unsigned int)ðStats, sizeof(ethStats)); + if ((res = ixEthAccMibIIStatsGetClear(priv->port_id, ðStats))) + { + P_ERROR("%s: ixEthAccMibIIStatsGet failed for port %d, res = %d\n", +@@ -2565,7 +2814,6 @@ + miiAccessMutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); + if (!miiAccessMutex) + return -ENOMEM; +- + init_MUTEX(miiAccessMutex); + + TRACE; +@@ -2673,12 +2921,12 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ +-int dev_set_mac_address(struct net_device *dev, void *addr) ++int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +- struct sockaddr *saddr = (struct sockaddr *)addr; ++ // struct sockaddr *saddr = (struct sockaddr *)addr; + + /* Get MAC addr from parameter */ + memcpy(&npeMacAddr.macAddress, +@@ -2751,35 +2999,16 @@ + /* Initialize device structs. + * Resource allocation is deffered until do_dev_open + */ +-static int __devinit dev_eth_probe(struct net_device *dev) ++static int __devinit dev_eth_probe(struct device *_dev) + { +- static int found_devices = 0; +- priv_data_t *priv; ++ int res = -ENOMEM; ++ struct platform_device *pdev = to_platform_device(_dev); ++ struct net_device *ndev = dev_get_drvdata(_dev); ++ priv_data_t *priv = (priv_data_t*)ndev->priv; + + TRACE; + +- /* there is a limited number of devices */ +- if (found_devices >= dev_max_count) /* module parameter */ +- return -ENODEV; +- +- SET_MODULE_OWNER(dev); +- +- /* set device name */ +- sprintf(dev->name, DEVICE_NAME "%d", found_devices); +- +- /* allocate and initialize priv struct */ +- priv = dev->priv = kmalloc(sizeof(priv_data_t), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- +- memset(dev->priv, 0, sizeof(priv_data_t)); +- +- TRACE; +- +- /* set the mapping between port ID and devices +- * +- */ +- priv->port_id = default_portId[found_devices]; ++ priv->port_id = pdev->id; + + TRACE; + +@@ -2789,9 +3018,8 @@ + if(priv->rx_pool == NULL) + { + P_ERROR("%s: Buffer RX Pool init failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + + TRACE; +@@ -2802,45 +3030,45 @@ + if(priv->tx_pool == NULL) + { + P_ERROR("%s: Buffer TX Pool init failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + +- TRACE; +- + /* initialise the MII register access mutex */ + priv->maintenanceCheckThreadComplete = (struct semaphore *) + kmalloc(sizeof(struct semaphore), GFP_KERNEL); + if (!priv->maintenanceCheckThreadComplete) + { +- kfree(dev->priv); +- return -ENOMEM; ++ P_ERROR("%s: Failed to allocate maintenance semaphore %d\n", ++ ndev->name, priv->port_id); ++ goto out; + } + priv->lock = SPIN_LOCK_UNLOCKED; + init_MUTEX(priv->maintenanceCheckThreadComplete); + priv->maintenanceCheckStopped = TRUE; + + /* initialize ethernet device (default handlers) */ +- ether_setup(dev); ++ ether_setup(ndev); + + TRACE; + +- /* fill in dev struct callbacks with customized handlers */ +- dev->open = do_dev_open; +- dev->stop = do_dev_stop; ++ INIT_WORK(&priv->mii_job, dev_media_check_work, ndev); ++ INIT_WORK(&priv->tx_timeout_job, dev_tx_timeout_work, ndev); + +- dev->hard_start_xmit = dev_hard_start_xmit; +- +- dev->watchdog_timeo = DEV_WATCHDOG_TIMEO; +- dev->tx_timeout = dev_tx_timeout; +- dev->change_mtu = dev_change_mtu; +- dev->do_ioctl = do_dev_ioctl; +- dev->get_stats = dev_get_stats; +- dev->set_multicast_list = dev_set_multicast_list; +- dev->flags |= IFF_MULTICAST; ++ TRACE; + +- dev->set_mac_address = dev_set_mac_address; ++ /* fill in dev struct callbacks with customized handlers */ ++ ndev->open = do_dev_open; ++ ndev->stop = do_dev_stop; ++ ndev->hard_start_xmit = dev_hard_start_xmit; ++ ndev->watchdog_timeo = DEV_WATCHDOG_TIMEO; ++ ndev->tx_timeout = dev_tx_timeout; ++ ndev->change_mtu = dev_change_mtu; ++ ndev->do_ioctl = do_dev_ioctl; ++ ndev->get_stats = dev_get_stats; ++ ndev->set_multicast_list = dev_set_multicast_list; ++ ndev->flags |= IFF_MULTICAST; ++ ndev->set_mac_address = dev_set_mac_address; + + TRACE; + +@@ -2858,22 +3086,22 @@ + * + */ + +- memcpy(dev->dev_addr, ++ memcpy(ndev->dev_addr, + &default_mac_addr[priv->port_id].macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + + /* possibly remove this test and the message when a valid MAC address + * is not hardcoded in the driver source code. + */ +- if (is_valid_ether_addr(dev->dev_addr)) ++ if (is_valid_ether_addr(ndev->dev_addr)) + { + P_WARN("Use default MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", +- (unsigned)dev->dev_addr[0], +- (unsigned)dev->dev_addr[1], +- (unsigned)dev->dev_addr[2], +- (unsigned)dev->dev_addr[3], +- (unsigned)dev->dev_addr[4], +- (unsigned)dev->dev_addr[5], ++ (unsigned)ndev->dev_addr[0], ++ (unsigned)ndev->dev_addr[1], ++ (unsigned)ndev->dev_addr[2], ++ (unsigned)ndev->dev_addr[3], ++ (unsigned)ndev->dev_addr[4], ++ (unsigned)ndev->dev_addr[5], + priv->port_id); + } + +@@ -2883,31 +3111,30 @@ + */ + TRACE; + +- dev_change_msdu(dev, dev->mtu + dev->hard_header_len + VLAN_HDR); +- ++ dev_change_msdu(ndev, ndev->mtu + ndev->hard_header_len + VLAN_HDR); ++#if 0 + priv->tq_timeout.routine = dev_tx_timeout_task; + priv->tq_timeout.data = (void *)dev; +- ++#endif + #ifdef CONFIG_IXP400_ETH_QDISC_ENABLED + /* configure and enable a fast TX queuing discipline */ + TRACE; + +- priv->qdisc = qdisc_create_dflt(dev, &dev_qdisc_ops); +- dev->qdisc_sleeping = priv->qdisc; +- dev->qdisc = priv->qdisc; ++ priv->qdisc = qdisc_create_dflt(ndev, &dev_qdisc_ops); ++ ndev->qdisc_sleeping = priv->qdisc; ++ ndev->qdisc = priv->qdisc; + +- if (!dev->qdisc_sleeping) ++ if (!ndev->qdisc_sleeping) + { + P_ERROR("%s: qdisc_create_dflt failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + #endif + + /* set the internal maximum queueing capabilities */ +- dev->tx_queue_len = TX_MBUF_POOL_SIZE; +- ++ ndev->tx_queue_len = TX_MBUF_POOL_SIZE; ++#if 0 + if (!netif_queue_stopped(dev)) + { + TRACE; +@@ -2917,9 +3144,63 @@ + } + + found_devices++; ++#endif ++ if ((res = register_netdev(ndev))) ++ P_ERROR("Failed to register netdev. res = %d\n", res); + + TRACE; + ++ out: ++ return res; ++} ++ ++ ++static int __devinit npe_eth_init_device(struct device *dev) ++{ ++ int res = -ENOMEM; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct net_device *ndev = alloc_etherdev(sizeof(priv_data_t)); ++ TRACE; ++ if (ndev == NULL) { ++ P_ERROR("could not allocate device.\n"); ++ goto out; ++ } ++ SET_MODULE_OWNER(ndev); ++ SET_NETDEV_DEV(ndev, dev); ++ ixEthAccTxSchedulingDisciplineSet(pdev->id, FIFO_NO_PRIORITY); ++ dev_set_drvdata(dev, ndev); ++ res = dev_eth_probe(dev); ++ if (res == 0) { ++ /* This was added in v0.1.8 of the driver. It seems that we need to ++ * enable the port before the user can set a mac address for the port ++ * using 'ifconfig hw ether ...'. To enable the port we must first ++ * register Q callbacks, so we register the portDisable callbacks to ++ * ensure that no buffers are passed up to the kernel until the port is ++ * brought up properly (ifconfig up) ++ */ ++ ixEthAccPortTxDoneCallbackRegister(pdev->id, ++ tx_done_disable_cb, ++ (UINT32)ndev); ++ ixEthAccPortRxCallbackRegister(pdev->id, ++ rx_disable_cb, ++ (UINT32)ndev); ++ port_enable(ndev); ++ } else { ++ dev_set_drvdata(dev, NULL); ++ kfree(ndev); ++ } ++out: ++ TRACE; ++ return res; ++} ++ ++static int __devexit npe_eth_fini_device(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ TRACE; ++ dev_set_drvdata(dev, NULL); ++ unregister_netdev(ndev); ++ kfree(ndev); + return 0; + } + +@@ -2928,6 +3209,28 @@ + + #ifdef MODULE + ++#define MODULE_NAME "ixp400_eth" ++ ++static struct device_driver npe_eth_driver = { ++ .name = MODULE_NAME, ++ .bus = &platform_bus_type, ++ .probe = npe_eth_init_device, ++ .remove = npe_eth_fini_device, ++}; ++ ++static struct platform_device npe_eth_devs[] = { ++ { ++ .name = MODULE_NAME, ++ .id = IX_ETH_PORT_1, ++ }, ++ { ++ .name = MODULE_NAME, ++ .id = IX_ETH_PORT_2, ++ } ++}; ++ ++ ++ + static struct net_device ixp400_devices[IX_ETH_ACC_NUMBER_OF_PORTS]; + + int init_module(void) +@@ -2935,11 +3238,11 @@ + int res, dev_count; + IxEthAccPortId portId; + struct net_device *dev; +- ++ int i; + TRACE; + +- P_INFO("Initializing IXP400 NPE Ethernet driver software v. " MODULE_VERSION " \n"); +- ++ P_INFO("Initializing IXP400 NPE Ethernet driver software v. LE \n"); ++ ixOsalLogLevelSet(IX_OSAL_LOG_LVL_ALL); + TRACE; + + /* check module parameter range */ +@@ -2951,6 +3254,16 @@ + + TRACE; + ++ /* XXX do this very early */ ++ /* initialise the DB Maintenance task mutex */ ++ maintenance_mutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); ++ if (!maintenance_mutex) ++ return -ENOMEM; ++ ++ init_MUTEX(maintenance_mutex); ++ ++ TRACE; ++ + #ifndef DEBUG + /* check module parameter range */ + if (log_level >= 2) /* module parameter */ +@@ -3015,6 +3328,13 @@ + /* Initialise the NPEs and access layer */ + TRACE; + ++ for (i = 0; i < IX_ETH_ACC_NUMBER_OF_PORTS; i++) ++ { ++ if ((res = npe_start(i))) ++ return res; ++ TRACE; ++ } ++ + if ((res = ethacc_init())) + return res; + +@@ -3026,6 +3346,13 @@ + + TRACE; + ++ npe_eth_workqueue = create_workqueue(MODULE_NAME); ++ if (npe_eth_workqueue == NULL) ++ return -ENOMEM; ++ ++ TRACE; ++ ++#if 0 + /* Initialise the driver structure */ + for (dev_count = 0; + dev_count < dev_max_count; /* module parameter */ +@@ -3038,7 +3365,7 @@ + dev->init = dev_eth_probe; + + TRACE; +- ++ } + if ((res = register_netdev(dev))) + { + TRACE; +@@ -3068,6 +3395,35 @@ + return convert_error_ethAcc(res); + } + } ++#endif ++ /* set the softirq rx queue thresholds ++ * (These numbers are based on tuning experiments) ++ * maxbacklog = (netdev_max_backlog * 10) / 63; ++ */ ++ if (netdev_max_backlog == 0) ++ { ++ netdev_max_backlog = 290; /* system default */ ++ } ++ netdev_max_backlog /= BACKLOG_TUNE; ++ ++ TRACE; ++ ++ res = driver_register(&npe_eth_driver); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE EThernet driver (res = %d)\n", res); ++ return res; ++ } ++ ++ res = platform_device_register(&npe_eth_devs[0]); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE platform device 0 (res = %d)\n", res); ++ return res; ++ } ++ res = platform_device_register(&npe_eth_devs[1]); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE platform device 1 (res = %d)\n", res); ++ return res; ++ } + + TRACE; + +@@ -3104,33 +3460,13 @@ + } + + TRACE; +- +- /* initialise the DB Maintenance task mutex */ +- maintenance_mutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); +- if (!maintenance_mutex) +- return -ENOMEM; +- +- init_MUTEX(maintenance_mutex); +- +- TRACE; +- ++TRACE; + /* Do not start the EthDB maintenance thread if learning & filtering feature is disabled */ + if (npe_learning) /* module parameter */ + { +- maintenance_timer_set(); +- } +- +- TRACE; +- +- /* set the softirq rx queue thresholds +- * (These numbers are based on tuning experiments) +- * maxbacklog = (netdev_max_backlog * 10) / 63; +- */ +- if (netdev_max_backlog == 0) +- { +- netdev_max_backlog = 290; /* system default */ ++ schedule_db_maintenance(); ++ // maintenance_timer_set(); + } +- netdev_max_backlog /= BACKLOG_TUNE; + + TRACE; + +@@ -3175,7 +3511,8 @@ + TRACE; + + /* stop the maintenance timer */ +- maintenance_timer_clear(); ++ // maintenance_timer_clear(); ++ cancel_db_maintenance(); + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/makefile.patch b/recipes/ixp425-eth/ixp400-eth-1.4/makefile.patch new file mode 100644 index 0000000000..350485c1aa --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/makefile.patch @@ -0,0 +1,33 @@ +--- /dev/null 2005-09-06 00:17:15.000000000 -0700 ++++ ./Makefile 2005-10-02 22:15:19.974595551 -0700 +@@ -0,0 +1,30 @@ ++obj-m := ixp400_eth.o ++ ++CFLAGS_ixp400_eth.o = -DWall \ ++ -I$(IXP4XX_CSR_DIR) \ ++ -I$(OSAL_DIR)/ \ ++ -I$(OSAL_DIR)/os/linux/include/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/include/ \ ++ -I$(OSAL_DIR)/include/modules/ \ ++ -I$(OSAL_DIR)/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/include/modules/core/ \ ++ -I$(OSAL_DIR)/include/platforms/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/xp425/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425/ \ ++ $(IX_CFLAGS) ++ ++default: ++ $(MAKE) ARCH=arm CROSS_COMPILE=$(LINUX_CROSS_COMPILE) V=1 -C $(LINUX_SRC) SUBDIRS=$(PWD) modules ++ ++clean: ++ rm -f ixp400_eth.ko diff --git a/recipes/ixp425-eth/ixp400-eth-1.4/modprobe.conf b/recipes/ixp425-eth/ixp400-eth-1.4/modprobe.conf new file mode 100644 index 0000000000..9d579eeac1 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.4/modprobe.conf @@ -0,0 +1,3 @@ +# Add an alias for eth0 to ixp400_eth to cause the S40networking +# init script to load the ixp400_eth driver on the first boot +alias eth0 ixp400_eth diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.14.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.14.patch new file mode 100644 index 0000000000..fb55f92868 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.14.patch @@ -0,0 +1,28 @@ + ixp400_eth.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletion(-) + +Index: ixp400-eth-1.5.1-r0/ixp400_eth.c +=================================================================== +--- ixp400-eth-1.5.1-r0.orig/ixp400_eth.c ++++ ixp400-eth-1.5.1-r0/ixp400_eth.c +@@ -1848,7 +1848,11 @@ + skb->len -= header_len; + + /* fill the pkt arrival time (set at the irq callback entry) */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->stamp = irq_stamp; ++#else ++ skb_set_timestamp(skb, &irq_stamp); ++#endif + + /* fill the input device field */ + skb->dev = dev; +@@ -3040,7 +3044,7 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ +-int ixp400_dev_set_mac_address(struct net_device *dev, void *addr) ++static int ixp400_dev_set_mac_address(struct net_device *dev, void *addr) + { + int res; + IxEthAccMacAddr npeMacAddr; diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.15.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.15.patch new file mode 100644 index 0000000000..83115d8efa --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/2.6.15.patch @@ -0,0 +1,18 @@ +2.6.15 needs platform_device.h + + ixp400_eth.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -65,6 +65,10 @@ + #include <linux/sysctl.h> + #include <linux/unistd.h> + ++#ifndef to_platform_device ++#include <linux/platform_device.h> ++#endif ++ + /* + * Intel IXP400 Software specific header files + */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/Makefile.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/Makefile.patch new file mode 100644 index 0000000000..3bc51f0b66 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/Makefile.patch @@ -0,0 +1,36 @@ +This is an OpenEmbedded only patch to make the code buildable in +the OpenEmbedded environment. + +--- ixp400-eth/Makefile 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/Makefile 1970-01-01 00:00:00.000000000 +0000 +@@ -0,0 +1,30 @@ ++obj-m := ixp400_eth.o ++ ++CFLAGS_ixp400_eth.o = -DWall \ ++ -I$(IXP4XX_CSR_DIR) \ ++ -I$(OSAL_DIR)/ \ ++ -I$(OSAL_DIR)/os/linux/include/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/include/ \ ++ -I$(OSAL_DIR)/include/modules/ \ ++ -I$(OSAL_DIR)/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/include/modules/core/ \ ++ -I$(OSAL_DIR)/include/platforms/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/xp425/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425/ \ ++ $(IX_CFLAGS) ++ ++default: ++ $(MAKE) ARCH=arm CROSS_COMPILE=$(LINUX_CROSS_COMPILE) $(KERNEL_VERBOSE) symverfile=$(IXP4XX_CSR_SYMVERS) -C $(LINUX_SRC) SUBDIRS=$(PWD) modules ++ ++clean: ++ rm -f ixp400_eth.ko diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/continue-if-qmgr-init-fails.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/continue-if-qmgr-init-fails.patch new file mode 100644 index 0000000000..8508790fa5 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/continue-if-qmgr-init-fails.patch @@ -0,0 +1,22 @@ +tries to go on even if queue manager initialization +fails. this is hand because you'll be allowed to +insert ixp400_eth immediately after you have removed +it, without re-inserting ixp400. + + ixp400_eth.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2850,10 +2850,7 @@ static int qmgr_init(void) + /* Initialise Queue Manager */ + P_VERBOSE("Initialising Queue Manager...\n"); + if ((res = ixQMgrInit())) +- { +- P_ERROR("Error initialising queue manager!\n"); +- return -1; +- } ++ P_ERROR("Error initialising queue manager, trying to continue!\n"); + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/debug.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/debug.patch new file mode 100644 index 0000000000..c684c078d2 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/debug.patch @@ -0,0 +1,131 @@ +This patch is not necessary but helps when debugging the build + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -1350,9 +1350,10 @@ static int dev_media_check_thread (void* + + if (res != IX_ETH_ACC_SUCCESS) + { +- P_WARN("ixEthMiiLinkStatus failed on PHY%d.\n" ++ P_WARN("%s: ixEthMiiLinkStatus failed on PHY%d.\n" + "\tCan't determine\nthe auto negotiated parameters. " + "Using default values.\n", ++ dev->name, + phyNum); + /* something is bad, gracefully stops the loop */ + priv->maintenanceCheckStopped = TRUE; +@@ -2213,7 +2214,8 @@ static int port_enable(struct net_device + IX_IEEE803_MAC_ADDRESS_SIZE); + if ((res = ixEthAccPortUnicastMacAddressSet(priv->port_id, &npeMacAddr))) + { +- P_VERBOSE("Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ P_VERBOSE("%s: Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ dev->name, + (unsigned)npeMacAddr.macAddress[0], + (unsigned)npeMacAddr.macAddress[1], + (unsigned)npeMacAddr.macAddress[2], +@@ -2707,8 +2709,8 @@ static int do_dev_ioctl(struct net_devic + down (miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiReadRtn (data->phy_id, data->reg_num, &data->val_out))) + { +- P_ERROR("Error reading MII reg %d on phy %d\n", +- data->reg_num, data->phy_id); ++ P_ERROR("%s: Error reading MII reg %d on phy %d\n", ++ dev->name, data->reg_num, data->phy_id); + res = -1; + } + up (miiAccessMutex); /* release the MII register access mutex */ +@@ -2720,8 +2722,8 @@ static int do_dev_ioctl(struct net_devic + down (miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiWriteRtn (data->phy_id, data->reg_num, data->val_in))) + { +- P_ERROR("Error writing MII reg %d on phy %d\n", +- data->reg_num, data->phy_id); ++ P_ERROR("%s: Error writing MII reg %d on phy %d\n", ++ dev->name, data->reg_num, data->phy_id); + res = -1; + } + up (miiAccessMutex); /* release the MII register access mutex */ +@@ -3049,7 +3051,8 @@ static int set_mac_address(struct net_de + /* Set MAC addr in h/w (ethAcc checks for MAC address to be valid) */ + if ((res = ixEthAccPortUnicastMacAddressSet(priv->port_id, &npeMacAddr))) + { +- P_VERBOSE("Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ P_VERBOSE("%s: Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ dev->name, + (unsigned)npeMacAddr.macAddress[0], + (unsigned)npeMacAddr.macAddress[1], + (unsigned)npeMacAddr.macAddress[2], +@@ -3267,6 +3270,8 @@ static int __devinit dev_eth_probe(struc + kmalloc(sizeof(struct semaphore), GFP_KERNEL); + if (!priv->maintenanceCheckThreadComplete) + { ++ P_ERROR("%s: Failed to allocate maintenance semaphore %d\n", ++ ndev->name, priv->port_id); + goto error; + } + priv->lock = SPIN_LOCK_UNLOCKED; +@@ -3360,7 +3365,11 @@ static int __devinit dev_eth_probe(struc + + #if IS_KERNEL26 + if (register_netdev(ndev)) ++ { ++ P_ERROR("%s: Failed to register netdevice %d\n", ++ ndev->name, priv->port_id); + goto error; ++ } + #else + found_devices++; + #endif /* IS_KERNEL26 */ +@@ -3370,6 +3379,8 @@ static int __devinit dev_eth_probe(struc + /* register EthAcc callbacks for this port */ + if (dev_rxtxcallback_register(portId, (UINT32)ndev)) + { ++ P_ERROR("%s: Failed to register callback %d\n", ++ ndev->name, priv->port_id); + goto error; + } + +@@ -3393,6 +3404,7 @@ static int __devinit dev_eth_probe(struc + + /* Error handling: enter here whenever error detected */ + error: ++ P_ERROR("%s: dev_eth_probe fails\n", ndev->name); + TRACE; + + #ifdef CONFIG_IXP400_ETH_QDISC_ENABLED +@@ -3465,21 +3477,21 @@ static int __devexit dev_eth_remove(int + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEA)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + if (default_npeImageId[portId] == IX_ETH_NPE_B_IMAGE_ID) + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEB)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + if (default_npeImageId[portId] == IX_ETH_NPE_C_IMAGE_ID) + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEC)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + +@@ -3528,6 +3540,9 @@ static int __init ixp400_eth_init(void) + TRACE; + + P_INFO("Initializing IXP400 NPE Ethernet driver software v. " MOD_VERSION " \n"); ++#ifdef IX_OSAL_ENSURE_ON ++ ixOsalLogLevelSet(IX_OSAL_LOG_LVL_ALL); ++#endif + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/device-name.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/device-name.patch new file mode 100644 index 0000000000..492c9274fd --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/device-name.patch @@ -0,0 +1,49 @@ + register the ethernet devices as ethX + + ixp400_eth.c | 12 +++--------- + 1 files changed, 3 insertions(+), 9 deletions(-) + +Index: ixp400-eth-1.5.1-r0/ixp400_eth.c +=================================================================== +--- ixp400-eth-1.5.1-r0.orig/ixp400_eth.c ++++ ixp400-eth-1.5.1-r0/ixp400_eth.c +@@ -160,9 +160,6 @@ + MODULE_PARM(dev_max_count, "i"); + MODULE_PARM_DESC(dev_max_count, "Number of devices to initialize"); + +-/* devices will be called ixp0 and ixp1 */ +-#define DEVICE_NAME "ixp" +- + /* boolean values for PHY link speed, duplex, and autonegotiation */ + #define PHY_SPEED_10 0 + #define PHY_SPEED_100 1 +@@ -1579,7 +1576,7 @@ + if (request_irq(IX_OSAL_IXP400_XSCALE_PMU_IRQ_LVL, + dev_pmu_timer_os_isr, + SA_SHIRQ, +- DEVICE_NAME, ++ MODULE_NAME, + (void *)IRQ_ANY_PARAMETER)) + { + P_ERROR("Failed to reassign irq to PMU timer interrupt!\n"); +@@ -3035,8 +3032,8 @@ + if (port_id == IX_ETH_PORT_2) npe_id = "C"; + if (port_id == IX_ETH_PORT_3) npe_id = "A"; + +- P_INFO("%s%d is using NPE%s and the PHY at address %d\n", +- DEVICE_NAME, port_id, npe_id, phyAddresses[port_id]); ++ P_INFO("ethernet %d is using NPE%s and the PHY at address %d\n", ++ dev_count, npe_id, phyAddresses[port_id]); + + /* Set the MAC to the same duplex mode as the phy */ + ixEthAccPortDuplexModeSet(port_id, +@@ -3244,9 +3241,6 @@ + /* set the private port ID */ + priv->port_id = portId; + +- /* set device name */ +- sprintf(ndev->name, DEVICE_NAME"%d", priv->port_id); +- + TRACE; + + /* initialize RX pool */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/int-random.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/int-random.patch new file mode 100644 index 0000000000..fede9daf90 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/int-random.patch @@ -0,0 +1,16 @@ +use the ethernet device interrupts to gather entropy + + ixp400_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2864,7 +2864,7 @@ static int qmgr_init(void) + + if (request_irq(IX_OSAL_IXP400_QM1_IRQ_LVL, + dev_qmgr_os_isr, +- SA_SHIRQ, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, + MODULE_NAME, + (void *)IRQ_ANY_PARAMETER)) + { diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/le.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/le.patch new file mode 100644 index 0000000000..3d569015e6 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/le.patch @@ -0,0 +1,41 @@ +little endian support + + ixp400_eth.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2040,6 +2040,16 @@ static void rx_cb(UINT32 callbackTag, IX + skb->tail = skb->data + len; + skb->len = len; + ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif ++ + #ifdef DEBUG_DUMP + skb_dump("rx", skb); + #endif +@@ -2431,6 +2441,16 @@ static int dev_hard_start_xmit(struct sk + return 0; + } + ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif ++ + #ifdef DEBUG_DUMP + skb_dump("tx", skb); + #endif diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/mac-address.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/mac-address.patch new file mode 100644 index 0000000000..e23eaf5f2b --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/mac-address.patch @@ -0,0 +1,123 @@ +Patch to use maclist - get the MAC to use from the board level +MAC repository based on the device portId. + +Signed-off-by: John Bowler <jbowler@acm.org> + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -23,10 +23,10 @@ + * This driver is written and optimized for Intel Xscale technology. + * + * SETUP NOTES: +- * By default, this driver uses predefined MAC addresses. +- * These are set in global var 'default_mac_addr' in this file. +- * If required, these can be changed at run-time using +- * the 'ifconfig' tool. ++ * By default, this driver uses MAC addresses from maclist, if ++ * these are not available the kernel api to randomly generate ++ * a locally assigned MAC address is used. The MAC can be ++ * overridden with ifconfig if absolutely necessary. + * + * Example - to set ixp0 MAC address to 00:02:B3:66:88:AA, + * run ifconfig with the following arguments: +@@ -64,6 +64,7 @@ + #include <linux/sysctl.h> + #include <linux/unistd.h> + #include <linux/version.h> ++#include <net/maclist.h> + + #if KERNEL_VERSION(2,6,0) <= LINUX_VERSION_CODE + #include <linux/workqueue.h> +@@ -130,6 +131,8 @@ static int dev_max_count = 1; /* only NP + static int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) + static int dev_max_count = 3; /* all NPEs are used */ ++#else ++static int dev_max_count = -1;/* use maclist_count */ + #endif + + #ifndef CONFIG_IXP400_NAPI +@@ -614,21 +617,6 @@ static phy_cfg_t default_phy_cfg[] = + #endif + }; + +-/* Default MAC addresses for EthAcc Ports 1 and 2 (using Intel MAC prefix) +- * Default is +- * IX_ETH_PORT_1 -> MAC 00:02:b3:01:01:01 +- * IX_ETH_PORT_2 -> MAC 00:02:b3:02:02:02 +- * IX_ETH_PORT_3 -> MAC 00:02:b3:03:03:03 +-*/ +-static IxEthAccMacAddr default_mac_addr[] = +-{ +- {{0x00, 0x02, 0xB3, 0x01, 0x01, 0x01}} /* EthAcc Port 0 */ +- ,{{0x00, 0x02, 0xB3, 0x02, 0x02, 0x02}} /* EthAcc Port 1 */ +-#if defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +- ,{{0x00, 0x02, 0xB3, 0x03, 0x03, 0x03}} /* EthAcc Port 2 */ +-#endif +-}; +- + /* Default mapping of NpeImageIds for EthAcc Ports + * Default is + * IX_ETH_PORT_1 -> IX_ETH_NPE_B +@@ -3325,28 +3313,10 @@ static int __devinit dev_eth_probe(struc + + /* Defines the unicast MAC address + * +- * Here is a good place to read a board-specific MAC address +- * from a non-volatile memory, e.g. an external eeprom. +- * +- * This memcpy uses a default MAC address from this +- * source code. +- * +- * This can be overriden later by the (optional) command +- * +- * ifconfig ixp0 ether 0002b3010101 +- * ++ * The code reads from the maclist API. + */ +- +- memcpy(ndev->dev_addr, +- &default_mac_addr[priv->port_id].macAddress, +- IX_IEEE803_MAC_ADDRESS_SIZE); +- +- /* possibly remove this test and the message when a valid MAC address +- * is not hardcoded in the driver source code. +- */ +- if (is_valid_ether_addr(ndev->dev_addr)) +- { +- P_WARN("Use default MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ maclist_read((u8(*)[6])&ndev->dev_addr, priv->port_id); ++ P_INFO("Use MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", + (unsigned)ndev->dev_addr[0], + (unsigned)ndev->dev_addr[1], + (unsigned)ndev->dev_addr[2], +@@ -3354,7 +3324,6 @@ static int __devinit dev_eth_probe(struc + (unsigned)ndev->dev_addr[4], + (unsigned)ndev->dev_addr[5], + priv->port_id); +- } + + /* Set/update the internal packet size + * This can be overriden later by the command +@@ -3562,12 +3531,15 @@ static int __init ixp400_eth_init(void) + + TRACE; + +- /* check module parameter range */ +- if (dev_max_count == 0 || dev_max_count > IX_ETH_ACC_NUMBER_OF_PORTS) +- { +- P_ERROR("Number of ports supported is dev_max_count <= %d\n", IX_ETH_ACC_NUMBER_OF_PORTS); +- return -1; +- } ++ /* fix dev_max_count to maclist_count - the actual number of ++ * available MACs ++ */ ++ if (dev_max_count <= 0 || (dev_max_count > maclist_count() && maclist_count() > 0)) ++ dev_max_count = maclist_count(); ++ if (dev_max_count <= 0) ++ dev_max_count = 1; ++ else if (dev_max_count > IX_ETH_ACC_NUMBER_OF_PORTS) ++ dev_max_count = IX_ETH_ACC_NUMBER_OF_PORTS; + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/modprobe.conf b/recipes/ixp425-eth/ixp400-eth-1.5.1/modprobe.conf new file mode 100644 index 0000000000..f08b9a404c --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/modprobe.conf @@ -0,0 +1,4 @@ +# Add an alias for eth0 to ixp400_eth to cause the S40networking +# init script to load the ixp400_eth driver on the first boot +alias eth0 ixp400_eth +options ixp400_eth dev_max_count=1
\ No newline at end of file diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/module-param.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/module-param.patch new file mode 100644 index 0000000000..c54c45d716 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/module-param.patch @@ -0,0 +1,62 @@ + ixp400_eth.c | 32 ++++++++++++++++++++++++++++++++ + 1 files changed, 32 insertions(+) + +Index: ixp400_eth/ixp400_eth.c +=================================================================== +--- ixp400_eth.orig/ixp400_eth.c ++++ ixp400_eth/ixp400_eth.c +@@ -142,22 +142,54 @@ + + static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(ixp400_netdev_max_backlog, "i"); ++#else ++module_param(ixp400_netdev_max_backlog, int, 0644); ++#endif + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(datapath_poll, "i"); ++#else ++module_param(datapath_poll, int, 0644); ++#endif + MODULE_PARM_DESC(datapath_poll, "If non-zero, use polling method for datapath instead of interrupts"); + #endif /* CONFIG_IXP400_NAPI */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(npe_learning, "i"); ++#else ++module_param(npe_learning, int, 0644); ++#endif + MODULE_PARM_DESC(npe_learning, "If non-zero, NPE MAC Address Learning & Filtering feature will be enabled"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(log_level, "i"); ++#else ++module_param(log_level, int, 0644); ++#endif + MODULE_PARM_DESC(log_level, "Set log level: 0 - None, 1 - Verbose, 2 - Debug"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(no_ixp400_sw_init, "i"); ++#else ++module_param(no_ixp400_sw_init, int, 0644); ++#endif + MODULE_PARM_DESC(no_ixp400_sw_init, "If non-zero, do not initialise Intel IXP400 Software Release core components"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(no_phy_scan, "i"); ++#else ++module_param(no_phy_scan, int, 0644); ++#endif + MODULE_PARM_DESC(no_phy_scan, "If non-zero, use hard-coded phy addresses"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(phy_reset, "i"); ++#else ++module_param(phy_reset, int, 0644); ++#endif + MODULE_PARM_DESC(phy_reset, "If non-zero, reset the phys"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(dev_max_count, "i"); ++#else ++module_param(dev_max_count, int, 0644); ++#endif + MODULE_PARM_DESC(dev_max_count, "Number of devices to initialize"); + + /* boolean values for PHY link speed, duplex, and autonegotiation */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/netdev_max_backlog.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/netdev_max_backlog.patch new file mode 100644 index 0000000000..6891b6b4a9 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/netdev_max_backlog.patch @@ -0,0 +1,54 @@ +--- ixp400_eth/ixp400_eth.c~ 2006-01-09 01:03:11.000000000 +1030 ++++ ixp400_eth/ixp400_eth.c 2006-01-09 01:05:27.000000000 +1030 +@@ -139,12 +139,12 @@ + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +-static int netdev_max_backlog = 290; ++static int ixp400_netdev_max_backlog = 290; + + static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + +-MODULE_PARM(netdev_max_backlog, "i"); +-MODULE_PARM_DESC(netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); ++MODULE_PARM(ixp400_netdev_max_backlog, "i"); ++MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); + MODULE_PARM(datapath_poll, "i"); + MODULE_PARM_DESC(datapath_poll, "If non-zero, use polling method for datapath instead of interrupts"); + #endif /* CONFIG_IXP400_NAPI */ +@@ -213,7 +213,7 @@ + * high traffic rates. To measure the maximum throughput between the + * ports of the driver, + * - Modify /proc/sys/net/core/netdev_max_backlog value in the kernel +- * - Adjust netdev_max_backlog=n in the driver's command line ++ * - Adjust ixp400_netdev_max_backlog=n in the driver's command line + * in order to get the best rates depending on the testing tool + * and the OS load. + * +@@ -1997,7 +1997,7 @@ + /* check if the system accepts more traffic and + * against chained mbufs + */ +- if ((qlevel < netdev_max_backlog) ++ if ((qlevel < ixp400_netdev_max_backlog) + && (IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(mbuf) == NULL)) + #else + /* check against chained mbufs +@@ -3776,13 +3776,13 @@ + #ifndef CONFIG_IXP400_NAPI + /* set the softirq rx queue thresholds + * (These numbers are based on tuning experiments) +- * maxbacklog = (netdev_max_backlog * 10) / 63; ++ * maxbacklog = (ixp400_netdev_max_backlog * 10) / 63; + */ +- if (netdev_max_backlog == 0) ++ if (ixp400_netdev_max_backlog == 0) + { +- netdev_max_backlog = 290; /* system default */ ++ ixp400_netdev_max_backlog = 290; /* system default */ + } +- netdev_max_backlog /= BACKLOG_TUNE; ++ ixp400_netdev_max_backlog /= BACKLOG_TUNE; + + TRACE; + #endif diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/params.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/params.patch new file mode 100644 index 0000000000..86011deaaa --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/params.patch @@ -0,0 +1,75 @@ +*** ixp/ixp400_eth.c.orig Wed Jun 7 21:31:59 2006 +--- ixp/ixp400_eth.c Fri Jun 9 14:55:18 2006 +*************** +*** 112,135 **** + #define MOD_VERSION "1.5" + + /* Module parameters */ +! static int npe_learning = 1; /* default : NPE learning & filtering enable */ +! static int log_level = 0; /* default : no log */ +! static int no_ixp400_sw_init = 0; /* default : init core components of the IXP400 Software */ +! static int no_phy_scan = 0; /* default : do phy discovery */ +! static int phy_reset = 0; /* default : mo phy reset */ + + /* maximum number of ports supported by this driver ixp0, ixp1 .... + * The default is to configure all ports defined in EthAcc component + */ + #ifdef CONFIG_IXP400_ETH_NPEC_ONLY +! static int dev_max_count = 1; /* only NPEC is used */ +! #elif defined (CONFIG_IXP400_ETH_NPEB_ONLY) +! static int dev_max_count = 1; /* only NPEB is used */ + #elif defined (CONFIG_ARCH_IXDP425) || defined(CONFIG_ARCH_IXDPG425)\ + || defined (CONFIG_ARCH_ADI_COYOTE) +! static int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +! static int dev_max_count = 3; /* all NPEs are used */ + #endif + + #ifndef CONFIG_IXP400_NAPI +--- 112,136 ---- + #define MOD_VERSION "1.5" + + /* Module parameters */ +! /* gcc 4.1.1+kernel2.6.16 do not like it if these are static! */ +! int npe_learning = 1; /* default : NPE learning & filtering enable */ +! int log_level = 0; /* default : no log */ +! int no_ixp400_sw_init = 0; /* default : init core components of the IXP400 Software */ +! int no_phy_scan = 0; /* default : do phy discovery */ +! int phy_reset = 0; /* default : mo phy reset */ + + /* maximum number of ports supported by this driver ixp0, ixp1 .... + * The default is to configure all ports defined in EthAcc component + */ + #ifdef CONFIG_IXP400_ETH_NPEC_ONLY +! int dev_max_count = 1; /* only NPEC is used */ +! #elif defined (CONFIG_IXP400_ETH_NPEB_ONLY) +! int dev_max_count = 1; /* only NPEB is used */ + #elif defined (CONFIG_ARCH_IXDP425) || defined(CONFIG_ARCH_IXDPG425)\ + || defined (CONFIG_ARCH_ADI_COYOTE) +! int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +! int dev_max_count = 3; /* all NPEs are used */ + #endif + + #ifndef CONFIG_IXP400_NAPI +*************** +*** 138,146 **** + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +! static int ixp400_netdev_max_backlog = 290; + +! static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + + MODULE_PARM(ixp400_netdev_max_backlog, "i"); + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); +--- 139,147 ---- + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +! int ixp400_netdev_max_backlog = 290; + +! int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + + MODULE_PARM(ixp400_netdev_max_backlog, "i"); + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/poll-controller.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/poll-controller.patch new file mode 100644 index 0000000000..64fb310ee5 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/poll-controller.patch @@ -0,0 +1,50 @@ +poll controller support + + ixp400_eth.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -348,6 +348,12 @@ static int dev_pmu_timer_init(void); + extern void + ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId); + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* poll controller (needed for netconsole et al) */ ++static void ++ixp425eth_poll_controller(struct net_device *dev); ++#endif ++ + /* Private device data */ + typedef struct { + spinlock_t lock; /* multicast management lock */ +@@ -3060,6 +3066,19 @@ static int set_mac_address(struct net_de + return 0; + } + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling receive - used by netconsole and other diagnostic tools ++ * to allow network i/o with interrupts disabled. ++ * (stolen from 8139too.c by siddy) ++ */ ++static void ixp425eth_poll_controller(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ dev_qmgr_os_isr(dev->irq, dev, NULL); ++ enable_irq(dev->irq); ++} ++#endif + + /* + * TX QDISC +@@ -3270,6 +3289,9 @@ static int __devinit dev_eth_probe(struc + ndev->get_stats = dev_get_stats; + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ ndev->poll_controller = ixp425eth_poll_controller; ++#endif + + ndev->set_mac_address = set_mac_address; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5.1/stop-on-rmmod.patch b/recipes/ixp425-eth/ixp400-eth-1.5.1/stop-on-rmmod.patch new file mode 100644 index 0000000000..2ddc98938a --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5.1/stop-on-rmmod.patch @@ -0,0 +1,29 @@ +devices must be explicitely stopped when +the driver is going do be removed, otherwise +it will simply hang. + + ixp400_eth.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -3800,9 +3800,16 @@ void __exit ixp400_eth_exit(void) + + TRACE; + +- /* We can only get here when the module use count is 0, +- * so there's no need to stop devices. +- */ ++ /* stop devices */ ++ ++#if IS_KERNEL26 ++ for (dev_count = 0; ++ dev_count < dev_max_count; /* module parameter */ ++ dev_count++) ++ { ++ do_dev_stop(platform_get_drvdata(&ixp400_eth_devices[dev_count])); ++ } ++#endif + + if (no_ixp400_sw_init == 0) /* module parameter */ + { diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/2.6.14.patch b/recipes/ixp425-eth/ixp400-eth-1.5/2.6.14.patch new file mode 100644 index 0000000000..f3426e4287 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/2.6.14.patch @@ -0,0 +1,35 @@ + ixp400_eth.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -1838,7 +1838,11 @@ static inline void dev_eth_type_trans(un + skb->len -= header_len; + + /* fill the pkt arrival time (set at the irq callback entry) */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->stamp = irq_stamp; ++#else ++ skb_set_timestamp(skb, &irq_stamp); ++#endif + + /* fill the input device field */ + skb->dev = dev; +@@ -3014,7 +3018,7 @@ static int phy_init(void) + } + + /* set port MAC addr and update the dev struct if successfull */ +-int dev_set_mac_address(struct net_device *dev, void *addr) ++static int set_mac_address(struct net_device *dev, void *addr) + { + int res; + IxEthAccMacAddr npeMacAddr; +@@ -3266,7 +3270,7 @@ static int __devinit dev_eth_probe(struc + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; + +- ndev->set_mac_address = dev_set_mac_address; ++ ndev->set_mac_address = set_mac_address; + + #ifdef CONFIG_IXP400_NAPI + ndev->poll = &dev_rx_poll; diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/2.6.15.patch b/recipes/ixp425-eth/ixp400-eth-1.5/2.6.15.patch new file mode 100644 index 0000000000..83115d8efa --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/2.6.15.patch @@ -0,0 +1,18 @@ +2.6.15 needs platform_device.h + + ixp400_eth.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -65,6 +65,10 @@ + #include <linux/sysctl.h> + #include <linux/unistd.h> + ++#ifndef to_platform_device ++#include <linux/platform_device.h> ++#endif ++ + /* + * Intel IXP400 Software specific header files + */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/Makefile.patch b/recipes/ixp425-eth/ixp400-eth-1.5/Makefile.patch new file mode 100644 index 0000000000..3bc51f0b66 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/Makefile.patch @@ -0,0 +1,36 @@ +This is an OpenEmbedded only patch to make the code buildable in +the OpenEmbedded environment. + +--- ixp400-eth/Makefile 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/Makefile 1970-01-01 00:00:00.000000000 +0000 +@@ -0,0 +1,30 @@ ++obj-m := ixp400_eth.o ++ ++CFLAGS_ixp400_eth.o = -DWall \ ++ -I$(IXP4XX_CSR_DIR) \ ++ -I$(OSAL_DIR)/ \ ++ -I$(OSAL_DIR)/os/linux/include/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/include/ \ ++ -I$(OSAL_DIR)/include/modules/ \ ++ -I$(OSAL_DIR)/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/include/modules/core/ \ ++ -I$(OSAL_DIR)/include/platforms/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/xp425/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ixp425/ \ ++ $(IX_CFLAGS) ++ ++default: ++ $(MAKE) ARCH=arm CROSS_COMPILE=$(LINUX_CROSS_COMPILE) $(KERNEL_VERBOSE) symverfile=$(IXP4XX_CSR_SYMVERS) -C $(LINUX_SRC) SUBDIRS=$(PWD) modules ++ ++clean: ++ rm -f ixp400_eth.ko diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/continue-if-qmgr-init-fails.patch b/recipes/ixp425-eth/ixp400-eth-1.5/continue-if-qmgr-init-fails.patch new file mode 100644 index 0000000000..8508790fa5 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/continue-if-qmgr-init-fails.patch @@ -0,0 +1,22 @@ +tries to go on even if queue manager initialization +fails. this is hand because you'll be allowed to +insert ixp400_eth immediately after you have removed +it, without re-inserting ixp400. + + ixp400_eth.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2850,10 +2850,7 @@ static int qmgr_init(void) + /* Initialise Queue Manager */ + P_VERBOSE("Initialising Queue Manager...\n"); + if ((res = ixQMgrInit())) +- { +- P_ERROR("Error initialising queue manager!\n"); +- return -1; +- } ++ P_ERROR("Error initialising queue manager, trying to continue!\n"); + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/debug.patch b/recipes/ixp425-eth/ixp400-eth-1.5/debug.patch new file mode 100644 index 0000000000..c684c078d2 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/debug.patch @@ -0,0 +1,131 @@ +This patch is not necessary but helps when debugging the build + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -1350,9 +1350,10 @@ static int dev_media_check_thread (void* + + if (res != IX_ETH_ACC_SUCCESS) + { +- P_WARN("ixEthMiiLinkStatus failed on PHY%d.\n" ++ P_WARN("%s: ixEthMiiLinkStatus failed on PHY%d.\n" + "\tCan't determine\nthe auto negotiated parameters. " + "Using default values.\n", ++ dev->name, + phyNum); + /* something is bad, gracefully stops the loop */ + priv->maintenanceCheckStopped = TRUE; +@@ -2213,7 +2214,8 @@ static int port_enable(struct net_device + IX_IEEE803_MAC_ADDRESS_SIZE); + if ((res = ixEthAccPortUnicastMacAddressSet(priv->port_id, &npeMacAddr))) + { +- P_VERBOSE("Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ P_VERBOSE("%s: Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ dev->name, + (unsigned)npeMacAddr.macAddress[0], + (unsigned)npeMacAddr.macAddress[1], + (unsigned)npeMacAddr.macAddress[2], +@@ -2707,8 +2709,8 @@ static int do_dev_ioctl(struct net_devic + down (miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiReadRtn (data->phy_id, data->reg_num, &data->val_out))) + { +- P_ERROR("Error reading MII reg %d on phy %d\n", +- data->reg_num, data->phy_id); ++ P_ERROR("%s: Error reading MII reg %d on phy %d\n", ++ dev->name, data->reg_num, data->phy_id); + res = -1; + } + up (miiAccessMutex); /* release the MII register access mutex */ +@@ -2720,8 +2722,8 @@ static int do_dev_ioctl(struct net_devic + down (miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiWriteRtn (data->phy_id, data->reg_num, data->val_in))) + { +- P_ERROR("Error writing MII reg %d on phy %d\n", +- data->reg_num, data->phy_id); ++ P_ERROR("%s: Error writing MII reg %d on phy %d\n", ++ dev->name, data->reg_num, data->phy_id); + res = -1; + } + up (miiAccessMutex); /* release the MII register access mutex */ +@@ -3049,7 +3051,8 @@ static int set_mac_address(struct net_de + /* Set MAC addr in h/w (ethAcc checks for MAC address to be valid) */ + if ((res = ixEthAccPortUnicastMacAddressSet(priv->port_id, &npeMacAddr))) + { +- P_VERBOSE("Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ P_VERBOSE("%s: Failed to set MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ dev->name, + (unsigned)npeMacAddr.macAddress[0], + (unsigned)npeMacAddr.macAddress[1], + (unsigned)npeMacAddr.macAddress[2], +@@ -3267,6 +3270,8 @@ static int __devinit dev_eth_probe(struc + kmalloc(sizeof(struct semaphore), GFP_KERNEL); + if (!priv->maintenanceCheckThreadComplete) + { ++ P_ERROR("%s: Failed to allocate maintenance semaphore %d\n", ++ ndev->name, priv->port_id); + goto error; + } + priv->lock = SPIN_LOCK_UNLOCKED; +@@ -3360,7 +3365,11 @@ static int __devinit dev_eth_probe(struc + + #if IS_KERNEL26 + if (register_netdev(ndev)) ++ { ++ P_ERROR("%s: Failed to register netdevice %d\n", ++ ndev->name, priv->port_id); + goto error; ++ } + #else + found_devices++; + #endif /* IS_KERNEL26 */ +@@ -3370,6 +3379,8 @@ static int __devinit dev_eth_probe(struc + /* register EthAcc callbacks for this port */ + if (dev_rxtxcallback_register(portId, (UINT32)ndev)) + { ++ P_ERROR("%s: Failed to register callback %d\n", ++ ndev->name, priv->port_id); + goto error; + } + +@@ -3393,6 +3404,7 @@ static int __devinit dev_eth_probe(struc + + /* Error handling: enter here whenever error detected */ + error: ++ P_ERROR("%s: dev_eth_probe fails\n", ndev->name); + TRACE; + + #ifdef CONFIG_IXP400_ETH_QDISC_ENABLED +@@ -3465,21 +3477,21 @@ static int __devexit dev_eth_remove(int + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEA)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + if (default_npeImageId[portId] == IX_ETH_NPE_B_IMAGE_ID) + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEB)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + if (default_npeImageId[portId] == IX_ETH_NPE_C_IMAGE_ID) + { + if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEC)) + { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); ++ P_NOTICE("%s: Error Halting NPE for Ethernet port %d!\n", ndev->name, portId); + } + } + +@@ -3528,6 +3540,9 @@ static int __init ixp400_eth_init(void) + TRACE; + + P_INFO("Initializing IXP400 NPE Ethernet driver software v. " MOD_VERSION " \n"); ++#ifdef IX_OSAL_ENSURE_ON ++ ixOsalLogLevelSet(IX_OSAL_LOG_LVL_ALL); ++#endif + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/device-name.patch b/recipes/ixp425-eth/ixp400-eth-1.5/device-name.patch new file mode 100644 index 0000000000..d8bbc97b8c --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/device-name.patch @@ -0,0 +1,47 @@ + register the ethernet devices as ethX + + ixp400_eth.c | 41 +++++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 22 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -160,9 +160,6 @@ MODULE_PARM_DESC(phy_reset, "If non-zero + MODULE_PARM(dev_max_count, "i"); + MODULE_PARM_DESC(dev_max_count, "Number of devices to initialize"); + +-/* devices will be called ixp0 and ixp1 */ +-#define DEVICE_NAME "ixp" +- + /* boolean values for PHY link speed, duplex, and autonegotiation */ + #define PHY_SPEED_10 0 + #define PHY_SPEED_100 1 +@@ -1570,7 +1568,7 @@ static int dev_pmu_timer_setup(void) + if (request_irq(IX_OSAL_IXP400_XSCALE_PMU_IRQ_LVL, + dev_pmu_timer_os_isr, + SA_SHIRQ, +- DEVICE_NAME, ++ MODULE_NAME, + (void *)IRQ_ANY_PARAMETER)) + { + P_ERROR("Failed to reassign irq to PMU timer interrupt!\n"); +@@ -3009,8 +3008,8 @@ static int phy_init(void) + if (port_id == IX_ETH_PORT_2) npe_id = "C"; + if (port_id == IX_ETH_PORT_3) npe_id = "A"; + +- P_INFO("%s%d is using NPE%s and the PHY at address %d\n", +- DEVICE_NAME, dev_count, npe_id, phyAddresses[port_id]); ++ P_INFO("ethernet %d using NPE%s and the PHY at address %d\n", ++ dev_count, npe_id, phyAddresses[port_id]); + + /* Set the MAC to the same duplex mode as the phy */ + ixEthAccPortDuplexModeSet(port_id, +@@ -3215,9 +3215,6 @@ static int __devinit dev_eth_probe(struc + /* set the private port ID */ + priv->port_id = portId; + +- /* set device name */ +- sprintf(ndev->name, DEVICE_NAME"%d", priv->port_id); +- + TRACE; + + /* initialize RX pool */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/int-random.patch b/recipes/ixp425-eth/ixp400-eth-1.5/int-random.patch new file mode 100644 index 0000000000..fede9daf90 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/int-random.patch @@ -0,0 +1,16 @@ +use the ethernet device interrupts to gather entropy + + ixp400_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2864,7 +2864,7 @@ static int qmgr_init(void) + + if (request_irq(IX_OSAL_IXP400_QM1_IRQ_LVL, + dev_qmgr_os_isr, +- SA_SHIRQ, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, + MODULE_NAME, + (void *)IRQ_ANY_PARAMETER)) + { diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/le.patch b/recipes/ixp425-eth/ixp400-eth-1.5/le.patch new file mode 100644 index 0000000000..3d569015e6 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/le.patch @@ -0,0 +1,41 @@ +little endian support + + ixp400_eth.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -2040,6 +2040,16 @@ static void rx_cb(UINT32 callbackTag, IX + skb->tail = skb->data + len; + skb->len = len; + ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif ++ + #ifdef DEBUG_DUMP + skb_dump("rx", skb); + #endif +@@ -2431,6 +2441,16 @@ static int dev_hard_start_xmit(struct sk + return 0; + } + ++#ifndef __ARMEB__ ++ { ++ /* Byte swap all words containing data from the buffer. */ ++ unsigned long *p = (unsigned long*)((unsigned)skb->data & ~0x3); ++ unsigned long *e = (unsigned long*)(((unsigned)skb->data + skb->len + 3) & ~0x3); ++ while (p < e) ++ *p = ntohl(*p), ++p; ++ } ++#endif ++ + #ifdef DEBUG_DUMP + skb_dump("tx", skb); + #endif diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/mac-address.patch b/recipes/ixp425-eth/ixp400-eth-1.5/mac-address.patch new file mode 100644 index 0000000000..e23eaf5f2b --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/mac-address.patch @@ -0,0 +1,123 @@ +Patch to use maclist - get the MAC to use from the board level +MAC repository based on the device portId. + +Signed-off-by: John Bowler <jbowler@acm.org> + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -23,10 +23,10 @@ + * This driver is written and optimized for Intel Xscale technology. + * + * SETUP NOTES: +- * By default, this driver uses predefined MAC addresses. +- * These are set in global var 'default_mac_addr' in this file. +- * If required, these can be changed at run-time using +- * the 'ifconfig' tool. ++ * By default, this driver uses MAC addresses from maclist, if ++ * these are not available the kernel api to randomly generate ++ * a locally assigned MAC address is used. The MAC can be ++ * overridden with ifconfig if absolutely necessary. + * + * Example - to set ixp0 MAC address to 00:02:B3:66:88:AA, + * run ifconfig with the following arguments: +@@ -64,6 +64,7 @@ + #include <linux/sysctl.h> + #include <linux/unistd.h> + #include <linux/version.h> ++#include <net/maclist.h> + + #if KERNEL_VERSION(2,6,0) <= LINUX_VERSION_CODE + #include <linux/workqueue.h> +@@ -130,6 +131,8 @@ static int dev_max_count = 1; /* only NP + static int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) + static int dev_max_count = 3; /* all NPEs are used */ ++#else ++static int dev_max_count = -1;/* use maclist_count */ + #endif + + #ifndef CONFIG_IXP400_NAPI +@@ -614,21 +617,6 @@ static phy_cfg_t default_phy_cfg[] = + #endif + }; + +-/* Default MAC addresses for EthAcc Ports 1 and 2 (using Intel MAC prefix) +- * Default is +- * IX_ETH_PORT_1 -> MAC 00:02:b3:01:01:01 +- * IX_ETH_PORT_2 -> MAC 00:02:b3:02:02:02 +- * IX_ETH_PORT_3 -> MAC 00:02:b3:03:03:03 +-*/ +-static IxEthAccMacAddr default_mac_addr[] = +-{ +- {{0x00, 0x02, 0xB3, 0x01, 0x01, 0x01}} /* EthAcc Port 0 */ +- ,{{0x00, 0x02, 0xB3, 0x02, 0x02, 0x02}} /* EthAcc Port 1 */ +-#if defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +- ,{{0x00, 0x02, 0xB3, 0x03, 0x03, 0x03}} /* EthAcc Port 2 */ +-#endif +-}; +- + /* Default mapping of NpeImageIds for EthAcc Ports + * Default is + * IX_ETH_PORT_1 -> IX_ETH_NPE_B +@@ -3325,28 +3313,10 @@ static int __devinit dev_eth_probe(struc + + /* Defines the unicast MAC address + * +- * Here is a good place to read a board-specific MAC address +- * from a non-volatile memory, e.g. an external eeprom. +- * +- * This memcpy uses a default MAC address from this +- * source code. +- * +- * This can be overriden later by the (optional) command +- * +- * ifconfig ixp0 ether 0002b3010101 +- * ++ * The code reads from the maclist API. + */ +- +- memcpy(ndev->dev_addr, +- &default_mac_addr[priv->port_id].macAddress, +- IX_IEEE803_MAC_ADDRESS_SIZE); +- +- /* possibly remove this test and the message when a valid MAC address +- * is not hardcoded in the driver source code. +- */ +- if (is_valid_ether_addr(ndev->dev_addr)) +- { +- P_WARN("Use default MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", ++ maclist_read((u8(*)[6])&ndev->dev_addr, priv->port_id); ++ P_INFO("Use MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", + (unsigned)ndev->dev_addr[0], + (unsigned)ndev->dev_addr[1], + (unsigned)ndev->dev_addr[2], +@@ -3354,7 +3324,6 @@ static int __devinit dev_eth_probe(struc + (unsigned)ndev->dev_addr[4], + (unsigned)ndev->dev_addr[5], + priv->port_id); +- } + + /* Set/update the internal packet size + * This can be overriden later by the command +@@ -3562,12 +3531,15 @@ static int __init ixp400_eth_init(void) + + TRACE; + +- /* check module parameter range */ +- if (dev_max_count == 0 || dev_max_count > IX_ETH_ACC_NUMBER_OF_PORTS) +- { +- P_ERROR("Number of ports supported is dev_max_count <= %d\n", IX_ETH_ACC_NUMBER_OF_PORTS); +- return -1; +- } ++ /* fix dev_max_count to maclist_count - the actual number of ++ * available MACs ++ */ ++ if (dev_max_count <= 0 || (dev_max_count > maclist_count() && maclist_count() > 0)) ++ dev_max_count = maclist_count(); ++ if (dev_max_count <= 0) ++ dev_max_count = 1; ++ else if (dev_max_count > IX_ETH_ACC_NUMBER_OF_PORTS) ++ dev_max_count = IX_ETH_ACC_NUMBER_OF_PORTS; + + TRACE; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/modprobe.conf b/recipes/ixp425-eth/ixp400-eth-1.5/modprobe.conf new file mode 100644 index 0000000000..f08b9a404c --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/modprobe.conf @@ -0,0 +1,4 @@ +# Add an alias for eth0 to ixp400_eth to cause the S40networking +# init script to load the ixp400_eth driver on the first boot +alias eth0 ixp400_eth +options ixp400_eth dev_max_count=1
\ No newline at end of file diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/module-param.patch b/recipes/ixp425-eth/ixp400-eth-1.5/module-param.patch new file mode 100644 index 0000000000..c54c45d716 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/module-param.patch @@ -0,0 +1,62 @@ + ixp400_eth.c | 32 ++++++++++++++++++++++++++++++++ + 1 files changed, 32 insertions(+) + +Index: ixp400_eth/ixp400_eth.c +=================================================================== +--- ixp400_eth.orig/ixp400_eth.c ++++ ixp400_eth/ixp400_eth.c +@@ -142,22 +142,54 @@ + + static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(ixp400_netdev_max_backlog, "i"); ++#else ++module_param(ixp400_netdev_max_backlog, int, 0644); ++#endif + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(datapath_poll, "i"); ++#else ++module_param(datapath_poll, int, 0644); ++#endif + MODULE_PARM_DESC(datapath_poll, "If non-zero, use polling method for datapath instead of interrupts"); + #endif /* CONFIG_IXP400_NAPI */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(npe_learning, "i"); ++#else ++module_param(npe_learning, int, 0644); ++#endif + MODULE_PARM_DESC(npe_learning, "If non-zero, NPE MAC Address Learning & Filtering feature will be enabled"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(log_level, "i"); ++#else ++module_param(log_level, int, 0644); ++#endif + MODULE_PARM_DESC(log_level, "Set log level: 0 - None, 1 - Verbose, 2 - Debug"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(no_ixp400_sw_init, "i"); ++#else ++module_param(no_ixp400_sw_init, int, 0644); ++#endif + MODULE_PARM_DESC(no_ixp400_sw_init, "If non-zero, do not initialise Intel IXP400 Software Release core components"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(no_phy_scan, "i"); ++#else ++module_param(no_phy_scan, int, 0644); ++#endif + MODULE_PARM_DESC(no_phy_scan, "If non-zero, use hard-coded phy addresses"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(phy_reset, "i"); ++#else ++module_param(phy_reset, int, 0644); ++#endif + MODULE_PARM_DESC(phy_reset, "If non-zero, reset the phys"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) + MODULE_PARM(dev_max_count, "i"); ++#else ++module_param(dev_max_count, int, 0644); ++#endif + MODULE_PARM_DESC(dev_max_count, "Number of devices to initialize"); + + /* boolean values for PHY link speed, duplex, and autonegotiation */ diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/netdev_max_backlog.patch b/recipes/ixp425-eth/ixp400-eth-1.5/netdev_max_backlog.patch new file mode 100644 index 0000000000..6891b6b4a9 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/netdev_max_backlog.patch @@ -0,0 +1,54 @@ +--- ixp400_eth/ixp400_eth.c~ 2006-01-09 01:03:11.000000000 +1030 ++++ ixp400_eth/ixp400_eth.c 2006-01-09 01:05:27.000000000 +1030 +@@ -139,12 +139,12 @@ + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +-static int netdev_max_backlog = 290; ++static int ixp400_netdev_max_backlog = 290; + + static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + +-MODULE_PARM(netdev_max_backlog, "i"); +-MODULE_PARM_DESC(netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); ++MODULE_PARM(ixp400_netdev_max_backlog, "i"); ++MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); + MODULE_PARM(datapath_poll, "i"); + MODULE_PARM_DESC(datapath_poll, "If non-zero, use polling method for datapath instead of interrupts"); + #endif /* CONFIG_IXP400_NAPI */ +@@ -213,7 +213,7 @@ + * high traffic rates. To measure the maximum throughput between the + * ports of the driver, + * - Modify /proc/sys/net/core/netdev_max_backlog value in the kernel +- * - Adjust netdev_max_backlog=n in the driver's command line ++ * - Adjust ixp400_netdev_max_backlog=n in the driver's command line + * in order to get the best rates depending on the testing tool + * and the OS load. + * +@@ -1997,7 +1997,7 @@ + /* check if the system accepts more traffic and + * against chained mbufs + */ +- if ((qlevel < netdev_max_backlog) ++ if ((qlevel < ixp400_netdev_max_backlog) + && (IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(mbuf) == NULL)) + #else + /* check against chained mbufs +@@ -3776,13 +3776,13 @@ + #ifndef CONFIG_IXP400_NAPI + /* set the softirq rx queue thresholds + * (These numbers are based on tuning experiments) +- * maxbacklog = (netdev_max_backlog * 10) / 63; ++ * maxbacklog = (ixp400_netdev_max_backlog * 10) / 63; + */ +- if (netdev_max_backlog == 0) ++ if (ixp400_netdev_max_backlog == 0) + { +- netdev_max_backlog = 290; /* system default */ ++ ixp400_netdev_max_backlog = 290; /* system default */ + } +- netdev_max_backlog /= BACKLOG_TUNE; ++ ixp400_netdev_max_backlog /= BACKLOG_TUNE; + + TRACE; + #endif diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/params.patch b/recipes/ixp425-eth/ixp400-eth-1.5/params.patch new file mode 100644 index 0000000000..86011deaaa --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/params.patch @@ -0,0 +1,75 @@ +*** ixp/ixp400_eth.c.orig Wed Jun 7 21:31:59 2006 +--- ixp/ixp400_eth.c Fri Jun 9 14:55:18 2006 +*************** +*** 112,135 **** + #define MOD_VERSION "1.5" + + /* Module parameters */ +! static int npe_learning = 1; /* default : NPE learning & filtering enable */ +! static int log_level = 0; /* default : no log */ +! static int no_ixp400_sw_init = 0; /* default : init core components of the IXP400 Software */ +! static int no_phy_scan = 0; /* default : do phy discovery */ +! static int phy_reset = 0; /* default : mo phy reset */ + + /* maximum number of ports supported by this driver ixp0, ixp1 .... + * The default is to configure all ports defined in EthAcc component + */ + #ifdef CONFIG_IXP400_ETH_NPEC_ONLY +! static int dev_max_count = 1; /* only NPEC is used */ +! #elif defined (CONFIG_IXP400_ETH_NPEB_ONLY) +! static int dev_max_count = 1; /* only NPEB is used */ + #elif defined (CONFIG_ARCH_IXDP425) || defined(CONFIG_ARCH_IXDPG425)\ + || defined (CONFIG_ARCH_ADI_COYOTE) +! static int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +! static int dev_max_count = 3; /* all NPEs are used */ + #endif + + #ifndef CONFIG_IXP400_NAPI +--- 112,136 ---- + #define MOD_VERSION "1.5" + + /* Module parameters */ +! /* gcc 4.1.1+kernel2.6.16 do not like it if these are static! */ +! int npe_learning = 1; /* default : NPE learning & filtering enable */ +! int log_level = 0; /* default : no log */ +! int no_ixp400_sw_init = 0; /* default : init core components of the IXP400 Software */ +! int no_phy_scan = 0; /* default : do phy discovery */ +! int phy_reset = 0; /* default : mo phy reset */ + + /* maximum number of ports supported by this driver ixp0, ixp1 .... + * The default is to configure all ports defined in EthAcc component + */ + #ifdef CONFIG_IXP400_ETH_NPEC_ONLY +! int dev_max_count = 1; /* only NPEC is used */ +! #elif defined (CONFIG_IXP400_ETH_NPEB_ONLY) +! int dev_max_count = 1; /* only NPEB is used */ + #elif defined (CONFIG_ARCH_IXDP425) || defined(CONFIG_ARCH_IXDPG425)\ + || defined (CONFIG_ARCH_ADI_COYOTE) +! int dev_max_count = 2; /* only NPEB and NPEC */ + #elif defined (CONFIG_ARCH_IXDP465) || defined(CONFIG_MACH_IXDP465) +! int dev_max_count = 3; /* all NPEs are used */ + #endif + + #ifndef CONFIG_IXP400_NAPI +*************** +*** 138,146 **** + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +! static int ixp400_netdev_max_backlog = 290; + +! static int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + + MODULE_PARM(ixp400_netdev_max_backlog, "i"); + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); +--- 139,147 ---- + * skbuf to push into the linux stack, and avoid the performance degradations + * during overflow. + */ +! int ixp400_netdev_max_backlog = 290; + +! int datapath_poll = 1; /* default : rx/tx polling, not interrupt driven*/ + + MODULE_PARM(ixp400_netdev_max_backlog, "i"); + MODULE_PARM_DESC(ixp400_netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/poll-controller.patch b/recipes/ixp425-eth/ixp400-eth-1.5/poll-controller.patch new file mode 100644 index 0000000000..64fb310ee5 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/poll-controller.patch @@ -0,0 +1,50 @@ +poll controller support + + ixp400_eth.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -348,6 +348,12 @@ static int dev_pmu_timer_init(void); + extern void + ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId); + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* poll controller (needed for netconsole et al) */ ++static void ++ixp425eth_poll_controller(struct net_device *dev); ++#endif ++ + /* Private device data */ + typedef struct { + spinlock_t lock; /* multicast management lock */ +@@ -3060,6 +3066,19 @@ static int set_mac_address(struct net_de + return 0; + } + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling receive - used by netconsole and other diagnostic tools ++ * to allow network i/o with interrupts disabled. ++ * (stolen from 8139too.c by siddy) ++ */ ++static void ixp425eth_poll_controller(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ dev_qmgr_os_isr(dev->irq, dev, NULL); ++ enable_irq(dev->irq); ++} ++#endif + + /* + * TX QDISC +@@ -3270,6 +3289,9 @@ static int __devinit dev_eth_probe(struc + ndev->get_stats = dev_get_stats; + ndev->set_multicast_list = dev_set_multicast_list; + ndev->flags |= IFF_MULTICAST; ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ ndev->poll_controller = ixp425eth_poll_controller; ++#endif + + ndev->set_mac_address = set_mac_address; + diff --git a/recipes/ixp425-eth/ixp400-eth-1.5/stop-on-rmmod.patch b/recipes/ixp425-eth/ixp400-eth-1.5/stop-on-rmmod.patch new file mode 100644 index 0000000000..2ddc98938a --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth-1.5/stop-on-rmmod.patch @@ -0,0 +1,29 @@ +devices must be explicitely stopped when +the driver is going do be removed, otherwise +it will simply hang. + + ixp400_eth.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 ++++ ixp400-eth/ixp400_eth.c 1970-01-01 00:00:00.000000000 +0000 +@@ -3800,9 +3800,16 @@ void __exit ixp400_eth_exit(void) + + TRACE; + +- /* We can only get here when the module use count is 0, +- * so there's no need to stop devices. +- */ ++ /* stop devices */ ++ ++#if IS_KERNEL26 ++ for (dev_count = 0; ++ dev_count < dev_max_count; /* module parameter */ ++ dev_count++) ++ { ++ do_dev_stop(platform_get_drvdata(&ixp400_eth_devices[dev_count])); ++ } ++#endif + + if (no_ixp400_sw_init == 0) /* module parameter */ + { diff --git a/recipes/ixp425-eth/ixp400-eth_1.4.bb b/recipes/ixp425-eth/ixp400-eth_1.4.bb new file mode 100644 index 0000000000..6b1ff0c8d2 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth_1.4.bb @@ -0,0 +1,54 @@ +# This is the Intel GPL IXP4XX ethernet driver (Linux) plus patches +# to make it work on 2.6 kernels. +# +LICENSE = "GPL" +SRC_URI = "ftp://aiedownload.intel.com/df-support/8500/eng/GPL_ixp400LinuxEthernetDriverPatch-1_4.zip" +SRC_URI += "file://ixp400-le-be.patch;patch=1" +SRC_URI += "file://makefile.patch;patch=1" +SRC_URI += "file://2.6.13.patch;patch=1" +SRC_URI += "file://2.6.14.patch;patch=1" +SRC_URI += "file://ixp400_pollcontroller.patch;patch=1" +SRC_URI += "file://2.6.14-mm.patch;patch=1" +SRC_URI += "file://modprobe.conf" +PR = "r9" + +DEPENDS = "ixp4xx-csr" +RDEPENDS = "ixp4xx-csr" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^arm.*-linux.*" +COMPATIBLE_MACHINE = "(nslu2|ixp4xx)" + +PROVIDES = "virtual/ixp-eth" +RPROVIDES = "ixp-eth" + +inherit module + +# This is a somewhat arbitrary choice: +OSAL_DIR = "${STAGING_KERNEL_DIR}/ixp_osal" + +IX_TARGET = "linux${SITEINFO_ENDIANESS}" + +EXTRA_OEMAKE = "'CC=${KERNEL_CC}' \ + 'LD=${KERNEL_LD}' \ + 'PWD=${S}' \ + 'IX_TARGET=${IX_TARGET}' \ + 'IXP4XX_CSR_DIR=${STAGING_INCDIR}/linux/ixp4xx-csr' \ + 'OSAL_DIR=${OSAL_DIR}' \ + 'IX_CFLAGS=-DIX_UTOPIAMODE=0 -DIX_MPHYSINGLEPORT=1 -DCONFIG_IXP400_ETH_NPEB_ONLY=1' \ + 'LINUX_SRC=${STAGING_KERNEL_DIR}' \ + 'LINUX_CROSS_COMPILE=${HOST_PREFIX}' \ + " + +do_compile () { + unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS + oe_runmake +} + +do_install () { + install -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net + install -m 0644 ixp400_eth.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 modprobe.conf ${D}${sysconfdir}/modprobe.d/eth0 +} diff --git a/recipes/ixp425-eth/ixp400-eth_1.5.1.bb b/recipes/ixp425-eth/ixp400-eth_1.5.1.bb new file mode 100644 index 0000000000..2fa04fc672 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth_1.5.1.bb @@ -0,0 +1,87 @@ +DEFAULT_PREFERENCE = "-1" +# This is the Intel GPL IXP4XX ethernet driver (Linux) plus patches +# to make it work on 2.6 kernels. +# +HOMEPAGE = "http://www.intel.com/design/network/products/npfamily/ixp420.htm" +LICENSE = "GPL" +PR = "r0" + +DEPENDS = "ixp-osal" +DEPENDS = "ixp4xx-csr" +RDEPENDS = "ixp4xx-csr" + +SRC_URI = "http://downloadmirror.intel.com/df-support/10159/eng/GPL_ixp400LinuxEthernetDriverPatch-1_5_1.zip" +SRC_URI += "file://2.6.14.patch;patch=1" +SRC_URI += "file://2.6.15.patch;patch=1" +SRC_URI += "file://device-name.patch;patch=1" +SRC_URI += "file://poll-controller.patch;patch=1" +SRC_URI += "file://le.patch;patch=1" +SRC_URI += "file://int-random.patch;patch=1" +SRC_URI += "file://stop-on-rmmod.patch;patch=1" +SRC_URI += "file://continue-if-qmgr-init-fails.patch;patch=1" +SRC_URI += "file://netdev_max_backlog.patch;patch=1" +SRC_URI += "file://debug.patch;patch=1" +SRC_URI += "file://Makefile.patch;patch=1" +SRC_URI += "file://params.patch;patch=1" +SRC_URI += "file://module-param.patch;patch=1" +SRC_URI += "file://modprobe.conf" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^arm.*-linux.*" +COMPATIBLE_MACHINE = "(nslu2|ixp4xx)" + +PROVIDES = "virtual/ixp-eth" +RPROVIDES = "ixp-eth" + +inherit module + +# This is a somewhat arbitrary choice: +OSAL_DIR = "${STAGING_KERNEL_DIR}/ixp_osal" + +IX_TARGET = "linux${SITEINFO_ENDIANESS}" +IX_ENSURE = "" +#IX_ENSURE = "-DIX_OSAL_ENSURE_ON=1" +# The following controls the name of the ethernet devices which get +# registered, the default (if this is empty) is ixp0, ixp1, otherwise +# it is eth0, eth1 +DEVICE_NAME = "-DIX_DEVICE_NAME_ETH=1" + +IXP4XX_CSR_SYMVERS = "${STAGING_KERNEL_DIR}/ixp400-csr.symvers" + +EXTRA_OEMAKE = "'PWD=${S}' \ + 'IX_TARGET=${IX_TARGET}' \ + 'IXP4XX_CSR_DIR=${STAGING_INCDIR}/linux/ixp4xx-csr' \ + 'IXP4XX_CSR_SYMVERS=${IXP4XX_CSR_SYMVERS}' \ + 'OSAL_DIR=${OSAL_DIR}' \ + 'IX_CFLAGS=-DIX_UTOPIAMODE=0 -DIX_MPHYSINGLEPORT=1 ${IX_ENSURE} ${DEVICE_NAME} -DIX_COMPONENT_NAME=-1' \ + 'LINUX_SRC=${STAGING_KERNEL_DIR}' \ + 'LINUX_CROSS_COMPILE=${HOST_PREFIX}' \ + " + +# This is to check for unresolved symbol errors and ensure the build +# fails, an error here probably means too much as been deconfigured +# out of ixp4xx-csr. +KCONFIG_FILE = "${STAGING_KERNEL_DIR}/kernel-config" +do_compile_append () { + . '${KCONFIG_FILE}' + echo "MODPOST: checking that all symbols are resolved" + if '${STAGING_KERNEL_DIR}/scripts/mod/modpost' \ + ${CONFIG_MODVERSIONS:+-m} \ + ${CONFIG_MODULE_SRCVERSION_ALL:+-a} \ + -i '${STAGING_KERNEL_DIR}/ixp400-csr.symvers' \ + ixp400_eth.o 2>&1 | egrep . + then + echo "MODPOST errors - see above" + return 1 + else + return 0 + fi +} + +do_install () { + install -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net + install -m 0644 ixp400_eth.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 modprobe.conf ${D}${sysconfdir}/modprobe.d/eth0 +} diff --git a/recipes/ixp425-eth/ixp400-eth_1.5.bb b/recipes/ixp425-eth/ixp400-eth_1.5.bb new file mode 100644 index 0000000000..5e25deb1d4 --- /dev/null +++ b/recipes/ixp425-eth/ixp400-eth_1.5.bb @@ -0,0 +1,86 @@ +# This is the Intel GPL IXP4XX ethernet driver (Linux) plus patches +# to make it work on 2.6 kernels. +# +HOMEPAGE = "http://www.intel.com/design/network/products/npfamily/ixp420.htm" +LICENSE = "GPL" +PR = "r15" + +DEPENDS = "ixp-osal" +DEPENDS = "ixp4xx-csr" +RDEPENDS = "ixp4xx-csr" + +SRC_URI = "ftp://aiedownload.intel.com/df-support/9519/eng/GPL_ixp400LinuxEthernetDriverPatch-1_5.zip" +SRC_URI += "file://2.6.14.patch;patch=1" +SRC_URI += "file://2.6.15.patch;patch=1" +SRC_URI += "file://device-name.patch;patch=1" +SRC_URI += "file://poll-controller.patch;patch=1" +SRC_URI += "file://le.patch;patch=1" +SRC_URI += "file://int-random.patch;patch=1" +SRC_URI += "file://stop-on-rmmod.patch;patch=1" +SRC_URI += "file://continue-if-qmgr-init-fails.patch;patch=1" +SRC_URI += "file://netdev_max_backlog.patch;patch=1" +SRC_URI += "file://debug.patch;patch=1" +SRC_URI += "file://Makefile.patch;patch=1" +SRC_URI += "file://params.patch;patch=1" +SRC_URI += "file://module-param.patch;patch=1" +SRC_URI += "file://modprobe.conf" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^arm.*-linux.*" +COMPATIBLE_MACHINE = "(nslu2|ixp4xx)" + +PROVIDES = "virtual/ixp-eth" +RPROVIDES = "ixp-eth" + +inherit module + +# This is a somewhat arbitrary choice: +OSAL_DIR = "${STAGING_KERNEL_DIR}/ixp_osal" + +IX_TARGET = "linux${SITEINFO_ENDIANESS}" +IX_ENSURE = "" +#IX_ENSURE = "-DIX_OSAL_ENSURE_ON=1" +# The following controls the name of the ethernet devices which get +# registered, the default (if this is empty) is ixp0, ixp1, otherwise +# it is eth0, eth1 +DEVICE_NAME = "-DIX_DEVICE_NAME_ETH=1" + +IXP4XX_CSR_SYMVERS = "${STAGING_KERNEL_DIR}/ixp400-csr.symvers" + +EXTRA_OEMAKE = "'PWD=${S}' \ + 'IX_TARGET=${IX_TARGET}' \ + 'IXP4XX_CSR_DIR=${STAGING_INCDIR}/linux/ixp4xx-csr' \ + 'IXP4XX_CSR_SYMVERS=${IXP4XX_CSR_SYMVERS}' \ + 'OSAL_DIR=${OSAL_DIR}' \ + 'IX_CFLAGS=-DIX_UTOPIAMODE=0 -DIX_MPHYSINGLEPORT=1 ${IX_ENSURE} ${DEVICE_NAME} -DIX_COMPONENT_NAME=-1' \ + 'LINUX_SRC=${STAGING_KERNEL_DIR}' \ + 'LINUX_CROSS_COMPILE=${HOST_PREFIX}' \ + " + +# This is to check for unresolved symbol errors and ensure the build +# fails, an error here probably means too much as been deconfigured +# out of ixp4xx-csr. +KCONFIG_FILE = "${STAGING_KERNEL_DIR}/kernel-config" +do_compile_append () { + . '${KCONFIG_FILE}' + echo "MODPOST: checking that all symbols are resolved" + if '${STAGING_KERNEL_DIR}/scripts/mod/modpost' \ + ${CONFIG_MODVERSIONS:+-m} \ + ${CONFIG_MODULE_SRCVERSION_ALL:+-a} \ + -i '${STAGING_KERNEL_DIR}/ixp400-csr.symvers' \ + ixp400_eth.o 2>&1 | egrep . + then + echo "MODPOST errors - see above" + return 1 + else + return 0 + fi +} + +do_install () { + install -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net + install -m 0644 ixp400_eth.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 modprobe.conf ${D}${sysconfdir}/modprobe.d/eth0 +} diff --git a/recipes/ixp425-eth/ixp425-eth-1.2/2.6.13.patch b/recipes/ixp425-eth/ixp425-eth-1.2/2.6.13.patch new file mode 100644 index 0000000000..e5825740bb --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth-1.2/2.6.13.patch @@ -0,0 +1,39 @@ +--- ./ixp425_eth.c 2005-10-01 00:45:45.180897520 -0700 ++++ ./ixp425_eth.c 2005-10-01 00:50:45.179775259 -0700 +@@ -797,7 +797,9 @@ + skb->pkt_type = PACKET_HOST; /* Default type */ + skb->ip_summed = 0; + skb->priority = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + skb->security = 0; ++#endif + #ifdef CONFIG_NET_SCHED + skb->tc_index = 0; + #endif +@@ -2564,8 +2566,14 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { ++#else ++static int set_mac_address(struct net_device *dev, void *saddrIn) ++{ ++ struct sockaddr *saddr = saddrIn; ++#endif + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +@@ -2700,7 +2708,11 @@ + #ifdef CONFIG_NET_POLL_CONTROLLER + ndev->poll_controller = ixp425eth_poll_controller; + #endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) + ndev->set_mac_address = dev_set_mac_address; ++#else ++ ndev->set_mac_address = set_mac_address; ++#endif + + TRACE; + diff --git a/recipes/ixp425-eth/ixp425-eth-1.2/2.6.14.patch b/recipes/ixp425-eth/ixp425-eth-1.2/2.6.14.patch new file mode 100644 index 0000000000..57f441c5bc --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth-1.2/2.6.14.patch @@ -0,0 +1,24 @@ +--- ./ixp425_eth.c 2005-10-01 00:50:45.179775259 -0700 ++++ ./ixp425_eth.c 2005-10-01 00:54:10.976725245 -0700 +@@ -777,7 +777,9 @@ + * before re-using it on the Rx-path + */ + skb->nfmark = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->nfcache = 0; ++#endif + nf_conntrack_put(skb->nfct); + skb->nfct = NULL; + #ifdef CONFIG_NETFILTER_DEBUG +@@ -1451,7 +1453,11 @@ + skb->len -= header_len; + + /* fill the pkt arrival time (set at the irq callback entry) */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) + skb->stamp = irq_stamp; ++#else ++ skb_set_timestamp(skb, &irq_stamp); ++#endif + + /* fill the input device field */ + skb->dev = dev; diff --git a/recipes/ixp425-eth/ixp425-eth-1.2/ixp400linuxethernetdriver-1_2-kernel26_hr_20050929.patch b/recipes/ixp425-eth/ixp425-eth-1.2/ixp400linuxethernetdriver-1_2-kernel26_hr_20050929.patch new file mode 100644 index 0000000000..e4ef3f96c8 --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth-1.2/ixp400linuxethernetdriver-1_2-kernel26_hr_20050929.patch @@ -0,0 +1,1468 @@ +diff -Naur ixp425_eth.orig/Makefile ixp425_eth/Makefile +--- ixp425_eth.orig/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ ixp425_eth/Makefile 2005-09-28 19:03:50.000000000 +0200 +@@ -0,0 +1,36 @@ ++obj-m := ixp425_eth.o ++ ++PWD := $(shell pwd) ++ ++LINUX_SRC := $($(IX_TARGET)_KERNEL_DIR) ++ ++OSAL_DIR := $(IX_XSCALE_SW)/../ixp_osal ++CFLAGS_ixp425_eth.o = -DWall \ ++ -I$(IX_XSCALE_SW)/src/include \ ++ -I$(OSAL_DIR)/ \ ++ -I$(OSAL_DIR)/os/linux/include/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ \ ++ -I$(OSAL_DIR)/os/linux/include/platforms/ixp400/ \ ++ -I$(OSAL_DIR)/os/linux/include/core/ \ ++ -I$(OSAL_DIR)/include/ \ ++ -I$(OSAL_DIR)/include/modules/ \ ++ -I$(OSAL_DIR)/include/modules/bufferMgt/ \ ++ -I$(OSAL_DIR)/include/modules/ioMem/ \ ++ -I$(OSAL_DIR)/include/modules/core/ \ ++ -I$(OSAL_DIR)/include/platforms/ \ ++ -I$(OSAL_DIR)/include/platforms/ixp400/ \ ++ ++# -DDEBUG ++ ++# -DDEBUG_DUMP ++ ++default: ++ $(MAKE) ARCH=arm CROSS_COMPILE=$(LINUX_CROSS_COMPILE) V=1 -C $(LINUX_SRC) SUBDIRS=$(PWD) modules ++ ++clean: ++ rm -f ixp425_eth.ko +diff -Naur ixp425_eth.orig/Readme-Kernel-2_6-Patch.txt ixp425_eth/Readme-Kernel-2_6-Patch.txt +--- ixp425_eth.orig/Readme-Kernel-2_6-Patch.txt 1970-01-01 01:00:00.000000000 +0100 ++++ ixp425_eth/Readme-Kernel-2_6-Patch.txt 2005-09-28 20:26:19.000000000 +0200 +@@ -0,0 +1,33 @@ ++This file describes a patch to use version 1.2 of the ethernet driver ++for Intel Ixp4XX with Linux 2.6 kernels. ++ ++Authors/History ++--------------- ++ ++This patch is based on the nslu2-linux project's patches for version ++1.1 of the same driver. The changes were adapted to version 1.2 by ++Hannes Reich & Cian Masterson. ++ ++Status ++------ ++ ++This code has been tested on a Linksys NSLU2. It works in big-endian ++mode, performance seems around 10% faster than 1.4. ++ ++The code does not work in little-endian mode. It appears as though the ++hardware is initialised correctly, but packet receive / transmit done ++callbacks are never called. ++ ++The driver has not been tested in "polling mode". ++ ++Licence Information ++------------------- ++ ++This patch is licenced under the same terms as the original Ethernet ++driver (GPL v2). ++ ++References ++---------- ++ ++The nslu2-linux project's patch for version 1.1 of the driver is at ++http://nslu.sourceforge.net/downloads/ixp425_eth.c.patch +\ No newline at end of file +diff -Naur ixp425_eth.orig/ixp425_eth.c ixp425_eth/ixp425_eth.c +--- ixp425_eth.orig/ixp425_eth.c 2005-08-26 21:44:19.000000000 +0200 ++++ ixp425_eth/ixp425_eth.c 2005-09-02 00:01:59.000000000 +0200 +@@ -47,21 +47,18 @@ + */ + #include <linux/config.h> + #include <linux/module.h> +-#include <linux/kernel.h> ++#include <linux/moduleparam.h> + #include <linux/init.h> ++#include <linux/kernel.h> + #include <linux/ioport.h> ++#include <linux/device.h> + #include <linux/netdevice.h> + #include <linux/etherdevice.h> +-#include <linux/delay.h> + #include <linux/mii.h> +-#include <linux/socket.h> +-#include <linux/cache.h> + #include <asm/io.h> + #include <asm/errno.h> + #include <net/pkt_sched.h> + #include <net/ip.h> +-#include <linux/sysctl.h> +-#include <linux/unistd.h> + + /* + * Intel IXP400 Software specific header files +@@ -93,8 +90,8 @@ + MODULE_DESCRIPTION("IXP425 NPE Ethernet driver"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Intel Corporation"); +-#define MODULE_NAME "ixp425_eth" +-#define MODULE_VERSION "1.2" ++#define DRV_NAME "ixp425_eth" ++#define DRV_VERSION "1.2A" + + /* Module parameters */ + static int npe_learning = 1; /* default : NPE learning & filtering enable */ +@@ -122,26 +119,23 @@ + */ + static int netdev_max_backlog = 290; + +-MODULE_PARM(npe_learning, "i"); ++module_param(npe_learning, int, 4); + MODULE_PARM_DESC(npe_learning, "If non-zero, NPE MAC Address Learning & Filtering feature will be enabled"); +-MODULE_PARM(log_level, "i"); ++module_param(log_level, int, 6); + MODULE_PARM_DESC(log_level, "Set log level: 0 - None, 1 - Verbose, 2 - Debug"); +-MODULE_PARM(no_csr_init, "i"); ++module_param(no_csr_init, int, 0); + MODULE_PARM_DESC(no_csr_init, "If non-zero, do not initialise Intel IXP400 Software Release core components"); +-MODULE_PARM(no_phy_scan, "i"); ++module_param(no_phy_scan, int, 0); + MODULE_PARM_DESC(no_phy_scan, "If non-zero, use hard-coded phy addresses"); +-MODULE_PARM(datapath_poll, "i"); ++module_param(datapath_poll, int, 0); + MODULE_PARM_DESC(datapath_poll, "If non-zero, use polling method for datapath instead of interrupts"); +-MODULE_PARM(phy_reset, "i"); ++module_param(phy_reset, int, 0); + MODULE_PARM_DESC(phy_reset, "If non-zero, reset the phys"); +-MODULE_PARM(netdev_max_backlog, "i"); ++module_param(netdev_max_backlog, int, 4); + MODULE_PARM_DESC(netdev_max_backlog, "Should be set to the value of /proc/sys/net/core/netdev_max_backlog (perf affecting)"); +-MODULE_PARM(dev_max_count, "i"); ++module_param(dev_max_count, int, 4); + MODULE_PARM_DESC(dev_max_count, "Number of devices to initialize"); + +-/* devices will be called ixp0 and ixp1 */ +-#define DEVICE_NAME "ixp" +- + /* boolean values for PHY link speed, duplex, and autonegotiation */ + #define PHY_SPEED_10 0 + #define PHY_SPEED_100 1 +@@ -257,36 +251,35 @@ + */ + /* Print kernel error */ + #define P_ERROR(args...) \ +- printk(KERN_ERR MODULE_NAME ": " args) ++ printk(KERN_ERR DRV_NAME ": " args) + /* Print kernel warning */ + #define P_WARN(args...) \ +- printk(KERN_WARNING MODULE_NAME ": " args) ++ printk(KERN_WARNING DRV_NAME ": " args) + /* Print kernel notice */ + #define P_NOTICE(args...) \ +- printk(KERN_NOTICE MODULE_NAME ": " args) ++ printk(KERN_NOTICE DRV_NAME ": " args) + /* Print kernel info */ + #define P_INFO(args...) \ +- printk(KERN_INFO MODULE_NAME ": " args) ++ printk(KERN_INFO DRV_NAME ": " args) + /* Print verbose message. Enabled/disabled by 'log_level' param */ + #define P_VERBOSE(args...) \ +- if (log_level >= 1) printk(MODULE_NAME ": " args) ++ if (log_level >= 1) printk(DRV_NAME ": " args) + /* Print debug message. Enabled/disabled by 'log_level' param */ + #define P_DEBUG(args...) \ + if (log_level >= 2) { \ +- printk("%s: %s()\n", MODULE_NAME, __FUNCTION__); \ ++ printk("%s: %s()\n", DRV_NAME, __FUNCTION__); \ + printk(args); } + + #ifdef DEBUG + /* Print trace message */ + #define TRACE \ +- if (log_level >= 2) printk("%s: %s(): line %d\n", MODULE_NAME, __FUNCTION__, __LINE__) ++ if (log_level >= 2) printk("%s: %s(): line %d\n", DRV_NAME, __FUNCTION__, __LINE__) + #else + /* no trace */ + #define TRACE + #endif + + /* extern Linux kernel data */ +-extern struct softnet_data softnet_data[]; /* used to get the current queue level */ + extern unsigned long loops_per_jiffy; /* used to calculate CPU clock speed */ + + /* internal Ethernet Access layer polling entry points */ +@@ -295,10 +288,12 @@ + extern void + ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId); + ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void ixp425eth_poll_controller(struct net_device *dev); ++#endif ++ + /* Private device data */ + typedef struct { +- spinlock_t lock; /* multicast management lock */ +- + unsigned int msdu_size; + unsigned int replenish_size; + unsigned int pkt_size; +@@ -338,17 +333,11 @@ + /* TX MBUF pool */ + IX_OSAL_MBUF_POOL *tx_pool; + +- /* id of thread for the link duplex monitoring */ +- int maintenanceCheckThreadId; +- +- /* mutex locked by thread, until the thread exits */ +- struct semaphore *maintenanceCheckThreadComplete; +- +- /* Used to stop the kernel thread for link monitoring. */ +- volatile BOOL maintenanceCheckStopped; ++ /* link duplex monitoring */ ++ struct work_struct mii_job; + +- /* used for tx timeout */ +- struct tq_struct tq_timeout; ++ /* handle tx timeouts */ ++ struct work_struct tx_timeout_job; + + /* used to control the message output */ + UINT32 devFlags; +@@ -370,11 +359,13 @@ + */ + + /* values used inside the irq */ ++#ifdef IXP425ETH_POLLING_MODE + static unsigned long timer_countup_ticks; ++static unsigned int rx_queue_id = IX_QMGR_MAX_NUM_QUEUES; ++#endif + static IxQMgrDispatcherFuncPtr dispatcherFunc; + static struct timeval irq_stamp; /* time of interrupt */ + static unsigned int maxbacklog = RX_MBUF_POOL_SIZE; +-static unsigned int rx_queue_id = IX_QMGR_MAX_NUM_QUEUES; + + /* Implements a software queue for skbufs + * This queue is written in the tx done process and +@@ -523,13 +514,18 @@ + #endif + }; + ++/* ++ * Shared workqueue thread for device maintenance tasks. ++ */ ++static struct workqueue_struct *npe_eth_workqueue; ++ + /* Mutex lock used to coordinate access to IxEthAcc functions + * which manipulate the MII registers on the PHYs + */ +-static struct semaphore *miiAccessMutex; ++static DECLARE_MUTEX(miiAccessMutex); + + /* mutex locked when maintenance is being performed */ +-static struct semaphore *maintenance_mutex; ++static DECLARE_MUTEX(maintenance_mutex); + + /* Flags which is set when the corresponding IRQ is running, + */ +@@ -592,7 +588,7 @@ + printk(">> mbuf:\n"); + hex_dump(mbuf, sizeof(*mbuf)); + printk(">> m_data:\n"); +- hex_dump(__va(IX_OSAL_MBUF_MDATA(mbuf)), IX_OSAL_MBUF_MLEN(mbuf)); ++ hex_dump(IX_OSAL_MBUF_MDATA(mbuf), IX_OSAL_MBUF_MLEN(mbuf)); + printk("\n-------------------------\n"); + } + +@@ -791,6 +787,8 @@ + #ifdef CONFIG_NETFILTER + #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) + /* We need to free the memory attached to the nf_bridge pointer to avoid a memory leak */ ++ nf_bridge_put(skb->nf_bridge); ++ skb->nf_bridge = NULL; + + #endif + #endif /* CONFIG_NETFILTER */ +@@ -1041,135 +1039,63 @@ + * KERNEL THREADS + */ + +-/* flush the pending signals for a thread and +- * check if a thread is killed (e.g. system shutdown) +- */ +-static BOOL dev_thread_signal_killed(void) +-{ +- int killed = FALSE; +- if (signal_pending (current)) +- { +- spin_lock_irq(¤t->sigmask_lock); +- if (sigismember(&(current->pending.signal), SIGKILL) +- || sigismember(&(current->pending.signal), SIGTERM)) +- { +- /* someone kills this thread */ +- killed = TRUE; +- } +- flush_signals(current); +- spin_unlock_irq(¤t->sigmask_lock); +- } +- return killed; +-} +- +-/* This timer will check the PHY for the link duplex and ++/* This workqueue job will check the PHY for the link duplex and + * update the MAC accordingly. It also executes some buffer + * maintenance to release mbuf in excess or replenish after + * a severe starvation + * + * This function loops and wake up every 3 seconds. + */ +-static int dev_media_check_thread (void* arg) ++static void dev_media_check_work (void* arg) + { + struct net_device *dev = (struct net_device *) arg; + priv_data_t *priv = dev->priv; +- int linkUp; +- int speed100; +- int fullDuplex = -1; /* unknown duplex mode */ +- int newDuplex; +- int autonegotiate; +- unsigned phyNum = phyAddresses[priv->port_id]; +- int res; + +- TRACE; + +- /* Lock the mutex for this thread. +- This mutex can be used to wait until the thread exits +- */ +- down (priv->maintenanceCheckThreadComplete); +- +- daemonize(); +- reparent_to_init(); +- spin_lock_irq(¤t->sigmask_lock); +- sigemptyset(¤t->blocked); +- recalc_sigpending(current); +- spin_unlock_irq(¤t->sigmask_lock); +- +- snprintf(current->comm, sizeof(current->comm), "ixp425 %s", dev->name); ++ /* ++ * Determine the link status ++ */ + +- TRACE; +- +- while (1) ++ if (default_phy_cfg[priv->port_id].linkMonitor) + { +- /* We may have been woken up by a signal. If so, we need to +- * flush it out and check for thread termination +- */ +- if (dev_thread_signal_killed()) +- { +- priv->maintenanceCheckStopped = TRUE; +- } +- +- /* If the interface is down, or the thread is killed, +- * or gracefully aborted, we need to exit this loop +- */ +- if (priv->maintenanceCheckStopped) +- { +- break; +- } +- +- /* +- * Determine the link status +- */ ++ int linkUp; ++ int speed100; ++ int fullDuplex = -1; /* unknown duplex mode */ ++ int newDuplex; ++ int autonegotiate; ++ unsigned phyNum = phyAddresses[priv->port_id]; ++ int res; + + TRACE; + +- if (default_phy_cfg[priv->port_id].linkMonitor) +- { +- /* lock the MII register access mutex */ +- down(miiAccessMutex); ++ /* lock the MII register access mutex */ ++ down(&miiAccessMutex); + +- res = ixEthMiiLinkStatus(phyNum, +- &linkUp, +- &speed100, +- &newDuplex, +- &autonegotiate); +- /* release the MII register access mutex */ +- up(miiAccessMutex); +- +- /* We may have been woken up by a signal. If so, we need to +- * flush it out and check for thread termination +- */ +- if (dev_thread_signal_killed()) +- { +- priv->maintenanceCheckStopped = TRUE; +- } ++ res = ixEthMiiLinkStatus(phyNum, ++ &linkUp, ++ &speed100, ++ &newDuplex, ++ &autonegotiate); ++ /* release the MII register access mutex */ ++ up(&miiAccessMutex); ++ ++ if (res != IX_ETH_ACC_SUCCESS) ++ { ++ P_WARN("ixEthMiiLinkStatus failed on PHY%d.\n" ++ "\tCan't determine\nthe auto negotiated parameters. " ++ "Using default values.\n", ++ phyNum); ++ /* this shouldn't happen. exit the thread if it does */ ++ goto out; ++ } + +- /* If the interface is down, or the thread is killed, +- * or gracefully aborted, we need to exit this loop +- */ +- if (priv->maintenanceCheckStopped) +- { +- break; +- } +- +- if (res != IX_ETH_ACC_SUCCESS) ++ if (linkUp) ++ { ++ if (! netif_carrier_ok(dev)) + { +- P_WARN("ixEthMiiLinkStatus failed on PHY%d.\n" +- "\tCan't determine\nthe auto negotiated parameters. " +- "Using default values.\n", +- phyNum); +- /* something is bad, gracefully stops the loop */ +- priv->maintenanceCheckStopped = TRUE; +- break; ++ /* inform the kernel of a change in link state */ ++ netif_carrier_on(dev); + } +- +- if (linkUp) +- { +- if (! netif_carrier_ok(dev)) +- { +- /* inform the kernel of a change in link state */ +- netif_carrier_on(dev); +- } + + /* + * Update the MAC mode to match the PHY mode if +@@ -1218,18 +1144,14 @@ + * long + */ + dev_buff_maintenance(dev); +- +- /* Now sleep for 3 seconds */ +- current->state = TASK_INTERRUPTIBLE; +- schedule_timeout(MEDIA_CHECK_INTERVAL); +- } /* while (1) ... */ +- +- /* free the mutex for this thread. */ +- up (priv->maintenanceCheckThreadComplete); +- +- return 0; ++ /* reschedule to run in 3 seconds */ ++ queue_delayed_work(npe_eth_workqueue, &priv->mii_job, 3*HZ); ++out: ++ return; + } + ++#ifdef IXP425ETH_POLLING_MODE ++ + /* + * TIMERS + * +@@ -1263,12 +1185,14 @@ + restore_flags(flags); + } + ++#endif /* IXP425ETH_POLLING_MODE */ ++ + /* Internal ISR : run a few thousand times per second and calls + * the queue manager dispatcher entry point. + */ +-static void dev_qmgr_os_isr(int irg, void *dev_id, struct pt_regs *regs) ++static irqreturn_t dev_qmgr_os_isr(int irg, void *dev_id, struct pt_regs *regs) + { +- int qlevel = softnet_data[0].input_pkt_queue.qlen; ++ int qlevel = __get_cpu_var(softnet_data).input_pkt_queue.qlen; + + /* at the interrupt entry, the queue contains already a few entries + * so it is safe to decrease the number of entries +@@ -1302,14 +1226,17 @@ + + /* call the queue manager entry point */ + dispatcherFunc(IX_QMGR_QUELOW_GROUP); ++ return IRQ_HANDLED; + } + ++#ifdef IXP425ETH_POLLING_MODE ++ + /* Internal ISR : run a few thousand times per second and calls + * the ethernet entry point. + */ +-static void dev_poll_os_isr(int irg, void *dev_id, struct pt_regs *regs) ++static irqreturn_t dev_poll_os_isr(int irg, void *dev_id, struct pt_regs *regs) + { +- int qlevel = softnet_data[0].input_pkt_queue.qlen; ++ int qlevel = __get_cpu_var(softnet_data).input_pkt_queue.qlen; + dev_pmu_timer_restart(); /* set up the timer for the next interrupt */ + + /* at the interrupt entry, the queue contains already a few entries +@@ -1346,6 +1273,7 @@ + ixEthRxFrameQMCallback(rx_queue_id,0); + ixEthTxFrameDoneQMCallback(0,0); + ++ return IRQ_HANDLED; + } + + /* initialize the PMU timer */ +@@ -1400,46 +1328,33 @@ + restore_flags(flags); + } + +-/* This timer will call ixEthDBDatabaseMaintenance every +- * IX_ETH_DB_MAINTENANCE_TIME jiffies +- */ +-static void maintenance_timer_cb(unsigned long data); +- +-static struct timer_list maintenance_timer = { +- function:&maintenance_timer_cb +-}; ++#endif /* IXP425ETH_POLLING_MODE */ + +-static void maintenance_timer_task(void *data); + +-/* task spawned by timer interrupt for EthDB maintenance */ +-static struct tq_struct tq_maintenance = { +- routine:maintenance_timer_task +-}; ++static void db_maintenance_code(void *data); ++static DECLARE_WORK(db_maintenance_job, db_maintenance_code, NULL); + +-static void maintenance_timer_set(void) ++static inline ++void schedule_db_maintenance(void) + { +- maintenance_timer.expires = jiffies + DB_MAINTENANCE_TIME; +- add_timer(&maintenance_timer); ++ queue_delayed_work(npe_eth_workqueue, &db_maintenance_job, ++ DB_MAINTENANCE_TIME); + } + +-static void maintenance_timer_clear(void) ++static inline ++void cancel_db_maintenance(void) + { +- del_timer_sync(&maintenance_timer); ++ cancel_delayed_work(&db_maintenance_job); + } + +-static void maintenance_timer_task(void *data) ++static void db_maintenance_code(void *data) + { +- down(maintenance_mutex); ++ down(&maintenance_mutex); + ixEthDBDatabaseMaintenance(); +- up(maintenance_mutex); ++ up(&maintenance_mutex); ++ schedule_db_maintenance(); + } + +-static void maintenance_timer_cb(unsigned long data) +-{ +- schedule_task(&tq_maintenance); +- +- maintenance_timer_set(); +-} + + /* + * DATAPLANE +@@ -1553,7 +1468,7 @@ + * and its constants are taken from the eth_type_trans() + * function. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned short hproto = ntohs(eth->h_proto); + + if (hproto >= 1536) +@@ -1595,7 +1510,7 @@ + * mode is set This costs + * a lookup inside the packet payload. + */ +- struct ethhdr *eth = skb->mac.ethernet; ++ struct ethhdr *eth = eth_hdr(skb); + unsigned char *hdest = eth->h_dest; + + if (memcmp(hdest, dev->dev_addr, ETH_ALEN)!=0) +@@ -1654,7 +1569,7 @@ + dev = (struct net_device *)callbackTag; + priv = dev->priv; + +- qlevel = softnet_data[0].input_pkt_queue.qlen; ++ qlevel = __get_cpu_var(softnet_data).input_pkt_queue.qlen; + /* check if the system accepts more traffic and + * against chained mbufs + */ +@@ -1754,10 +1669,6 @@ + + TRACE; + +- /* if called from irq handler, lock already acquired */ +- if (!in_irq()) +- spin_lock_irq(&priv->lock); +- + /* clear multicast addresses that were set the last time (if exist) */ + ixEthAccPortMulticastAddressLeaveAll (priv->port_id); + +@@ -1838,10 +1749,10 @@ + } + + Exit: +- if (!in_irq()) +- spin_unlock_irq(&priv->lock); ++ return; + } + ++#ifdef IXP425ETH_POLLING_MODE + /* The QMgr dispatch entry point can be called from the + * IX_OSAL_IXP400_QM1_IRQ_LVL irq (which will trigger + * an interrupt for every packet) or a timer (which will +@@ -1893,8 +1804,8 @@ + /* poll the datapath from a timer IRQ */ + if (request_irq(IX_OSAL_IXP400_XSCALE_PMU_IRQ_LVL, + dev_poll_os_isr, +- SA_SHIRQ, +- MODULE_NAME, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, ++ DRV_NAME, + (void *)IRQ_ANY_PARAMETER)) + { + P_ERROR("Failed to reassign irq to PMU timer interrupt!\n"); +@@ -1918,6 +1829,8 @@ + return 0; + } + ++#endif /* IXP425ETH_POLLING_MODE */ ++ + /* Enable the MAC port. + * Called on do_dev_open, dev_tx_timeout and mtu size changes + */ +@@ -1946,23 +1859,6 @@ + return convert_error_ethAcc(res); + } + +- /* restart the link-monitoring thread if necessary */ +- if (priv->maintenanceCheckStopped) +- { +- /* Starts the driver monitoring thread, if configured */ +- priv->maintenanceCheckStopped = FALSE; +- +- priv->maintenanceCheckThreadId = +- kernel_thread(dev_media_check_thread, +- (void *) dev, +- CLONE_FS | CLONE_FILES); +- if (priv->maintenanceCheckThreadId < 0) +- { +- P_ERROR("%s: Failed to start thread for media checks\n", dev->name); +- priv->maintenanceCheckStopped = TRUE; +- } +- } +- + /* force replenish if necessary */ + dev_rx_buff_prealloc(priv); + +@@ -2019,38 +1915,11 @@ + static void port_disable(struct net_device *dev) + { + priv_data_t *priv = dev->priv; +- int res; + IX_STATUS status; + + P_DEBUG("port_disable(%s)\n", dev->name); + +- if (!netif_queue_stopped(dev)) +- { +- dev->trans_start = jiffies; +- netif_stop_queue(dev); +- } +- +- if (priv->maintenanceCheckStopped) +- { +- /* thread is not running */ +- } +- else +- { +- /* thread is running */ +- priv->maintenanceCheckStopped = TRUE; +- /* Wake up the media-check thread with a signal. +- It will check the 'running' flag and exit */ +- if ((res = kill_proc (priv->maintenanceCheckThreadId, SIGKILL, 1))) +- { +- P_ERROR("%s: unable to signal thread\n", dev->name); +- } +- else +- { +- /* wait for the thread to exit. */ +- down (priv->maintenanceCheckThreadComplete); +- up (priv->maintenanceCheckThreadComplete); +- } +- } ++ netif_stop_queue(dev); + + /* Set callbacks when port is disabled */ + ixEthAccPortTxDoneCallbackRegister(priv->port_id, +@@ -2100,7 +1969,6 @@ + ixEthAccPortTxDoneCallbackRegister(priv->port_id, + tx_done_queue_stopped_cb, + (UINT32)dev); +- dev->trans_start = jiffies; + netif_stop_queue (dev); + } + return 0; +@@ -2143,12 +2011,19 @@ + int res; + + /* prevent the maintenance task from running while bringing up port */ +- down(maintenance_mutex); ++ down(&maintenance_mutex); + + /* bring up the port */ + res = port_enable(dev); + +- up(maintenance_mutex); ++ up(&maintenance_mutex); ++ ++ if(!res) ++ { ++ /* schedule mii job to run in 3 seconds */ ++ priv_data_t *priv = dev->priv; ++ queue_delayed_work(npe_eth_workqueue, &priv->mii_job, 3*HZ); ++ } + + return res; + } +@@ -2158,28 +2033,34 @@ + */ + static int do_dev_stop(struct net_device *dev) + { ++ priv_data_t *priv = dev->priv; ++ + TRACE; + ++ cancel_delayed_work(&priv->mii_job); ++ cancel_delayed_work(&priv->tx_timeout_job); ++ netif_stop_queue(dev); ++ netif_carrier_off(dev); + /* prevent the maintenance task from running while bringing up port */ +- down(maintenance_mutex); ++ down(&maintenance_mutex); + + /* bring the port down */ + port_disable(dev); + +- up(maintenance_mutex); ++ up(&maintenance_mutex); + + return 0; + } + + static void +-dev_tx_timeout_task(void *dev_id) ++dev_tx_timeout_work(void *arg) + { +- struct net_device *dev = (struct net_device *)dev_id; ++ struct net_device *dev = (struct net_device *)arg; + priv_data_t *priv = dev->priv; + + P_WARN("%s: Tx Timeout for port %d\n", dev->name, priv->port_id); + +- down(maintenance_mutex); ++ down(&maintenance_mutex); + port_disable(dev); + + /* Note to user: Consider performing other reset operations here +@@ -2202,7 +2083,7 @@ + port_enable(dev); + } + +- up(maintenance_mutex); ++ up(&maintenance_mutex); + } + + +@@ -2212,8 +2093,7 @@ + priv_data_t *priv = dev->priv; + + TRACE; +- schedule_task(&priv->tq_timeout); +- ++ queue_work(npe_eth_workqueue, &priv->tx_timeout_job); + } + + /* update the maximum msdu value for this device */ +@@ -2270,14 +2150,14 @@ + } + + /* safer to stop maintenance task while bringing port down and up */ +- down(maintenance_mutex); ++ down(&maintenance_mutex); + + if (ixEthDBFilteringPortMaximumFrameSizeSet(priv->port_id, + new_msdu_size)) + { + P_ERROR("%s: ixEthDBFilteringPortMaximumFrameSizeSet failed for port %d\n", + dev->name, priv->port_id); +- up(maintenance_mutex); ++ up(&maintenance_mutex); + + return -1; + } +@@ -2287,7 +2167,7 @@ + /* update the driver mtu value */ + dev->mtu = new_mtu_size; + +- up(maintenance_mutex); ++ up(&maintenance_mutex); + + return 0; + } +@@ -2316,27 +2196,27 @@ + /* Read MII PHY register */ + case SIOCGMIIREG: + case SIOCDEVPRIVATE+1: +- down (miiAccessMutex); /* lock the MII register access mutex */ ++ down (&miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiReadRtn (data->phy_id, data->reg_num, &data->val_out))) + { + P_ERROR("Error reading MII reg %d on phy %d\n", + data->reg_num, data->phy_id); + res = -1; + } +- up (miiAccessMutex); /* release the MII register access mutex */ ++ up (&miiAccessMutex); /* release the MII register access mutex */ + return res; + + /* Write MII PHY register */ + case SIOCSMIIREG: + case SIOCDEVPRIVATE+2: +- down (miiAccessMutex); /* lock the MII register access mutex */ ++ down (&miiAccessMutex); /* lock the MII register access mutex */ + if ((res = ixEthAccMiiWriteRtn (data->phy_id, data->reg_num, data->val_in))) + { + P_ERROR("Error writing MII reg %d on phy %d\n", + data->reg_num, data->phy_id); + res = -1; + } +- up (miiAccessMutex); /* release the MII register access mutex */ ++ up (&miiAccessMutex); /* release the MII register access mutex */ + return res; + + /* set the MTU size */ +@@ -2373,7 +2253,7 @@ + + TRACE; + +- invalidate_dcache_range((unsigned int)ðStats, sizeof(ethStats)); ++ IX_ACC_DATA_CACHE_INVALIDATE(ðStats, sizeof(ethStats)); + if ((res = ixEthAccMibIIStatsGetClear(priv->port_id, ðStats))) + { + P_ERROR("%s: ixEthAccMibIIStatsGet failed for port %d, res = %d\n", +@@ -2462,8 +2342,8 @@ + */ + if (request_irq(IX_OSAL_IXP400_QM1_IRQ_LVL, + dev_qmgr_os_isr, +- SA_SHIRQ, +- MODULE_NAME, ++ SA_SHIRQ | SA_SAMPLE_RANDOM, ++ DRV_NAME, + (void *)IRQ_ANY_PARAMETER)) + { + P_ERROR("Failed to request_irq to Queue Manager interrupt!\n"); +@@ -2582,15 +2462,6 @@ + BOOL physcan[IXP425_ETH_ACC_MII_MAX_ADDR]; + int i, phy_found, num_phys_to_set, dev_count; + +- /* initialise the MII register access mutex */ +- miiAccessMutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); +- if (!miiAccessMutex) +- return -ENOMEM; +- +- init_MUTEX(miiAccessMutex); +- +- TRACE; +- + /* detect the PHYs (ethMii requires the PHYs to be detected) + * and provides a maximum number of PHYs to search for. + */ +@@ -2680,8 +2551,8 @@ + if (port_id == IX_ETH_PORT_1) npe_id = "B"; + if (port_id == IX_ETH_PORT_2) npe_id = "C"; + +- P_INFO("%s%d is using NPE%s and the PHY at address %d\n", +- DEVICE_NAME, dev_count, npe_id, phyAddresses[port_id]); ++ P_INFO("npe%d is using NPE%s and the PHY at address %d\n", ++ dev_count, npe_id, phyAddresses[port_id]); + + /* Set the MAC to the same duplex mode as the phy */ + ixEthAccPortDuplexModeSet(port_id, +@@ -2693,12 +2564,11 @@ + } + + /* set port MAC addr and update the dev struct if successfull */ +-int dev_set_mac_address(struct net_device *dev, void *addr) ++int dev_set_mac_address(struct net_device *dev, struct sockaddr *saddr) + { + int res; + priv_data_t *priv = dev->priv; + IxEthAccMacAddr npeMacAddr; +- struct sockaddr *saddr = (struct sockaddr *)addr; + + /* Get MAC addr from parameter */ + memcpy(&npeMacAddr.macAddress, +@@ -2758,7 +2628,7 @@ + + static struct Qdisc_ops dev_qdisc_ops = + { +- NULL, NULL, "ixp425_eth", 0, ++ NULL, NULL, DRV_NAME, 0, + dev_qdisc_no_enqueue, + dev_qdisc_no_dequeue, + dev_qdisc_no_enqueue, +@@ -2771,35 +2641,13 @@ + /* Initialize device structs. + * Resource allocation is deffered until do_dev_open + */ +-static int __devinit dev_eth_probe(struct net_device *dev) ++static int __devinit dev_eth_probe(struct device *dev) + { +- static int found_devices = 0; +- priv_data_t *priv; +- +- TRACE; +- +- /* there is a limited number of devices */ +- if (found_devices >= dev_max_count) /* module parameter */ +- return -ENODEV; +- +- SET_MODULE_OWNER(dev); +- +- /* set device name */ +- strcpy(dev->name, found_devices ? DEVICE_NAME "1" : DEVICE_NAME "0"); +- +- /* allocate and initialize priv struct */ +- priv = dev->priv = kmalloc(sizeof(priv_data_t), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- +- memset(dev->priv, 0, sizeof(priv_data_t)); +- +- TRACE; +- +- /* set the mapping between port ID and devices +- * +- */ +- priv->port_id = default_portId[found_devices]; ++ int res = -ENOMEM; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct net_device *ndev = dev_get_drvdata(dev); ++ priv_data_t *priv = (priv_data_t*)ndev->priv; ++ priv->port_id = pdev->id; + + TRACE; + +@@ -2809,9 +2657,8 @@ + if(priv->rx_pool == NULL) + { + P_ERROR("%s: Buffer RX Pool init failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + + TRACE; +@@ -2822,45 +2669,38 @@ + if(priv->tx_pool == NULL) + { + P_ERROR("%s: Buffer TX Pool init failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + +- TRACE; ++ TRACE; + +- /* initialise the MII register access mutex */ +- priv->maintenanceCheckThreadComplete = (struct semaphore *) +- kmalloc(sizeof(struct semaphore), GFP_KERNEL); +- if (!priv->maintenanceCheckThreadComplete) +- { +- kfree(dev->priv); +- return -ENOMEM; +- } +- priv->lock = SPIN_LOCK_UNLOCKED; +- init_MUTEX(priv->maintenanceCheckThreadComplete); +- priv->maintenanceCheckStopped = TRUE; +- +- /* initialize ethernet device (default handlers) */ +- ether_setup(dev); ++ /* initialise the MII and tx timeout jobs */ ++ INIT_WORK(&priv->mii_job, dev_media_check_work, ndev); ++ INIT_WORK(&priv->tx_timeout_job, dev_tx_timeout_work, ndev); + + TRACE; + +- /* fill in dev struct callbacks with customized handlers */ +- dev->open = do_dev_open; +- dev->stop = do_dev_stop; ++ /* initialize ethernet device (default handlers) */ ++ ether_setup(ndev); + +- dev->hard_start_xmit = dev_hard_start_xmit; ++ /* fill in dev struct callbacks with customized handlers */ ++ ndev->open = do_dev_open; ++ ndev->stop = do_dev_stop; + +- dev->watchdog_timeo = DEV_WATCHDOG_TIMEO; +- dev->tx_timeout = dev_tx_timeout; +- dev->change_mtu = dev_change_mtu; +- dev->do_ioctl = do_dev_ioctl; +- dev->get_stats = dev_get_stats; +- dev->set_multicast_list = dev_set_multicast_list; +- dev->flags |= IFF_MULTICAST; ++ ndev->hard_start_xmit = dev_hard_start_xmit; + +- dev->set_mac_address = dev_set_mac_address; ++ ndev->watchdog_timeo = DEV_WATCHDOG_TIMEO; ++ ndev->tx_timeout = dev_tx_timeout; ++ ndev->change_mtu = dev_change_mtu; ++ ndev->do_ioctl = do_dev_ioctl; ++ ndev->get_stats = dev_get_stats; ++ ndev->set_multicast_list = dev_set_multicast_list; ++ ndev->flags |= IFF_MULTICAST; ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ ndev->poll_controller = ixp425eth_poll_controller; ++#endif ++ ndev->set_mac_address = dev_set_mac_address; + + TRACE; + +@@ -2878,22 +2718,22 @@ + * + */ + +- memcpy(dev->dev_addr, ++ memcpy(ndev->dev_addr, + &default_mac_addr[priv->port_id].macAddress, + IX_IEEE803_MAC_ADDRESS_SIZE); + + /* possibly remove this test and the message when a valid MAC address + * is not hardcoded in the driver source code. + */ +- if (is_valid_ether_addr(dev->dev_addr)) ++ if (is_valid_ether_addr(ndev->dev_addr)) + { + P_WARN("Use default MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x for port %d\n", +- (unsigned)dev->dev_addr[0], +- (unsigned)dev->dev_addr[1], +- (unsigned)dev->dev_addr[2], +- (unsigned)dev->dev_addr[3], +- (unsigned)dev->dev_addr[4], +- (unsigned)dev->dev_addr[5], ++ (unsigned)ndev->dev_addr[0], ++ (unsigned)ndev->dev_addr[1], ++ (unsigned)ndev->dev_addr[2], ++ (unsigned)ndev->dev_addr[3], ++ (unsigned)ndev->dev_addr[4], ++ (unsigned)ndev->dev_addr[5], + priv->port_id); + } + +@@ -2903,62 +2743,132 @@ + */ + TRACE; + +- dev_change_msdu(dev, dev->mtu + dev->hard_header_len + VLAN_HDR); +- +- priv->tq_timeout.routine = dev_tx_timeout_task; +- priv->tq_timeout.data = (void *)dev; ++ dev_change_msdu(ndev, ndev->mtu + ndev->hard_header_len + VLAN_HDR); + + #ifdef CONFIG_IXP425_ETH_QDISC_ENABLED + /* configure and enable a fast TX queuing discipline */ + TRACE; + +- priv->qdisc = qdisc_create_dflt(dev, &dev_qdisc_ops); +- dev->qdisc_sleeping = priv->qdisc; +- dev->qdisc = priv->qdisc; ++ priv->qdisc = qdisc_create_dflt(ndev, &dev_qdisc_ops); ++ ndev->qdisc_sleeping = priv->qdisc; ++ ndev->qdisc = priv->qdisc; + +- if (!dev->qdisc_sleeping) ++ if (!ndev->qdisc_sleeping) + { + P_ERROR("%s: qdisc_create_dflt failed on port %d\n", +- dev->name, priv->port_id); +- kfree(dev->priv); +- return -ENOMEM; ++ ndev->name, priv->port_id); ++ goto out; + } + #endif + + /* set the internal maximum queueing capabilities */ +- dev->tx_queue_len = TX_MBUF_POOL_SIZE; ++ ndev->tx_queue_len = TX_MBUF_POOL_SIZE; + +- if (!netif_queue_stopped(dev)) +- { +- TRACE; ++ if ((res = register_netdev(ndev))) ++ P_ERROR("Failed to register netdev. res = %d\n", res); ++out: ++ return res; ++} + +- dev->trans_start = jiffies; +- netif_stop_queue(dev); +- } ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling receive - used by netconsole and other diagnostic tools ++ * to allow network i/o with interrupts disabled. ++ * (stolen from 8139too.c by siddy) ++ */ ++static void ixp425eth_poll_controller(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ dev_qmgr_os_isr(dev->irq, dev, NULL); ++ enable_irq(dev->irq); ++} ++#endif + +- found_devices++; ++static int __devinit npe_eth_init_device(struct device *dev) ++{ ++ int res = -ENOMEM; ++ int ixRes = 0; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct net_device *ndev = alloc_etherdev(sizeof(priv_data_t)); ++ if (ndev == NULL) { ++ P_ERROR("could not allocate device.\n"); ++ goto out; ++ } ++ SET_MODULE_OWNER(ndev); ++ SET_NETDEV_DEV(ndev, dev); ++ ixEthAccTxSchedulingDisciplineSet(pdev->id, FIFO_NO_PRIORITY); ++ dev_set_drvdata(dev, ndev); ++ res = dev_eth_probe(dev); ++ if (res == 0) { ++ /* This was added in v0.1.8 of the driver. It seems that we need to ++ * enable the port before the user can set a mac address for the port ++ * using 'ifconfig hw ether ...'. To enable the port we must first ++ * register Q callbacks, so we register the portDisable callbacks to ++ * ensure that no buffers are passed up to the kernel until the port is ++ * brought up properly (ifconfig up) ++ */ ++ if ((ixRes = ixEthAccPortTxDoneCallbackRegister(pdev->id, ++ tx_done_disable_cb, ++ (UINT32)dev))) + +- TRACE; ++ { ++ TRACE; ++ res = convert_error_ethAcc(ixRes); ++ goto out; ++ } ++ if ((ixRes = ixEthAccPortRxCallbackRegister(pdev->id, ++ rx_disable_cb, ++ (UINT32)dev))) ++ { ++ TRACE; ++ res = convert_error_ethAcc(ixRes); ++ goto out; ++ } ++ port_enable(ndev); ++ } else { ++ dev_set_drvdata(dev, NULL); ++ kfree(ndev); ++ } ++out: ++ return res; ++} + ++static int __devexit npe_eth_fini_device(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ dev_set_drvdata(dev, NULL); ++ unregister_netdev(ndev); ++ kfree(ndev); + return 0; + } + +- + /* Module initialization and cleanup */ + + #ifdef MODULE + +-static struct net_device ixp425_devices[IX_ETH_ACC_NUMBER_OF_PORTS]; ++static struct device_driver npe_eth_driver = { ++ .name = DRV_NAME, ++ .bus = &platform_bus_type, ++ .probe = npe_eth_init_device, ++ .remove = npe_eth_fini_device, ++}; + +-int init_module(void) +-{ +- int res, dev_count; +- IxEthAccPortId portId; +- struct net_device *dev; ++static struct platform_device npe_eth_devs[] = { ++ { ++ .name = DRV_NAME, ++ .id = IX_ETH_PORT_1, ++ }, ++ { ++ .name = DRV_NAME, ++ .id = IX_ETH_PORT_2, ++ } ++}; + +- TRACE; ++static int __init ixp425_eth_init(void) ++{ ++ int res; + +- P_INFO("Initializing IXP425 NPE Ethernet driver software v. " MODULE_VERSION " \n"); ++ P_INFO("Initializing IXP425 NPE Ethernet driver software v. " DRV_VERSION " \n"); + + TRACE; + +@@ -3037,82 +2947,16 @@ + + TRACE; + +- /* Initialise the driver structure */ +- for (dev_count = 0; +- dev_count < dev_max_count; /* module parameter */ +- dev_count++) +- { +- portId = default_portId[dev_count]; +- +- dev = &ixp425_devices[dev_count]; +- +- dev->init = dev_eth_probe; +- +- TRACE; +- +- if ((res = register_netdev(dev))) +- { +- TRACE; +- +- P_ERROR("Failed to register netdev. res = %d\n", res); +- return res; +- } +- +- TRACE; +- +- /* register "safe" callbacks. This ensure that no traffic will be +- * sent to the stack until the port is brought up (ifconfig up) +- */ +- if ((res = ixEthAccPortTxDoneCallbackRegister(portId, +- tx_done_disable_cb, +- (UINT32)dev))) +- +- { +- TRACE; +- return convert_error_ethAcc(res); +- } +- if ((res = ixEthAccPortRxCallbackRegister(portId, +- rx_disable_cb, +- (UINT32)dev))) +- { +- TRACE; +- return convert_error_ethAcc(res); +- } +- } +- +- TRACE; +- +- if (no_csr_init == 0 && datapath_poll != 0 ) /* module parameter */ +- { +- /* The QMgr dispatch entry point is called from the +- * IX_OSAL_IXP400_QM1_IRQ_LVL irq (which will trigger +- * an interrupt for every packet) +- * This function setup the datapath in polling mode +- * for better performances. +- */ +- +- if ((res = ethAcc_datapath_poll_setup())) +- { +- TRACE; +- return res; +- } +- } +- +- TRACE; +- +- /* initialise the DB Maintenance task mutex */ +- maintenance_mutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); +- if (!maintenance_mutex) ++ npe_eth_workqueue = create_workqueue(DRV_NAME); ++ if (npe_eth_workqueue == NULL) + return -ENOMEM; + +- init_MUTEX(maintenance_mutex); +- + TRACE; + + /* Do not start the EthDB maintenance thread if learning & filtering feature is disabled */ + if (npe_learning) /* module parameter */ + { +- maintenance_timer_set(); ++ schedule_db_maintenance(); + } + + TRACE; +@@ -3127,12 +2971,29 @@ + } + netdev_max_backlog /= BACKLOG_TUNE; + ++ res = driver_register(&npe_eth_driver); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE EThernet driver (res = %d)\n", res); ++ return res; ++ } ++ + TRACE; + ++ res = platform_device_register(&npe_eth_devs[0]); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE platform device 0 (res = %d)\n", res); ++ return res; ++ } ++ res = platform_device_register(&npe_eth_devs[1]); ++ if (res != 0) { ++ P_ERROR("Failed to register NPE platform device 1 (res = %d)\n", res); ++ return res; ++ } ++ + return 0; + } + +-void cleanup_module(void) ++static void __exit ixp425_eth_exit(void) + { + int dev_count; + +@@ -3147,7 +3008,9 @@ + { + TRACE; + ++#ifdef IXP425ETH_POLLING_MODE + dev_pmu_timer_disable(); /* stop the timer */ ++#endif + + if (irq_pmu_used) + { +@@ -3169,19 +3032,10 @@ + + TRACE; + +- /* stop the maintenance timer */ +- maintenance_timer_clear(); +- +- TRACE; +- +- /* Wait for maintenance task to complete (if started) */ +- if (npe_learning) /* module parameter */ +- { +- TRACE; +- +- down(maintenance_mutex); +- up(maintenance_mutex); +- } ++ /* stop the maintenance timer and destroy the driver's work queue */ ++ cancel_db_maintenance(); ++ flush_workqueue(npe_eth_workqueue); ++ destroy_workqueue(npe_eth_workqueue); + + TRACE; + +@@ -3194,37 +3048,39 @@ + dev_count < dev_max_count; /* module parameter */ + dev_count++) + { +- struct net_device *dev = &ixp425_devices[dev_count]; +- priv_data_t *priv = dev->priv; +- if (priv != NULL) ++ IxEthAccPortId portId = default_portId[dev_count]; ++ ++ if (default_npeImageId[portId] == IX_ETH_NPE_B_IMAGE_ID) + { +- IxEthAccPortId portId = default_portId[dev_count]; +- +- if (default_npeImageId[portId] == IX_ETH_NPE_B_IMAGE_ID) ++ if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEB)) + { +- if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEB)) +- { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); +- } ++ P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); + } +- if (default_npeImageId[portId] == IX_ETH_NPE_C_IMAGE_ID) ++ } ++ if (default_npeImageId[portId] == IX_ETH_NPE_C_IMAGE_ID) ++ { ++ if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEC)) + { +- if (IX_SUCCESS != ixNpeDlNpeStopAndReset(IX_NPEDL_NPEID_NPEC)) +- { +- P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); +- } ++ P_NOTICE("Error Halting NPE for Ethernet port %d!\n", portId); + } +- unregister_netdev(dev); +- kfree(dev->priv); +- dev->priv = NULL; + } + } + + TRACE; + ++ driver_unregister(&npe_eth_driver); ++ platform_device_unregister(&npe_eth_devs[1]); ++ platform_device_unregister(&npe_eth_devs[0]); ++ ++ TRACE; ++ + P_VERBOSE("IXP425 NPE Ethernet driver software uninstalled\n"); + } + + #endif /* MODULE */ + ++module_init(ixp425_eth_init); ++module_exit(ixp425_eth_exit); ++ ++ + diff --git a/recipes/ixp425-eth/ixp425-eth-1.2/makefile.patch b/recipes/ixp425-eth/ixp425-eth-1.2/makefile.patch new file mode 100644 index 0000000000..f26c28e351 --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth-1.2/makefile.patch @@ -0,0 +1,11 @@ +--- ./Makefile 2005-10-01 00:36:42.634757244 -0700 ++++ ./Makefile 2005-10-01 00:39:00.107407852 -0700 +@@ -6,7 +6,7 @@ + + OSAL_DIR := $(IX_XSCALE_SW)/../ixp_osal + CFLAGS_ixp425_eth.o = -DWall \ +- -I$(IX_XSCALE_SW)/src/include \ ++ -I$(IXP4XX_CSR_DIR) \ + -I$(OSAL_DIR)/ \ + -I$(OSAL_DIR)/os/linux/include/ \ + -I$(OSAL_DIR)/os/linux/include/modules/ \ diff --git a/recipes/ixp425-eth/ixp425-eth_1.1.bb b/recipes/ixp425-eth/ixp425-eth_1.1.bb new file mode 100644 index 0000000000..92e11e3fd2 --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth_1.1.bb @@ -0,0 +1,46 @@ +DEPENDS = "ixp4xx-csr patcher-native" +LICENSE = "GPL" +SRC_URI = "http://www.intel.com/design/network/swsup/ixp400LinuxEthernetDriverPatch-1_1.zip \ + http://nslu.sourceforge.net/downloads/ixp425_eth.c.patch \ + file://makefile.patch;patch=1 \ + file://ethhdr.patch;patch=1 \ + file://intdriven.patch;patch=1 \ + file://pollcontroller.patch;patch=1 \ + file://mm4.patch;patch=1" +SRC_URI += "file://2.6.13.patch;patch=1" +SRC_URI += "file://2.6.14.patch;patch=1" +SRC_URI += "file://modprobe.conf" +PR = "r15" + +RDEPENDS = "ixp4xx-csr" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^armeb-linux.*" + +PROVIDES = "virtual/ixp-eth" +RPROVIDES = "ixp-eth" + +inherit module + +do_pre_patch () { + patcher -p 0 -i ixp425_eth_1_1_update_nf_bridge.patch + patcher -f -p 0 -i ixp425_eth.c.patch +} + +addtask pre_patch before do_patch + +do_compile () { + unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS + oe_runmake 'KDIR=${STAGING_KERNEL_DIR}' \ + 'CC=${KERNEL_CC}' \ + 'LD=${KERNEL_LD}' \ + 'EXTRA_CFLAGS=-I${STAGING_INCDIR}/linux/ixp4xx-csr -I${STAGING_KERNEL_DIR}/include -DCPU=33 -DXSCALE=33' +} + +do_install () { + install -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net + install -m 0644 ixp425_eth.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 modprobe.conf ${D}${sysconfdir}/modprobe.d/eth0 +} diff --git a/recipes/ixp425-eth/ixp425-eth_1.2.bb b/recipes/ixp425-eth/ixp425-eth_1.2.bb new file mode 100644 index 0000000000..9d537d9126 --- /dev/null +++ b/recipes/ixp425-eth/ixp425-eth_1.2.bb @@ -0,0 +1,46 @@ +# This is the Intel GPL IXP4XX ethernet driver (Linux) plus patches +# to make it work on 2.6 kernels. +# +LICENSE = "GPL" +SRC_URI = "ftp://download.intel.com/design/network/swsup/ixp400linuxethernetdriverpatch-1_2.zip" +SRC_URI += "file://ixp400linuxethernetdriver-1_2-kernel26_hr_20050929.patch;patch=1" +SRC_URI += "file://makefile.patch;patch=1" +SRC_URI += "file://2.6.13.patch;patch=1" +SRC_URI += "file://2.6.14.patch;patch=1" +SRC_URI += "file://modprobe.conf" +PR = "r4" + +DEPENDS = "ixp4xx-csr" +RDEPENDS = "ixp4xx-csr" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^armeb-linux.*" + +PROVIDES = "virtual/ixp-eth" +RPROVIDES = "ixp-eth" + +inherit module + +# This is a somewhat arbitrary choice: +OSAL_DIR = "${STAGING_KERNEL_DIR}/ixp_osal" + +EXTRA_OEMAKE = "'CC=${KERNEL_CC}' \ + 'LD=${KERNEL_LD}' \ + 'IXP4XX_CSR_DIR=${STAGING_INCDIR}/linux/ixp4xx-csr' \ + 'OSAL_DIR=${OSAL_DIR}' \ + 'LINUX_SRC=${STAGING_KERNEL_DIR}' \ + 'LINUX_CROSS_COMPILE=${HOST_PREFIX}' \ + " + +do_compile () { + unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS + oe_runmake +} + +do_install () { + install -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net + install -m 0644 ixp425_eth.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/ + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 modprobe.conf ${D}${sysconfdir}/modprobe.d/eth0 +} |