Index: /src/linux/ar531x/linux-2.6.23/kernel/module.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/kernel/module.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/kernel/module.c (revision 12400) @@ -1738,4 +1738,8 @@ layout_sections(mod, hdr, sechdrs, secstrings); +#ifdef __mips + module_relayout(hdr, sechdrs, secstrings, symindex, mod); +#endif + /* Do the allocs. */ ptr = module_alloc(mod->core_size); Index: /src/linux/ar531x/linux-2.6.23/lib/string.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/lib/string.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/lib/string.c (revision 12400) @@ -529,12 +529,39 @@ const char *s = src; - while (count--) - *tmp++ = *s++; + unsigned int val,offset=0; + while(count--) //aligned copy + { + if (((unsigned int)offset % 4) == 0) { + val = *(unsigned int *)s; + s += 4; + } + *tmp++ = ((unsigned char *)&val) + (offset++ & 3); + } return dest; } + EXPORT_SYMBOL(memcpy); #endif #ifndef __HAVE_ARCH_MEMMOVE + +void *memcpy_rev(void *dest, const void *src, size_t count) +{ + char *tmp = dest; + const char *s = src; + s+=count; + tmp+=count; + unsigned int val,offset=0; + while(count--) //aligned copy + { + if (((unsigned int)offset % 4) == 0) { + val = *(unsigned int *)s; + s -= 4; + } + *tmp-- = ((unsigned char *)&val) + (offset++ & 3); + } + return dest; +} + /** * memmove - Copy one area of memory to another @@ -553,6 +580,5 @@ tmp = dest; s = src; - while (count--) - *tmp++ = *s++; + memcpy(tmp,s,count); } else { tmp = dest; @@ -561,5 +587,5 @@ s += count; while (count--) - *--tmp = *--s; + memcpy_rev(tmp,s,count); } return dest; Index: /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.c (revision 12400) @@ -46,5 +46,5 @@ } CRangeDecoder; -Byte RangeDecoderReadByte(CRangeDecoder *rd) +static inline Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) @@ -67,5 +67,5 @@ #define ReadByte (RangeDecoderReadByte(rd)) -void RangeDecoderInit(CRangeDecoder *rd, +static void RangeDecoderInit(CRangeDecoder *rd, #ifdef _LZMA_IN_CB ILzmaInCallback *inCallback @@ -94,5 +94,5 @@ #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } -UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) +static inline UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR @@ -122,5 +122,5 @@ } -int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) +static inline int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; @@ -160,5 +160,5 @@ #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) -int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +static inline int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; @@ -182,5 +182,5 @@ } -int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +static inline int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; @@ -207,5 +207,5 @@ } -Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) +static inline Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; @@ -229,5 +229,5 @@ } -Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) +static inline Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; @@ -287,5 +287,5 @@ #define kNumLenProbs (LenHigh + kLenNumHighSymbols) -int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) +static inline int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) Index: /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.h (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/fs/squashfs/LzmaDecode.h (revision 12400) @@ -29,9 +29,9 @@ /* Use read function for output data */ -/* #define _LZMA_PROB32 */ +#define _LZMA_PROB32 /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ -/* #define _LZMA_LOC_OPT */ +#define _LZMA_LOC_OPT /* Enable local speed optimizations inside code */ Index: /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 12400) @@ -135,5 +135,6 @@ *(.bss) *(COMMON) - } + . = (ALIGN(_PAGE_SIZE) - .) < 8 ? ALIGN(_PAGE_SIZE) + 4 : . ; + } __bss_stop = .; Index: /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/module.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/module.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/module.c (revision 12400) @@ -30,4 +30,5 @@ #include #include +#include #include /* MODULE_START */ @@ -43,4 +44,39 @@ static DEFINE_SPINLOCK(dbe_lock); +static void *alloc_phys(unsigned long size) +{ + unsigned order; + struct page *page; + struct page *p; + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages( + GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | __GFP_THISNODE, + order); + if (!page) + return 0; + + split_page(page, order); + + for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) + __free_page(p); + + return page_address(page); +} + +static void free_phys(void *ptr, unsigned long size) +{ + struct page *page; + struct page *end; + + page = virt_to_page(ptr); + end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); + + for (; page < end; ++page) + __free_pages(page, 0); +} + void *module_alloc(unsigned long size) { @@ -58,8 +94,39 @@ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else + unsigned addr; + void *ptr; + + size = PAGE_ALIGN(size); if (size == 0) return NULL; - return vmalloc(size); + + ptr = alloc_phys(size); + if (ptr) + return ptr; + + /* try to allocate contiguos chunk of memory not spanning 256Mb + range, so all jump instructions can work */ + addr = VMALLOC_START; + while (addr < VMALLOC_END) { + unsigned end = ALIGN(addr + 1, 1u << 28); + + if (addr + size <= end) { + struct vm_struct *area + = __get_vm_area(size, VM_ALLOC, addr, end); + + if (area) + return __vmalloc_area( + area, GFP_KERNEL, PAGE_KERNEL); + } + addr = end; + } + return NULL; #endif +} + +static inline int is_phys(void *ptr) +{ + unsigned addr = (unsigned) ptr; + return addr && (addr < VMALLOC_START || addr > VMALLOC_END); } @@ -67,4 +134,14 @@ void module_free(struct module *mod, void *module_region) { + if (is_phys(module_region)) { + if (mod->module_init == module_region) + free_phys(module_region, mod->init_size); + else if (mod->module_core == module_region) + free_phys(module_region, mod->core_size); + else + BUG(); + return; + } + vfree(module_region); /* FIXME: If module_region == mod->init_region, trim exception @@ -78,4 +155,98 @@ } +/* Get the potential trampolines size required of the init and + non-init sections */ +static unsigned get_plt_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + unsigned symindex, + int is_init) +{ + unsigned long ret = 0; + unsigned i, j; + Elf_Sym *syms; + + /* Everything marked ALLOC (this includes the exported symbols) */ + for (i = 1; i < hdr->e_shnum; ++i) { + unsigned int info = sechdrs[i].sh_info; + + if (sechdrs[i].sh_type != SHT_REL + && sechdrs[i].sh_type != SHT_RELA) + continue; + + /* Not a valid relocation section? */ + if (info >= hdr->e_shnum) + continue; + + /* Don't bother with non-allocated sections */ + if (!(sechdrs[info].sh_flags & SHF_ALLOC)) + continue; + + /* If it's called *.init*, and we're not init, we're + not interested */ + if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) + != is_init) + continue; + + syms = (Elf_Sym *) sechdrs[symindex].sh_addr; + if (sechdrs[i].sh_type == SHT_REL) { + Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; + unsigned size = sechdrs[i].sh_size / sizeof(*rel); + + for (j = 0; j < size; ++j) { + Elf_Sym *sym; + + if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) + continue; + sym = syms + ELF_MIPS_R_SYM(rel[j]); + if (!is_init && sym->st_shndx != SHN_UNDEF) + continue; + + ret += sizeof(unsigned[4]); + } + } else { + Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; + unsigned size = sechdrs[i].sh_size / sizeof(*rela); + + for (j = 0; j < size; ++j) { + Elf_Sym *sym; + + if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) + continue; + sym = syms + ELF_MIPS_R_SYM(rela[j]); + if (!is_init && sym->st_shndx != SHN_UNDEF) + continue; + + ret += sizeof(unsigned[4]); + } + } + + } + + return ret; +} + +int module_relayout(Elf32_Ehdr *hdr, + Elf32_Shdr *sechdrs, + char *secstrings, + unsigned symindex, + struct module *me) +{ + unsigned core_plt_size = get_plt_size( + hdr, sechdrs, secstrings, symindex, 0); + unsigned init_plt_size = get_plt_size( + hdr, sechdrs, secstrings, symindex, 1); + + if (core_plt_size > 0) + me->core_size = PAGE_ALIGN(me->core_size); + me->arch.core_plt_offset = me->core_size; + me->core_size = me->core_size + core_plt_size; + + me->arch.init_plt_offset = me->init_size; + me->init_size = me->init_size + init_plt_size; + + return 0; +} + static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) { @@ -94,4 +265,42 @@ *location = v; + return 0; +} + +static Elf_Addr add_plt_entry_to(unsigned *plt_offset, + void *start, unsigned size, Elf_Addr v) +{ + unsigned *tramp = start + *plt_offset; + if (*plt_offset == size) return 0; + + *plt_offset += sizeof(unsigned[4]); + + /* adjust carry for addiu */ + if (v & 0x00008000) + v += 0x10000; + + tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ + tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ + tramp[2] = 0x03200008; /* jr t9 */ + tramp[3] = 0x00000000; /* nop */ + + return (Elf_Addr) tramp; +} + +static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) +{ + if (location >= me->module_core + && location < me->module_core + me->core_size) { + return add_plt_entry_to(&me->arch.core_plt_offset, + me->module_core, me->core_size, v); + } else if (location > me->module_init + && location < me->module_init + me->init_size) { + return add_plt_entry_to(&me->arch.init_plt_offset, + me->module_init, me->init_size, v); + } else { + printk(KERN_ERR "module %s: " + "relocation to unknown segment %u\n", + me->name, v); + } return 0; } @@ -105,4 +314,7 @@ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + v = add_plt_entry(me, location, + v + ((*location & 0x03ffffff) << 2)); + if (v == 0) { printk(KERN_ERR "module %s: relocation overflow\n", @@ -110,4 +322,8 @@ return -ENOEXEC; } + *location = (*location & ~0x03ffffff) | + ((v >> 2) & 0x03ffffff); + return 0; + } *location = (*location & ~0x03ffffff) | @@ -125,8 +341,11 @@ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + v = add_plt_entry(me, location, v); + if (v == 0) { printk(KERN_ERR "module %s: relocation overflow\n", me->name); return -ENOEXEC; + } } @@ -400,4 +619,12 @@ spin_unlock_irq(&dbe_lock); } + + if (me->arch.core_plt_offset < me->core_size + && PAGE_ALIGN(me->arch.core_plt_offset) == me->arch.core_plt_offset + && is_phys(me->module_core)) { + free_phys(me->module_core + me->arch.core_plt_offset, + me->core_size - me->arch.core_plt_offset); + me->core_size = me->arch.core_plt_offset; + } return 0; } Index: /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/scall32-o32.S =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 12400) @@ -647,5 +647,5 @@ sys sys_ppoll 5 sys sys_unshare 1 - sys sys_splice 4 + sys sys_splice 6 sys sys_sync_file_range 7 /* 4305 */ sys sys_tee 4 Index: /src/linux/ar531x/linux-2.6.23/arch/mips/Makefile =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/Makefile (revision 9058) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/Makefile (revision 12400) @@ -84,5 +84,5 @@ cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib -MODFLAGS += -mlong-calls +MODFLAGS += -mno-long-calls cflags-y += -ffreestanding Index: /src/linux/ar531x/linux-2.6.23/arch/mips/atheros/ar5315/board.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/atheros/ar5315/board.c (revision 11759) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/atheros/ar5315/board.c (revision 12400) @@ -236,4 +236,5 @@ /* reset the system */ sysRegWrite(AR5315_COLD_RESET,AR5317_RESET_SYSTEM); + mdelay(100); /* * Cold reset does not work on the AR2315/6, use the GPIO reset bits a workaround. Index: /src/linux/ar531x/linux-2.6.23/arch/mips/mm/c-r4k.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 11387) +++ /src/linux/ar531x/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 12400) @@ -932,5 +932,7 @@ c->dcache.waybit = __ffs(dcache_size/c->dcache.ways); +#ifdef CONFIG_CPU_HAS_PREFETCH c->options |= MIPS_CPU_PREFETCH; +#endif break; } Index: /src/linux/ar531x/linux-2.6.23/crypto/api.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/crypto/api.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/crypto/api.c (revision 12400) @@ -394,5 +394,5 @@ return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(crypto_alloc_base); +EXPORT_SYMBOL(crypto_alloc_base); /* @@ -422,5 +422,5 @@ } -EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL(crypto_free_tfm); int crypto_alg_available(const char *name, u32 flags) Index: /src/linux/ar531x/linux-2.6.23/include/asm-mips/module.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/include/asm-mips/module.h (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/include/asm-mips/module.h (revision 12400) @@ -10,4 +10,7 @@ const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; + + unsigned int core_plt_offset; + unsigned int init_plt_offset; }; @@ -66,4 +69,6 @@ /* Given an address, look for it in the exception tables. */ const struct exception_table_entry*search_module_dbetables(unsigned long addr); +int module_relayout(Elf32_Ehdr *hdr, Elf32_Shdr *sechdrs, + char *secstrings, unsigned symindex, struct module *me); #else /* Given an address, look for it in the exception tables. */ Index: /src/linux/ar531x/linux-2.6.23/include/asm-mips/string.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/include/asm-mips/string.h (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/include/asm-mips/string.h (revision 12400) @@ -109,6 +109,7 @@ ".set\tnoreorder\n\t" ".set\tnoat\n" - "1:\tlbu\t%3,(%0)\n\t" - "beqz\t%2,2f\n\t" + "1:\tbeqz\t%2,2f\n\t" + "nop\n\t" + "lbu\t%3,(%0)\n\t" "lbu\t$1,(%1)\n\t" "subu\t%2,1\n\t" Index: /src/linux/ar531x/linux-2.6.23/include/linux/skbuff.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/include/linux/skbuff.h (revision 8438) +++ /src/linux/ar531x/linux-2.6.23/include/linux/skbuff.h (revision 12400) @@ -1297,7 +1297,7 @@ gfp_t gfp_mask) { - struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); + struct sk_buff *skb = alloc_skb(length + 64, gfp_mask); if (likely(skb)) - skb_reserve(skb, NET_SKB_PAD); + skb_reserve(skb, 64); return skb; } Index: /src/linux/ar531x/linux-2.6.23/include/linux/jhash.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/include/linux/jhash.h (revision 11888) +++ /src/linux/ar531x/linux-2.6.23/include/linux/jhash.h (revision 12400) Index: /src/linux/ar531x/linux-2.6.23/include/linux/netfilter_ipv4/ip_tables.h =================================================================== --- /src/linux/ar531x/linux-2.6.23/include/linux/netfilter_ipv4/ip_tables.h (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/include/linux/netfilter_ipv4/ip_tables.h (revision 12400) @@ -63,4 +63,5 @@ #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ +#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ /* Values for "inv" field in struct ipt_ip. */ Index: /src/linux/ar531x/linux-2.6.23/net/core/skbuff.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/net/core/skbuff.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/net/core/skbuff.c (revision 12400) @@ -221,7 +221,7 @@ struct sk_buff *skb; - skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node); + skb = __alloc_skb(length + 64, gfp_mask, 0, node); if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD); + skb_reserve(skb, 64); skb->dev = dev; } Index: /src/linux/ar531x/linux-2.6.23/net/ipv4/netfilter/ip_tables.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/net/ipv4/netfilter/ip_tables.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/net/ipv4/netfilter/ip_tables.c (revision 12400) @@ -87,4 +87,7 @@ #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg)) + if (ipinfo->flags & IPT_F_NO_DEF_MATCH) + return true; + if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, IPT_INV_SRCIP) @@ -149,4 +152,5 @@ return 0; } +#undef FWINV return 1; @@ -154,7 +158,28 @@ static inline bool -ip_checkentry(const struct ipt_ip *ip) -{ - if (ip->flags & ~IPT_F_MASK) { +ip_checkentry(struct ipt_ip *ip) +{ +#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg))) + + if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) || + FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP)) + goto has_match_rules; + + if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0], + IPT_INV_VIA_IN) || + FWINV(!!((const unsigned long *)ip->outiface_mask)[0], + IPT_INV_VIA_OUT)) + goto has_match_rules; + + if (FWINV(ip->proto, IPT_INV_PROTO)) + goto has_match_rules; + + if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG)) + goto has_match_rules; + + ip->flags |= IPT_F_NO_DEF_MATCH; + +has_match_rules: + if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) { duprintf("Unknown flag bits set: %08X\n", ip->flags & ~IPT_F_MASK); @@ -166,4 +191,5 @@ return false; } +#undef FWINV return true; } @@ -331,6 +357,25 @@ struct xt_table_info *private; + ip = ip_hdr(*pskb); + + read_lock_bh(&table->lock); + IP_NF_ASSERT(table->valid_hooks & (1 << hook)); + private = table->private; + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); + if (e->target_offset <= sizeof(struct ipt_entry) && + (e->ip.flags & IPT_F_NO_DEF_MATCH)) { + struct ipt_entry_target *t = ipt_get_target(e); + if (!t->u.kernel.target->target) { + int v = ((struct ipt_standard_target *)t)->verdict; + if ((v < 0) && (v != IPT_RETURN)) { + ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); + read_unlock_bh(&table->lock); + return (unsigned)(-v) - 1; + } + } + } + /* Initialization */ - ip = ip_hdr(*pskb); datalen = (*pskb)->len - ip->ihl * 4; indev = in ? in->name : nulldevname; @@ -344,10 +389,10 @@ offset = ntohs(ip->frag_off) & IP_OFFSET; - read_lock_bh(&table->lock); +/* read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); - +*/ /* For return from builtin chain */ back = get_entry(table_base, private->underflow[hook]); Index: /src/linux/ar531x/linux-2.6.23/mm/page_alloc.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/mm/page_alloc.c (revision 8169) +++ /src/linux/ar531x/linux-2.6.23/mm/page_alloc.c (revision 12400) @@ -1265,4 +1265,12 @@ /* + * Code in arch/mips/kernel/module.c wants physically + * contiguous memory only if there is plenty of free of them. + */ + if ((gfp_mask & (__GFP_THISNODE | __GFP_NORETRY | __GFP_NOWARN)) + == (__GFP_THISNODE | __GFP_NORETRY | __GFP_NOWARN)) + goto nopage; + + /* * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and * __GFP_NOWARN set) should not cause reclaim since the subsystem @@ -1277,4 +1285,7 @@ for (z = zonelist->zones; *z; z++) wakeup_kswapd(*z, order); + + if (gfp_mask & 0x80000000) + goto nopage; /* Index: /src/linux/ar531x/linux-2.6.23/drivers/mtd/devices/spiflash.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/drivers/mtd/devices/spiflash.c (revision 9243) +++ /src/linux/ar531x/linux-2.6.23/drivers/mtd/devices/spiflash.c (revision 12400) @@ -256,4 +256,5 @@ spiflash_regwrite32(SPI_FLASH_CTL, reg); + busy_wait(spiflash_regread32(SPI_FLASH_CTL) & SPI_CTL_BUSY, 0); Index: /src/linux/ar531x/linux-2.6.23/drivers/mtd/maps/eoc5610_flash.c =================================================================== --- /src/linux/ar531x/linux-2.6.23/drivers/mtd/maps/eoc5610_flash.c (revision 11767) +++ /src/linux/ar531x/linux-2.6.23/drivers/mtd/maps/eoc5610_flash.c (revision 12400) @@ -6,5 +6,5 @@ * Copyright (C) 2006-2007 Tomas Dlabac */ - + /* * @@ -22,5 +22,4 @@ #include - #ifdef CONFIG_MTD_PARTITIONS #include @@ -31,86 +30,102 @@ #define WINDOW_SIZE 0x00800000 - /* These ought to be somewhere common... */ #define AR531X_FLASHCTL 0x18400000 -#define FLASHCTL_MW 0x30000000 /* Memory width */ -#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ -#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ -#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ +#define FLASHCTL_MW 0x30000000 /* Memory width */ +#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ +#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ +#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ #define sysRegRead(phys) __raw_readl(KSEG1ADDR(phys)) - static struct mtd_info *mymtd; #ifdef CONFIG_MTD_PARTITIONS -static const char *probes []={"cmdlinepart",NULL}; +static const char *probes[] = { "cmdlinepart", NULL }; #endif struct map_info ar531x_map = { - name: "ar531x", - size: WINDOW_SIZE + name:"ar531x", + size:WINDOW_SIZE }; #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition *mtd_parts = 0; -static int mtd_parts_nb = 0; +static int mtd_parts_nb = 0; struct img_info { uint32_t lenght; uint32_t CRC; - }; - -static struct mtd_partition ar531x_partitions[] = { - { - name: "RedBoot", - size: 0x30000, /* 64KB */ - offset: 0, - }, { - name: "linux", - size: 0x7A0000, - offset: 0x30000, - }, { - name: "rootfs", - size: 0x0, - offset: MTDPART_OFS_APPEND, - }, { - name: "ddwrt", - size: 0x0, - offset: MTDPART_OFS_APPEND, - }, { - name: "nvram", - size: 0x10000, - offset: 0x7D0000, - }, { - name: "FIS directory", - size: 0x10000, - offset: 0x7E0000, - }, { - name: "board_config", - size: 0x10000, /* 64KB */ - offset: 0x7F0000, - } - -}; - -#define NUM_PARTITIONS (sizeof(ar531x_partitions)/sizeof(struct mtd_partition)) -#endif - - +}; + +static struct mtd_partition dir_parts[] = { + { + name:"RedBoot", + size:0x30000, /* 64KB */ + offset:0, + }, { + name:"linux", + size:0x7A0000, + offset:0x30000, + }, { + name:"rootfs", + size:0x0, + offset:MTDPART_OFS_APPEND, + }, { + name: "ddwrt", + size: 0x0, + offset:MTDPART_OFS_APPEND, + }, { + name: "nvram", + size: 0x10000, + offset: 0x7D0000, + }, { + name: "FIS directory", + size: 0x10000, + offset: 0x7E0000, + }, { + name: "board_config", + size: 0x10000, /* 64KB */ + offset: 0x7F0000, + } + , { + name:"fullflash", + size:0x800000, /* 64KB */ + offset:0x000000, + } +}; + +struct fis_image_desc { + unsigned char name[16]; // Null terminated name + unsigned long flash_base; // Address within FLASH of image + unsigned long mem_base; // Address in memory where it executes + unsigned long size; // Length of image + unsigned long entry_point; // Execution entry point + unsigned long data_length; // Length of actual data + unsigned char _pad[256 - (16 + 7 * sizeof(unsigned long))]; + unsigned long desc_cksum; // Checksum over image descriptor + unsigned long file_cksum; // Checksum over image data +}; + +#define NUM_PARTITIONS (sizeof(dir_parts)/sizeof(struct mtd_partition)) +#endif int __init init_ar531x(void) { - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 }; + static const char *rom_probe_types[] = + { "cfi_probe", "jedec_probe", "map_rom", 0 }; const char **type; unsigned int flashctl; void *buf; - size_t retlen; + size_t retlen; int ret; + unsigned char *p; + struct fis_image_desc *fis; struct img_info *image_info; struct squashfs_super_block *sb; - int len; + int len; + size_t rootsize; /* This is nasty, but needed as the new AR2312-01 parts only @@ -126,10 +141,10 @@ else { printk(KERN_ERR "ar531x illegal flash buswidth (%#x)\n", - flashctl); + flashctl); return -ENXIO; } -// printk(KERN_NOTICE "ar531x flash buswidth detected as %d\n", -// ar531x_map.bankwidth); +// printk(KERN_NOTICE "ar531x flash buswidth detected as %d\n", +// ar531x_map.bankwidth); /* @@ -139,9 +154,9 @@ ar531x_map.phys = WINDOW_ADDR; - ar531x_map.virt = ioremap(WINDOW_ADDR,WINDOW_SIZE); - + ar531x_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); + if (!ar531x_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; + printk("Failed to ioremap\n"); + return -EIO; } @@ -150,51 +165,107 @@ mymtd = 0; type = rom_probe_types; - for(; !mymtd && *type; type++) { + for (; !mymtd && *type; type++) { mymtd = do_map_probe(*type, &ar531x_map); } if (mymtd) { mymtd->owner = THIS_MODULE; -// add_mtd_device(mymtd); - printk(KERN_NOTICE "AR531x Flash device initialized: size 0x%x at 0x%x bankwidth 0x%x\n", - mymtd->size, WINDOW_ADDR, ar531x_map.bankwidth); - -#ifdef CONFIG_MTD_PARTITIONS - if (buf) { - int offset = 0x0; - char *buf = (char*)0xbfc00000; - while((offset+mymtd->erasesize)size) - { - if (*((__u32 *) buf) == SQUASHFS_MAGIC) - { - printk(KERN_EMERG "\nfound squashfs at %X\n",offset); - sb = (struct squashfs_super_block *) buf; - - ar531x_partitions[2].offset=offset; +// add_mtd_device(mymtd); + printk(KERN_NOTICE + "AR531x Flash device initialized: size 0x%x at 0x%x bankwidth 0x%x\n", + mymtd->size, WINDOW_ADDR, ar531x_map.bankwidth); + +#ifdef CONFIG_MTD_PARTITIONS + { + int offset = 0x0; + unsigned char *buf = (unsigned char *)0xa8000000; + while ((offset + mymtd->erasesize) < mymtd->size) { + if (*((__u32 *)buf) == SQUASHFS_MAGIC) { + printk(KERN_EMERG + "\nfound squashfs at %X\n", + offset); + sb = (struct squashfs_super_block *)buf; + + dir_parts[2].offset = offset; len = sb->bytes_used; - len += (mymtd->erasesize - 1); + len += (mymtd->erasesize - 1); len &= ~(mymtd->erasesize - 1); - ar531x_partitions[2].size = len; - ar531x_partitions[3].offset=offset+ar531x_partitions[2].size; - ar531x_partitions[3].size = ar531x_partitions[1].size-(ar531x_partitions[3].offset-0x30000); - ar531x_partitions[6].offset=mymtd->size-mymtd->erasesize; - ar531x_partitions[5].offset=mymtd->size-(mymtd->erasesize*2); - ar531x_partitions[4].offset=mymtd->size-(mymtd->erasesize*3); + dir_parts[2].size = len; + dir_parts[3].offset = + offset + dir_parts[2].size; + dir_parts[3].size = + dir_parts[1].size - + (dir_parts[3].offset - + 0x30000); + dir_parts[6].offset = + mymtd->size - mymtd->erasesize; + dir_parts[5].offset = + mymtd->size - + (mymtd->erasesize * 2); + dir_parts[4].offset = + mymtd->size - + (mymtd->erasesize * 3); + rootsize = dir_parts[4].offset - offset; //size of rootfs aligned to nvram offset + + p = (unsigned char *)(0xa8000000 + + dir_parts[5]. + offset); + fis = (struct fis_image_desc *)p; + while (1) { + if (fis->name[0] == 0xff) { + goto def; + } + if (!strcmp + (fis->name, "RedBoot")) { + printk(KERN_EMERG + "found RedBoot partition at [0x%08lX]\n", + fis->flash_base); + dir_parts[0].size = + fis->size; + dir_parts[7].offset = 0; + } + if (!strcmp(fis->name, "linux") + || !strncmp(fis->name, + "vmlinux", 7) + || !strcmp(fis->name, + "kernel")) { + printk(KERN_EMERG + "found linux partition at [0x%08lX]\n", + fis->flash_base); + dir_parts[1].offset = + fis-> + flash_base & (mymtd-> + size - + 1); + dir_parts[1].size = + (dir_parts[2]. + offset - + dir_parts[1]. + offset) + rootsize; + dir_parts[7].size = mymtd->size; // linux + nvram = phy size + } + p += sizeof(struct + fis_image_desc); + fis = + (struct fis_image_desc *)p; + } break; - } - offset+=mymtd->erasesize; - buf+=mymtd->erasesize; - } - if (NUM_PARTITIONS != 0) - { - printk(KERN_NOTICE "Using ar531x DD-WRT partition definition\n"); - add_mtd_partitions (mymtd, ar531x_partitions, NUM_PARTITIONS); } - - } + offset += mymtd->erasesize; + buf += mymtd->erasesize; + } + def:; + if (NUM_PARTITIONS != 0) { + printk(KERN_NOTICE + "Using ar531x DD-WRT partition definition\n"); + add_mtd_partitions(mymtd, dir_parts, + NUM_PARTITIONS); + } + + } #endif return 0; } - iounmap ((void *)ar531x_map.virt); + iounmap((void *)ar531x_map.virt); return -ENXIO; } @@ -207,6 +278,6 @@ } if (ar531x_map.virt) { - iounmap ((void *)ar531x_map.virt); - ar531x_map.virt=0; + iounmap((void *)ar531x_map.virt); + ar531x_map.virt = 0; } } @@ -214,5 +285,4 @@ module_init(init_ar531x); module_exit(cleanup_ar531x); - MODULE_LICENSE("GPL");