From 3045b0eff6c4690d4a92d84cda6a9ce9dec04e44 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Mon, 3 Oct 2005 06:16:32 +0000 Subject: ixp4xx, ixp425-eth: add Intel Access Library 2.0, ethernet driver 1.4 NOTE: to use these you must pin ixp4xx-csr, ixp-oxal and ixp400-eth. The name of the ethernet driver changes with this commit - it is now ixp400-eth, not ixp425-eth - changes are required in systems which need to use the ethernet driver and these changes are *not* in this commit. The things to change are the image (which must now depend on ixp400-eth) and any modprobe.conf (which, at least in NSLU2 - openslug-init - aliases eth0 as ixp4??-eth). --- packages/ixp425-eth/ixp400-eth-1.4/.mtn2git_empty | 0 packages/ixp425-eth/ixp400-eth-1.4/2.6.13.patch | 39 + packages/ixp425-eth/ixp400-eth-1.4/2.6.14.patch | 24 + .../ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch | 943 +++++++++++++++++++++ packages/ixp425-eth/ixp400-eth-1.4/makefile.patch | 33 + packages/ixp425-eth/ixp400-eth_1.4.bb | 47 + 6 files changed, 1086 insertions(+) create mode 100644 packages/ixp425-eth/ixp400-eth-1.4/.mtn2git_empty create mode 100644 packages/ixp425-eth/ixp400-eth-1.4/2.6.13.patch create mode 100644 packages/ixp425-eth/ixp400-eth-1.4/2.6.14.patch create mode 100644 packages/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch create mode 100644 packages/ixp425-eth/ixp400-eth-1.4/makefile.patch create mode 100644 packages/ixp425-eth/ixp400-eth_1.4.bb (limited to 'packages/ixp425-eth') diff --git a/packages/ixp425-eth/ixp400-eth-1.4/.mtn2git_empty b/packages/ixp425-eth/ixp400-eth-1.4/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/ixp425-eth/ixp400-eth-1.4/2.6.13.patch b/packages/ixp425-eth/ixp400-eth-1.4/2.6.13.patch new file mode 100644 index 0000000000..376bb3b03b --- /dev/null +++ b/packages/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/packages/ixp425-eth/ixp400-eth-1.4/2.6.14.patch b/packages/ixp425-eth/ixp400-eth-1.4/2.6.14.patch new file mode 100644 index 0000000000..c4c19db795 --- /dev/null +++ b/packages/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/packages/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch b/packages/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch new file mode 100644 index 0000000000..a1909dfe82 --- /dev/null +++ b/packages/ixp425-eth/ixp400-eth-1.4/ixp400-le-be.patch @@ -0,0 +1,943 @@ +--- ./ixp400_eth.c.orig 2005-10-02 18:38:46.472966042 -0700 ++++ ./ixp400_eth.c 2005-10-02 18:39:33.271910913 -0700 +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -94,8 +95,10 @@ + MODULE_DESCRIPTION("IXP400 NPE Ethernet driver"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Intel Corporation"); +-#define MODULE_NAME "ixp400_eth" +-#define MODULE_VERSION "1.4" ++#define MODULE_NAME "ixp400_eth" ++#define MODULE_VERSION_IXP400_ETH "1.4B" ++ ++#define CONFIG_ARCH_IXDP425 + + /* Module parameters */ + static int npe_learning = 1; /* default : NPE learning & filtering enable */ +@@ -358,8 +361,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 +565,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 +575,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 +1085,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 +1248,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 +1411,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 +1420,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 +1434,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 +1506,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 +1555,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 +1696,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 +1738,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 +1797,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 +1839,21 @@ + /* set the length of the received skb from the mbuf length */ + skb->tail = skb->data + len; + skb->len = len; ++ ++ { ++ int l = (skb->len+3) >> 2; ++ unsigned *p = (unsigned*)((unsigned)skb->data & ~0x3); ++ int i; ++ for (i = 0; i < l; i++) { ++ *p = ntohl(*p); ++ p++; ++ } ++ } + + #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 +1997,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 +2115,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, +@@ -2084,6 +2302,15 @@ + } + return 0; + } ++ { ++ int l = (skb->len+3) >> 2; ++ unsigned *p = (unsigned*)((unsigned)skb->data & ~0x3); ++ int i; ++ for (i = 0; i < l; i++) { ++ *p = ntohl(*p); ++ p++; ++ } ++ } + + #ifdef DEBUG_DUMP + skb_dump("tx", skb); +@@ -2120,6 +2347,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 +2379,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 +2440,7 @@ + priv_data_t *priv = dev->priv; + + TRACE; +- schedule_task(&priv->tq_timeout); ++ queue_work(npe_eth_workqueue, &priv->tx_timeout_job); + + } + +@@ -2352,7 +2601,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 +2815,6 @@ + miiAccessMutex = (struct semaphore *) kmalloc(sizeof(struct semaphore), GFP_KERNEL); + if (!miiAccessMutex) + return -ENOMEM; +- + init_MUTEX(miiAccessMutex); + + TRACE; +@@ -2673,12 +2922,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 +3000,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 +3019,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,13 +3031,14 @@ + if(priv->tx_pool == NULL) + { + P_ERROR("%s: Buffer TX Pool init failed on port %d\n", +- dev->name, priv->port_id); ++ ndev->name, priv->port_id); ++ goto out; ++ } ++#if 0 + kfree(dev->priv); + return -ENOMEM; + } + +- TRACE; +- + /* initialise the MII register access mutex */ + priv->maintenanceCheckThreadComplete = (struct semaphore *) + kmalloc(sizeof(struct semaphore), GFP_KERNEL); +@@ -2823,24 +3053,27 @@ + + /* initialize ethernet device (default handlers) */ + ether_setup(dev); ++#endif + + 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 +3091,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 +3116,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 +3149,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 +3214,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 +3243,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 +3259,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 +3333,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 +3351,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 +3370,7 @@ + dev->init = dev_eth_probe; + + TRACE; +- ++ } + if ((res = register_netdev(dev))) + { + TRACE; +@@ -3068,6 +3400,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 +3465,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 +3516,8 @@ + TRACE; + + /* stop the maintenance timer */ +- maintenance_timer_clear(); ++ // maintenance_timer_clear(); ++ cancel_db_maintenance(); + + TRACE; + diff --git a/packages/ixp425-eth/ixp400-eth-1.4/makefile.patch b/packages/ixp425-eth/ixp400-eth-1.4/makefile.patch new file mode 100644 index 0000000000..350485c1aa --- /dev/null +++ b/packages/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/packages/ixp425-eth/ixp400-eth_1.4.bb b/packages/ixp425-eth/ixp400-eth_1.4.bb new file mode 100644 index 0000000000..18251b2ddf --- /dev/null +++ b/packages/ixp425-eth/ixp400-eth_1.4.bb @@ -0,0 +1,47 @@ +# This is the Intel GPL IXP4XX ethernet driver (Linux) plus patches +# to make it work on 2.6 kernels. +# +DEPENDS = "ixp4xx-csr" +LICENSE = "GPL" +MAINTAINER = "Chris Larson " +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" +PR = "r0" + +S = "${WORKDIR}" + +COMPATIBLE_HOST = "^armeb-linux.*" + +inherit module + +# Add the architecture compiler flags to KERNEL_CC and KERNEL_LD as +# required. Notice that this has to be done for each separately built +# module as well! +KERNEL_CC += "${TARGET_CC_KERNEL_ARCH}" +KERNEL_LD += "${TARGET_LD_KERNEL_ARCH}" + +# This is a somewhat arbitrary choice: +OSAL_DIR = "${STAGING_KERNEL_DIR}/ixp_osal" + +EXTRA_OEMAKE = "'CC=${KERNEL_CC}' \ + 'LD=${KERNEL_LD}' \ + 'PWD=${S}' \ + 'IXP4XX_CSR_DIR=${STAGING_INCDIR}/linux/ixp4xx-csr' \ + 'OSAL_DIR=${OSAL_DIR}' \ + 'IX_CFLAGS=-DIX_UTOPIAMODE=0 -DIX_MPHYSINGLEPORT=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/ +} -- cgit v1.2.3