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, &param);
+#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(&current->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

Reply via email to