While Daniel González and me were fighting with jffs2 tested some code extracted from Netgear. Here are what we found. We only tested brcm_wait, broadcom checksum code and the modification in tlbex.c and nothing strange happened when we flashed it. Hope this could help for the Broadcom SoCs and maybe others.
diff -urN b/include/asm-mips/checksum.h a/include/asm-mips/checksum.h --- b/include/asm-mips/checksum.h 2007-06-12 16:13:11.000000000 +0200 +++ a/include/asm-mips/checksum.h 2010-05-31 03:43:32.000000000 +0200 @@ -98,6 +98,64 @@ * By Jorge Cwik <jo...@laser.satlink.net>, adapted for linux by * Arnt Gulbrandsen. */ + +#if defined(CONFIG_MIPS_BRCM) + +/* Brcm version can handle unaligned data. Merged from brcm 2.6.8 kernel.*/ +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + if (((__u32)iph&0x3) == 0) { + unsigned int *word = (unsigned int *) iph; + unsigned int *stop = word + ihl; + unsigned int csum; + int carry; + + csum = word[0]; + csum += word[1]; + carry = (csum < word[1]); + csum += carry; + + csum += word[2]; + carry = (csum < word[2]); + csum += carry; + + csum += word[3]; + carry = (csum < word[3]); + csum += carry; + + word += 4; + do { + csum += *word; + carry = (csum < *word); + csum += carry; + word++; + } while (word != stop); + + return csum_fold(csum); + } else { + __u16 * buff = (__u16 *) iph; + __u32 sum=0; + __u16 i; + + // make 16 bit words out of every two adjacent 8 bit words in the packet + // and add them up + for (i=0;i<ihl*2;i++){ + sum = sum + (__u32) buff[i]; + } + + // take only 16 bits out of the 32 bit sum and add up the carries + while (sum>>16) + sum = (sum & 0xFFFF)+(sum >> 16); + + // one's complement the result + sum = ~sum; + + return ((__sum16) sum); + } +} + +#else + static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) { const unsigned int *word = iph; @@ -129,6 +187,8 @@ return csum_fold(csum); } +#endif + static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) ------------------------------------------------------------------------------------------------------------------ diff -urN b/drivers/mtd/mtd_blkdevs.c a/drivers/mtd/mtd_blkdevs.c --- b/drivers/mtd/mtd_blkdevs.c 2007-06-12 16:13:11.000000000 +0200 +++ a/drivers/mtd/mtd_blkdevs.c 2010-05-31 03:52:56.000000000 +0200 @@ -21,6 +21,9 @@ #include <linux/init.h> #include <linux/mutex.h> #include <asm/uaccess.h> +#if defined(CONFIG_MIPS_BRCM) +#include <linux/syscalls.h> +#endif static LIST_HEAD(blktrans_majors); @@ -80,13 +83,23 @@ struct mtd_blktrans_ops *tr = arg; struct request_queue *rq = tr->blkcore_priv->rq; +#if defined(CONFIG_MIPS_BRCM) +#if defined (CONFIG_PREEMPT_SOFTIRQS) + /* mtdblockd needs to run at the same priority as ksoftirqd threads so loading of applications from flash won't get blocked by network traffic. + One bad thing about blocking application loading is that voice applications can be blocked by network traffic, despite that they have higher + priority than network tasks. This would be a priority inversion scenario if happens. */ + struct sched_param param = { .sched_priority = CONFIG_BRCM_SOFTIRQ_BASE_RT_PRIO }; + sched_setscheduler(current, SCHED_RR, ¶m); +#endif +#endif + /* we might get involved when memory gets low, so use PF_MEMALLOC */ current->flags |= PF_MEMALLOC | PF_NOFREEZE; daemonize("%sd", tr->name); /* daemonize() doesn't do this for us since some kernel threads - actually want to deal with signals. We can't just call + actually want to deal with signals. We can't just call exit_sighand() since that'll cause an oops when we finally do exit. */ spin_lock_irq(¤t->sighand->siglock); --------------------------------------------------------------------------------------------------------- diff -urN b/include/linux/mmzone.h a/include/linux/mmzone.h --- b/include/linux/mmzone.h 2007-06-12 16:13:11.000000000 +0200 +++ a/include/linux/mmzone.h 2010-05-31 03:45:11.000000000 +0200 @@ -306,7 +306,17 @@ * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the * queues ("queue_length >> 12") during an aging round. */ + +#if defined(CONFIG_MIPS_BRCM) +/* We normally have only 8M~32M of RAM while desktop systems can have 4G or + * more. The Linux default value of 12 means that the first iteration scans + * only 1~8 pages in our system. This can cause excessive fragmentation in + * the buddy system and is potentially CPU inefficient. Start from a higher + * priority (lower value) for more optimized memory scanning. */ +#define DEF_PRIORITY 6 +#else #define DEF_PRIORITY 12 +#endif /* Maximum number of zones on a zonelist */ #define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES) --------------------------------------------------------------------------------------------------------- diff -urN b/arch/mips/kernel/setup.c a/arch/mips/kernel/setup.c --- b/arch/mips/kernel/setup.c 2007-06-12 16:13:11.000000000 +0200 +++ a/arch/mips/kernel/setup.c 2010-05-31 03:51:37.000000000 +0200 @@ -64,7 +64,11 @@ * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ -const unsigned long mips_io_port_base __read_mostly = -1; + +#if defined(CONFIG_MIPS_BRCM) +const unsigned long mips_io_port_base __read_mostly = KSEG1; +#endif + EXPORT_SYMBOL(mips_io_port_base); /* --------------------------------------------------------------------------------------------------------- diff -urN a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c --- a/arch/mips/mm/tlbex.c 2009-12-04 10:32:25.000000000 +0100 +++ b/arch/mips/mm/tlbex.c 2013-01-22 11:00:55.000000000 +0100 @@ -270,6 +270,9 @@ case CPU_R4400PC: case CPU_R4400SC: case CPU_R4400MC: +#if defined(CONFIG_MIPS_BRCM) + case CPU_BMIPS4350: +#endif /* * This branch uses up a mtc0 hazard nop slot and saves * two nops after the tlbw instruction. --------------------------------------------------------------------------------------------------------- diff -urN a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c --- a/arch/mips/mm/c-r4k.c 2009-12-04 10:32:25.000000000 +0100 +++ b/arch/mips/mm/c-r4k.c 2013-01-22 11:00:55.000000000 +0100 @@ -531,11 +531,19 @@ static void r4k_flush_data_cache_page(unsigned long addr) { +#if defined(CONFIG_MIPS_BRCM) && defined(CONFIG_BRCM_DCACHE_SHARED) + + local_r4k_flush_data_cache_page((void *) addr); + +#else + if (in_atomic()) local_r4k_flush_data_cache_page((void *)addr); else r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1); + +#endif } struct flush_icache_range_args { @@ -1304,6 +1312,9 @@ case CPU_R4400PC: case CPU_R4400SC: case CPU_R4400MC: +#if defined(CONFIG_MIPS_BRCM) + case CPU_BMIPS4350: +#endif clear_c0_config(CONF_CU); break; /* --------------------------------------------------------------------------------------------------------- diff -urN a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c --- a/arch/mips/kernel/time.c 2009-12-04 10:32:25.000000000 +0100 +++ b/arch/mips/kernel/time.c 2013-01-22 11:00:46.000000000 +0100 @@ -34,6 +34,13 @@ DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); +/* how many counter cycles in a jiffy */ +#if defined(CONFIG_MIPS_BRCM) +unsigned long cycles_per_jiffy __read_mostly; +#else +static unsigned long cycles_per_jiffy __read_mostly; +#endif + int __weak rtc_mips_set_time(unsigned long sec) { return 0; ----------------------------------------------------------------------------------------------------------- diff -urN a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c --- a/arch/mips/kernel/idle.c 2013-11-29 20:12:03.000000000 +0100 +++ b/arch/mips/kernel/idle.c 2013-12-31 16:31:25.899704273 +0100 @@ -45,6 +45,42 @@ local_irq_enable(); } +/* Brcm version minimizes the chance of an irq sneaking in between checking +need_resched and wait instruction, or eliminates it completely (depending on +pipeline design). This avoids delayed processing of softirq. (The delayed +softirq problem can happen when preemption is disabled and softirq runs in +process context.) */ + +static void brcm_wait(void) +{ + /* Always try to treat the segment below as an atomic entity and try not + to insert code or move code around */ + /* Begin fixed safe code pattern for the particular MIPS pipleline*/ + raw_local_irq_disable(); + if (!need_resched() && !(read_c0_cause() & read_c0_status())) { + /* Perform SYNC, enable interrupts, then WAIT */ + __asm__ __volatile__ ( + ".set push\n" + ".set noreorder\n" + ".set noat\n" + "sync\n" + "mfc0 $1, $12\n" + "ori $1, $1, 0x1f\n" + "xori $1, $1, 0x1e\n" + "mtc0 $1, $12\n" + "nop\n" // Recommended by MIPS team + "wait\n" + "nop\n" // Needed to ensure next instruction is safe + "nop\n" // When speed is reduced to 1/8, need one more to get DG interrupt + "nop\n" // Safety net... + ".set pop\n"); + } + else { + raw_local_irq_enable(); + } + /* End fixed code pattern */ +} + void r4k_wait(void) { local_irq_enable(); @@ -144,6 +180,16 @@ case CPU_TX3927: cpu_wait = r39xx_wait; break; +/* No idea if brcm_wait can be used safely by all the BMIPS cpus; + at least with BMIPS4350 nothing strange happens. */ + case CPU_BMIPS3300: + case CPU_BMIPS4350: + case CPU_BMIPS4380: + case CPU_BMIPS5000: + cpu_wait = brcm_wait; + printk("brcm wait instruction: enabled\n"); + break; + case CPU_R4200: /* case CPU_R4300: */ case CPU_R4600: @@ -159,10 +205,6 @@ case CPU_5KC: case CPU_25KF: case CPU_PR4450: - case CPU_BMIPS3300: - case CPU_BMIPS4350: - case CPU_BMIPS4380: - case CPU_BMIPS5000: case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2:
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel