Index: /src/linux/adm5120/linux-2.6.23/kernel/module.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/kernel/module.c (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/kernel/module.c (revision 12415) @@ -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/adm5120/linux-2.6.23/crypto/api.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/crypto/api.c (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/crypto/api.c (revision 12415) @@ -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/adm5120/linux-2.6.23/include/asm-mips/module.h =================================================================== --- /src/linux/adm5120/linux-2.6.23/include/asm-mips/module.h (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/include/asm-mips/module.h (revision 12415) @@ -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/adm5120/linux-2.6.23/include/asm-mips/string.h =================================================================== --- /src/linux/adm5120/linux-2.6.23/include/asm-mips/string.h (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/include/asm-mips/string.h (revision 12415) @@ -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/adm5120/linux-2.6.23/.config =================================================================== --- /src/linux/adm5120/linux-2.6.23/.config (revision 11895) +++ /src/linux/adm5120/linux-2.6.23/.config (revision 12415) @@ -2,5 +2,5 @@ # Automatically generated make config: don't edit # Linux kernel version: 2.6.24.111 -# Mon Apr 6 11:23:59 2009 +# Tue Jun 30 13:35:08 2009 # CONFIG_MIPS=y @@ -686,5 +686,5 @@ # CONFIG_IMQ_BEHAVIOR_BB is not set CONFIG_IMQ_NUM_DEVS=2 -# CONFIG_TUN is not set +CONFIG_TUN=y # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set Index: /src/linux/adm5120/linux-2.6.23/.config_np28g =================================================================== --- /src/linux/adm5120/linux-2.6.23/.config_np28g (revision 11405) +++ /src/linux/adm5120/linux-2.6.23/.config_np28g (revision 12415) @@ -685,5 +685,5 @@ # CONFIG_IMQ_BEHAVIOR_BB is not set CONFIG_IMQ_NUM_DEVS=2 -# CONFIG_TUN is not set +CONFIG_TUN=y # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set Index: /src/linux/adm5120/linux-2.6.23/.config_full =================================================================== --- /src/linux/adm5120/linux-2.6.23/.config_full (revision 11405) +++ /src/linux/adm5120/linux-2.6.23/.config_full (revision 12415) @@ -685,5 +685,5 @@ # CONFIG_IMQ_BEHAVIOR_BB is not set CONFIG_IMQ_NUM_DEVS=2 -# CONFIG_TUN is not set +CONFIG_TUN=y # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set Index: /src/linux/adm5120/linux-2.6.23/mm/page_alloc.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/mm/page_alloc.c (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/mm/page_alloc.c (revision 12415) @@ -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/adm5120/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/vmlinux.lds.S (revision 12415) @@ -135,5 +135,6 @@ *(.bss) *(COMMON) - } + . = (ALIGN(_PAGE_SIZE) - .) < 8 ? ALIGN(_PAGE_SIZE) + 4 : . ; + } __bss_stop = .; Index: /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/module.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/module.c (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/module.c (revision 12415) @@ -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/adm5120/linux-2.6.23/arch/mips/kernel/scall32-o32.S =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/kernel/scall32-o32.S (revision 12415) @@ -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/adm5120/linux-2.6.23/arch/mips/adm5120/proc_gpio.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/proc_gpio.c (revision 11371) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/proc_gpio.c (revision 12415) @@ -154,5 +154,5 @@ int gpiocount; - gpiocount = 8; + gpiocount = 22; /* create directory gpio */ Index: /src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/boards/compex.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/boards/compex.c (revision 11371) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/boards/compex.c (revision 12415) @@ -81,5 +81,5 @@ unsigned char wp54_vlans[6] __initdata = { - 0x41, 0x42, 0x00, 0x00, 0x00, 0x00 + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 }; @@ -171,5 +171,5 @@ .board_setup = wp54_setup, .board_reset = wp54_reset, - .eth_num_ports = 2, + .eth_num_ports = 5, .eth_vlans = wp54_vlans, .num_devices = ARRAY_SIZE(wp54_devices), @@ -182,5 +182,5 @@ .board_setup = wp54_setup, .board_reset = wp54_reset, - .eth_num_ports = 2, + .eth_num_ports = 5, .eth_vlans = wp54_vlans, .num_devices = ARRAY_SIZE(wp54_devices), @@ -193,5 +193,5 @@ .board_setup = wp54_wrt_setup, .board_reset = wp54_reset, - .eth_num_ports = 2, + .eth_num_ports = 5, .eth_vlans = wp54_vlans, .num_devices = ARRAY_SIZE(wp54_devices), @@ -204,5 +204,5 @@ .board_setup = wp54_setup, .board_reset = wp54_reset, - .eth_num_ports = 2, + .eth_num_ports = 5, .eth_vlans = wp54_vlans, .num_devices = ARRAY_SIZE(wp54_devices), @@ -215,9 +215,9 @@ .board_setup = wp54_setup, .board_reset = wp54_reset, - .eth_num_ports = 2, - .eth_vlans = wp54_vlans, - .num_devices = ARRAY_SIZE(wp54_devices), - .devices = wp54_devices, - .pci_nr_irqs = ARRAY_SIZE(wp54_pci_irqs), - .pci_irq_map = wp54_pci_irqs, -ADM5120_BOARD_END + .eth_num_ports = 5, + .eth_vlans = wp54_vlans, + .num_devices = ARRAY_SIZE(wp54_devices), + .devices = wp54_devices, + .pci_nr_irqs = ARRAY_SIZE(wp54_pci_irqs), + .pci_irq_map = wp54_pci_irqs, +ADM5120_BOARD_END Index: /src/linux/adm5120/linux-2.6.23/arch/mips/Makefile =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/Makefile (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/Makefile (revision 12415) @@ -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/adm5120/linux-2.6.23/arch/mips/mm/c-r4k.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 10172) +++ /src/linux/adm5120/linux-2.6.23/arch/mips/mm/c-r4k.c (revision 12415) @@ -914,5 +914,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/adm5120/linux-2.6.23/drivers/net/adm5120sw.c =================================================================== --- /src/linux/adm5120/linux-2.6.23/drivers/net/adm5120sw.c (revision 11952) +++ /src/linux/adm5120/linux-2.6.23/drivers/net/adm5120sw.c (revision 12415) @@ -798,6 +798,8 @@ static inline void adm5120_if_napi_disable(struct net_device *dev) {} #endif /* CONFIG_ADM5120_SWITCH_NAPI */ +static void adm5120_if_set_multicast_list(struct net_device *dev); /* ------------------------------------------------------------------------ */ +#define SW_DIS_SA_LEARN_MASK 0x0000003F static int adm5120_if_open(struct net_device *dev) @@ -820,4 +822,5 @@ sw_int_unmask(SWITCH_INTS_USED); + /* enable (additional) port */ t = sw_read_reg(SWITCH_REG_PORT_CONF0); @@ -828,4 +831,31 @@ sw_write_reg(SWITCH_REG_PORT_CONF0, t); + +//wp54g patch + sw_write_reg(SWITCH_REG_PORT_CONF1, sw_read_reg(SWITCH_REG_PORT_CONF1) | SW_DIS_SA_LEARN_MASK); + adm5120_if_set_multicast_list(dev); + adm5120_write_mac(dev); +/* +//important: promisc mode +#define SW_DIS_UN_SHIFT 9 +#define SW_DIS_UN_MASK (0x3F << SW_DIS_UN_SHIFT) +#define SW_DIS_MC_SHIFT 16 +#define SW_DIS_MC_MASK (0x3F << SW_DIS_MC_SHIFT) +#define SW_DIS_BC_SHIFT 24 +#define SW_DIS_BC_MASK (0x3F << SW_DIS_BC_SHIFT) + + if (dev->flags & IFF_PROMISC) { + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); + sw_write_reg(SWITCH_REG_CPUP_CONF, sw_read_reg(SWITCH_REG_CPUP_CONF) & ~(SW_DIS_BC_MASK | SW_DIS_MC_MASK | SW_DIS_UN_MASK)); + } else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { + sw_write_reg(SWITCH_REG_CPUP_CONF, sw_read_reg(SWITCH_REG_CPUP_CONF) & ~(SW_DIS_BC_MASK | SW_DIS_MC_MASK | SW_DIS_UN_MASK)); + } else { + sw_write_reg(SWITCH_REG_CPUP_CONF, (sw_read_reg(SWITCH_REG_CPUP_CONF) & ~(SW_DIS_BC_MASK | SW_DIS_UN_MASK)) | SW_DIS_MC_MASK); + } + + // Sets the switch bridge mode + sw_write_reg(SWITCH_REG_CPUP_CONF, sw_read_reg(SWITCH_REG_CPUP_CONF) | CPUP_CONF_BTM); +*/ netif_start_queue(dev); @@ -1075,9 +1105,9 @@ adm5120_nrdevs = adm5120_eth_num_ports; - sw_write_reg(SWITCH_REG_PORT0_LED, 0x9); - sw_write_reg(SWITCH_REG_PORT1_LED, 0x9); - sw_write_reg(SWITCH_REG_PORT2_LED, 0x9); - sw_write_reg(SWITCH_REG_PORT3_LED, 0x9); - sw_write_reg(SWITCH_REG_PORT4_LED, 0x9); + sw_write_reg(SWITCH_REG_PORT0_LED,(LED_MODE_LINK_ACT << LED0_MODE_SHIFT) | (LED_MODE_SPEED << LED1_MODE_SHIFT) | (LED_MODE_LINK << LED2_MODE_SHIFT)); + sw_write_reg(SWITCH_REG_PORT1_LED,(LED_MODE_LINK_ACT << LED0_MODE_SHIFT) | (LED_MODE_SPEED << LED1_MODE_SHIFT) | (LED_MODE_LINK << LED2_MODE_SHIFT)); + sw_write_reg(SWITCH_REG_PORT2_LED,(LED_MODE_LINK_ACT << LED0_MODE_SHIFT) | (LED_MODE_SPEED << LED1_MODE_SHIFT) | (LED_MODE_LINK << LED2_MODE_SHIFT)); + sw_write_reg(SWITCH_REG_PORT3_LED,(LED_MODE_LINK_ACT << LED0_MODE_SHIFT) | (LED_MODE_SPEED << LED1_MODE_SHIFT) | (LED_MODE_LINK << LED2_MODE_SHIFT)); + sw_write_reg(SWITCH_REG_PORT4_LED,(LED_MODE_LINK_ACT << LED0_MODE_SHIFT) | (LED_MODE_SPEED << LED1_MODE_SHIFT) | (LED_MODE_LINK << LED2_MODE_SHIFT)); t = CPUP_CONF_DCPUP | CPUP_CONF_CRCP | @@ -1085,4 +1115,7 @@ SWITCH_PORTS_NOCPU << CPUP_CONF_DMCP_SHIFT ; sw_write_reg(SWITCH_REG_CPUP_CONF, t); + + + t = (SWITCH_PORTS_NOCPU << PORT_CONF0_EMCP_SHIFT) |