From: florian Date: Fri, 16 Nov 2012 16:32:55 +0000 (+0000) Subject: [leon] move patches to patches-2.6.36 X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=commitdiff_plain;h=763c067152ac8f8acc6a4920bd335254435feb2b [leon] move patches to patches-2.6.36 Signed-off-by: Florian Fainelli git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34220 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/target/linux/leon/patches-2.6.36/001-find_irq_and_timer_via_of.patch b/target/linux/leon/patches-2.6.36/001-find_irq_and_timer_via_of.patch new file mode 100644 index 0000000000..18d7f8beac --- /dev/null +++ b/target/linux/leon/patches-2.6.36/001-find_irq_and_timer_via_of.patch @@ -0,0 +1,48 @@ +From af1da1d5a8701f39cdbae4a0ab8e04b450eef298 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 8 Sep 2010 18:05:38 +0200 +Subject: [PATCH] SPARC/LEON: find IRQ and Timer via OF-Tree, instead of hardcoded. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/leon_kernel.c | 23 ++++++++++++++++++++++- + 1 files changed, 22 insertions(+), 1 deletions(-) + +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -105,13 +105,34 @@ static void leon_disable_irq(unsigned in + void __init leon_init_timers(irq_handler_t counter_fn) + { + int irq; ++ struct device_node *rootnp, *np; ++ struct property *pp; ++ int len; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; + master_l10_counter = (unsigned int *)&dummy_master_l10_counter; + dummy_master_l10_counter = 0; + +- if (leon3_gptimer_regs && leon3_irqctrl_regs) { ++ /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ ++ rootnp = of_find_node_by_path("/ambapp0"); ++ if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) { ++ pp = of_find_property(np, "reg", &len); ++ if (pp) ++ leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; ++ } ++ ++ /* Find GPTIMER Timer Registers base address otherwise bail out. */ ++ if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) { ++ pp = of_find_property(np, "reg", &len); ++ if (pp) ++ leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; ++ pp = of_find_property(np, "interrupts", &len); ++ if (pp) ++ leon3_gptimer_irq = *(unsigned int *)pp->value; ++ } ++ ++ if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, + (((1000000 / HZ) - 1))); diff --git a/target/linux/leon/patches-2.6.36/002-sparc_uimage_target.patch b/target/linux/leon/patches-2.6.36/002-sparc_uimage_target.patch new file mode 100644 index 0000000000..6e25ff27d7 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/002-sparc_uimage_target.patch @@ -0,0 +1,79 @@ +From 234ef25344b567b3b8dad62c0863ebe16377528f Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Tue, 14 Sep 2010 11:26:55 +0200 +Subject: [PATCH] SPARC: added U-Boot build target: uImage + +--- + arch/sparc/Makefile | 3 ++- + arch/sparc/boot/Makefile | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 37 insertions(+), 1 deletions(-) + +--- a/arch/sparc/Makefile ++++ b/arch/sparc/Makefile +@@ -88,7 +88,7 @@ boot := arch/sparc/boot + # Default target + all: zImage + +-image zImage tftpboot.img vmlinux.aout: vmlinux ++image zImage uImage tftpboot.img vmlinux.aout: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + + archclean: +@@ -102,6 +102,7 @@ ifeq ($(ARCH),sparc) + define archhelp + echo '* image - kernel image ($(boot)/image)' + echo '* zImage - stripped kernel image ($(boot)/zImage)' ++ echo ' uImage - U-Boot SPARC32/LEON Image' + echo ' tftpboot.img - image prepared for tftp' + endef + else +--- a/arch/sparc/boot/Makefile ++++ b/arch/sparc/boot/Makefile +@@ -5,6 +5,7 @@ + + ROOT_IMG := /usr/src/root.img + ELFTOAOUT := elftoaout ++MKIMAGE := $(srctree)/scripts/mkuboot.sh + + hostprogs-y := piggyback_32 piggyback_64 btfixupprep + targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout +@@ -90,5 +91,39 @@ $(obj)/tftpboot.img: $(obj)/image $(obj) + $(obj)/vmlinux.aout: vmlinux FORCE + $(call if_changed,elftoaout) + @echo ' kernel: $@ is ready' ++else ++ ++# The following lines make a readable image for U-Boot. ++# uImage - Binary file read by U-boot ++# uImage.o - object file of uImage for loading with a ++# flash programmer understanding ELF. ++ ++OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment ++$(obj)/image.bin: $(obj)/image FORCE ++ $(call if_changed,objcopy) ++ ++$(obj)/image.gz: $(obj)/image.bin ++ $(call if_changed,gzip) ++ ++# Start of Main memory ++ifndef UIMAGE_LOADADDR ++UIMAGE_LOADADDR=0x40004000 + endif + ++# The first sector after the U-Boot image (256k) ++ifndef UIMAGE_FLASHADDR ++UIMAGE_FLASHADDR=0x00040000 ++endif ++ ++quiet_cmd_uimage = UIMAGE $@ ++ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \ ++ -C gzip -a $(UIMAGE_LOADADDR) -e 0xf0004000 -n 'Linux-$(KERNELRELEASE)' \ ++ -d $< $@ ++ ++targets += uImage ++$(obj)/uImage: $(obj)/image.gz ++ $(call if_changed,uimage) ++ $(LD) -Tdata $(UIMAGE_FLASHADDR) -r -b binary arch/sparc/boot/uImage -o arch/sparc/boot/uImage.o ++ @echo ' Image $@ is ready' ++ ++endif diff --git a/target/linux/leon/patches-2.6.36/003-smp_cpu_stuck_fix.patch b/target/linux/leon/patches-2.6.36/003-smp_cpu_stuck_fix.patch new file mode 100644 index 0000000000..3d572f5f29 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/003-smp_cpu_stuck_fix.patch @@ -0,0 +1,23 @@ +From 417bc6751fdd3c24df274f25e020ec3decd09280 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Thu, 16 Sep 2010 11:00:46 +0200 +Subject: [PATCH] Fixed SPARC/LEON SMP CPU Stuck problem. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/leon_smp.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/leon_smp.c ++++ b/arch/sparc/kernel/leon_smp.c +@@ -56,8 +56,8 @@ void __init leon_configure_cache_smp(voi + static inline unsigned long do_swap(volatile unsigned long *ptr, + unsigned long val) + { +- __asm__ __volatile__("swapa [%1] %2, %0\n\t" : "=&r"(val) +- : "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) ++ __asm__ __volatile__("swapa [%2] %3, %0\n\t" : "=&r"(val) ++ : "0"(val), "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) + : "memory"); + return val; + } diff --git a/target/linux/leon/patches-2.6.36/004-extended_irq_controller.patch b/target/linux/leon/patches-2.6.36/004-extended_irq_controller.patch new file mode 100644 index 0000000000..b660b648b8 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/004-extended_irq_controller.patch @@ -0,0 +1,119 @@ +From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Thu, 16 Sep 2010 11:12:41 +0200 +Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/include/asm/irq_32.h | 4 ++++ + arch/sparc/kernel/irq_32.c | 32 ++++++++++++++++++++++++++------ + arch/sparc/kernel/leon_kernel.c | 8 +++++++- + 3 files changed, 37 insertions(+), 7 deletions(-) + +--- a/arch/sparc/include/asm/irq_32.h ++++ b/arch/sparc/include/asm/irq_32.h +@@ -6,7 +6,11 @@ + #ifndef _SPARC_IRQ_H + #define _SPARC_IRQ_H + ++#ifdef CONFIG_SPARC_LEON ++#define NR_IRQS 32 ++#else + #define NR_IRQS 16 ++#endif + + #include + +--- a/arch/sparc/kernel/irq_32.c ++++ b/arch/sparc/kernel/irq_32.c +@@ -110,6 +110,11 @@ EXPORT_SYMBOL(__raw_local_irq_save); + EXPORT_SYMBOL(raw_local_irq_enable); + EXPORT_SYMBOL(raw_local_irq_restore); + ++#ifdef CONFIG_SPARC_LEON ++extern unsigned int sparc_leon_eirq; ++extern int sparc_leon_eirq_get(int eirq, int cpu); ++#endif ++ + /* + * Dave Redman (djhr@tadpole.co.uk) + * +@@ -222,10 +227,11 @@ void free_irq(unsigned int irq, void *de + return; + } + cpu_irq = irq & (NR_IRQS - 1); +- if (cpu_irq > 14) { /* 14 irq levels on the sparc */ +- printk("Trying to free bogus IRQ %d\n", irq); +- return; +- } ++ /* 14 irq levels on the sparc, however some LEON systems have 31 IRQs */ ++ if ((cpu_irq == 15) || (cpu_irq >= NR_IRQS)) { ++ printk("Trying to free bogus IRQ %d\n", irq); ++ return; ++ } + + spin_lock_irqsave(&irq_action_lock, flags); + +@@ -303,7 +309,14 @@ void unexpected_irq(int irq, void *dev_i + int i; + struct irqaction * action; + unsigned int cpu_irq; +- ++ ++#ifdef CONFIG_SPARC_LEON ++ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */ ++ if ( sparc_leon_eirq == irq ) { ++ irq = sparc_leon_eirq_get(irq, smp_processor_id()); ++ } ++#endif ++ + cpu_irq = irq & (NR_IRQS - 1); + action = sparc_irq[cpu_irq].action; + +@@ -330,6 +343,13 @@ void handler_irq(int irq, struct pt_regs + extern void smp4m_irq_rotate(int cpu); + #endif + ++#ifdef CONFIG_SPARC_LEON ++ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */ ++ if ( sparc_leon_eirq == irq ) { ++ irq = sparc_leon_eirq_get(irq, cpu); ++ } ++#endif ++ + old_regs = set_irq_regs(regs); + irq_enter(); + disable_pil_irq(irq); +@@ -526,7 +546,7 @@ int request_irq(unsigned int irq, + return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); + } + cpu_irq = irq & (NR_IRQS - 1); +- if(cpu_irq > 14) { ++ if(cpu_irq == 15) { + ret = -EINVAL; + goto out; + } +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -104,7 +104,7 @@ static void leon_disable_irq(unsigned in + + void __init leon_init_timers(irq_handler_t counter_fn) + { +- int irq; ++ int irq, eirq; + struct device_node *rootnp, *np; + struct property *pp; + int len; +@@ -153,6 +153,12 @@ void __init leon_init_timers(irq_handler + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); + # endif + ++ LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); ++ eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf; ++ if ( eirq != 0 ) { ++ /* Extended IRQ controller available */ ++ sparc_leon_eirq_register(eirq); ++ } + } else { + printk(KERN_ERR "No Timer/irqctrl found\n"); + BUG(); diff --git a/target/linux/leon/patches-2.6.36/005-avoid_openprom_duplicates.patch b/target/linux/leon/patches-2.6.36/005-avoid_openprom_duplicates.patch new file mode 100644 index 0000000000..54bfd2726b --- /dev/null +++ b/target/linux/leon/patches-2.6.36/005-avoid_openprom_duplicates.patch @@ -0,0 +1,58 @@ +From 486a578298b7ab45c3edfdce8d4feaef93c3229b Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Thu, 16 Sep 2010 11:15:37 +0200 +Subject: [PATCH] SPARC/LEON: to avoid name duplicates in openprom fs when REG is not available the NAME now includes NODE ID when REG not present + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/prom_32.c | 27 +++++++++++++++++++-------- + 1 files changed, 19 insertions(+), 8 deletions(-) + +--- a/arch/sparc/kernel/prom_32.c ++++ b/arch/sparc/kernel/prom_32.c +@@ -136,18 +136,29 @@ static void __init ebus_path_component(s + /* "name:vendor:device@irq,addrlo" */ + static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) + { +- struct amba_prom_registers *regs; unsigned int *intr; +- unsigned int *device, *vendor; ++ struct amba_prom_registers *regs; ++ unsigned int *intr, *device, *vendor, reg0; + struct property *prop; ++ int interrupt = 0; + ++ /* In order to get a unique ID in the device tree (multiple AMBA devices ++ * may have the same name) the node number is printed ++ */ + prop = of_find_property(dp, "reg", NULL); +- if (!prop) +- return; +- regs = prop->value; ++ if (!prop) { ++ reg0 = (unsigned int)dp->phandle; ++ } else { ++ regs = prop->value; ++ reg0 = regs->phys_addr; ++ } ++ ++ /* Not all cores have Interrupt */ + prop = of_find_property(dp, "interrupts", NULL); + if (!prop) +- return; +- intr = prop->value; ++ intr = &interrupt; /* IRQ0 does not exist */ ++ else ++ intr = prop->value; ++ + prop = of_find_property(dp, "vendor", NULL); + if (!prop) + return; +@@ -159,7 +170,7 @@ static void __init ambapp_path_component + + sprintf(tmp_buf, "%s:%d:%d@%x,%x", + dp->name, *vendor, *device, +- *intr, regs->phys_addr); ++ *intr, reg0); + } + + static void __init __build_path_component(struct device_node *dp, char *tmp_buf) diff --git a/target/linux/leon/patches-2.6.36/006-amp_support.patch b/target/linux/leon/patches-2.6.36/006-amp_support.patch new file mode 100644 index 0000000000..98d1c9f30d --- /dev/null +++ b/target/linux/leon/patches-2.6.36/006-amp_support.patch @@ -0,0 +1,85 @@ +From 25a68b8cd8ea1553f8b56278418d6c1ecc12e247 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 22 Sep 2010 10:19:34 +0200 +Subject: [PATCH] SPARC/LEON: added support for AMP systems with IRQAMP IRQ Controller. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/include/asm/leon.h | 12 ++++++++++++ + arch/sparc/include/asm/leon_amba.h | 6 +++--- + arch/sparc/kernel/leon_kernel.c | 14 ++++++++++++++ + 3 files changed, 29 insertions(+), 3 deletions(-) + +--- a/arch/sparc/include/asm/leon.h ++++ b/arch/sparc/include/asm/leon.h +@@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_c + "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); + }; + ++static inline unsigned long sparc_leon3_asr17(void) ++{ ++ u32 asr17; ++ __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17)); ++ return asr17; ++}; ++ ++static inline int sparc_leon3_cpuid(void) ++{ ++ return sparc_leon3_asr17() >> 28; ++} ++ + #endif /*!__ASSEMBLY__*/ + + #ifdef CONFIG_SMP +--- a/arch/sparc/include/asm/leon_amba.h ++++ b/arch/sparc/include/asm/leon_amba.h +@@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map { + u32 mpbroadcast; + u32 notused02; + u32 notused03; +- u32 notused10; +- u32 notused11; +- u32 notused12; ++ u32 ampctrl; ++ u32 icsel[2]; + u32 notused13; + u32 notused20; + u32 notused21; +@@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map { + u32 force[16]; + /* Extended IRQ registers */ + u32 intid[16]; /* 0xc0 */ ++ u32 unused[(0x1000-0x100)/4]; + }; + + struct leon3_apbuart_regs_map { +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -108,6 +108,7 @@ void __init leon_init_timers(irq_handler + struct device_node *rootnp, *np; + struct property *pp; + int len; ++ int cpu, icsel; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; +@@ -153,6 +154,19 @@ void __init leon_init_timers(irq_handler + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); + # endif + ++ /* The IRQ controller may (if implemented) consist of multiple ++ * IRQ controllers, each mapped on a 4Kb boundary. ++ * Each CPU may be routed to different IRQCTRLs, however ++ * we assume that all CPUs (in SMP system) is routed to the ++ * same IRQ Controller, and for non-SMP only one IRQCTRL is ++ * accessed anyway. ++ * In AMP systems, Linux may not be run on CPU0. ++ */ ++ cpu = sparc_leon3_cpuid(); ++ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); ++ icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; ++ leon3_irqctrl_regs += icsel; ++ + LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); + eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf; + if ( eirq != 0 ) { diff --git a/target/linux/leon/patches-2.6.36/007-amp_timer.patch b/target/linux/leon/patches-2.6.36/007-amp_timer.patch new file mode 100644 index 0000000000..d8d436347f --- /dev/null +++ b/target/linux/leon/patches-2.6.36/007-amp_timer.patch @@ -0,0 +1,120 @@ +From 1dffe06838c26b7c3fc99f9ddb7db78e378f6908 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 22 Sep 2010 13:21:13 +0200 +Subject: [PATCH] SPARC/LEON: added support for selecting Timer Core and Timer within core, useful for AMP systems. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/leon_kernel.c | 41 +++++++++++++++++++++++++------------- + 1 files changed, 27 insertions(+), 14 deletions(-) + +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -23,15 +23,16 @@ + #include "prom.h" + #include "irq.h" + +-struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ +-struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ ++struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */ ++struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */ + struct amba_apb_device leon_percpu_timer_dev[16]; + + int leondebug_irq_disable; + int leon_debug_irqout; + static int dummy_master_l10_counter; + +-unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ ++unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */ ++unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */ + unsigned int sparc_leon_eirq; + #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) + +@@ -109,6 +110,7 @@ void __init leon_init_timers(irq_handler + struct property *pp; + int len; + int cpu, icsel; ++ int ampopts; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; +@@ -124,24 +126,35 @@ void __init leon_init_timers(irq_handler + } + + /* Find GPTIMER Timer Registers base address otherwise bail out. */ +- if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) { ++ np = rootnp; ++ while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) { ++ ampopts = 0; ++ pp = of_find_property(np, "ampopts", &len); ++ if ( pp && ((ampopts = *(int *)pp->value) == 0) ) { ++ /* Skip this instance, resource already allocated by other OS */ ++ continue; ++ } ++ /* Select Timer-Instance on Timer Core. Default is zero */ ++ leon3_gptimer_idx = ampopts & 0x7; ++ + pp = of_find_property(np, "reg", &len); + if (pp) + leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; + pp = of_find_property(np, "interrupts", &len); + if (pp) + leon3_gptimer_irq = *(unsigned int *)pp->value; ++ break; + } + + if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, +- (((1000000 / HZ) - 1))); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, ++ (((1000000 / 100) - 1))); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); + + #ifdef CONFIG_SMP + leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; +- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; ++ leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx; + + if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & + (1<e[1].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1))); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); + # endif + + /* The IRQ controller may (if implemented) consist of multiple +@@ -178,7 +191,7 @@ void __init leon_init_timers(irq_handler + BUG(); + } + +- irq = request_irq(leon3_gptimer_irq, ++ irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, + counter_fn, + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); + +@@ -210,13 +223,13 @@ void __init leon_init_timers(irq_handler + # endif + + if (leon3_gptimer_regs) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); + + #ifdef CONFIG_SMP +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | diff --git a/target/linux/leon/patches-2.6.36/008-hz_specific_timer_init.patch b/target/linux/leon/patches-2.6.36/008-hz_specific_timer_init.patch new file mode 100644 index 0000000000..aae3d29cdd --- /dev/null +++ b/target/linux/leon/patches-2.6.36/008-hz_specific_timer_init.patch @@ -0,0 +1,30 @@ +From e4d697dad4d43109f045a4f25cb1d706122045c0 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 22 Sep 2010 13:24:36 +0200 +Subject: [PATCH] SPARC/LEON: removed constant timer initialization as if HZ=100, now it reflects the value of HZ + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/leon_kernel.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -149,7 +149,7 @@ void __init leon_init_timers(irq_handler + if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, +- (((1000000 / 100) - 1))); ++ (((1000000 / HZ) - 1))); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); + + #ifdef CONFIG_SMP +@@ -163,7 +163,7 @@ void __init leon_init_timers(irq_handler + } + + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1))); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1))); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); + # endif + diff --git a/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch b/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch new file mode 100644 index 0000000000..b0b1346156 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch @@ -0,0 +1,187 @@ +From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 22 Sep 2010 15:39:05 +0200 +Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/include/asm/leon.h | 2 +- + arch/sparc/include/asm/leon_amba.h | 3 +- + arch/sparc/kernel/entry.S | 3 +- + arch/sparc/kernel/leon_kernel.c | 37 ++++++++--------------------------- + arch/sparc/kernel/leon_smp.c | 8 ++++++- + 5 files changed, 21 insertions(+), 32 deletions(-) + +--- a/arch/sparc/include/asm/leon.h ++++ b/arch/sparc/include/asm/leon.h +@@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void + + #ifdef CONFIG_SMP + # define LEON3_IRQ_RESCHEDULE 13 +-# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) ++# define LEON3_IRQ_TICKER (leon3_gptimer_irq + leon3_gptimer_idx) + # define LEON3_IRQ_CROSS_CALL 15 + #endif + +--- a/arch/sparc/include/asm/leon_amba.h ++++ b/arch/sparc/include/asm/leon_amba.h +@@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp, + + extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; + extern struct leon3_gptimer_regs_map *leon3_gptimer_regs; +-extern struct amba_apb_device leon_percpu_timer_dev[16]; + extern int leondebug_irq_disable; + extern int leon_debug_irqout; + extern unsigned long leon3_gptimer_irq; ++extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */ + extern unsigned int sparc_leon_eirq; ++extern unsigned long leon3_cpu_idx; + + #endif /* __ASSEMBLY__ */ + +--- a/arch/sparc/kernel/entry.S ++++ b/arch/sparc/kernel/entry.S +@@ -411,8 +411,9 @@ smpleon_ticker: + WRITE_PAUSE + wr %g2, PSR_ET, %psr + WRITE_PAUSE ++ mov %l7, %o0 ! irq level + call leon_percpu_timer_interrupt +- add %sp, STACKFRAME_SZ, %o0 ++ add %sp, STACKFRAME_SZ, %o1 ! pt_regs + wr %l0, PSR_ET, %psr + WRITE_PAUSE + RESTORE_ALL +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -25,7 +25,6 @@ + + struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */ + struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */ +-struct amba_apb_device leon_percpu_timer_dev[16]; + + int leondebug_irq_disable; + int leon_debug_irqout; +@@ -34,6 +33,7 @@ static int dummy_master_l10_counter; + unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */ + unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */ + unsigned int sparc_leon_eirq; ++unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */ + #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) + + /* Return the IRQ of the pending IRQ on the extended IRQ controller */ +@@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler + struct device_node *rootnp, *np; + struct property *pp; + int len; +- int cpu, icsel; ++ int icsel; + int ampopts; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; + master_l10_counter = (unsigned int *)&dummy_master_l10_counter; + dummy_master_l10_counter = 0; ++ leon3_cpu_idx = sparc_leon3_cpuid(); + + /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ + rootnp = of_find_node_by_path("/ambapp0"); +@@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler + (((1000000 / HZ) - 1))); + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); + +-#ifdef CONFIG_SMP +- leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; +- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx; +- + if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & + (1<e[leon3_gptimer_idx+1].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1))); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); +-# endif +- + /* The IRQ controller may (if implemented) consist of multiple + * IRQ controllers, each mapped on a 4Kb boundary. + * Each CPU may be routed to different IRQCTRLs, however +@@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler + * accessed anyway. + * In AMP systems, Linux may not be run on CPU0. + */ +- cpu = sparc_leon3_cpuid(); +- icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); +- icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; ++ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]); ++ icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf; + leon3_irqctrl_regs += icsel; + + LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); +@@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler + # ifdef CONFIG_SMP + { + unsigned long flags; +- struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; ++ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + ++ (leon3_gptimer_irq + leon3_gptimer_idx - 1)]; + + /* For SMP we use the level 14 ticker, however the bootup code + * has copied the firmwares level 14 vector into boot cpu's +@@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler + } + # endif + +- if (leon3_gptimer_regs) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); + +-#ifdef CONFIG_SMP +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, +- LEON3_GPTIMER_EN | +- LEON3_GPTIMER_RL | +- LEON3_GPTIMER_LD | +- LEON3_GPTIMER_IRQEN); +-#endif +- +- } + } + + void leon_clear_clock_irq(void) +--- a/arch/sparc/kernel/leon_smp.c ++++ b/arch/sparc/kernel/leon_smp.c +@@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin + extern unsigned char boot_cpu_id; + extern cpumask_t smp_commenced_mask; + void __init leon_configure_cache_smp(void); ++extern void handler_irq(int irq, struct pt_regs * regs); + + static inline unsigned long do_swap(volatile unsigned long *ptr, + unsigned long val) +@@ -385,7 +386,7 @@ void leon_cross_call_irq(void) + ccall_info.processors_out[i] = 1; + } + +-void leon_percpu_timer_interrupt(struct pt_regs *regs) ++void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs) + { + struct pt_regs *old_regs; + int cpu = smp_processor_id(); +@@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct + prof_counter(cpu) = prof_multiplier(cpu); + } + set_irq_regs(old_regs); ++ ++ if ( cpu == leon3_cpu_idx ) { ++ /* Ticker Clock is shared with the System Clock */ ++ handler_irq(irq, regs); ++ } + } + + static void __init smp_setup_percpu_timer(void) diff --git a/target/linux/leon/patches-2.6.36/010-apbuart_ampopts.patch b/target/linux/leon/patches-2.6.36/010-apbuart_ampopts.patch new file mode 100644 index 0000000000..f47c54a7be --- /dev/null +++ b/target/linux/leon/patches-2.6.36/010-apbuart_ampopts.patch @@ -0,0 +1,41 @@ +From 8129fa5437f3fe5f95bac180a43cd5a856cebdf3 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 20 Oct 2010 17:00:41 +0200 +Subject: [PATCH] Added support for ampopts in APBUART driver. Used in AMP systems. + +Signed-off-by: Daniel Hellstrom +--- + drivers/serial/apbuart.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +--- a/drivers/serial/apbuart.c ++++ b/drivers/serial/apbuart.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -573,7 +574,6 @@ static int __devinit apbuart_probe(struc + printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n", + (unsigned long long) port->mapbase, port->irq); + return 0; +- + } + + static struct of_device_id __initdata apbuart_match[] = { +@@ -620,9 +620,12 @@ static void grlib_apbuart_configure(void + int *vendor = (int *) of_get_property(np, "vendor", NULL); + int *device = (int *) of_get_property(np, "device", NULL); + int *irqs = (int *) of_get_property(np, "interrupts", NULL); ++ int *ampopts = (int *) of_get_property(np, "ampopts", NULL); + regs = (struct amba_prom_registers *) + of_get_property(np, "reg", NULL); + ++ if (ampopts && (*ampopts == 0)) ++ continue; /* Ignore if used by another OS instance */ + if (vendor) + v = *vendor; + if (device) diff --git a/target/linux/leon/patches-2.6.36/011-greth_fix_unhandled_irq.patch b/target/linux/leon/patches-2.6.36/011-greth_fix_unhandled_irq.patch new file mode 100644 index 0000000000..55e6185a2c --- /dev/null +++ b/target/linux/leon/patches-2.6.36/011-greth_fix_unhandled_irq.patch @@ -0,0 +1,21 @@ +From 3d7788e8f5ae3d44e48f9b7476528acf3d9c8b32 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 20 Oct 2010 17:07:12 +0200 +Subject: [PATCH] GRETH: Fixed potential future problem where unhandled IRQ is cleared. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -584,7 +584,7 @@ static irqreturn_t greth_interrupt(int i + if (status & (GRETH_INT_RX | GRETH_INT_TX)) { + + /* Clear interrupt status */ +- GRETH_REGORIN(greth->regs->status, ++ GRETH_REGSAVE(greth->regs->status, + status & (GRETH_INT_RX | GRETH_INT_TX)); + + retval = IRQ_HANDLED; diff --git a/target/linux/leon/patches-2.6.36/012-greth_amba_vendor_device.patch b/target/linux/leon/patches-2.6.36/012-greth_amba_vendor_device.patch new file mode 100644 index 0000000000..78b526cb8f --- /dev/null +++ b/target/linux/leon/patches-2.6.36/012-greth_amba_vendor_device.patch @@ -0,0 +1,22 @@ +From ff5f2ee8b37f2278dd86946761313c3664c51836 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Thu, 21 Oct 2010 14:34:48 +0200 +Subject: [PATCH] GRETH: added raw AMBA vendor/device number to match against. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -1600,6 +1600,9 @@ static struct of_device_id greth_of_matc + { + .name = "GAISLER_ETHMAC", + }, ++ { ++ .name = "01_01d", ++ }, + {}, + }; + diff --git a/target/linux/leon/patches-2.6.36/013-apbuart_amba_vendor_device.patch b/target/linux/leon/patches-2.6.36/013-apbuart_amba_vendor_device.patch new file mode 100644 index 0000000000..7675f108e7 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/013-apbuart_amba_vendor_device.patch @@ -0,0 +1,22 @@ +From 1c14b8995c1b8212180b5009dc04ac222a449ecb Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Thu, 21 Oct 2010 14:35:09 +0200 +Subject: [PATCH] APBUART: added raw AMBA vendor/device number to match against. + +Signed-off-by: Daniel Hellstrom +--- + drivers/serial/apbuart.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +--- a/drivers/serial/apbuart.c ++++ b/drivers/serial/apbuart.c +@@ -580,6 +580,9 @@ static struct of_device_id __initdata ap + { + .name = "GAISLER_APBUART", + }, ++ { ++ .name = "01_00c", ++ }, + {}, + }; + diff --git a/target/linux/leon/patches-2.6.36/014-timer_irqctrl_amba_vendor_device.patch b/target/linux/leon/patches-2.6.36/014-timer_irqctrl_amba_vendor_device.patch new file mode 100644 index 0000000000..58f7657d40 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/014-timer_irqctrl_amba_vendor_device.patch @@ -0,0 +1,32 @@ +From 12782c44d0c687b5b0400a8224a9b1bf9eb9a428 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Tue, 26 Oct 2010 09:59:05 +0200 +Subject: [PATCH] TIMER,IRQCTRL: added raw AMBA vendor/device number to match against. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/kernel/leon_kernel.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -120,7 +120,8 @@ void __init leon_init_timers(irq_handler + + /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ + rootnp = of_find_node_by_path("/ambapp0"); +- if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) { ++ if (rootnp && ((np=of_find_node_by_name(rootnp, "GAISLER_IRQMP")) || ++ (np=of_find_node_by_name(rootnp, "01_00d")))) { + pp = of_find_property(np, "reg", &len); + if (pp) + leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; +@@ -128,7 +129,8 @@ void __init leon_init_timers(irq_handler + + /* Find GPTIMER Timer Registers base address otherwise bail out. */ + np = rootnp; +- while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) { ++ while (np && ((np=of_find_node_by_name(np, "GAISLER_GPTIMER")) || ++ (np=of_find_node_by_name(np, "01_011")))) { + ampopts = 0; + pp = of_find_property(np, "ampopts", &len); + if ( pp && ((ampopts = *(int *)pp->value) == 0) ) { diff --git a/target/linux/leon/patches-2.6.36/015-dma_ops.patch b/target/linux/leon/patches-2.6.36/015-dma_ops.patch new file mode 100644 index 0000000000..7f488e0221 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/015-dma_ops.patch @@ -0,0 +1,296 @@ +From c6d8f92cfd7f4f19eb3b16545b3b68c561978fe8 Mon Sep 17 00:00:00 2001 +From: Kristoffer Glembo +Date: Mon, 7 Jun 2010 14:00:30 +0200 +Subject: [PATCH] sparc32: Added LEON dma_ops. + +Added leon3_dma_ops and mmu_inval_dma_area. +--- + arch/sparc/kernel/ioport.c | 139 +++++++++++++++++++++++++++++++------------ + 1 files changed, 100 insertions(+), 39 deletions(-) + +--- a/arch/sparc/kernel/ioport.c ++++ b/arch/sparc/kernel/ioport.c +@@ -50,10 +50,15 @@ + #include + #include + +-#ifdef CONFIG_SPARC_LEON +-#define mmu_inval_dma_area(p, l) leon_flush_dcache_all() +-#else ++#ifndef CONFIG_SPARC_LEON + #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ ++#else ++static inline void mmu_inval_dma_area(unsigned long va, unsigned long len) ++{ ++ if (!sparc_leon3_snooping_enabled()) { ++ leon_flush_dcache_all(); ++ } ++} + #endif + + static struct resource *_sparc_find_resource(struct resource *r, +@@ -254,7 +259,7 @@ static void *sbus_alloc_coherent(struct + dma_addr_t *dma_addrp, gfp_t gfp) + { + struct platform_device *op = to_platform_device(dev); +- unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; ++ unsigned long len_total = PAGE_ALIGN(len); + unsigned long va; + struct resource *res; + int order; +@@ -287,15 +292,19 @@ static void *sbus_alloc_coherent(struct + * XXX That's where sdev would be used. Currently we load + * all iommu tables with the same translations. + */ +- if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) +- goto err_noiommu; +- +- res->name = op->dev.of_node->name; ++#ifdef CONFIG_SPARC_LEON ++ sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); ++ *dma_addrp = virt_to_phys(va); ++#else ++ if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) { ++ release_resource(res); ++ goto err_nova; ++ } ++#endif ++ res->name = op->node->name; + + return (void *)(unsigned long)res->start; + +-err_noiommu: +- release_resource(res); + err_nova: + free_pages(va, order); + err_nomem: +@@ -321,7 +330,7 @@ static void sbus_free_coherent(struct de + return; + } + +- n = (n + PAGE_SIZE-1) & PAGE_MASK; ++ n = PAGE_ALIGN(n); + if ((res->end-res->start)+1 != n) { + printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", + (long)((res->end-res->start)+1), n); +@@ -333,7 +342,12 @@ static void sbus_free_coherent(struct de + + /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ + pgv = virt_to_page(p); +- mmu_unmap_dma_area(dev, ba, n); ++ ++#ifdef CONFIG_SPARC_LEON ++ sparc_unmapiorange((unsigned long)p, n); ++#else ++ mmu_unmap_dma_area(dev, ba, n); ++#endif + + __free_pages(pgv, get_order(n)); + } +@@ -408,9 +422,6 @@ struct dma_map_ops sbus_dma_ops = { + .sync_sg_for_device = sbus_sync_sg_for_device, + }; + +-struct dma_map_ops *dma_ops = &sbus_dma_ops; +-EXPORT_SYMBOL(dma_ops); +- + static int __init sparc_register_ioport(void) + { + register_proc_sparc_ioport(); +@@ -422,7 +433,7 @@ arch_initcall(sparc_register_ioport); + + #endif /* CONFIG_SBUS */ + +-#ifdef CONFIG_PCI ++#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON) + + /* Allocate and map kernel buffer using consistent mode DMA for a device. + * hwdev should be valid struct pci_dev pointer for PCI devices. +@@ -430,7 +441,7 @@ arch_initcall(sparc_register_ioport); + static void *pci32_alloc_coherent(struct device *dev, size_t len, + dma_addr_t *pba, gfp_t gfp) + { +- unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; ++ unsigned long len_total = PAGE_ALIGN(len); + unsigned long va; + struct resource *res; + int order; +@@ -463,10 +474,6 @@ static void *pci32_alloc_coherent(struct + return NULL; + } + mmu_inval_dma_area(va, len_total); +-#if 0 +-/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n", +- (long)va, (long)res->start, (long)virt_to_phys(va), len_total); +-#endif + sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); + + *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ +@@ -498,7 +505,7 @@ static void pci32_free_coherent(struct d + return; + } + +- n = (n + PAGE_SIZE-1) & PAGE_MASK; ++ n = PAGE_ALIGN(n); + if ((res->end-res->start)+1 != n) { + printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", + (long)((res->end-res->start)+1), (long)n); +@@ -515,6 +522,14 @@ static void pci32_free_coherent(struct d + free_pages(pgp, get_order(n)); + } + ++static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, ++ enum dma_data_direction dir, struct dma_attrs *attrs) ++{ ++ if (dir != PCI_DMA_TODEVICE) { ++ mmu_inval_dma_area((unsigned long)phys_to_virt(ba), PAGE_ALIGN(size)); ++ } ++} ++ + /* + * Same as pci_map_single, but with pages. + */ +@@ -551,8 +566,7 @@ static int pci32_map_sg(struct device *d + + /* IIep is write-through, not flushing. */ + for_each_sg(sgl, sg, nents, n) { +- BUG_ON(page_address(sg_page(sg)) == NULL); +- sg->dma_address = virt_to_phys(sg_virt(sg)); ++ sg->dma_address = sg_phys(sg); + sg->dma_length = sg->length; + } + return nents; +@@ -571,10 +585,7 @@ static void pci32_unmap_sg(struct device + + if (dir != PCI_DMA_TODEVICE) { + for_each_sg(sgl, sg, nents, n) { +- BUG_ON(page_address(sg_page(sg)) == NULL); +- mmu_inval_dma_area( +- (unsigned long) page_address(sg_page(sg)), +- (sg->length + PAGE_SIZE-1) & PAGE_MASK); ++ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); + } + } + } +@@ -594,7 +605,7 @@ static void pci32_sync_single_for_cpu(st + { + if (dir != PCI_DMA_TODEVICE) { + mmu_inval_dma_area((unsigned long)phys_to_virt(ba), +- (size + PAGE_SIZE-1) & PAGE_MASK); ++ PAGE_ALIGN(size)); + } + } + +@@ -621,10 +632,7 @@ static void pci32_sync_sg_for_cpu(struct + + if (dir != PCI_DMA_TODEVICE) { + for_each_sg(sgl, sg, nents, n) { +- BUG_ON(page_address(sg_page(sg)) == NULL); +- mmu_inval_dma_area( +- (unsigned long) page_address(sg_page(sg)), +- (sg->length + PAGE_SIZE-1) & PAGE_MASK); ++ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); + } + } + } +@@ -637,18 +645,38 @@ static void pci32_sync_sg_for_device(str + + if (dir != PCI_DMA_TODEVICE) { + for_each_sg(sgl, sg, nents, n) { +- BUG_ON(page_address(sg_page(sg)) == NULL); +- mmu_inval_dma_area( +- (unsigned long) page_address(sg_page(sg)), +- (sg->length + PAGE_SIZE-1) & PAGE_MASK); ++ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); + } + } + } + ++/* LEON3 unmapping functions ++ * ++ * We can only invalidate the whole cache so unmap_page and unmap_sg do the same thing ++ */ ++static void leon3_unmap_page(struct device *dev, dma_addr_t ba, size_t size, ++ enum dma_data_direction dir, struct dma_attrs *attrs) ++{ ++ if (dir != PCI_DMA_TODEVICE) { ++ mmu_inval_dma_area(0, 0); ++ } ++} ++ ++static void leon3_unmap_sg(struct device *dev, struct scatterlist *sgl, ++ int nents, enum dma_data_direction dir, ++ struct dma_attrs *attrs) ++{ ++ ++ if (dir != PCI_DMA_TODEVICE) { ++ mmu_inval_dma_area(0, 0); ++ } ++} ++ + struct dma_map_ops pci32_dma_ops = { + .alloc_coherent = pci32_alloc_coherent, + .free_coherent = pci32_free_coherent, + .map_page = pci32_map_page, ++ .unmap_page = pci32_unmap_page, + .map_sg = pci32_map_sg, + .unmap_sg = pci32_unmap_sg, + .sync_single_for_cpu = pci32_sync_single_for_cpu, +@@ -658,7 +686,30 @@ struct dma_map_ops pci32_dma_ops = { + }; + EXPORT_SYMBOL(pci32_dma_ops); + +-#endif /* CONFIG_PCI */ ++struct dma_map_ops leon3_dma_ops = { ++ .alloc_coherent = sbus_alloc_coherent, ++ .free_coherent = sbus_free_coherent, ++ .map_page = pci32_map_page, ++ .unmap_page = leon3_unmap_page, ++ .map_sg = pci32_map_sg, ++ .unmap_sg = leon3_unmap_sg, ++ .sync_single_for_cpu = pci32_sync_single_for_cpu, ++ .sync_single_for_device = pci32_sync_single_for_device, ++ .sync_sg_for_cpu = pci32_sync_sg_for_cpu, ++ .sync_sg_for_device = pci32_sync_sg_for_device, ++}; ++ ++#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */ ++ ++#ifdef CONFIG_SPARC_LEON ++struct dma_map_ops *dma_ops = &leon3_dma_ops; ++#else ++struct dma_map_ops *dma_ops = &sbus_dma_ops; ++#endif ++ ++#ifdef CONFIG_SBUS ++EXPORT_SYMBOL(dma_ops); ++#endif + + /* + * Return whether the given PCI device DMA address mask can be +@@ -676,6 +727,16 @@ int dma_supported(struct device *dev, u6 + } + EXPORT_SYMBOL(dma_supported); + ++int dma_set_mask(struct device *dev, u64 dma_mask) ++{ ++#ifdef CONFIG_PCI ++ if (dev->bus == &pci_bus_type) ++ return pci_set_dma_mask(to_pci_dev(dev), dma_mask); ++#endif ++ return -EOPNOTSUPP; ++} ++EXPORT_SYMBOL(dma_set_mask); ++ + #ifdef CONFIG_PROC_FS + + static int sparc_io_proc_show(struct seq_file *m, void *v) +@@ -717,7 +778,7 @@ static const struct file_operations spar + static struct resource *_sparc_find_resource(struct resource *root, + unsigned long hit) + { +- struct resource *tmp; ++ struct resource *tmp; + + for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { + if (tmp->start <= hit && tmp->end >= hit) diff --git a/target/linux/leon/patches-2.6.36/016-ioport_update.patch b/target/linux/leon/patches-2.6.36/016-ioport_update.patch new file mode 100644 index 0000000000..130b36ed11 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/016-ioport_update.patch @@ -0,0 +1,51 @@ +From 36cad96a50eb877d0c5cb3d8d93c1807ad9c774c Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 09:37:23 +0100 +Subject: [PATCH] Fix kristoffers ioport.c patch for more recent kernel. + +Signed-off-by: Daniel Hellstrom +--- + arch/sparc/include/asm/dma-mapping.h | 13 +------------ + arch/sparc/kernel/ioport.c | 3 ++- + 2 files changed, 3 insertions(+), 13 deletions(-) + +--- a/arch/sparc/include/asm/dma-mapping.h ++++ b/arch/sparc/include/asm/dma-mapping.h +@@ -51,17 +51,6 @@ static inline int dma_mapping_error(stru + return (dma_addr == DMA_ERROR_CODE); + } + +-static inline int dma_set_mask(struct device *dev, u64 mask) +-{ +-#ifdef CONFIG_PCI +- if (dev->bus == &pci_bus_type) { +- if (!dev->dma_mask || !dma_supported(dev, mask)) +- return -EINVAL; +- *dev->dma_mask = mask; +- return 0; +- } +-#endif +- return -EINVAL; +-} ++extern int dma_set_mask(struct device *dev, u64 dma_mask); + + #endif +--- a/arch/sparc/kernel/ioport.c ++++ b/arch/sparc/kernel/ioport.c +@@ -301,7 +301,7 @@ static void *sbus_alloc_coherent(struct + goto err_nova; + } + #endif +- res->name = op->node->name; ++ res->name = op->dev.of_node->name; + + return (void *)(unsigned long)res->start; + +@@ -737,6 +737,7 @@ int dma_set_mask(struct device *dev, u64 + } + EXPORT_SYMBOL(dma_set_mask); + ++ + #ifdef CONFIG_PROC_FS + + static int sparc_io_proc_show(struct seq_file *m, void *v) diff --git a/target/linux/leon/patches-2.6.36/017-greth_no_gbit.patch b/target/linux/leon/patches-2.6.36/017-greth_no_gbit.patch new file mode 100644 index 0000000000..5e3ee3d6a0 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/017-greth_no_gbit.patch @@ -0,0 +1,66 @@ +From 2e864d18c31d4e0255269f9e9cfccc09512676c6 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 16:51:38 +0100 +Subject: [PATCH] GRETH: added greth_no_gbit option + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 15 +++++++++++++-- + drivers/net/greth.h | 1 + + 2 files changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -66,6 +66,10 @@ static int greth_edcl = 1; + module_param(greth_edcl, int, 0); + MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used."); + ++static int no_gbit = 0; ++module_param(no_gbit, int, S_IRUGO); ++MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off)."); ++ + static int greth_open(struct net_device *dev); + static netdev_tx_t greth_start_xmit(struct sk_buff *skb, + struct net_device *dev); +@@ -1284,7 +1288,7 @@ static int greth_mdio_probe(struct net_d + } + + ret = phy_connect_direct(dev, phy, &greth_link_change, +- 0, greth->gbit_mac ? ++ 0, greth->gbit_phy_support ? + PHY_INTERFACE_MODE_GMII : + PHY_INTERFACE_MODE_MII); + if (ret) { +@@ -1293,7 +1297,7 @@ static int greth_mdio_probe(struct net_d + return ret; + } + +- if (greth->gbit_mac) ++ if (greth->gbit_phy_support) + phy->supported &= PHY_GBIT_FEATURES; + else + phy->supported &= PHY_BASIC_FEATURES; +@@ -1441,6 +1445,13 @@ static int __devinit greth_of_probe(stru + tmp = GRETH_REGLOAD(regs->control); + greth->gbit_mac = (tmp >> 27) & 1; + ++ /* Let user skip GBit link mode by telling MDIO layer that MAC does ++ * not support GBIT (for debug) */ ++ if (greth->gbit_mac && !no_gbit) ++ greth->gbit_phy_support = 1; ++ else ++ greth->gbit_phy_support = 0; ++ + /* Check for multicast capability */ + greth->multicast = (tmp >> 25) & 1; + +--- a/drivers/net/greth.h ++++ b/drivers/net/greth.h +@@ -138,6 +138,7 @@ struct greth_private { + u8 gbit_mac; + u8 mdio_int_en; + u8 edcl; ++ u8 gbit_phy_support; + }; + + #endif diff --git a/target/linux/leon/patches-2.6.36/018-greth_compat_mode.patch b/target/linux/leon/patches-2.6.36/018-greth_compat_mode.patch new file mode 100644 index 0000000000..4afe89eb07 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/018-greth_compat_mode.patch @@ -0,0 +1,41 @@ +From a498d7076ee0f82ec3f508293a9cf1ccba15829e Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 16:52:19 +0100 +Subject: [PATCH] GRETH: added greth_compat_mode module parameter + +The greth_compat_mode option can be used to set a GRETH GBit capable MAC +in operate as if the GRETH 10/100 device was found. The GRETH GBit supports +TCP/UDP checksum offloading, unaligned frame buffers, scatter gather etc. +Enabling this mode allows the developer to test the GRETH 10/100 device +without all features mentioned above on a GBit MAC capable of the above. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 9 +++++++++ + 1 files changed, 9 insertions(+), 0 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -70,6 +70,11 @@ static int no_gbit = 0; + module_param(no_gbit, int, S_IRUGO); + MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off)."); + ++/* Use this option to enable GRETH 10/100 code on GRETH_GBIT hardware (debug legacy code option) */ ++static int compat_mode = 0; ++module_param(compat_mode, int, S_IRUGO); ++MODULE_PARM_DESC(compat_mode, "GRETH 10/100 legacy mode enable. Only affects GRETH GBit MAC, default 0 (off)."); ++ + static int greth_open(struct net_device *dev); + static netdev_tx_t greth_start_xmit(struct sk_buff *skb, + struct net_device *dev); +@@ -1452,6 +1457,10 @@ static int __devinit greth_of_probe(stru + else + greth->gbit_phy_support = 0; + ++ /* Force GBit MAC in legacy 10/100 mode (no offloading etc.) */ ++ if (compat_mode == 1) ++ greth->gbit_mac = 0; ++ + /* Check for multicast capability */ + greth->multicast = (tmp >> 25) & 1; + diff --git a/target/linux/leon/patches-2.6.36/019-greth_fix_open_close.patch b/target/linux/leon/patches-2.6.36/019-greth_fix_open_close.patch new file mode 100644 index 0000000000..fffb39133a --- /dev/null +++ b/target/linux/leon/patches-2.6.36/019-greth_fix_open_close.patch @@ -0,0 +1,34 @@ +From 6216bc809c5bdd586b14d096fbaf6dc25574b928 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 09:59:14 +0100 +Subject: [PATCH] GRETH: fix opening/closing + +When NAPI is disabled there is no point in having IRQs enabled, TX/RX +should be off before clearing the TX/RX descriptor rings. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -365,6 +365,8 @@ static int greth_open(struct net_device + dev_dbg(&dev->dev, " starting queue\n"); + netif_start_queue(dev); + ++ GRETH_REGSAVE(greth->regs->status, 0xFF); ++ + napi_enable(&greth->napi); + + greth_enable_irqs(greth); +@@ -380,7 +382,9 @@ static int greth_close(struct net_device + + napi_disable(&greth->napi); + ++ greth_disable_irqs(greth); + greth_disable_tx(greth); ++ greth_disable_rx(greth); + + netif_stop_queue(dev); + diff --git a/target/linux/leon/patches-2.6.36/020-greth_optimize_gbit_tx_descriptor_handling.patch b/target/linux/leon/patches-2.6.36/020-greth_optimize_gbit_tx_descriptor_handling.patch new file mode 100644 index 0000000000..3a14eb76d9 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/020-greth_optimize_gbit_tx_descriptor_handling.patch @@ -0,0 +1,61 @@ +From 544631281bed5cc37b8f2d3a99f44c9d4b97f9a8 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 10:07:12 +0100 +Subject: [PATCH] GRETH: GBit transmit descriptor handling optimization + +It is safe to enable all fragments before enabling the first descriptor, +this way all descriptors don't have to be processed twice, added extra +memory barrier. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 19 ++++++++++--------- + 1 files changed, 10 insertions(+), 9 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -512,7 +512,7 @@ greth_start_xmit_gbit(struct sk_buff *sk + greth->tx_skbuff[curr_tx] = NULL; + bdp = greth->tx_bd_base + curr_tx; + +- status = GRETH_TXBD_CSALL; ++ status = GRETH_TXBD_CSALL | GRETH_BD_EN; + status |= frag->size & GRETH_BD_LEN; + + /* Wrap around descriptor ring */ +@@ -549,26 +549,27 @@ greth_start_xmit_gbit(struct sk_buff *sk + + wmb(); + +- /* Enable the descriptors that we configured ... */ +- for (i = 0; i < nr_frags + 1; i++) { +- bdp = greth->tx_bd_base + greth->tx_next; +- greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); +- greth->tx_next = NEXT_TX(greth->tx_next); +- greth->tx_free--; +- } ++ /* Enable the descriptor chain by enabling the first descriptor */ ++ bdp = greth->tx_bd_base + greth->tx_next; ++ greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); ++ greth->tx_next = curr_tx; ++ greth->tx_free -= nr_frags + 1; ++ ++ wmb(); + + greth_enable_tx(greth); + + return NETDEV_TX_OK; + + frag_map_error: +- /* Unmap SKB mappings that succeeded */ ++ /* Unmap SKB mappings that succeeded and disable descriptor */ + for (i = 0; greth->tx_next + i != curr_tx; i++) { + bdp = greth->tx_bd_base + greth->tx_next + i; + dma_unmap_single(greth->dev, + greth_read_bd(&bdp->addr), + greth_read_bd(&bdp->stat) & GRETH_BD_LEN, + DMA_TO_DEVICE); ++ greth_write_bd(&bdp->stat, 0); + } + map_error: + if (net_ratelimit()) diff --git a/target/linux/leon/patches-2.6.36/021-greth_fix_memory_leak.patch b/target/linux/leon/patches-2.6.36/021-greth_fix_memory_leak.patch new file mode 100644 index 0000000000..1d05af1247 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/021-greth_fix_memory_leak.patch @@ -0,0 +1,49 @@ +From 54789a03adf9c924d0cf7b890323c9c1ca7ab042 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 10:26:09 +0100 +Subject: [PATCH] GRETH: fixed skb buffer memory leak on frame errors + +A new SKB buffer should not be allocated when the old SKB is reused. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 17 +++++++++++------ + 1 files changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -879,10 +879,8 @@ static int greth_rx_gbit(struct net_devi + } + } + +- /* Allocate new skb to replace current */ +- newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN); +- +- if (!bad && newskb) { ++ /* Allocate new skb to replace current, not needed if the current skb can be reused */ ++ if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) { + skb_reserve(newskb, NET_IP_ALIGN); + + dma_addr = dma_map_single(greth->dev, +@@ -919,12 +917,19 @@ static int greth_rx_gbit(struct net_devi + if (net_ratelimit()) + dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n"); + dev_kfree_skb(newskb); +- dev->stats.rx_dropped++; ++ dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */ + } ++ } else if ( bad ) { ++ /* Bad Frame transfer, the skb is reused */ ++ dev->stats.rx_dropped++; + } else { ++ /* Failed Allocating a new skb. This is rather stupid but the current "filled" ++ * skb is reused, as if transfer failure. One could argue that RX descriptor table ++ * handling should be divided into cleaning and filling as the TX part of the driver ++ */ + if (net_ratelimit()) + dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n"); +- dev->stats.rx_dropped++; ++ dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */ + } + + status = GRETH_BD_EN | GRETH_BD_IE; diff --git a/target/linux/leon/patches-2.6.36/022-greth_avoid_bad_speed_duplex.patch b/target/linux/leon/patches-2.6.36/022-greth_avoid_bad_speed_duplex.patch new file mode 100644 index 0000000000..e8253640dc --- /dev/null +++ b/target/linux/leon/patches-2.6.36/022-greth_avoid_bad_speed_duplex.patch @@ -0,0 +1,50 @@ +From c2e963057ca5635d6e5387623c3ad0c0b3123754 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 10:28:37 +0100 +Subject: [PATCH] GRETH: avoid writing bad speed/duplex when setting transfer mode + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 19 ++++++++----------- + 1 files changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -1236,29 +1236,26 @@ static void greth_link_change(struct net + struct greth_private *greth = netdev_priv(dev); + struct phy_device *phydev = greth->phy; + unsigned long flags; +- + int status_change = 0; ++ u32 ctrl; + + spin_lock_irqsave(&greth->devlock, flags); + + if (phydev->link) { + + if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) { +- +- GRETH_REGANDIN(greth->regs->control, +- ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB)); ++ ctrl = GRETH_REGLOAD(greth->regs->control) & ++ ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB); + + if (phydev->duplex) +- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD); +- +- if (phydev->speed == SPEED_100) { +- +- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP); +- } ++ ctrl |= GRETH_CTRL_FD; + ++ if (phydev->speed == SPEED_100) ++ ctrl |= GRETH_CTRL_SP; + else if (phydev->speed == SPEED_1000) +- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB); ++ ctrl |= GRETH_CTRL_GB; + ++ GRETH_REGSAVE(greth->regs->control, ctrl); + greth->speed = phydev->speed; + greth->duplex = phydev->duplex; + status_change = 1; diff --git a/target/linux/leon/patches-2.6.36/023-greth_handle_frame_error_interrupts.patch b/target/linux/leon/patches-2.6.36/023-greth_handle_frame_error_interrupts.patch new file mode 100644 index 0000000000..12bfb1c01f --- /dev/null +++ b/target/linux/leon/patches-2.6.36/023-greth_handle_frame_error_interrupts.patch @@ -0,0 +1,49 @@ +From f62c047af910c9c9696db7b47472a3728b8100e8 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 11:56:22 +0100 +Subject: [PATCH] GRETH: handle frame error interrupts + +Not handling frame error interrupts are unlikly but may lead to dead +lock if 128 error frames are recieved in a row. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 5 +++-- + drivers/net/greth.h | 2 ++ + 2 files changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -595,11 +595,12 @@ static irqreturn_t greth_interrupt(int i + status = GRETH_REGLOAD(greth->regs->status); + + /* Handle rx and tx interrupts through poll */ +- if (status & (GRETH_INT_RX | GRETH_INT_TX)) { ++ if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) { + + /* Clear interrupt status */ + GRETH_REGSAVE(greth->regs->status, +- status & (GRETH_INT_RX | GRETH_INT_TX)); ++ status & (GRETH_INT_RE | GRETH_INT_RX | ++ GRETH_INT_TE | GRETH_INT_TX)); + + retval = IRQ_HANDLED; + +--- a/drivers/net/greth.h ++++ b/drivers/net/greth.h +@@ -23,6 +23,7 @@ + #define GRETH_BD_LEN 0x7FF + + #define GRETH_TXEN 0x1 ++#define GRETH_INT_TE 0x2 + #define GRETH_INT_TX 0x8 + #define GRETH_TXI 0x4 + #define GRETH_TXBD_STATUS 0x0001C000 +@@ -35,6 +36,7 @@ + #define GRETH_TXBD_ERR_UE 0x4000 + #define GRETH_TXBD_ERR_AL 0x8000 + ++#define GRETH_INT_RE 0x1 + #define GRETH_INT_RX 0x4 + #define GRETH_RXEN 0x2 + #define GRETH_RXI 0x8 diff --git a/target/linux/leon/patches-2.6.36/024-greth_resolve_smp_and_other_issues.patch b/target/linux/leon/patches-2.6.36/024-greth_resolve_smp_and_other_issues.patch new file mode 100644 index 0000000000..c2293cae04 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/024-greth_resolve_smp_and_other_issues.patch @@ -0,0 +1,399 @@ +From 4439d933884ee3c7e320b8d33bd2e268dd5b6fa5 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 11:40:19 +0100 +Subject: [PATCH] GRETH: resolve SMP issues and other problems + +Fixes the following: +1. POLL should not enable IRQ when work is not completed +2. No locking between TX descriptor cleaning and XMIT descriptor handling +3. No locking between RX POLL and XMIT modifying control register +4. Since TX cleaning (called from POLL) is running in parallel with XMIT + unnecessary locking is needed. +5. IRQ handler looks at RX frame status solely, this is wrong when IRQ is + temporarily disabled (in POLL), and when IRQ is shared. +6. IRQ handler clears IRQ status, which is unnecessary +7. TX queue was stopped in preventing cause when not MAX_SKB_FRAGS+1 descriptors + were available after a SKB been scheduled by XMIT. Instead the TX queue is + stopped first when not enough descriptors are available upon entering XMIT. + +It was hard to split up this patch in smaller pieces since all are tied +together somehow. + +Note the RX flag used in the interrupt handler does not signal that interrtupt +was asserted, but that a frame was received. Same goes for TX. Also, IRQ is not +asserted when the RX flag is set before enabling IRQ enable until a new frame is +received. So extra care must be taken to avoid enabling IRQ and all descriptors +are already used, hence dead lock will upon us. See new POLL implementation that +enableds IRQ then look at the RX flag to determine if one or more IRQs may have +been missed. TX/RX flags are cleared before handling previously enabled +descriptors, this ensures that the RX/TX flags are valid when determining if IRQ +should be turned on again. + +By moving TX cleaning from POLL to XMIT in the standard case, removes some +locking trouble. Enabling TX cleaning from poll only when not enough TX +descriptors are available is safe because the TX queue is at the same time +stopped, thus XMIT will not be called. The TX queue is woken up again when +enough descriptrs are available. + +TX Frames are always enabled with IRQ, however the TX IRQ Enable flag will not +be enabled until XMIT must wait for free descriptors. + +Locking RX and XMIT parts of the driver from each other is needed because the +RX/TX enable bits share the same register. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 158 ++++++++++++++++++++++++++++++--------------------- + 1 files changed, 93 insertions(+), 65 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -1,7 +1,7 @@ + /* + * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC. + * +- * 2005-2009 (c) Aeroflex Gaisler AB ++ * 2005-2010 (c) Aeroflex Gaisler AB + * + * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs + * available in the GRLIB VHDL IP core library. +@@ -401,12 +401,20 @@ greth_start_xmit(struct sk_buff *skb, st + struct greth_private *greth = netdev_priv(dev); + struct greth_bd *bdp; + int err = NETDEV_TX_OK; +- u32 status, dma_addr; ++ u32 status, dma_addr, ctrl; ++ unsigned long flags; + +- bdp = greth->tx_bd_base + greth->tx_next; ++ /* Clean TX Ring */ ++ greth_clean_tx(greth->netdev); + + if (unlikely(greth->tx_free <= 0)) { ++ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ ++ ctrl = GRETH_REGLOAD(greth->regs->control); ++ /* Enable TX IRQ only if not already in poll() routine */ ++ if ( ctrl & GRETH_RXI ) ++ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); + netif_stop_queue(dev); ++ spin_unlock_irqrestore(&greth->devlock, flags); + return NETDEV_TX_BUSY; + } + +@@ -419,13 +427,14 @@ greth_start_xmit(struct sk_buff *skb, st + goto out; + } + ++ bdp = greth->tx_bd_base + greth->tx_next; + dma_addr = greth_read_bd(&bdp->addr); + + memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); + + dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); + +- status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN); ++ status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN); + + /* Wrap around descriptor ring */ + if (greth->tx_next == GRETH_TXBD_NUM_MASK) { +@@ -435,22 +444,11 @@ greth_start_xmit(struct sk_buff *skb, st + greth->tx_next = NEXT_TX(greth->tx_next); + greth->tx_free--; + +- /* No more descriptors */ +- if (unlikely(greth->tx_free == 0)) { +- +- /* Free transmitted descriptors */ +- greth_clean_tx(dev); +- +- /* If nothing was cleaned, stop queue & wait for irq */ +- if (unlikely(greth->tx_free == 0)) { +- status |= GRETH_BD_IE; +- netif_stop_queue(dev); +- } +- } +- + /* Write descriptor control word and enable transmission */ + greth_write_bd(&bdp->stat, status); ++ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ + greth_enable_tx(greth); ++ spin_unlock_irqrestore(&greth->devlock, flags); + + out: + dev_kfree_skb(skb); +@@ -463,13 +461,24 @@ greth_start_xmit_gbit(struct sk_buff *sk + { + struct greth_private *greth = netdev_priv(dev); + struct greth_bd *bdp; +- u32 status = 0, dma_addr; ++ u32 status = 0, dma_addr, ctrl; + int curr_tx, nr_frags, i, err = NETDEV_TX_OK; ++ unsigned long flags; + + nr_frags = skb_shinfo(skb)->nr_frags; + ++ /* Clean TX Ring */ ++ greth_clean_tx_gbit(dev); ++ + if (greth->tx_free < nr_frags + 1) { ++ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ ++ ctrl = GRETH_REGLOAD(greth->regs->control); ++ /* Enable TX IRQ only if not already in poll() routine */ ++ if ( ctrl & GRETH_RXI ) { ++ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); ++ } + netif_stop_queue(dev); ++ spin_unlock_irqrestore(&greth->devlock, flags); + err = NETDEV_TX_BUSY; + goto out; + } +@@ -522,14 +531,8 @@ greth_start_xmit_gbit(struct sk_buff *sk + /* More fragments left */ + if (i < nr_frags - 1) + status |= GRETH_TXBD_MORE; +- +- /* ... last fragment, check if out of descriptors */ +- else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) { +- +- /* Enable interrupts and stop queue */ +- status |= GRETH_BD_IE; +- netif_stop_queue(dev); +- } ++ else ++ status |= GRETH_BD_IE; /* enable IRQ on last fragment */ + + greth_write_bd(&bdp->stat, status); + +@@ -557,7 +560,9 @@ greth_start_xmit_gbit(struct sk_buff *sk + + wmb(); + ++ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ + greth_enable_tx(greth); ++ spin_unlock_irqrestore(&greth->devlock, flags); + + return NETDEV_TX_OK; + +@@ -579,12 +584,11 @@ out: + return err; + } + +- + static irqreturn_t greth_interrupt(int irq, void *dev_id) + { + struct net_device *dev = dev_id; + struct greth_private *greth; +- u32 status; ++ u32 status, ctrl; + irqreturn_t retval = IRQ_NONE; + + greth = netdev_priv(dev); +@@ -594,13 +598,14 @@ static irqreturn_t greth_interrupt(int i + /* Get the interrupt events that caused us to be here. */ + status = GRETH_REGLOAD(greth->regs->status); + +- /* Handle rx and tx interrupts through poll */ +- if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) { ++ /* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be set regardless ++ * of whether IRQ is enabled or not. Especially important when shared IRQ. ++ */ ++ ctrl = GRETH_REGLOAD(greth->regs->control); + +- /* Clear interrupt status */ +- GRETH_REGSAVE(greth->regs->status, +- status & (GRETH_INT_RE | GRETH_INT_RX | +- GRETH_INT_TE | GRETH_INT_TX)); ++ /* Handle rx and tx interrupts through poll */ ++ if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) || ++ ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) { + + retval = IRQ_HANDLED; + +@@ -625,6 +630,8 @@ static void greth_clean_tx(struct net_de + + while (1) { + bdp = greth->tx_bd_base + greth->tx_last; ++ GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); ++ mb(); + stat = greth_read_bd(&bdp->stat); + + if (unlikely(stat & GRETH_BD_EN)) +@@ -685,7 +692,10 @@ static void greth_clean_tx_gbit(struct n + + /* We only clean fully completed SKBs */ + bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags); +- stat = bdp_last_frag->stat; ++ ++ GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); ++ mb(); ++ stat = greth_read_bd(&bdp_last_frag->stat); + + if (stat & GRETH_BD_EN) + break; +@@ -717,23 +727,12 @@ static void greth_clean_tx_gbit(struct n + greth->tx_free += nr_frags+1; + dev_kfree_skb(skb); + } +- if (greth->tx_free > (MAX_SKB_FRAGS + 1)) { ++ ++ if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS + 1))) { + netif_wake_queue(dev); + } + } + +-static int greth_pending_packets(struct greth_private *greth) +-{ +- struct greth_bd *bdp; +- u32 status; +- bdp = greth->rx_bd_base + greth->rx_cur; +- status = greth_read_bd(&bdp->stat); +- if (status & GRETH_BD_EN) +- return 0; +- else +- return 1; +-} +- + static int greth_rx(struct net_device *dev, int limit) + { + struct greth_private *greth; +@@ -742,20 +741,24 @@ static int greth_rx(struct net_device *d + int pkt_len; + int bad, count; + u32 status, dma_addr; ++ unsigned long flags; + + greth = netdev_priv(dev); + + for (count = 0; count < limit; ++count) { + + bdp = greth->rx_bd_base + greth->rx_cur; ++ GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); ++ mb(); + status = greth_read_bd(&bdp->stat); +- dma_addr = greth_read_bd(&bdp->addr); +- bad = 0; + + if (unlikely(status & GRETH_BD_EN)) { + break; + } + ++ dma_addr = greth_read_bd(&bdp->addr); ++ bad = 0; ++ + /* Check status for errors. */ + if (unlikely(status & GRETH_RXBD_STATUS)) { + if (status & GRETH_RXBD_ERR_FT) { +@@ -817,7 +820,9 @@ static int greth_rx(struct net_device *d + + dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE); + ++ spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */ + greth_enable_rx(greth); ++ spin_unlock_irqrestore(&greth->devlock, flags); + + greth->rx_cur = NEXT_RX(greth->rx_cur); + } +@@ -851,6 +856,7 @@ static int greth_rx_gbit(struct net_devi + int pkt_len; + int bad, count = 0; + u32 status, dma_addr; ++ unsigned long flags; + + greth = netdev_priv(dev); + +@@ -858,6 +864,8 @@ static int greth_rx_gbit(struct net_devi + + bdp = greth->rx_bd_base + greth->rx_cur; + skb = greth->rx_skbuff[greth->rx_cur]; ++ GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); ++ mb(); + status = greth_read_bd(&bdp->stat); + bad = 0; + +@@ -940,7 +948,9 @@ static int greth_rx_gbit(struct net_devi + + wmb(); + greth_write_bd(&bdp->stat, status); ++ spin_lock_irqsave(&greth->devlock, flags); + greth_enable_rx(greth); ++ spin_unlock_irqrestore(&greth->devlock, flags); + greth->rx_cur = NEXT_RX(greth->rx_cur); + } + +@@ -952,15 +962,19 @@ static int greth_poll(struct napi_struct + { + struct greth_private *greth; + int work_done = 0; ++ unsigned long flags; ++ u32 mask, ctrl; + greth = container_of(napi, struct greth_private, napi); + +- if (greth->gbit_mac) { +- greth_clean_tx_gbit(greth->netdev); +- } else { +- greth_clean_tx(greth->netdev); ++restart_txrx_poll: ++ if ( netif_queue_stopped(greth->netdev) ) { ++ if (greth->gbit_mac) { ++ greth_clean_tx_gbit(greth->netdev); ++ } else { ++ greth_clean_tx(greth->netdev); ++ } + } + +-restart_poll: + if (greth->gbit_mac) { + work_done += greth_rx_gbit(greth->netdev, budget - work_done); + } else { +@@ -969,15 +983,29 @@ restart_poll: + + if (work_done < budget) { + +- napi_complete(napi); ++ spin_lock_irqsave(&greth->devlock, flags); + +- if (greth_pending_packets(greth)) { +- napi_reschedule(napi); +- goto restart_poll; ++ ctrl = GRETH_REGLOAD(greth->regs->control); ++ if (netif_queue_stopped(greth->netdev)) { ++ GRETH_REGSAVE(greth->regs->control, ++ ctrl | GRETH_TXI | GRETH_RXI); ++ mask = GRETH_INT_RX | GRETH_INT_RE | ++ GRETH_INT_TX | GRETH_INT_TE; ++ } else { ++ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI); ++ mask = GRETH_INT_RX | GRETH_INT_RE; ++ } ++ ++ if (GRETH_REGLOAD(greth->regs->status) & mask) { ++ GRETH_REGSAVE(greth->regs->control, ctrl); ++ spin_unlock_irqrestore(&greth->devlock, flags); ++ goto restart_txrx_poll; ++ } else { ++ __napi_complete(napi); ++ spin_unlock_irqrestore(&greth->devlock, flags); + } + } + +- greth_enable_irqs(greth); + return work_done; + } + +@@ -1172,11 +1200,11 @@ static const struct ethtool_ops greth_et + }; + + static struct net_device_ops greth_netdev_ops = { +- .ndo_open = greth_open, +- .ndo_stop = greth_close, +- .ndo_start_xmit = greth_start_xmit, +- .ndo_set_mac_address = greth_set_mac_add, +- .ndo_validate_addr = eth_validate_addr, ++ .ndo_open = greth_open, ++ .ndo_stop = greth_close, ++ .ndo_start_xmit = greth_start_xmit, ++ .ndo_set_mac_address = greth_set_mac_add, ++ .ndo_validate_addr = eth_validate_addr, + }; + + static inline int wait_for_mdio(struct greth_private *greth) diff --git a/target/linux/leon/patches-2.6.36/025-greth_bootloader_disable_device_node.patch b/target/linux/leon/patches-2.6.36/025-greth_bootloader_disable_device_node.patch new file mode 100644 index 0000000000..836bab1fa4 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/025-greth_bootloader_disable_device_node.patch @@ -0,0 +1,25 @@ +From 66d5b37cc6d32291419bf99161e83e2946ea5f25 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 12:11:03 +0100 +Subject: [PATCH] GRETH: added option to disable a device node from bootloader. + +Signed-off-by: Daniel Hellstrom +--- + drivers/net/greth.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -1428,6 +1428,12 @@ static int __devinit greth_of_probe(stru + int err; + int tmp; + unsigned long timeout; ++ int *ampopts; ++ ++ /* Skip device if used by another OS instance */ ++ ampopts = (int *) of_get_property(ofdev->dev.of_node, "ampopts", NULL); ++ if (ampopts && (*ampopts == 0)) ++ return -EIO; + + dev = alloc_etherdev(sizeof(struct greth_private)); + diff --git a/target/linux/leon/patches-2.6.36/026-greth_gbit_mac_set_ee_when_edcl.patch b/target/linux/leon/patches-2.6.36/026-greth_gbit_mac_set_ee_when_edcl.patch new file mode 100644 index 0000000000..94fa0bd344 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/026-greth_gbit_mac_set_ee_when_edcl.patch @@ -0,0 +1,31 @@ +From 50fcb51c42bc721f18f1bfa10f705519cd344a2a Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom +Date: Wed, 1 Dec 2010 16:20:01 +0100 +Subject: [PATCH] GRETH: Newer GBit MACs need setting EE bit when EDCL should be enabled + +--- + drivers/net/greth.c | 2 +- + drivers/net/greth.h | 1 + + 2 files changed, 2 insertions(+), 1 deletions(-) + +--- a/drivers/net/greth.c ++++ b/drivers/net/greth.c +@@ -1511,7 +1511,7 @@ static int __devinit greth_of_probe(stru + /* If we have EDCL we disable the EDCL speed-duplex FSM so + * it doesn't interfere with the software */ + if (greth->edcl != 0) +- GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX); ++ GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX|GRETH_CTRL_EE); + + /* Check if MAC can handle MDIO interrupts */ + greth->mdio_int_en = (tmp >> 26) & 1; +--- a/drivers/net/greth.h ++++ b/drivers/net/greth.h +@@ -15,6 +15,7 @@ + #define GRETH_CTRL_PSTATIEN 0x400 + #define GRETH_CTRL_MCEN 0x800 + #define GRETH_CTRL_DISDUPLEX 0x1000 ++#define GRETH_CTRL_EE 0x4000 + #define GRETH_STATUS_PHYSTAT 0x100 + + #define GRETH_BD_EN 0x800 diff --git a/target/linux/leon/patches-2.6.36/027-sparc_v8_assembler.patch b/target/linux/leon/patches-2.6.36/027-sparc_v8_assembler.patch new file mode 100644 index 0000000000..5baea94f74 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/027-sparc_v8_assembler.patch @@ -0,0 +1,31 @@ +[PATCH] sparc32: Add -Av8 to assembler command line. + +Newer version of binutils are more strict about specifying the +correct options to enable certain classes of instructions. + +The sparc32 build is done for v7 in order to support sun4c systems +which lack hardware integer multiply and divide instructions. + +So we have to pass -Av8 when building the assembler routines that +use these instructions and get patched into the kernel when we find +out that we have a v8 capable cpu. + +Reported-by: Paul Gortmaker +Signed-off-by: David S. Miller +--- + arch/sparc/Makefile | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile +index ad1fb5d..eddcfb3 100644 +--- a/arch/sparc/Makefile ++++ b/arch/sparc/Makefile +@@ -31,7 +31,7 @@ UTS_MACHINE := sparc + + #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 + KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 +-KBUILD_AFLAGS += -m32 ++KBUILD_AFLAGS += -m32 -Wa,-Av8 + + #LDFLAGS_vmlinux = -N -Ttext 0xf0004000 + # Since 2.5.40, the first stage is left not btfix-ed. diff --git a/target/linux/leon/patches/001-find_irq_and_timer_via_of.patch b/target/linux/leon/patches/001-find_irq_and_timer_via_of.patch deleted file mode 100644 index 18d7f8beac..0000000000 --- a/target/linux/leon/patches/001-find_irq_and_timer_via_of.patch +++ /dev/null @@ -1,48 +0,0 @@ -From af1da1d5a8701f39cdbae4a0ab8e04b450eef298 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 8 Sep 2010 18:05:38 +0200 -Subject: [PATCH] SPARC/LEON: find IRQ and Timer via OF-Tree, instead of hardcoded. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/leon_kernel.c | 23 ++++++++++++++++++++++- - 1 files changed, 22 insertions(+), 1 deletions(-) - ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -105,13 +105,34 @@ static void leon_disable_irq(unsigned in - void __init leon_init_timers(irq_handler_t counter_fn) - { - int irq; -+ struct device_node *rootnp, *np; -+ struct property *pp; -+ int len; - - leondebug_irq_disable = 0; - leon_debug_irqout = 0; - master_l10_counter = (unsigned int *)&dummy_master_l10_counter; - dummy_master_l10_counter = 0; - -- if (leon3_gptimer_regs && leon3_irqctrl_regs) { -+ /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ -+ rootnp = of_find_node_by_path("/ambapp0"); -+ if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) { -+ pp = of_find_property(np, "reg", &len); -+ if (pp) -+ leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; -+ } -+ -+ /* Find GPTIMER Timer Registers base address otherwise bail out. */ -+ if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) { -+ pp = of_find_property(np, "reg", &len); -+ if (pp) -+ leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; -+ pp = of_find_property(np, "interrupts", &len); -+ if (pp) -+ leon3_gptimer_irq = *(unsigned int *)pp->value; -+ } -+ -+ if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, - (((1000000 / HZ) - 1))); diff --git a/target/linux/leon/patches/002-sparc_uimage_target.patch b/target/linux/leon/patches/002-sparc_uimage_target.patch deleted file mode 100644 index 6e25ff27d7..0000000000 --- a/target/linux/leon/patches/002-sparc_uimage_target.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 234ef25344b567b3b8dad62c0863ebe16377528f Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Tue, 14 Sep 2010 11:26:55 +0200 -Subject: [PATCH] SPARC: added U-Boot build target: uImage - ---- - arch/sparc/Makefile | 3 ++- - arch/sparc/boot/Makefile | 35 +++++++++++++++++++++++++++++++++++ - 2 files changed, 37 insertions(+), 1 deletions(-) - ---- a/arch/sparc/Makefile -+++ b/arch/sparc/Makefile -@@ -88,7 +88,7 @@ boot := arch/sparc/boot - # Default target - all: zImage - --image zImage tftpboot.img vmlinux.aout: vmlinux -+image zImage uImage tftpboot.img vmlinux.aout: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - - archclean: -@@ -102,6 +102,7 @@ ifeq ($(ARCH),sparc) - define archhelp - echo '* image - kernel image ($(boot)/image)' - echo '* zImage - stripped kernel image ($(boot)/zImage)' -+ echo ' uImage - U-Boot SPARC32/LEON Image' - echo ' tftpboot.img - image prepared for tftp' - endef - else ---- a/arch/sparc/boot/Makefile -+++ b/arch/sparc/boot/Makefile -@@ -5,6 +5,7 @@ - - ROOT_IMG := /usr/src/root.img - ELFTOAOUT := elftoaout -+MKIMAGE := $(srctree)/scripts/mkuboot.sh - - hostprogs-y := piggyback_32 piggyback_64 btfixupprep - targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout -@@ -90,5 +91,39 @@ $(obj)/tftpboot.img: $(obj)/image $(obj) - $(obj)/vmlinux.aout: vmlinux FORCE - $(call if_changed,elftoaout) - @echo ' kernel: $@ is ready' -+else -+ -+# The following lines make a readable image for U-Boot. -+# uImage - Binary file read by U-boot -+# uImage.o - object file of uImage for loading with a -+# flash programmer understanding ELF. -+ -+OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment -+$(obj)/image.bin: $(obj)/image FORCE -+ $(call if_changed,objcopy) -+ -+$(obj)/image.gz: $(obj)/image.bin -+ $(call if_changed,gzip) -+ -+# Start of Main memory -+ifndef UIMAGE_LOADADDR -+UIMAGE_LOADADDR=0x40004000 - endif - -+# The first sector after the U-Boot image (256k) -+ifndef UIMAGE_FLASHADDR -+UIMAGE_FLASHADDR=0x00040000 -+endif -+ -+quiet_cmd_uimage = UIMAGE $@ -+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \ -+ -C gzip -a $(UIMAGE_LOADADDR) -e 0xf0004000 -n 'Linux-$(KERNELRELEASE)' \ -+ -d $< $@ -+ -+targets += uImage -+$(obj)/uImage: $(obj)/image.gz -+ $(call if_changed,uimage) -+ $(LD) -Tdata $(UIMAGE_FLASHADDR) -r -b binary arch/sparc/boot/uImage -o arch/sparc/boot/uImage.o -+ @echo ' Image $@ is ready' -+ -+endif diff --git a/target/linux/leon/patches/003-smp_cpu_stuck_fix.patch b/target/linux/leon/patches/003-smp_cpu_stuck_fix.patch deleted file mode 100644 index 3d572f5f29..0000000000 --- a/target/linux/leon/patches/003-smp_cpu_stuck_fix.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 417bc6751fdd3c24df274f25e020ec3decd09280 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Thu, 16 Sep 2010 11:00:46 +0200 -Subject: [PATCH] Fixed SPARC/LEON SMP CPU Stuck problem. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/leon_smp.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/sparc/kernel/leon_smp.c -+++ b/arch/sparc/kernel/leon_smp.c -@@ -56,8 +56,8 @@ void __init leon_configure_cache_smp(voi - static inline unsigned long do_swap(volatile unsigned long *ptr, - unsigned long val) - { -- __asm__ __volatile__("swapa [%1] %2, %0\n\t" : "=&r"(val) -- : "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) -+ __asm__ __volatile__("swapa [%2] %3, %0\n\t" : "=&r"(val) -+ : "0"(val), "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) - : "memory"); - return val; - } diff --git a/target/linux/leon/patches/004-extended_irq_controller.patch b/target/linux/leon/patches/004-extended_irq_controller.patch deleted file mode 100644 index b660b648b8..0000000000 --- a/target/linux/leon/patches/004-extended_irq_controller.patch +++ /dev/null @@ -1,119 +0,0 @@ -From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Thu, 16 Sep 2010 11:12:41 +0200 -Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/include/asm/irq_32.h | 4 ++++ - arch/sparc/kernel/irq_32.c | 32 ++++++++++++++++++++++++++------ - arch/sparc/kernel/leon_kernel.c | 8 +++++++- - 3 files changed, 37 insertions(+), 7 deletions(-) - ---- a/arch/sparc/include/asm/irq_32.h -+++ b/arch/sparc/include/asm/irq_32.h -@@ -6,7 +6,11 @@ - #ifndef _SPARC_IRQ_H - #define _SPARC_IRQ_H - -+#ifdef CONFIG_SPARC_LEON -+#define NR_IRQS 32 -+#else - #define NR_IRQS 16 -+#endif - - #include - ---- a/arch/sparc/kernel/irq_32.c -+++ b/arch/sparc/kernel/irq_32.c -@@ -110,6 +110,11 @@ EXPORT_SYMBOL(__raw_local_irq_save); - EXPORT_SYMBOL(raw_local_irq_enable); - EXPORT_SYMBOL(raw_local_irq_restore); - -+#ifdef CONFIG_SPARC_LEON -+extern unsigned int sparc_leon_eirq; -+extern int sparc_leon_eirq_get(int eirq, int cpu); -+#endif -+ - /* - * Dave Redman (djhr@tadpole.co.uk) - * -@@ -222,10 +227,11 @@ void free_irq(unsigned int irq, void *de - return; - } - cpu_irq = irq & (NR_IRQS - 1); -- if (cpu_irq > 14) { /* 14 irq levels on the sparc */ -- printk("Trying to free bogus IRQ %d\n", irq); -- return; -- } -+ /* 14 irq levels on the sparc, however some LEON systems have 31 IRQs */ -+ if ((cpu_irq == 15) || (cpu_irq >= NR_IRQS)) { -+ printk("Trying to free bogus IRQ %d\n", irq); -+ return; -+ } - - spin_lock_irqsave(&irq_action_lock, flags); - -@@ -303,7 +309,14 @@ void unexpected_irq(int irq, void *dev_i - int i; - struct irqaction * action; - unsigned int cpu_irq; -- -+ -+#ifdef CONFIG_SPARC_LEON -+ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */ -+ if ( sparc_leon_eirq == irq ) { -+ irq = sparc_leon_eirq_get(irq, smp_processor_id()); -+ } -+#endif -+ - cpu_irq = irq & (NR_IRQS - 1); - action = sparc_irq[cpu_irq].action; - -@@ -330,6 +343,13 @@ void handler_irq(int irq, struct pt_regs - extern void smp4m_irq_rotate(int cpu); - #endif - -+#ifdef CONFIG_SPARC_LEON -+ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */ -+ if ( sparc_leon_eirq == irq ) { -+ irq = sparc_leon_eirq_get(irq, cpu); -+ } -+#endif -+ - old_regs = set_irq_regs(regs); - irq_enter(); - disable_pil_irq(irq); -@@ -526,7 +546,7 @@ int request_irq(unsigned int irq, - return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); - } - cpu_irq = irq & (NR_IRQS - 1); -- if(cpu_irq > 14) { -+ if(cpu_irq == 15) { - ret = -EINVAL; - goto out; - } ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -104,7 +104,7 @@ static void leon_disable_irq(unsigned in - - void __init leon_init_timers(irq_handler_t counter_fn) - { -- int irq; -+ int irq, eirq; - struct device_node *rootnp, *np; - struct property *pp; - int len; -@@ -153,6 +153,12 @@ void __init leon_init_timers(irq_handler - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); - # endif - -+ LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); -+ eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf; -+ if ( eirq != 0 ) { -+ /* Extended IRQ controller available */ -+ sparc_leon_eirq_register(eirq); -+ } - } else { - printk(KERN_ERR "No Timer/irqctrl found\n"); - BUG(); diff --git a/target/linux/leon/patches/005-avoid_openprom_duplicates.patch b/target/linux/leon/patches/005-avoid_openprom_duplicates.patch deleted file mode 100644 index 54bfd2726b..0000000000 --- a/target/linux/leon/patches/005-avoid_openprom_duplicates.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 486a578298b7ab45c3edfdce8d4feaef93c3229b Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Thu, 16 Sep 2010 11:15:37 +0200 -Subject: [PATCH] SPARC/LEON: to avoid name duplicates in openprom fs when REG is not available the NAME now includes NODE ID when REG not present - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/prom_32.c | 27 +++++++++++++++++++-------- - 1 files changed, 19 insertions(+), 8 deletions(-) - ---- a/arch/sparc/kernel/prom_32.c -+++ b/arch/sparc/kernel/prom_32.c -@@ -136,18 +136,29 @@ static void __init ebus_path_component(s - /* "name:vendor:device@irq,addrlo" */ - static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) - { -- struct amba_prom_registers *regs; unsigned int *intr; -- unsigned int *device, *vendor; -+ struct amba_prom_registers *regs; -+ unsigned int *intr, *device, *vendor, reg0; - struct property *prop; -+ int interrupt = 0; - -+ /* In order to get a unique ID in the device tree (multiple AMBA devices -+ * may have the same name) the node number is printed -+ */ - prop = of_find_property(dp, "reg", NULL); -- if (!prop) -- return; -- regs = prop->value; -+ if (!prop) { -+ reg0 = (unsigned int)dp->phandle; -+ } else { -+ regs = prop->value; -+ reg0 = regs->phys_addr; -+ } -+ -+ /* Not all cores have Interrupt */ - prop = of_find_property(dp, "interrupts", NULL); - if (!prop) -- return; -- intr = prop->value; -+ intr = &interrupt; /* IRQ0 does not exist */ -+ else -+ intr = prop->value; -+ - prop = of_find_property(dp, "vendor", NULL); - if (!prop) - return; -@@ -159,7 +170,7 @@ static void __init ambapp_path_component - - sprintf(tmp_buf, "%s:%d:%d@%x,%x", - dp->name, *vendor, *device, -- *intr, regs->phys_addr); -+ *intr, reg0); - } - - static void __init __build_path_component(struct device_node *dp, char *tmp_buf) diff --git a/target/linux/leon/patches/006-amp_support.patch b/target/linux/leon/patches/006-amp_support.patch deleted file mode 100644 index 98d1c9f30d..0000000000 --- a/target/linux/leon/patches/006-amp_support.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 25a68b8cd8ea1553f8b56278418d6c1ecc12e247 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 22 Sep 2010 10:19:34 +0200 -Subject: [PATCH] SPARC/LEON: added support for AMP systems with IRQAMP IRQ Controller. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/include/asm/leon.h | 12 ++++++++++++ - arch/sparc/include/asm/leon_amba.h | 6 +++--- - arch/sparc/kernel/leon_kernel.c | 14 ++++++++++++++ - 3 files changed, 29 insertions(+), 3 deletions(-) - ---- a/arch/sparc/include/asm/leon.h -+++ b/arch/sparc/include/asm/leon.h -@@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_c - "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); - }; - -+static inline unsigned long sparc_leon3_asr17(void) -+{ -+ u32 asr17; -+ __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17)); -+ return asr17; -+}; -+ -+static inline int sparc_leon3_cpuid(void) -+{ -+ return sparc_leon3_asr17() >> 28; -+} -+ - #endif /*!__ASSEMBLY__*/ - - #ifdef CONFIG_SMP ---- a/arch/sparc/include/asm/leon_amba.h -+++ b/arch/sparc/include/asm/leon_amba.h -@@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map { - u32 mpbroadcast; - u32 notused02; - u32 notused03; -- u32 notused10; -- u32 notused11; -- u32 notused12; -+ u32 ampctrl; -+ u32 icsel[2]; - u32 notused13; - u32 notused20; - u32 notused21; -@@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map { - u32 force[16]; - /* Extended IRQ registers */ - u32 intid[16]; /* 0xc0 */ -+ u32 unused[(0x1000-0x100)/4]; - }; - - struct leon3_apbuart_regs_map { ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -108,6 +108,7 @@ void __init leon_init_timers(irq_handler - struct device_node *rootnp, *np; - struct property *pp; - int len; -+ int cpu, icsel; - - leondebug_irq_disable = 0; - leon_debug_irqout = 0; -@@ -153,6 +154,19 @@ void __init leon_init_timers(irq_handler - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); - # endif - -+ /* The IRQ controller may (if implemented) consist of multiple -+ * IRQ controllers, each mapped on a 4Kb boundary. -+ * Each CPU may be routed to different IRQCTRLs, however -+ * we assume that all CPUs (in SMP system) is routed to the -+ * same IRQ Controller, and for non-SMP only one IRQCTRL is -+ * accessed anyway. -+ * In AMP systems, Linux may not be run on CPU0. -+ */ -+ cpu = sparc_leon3_cpuid(); -+ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); -+ icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; -+ leon3_irqctrl_regs += icsel; -+ - LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); - eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf; - if ( eirq != 0 ) { diff --git a/target/linux/leon/patches/007-amp_timer.patch b/target/linux/leon/patches/007-amp_timer.patch deleted file mode 100644 index d8d436347f..0000000000 --- a/target/linux/leon/patches/007-amp_timer.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 1dffe06838c26b7c3fc99f9ddb7db78e378f6908 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 22 Sep 2010 13:21:13 +0200 -Subject: [PATCH] SPARC/LEON: added support for selecting Timer Core and Timer within core, useful for AMP systems. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/leon_kernel.c | 41 +++++++++++++++++++++++++------------- - 1 files changed, 27 insertions(+), 14 deletions(-) - ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -23,15 +23,16 @@ - #include "prom.h" - #include "irq.h" - --struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ --struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ -+struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */ -+struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */ - struct amba_apb_device leon_percpu_timer_dev[16]; - - int leondebug_irq_disable; - int leon_debug_irqout; - static int dummy_master_l10_counter; - --unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ -+unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */ -+unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */ - unsigned int sparc_leon_eirq; - #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) - -@@ -109,6 +110,7 @@ void __init leon_init_timers(irq_handler - struct property *pp; - int len; - int cpu, icsel; -+ int ampopts; - - leondebug_irq_disable = 0; - leon_debug_irqout = 0; -@@ -124,24 +126,35 @@ void __init leon_init_timers(irq_handler - } - - /* Find GPTIMER Timer Registers base address otherwise bail out. */ -- if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) { -+ np = rootnp; -+ while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) { -+ ampopts = 0; -+ pp = of_find_property(np, "ampopts", &len); -+ if ( pp && ((ampopts = *(int *)pp->value) == 0) ) { -+ /* Skip this instance, resource already allocated by other OS */ -+ continue; -+ } -+ /* Select Timer-Instance on Timer Core. Default is zero */ -+ leon3_gptimer_idx = ampopts & 0x7; -+ - pp = of_find_property(np, "reg", &len); - if (pp) - leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; - pp = of_find_property(np, "interrupts", &len); - if (pp) - leon3_gptimer_irq = *(unsigned int *)pp->value; -+ break; - } - - if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, -- (((1000000 / HZ) - 1))); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, -+ (((1000000 / 100) - 1))); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); - - #ifdef CONFIG_SMP - leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; -- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; -+ leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx; - - if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & - (1<e[1].val, 0); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1))); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); - # endif - - /* The IRQ controller may (if implemented) consist of multiple -@@ -178,7 +191,7 @@ void __init leon_init_timers(irq_handler - BUG(); - } - -- irq = request_irq(leon3_gptimer_irq, -+ irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, - counter_fn, - (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); - -@@ -210,13 +223,13 @@ void __init leon_init_timers(irq_handler - # endif - - if (leon3_gptimer_regs) { -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, - LEON3_GPTIMER_EN | - LEON3_GPTIMER_RL | - LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); - - #ifdef CONFIG_SMP -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, - LEON3_GPTIMER_EN | - LEON3_GPTIMER_RL | - LEON3_GPTIMER_LD | diff --git a/target/linux/leon/patches/008-hz_specific_timer_init.patch b/target/linux/leon/patches/008-hz_specific_timer_init.patch deleted file mode 100644 index aae3d29cdd..0000000000 --- a/target/linux/leon/patches/008-hz_specific_timer_init.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e4d697dad4d43109f045a4f25cb1d706122045c0 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 22 Sep 2010 13:24:36 +0200 -Subject: [PATCH] SPARC/LEON: removed constant timer initialization as if HZ=100, now it reflects the value of HZ - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/leon_kernel.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -149,7 +149,7 @@ void __init leon_init_timers(irq_handler - if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, -- (((1000000 / 100) - 1))); -+ (((1000000 / HZ) - 1))); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); - - #ifdef CONFIG_SMP -@@ -163,7 +163,7 @@ void __init leon_init_timers(irq_handler - } - - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1))); -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1))); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); - # endif - diff --git a/target/linux/leon/patches/009-remove_second_timer.patch b/target/linux/leon/patches/009-remove_second_timer.patch deleted file mode 100644 index b0b1346156..0000000000 --- a/target/linux/leon/patches/009-remove_second_timer.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 22 Sep 2010 15:39:05 +0200 -Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/include/asm/leon.h | 2 +- - arch/sparc/include/asm/leon_amba.h | 3 +- - arch/sparc/kernel/entry.S | 3 +- - arch/sparc/kernel/leon_kernel.c | 37 ++++++++--------------------------- - arch/sparc/kernel/leon_smp.c | 8 ++++++- - 5 files changed, 21 insertions(+), 32 deletions(-) - ---- a/arch/sparc/include/asm/leon.h -+++ b/arch/sparc/include/asm/leon.h -@@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void - - #ifdef CONFIG_SMP - # define LEON3_IRQ_RESCHEDULE 13 --# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) -+# define LEON3_IRQ_TICKER (leon3_gptimer_irq + leon3_gptimer_idx) - # define LEON3_IRQ_CROSS_CALL 15 - #endif - ---- a/arch/sparc/include/asm/leon_amba.h -+++ b/arch/sparc/include/asm/leon_amba.h -@@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp, - - extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; - extern struct leon3_gptimer_regs_map *leon3_gptimer_regs; --extern struct amba_apb_device leon_percpu_timer_dev[16]; - extern int leondebug_irq_disable; - extern int leon_debug_irqout; - extern unsigned long leon3_gptimer_irq; -+extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */ - extern unsigned int sparc_leon_eirq; -+extern unsigned long leon3_cpu_idx; - - #endif /* __ASSEMBLY__ */ - ---- a/arch/sparc/kernel/entry.S -+++ b/arch/sparc/kernel/entry.S -@@ -411,8 +411,9 @@ smpleon_ticker: - WRITE_PAUSE - wr %g2, PSR_ET, %psr - WRITE_PAUSE -+ mov %l7, %o0 ! irq level - call leon_percpu_timer_interrupt -- add %sp, STACKFRAME_SZ, %o0 -+ add %sp, STACKFRAME_SZ, %o1 ! pt_regs - wr %l0, PSR_ET, %psr - WRITE_PAUSE - RESTORE_ALL ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -25,7 +25,6 @@ - - struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */ - struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */ --struct amba_apb_device leon_percpu_timer_dev[16]; - - int leondebug_irq_disable; - int leon_debug_irqout; -@@ -34,6 +33,7 @@ static int dummy_master_l10_counter; - unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */ - unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */ - unsigned int sparc_leon_eirq; -+unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */ - #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) - - /* Return the IRQ of the pending IRQ on the extended IRQ controller */ -@@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler - struct device_node *rootnp, *np; - struct property *pp; - int len; -- int cpu, icsel; -+ int icsel; - int ampopts; - - leondebug_irq_disable = 0; - leon_debug_irqout = 0; - master_l10_counter = (unsigned int *)&dummy_master_l10_counter; - dummy_master_l10_counter = 0; -+ leon3_cpu_idx = sparc_leon3_cpuid(); - - /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ - rootnp = of_find_node_by_path("/ambapp0"); -@@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler - (((1000000 / HZ) - 1))); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); - --#ifdef CONFIG_SMP -- leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; -- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx; -- - if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & - (1<e[leon3_gptimer_idx+1].val, 0); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1))); -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); --# endif -- - /* The IRQ controller may (if implemented) consist of multiple - * IRQ controllers, each mapped on a 4Kb boundary. - * Each CPU may be routed to different IRQCTRLs, however -@@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler - * accessed anyway. - * In AMP systems, Linux may not be run on CPU0. - */ -- cpu = sparc_leon3_cpuid(); -- icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); -- icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; -+ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]); -+ icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf; - leon3_irqctrl_regs += icsel; - - LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); -@@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler - # ifdef CONFIG_SMP - { - unsigned long flags; -- struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; -+ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + -+ (leon3_gptimer_irq + leon3_gptimer_idx - 1)]; - - /* For SMP we use the level 14 ticker, however the bootup code - * has copied the firmwares level 14 vector into boot cpu's -@@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler - } - # endif - -- if (leon3_gptimer_regs) { -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, -+ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, - LEON3_GPTIMER_EN | - LEON3_GPTIMER_RL | - LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); - --#ifdef CONFIG_SMP -- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, -- LEON3_GPTIMER_EN | -- LEON3_GPTIMER_RL | -- LEON3_GPTIMER_LD | -- LEON3_GPTIMER_IRQEN); --#endif -- -- } - } - - void leon_clear_clock_irq(void) ---- a/arch/sparc/kernel/leon_smp.c -+++ b/arch/sparc/kernel/leon_smp.c -@@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin - extern unsigned char boot_cpu_id; - extern cpumask_t smp_commenced_mask; - void __init leon_configure_cache_smp(void); -+extern void handler_irq(int irq, struct pt_regs * regs); - - static inline unsigned long do_swap(volatile unsigned long *ptr, - unsigned long val) -@@ -385,7 +386,7 @@ void leon_cross_call_irq(void) - ccall_info.processors_out[i] = 1; - } - --void leon_percpu_timer_interrupt(struct pt_regs *regs) -+void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs) - { - struct pt_regs *old_regs; - int cpu = smp_processor_id(); -@@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct - prof_counter(cpu) = prof_multiplier(cpu); - } - set_irq_regs(old_regs); -+ -+ if ( cpu == leon3_cpu_idx ) { -+ /* Ticker Clock is shared with the System Clock */ -+ handler_irq(irq, regs); -+ } - } - - static void __init smp_setup_percpu_timer(void) diff --git a/target/linux/leon/patches/010-apbuart_ampopts.patch b/target/linux/leon/patches/010-apbuart_ampopts.patch deleted file mode 100644 index f47c54a7be..0000000000 --- a/target/linux/leon/patches/010-apbuart_ampopts.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 8129fa5437f3fe5f95bac180a43cd5a856cebdf3 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 20 Oct 2010 17:00:41 +0200 -Subject: [PATCH] Added support for ampopts in APBUART driver. Used in AMP systems. - -Signed-off-by: Daniel Hellstrom ---- - drivers/serial/apbuart.c | 5 ++++- - 1 files changed, 4 insertions(+), 1 deletions(-) - ---- a/drivers/serial/apbuart.c -+++ b/drivers/serial/apbuart.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -573,7 +574,6 @@ static int __devinit apbuart_probe(struc - printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n", - (unsigned long long) port->mapbase, port->irq); - return 0; -- - } - - static struct of_device_id __initdata apbuart_match[] = { -@@ -620,9 +620,12 @@ static void grlib_apbuart_configure(void - int *vendor = (int *) of_get_property(np, "vendor", NULL); - int *device = (int *) of_get_property(np, "device", NULL); - int *irqs = (int *) of_get_property(np, "interrupts", NULL); -+ int *ampopts = (int *) of_get_property(np, "ampopts", NULL); - regs = (struct amba_prom_registers *) - of_get_property(np, "reg", NULL); - -+ if (ampopts && (*ampopts == 0)) -+ continue; /* Ignore if used by another OS instance */ - if (vendor) - v = *vendor; - if (device) diff --git a/target/linux/leon/patches/011-greth_fix_unhandled_irq.patch b/target/linux/leon/patches/011-greth_fix_unhandled_irq.patch deleted file mode 100644 index 55e6185a2c..0000000000 --- a/target/linux/leon/patches/011-greth_fix_unhandled_irq.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 3d7788e8f5ae3d44e48f9b7476528acf3d9c8b32 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 20 Oct 2010 17:07:12 +0200 -Subject: [PATCH] GRETH: Fixed potential future problem where unhandled IRQ is cleared. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -584,7 +584,7 @@ static irqreturn_t greth_interrupt(int i - if (status & (GRETH_INT_RX | GRETH_INT_TX)) { - - /* Clear interrupt status */ -- GRETH_REGORIN(greth->regs->status, -+ GRETH_REGSAVE(greth->regs->status, - status & (GRETH_INT_RX | GRETH_INT_TX)); - - retval = IRQ_HANDLED; diff --git a/target/linux/leon/patches/012-greth_amba_vendor_device.patch b/target/linux/leon/patches/012-greth_amba_vendor_device.patch deleted file mode 100644 index 78b526cb8f..0000000000 --- a/target/linux/leon/patches/012-greth_amba_vendor_device.patch +++ /dev/null @@ -1,22 +0,0 @@ -From ff5f2ee8b37f2278dd86946761313c3664c51836 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Thu, 21 Oct 2010 14:34:48 +0200 -Subject: [PATCH] GRETH: added raw AMBA vendor/device number to match against. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -1600,6 +1600,9 @@ static struct of_device_id greth_of_matc - { - .name = "GAISLER_ETHMAC", - }, -+ { -+ .name = "01_01d", -+ }, - {}, - }; - diff --git a/target/linux/leon/patches/013-apbuart_amba_vendor_device.patch b/target/linux/leon/patches/013-apbuart_amba_vendor_device.patch deleted file mode 100644 index 7675f108e7..0000000000 --- a/target/linux/leon/patches/013-apbuart_amba_vendor_device.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 1c14b8995c1b8212180b5009dc04ac222a449ecb Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Thu, 21 Oct 2010 14:35:09 +0200 -Subject: [PATCH] APBUART: added raw AMBA vendor/device number to match against. - -Signed-off-by: Daniel Hellstrom ---- - drivers/serial/apbuart.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - ---- a/drivers/serial/apbuart.c -+++ b/drivers/serial/apbuart.c -@@ -580,6 +580,9 @@ static struct of_device_id __initdata ap - { - .name = "GAISLER_APBUART", - }, -+ { -+ .name = "01_00c", -+ }, - {}, - }; - diff --git a/target/linux/leon/patches/014-timer_irqctrl_amba_vendor_device.patch b/target/linux/leon/patches/014-timer_irqctrl_amba_vendor_device.patch deleted file mode 100644 index 58f7657d40..0000000000 --- a/target/linux/leon/patches/014-timer_irqctrl_amba_vendor_device.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 12782c44d0c687b5b0400a8224a9b1bf9eb9a428 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Tue, 26 Oct 2010 09:59:05 +0200 -Subject: [PATCH] TIMER,IRQCTRL: added raw AMBA vendor/device number to match against. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/kernel/leon_kernel.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) - ---- a/arch/sparc/kernel/leon_kernel.c -+++ b/arch/sparc/kernel/leon_kernel.c -@@ -120,7 +120,8 @@ void __init leon_init_timers(irq_handler - - /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ - rootnp = of_find_node_by_path("/ambapp0"); -- if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_IRQMP"))) { -+ if (rootnp && ((np=of_find_node_by_name(rootnp, "GAISLER_IRQMP")) || -+ (np=of_find_node_by_name(rootnp, "01_00d")))) { - pp = of_find_property(np, "reg", &len); - if (pp) - leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; -@@ -128,7 +129,8 @@ void __init leon_init_timers(irq_handler - - /* Find GPTIMER Timer Registers base address otherwise bail out. */ - np = rootnp; -- while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) { -+ while (np && ((np=of_find_node_by_name(np, "GAISLER_GPTIMER")) || -+ (np=of_find_node_by_name(np, "01_011")))) { - ampopts = 0; - pp = of_find_property(np, "ampopts", &len); - if ( pp && ((ampopts = *(int *)pp->value) == 0) ) { diff --git a/target/linux/leon/patches/015-dma_ops.patch b/target/linux/leon/patches/015-dma_ops.patch deleted file mode 100644 index 7f488e0221..0000000000 --- a/target/linux/leon/patches/015-dma_ops.patch +++ /dev/null @@ -1,296 +0,0 @@ -From c6d8f92cfd7f4f19eb3b16545b3b68c561978fe8 Mon Sep 17 00:00:00 2001 -From: Kristoffer Glembo -Date: Mon, 7 Jun 2010 14:00:30 +0200 -Subject: [PATCH] sparc32: Added LEON dma_ops. - -Added leon3_dma_ops and mmu_inval_dma_area. ---- - arch/sparc/kernel/ioport.c | 139 +++++++++++++++++++++++++++++++------------ - 1 files changed, 100 insertions(+), 39 deletions(-) - ---- a/arch/sparc/kernel/ioport.c -+++ b/arch/sparc/kernel/ioport.c -@@ -50,10 +50,15 @@ - #include - #include - --#ifdef CONFIG_SPARC_LEON --#define mmu_inval_dma_area(p, l) leon_flush_dcache_all() --#else -+#ifndef CONFIG_SPARC_LEON - #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ -+#else -+static inline void mmu_inval_dma_area(unsigned long va, unsigned long len) -+{ -+ if (!sparc_leon3_snooping_enabled()) { -+ leon_flush_dcache_all(); -+ } -+} - #endif - - static struct resource *_sparc_find_resource(struct resource *r, -@@ -254,7 +259,7 @@ static void *sbus_alloc_coherent(struct - dma_addr_t *dma_addrp, gfp_t gfp) - { - struct platform_device *op = to_platform_device(dev); -- unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; -+ unsigned long len_total = PAGE_ALIGN(len); - unsigned long va; - struct resource *res; - int order; -@@ -287,15 +292,19 @@ static void *sbus_alloc_coherent(struct - * XXX That's where sdev would be used. Currently we load - * all iommu tables with the same translations. - */ -- if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) -- goto err_noiommu; -- -- res->name = op->dev.of_node->name; -+#ifdef CONFIG_SPARC_LEON -+ sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); -+ *dma_addrp = virt_to_phys(va); -+#else -+ if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) { -+ release_resource(res); -+ goto err_nova; -+ } -+#endif -+ res->name = op->node->name; - - return (void *)(unsigned long)res->start; - --err_noiommu: -- release_resource(res); - err_nova: - free_pages(va, order); - err_nomem: -@@ -321,7 +330,7 @@ static void sbus_free_coherent(struct de - return; - } - -- n = (n + PAGE_SIZE-1) & PAGE_MASK; -+ n = PAGE_ALIGN(n); - if ((res->end-res->start)+1 != n) { - printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", - (long)((res->end-res->start)+1), n); -@@ -333,7 +342,12 @@ static void sbus_free_coherent(struct de - - /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ - pgv = virt_to_page(p); -- mmu_unmap_dma_area(dev, ba, n); -+ -+#ifdef CONFIG_SPARC_LEON -+ sparc_unmapiorange((unsigned long)p, n); -+#else -+ mmu_unmap_dma_area(dev, ba, n); -+#endif - - __free_pages(pgv, get_order(n)); - } -@@ -408,9 +422,6 @@ struct dma_map_ops sbus_dma_ops = { - .sync_sg_for_device = sbus_sync_sg_for_device, - }; - --struct dma_map_ops *dma_ops = &sbus_dma_ops; --EXPORT_SYMBOL(dma_ops); -- - static int __init sparc_register_ioport(void) - { - register_proc_sparc_ioport(); -@@ -422,7 +433,7 @@ arch_initcall(sparc_register_ioport); - - #endif /* CONFIG_SBUS */ - --#ifdef CONFIG_PCI -+#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON) - - /* Allocate and map kernel buffer using consistent mode DMA for a device. - * hwdev should be valid struct pci_dev pointer for PCI devices. -@@ -430,7 +441,7 @@ arch_initcall(sparc_register_ioport); - static void *pci32_alloc_coherent(struct device *dev, size_t len, - dma_addr_t *pba, gfp_t gfp) - { -- unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; -+ unsigned long len_total = PAGE_ALIGN(len); - unsigned long va; - struct resource *res; - int order; -@@ -463,10 +474,6 @@ static void *pci32_alloc_coherent(struct - return NULL; - } - mmu_inval_dma_area(va, len_total); --#if 0 --/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n", -- (long)va, (long)res->start, (long)virt_to_phys(va), len_total); --#endif - sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); - - *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ -@@ -498,7 +505,7 @@ static void pci32_free_coherent(struct d - return; - } - -- n = (n + PAGE_SIZE-1) & PAGE_MASK; -+ n = PAGE_ALIGN(n); - if ((res->end-res->start)+1 != n) { - printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", - (long)((res->end-res->start)+1), (long)n); -@@ -515,6 +522,14 @@ static void pci32_free_coherent(struct d - free_pages(pgp, get_order(n)); - } - -+static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, -+ enum dma_data_direction dir, struct dma_attrs *attrs) -+{ -+ if (dir != PCI_DMA_TODEVICE) { -+ mmu_inval_dma_area((unsigned long)phys_to_virt(ba), PAGE_ALIGN(size)); -+ } -+} -+ - /* - * Same as pci_map_single, but with pages. - */ -@@ -551,8 +566,7 @@ static int pci32_map_sg(struct device *d - - /* IIep is write-through, not flushing. */ - for_each_sg(sgl, sg, nents, n) { -- BUG_ON(page_address(sg_page(sg)) == NULL); -- sg->dma_address = virt_to_phys(sg_virt(sg)); -+ sg->dma_address = sg_phys(sg); - sg->dma_length = sg->length; - } - return nents; -@@ -571,10 +585,7 @@ static void pci32_unmap_sg(struct device - - if (dir != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { -- BUG_ON(page_address(sg_page(sg)) == NULL); -- mmu_inval_dma_area( -- (unsigned long) page_address(sg_page(sg)), -- (sg->length + PAGE_SIZE-1) & PAGE_MASK); -+ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); - } - } - } -@@ -594,7 +605,7 @@ static void pci32_sync_single_for_cpu(st - { - if (dir != PCI_DMA_TODEVICE) { - mmu_inval_dma_area((unsigned long)phys_to_virt(ba), -- (size + PAGE_SIZE-1) & PAGE_MASK); -+ PAGE_ALIGN(size)); - } - } - -@@ -621,10 +632,7 @@ static void pci32_sync_sg_for_cpu(struct - - if (dir != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { -- BUG_ON(page_address(sg_page(sg)) == NULL); -- mmu_inval_dma_area( -- (unsigned long) page_address(sg_page(sg)), -- (sg->length + PAGE_SIZE-1) & PAGE_MASK); -+ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); - } - } - } -@@ -637,18 +645,38 @@ static void pci32_sync_sg_for_device(str - - if (dir != PCI_DMA_TODEVICE) { - for_each_sg(sgl, sg, nents, n) { -- BUG_ON(page_address(sg_page(sg)) == NULL); -- mmu_inval_dma_area( -- (unsigned long) page_address(sg_page(sg)), -- (sg->length + PAGE_SIZE-1) & PAGE_MASK); -+ mmu_inval_dma_area((unsigned long)sg_virt(sg), PAGE_ALIGN(sg->length)); - } - } - } - -+/* LEON3 unmapping functions -+ * -+ * We can only invalidate the whole cache so unmap_page and unmap_sg do the same thing -+ */ -+static void leon3_unmap_page(struct device *dev, dma_addr_t ba, size_t size, -+ enum dma_data_direction dir, struct dma_attrs *attrs) -+{ -+ if (dir != PCI_DMA_TODEVICE) { -+ mmu_inval_dma_area(0, 0); -+ } -+} -+ -+static void leon3_unmap_sg(struct device *dev, struct scatterlist *sgl, -+ int nents, enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ -+ if (dir != PCI_DMA_TODEVICE) { -+ mmu_inval_dma_area(0, 0); -+ } -+} -+ - struct dma_map_ops pci32_dma_ops = { - .alloc_coherent = pci32_alloc_coherent, - .free_coherent = pci32_free_coherent, - .map_page = pci32_map_page, -+ .unmap_page = pci32_unmap_page, - .map_sg = pci32_map_sg, - .unmap_sg = pci32_unmap_sg, - .sync_single_for_cpu = pci32_sync_single_for_cpu, -@@ -658,7 +686,30 @@ struct dma_map_ops pci32_dma_ops = { - }; - EXPORT_SYMBOL(pci32_dma_ops); - --#endif /* CONFIG_PCI */ -+struct dma_map_ops leon3_dma_ops = { -+ .alloc_coherent = sbus_alloc_coherent, -+ .free_coherent = sbus_free_coherent, -+ .map_page = pci32_map_page, -+ .unmap_page = leon3_unmap_page, -+ .map_sg = pci32_map_sg, -+ .unmap_sg = leon3_unmap_sg, -+ .sync_single_for_cpu = pci32_sync_single_for_cpu, -+ .sync_single_for_device = pci32_sync_single_for_device, -+ .sync_sg_for_cpu = pci32_sync_sg_for_cpu, -+ .sync_sg_for_device = pci32_sync_sg_for_device, -+}; -+ -+#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */ -+ -+#ifdef CONFIG_SPARC_LEON -+struct dma_map_ops *dma_ops = &leon3_dma_ops; -+#else -+struct dma_map_ops *dma_ops = &sbus_dma_ops; -+#endif -+ -+#ifdef CONFIG_SBUS -+EXPORT_SYMBOL(dma_ops); -+#endif - - /* - * Return whether the given PCI device DMA address mask can be -@@ -676,6 +727,16 @@ int dma_supported(struct device *dev, u6 - } - EXPORT_SYMBOL(dma_supported); - -+int dma_set_mask(struct device *dev, u64 dma_mask) -+{ -+#ifdef CONFIG_PCI -+ if (dev->bus == &pci_bus_type) -+ return pci_set_dma_mask(to_pci_dev(dev), dma_mask); -+#endif -+ return -EOPNOTSUPP; -+} -+EXPORT_SYMBOL(dma_set_mask); -+ - #ifdef CONFIG_PROC_FS - - static int sparc_io_proc_show(struct seq_file *m, void *v) -@@ -717,7 +778,7 @@ static const struct file_operations spar - static struct resource *_sparc_find_resource(struct resource *root, - unsigned long hit) - { -- struct resource *tmp; -+ struct resource *tmp; - - for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { - if (tmp->start <= hit && tmp->end >= hit) diff --git a/target/linux/leon/patches/016-ioport_update.patch b/target/linux/leon/patches/016-ioport_update.patch deleted file mode 100644 index 130b36ed11..0000000000 --- a/target/linux/leon/patches/016-ioport_update.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 36cad96a50eb877d0c5cb3d8d93c1807ad9c774c Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 09:37:23 +0100 -Subject: [PATCH] Fix kristoffers ioport.c patch for more recent kernel. - -Signed-off-by: Daniel Hellstrom ---- - arch/sparc/include/asm/dma-mapping.h | 13 +------------ - arch/sparc/kernel/ioport.c | 3 ++- - 2 files changed, 3 insertions(+), 13 deletions(-) - ---- a/arch/sparc/include/asm/dma-mapping.h -+++ b/arch/sparc/include/asm/dma-mapping.h -@@ -51,17 +51,6 @@ static inline int dma_mapping_error(stru - return (dma_addr == DMA_ERROR_CODE); - } - --static inline int dma_set_mask(struct device *dev, u64 mask) --{ --#ifdef CONFIG_PCI -- if (dev->bus == &pci_bus_type) { -- if (!dev->dma_mask || !dma_supported(dev, mask)) -- return -EINVAL; -- *dev->dma_mask = mask; -- return 0; -- } --#endif -- return -EINVAL; --} -+extern int dma_set_mask(struct device *dev, u64 dma_mask); - - #endif ---- a/arch/sparc/kernel/ioport.c -+++ b/arch/sparc/kernel/ioport.c -@@ -301,7 +301,7 @@ static void *sbus_alloc_coherent(struct - goto err_nova; - } - #endif -- res->name = op->node->name; -+ res->name = op->dev.of_node->name; - - return (void *)(unsigned long)res->start; - -@@ -737,6 +737,7 @@ int dma_set_mask(struct device *dev, u64 - } - EXPORT_SYMBOL(dma_set_mask); - -+ - #ifdef CONFIG_PROC_FS - - static int sparc_io_proc_show(struct seq_file *m, void *v) diff --git a/target/linux/leon/patches/017-greth_no_gbit.patch b/target/linux/leon/patches/017-greth_no_gbit.patch deleted file mode 100644 index 5e3ee3d6a0..0000000000 --- a/target/linux/leon/patches/017-greth_no_gbit.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 2e864d18c31d4e0255269f9e9cfccc09512676c6 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 16:51:38 +0100 -Subject: [PATCH] GRETH: added greth_no_gbit option - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 15 +++++++++++++-- - drivers/net/greth.h | 1 + - 2 files changed, 14 insertions(+), 2 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -66,6 +66,10 @@ static int greth_edcl = 1; - module_param(greth_edcl, int, 0); - MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used."); - -+static int no_gbit = 0; -+module_param(no_gbit, int, S_IRUGO); -+MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off)."); -+ - static int greth_open(struct net_device *dev); - static netdev_tx_t greth_start_xmit(struct sk_buff *skb, - struct net_device *dev); -@@ -1284,7 +1288,7 @@ static int greth_mdio_probe(struct net_d - } - - ret = phy_connect_direct(dev, phy, &greth_link_change, -- 0, greth->gbit_mac ? -+ 0, greth->gbit_phy_support ? - PHY_INTERFACE_MODE_GMII : - PHY_INTERFACE_MODE_MII); - if (ret) { -@@ -1293,7 +1297,7 @@ static int greth_mdio_probe(struct net_d - return ret; - } - -- if (greth->gbit_mac) -+ if (greth->gbit_phy_support) - phy->supported &= PHY_GBIT_FEATURES; - else - phy->supported &= PHY_BASIC_FEATURES; -@@ -1441,6 +1445,13 @@ static int __devinit greth_of_probe(stru - tmp = GRETH_REGLOAD(regs->control); - greth->gbit_mac = (tmp >> 27) & 1; - -+ /* Let user skip GBit link mode by telling MDIO layer that MAC does -+ * not support GBIT (for debug) */ -+ if (greth->gbit_mac && !no_gbit) -+ greth->gbit_phy_support = 1; -+ else -+ greth->gbit_phy_support = 0; -+ - /* Check for multicast capability */ - greth->multicast = (tmp >> 25) & 1; - ---- a/drivers/net/greth.h -+++ b/drivers/net/greth.h -@@ -138,6 +138,7 @@ struct greth_private { - u8 gbit_mac; - u8 mdio_int_en; - u8 edcl; -+ u8 gbit_phy_support; - }; - - #endif diff --git a/target/linux/leon/patches/018-greth_compat_mode.patch b/target/linux/leon/patches/018-greth_compat_mode.patch deleted file mode 100644 index 4afe89eb07..0000000000 --- a/target/linux/leon/patches/018-greth_compat_mode.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a498d7076ee0f82ec3f508293a9cf1ccba15829e Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 16:52:19 +0100 -Subject: [PATCH] GRETH: added greth_compat_mode module parameter - -The greth_compat_mode option can be used to set a GRETH GBit capable MAC -in operate as if the GRETH 10/100 device was found. The GRETH GBit supports -TCP/UDP checksum offloading, unaligned frame buffers, scatter gather etc. -Enabling this mode allows the developer to test the GRETH 10/100 device -without all features mentioned above on a GBit MAC capable of the above. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 9 +++++++++ - 1 files changed, 9 insertions(+), 0 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -70,6 +70,11 @@ static int no_gbit = 0; - module_param(no_gbit, int, S_IRUGO); - MODULE_PARM_DESC(no_gbit, "GRETH report GBit not supported by MAC enable. Only affects GRETH GBit MAC, default 0 (off)."); - -+/* Use this option to enable GRETH 10/100 code on GRETH_GBIT hardware (debug legacy code option) */ -+static int compat_mode = 0; -+module_param(compat_mode, int, S_IRUGO); -+MODULE_PARM_DESC(compat_mode, "GRETH 10/100 legacy mode enable. Only affects GRETH GBit MAC, default 0 (off)."); -+ - static int greth_open(struct net_device *dev); - static netdev_tx_t greth_start_xmit(struct sk_buff *skb, - struct net_device *dev); -@@ -1452,6 +1457,10 @@ static int __devinit greth_of_probe(stru - else - greth->gbit_phy_support = 0; - -+ /* Force GBit MAC in legacy 10/100 mode (no offloading etc.) */ -+ if (compat_mode == 1) -+ greth->gbit_mac = 0; -+ - /* Check for multicast capability */ - greth->multicast = (tmp >> 25) & 1; - diff --git a/target/linux/leon/patches/019-greth_fix_open_close.patch b/target/linux/leon/patches/019-greth_fix_open_close.patch deleted file mode 100644 index fffb39133a..0000000000 --- a/target/linux/leon/patches/019-greth_fix_open_close.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 6216bc809c5bdd586b14d096fbaf6dc25574b928 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 09:59:14 +0100 -Subject: [PATCH] GRETH: fix opening/closing - -When NAPI is disabled there is no point in having IRQs enabled, TX/RX -should be off before clearing the TX/RX descriptor rings. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -365,6 +365,8 @@ static int greth_open(struct net_device - dev_dbg(&dev->dev, " starting queue\n"); - netif_start_queue(dev); - -+ GRETH_REGSAVE(greth->regs->status, 0xFF); -+ - napi_enable(&greth->napi); - - greth_enable_irqs(greth); -@@ -380,7 +382,9 @@ static int greth_close(struct net_device - - napi_disable(&greth->napi); - -+ greth_disable_irqs(greth); - greth_disable_tx(greth); -+ greth_disable_rx(greth); - - netif_stop_queue(dev); - diff --git a/target/linux/leon/patches/020-greth_optimize_gbit_tx_descriptor_handling.patch b/target/linux/leon/patches/020-greth_optimize_gbit_tx_descriptor_handling.patch deleted file mode 100644 index 3a14eb76d9..0000000000 --- a/target/linux/leon/patches/020-greth_optimize_gbit_tx_descriptor_handling.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 544631281bed5cc37b8f2d3a99f44c9d4b97f9a8 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 10:07:12 +0100 -Subject: [PATCH] GRETH: GBit transmit descriptor handling optimization - -It is safe to enable all fragments before enabling the first descriptor, -this way all descriptors don't have to be processed twice, added extra -memory barrier. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 19 ++++++++++--------- - 1 files changed, 10 insertions(+), 9 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -512,7 +512,7 @@ greth_start_xmit_gbit(struct sk_buff *sk - greth->tx_skbuff[curr_tx] = NULL; - bdp = greth->tx_bd_base + curr_tx; - -- status = GRETH_TXBD_CSALL; -+ status = GRETH_TXBD_CSALL | GRETH_BD_EN; - status |= frag->size & GRETH_BD_LEN; - - /* Wrap around descriptor ring */ -@@ -549,26 +549,27 @@ greth_start_xmit_gbit(struct sk_buff *sk - - wmb(); - -- /* Enable the descriptors that we configured ... */ -- for (i = 0; i < nr_frags + 1; i++) { -- bdp = greth->tx_bd_base + greth->tx_next; -- greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); -- greth->tx_next = NEXT_TX(greth->tx_next); -- greth->tx_free--; -- } -+ /* Enable the descriptor chain by enabling the first descriptor */ -+ bdp = greth->tx_bd_base + greth->tx_next; -+ greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); -+ greth->tx_next = curr_tx; -+ greth->tx_free -= nr_frags + 1; -+ -+ wmb(); - - greth_enable_tx(greth); - - return NETDEV_TX_OK; - - frag_map_error: -- /* Unmap SKB mappings that succeeded */ -+ /* Unmap SKB mappings that succeeded and disable descriptor */ - for (i = 0; greth->tx_next + i != curr_tx; i++) { - bdp = greth->tx_bd_base + greth->tx_next + i; - dma_unmap_single(greth->dev, - greth_read_bd(&bdp->addr), - greth_read_bd(&bdp->stat) & GRETH_BD_LEN, - DMA_TO_DEVICE); -+ greth_write_bd(&bdp->stat, 0); - } - map_error: - if (net_ratelimit()) diff --git a/target/linux/leon/patches/021-greth_fix_memory_leak.patch b/target/linux/leon/patches/021-greth_fix_memory_leak.patch deleted file mode 100644 index 1d05af1247..0000000000 --- a/target/linux/leon/patches/021-greth_fix_memory_leak.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 54789a03adf9c924d0cf7b890323c9c1ca7ab042 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 10:26:09 +0100 -Subject: [PATCH] GRETH: fixed skb buffer memory leak on frame errors - -A new SKB buffer should not be allocated when the old SKB is reused. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 17 +++++++++++------ - 1 files changed, 11 insertions(+), 6 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -879,10 +879,8 @@ static int greth_rx_gbit(struct net_devi - } - } - -- /* Allocate new skb to replace current */ -- newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN); -- -- if (!bad && newskb) { -+ /* Allocate new skb to replace current, not needed if the current skb can be reused */ -+ if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) { - skb_reserve(newskb, NET_IP_ALIGN); - - dma_addr = dma_map_single(greth->dev, -@@ -919,12 +917,19 @@ static int greth_rx_gbit(struct net_devi - if (net_ratelimit()) - dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n"); - dev_kfree_skb(newskb); -- dev->stats.rx_dropped++; -+ dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */ - } -+ } else if ( bad ) { -+ /* Bad Frame transfer, the skb is reused */ -+ dev->stats.rx_dropped++; - } else { -+ /* Failed Allocating a new skb. This is rather stupid but the current "filled" -+ * skb is reused, as if transfer failure. One could argue that RX descriptor table -+ * handling should be divided into cleaning and filling as the TX part of the driver -+ */ - if (net_ratelimit()) - dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n"); -- dev->stats.rx_dropped++; -+ dev->stats.rx_dropped++; /* reusing current skb, so it is a drop */ - } - - status = GRETH_BD_EN | GRETH_BD_IE; diff --git a/target/linux/leon/patches/022-greth_avoid_bad_speed_duplex.patch b/target/linux/leon/patches/022-greth_avoid_bad_speed_duplex.patch deleted file mode 100644 index e8253640dc..0000000000 --- a/target/linux/leon/patches/022-greth_avoid_bad_speed_duplex.patch +++ /dev/null @@ -1,50 +0,0 @@ -From c2e963057ca5635d6e5387623c3ad0c0b3123754 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 10:28:37 +0100 -Subject: [PATCH] GRETH: avoid writing bad speed/duplex when setting transfer mode - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 19 ++++++++----------- - 1 files changed, 8 insertions(+), 11 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -1236,29 +1236,26 @@ static void greth_link_change(struct net - struct greth_private *greth = netdev_priv(dev); - struct phy_device *phydev = greth->phy; - unsigned long flags; -- - int status_change = 0; -+ u32 ctrl; - - spin_lock_irqsave(&greth->devlock, flags); - - if (phydev->link) { - - if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) { -- -- GRETH_REGANDIN(greth->regs->control, -- ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB)); -+ ctrl = GRETH_REGLOAD(greth->regs->control) & -+ ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB); - - if (phydev->duplex) -- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD); -- -- if (phydev->speed == SPEED_100) { -- -- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP); -- } -+ ctrl |= GRETH_CTRL_FD; - -+ if (phydev->speed == SPEED_100) -+ ctrl |= GRETH_CTRL_SP; - else if (phydev->speed == SPEED_1000) -- GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB); -+ ctrl |= GRETH_CTRL_GB; - -+ GRETH_REGSAVE(greth->regs->control, ctrl); - greth->speed = phydev->speed; - greth->duplex = phydev->duplex; - status_change = 1; diff --git a/target/linux/leon/patches/023-greth_handle_frame_error_interrupts.patch b/target/linux/leon/patches/023-greth_handle_frame_error_interrupts.patch deleted file mode 100644 index 12bfb1c01f..0000000000 --- a/target/linux/leon/patches/023-greth_handle_frame_error_interrupts.patch +++ /dev/null @@ -1,49 +0,0 @@ -From f62c047af910c9c9696db7b47472a3728b8100e8 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 11:56:22 +0100 -Subject: [PATCH] GRETH: handle frame error interrupts - -Not handling frame error interrupts are unlikly but may lead to dead -lock if 128 error frames are recieved in a row. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 5 +++-- - drivers/net/greth.h | 2 ++ - 2 files changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -595,11 +595,12 @@ static irqreturn_t greth_interrupt(int i - status = GRETH_REGLOAD(greth->regs->status); - - /* Handle rx and tx interrupts through poll */ -- if (status & (GRETH_INT_RX | GRETH_INT_TX)) { -+ if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) { - - /* Clear interrupt status */ - GRETH_REGSAVE(greth->regs->status, -- status & (GRETH_INT_RX | GRETH_INT_TX)); -+ status & (GRETH_INT_RE | GRETH_INT_RX | -+ GRETH_INT_TE | GRETH_INT_TX)); - - retval = IRQ_HANDLED; - ---- a/drivers/net/greth.h -+++ b/drivers/net/greth.h -@@ -23,6 +23,7 @@ - #define GRETH_BD_LEN 0x7FF - - #define GRETH_TXEN 0x1 -+#define GRETH_INT_TE 0x2 - #define GRETH_INT_TX 0x8 - #define GRETH_TXI 0x4 - #define GRETH_TXBD_STATUS 0x0001C000 -@@ -35,6 +36,7 @@ - #define GRETH_TXBD_ERR_UE 0x4000 - #define GRETH_TXBD_ERR_AL 0x8000 - -+#define GRETH_INT_RE 0x1 - #define GRETH_INT_RX 0x4 - #define GRETH_RXEN 0x2 - #define GRETH_RXI 0x8 diff --git a/target/linux/leon/patches/024-greth_resolve_smp_and_other_issues.patch b/target/linux/leon/patches/024-greth_resolve_smp_and_other_issues.patch deleted file mode 100644 index c2293cae04..0000000000 --- a/target/linux/leon/patches/024-greth_resolve_smp_and_other_issues.patch +++ /dev/null @@ -1,399 +0,0 @@ -From 4439d933884ee3c7e320b8d33bd2e268dd5b6fa5 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 11:40:19 +0100 -Subject: [PATCH] GRETH: resolve SMP issues and other problems - -Fixes the following: -1. POLL should not enable IRQ when work is not completed -2. No locking between TX descriptor cleaning and XMIT descriptor handling -3. No locking between RX POLL and XMIT modifying control register -4. Since TX cleaning (called from POLL) is running in parallel with XMIT - unnecessary locking is needed. -5. IRQ handler looks at RX frame status solely, this is wrong when IRQ is - temporarily disabled (in POLL), and when IRQ is shared. -6. IRQ handler clears IRQ status, which is unnecessary -7. TX queue was stopped in preventing cause when not MAX_SKB_FRAGS+1 descriptors - were available after a SKB been scheduled by XMIT. Instead the TX queue is - stopped first when not enough descriptors are available upon entering XMIT. - -It was hard to split up this patch in smaller pieces since all are tied -together somehow. - -Note the RX flag used in the interrupt handler does not signal that interrtupt -was asserted, but that a frame was received. Same goes for TX. Also, IRQ is not -asserted when the RX flag is set before enabling IRQ enable until a new frame is -received. So extra care must be taken to avoid enabling IRQ and all descriptors -are already used, hence dead lock will upon us. See new POLL implementation that -enableds IRQ then look at the RX flag to determine if one or more IRQs may have -been missed. TX/RX flags are cleared before handling previously enabled -descriptors, this ensures that the RX/TX flags are valid when determining if IRQ -should be turned on again. - -By moving TX cleaning from POLL to XMIT in the standard case, removes some -locking trouble. Enabling TX cleaning from poll only when not enough TX -descriptors are available is safe because the TX queue is at the same time -stopped, thus XMIT will not be called. The TX queue is woken up again when -enough descriptrs are available. - -TX Frames are always enabled with IRQ, however the TX IRQ Enable flag will not -be enabled until XMIT must wait for free descriptors. - -Locking RX and XMIT parts of the driver from each other is needed because the -RX/TX enable bits share the same register. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 158 ++++++++++++++++++++++++++++++--------------------- - 1 files changed, 93 insertions(+), 65 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -1,7 +1,7 @@ - /* - * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC. - * -- * 2005-2009 (c) Aeroflex Gaisler AB -+ * 2005-2010 (c) Aeroflex Gaisler AB - * - * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs - * available in the GRLIB VHDL IP core library. -@@ -401,12 +401,20 @@ greth_start_xmit(struct sk_buff *skb, st - struct greth_private *greth = netdev_priv(dev); - struct greth_bd *bdp; - int err = NETDEV_TX_OK; -- u32 status, dma_addr; -+ u32 status, dma_addr, ctrl; -+ unsigned long flags; - -- bdp = greth->tx_bd_base + greth->tx_next; -+ /* Clean TX Ring */ -+ greth_clean_tx(greth->netdev); - - if (unlikely(greth->tx_free <= 0)) { -+ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ -+ ctrl = GRETH_REGLOAD(greth->regs->control); -+ /* Enable TX IRQ only if not already in poll() routine */ -+ if ( ctrl & GRETH_RXI ) -+ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); - netif_stop_queue(dev); -+ spin_unlock_irqrestore(&greth->devlock, flags); - return NETDEV_TX_BUSY; - } - -@@ -419,13 +427,14 @@ greth_start_xmit(struct sk_buff *skb, st - goto out; - } - -+ bdp = greth->tx_bd_base + greth->tx_next; - dma_addr = greth_read_bd(&bdp->addr); - - memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); - - dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); - -- status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN); -+ status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN); - - /* Wrap around descriptor ring */ - if (greth->tx_next == GRETH_TXBD_NUM_MASK) { -@@ -435,22 +444,11 @@ greth_start_xmit(struct sk_buff *skb, st - greth->tx_next = NEXT_TX(greth->tx_next); - greth->tx_free--; - -- /* No more descriptors */ -- if (unlikely(greth->tx_free == 0)) { -- -- /* Free transmitted descriptors */ -- greth_clean_tx(dev); -- -- /* If nothing was cleaned, stop queue & wait for irq */ -- if (unlikely(greth->tx_free == 0)) { -- status |= GRETH_BD_IE; -- netif_stop_queue(dev); -- } -- } -- - /* Write descriptor control word and enable transmission */ - greth_write_bd(&bdp->stat, status); -+ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ - greth_enable_tx(greth); -+ spin_unlock_irqrestore(&greth->devlock, flags); - - out: - dev_kfree_skb(skb); -@@ -463,13 +461,24 @@ greth_start_xmit_gbit(struct sk_buff *sk - { - struct greth_private *greth = netdev_priv(dev); - struct greth_bd *bdp; -- u32 status = 0, dma_addr; -+ u32 status = 0, dma_addr, ctrl; - int curr_tx, nr_frags, i, err = NETDEV_TX_OK; -+ unsigned long flags; - - nr_frags = skb_shinfo(skb)->nr_frags; - -+ /* Clean TX Ring */ -+ greth_clean_tx_gbit(dev); -+ - if (greth->tx_free < nr_frags + 1) { -+ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ -+ ctrl = GRETH_REGLOAD(greth->regs->control); -+ /* Enable TX IRQ only if not already in poll() routine */ -+ if ( ctrl & GRETH_RXI ) { -+ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI); -+ } - netif_stop_queue(dev); -+ spin_unlock_irqrestore(&greth->devlock, flags); - err = NETDEV_TX_BUSY; - goto out; - } -@@ -522,14 +531,8 @@ greth_start_xmit_gbit(struct sk_buff *sk - /* More fragments left */ - if (i < nr_frags - 1) - status |= GRETH_TXBD_MORE; -- -- /* ... last fragment, check if out of descriptors */ -- else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) { -- -- /* Enable interrupts and stop queue */ -- status |= GRETH_BD_IE; -- netif_stop_queue(dev); -- } -+ else -+ status |= GRETH_BD_IE; /* enable IRQ on last fragment */ - - greth_write_bd(&bdp->stat, status); - -@@ -557,7 +560,9 @@ greth_start_xmit_gbit(struct sk_buff *sk - - wmb(); - -+ spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ - greth_enable_tx(greth); -+ spin_unlock_irqrestore(&greth->devlock, flags); - - return NETDEV_TX_OK; - -@@ -579,12 +584,11 @@ out: - return err; - } - -- - static irqreturn_t greth_interrupt(int irq, void *dev_id) - { - struct net_device *dev = dev_id; - struct greth_private *greth; -- u32 status; -+ u32 status, ctrl; - irqreturn_t retval = IRQ_NONE; - - greth = netdev_priv(dev); -@@ -594,13 +598,14 @@ static irqreturn_t greth_interrupt(int i - /* Get the interrupt events that caused us to be here. */ - status = GRETH_REGLOAD(greth->regs->status); - -- /* Handle rx and tx interrupts through poll */ -- if (status & (GRETH_INT_RE | GRETH_INT_RX | GRETH_INT_TE | GRETH_INT_TX)) { -+ /* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be set regardless -+ * of whether IRQ is enabled or not. Especially important when shared IRQ. -+ */ -+ ctrl = GRETH_REGLOAD(greth->regs->control); - -- /* Clear interrupt status */ -- GRETH_REGSAVE(greth->regs->status, -- status & (GRETH_INT_RE | GRETH_INT_RX | -- GRETH_INT_TE | GRETH_INT_TX)); -+ /* Handle rx and tx interrupts through poll */ -+ if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) || -+ ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) { - - retval = IRQ_HANDLED; - -@@ -625,6 +630,8 @@ static void greth_clean_tx(struct net_de - - while (1) { - bdp = greth->tx_bd_base + greth->tx_last; -+ GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); -+ mb(); - stat = greth_read_bd(&bdp->stat); - - if (unlikely(stat & GRETH_BD_EN)) -@@ -685,7 +692,10 @@ static void greth_clean_tx_gbit(struct n - - /* We only clean fully completed SKBs */ - bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags); -- stat = bdp_last_frag->stat; -+ -+ GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); -+ mb(); -+ stat = greth_read_bd(&bdp_last_frag->stat); - - if (stat & GRETH_BD_EN) - break; -@@ -717,23 +727,12 @@ static void greth_clean_tx_gbit(struct n - greth->tx_free += nr_frags+1; - dev_kfree_skb(skb); - } -- if (greth->tx_free > (MAX_SKB_FRAGS + 1)) { -+ -+ if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS + 1))) { - netif_wake_queue(dev); - } - } - --static int greth_pending_packets(struct greth_private *greth) --{ -- struct greth_bd *bdp; -- u32 status; -- bdp = greth->rx_bd_base + greth->rx_cur; -- status = greth_read_bd(&bdp->stat); -- if (status & GRETH_BD_EN) -- return 0; -- else -- return 1; --} -- - static int greth_rx(struct net_device *dev, int limit) - { - struct greth_private *greth; -@@ -742,20 +741,24 @@ static int greth_rx(struct net_device *d - int pkt_len; - int bad, count; - u32 status, dma_addr; -+ unsigned long flags; - - greth = netdev_priv(dev); - - for (count = 0; count < limit; ++count) { - - bdp = greth->rx_bd_base + greth->rx_cur; -+ GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); -+ mb(); - status = greth_read_bd(&bdp->stat); -- dma_addr = greth_read_bd(&bdp->addr); -- bad = 0; - - if (unlikely(status & GRETH_BD_EN)) { - break; - } - -+ dma_addr = greth_read_bd(&bdp->addr); -+ bad = 0; -+ - /* Check status for errors. */ - if (unlikely(status & GRETH_RXBD_STATUS)) { - if (status & GRETH_RXBD_ERR_FT) { -@@ -817,7 +820,9 @@ static int greth_rx(struct net_device *d - - dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE); - -+ spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */ - greth_enable_rx(greth); -+ spin_unlock_irqrestore(&greth->devlock, flags); - - greth->rx_cur = NEXT_RX(greth->rx_cur); - } -@@ -851,6 +856,7 @@ static int greth_rx_gbit(struct net_devi - int pkt_len; - int bad, count = 0; - u32 status, dma_addr; -+ unsigned long flags; - - greth = netdev_priv(dev); - -@@ -858,6 +864,8 @@ static int greth_rx_gbit(struct net_devi - - bdp = greth->rx_bd_base + greth->rx_cur; - skb = greth->rx_skbuff[greth->rx_cur]; -+ GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX); -+ mb(); - status = greth_read_bd(&bdp->stat); - bad = 0; - -@@ -940,7 +948,9 @@ static int greth_rx_gbit(struct net_devi - - wmb(); - greth_write_bd(&bdp->stat, status); -+ spin_lock_irqsave(&greth->devlock, flags); - greth_enable_rx(greth); -+ spin_unlock_irqrestore(&greth->devlock, flags); - greth->rx_cur = NEXT_RX(greth->rx_cur); - } - -@@ -952,15 +962,19 @@ static int greth_poll(struct napi_struct - { - struct greth_private *greth; - int work_done = 0; -+ unsigned long flags; -+ u32 mask, ctrl; - greth = container_of(napi, struct greth_private, napi); - -- if (greth->gbit_mac) { -- greth_clean_tx_gbit(greth->netdev); -- } else { -- greth_clean_tx(greth->netdev); -+restart_txrx_poll: -+ if ( netif_queue_stopped(greth->netdev) ) { -+ if (greth->gbit_mac) { -+ greth_clean_tx_gbit(greth->netdev); -+ } else { -+ greth_clean_tx(greth->netdev); -+ } - } - --restart_poll: - if (greth->gbit_mac) { - work_done += greth_rx_gbit(greth->netdev, budget - work_done); - } else { -@@ -969,15 +983,29 @@ restart_poll: - - if (work_done < budget) { - -- napi_complete(napi); -+ spin_lock_irqsave(&greth->devlock, flags); - -- if (greth_pending_packets(greth)) { -- napi_reschedule(napi); -- goto restart_poll; -+ ctrl = GRETH_REGLOAD(greth->regs->control); -+ if (netif_queue_stopped(greth->netdev)) { -+ GRETH_REGSAVE(greth->regs->control, -+ ctrl | GRETH_TXI | GRETH_RXI); -+ mask = GRETH_INT_RX | GRETH_INT_RE | -+ GRETH_INT_TX | GRETH_INT_TE; -+ } else { -+ GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI); -+ mask = GRETH_INT_RX | GRETH_INT_RE; -+ } -+ -+ if (GRETH_REGLOAD(greth->regs->status) & mask) { -+ GRETH_REGSAVE(greth->regs->control, ctrl); -+ spin_unlock_irqrestore(&greth->devlock, flags); -+ goto restart_txrx_poll; -+ } else { -+ __napi_complete(napi); -+ spin_unlock_irqrestore(&greth->devlock, flags); - } - } - -- greth_enable_irqs(greth); - return work_done; - } - -@@ -1172,11 +1200,11 @@ static const struct ethtool_ops greth_et - }; - - static struct net_device_ops greth_netdev_ops = { -- .ndo_open = greth_open, -- .ndo_stop = greth_close, -- .ndo_start_xmit = greth_start_xmit, -- .ndo_set_mac_address = greth_set_mac_add, -- .ndo_validate_addr = eth_validate_addr, -+ .ndo_open = greth_open, -+ .ndo_stop = greth_close, -+ .ndo_start_xmit = greth_start_xmit, -+ .ndo_set_mac_address = greth_set_mac_add, -+ .ndo_validate_addr = eth_validate_addr, - }; - - static inline int wait_for_mdio(struct greth_private *greth) diff --git a/target/linux/leon/patches/025-greth_bootloader_disable_device_node.patch b/target/linux/leon/patches/025-greth_bootloader_disable_device_node.patch deleted file mode 100644 index 836bab1fa4..0000000000 --- a/target/linux/leon/patches/025-greth_bootloader_disable_device_node.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 66d5b37cc6d32291419bf99161e83e2946ea5f25 Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 12:11:03 +0100 -Subject: [PATCH] GRETH: added option to disable a device node from bootloader. - -Signed-off-by: Daniel Hellstrom ---- - drivers/net/greth.c | 6 ++++++ - 1 files changed, 6 insertions(+), 0 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -1428,6 +1428,12 @@ static int __devinit greth_of_probe(stru - int err; - int tmp; - unsigned long timeout; -+ int *ampopts; -+ -+ /* Skip device if used by another OS instance */ -+ ampopts = (int *) of_get_property(ofdev->dev.of_node, "ampopts", NULL); -+ if (ampopts && (*ampopts == 0)) -+ return -EIO; - - dev = alloc_etherdev(sizeof(struct greth_private)); - diff --git a/target/linux/leon/patches/026-greth_gbit_mac_set_ee_when_edcl.patch b/target/linux/leon/patches/026-greth_gbit_mac_set_ee_when_edcl.patch deleted file mode 100644 index 94fa0bd344..0000000000 --- a/target/linux/leon/patches/026-greth_gbit_mac_set_ee_when_edcl.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 50fcb51c42bc721f18f1bfa10f705519cd344a2a Mon Sep 17 00:00:00 2001 -From: Daniel Hellstrom -Date: Wed, 1 Dec 2010 16:20:01 +0100 -Subject: [PATCH] GRETH: Newer GBit MACs need setting EE bit when EDCL should be enabled - ---- - drivers/net/greth.c | 2 +- - drivers/net/greth.h | 1 + - 2 files changed, 2 insertions(+), 1 deletions(-) - ---- a/drivers/net/greth.c -+++ b/drivers/net/greth.c -@@ -1511,7 +1511,7 @@ static int __devinit greth_of_probe(stru - /* If we have EDCL we disable the EDCL speed-duplex FSM so - * it doesn't interfere with the software */ - if (greth->edcl != 0) -- GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX); -+ GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX|GRETH_CTRL_EE); - - /* Check if MAC can handle MDIO interrupts */ - greth->mdio_int_en = (tmp >> 26) & 1; ---- a/drivers/net/greth.h -+++ b/drivers/net/greth.h -@@ -15,6 +15,7 @@ - #define GRETH_CTRL_PSTATIEN 0x400 - #define GRETH_CTRL_MCEN 0x800 - #define GRETH_CTRL_DISDUPLEX 0x1000 -+#define GRETH_CTRL_EE 0x4000 - #define GRETH_STATUS_PHYSTAT 0x100 - - #define GRETH_BD_EN 0x800 diff --git a/target/linux/leon/patches/027-sparc_v8_assembler.patch b/target/linux/leon/patches/027-sparc_v8_assembler.patch deleted file mode 100644 index 5baea94f74..0000000000 --- a/target/linux/leon/patches/027-sparc_v8_assembler.patch +++ /dev/null @@ -1,31 +0,0 @@ -[PATCH] sparc32: Add -Av8 to assembler command line. - -Newer version of binutils are more strict about specifying the -correct options to enable certain classes of instructions. - -The sparc32 build is done for v7 in order to support sun4c systems -which lack hardware integer multiply and divide instructions. - -So we have to pass -Av8 when building the assembler routines that -use these instructions and get patched into the kernel when we find -out that we have a v8 capable cpu. - -Reported-by: Paul Gortmaker -Signed-off-by: David S. Miller ---- - arch/sparc/Makefile | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile -index ad1fb5d..eddcfb3 100644 ---- a/arch/sparc/Makefile -+++ b/arch/sparc/Makefile -@@ -31,7 +31,7 @@ UTS_MACHINE := sparc - - #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7 - KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 --KBUILD_AFLAGS += -m32 -+KBUILD_AFLAGS += -m32 -Wa,-Av8 - - #LDFLAGS_vmlinux = -N -Ttext 0xf0004000 - # Since 2.5.40, the first stage is left not btfix-ed.