diff options
author | matteo <matteo@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-05-03 15:33:38 +0000 |
---|---|---|
committer | matteo <matteo@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-05-03 15:33:38 +0000 |
commit | c6a486db250288617f002aed6dfb31a6554fad38 (patch) | |
tree | 2d166d7b5075c536927041f2ac9a7d6c1f35f771 | |
parent | 8afd9e14ed4bb64622f8c27e49db03b4ada1ade5 (diff) |
ar7: 2.6.25.1 support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11023 3c298f89-4303-0410-b956-a3cf2f4a3e73
10 files changed, 723 insertions, 0 deletions
diff --git a/target/linux/ar7/patches-2.6.25/100-board_support.patch b/target/linux/ar7/patches-2.6.25/100-board_support.patch new file mode 100644 index 000000000..08cf79be2 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/100-board_support.patch @@ -0,0 +1,94 @@ +Index: linux-2.6.25.1/arch/mips/Kconfig +=================================================================== +--- linux-2.6.25.1.orig/arch/mips/Kconfig 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/arch/mips/Kconfig 2008-05-03 16:17:54.000000000 +0200 +@@ -18,6 +18,24 @@ + prompt "System type" + default SGI_IP22 + ++config AR7 ++ bool "Texas Instruments AR7" ++ select BOOT_ELF32 ++ select DMA_NONCOHERENT ++ select CEVT_R4K ++ select CSRC_R4K ++ select IRQ_CPU ++ select NO_EXCEPT_FILL ++ select SWAP_IO_SPACE ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_KGDB ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select GENERIC_GPIO ++ select GENERIC_HARDIRQS_NO__DO_IRQ ++ + config MACH_ALCHEMY + bool "Alchemy processor based machines" + +Index: linux-2.6.25.1/arch/mips/kernel/traps.c +=================================================================== +--- linux-2.6.25.1.orig/arch/mips/kernel/traps.c 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/arch/mips/kernel/traps.c 2008-05-03 16:17:54.000000000 +0200 +@@ -1112,9 +1112,22 @@ + + exception_handlers[n] = handler; + if (n == 0 && cpu_has_divec) { +- *(u32 *)(ebase + 0x200) = 0x08000000 | +- (0x03ffffff & (handler >> 2)); +- flush_icache_range(ebase + 0x200, ebase + 0x204); ++ if ((handler ^ (ebase + 4)) & 0xfc000000) { ++ /* lui k0, 0x0000 */ ++ *(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16); ++ /* ori k0, 0x0000 */ ++ *(u32 *)(ebase + 0x204) = ++ 0x375a0000 | (handler & 0xffff); ++ /* jr k0 */ ++ *(u32 *)(ebase + 0x208) = 0x03400008; ++ /* nop */ ++ *(u32 *)(ebase + 0x20C) = 0x00000000; ++ flush_icache_range(ebase + 0x200, ebase + 0x210); ++ } else { ++ *(u32 *)(ebase + 0x200) = ++ 0x08000000 | (0x03ffffff & (handler >> 2)); ++ flush_icache_range(ebase + 0x200, ebase + 0x204); ++ } + } + return (void *)old_handler; + } +Index: linux-2.6.25.1/arch/mips/Makefile +=================================================================== +--- linux-2.6.25.1.orig/arch/mips/Makefile 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/arch/mips/Makefile 2008-05-03 16:17:54.000000000 +0200 +@@ -167,6 +167,13 @@ + # + + # ++# Texas Instruments AR7 ++# ++core-$(CONFIG_AR7) += arch/mips/ar7/ ++cflags-$(CONFIG_AR7) += -Iinclude/asm-mips/ar7 ++load-$(CONFIG_AR7) += 0xffffffff94100000 ++ ++# + # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. + # + core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ +Index: linux-2.6.25.1/include/asm-mips/page.h +=================================================================== +--- linux-2.6.25.1.orig/include/asm-mips/page.h 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/include/asm-mips/page.h 2008-05-03 16:17:54.000000000 +0200 +@@ -182,8 +182,10 @@ + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) +-#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) ++#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \ ++ PHYS_OFFSET) ++#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \ ++ PHYS_OFFSET) + + #include <asm-generic/memory_model.h> + #include <asm-generic/page.h> diff --git a/target/linux/ar7/patches-2.6.25/110-flash.patch b/target/linux/ar7/patches-2.6.25/110-flash.patch new file mode 100644 index 000000000..02f8d952f --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/110-flash.patch @@ -0,0 +1,43 @@ +Index: linux-2.6.25.1/drivers/mtd/Kconfig +=================================================================== +--- linux-2.6.25.1.orig/drivers/mtd/Kconfig 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/mtd/Kconfig 2008-05-03 16:18:06.000000000 +0200 +@@ -158,6 +158,12 @@ + the partition map from the children of the flash node, + as described in Documentation/powerpc/booting-without-of.txt. + ++config MTD_AR7_PARTS ++ tristate "TI AR7 partitioning support" ++ depends on MTD_PARTITIONS ++ ---help--- ++ TI AR7 partitioning support ++ + comment "User Modules And Translation Layers" + + config MTD_CHAR +Index: linux-2.6.25.1/drivers/mtd/Makefile +=================================================================== +--- linux-2.6.25.1.orig/drivers/mtd/Makefile 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/mtd/Makefile 2008-05-03 16:18:06.000000000 +0200 +@@ -12,6 +12,7 @@ + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ++obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_CHAR) += mtdchar.o +Index: linux-2.6.25.1/drivers/mtd/maps/physmap.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/mtd/maps/physmap.c 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/mtd/maps/physmap.c 2008-05-03 16:18:06.000000000 +0200 +@@ -87,7 +87,8 @@ + + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; + #ifdef CONFIG_MTD_PARTITIONS +-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; ++static const char *part_probe_types[] = {"cmdlinepart", "RedBoot", ++ "ar7part", NULL }; + #endif + + static int physmap_flash_probe(struct platform_device *dev) diff --git a/target/linux/ar7/patches-2.6.25/120-gpio_chrdev.patch b/target/linux/ar7/patches-2.6.25/120-gpio_chrdev.patch new file mode 100644 index 000000000..f80f02225 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/120-gpio_chrdev.patch @@ -0,0 +1,32 @@ +Index: linux-2.6.25.1/drivers/char/Kconfig +=================================================================== +--- linux-2.6.25.1.orig/drivers/char/Kconfig 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/char/Kconfig 2008-05-03 16:18:26.000000000 +0200 +@@ -913,6 +913,15 @@ + To compile this driver as a module, choose M here: the + module will be called mwave. + ++config AR7_GPIO ++ tristate "TI AR7 GPIO Support" ++ depends on AR7 ++ help ++ Give userspace access to the GPIO pins on the Texas Instruments AR7 ++ processors. ++ ++ If compiled as a module, it will be called ar7_gpio. ++ + config SCx200_GPIO + tristate "NatSemi SCx200 GPIO Support" + depends on SCx200 +Index: linux-2.6.25.1/drivers/char/Makefile +=================================================================== +--- linux-2.6.25.1.orig/drivers/char/Makefile 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/char/Makefile 2008-05-03 16:18:26.000000000 +0200 +@@ -90,6 +90,7 @@ + obj-$(CONFIG_PPDEV) += ppdev.o + obj-$(CONFIG_NWBUTTON) += nwbutton.o + obj-$(CONFIG_NWFLASH) += nwflash.o ++obj-$(CONFIG_AR7_GPIO) += ar7_gpio.o + obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o + obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o + obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o diff --git a/target/linux/ar7/patches-2.6.25/130-vlynq.patch b/target/linux/ar7/patches-2.6.25/130-vlynq.patch new file mode 100644 index 000000000..090d8c599 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/130-vlynq.patch @@ -0,0 +1,22 @@ +Index: linux-2.6.25.1/drivers/Kconfig +=================================================================== +--- linux-2.6.25.1.orig/drivers/Kconfig 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/Kconfig 2008-05-03 16:19:06.000000000 +0200 +@@ -97,4 +97,6 @@ + source "drivers/auxdisplay/Kconfig" + + source "drivers/uio/Kconfig" ++ ++source "drivers/vlynq/Kconfig" + endmenu +Index: linux-2.6.25.1/drivers/Makefile +=================================================================== +--- linux-2.6.25.1.orig/drivers/Makefile 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/Makefile 2008-05-03 16:18:37.000000000 +0200 +@@ -91,5 +91,6 @@ + obj-$(CONFIG_HID) += hid/ + obj-$(CONFIG_PPC_PS3) += ps3/ + obj-$(CONFIG_OF) += of/ ++obj-$(CONFIG_VLYNQ) += vlynq/ + obj-$(CONFIG_SSB) += ssb/ + obj-$(CONFIG_VIRTIO) += virtio/ diff --git a/target/linux/ar7/patches-2.6.25/140-cpmac_fix.patch b/target/linux/ar7/patches-2.6.25/140-cpmac_fix.patch new file mode 100644 index 000000000..2435b3518 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/140-cpmac_fix.patch @@ -0,0 +1,169 @@ +Index: linux-2.6.25.1/drivers/net/cpmac.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/net/cpmac.c 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/net/cpmac.c 2008-05-03 16:21:17.000000000 +0200 +@@ -38,6 +38,7 @@ + #include <linux/platform_device.h> + #include <linux/dma-mapping.h> + #include <asm/gpio.h> ++#include <asm/atomic.h> + + MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); + MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); +@@ -207,6 +208,7 @@ + struct work_struct reset_work; + struct platform_device *pdev; + struct napi_struct napi; ++ atomic_t reset_pending; + }; + + static irqreturn_t cpmac_irq(int, void *); +@@ -455,6 +457,9 @@ + struct cpmac_desc *desc; + struct cpmac_priv *priv = netdev_priv(dev); + ++ if (unlikely(atomic_read(&priv->reset_pending))) ++ return NETDEV_TX_BUSY; ++ + if (unlikely(skb_padto(skb, ETH_ZLEN))) + return NETDEV_TX_OK; + +@@ -634,14 +639,14 @@ + priv->desc_ring[i].dataflags = 0; + if (priv->desc_ring[i].skb) { + dev_kfree_skb_any(priv->desc_ring[i].skb); +- if (netif_subqueue_stopped(dev, i)) +- netif_wake_subqueue(dev, i); ++ priv->desc_ring[i].skb = NULL; + } + } + } + + static void cpmac_hw_error(struct work_struct *work) + { ++ int i; + struct cpmac_priv *priv = + container_of(work, struct cpmac_priv, reset_work); + +@@ -650,8 +655,47 @@ + spin_unlock(&priv->rx_lock); + cpmac_clear_tx(priv->dev); + cpmac_hw_start(priv->dev); +- napi_enable(&priv->napi); +- netif_start_queue(priv->dev); ++ barrier(); ++ atomic_dec(&priv->reset_pending); ++ ++ for (i = 0; i < CPMAC_QUEUES; i++) { ++ netif_wake_subqueue(priv->dev, i); ++ } ++ netif_wake_queue(priv->dev); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); ++} ++ ++static void cpmac_check_status(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS); ++ int rx_channel = (macstatus >> 8) & 7; ++ int rx_code = (macstatus >> 12) & 15; ++ int tx_channel = (macstatus >> 16) & 7; ++ int tx_code = (macstatus >> 20) & 15; ++ ++ if (rx_code || tx_code) { ++ if (netif_msg_drv(priv) && net_ratelimit()) { ++ /* Can't find any documentation on what these error codes actually are. ++ * So just log them and hope.. ++ */ ++ if (rx_code) ++ printk(KERN_WARNING "%s: host error %d on rx channel %d (macstatus %08x), resetting\n", ++ dev->name, rx_code, rx_channel, macstatus); ++ if (tx_code) ++ printk(KERN_WARNING "%s: host error %d on tx channel %d (macstatus %08x), resetting\n", ++ dev->name, tx_code, tx_channel, macstatus); ++ } ++ ++ netif_stop_queue(dev); ++ cpmac_hw_stop(dev); ++ if (schedule_work(&priv->reset_work)) ++ atomic_inc(&priv->reset_pending); ++ if (unlikely(netif_msg_hw(priv))) ++ cpmac_dump_regs(dev); ++ } ++ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); + } + + static irqreturn_t cpmac_irq(int irq, void *dev_id) +@@ -682,49 +726,33 @@ + + cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); + +- if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) { +- if (netif_msg_drv(priv) && net_ratelimit()) +- printk(KERN_ERR "%s: hw error, resetting...\n", +- dev->name); +- netif_stop_queue(dev); +- napi_disable(&priv->napi); +- cpmac_hw_stop(dev); +- schedule_work(&priv->reset_work); +- if (unlikely(netif_msg_hw(priv))) +- cpmac_dump_regs(dev); +- } ++ if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) ++ cpmac_check_status(dev); + + return IRQ_HANDLED; + } + + static void cpmac_tx_timeout(struct net_device *dev) + { +- struct cpmac_priv *priv = netdev_priv(dev); + int i; ++ struct cpmac_priv *priv = netdev_priv(dev); + + spin_lock(&priv->lock); + dev->stats.tx_errors++; + spin_unlock(&priv->lock); + if (netif_msg_tx_err(priv) && net_ratelimit()) + printk(KERN_WARNING "%s: transmit timeout\n", dev->name); +- /* +- * FIXME: waking up random queue is not the best thing to +- * do... on the other hand why we got here at all? +- */ +-#ifdef CONFIG_NETDEVICES_MULTIQUEUE +- for (i = 0; i < CPMAC_QUEUES; i++) +- if (priv->desc_ring[i].skb) { +- priv->desc_ring[i].dataflags = 0; +- dev_kfree_skb_any(priv->desc_ring[i].skb); +- netif_wake_subqueue(dev, i); +- break; +- } +-#else +- priv->desc_ring[0].dataflags = 0; +- if (priv->desc_ring[0].skb) +- dev_kfree_skb_any(priv->desc_ring[0].skb); +- netif_wake_queue(dev); +-#endif ++ ++ atomic_inc(&priv->reset_pending); ++ barrier(); ++ cpmac_clear_tx(dev); ++ barrier(); ++ atomic_dec(&priv->reset_pending); ++ ++ netif_wake_queue(priv->dev); ++ for (i = 0; i < CPMAC_QUEUES; i++) { ++ netif_wake_subqueue(dev, i); ++ } + } + + static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +@@ -911,6 +939,7 @@ + goto fail_irq; + } + ++ atomic_set(&priv->reset_pending, 0); + INIT_WORK(&priv->reset_work, cpmac_hw_error); + cpmac_hw_start(dev); + diff --git a/target/linux/ar7/patches-2.6.25/150-cpmac_up_and_running.diff b/target/linux/ar7/patches-2.6.25/150-cpmac_up_and_running.diff new file mode 100644 index 000000000..9b15772c4 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/150-cpmac_up_and_running.diff @@ -0,0 +1,95 @@ +From 0daaa095cefd9d7091a7ccce2ff89f1ff4feae7a Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov <avorontsov@ru.mvista.com> +Date: Wed, 5 Mar 2008 14:52:26 +0300 +Subject: [PATCH] AR7/cpmac: convert to new fixed phy infrastructure, now for real + +This patch converts platform code to register fixed phys early. +cpmac driver modified to blindly accept fixed phy id (that is equal +to platform device id). + +Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> +--- + arch/mips/ar7/platform.c | 17 +++++++++++++++++ + drivers/net/cpmac.c | 19 +++---------------- + 2 files changed, 20 insertions(+), 16 deletions(-) + +Index: linux-2.6.25.1/arch/mips/ar7/platform.c +=================================================================== +--- linux-2.6.25.1.orig/arch/mips/ar7/platform.c 2008-05-03 16:17:30.000000000 +0200 ++++ linux-2.6.25.1/arch/mips/ar7/platform.c 2008-05-03 16:24:08.000000000 +0200 +@@ -33,6 +33,8 @@ + #include <linux/vlynq.h> + #include <linux/leds.h> + #include <linux/string.h> ++#include <linux/phy.h> ++#include <linux/phy_fixed.h> + + #include <asm/addrspace.h> + #include <asm/ar7/ar7.h> +@@ -205,6 +207,13 @@ + .width = 2, + }; + ++/* lets assume this is suitable for both high and low cpmacs links */ ++static struct fixed_phy_status fixed_phy_status __initdata = { ++ .link = 1, ++ .speed = 100, ++ .duplex = 1, ++}; ++ + static struct plat_cpmac_data cpmac_low_data = { + .reset_bit = 17, + .power_bit = 20, +@@ -506,6 +515,10 @@ + } + + if (ar7_has_high_cpmac()) { ++ res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status); ++ if (res && res != -ENODEV) ++ return res; ++ + cpmac_get_mac(1, cpmac_high_data.dev_addr); + res = platform_device_register(&cpmac_high); + if (res) +@@ -514,6 +527,10 @@ + cpmac_low_data.phy_mask = 0xffffffff; + } + ++ res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); ++ if (res && res != -ENODEV) ++ return res; ++ + cpmac_get_mac(0, cpmac_low_data.dev_addr); + res = platform_device_register(&cpmac_low); + if (res) +Index: linux-2.6.25.1/drivers/net/cpmac.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/net/cpmac.c 2008-05-03 16:21:17.000000000 +0200 ++++ linux-2.6.25.1/drivers/net/cpmac.c 2008-05-03 16:24:08.000000000 +0200 +@@ -1035,23 +1035,10 @@ + + if (phy_id == PHY_MAX_ADDR) { + if (external_switch || dumb_switch) { +- struct fixed_phy_status status = {}; +- +- mdio_bus_id = 0; +- +- /* +- * FIXME: this should be in the platform code! +- * Since there is not platform code at all (that is, +- * no mainline users of that driver), place it here +- * for now. +- */ +- phy_id = 0; +- status.link = 1; +- status.duplex = 1; +- status.speed = 100; +- fixed_phy_add(PHY_POLL, phy_id, &status); ++ mdio_bus_id = 0; /* fixed phys bus */ ++ phy_id = pdev->id; + } else { +- printk(KERN_ERR "cpmac: no PHY present\n"); ++ dev_err(&pdev->dev, "no PHY present\n"); + return -ENODEV; + } + } diff --git a/target/linux/ar7/patches-2.6.25/160-cpmac-rx-ring-use-eoq.diff b/target/linux/ar7/patches-2.6.25/160-cpmac-rx-ring-use-eoq.diff new file mode 100644 index 000000000..d99243f8a --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/160-cpmac-rx-ring-use-eoq.diff @@ -0,0 +1,180 @@ +Index: linux-2.6.25.1/drivers/net/cpmac.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/net/cpmac.c 2008-05-03 16:24:08.000000000 +0200 ++++ linux-2.6.25.1/drivers/net/cpmac.c 2008-05-03 16:24:37.000000000 +0200 +@@ -187,6 +187,7 @@ + #define CPMAC_EOQ 0x1000 + struct sk_buff *skb; + struct cpmac_desc *next; ++ struct cpmac_desc *prev; + dma_addr_t mapping; + dma_addr_t data_mapping; + }; +@@ -242,6 +243,16 @@ + printk("\n"); + } + ++static void cpmac_dump_all_desc(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct cpmac_desc *dump = priv->rx_head; ++ do { ++ cpmac_dump_desc(dev, dump); ++ dump = dump->next; ++ } while (dump != priv->rx_head); ++} ++ + static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) + { + int i; +@@ -413,21 +424,40 @@ + static int cpmac_poll(struct napi_struct *napi, int budget) + { + struct sk_buff *skb; +- struct cpmac_desc *desc; +- int received = 0; ++ struct cpmac_desc *desc, *restart; + struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi); ++ int received = 0, processed = 0; + + spin_lock(&priv->rx_lock); + if (unlikely(!priv->rx_head)) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + printk(KERN_WARNING "%s: rx: polling, but no queue\n", + priv->dev->name); ++ spin_unlock(&priv->rx_lock); + netif_rx_complete(priv->dev, napi); + return 0; + } + + desc = priv->rx_head; ++ restart = NULL; + while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) { ++ processed++; ++ ++ if ((desc->dataflags & CPMAC_EOQ) != 0) { ++ /* The last update to eoq->hw_next didn't happen soon enough, and the ++ * receiver stopped here. Remember this descriptor so we can restart ++ * the receiver after freeing some space. ++ */ ++ if (unlikely(restart)) { ++ if (netif_msg_rx_err(priv)) ++ printk(KERN_ERR "%s: poll found a duplicate EOQ: %p and %p\n", ++ priv->dev->name, restart, desc); ++ goto fatal_error; ++ } ++ ++ restart = desc->next; ++ } ++ + skb = cpmac_rx_one(priv, desc); + if (likely(skb)) { + netif_receive_skb(skb); +@@ -436,19 +466,81 @@ + desc = desc->next; + } + ++ if (desc != priv->rx_head) { ++ /* We freed some buffers, but not the whole ring, add what we did free to the rx list */ ++ desc->prev->hw_next = (u32)0; ++ priv->rx_head->prev->hw_next = priv->rx_head->mapping; ++ } ++ ++ /* Optimization: If we did not actually process an EOQ (perhaps because of ++ * quota limits), check to see if the tail of the queue has EOQ set. We ++ * should immediately restart in that case so that the receiver can restart ++ * and run in parallel with more packet processing. This lets us handle slightly ++ * larger bursts before running out of ring space (assuming dev->weight < ring_size) ++ */ ++ if (!restart && ++ (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ)) == CPMAC_EOQ && ++ (priv->rx_head->dataflags & CPMAC_OWN) != 0) { ++ /* reset EOQ so the poll loop (above) doesn't try to restart this when it ++ * eventually gets to this descriptor. ++ */ ++ priv->rx_head->prev->dataflags &= ~CPMAC_EOQ; ++ restart = priv->rx_head; ++ } ++ ++ if (restart) { ++ priv->dev->stats.rx_errors++; ++ priv->dev->stats.rx_fifo_errors++; ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: rx dma ring overrun\n", priv->dev->name); ++ ++ if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: cpmac_poll is trying to restart rx from a descriptor that's not free: %p\n", ++ priv->dev->name, restart); ++ goto fatal_error; ++ } ++ ++ cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping); ++ } ++ + priv->rx_head = desc; + spin_unlock(&priv->rx_lock); + if (unlikely(netif_msg_rx_status(priv))) + printk(KERN_DEBUG "%s: poll processed %d packets\n", + priv->dev->name, received); +- if (desc->dataflags & CPMAC_OWN) { ++ if (processed == 0) { ++ /* we ran out of packets to read, revert to interrupt-driven mode */ + netif_rx_complete(priv->dev, napi); +- cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); + cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); + return 0; + } + + return 1; ++ ++fatal_error: ++ /* Something went horribly wrong. Reset hardware to try to recover rather than wedging. */ ++ ++ if (netif_msg_drv(priv)) { ++ printk(KERN_ERR "%s: cpmac_poll is confused. Resetting hardware\n", priv->dev->name); ++ cpmac_dump_all_desc(priv->dev); ++ printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n", ++ priv->dev->name, ++ cpmac_read(priv->regs, CPMAC_RX_PTR(0)), ++ cpmac_read(priv->regs, CPMAC_RX_ACK(0))); ++ } ++ ++ spin_unlock(&priv->rx_lock); ++ netif_rx_complete(priv->dev, napi); ++ netif_stop_queue(priv->dev); ++ napi_disable(&priv->napi); ++ ++ atomic_inc(&priv->reset_pending); ++ cpmac_hw_stop(priv->dev); ++ if (!schedule_work(&priv->reset_work)) ++ atomic_dec(&priv->reset_pending); ++ return 0; ++ + } + + static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) +@@ -625,8 +717,10 @@ + desc->dataflags = CPMAC_OWN; + dev->stats.rx_dropped++; + } ++ desc->hw_next = desc->next->mapping; + desc = desc->next; + } ++ priv->rx_head->prev->hw_next = 0; + } + + static void cpmac_clear_tx(struct net_device *dev) +@@ -928,9 +1022,12 @@ + desc->buflen = CPMAC_SKB_SIZE; + desc->dataflags = CPMAC_OWN; + desc->next = &priv->rx_head[(i + 1) % priv->ring_size]; ++ desc->next->prev = desc; + desc->hw_next = (u32)desc->next->mapping; + } + ++ priv->rx_head->prev->hw_next = (u32)0; ++ + if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, + dev->name, dev))) { + if (netif_msg_drv(priv)) diff --git a/target/linux/ar7/patches-2.6.25/170-cpmac_eth_fix.patch b/target/linux/ar7/patches-2.6.25/170-cpmac_eth_fix.patch new file mode 100644 index 000000000..c720794d3 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/170-cpmac_eth_fix.patch @@ -0,0 +1,15 @@ +Index: linux-2.6.25.1/drivers/net/cpmac.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/net/cpmac.c 2008-05-03 16:24:37.000000000 +0200 ++++ linux-2.6.25.1/drivers/net/cpmac.c 2008-05-03 16:24:49.000000000 +0200 +@@ -1178,9 +1178,7 @@ + priv->msg_enable = netif_msg_init(debug_level, 0xff); + memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); + +- snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); +- +- priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, ++ priv->phy = phy_connect(dev, cpmac_mii.phy_map[phy_id]->dev.bus_id, &cpmac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(priv->phy)) { + if (netif_msg_drv(priv)) diff --git a/target/linux/ar7/patches-2.6.25/500-serial_kludge.patch b/target/linux/ar7/patches-2.6.25/500-serial_kludge.patch new file mode 100644 index 000000000..0832d3244 --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/500-serial_kludge.patch @@ -0,0 +1,44 @@ +Index: linux-2.6.25.1/drivers/serial/8250.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/serial/8250.c 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/drivers/serial/8250.c 2008-05-03 16:25:06.000000000 +0200 +@@ -267,6 +267,13 @@ + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, ++ [PORT_AR7] = { ++ .name = "TI-AR7", ++ .fifo_size = 16, ++ .tx_loadsz = 16, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, ++ .flags = UART_CAP_FIFO | UART_CAP_AFE, ++ }, + }; + + #if defined (CONFIG_SERIAL_8250_AU1X00) +@@ -2455,7 +2462,11 @@ + { + struct uart_8250_port *up = (struct uart_8250_port *)port; + ++#ifdef CONFIG_AR7 ++ wait_for_xmitr(up, BOTH_EMPTY); ++#else + wait_for_xmitr(up, UART_LSR_THRE); ++#endif + serial_out(up, UART_TX, ch); + } + +Index: linux-2.6.25.1/include/linux/serial_core.h +=================================================================== +--- linux-2.6.25.1.orig/include/linux/serial_core.h 2008-05-01 23:45:25.000000000 +0200 ++++ linux-2.6.25.1/include/linux/serial_core.h 2008-05-03 16:25:06.000000000 +0200 +@@ -40,7 +40,8 @@ + #define PORT_NS16550A 14 + #define PORT_XSCALE 15 + #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ +-#define PORT_MAX_8250 16 /* max port ID */ ++#define PORT_AR7 17 ++#define PORT_MAX_8250 17 /* max port ID */ + + /* + * ARM specific type numbers. These are not currently guaranteed diff --git a/target/linux/ar7/patches-2.6.25/900-temporary_cpmac_hack.diff b/target/linux/ar7/patches-2.6.25/900-temporary_cpmac_hack.diff new file mode 100644 index 000000000..43176f4ae --- /dev/null +++ b/target/linux/ar7/patches-2.6.25/900-temporary_cpmac_hack.diff @@ -0,0 +1,29 @@ +Index: linux-2.6.25.1/drivers/net/cpmac.c +=================================================================== +--- linux-2.6.25.1.orig/drivers/net/cpmac.c 2008-05-03 16:24:49.000000000 +0200 ++++ linux-2.6.25.1/drivers/net/cpmac.c 2008-05-03 16:25:17.000000000 +0200 +@@ -936,7 +936,8 @@ + int new_state = 0; + + spin_lock(&priv->lock); +- if (priv->phy->link) { ++ if (1 /* priv->phy->link */ ) { ++ netif_carrier_on(dev); + netif_start_queue(dev); + if (priv->phy->duplex != priv->oldduplex) { + new_state = 1; +@@ -948,11 +949,11 @@ + priv->oldspeed = priv->phy->speed; + } + +- if (!priv->oldlink) { ++ /*if (!priv->oldlink) { + new_state = 1; +- priv->oldlink = 1; ++ priv->oldlink = 1;*/ + netif_schedule(dev); +- } ++ /*}*/ + } else if (priv->oldlink) { + netif_stop_queue(dev); + new_state = 1; |