From 338322e6076c42a58e4cfcda8add4ef372d90274 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:28:43 -0500 Subject: [PATCH] Import 2.3.29pre3 --- arch/i386/boot/compressed/misc.c | 4 +- arch/i386/kernel/irq.c | 2 +- arch/i386/kernel/mtrr.c | 1 + arch/i386/kernel/setup.c | 1 - arch/i386/kernel/smp.c | 1 + arch/i386/kernel/smpboot.c | 12 +- arch/i386/kernel/traps.c | 1 + arch/i386/kernel/vm86.c | 2 +- arch/i386/mm/fault.c | 2 +- arch/i386/mm/init.c | 60 ++- arch/i386/mm/ioremap.c | 1 + drivers/block/ide-cd.c | 2 +- drivers/char/mem.c | 2 +- drivers/net/setup.c | 1 + drivers/parport/Config.in | 2 +- drivers/scsi/hosts.h | 1 - drivers/usb/Config.in | 8 +- drivers/video/Makefile | 646 +++++------------------------- drivers/video/fbmem.c | 33 -- drivers/video/fbmon.c | 73 ++++ fs/Config.in | 4 +- fs/binfmt_aout.c | 2 +- fs/binfmt_elf.c | 2 +- fs/exec.c | 2 +- fs/ncpfs/dir.c | 13 +- fs/ncpfs/mmap.c | 6 +- fs/nfs/dir.c | 9 +- fs/nfs/file.c | 3 +- fs/nfs/read.c | 16 +- fs/nfs/symlink.c | 9 +- fs/nfs/write.c | 5 +- fs/udf/dir.c | 4 - fs/udf/directory.c | 2 +- fs/udf/inode.c | 4 +- fs/udf/lowlevel.c | 2 +- fs/udf/namei.c | 12 +- fs/udf/udfdecl.h | 2 +- include/asm-i386/highmem.h | 13 + include/asm-i386/io.h | 1 - include/asm-i386/pgalloc-2level.h | 23 ++ include/asm-i386/pgalloc-3level.h | 68 ++++ include/asm-i386/pgalloc.h | 247 ++++++++++++ include/asm-i386/pgtable-2level.h | 15 - include/asm-i386/pgtable-3level.h | 63 +-- include/asm-i386/pgtable.h | 262 +----------- include/linux/bootmem.h | 1 + include/linux/coda_proc.h | 8 +- include/linux/fb.h | 11 +- include/linux/highmem.h | 5 +- include/linux/mm.h | 148 ++++++- include/linux/pagemap.h | 1 + init/main.c | 1 - kernel/fork.c | 1 + kernel/ksyms.c | 7 +- kernel/module.c | 2 +- mm/bootmem.c | 8 +- mm/filemap.c | 2 +- mm/highmem.c | 39 +- mm/memory.c | 6 +- mm/mmap.c | 2 +- mm/mprotect.c | 2 +- mm/mremap.c | 2 +- mm/page_alloc.c | 482 ++++++++++++---------- mm/slab.c | 20 +- mm/vmalloc.c | 1 + mm/vmscan.c | 3 +- net/irda/irproc.c | 2 +- net/wanrouter/wanproc.c | 10 +- 68 files changed, 1117 insertions(+), 1291 deletions(-) create mode 100644 drivers/video/fbmon.c create mode 100644 include/asm-i386/pgalloc-2level.h create mode 100644 include/asm-i386/pgalloc-3level.h create mode 100644 include/asm-i386/pgalloc.h diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 92ae6af45670..8aac90800b9d 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -9,10 +9,8 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ -#include -#include +#include #include - /* * gzip declarations */ diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 1bccad67bf4a..e9feeca3ad97 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index e00f379028c0..57d9b8b457f4 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -1818,6 +1818,7 @@ int __init mtrr_init(void) # ifdef CONFIG_PROC_FS proc_root_mtrr = create_proc_entry("mtrr", S_IWUSR|S_IRUGO, &proc_root); proc_root_mtrr->ops = &proc_mtrr_inode_operations; +#endif init_table (); return 0; } /* End Function mtrr_init */ diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 93283dfb9334..734053ed4c02 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -637,7 +637,6 @@ void __init setup_arch(char **cmdline_p) highstart_pfn = highend_pfn = max_pfn; if (max_pfn > MAXMEM_PFN) { highstart_pfn = MAXMEM_PFN; - highend_pfn = max_pfn; printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", pages_to_mb(highend_pfn - highstart_pfn)); } diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 1797ddf8cb69..8e4ecd7f4177 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -18,6 +18,7 @@ #include #include #include +#include /* * Some notes on processor bugs: diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 85f4399789a0..0f8a4060ab26 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -44,6 +44,7 @@ #include #include #include +#include /* Set if we find a B stepping CPU */ static int smp_b_stepping = 0; @@ -649,10 +650,11 @@ void __init smp_alloc_memory(void) void __init smp_store_cpu_info(int id) { - struct cpuinfo_x86 *c=&cpu_data[id]; + struct cpuinfo_x86 *c = cpu_data + id; *c = boot_cpu_data; c->pte_quick = 0; + c->pmd_quick = 0; c->pgd_quick = 0; c->pgtable_cache_sz = 0; identify_cpu(c); @@ -719,7 +721,7 @@ void __init setup_local_APIC(void) * Enable APIC */ value |= (1<<8); -#if 0 +#if 1 /* Enable focus processor (bit==0) */ value &= ~(1<<9); #else @@ -821,8 +823,7 @@ void __init init_smp_mappings(void) * could use the real zero-page, but it's safer * this way if some buggy code writes to this page ... */ - apic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)apic_phys, 0, PAGE_SIZE); + apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); apic_phys = __pa(apic_phys); } set_fixmap(FIX_APIC_BASE, apic_phys); @@ -837,8 +838,7 @@ void __init init_smp_mappings(void) if (smp_found_config) { ioapic_phys = mp_ioapics[i].mpc_apicaddr; } else { - ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)ioapic_phys, 0, PAGE_SIZE); + ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); ioapic_phys = __pa(ioapic_phys); } set_fixmap(idx,ioapic_phys); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f66f2363c331..ad713cf2dd9d 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -35,6 +35,7 @@ #include #include +#include #ifdef CONFIG_X86_VISWS_APIC #include diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 3fd5262ac5ed..5719ecaf17db 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include /* diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index b2a98859b7ca..618b36544ad1 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include extern void die(const char *,struct pt_regs *,long); diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 0cba81502d49..1ab6e68b3253 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -285,7 +286,6 @@ static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t #if CONFIG_X86_PAE if (pgd_none(*pgd)) { pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pmd, 0, PAGE_SIZE); pgd_val(*pgd) = __pa(pmd) + 0x1; if (pmd != pmd_offset(pgd, start)) BUG(); @@ -297,7 +297,6 @@ static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t for (; (j < PTRS_PER_PMD) && start; pmd++, j++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pte, 0, PAGE_SIZE); pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); if (pte != pte_offset(pmd, 0)) BUG(); @@ -327,7 +326,6 @@ static void __init pagetable_init(void) vaddr = i*PGDIR_SIZE; #if CONFIG_X86_PAE pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pmd, 0, PAGE_SIZE); pgd_val(*pgd) = __pa(pmd) + 0x1; #else pmd = (pmd_t *)pgd; @@ -352,7 +350,6 @@ static void __init pagetable_init(void) } pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pte, 0, PAGE_SIZE); pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); if (pte != pte_offset(pmd, 0)) @@ -412,7 +409,11 @@ void __init zap_low_mappings (void) * that case). */ for (i = 0; i < USER_PTRS_PER_PGD; i++) +#if CONFIG_X86_PAE + pgd_clear(swapper_pg_dir+i); +#else pgd_val(swapper_pg_dir[i]) = 0; +#endif flush_tlb_all(); } @@ -448,13 +449,23 @@ void __init paging_init(void) kmap_init(); #endif { - unsigned int zones_size[3]; - - zones_size[0] = virt_to_phys((char *)MAX_DMA_ADDRESS) - >> PAGE_SHIFT; - zones_size[1] = max_low_pfn - zones_size[0]; - zones_size[2] = highend_pfn - zones_size[0] - zones_size[1]; - + unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned int max_dma, high, low; + unsigned int align = (1 << (MAX_ORDER-1))-1; + + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + low = (max_low_pfn + align) & ~align; + high = (highend_pfn + align) & ~align; + + if (low < max_dma) + zones_size[ZONE_DMA] = low; + else { + zones_size[ZONE_DMA] = max_dma; + zones_size[ZONE_NORMAL] = low - max_dma; +#ifdef CONFIG_HIGHMEM + zones_size[ZONE_HIGHMEM] = high - low; +#endif + } free_area_init(zones_size); } return; @@ -533,15 +544,13 @@ static inline int page_is_ram (unsigned long pagenr) void __init mem_init(void) { - int codepages = 0; - int reservedpages = 0; - int datapages = 0; - int initpages = 0; -#ifdef CONFIG_HIGHMEM + int codesize, reservedpages, datasize, initsize; int tmp; if (!mem_map) BUG(); + +#ifdef CONFIG_HIGHMEM highmem_start_page = mem_map + highstart_pfn; /* cache the highmem_mapnr */ highmem_mapnr = highstart_pfn; @@ -557,6 +566,13 @@ void __init mem_init(void) /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem(); + reservedpages = 0; + for (tmp = 0; tmp < max_low_pfn; tmp++) + /* + * Only count reserved RAM pages + */ + if (page_is_ram(tmp) && PageReserved(mem_map+tmp)) + reservedpages++; #ifdef CONFIG_HIGHMEM for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { struct page *page = mem_map + tmp; @@ -573,19 +589,23 @@ void __init mem_init(void) } totalram_pages += totalhigh_pages; #endif + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), - codepages << (PAGE_SHIFT-10), + codesize >> 10, reservedpages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10), + datasize >> 10, + initsize >> 10, (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) ); #if CONFIG_X86_PAE if (!cpu_has_pae) - panic("cannot execute a PAE-enabled kernel on a PAE-incapable CPU!"); + panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!"); #endif if (boot_cpu_data.wp_works_ok < 0) test_wp_bit(); diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index 630d628cf045..431adb3c6ee1 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c @@ -10,6 +10,7 @@ #include #include +#include static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, unsigned long flags) diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 88d5b9739f68..e2ed170f8337 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -130,7 +130,7 @@ * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers * from Ben Galliart with * special help from Jeff Lightfoot - * + * * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives. diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 71fe66f5c268..bf8d57e9ce71 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -21,7 +21,7 @@ #include #include -#include +#include #ifdef CONFIG_SOUND void soundcore_init(void); diff --git a/drivers/net/setup.c b/drivers/net/setup.c index d70038767a21..7f931c48bc03 100644 --- a/drivers/net/setup.c +++ b/drivers/net/setup.c @@ -8,6 +8,7 @@ #include #include +extern int plip_init(void); extern int mkiss_init_ctrl_dev(void); extern int ppp_init(void); extern int slip_init_ctrl_dev(void); diff --git a/drivers/parport/Config.in b/drivers/parport/Config.in index 0ccc8050c26f..3297568f0f06 100644 --- a/drivers/parport/Config.in +++ b/drivers/parport/Config.in @@ -35,7 +35,7 @@ if [ "$CONFIG_PARPORT" != "n" ]; then else define_tristate CONFIG_PARPORT_ATARI n fi - if [ "$CONFIG_SBUS" = "y" ]; then + if [ "$CONFIG_SBUS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' Sparc hardware (EXPERIMENTAL)' CONFIG_PARPORT_SUNBPP $CONFIG_PARPORT else define_tristate CONFIG_PARPORT_SUNBPP n diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index 78375e844664..fa6ac5f6c53a 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -25,7 +25,6 @@ $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $ */ -#include #include /* It is senseless to set SG_ALL any higher than this - the performance diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index 3f31eb0872f3..75d4cf12f3f0 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -1,14 +1,10 @@ # # USB device configuration # -# NOTE NOTE NOTE! This is still considered extremely experimental. -# Right now hubs, mice and keyboards work - at least with UHCI. -# But that may be more a lucky coincidence than anything else.. -# mainmenu_option next_comment -comment 'USB drivers - not for the faint of heart' +comment 'Support for USB' -tristate 'Support for USB (EXPERIMENTAL!)' CONFIG_USB +tristate 'Support for USB' CONFIG_USB if [ ! "$CONFIG_USB" = "n" ]; then comment 'USB Controllers' dep_tristate ' UHCI (Intel PIIX4 and others) support' CONFIG_USB_UHCI \ diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5235070be36d..5191847f971b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -1,553 +1,119 @@ -# -# Makefile for the kernel video drivers. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now inherited from the -# parent makes.. -# - -L_TARGET := video.a -L_OBJS := -M_OBJS := -LX_OBJS := -MX_OBJS := -MOD_LIST_NAME := VIDEO_MODULES - -CONFIG_FBGEN_BUILTIN := -CONFIG_FBGEN_MODULE := - -# Frame Buffer Console - -ifeq ($(CONFIG_FB),y) - # Nasty trick to make sure all wanted stuff is linked in - O_TARGET = fbdev.o - L_OBJS += fbdev.o -endif - -ifeq ($(CONFIG_DUMMY_CONSOLE),y) - L_OBJS += dummycon.o -endif - -ifeq ($(CONFIG_PROM_CONSOLE),y) - L_OBJS += promcon.o promcon_tbl.o -endif - -ifeq ($(CONFIG_FB),y) - L_OBJS += fonts.o - OX_OBJS += fbcon.o fbcmap.o fbmem.o modedb.o - ifeq ($(CONFIG_FONT_8x8),y) - L_OBJS += font_8x8.o - endif - ifeq ($(CONFIG_FONT_8x16),y) - L_OBJS += font_8x16.o - endif - ifeq ($(CONFIG_FONT_SUN8x16),y) - L_OBJS += font_sun8x16.o - endif - ifeq ($(CONFIG_FONT_SUN12x22),y) - L_OBJS += font_sun12x22.o - endif - ifeq ($(CONFIG_FONT_6x11),y) - L_OBJS += font_6x11.o - endif - ifeq ($(CONFIG_FONT_ACORN_8x8),y) - L_OBJS += font_acorn_8x8.o - endif - ifeq ($(CONFIG_FONT_PEARL_8x8),y) - L_OBJS += font_pearl_8x8.o - endif -endif - -# Frame Buffer Devices - -ifeq ($(CONFIG_FB_ACORN),y) -L_OBJS += acornfb.o -else - ifeq ($(CONFIG_FB_ACORN),m) - M_OBJS += acornfb.o - endif -endif - -ifeq ($(CONFIG_FB_AMIGA),y) -L_OBJS += amifb.o -else - ifeq ($(CONFIG_FB_AMIGA),m) - M_OBJS += amifb.o - endif -endif - -ifeq ($(CONFIG_FB_PM2),y) -L_OBJS += pm2fb.o -CONFIG_FBGEN_BUILTIN = y -else - ifeq ($(CONFIG_FB_PM2),m) - M_OBJS += pm2fb.o - CONFIG_FBGEN_MODULE = y - endif -endif - -ifeq ($(CONFIG_FB_APOLLO),y) -L_OBJS += dnfb.o -endif - -ifeq ($(CONFIG_FB_Q40),y) -L_OBJS += q40fb.o -endif - -ifeq ($(CONFIG_FB_ATARI),y) -L_OBJS += atafb.o -else - ifeq ($(CONFIG_FB_ATARI),m) - M_OBJS += atafb.o - endif -endif - -ifeq ($(CONFIG_FB_ATY),y) -L_OBJS += atyfb.o -else - ifeq ($(CONFIG_FB_ATY),m) - M_OBJS += atyfb.o - endif -endif - -ifeq ($(CONFIG_FB_ATY128),y) -L_OBJS += aty128fb.o -endif - -ifeq ($(CONFIG_FB_IGA),y) -L_OBJS += igafb.o -endif - -ifeq ($(CONFIG_FB_CONTROL),y) -L_OBJS += controlfb.o -endif - -ifeq ($(CONFIG_FB_PLATINUM),y) -L_OBJS += platinumfb.o -endif - -ifeq ($(CONFIG_FB_VALKYRIE),y) -L_OBJS += valkyriefb.o -endif - -ifeq ($(CONFIG_FB_CT65550),y) -L_OBJS += chipsfb.o -endif - -ifeq ($(CONFIG_FB_CYBER),y) -L_OBJS += cyberfb.o -else - ifeq ($(CONFIG_FB_CYBER),m) - M_OBJS += cyberfb.o - endif -endif - -ifeq ($(CONFIG_FB_CYBER2000),y) -L_OBJS += cyber2000fb.o -else - ifeq ($(CONFIG_FB_CYBER2000),m) - M_OBJS += cyber2000fb.o - endif -endif - -ifeq ($(CONFIG_FB_SGIVW),y) -LX_OBJS += sgivwfb.o -else - ifeq ($(CONFIG_FB_SGIVW),m) - MX_OBJS += sgivwfb.o - endif -endif - -ifeq ($(CONFIG_FB_RIVA),y) -L_OBJS += rivafb.o riva_hw.o -endif - -ifeq ($(CONFIG_FB_3DFX),y) -L_OBJS += tdfxfb.o -endif - -ifeq ($(CONFIG_FB_MAC),y) -L_OBJS += macfb.o -endif - -ifeq ($(CONFIG_FB_HP300),y) -L_OBJS += hpfb.o -endif - -ifeq ($(CONFIG_FB_OF),y) -L_OBJS += offb.o macmodes.o -endif - -ifeq ($(CONFIG_FB_IMSTT),y) -L_OBJS += imsttfb.o -endif - -ifeq ($(CONFIG_FB_RETINAZ3),y) -L_OBJS += retz3fb.o -else - ifeq ($(CONFIG_FB_RETINAZ3),m) - M_OBJS += retz3fb.o - endif -endif - -ifeq ($(CONFIG_FB_CLGEN),y) -L_OBJS += clgenfb.o -CONFIG_FBGEN_BUILTIN = y -else - ifeq ($(CONFIG_FB_CLGEN),m) - M_OBJS += clgenfb.o - CONFIG_FBGEN_MODULE = y - endif -endif - -ifeq ($(CONFIG_FB_S3TRIO),y) -L_OBJS += S3triofb.o -else - ifeq ($(CONFIG_FB_S3TRIO),m) - M_OBJS += S3triofb.o - endif -endif - -ifeq ($(CONFIG_FB_TGA),y) -L_OBJS += tgafb.o -CONFIG_FBGEN_BUILTIN = y -else - ifeq ($(CONFIG_FB_TGA),m) - M_OBJS += tgafb.o - CONFIG_FBGEN_MODULE = y - endif -endif - -ifeq ($(CONFIG_FB_VESA),y) -L_OBJS += vesafb.o -endif - -ifeq ($(CONFIG_FB_VGA16),y) -L_OBJS += vga16fb.o -else - ifeq ($(CONFIG_FB_VGA16),m) - M_OBJS += vga16fb.o - endif -endif - -ifeq ($(CONFIG_FB_VIRGE),y) -L_OBJS += virgefb.o -else - ifeq ($(CONFIG_FB_VIRGE),m) - M_OBJS += virgefb.o - endif -endif - -ifdef CONFIG_FB_G364 -L_OBJS := $(L_OBJS) g364fb.o -endif - -ifdef CONFIG_FB_FM2 -L_OBJS := $(L_OBJS) fm2fb.o -endif - -ifeq ($(CONFIG_FB_SBUS),y) -L_OBJS += sbusfb.o - ifeq ($(CONFIG_FB_CREATOR),y) - L_OBJS += creatorfb.o - else - ifeq ($(CONFIG_FB_CREATOR),m) - M_OBJS += creatorfb.o - endif - endif - ifeq ($(CONFIG_FB_CGSIX),y) - L_OBJS += cgsixfb.o - else - ifeq ($(CONFIG_FB_CGSIX),m) - M_OBJS += cgsixfb.o - endif - endif - ifeq ($(CONFIG_FB_BWTWO),y) - L_OBJS += bwtwofb.o - else - ifeq ($(CONFIG_FB_BWTWO),m) - M_OBJS += bwtwofb.o - endif - endif - ifeq ($(CONFIG_FB_CGTHREE),y) - L_OBJS += cgthreefb.o - else - ifeq ($(CONFIG_FB_CGTHREE),m) - M_OBJS += cgthreefb.o - endif - endif - ifeq ($(CONFIG_FB_TCX),y) - L_OBJS += tcxfb.o - else - ifeq ($(CONFIG_FB_TCX),m) - M_OBJS += tcxfb.o - endif - endif - ifeq ($(CONFIG_FB_CGFOURTEEN),y) - L_OBJS += cgfourteenfb.o - else - ifeq ($(CONFIG_FB_CGFOURTEEN),m) - M_OBJS += cgfourteenfb.o - endif - endif - ifeq ($(CONFIG_FB_P9100),y) - L_OBJS += p9100fb.o - else - ifeq ($(CONFIG_FB_P9100),m) - M_OBJS += p9100fb.o - endif - endif - ifeq ($(CONFIG_FB_LEO),y) - L_OBJS += leofb.o - else - ifeq ($(CONFIG_FB_LEO),m) - M_OBJS += leofb.o - endif - endif -else - ifeq ($(CONFIG_FB_SBUS),m) - M_OBJS += sbusfb.o - ifeq ($(CONFIG_FB_CREATOR),y) - M_OBJS += creatorfb.o - else - ifeq ($(CONFIG_FB_CREATOR),m) - M_OBJS += creatorfb.o - endif - endif - ifeq ($(CONFIG_FB_CGSIX),y) - M_OBJS += cgsixfb.o - else - ifeq ($(CONFIG_FB_CGSIX),m) - M_OBJS += cgsixfb.o - endif - endif - ifeq ($(CONFIG_FB_BWTWO),y) - M_OBJS += bwtwofb.o - else - ifeq ($(CONFIG_FB_BWTWO),m) - M_OBJS += bwtwofb.o - endif - endif - ifeq ($(CONFIG_FB_CGTHREE),y) - M_OBJS += cgthreefb.o - else - ifeq ($(CONFIG_FB_CGTHREE),m) - M_OBJS += cgthreefb.o - endif - endif - ifeq ($(CONFIG_FB_TCX),y) - M_OBJS += tcxfb.o - else - ifeq ($(CONFIG_FB_TCX),m) - M_OBJS += tcxfb.o - endif - endif - ifeq ($(CONFIG_FB_CGFOURTEEN),y) - M_OBJS += cgfourteenfb.o - else - ifeq ($(CONFIG_FB_CGFOURTEEN),m) - M_OBJS += cgfourteenfb.o - endif - endif - ifeq ($(CONFIG_FB_P9100),y) - M_OBJS += p9100fb.o - else - ifeq ($(CONFIG_FB_P9100),m) - M_OBJS += p9100fb.o - endif - endif - ifeq ($(CONFIG_FB_LEO),y) - M_OBJS += leofb.o - else - ifeq ($(CONFIG_FB_LEO),m) - M_OBJS += leofb.o - endif - endif - endif -endif - -ifeq ($(CONFIG_FB_VIRTUAL),y) -L_OBJS += vfb.o -else - ifeq ($(CONFIG_FB_VIRTUAL),m) - M_OBJS += vfb.o - endif -endif - -ifdef CONFIG_FBGEN_BUILTIN -OX_OBJS += fbgen.o -else - ifdef CONFIG_FBGEN_MODULE - MX_OBJS += fbgen.o - endif -endif - -ifeq ($(CONFIG_FB_MATROX),y) -L_OBJS += matroxfb.o -else - ifeq ($(CONFIG_FB_MATROX),m) - M_OBJS += matroxfb.o - endif -endif +# Makefile for the Linux video drivers. +# 5 Aug 1999, James Simmons, +# Rewritten to use lists instead of if-statements. + +SUB_DIRS := +MOD_SUB_DIRS := +MOD_IN_SUB_DIRS := +ALL_SUB_DIRS := + +# All of the (potential) objects that export symbols. +# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. + +export-objs := fbmem.o fbcmap.o fbcon.o fbcon-afb.o fbcon-ilbm.o fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o fbcon-vga.o + +# Object file lists. +obj-y := +obj-m := +obj-n := +obj- := + +# Each configuration option enables a list of files. + +obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o +obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o vga_font.o +obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o +obj-$(CONFIG_VGA_CONSOLE) += vgacon.o +obj-$(CONFIG_MDA_CONSOLE) += mdacon.o + +obj-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o +obj-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o +obj-$(CONFIG_FONT_8x8) += font_8x8.o +obj-$(CONFIG_FONT_8x16) += font_8x16.o +obj-$(CONFIG_FONT_6x11) += font_6x11.o +obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o +obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o + +obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o fbcon.o fonts.o fbmon.o + +obj-$(CONFIG_FB_ACORN) += acornfb.o +obj-$(CONFIG_FB_AMIGA) += amifb.o +obj-$(CONFIG_FB_PM2) += pm2fb.o fbgen.o +obj-$(CONFIG_FB_APOLLO) += dnfb.o +obj-$(CONFIG_FB_Q40) += q40fb.o +obj-$(CONFIG_FB_ATARI) += atafb.o +obj-$(CONFIG_FB_ATY) += atyfb.o +obj-$(CONFIG_FB_ATY128) += aty128fb.o +obj-$(CONFIG_FB_IGA) += igafb.o +obj-$(CONFIG_FB_CONTROL) += controlfb.o +obj-$(CONFIG_FB_PLATINUM) += platinumfb.o +obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o +obj-$(CONFIG_FB_CT65550) += chipsfb.o +obj-$(CONFIG_FB_CYBER) += cyberfb.o +obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o +obj-$(CONFIG_FB_SGIVW) += sgivwfb.o +obj-$(CONFIG_FB_RIVA) += rivafb.o riva_hw.o +obj-$(CONFIG_FB_3DFX) += tdfxfb.o +obj-$(CONFIG_FB_MAC) += macfb.o +obj-$(CONFIG_FB_HP300) += hpfb.o +obj-$(CONFIG_FB_OF) += offb.o macmodes.o +obj-$(CONFIG_FB_IMSTT) += imsttfb.o +obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o +obj-$(CONFIG_FB_CLGEN) += clgenfb.o fbgen.o +obj-$(CONFIG_FB_S3TRIO) += S3triofb.o +obj-$(CONFIG_FB_TGA) += tgafb.o fbgen.o +obj-$(CONFIG_FB_VESA) += vesafb.o +obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o +obj-$(CONFIG_FB_VIRGE) += virgefb.o +obj-$(CONFIG_FB_G364) += g364fb.o +obj-$(CONFIG_FB_FM2) += fm2fb.o +obj-$(CONFIG_FB_CREATOR) += creatorfb.o sbusfb.o +obj-$(CONFIG_FB_CGSIX) += cgsixfb.o sbusfb.o +obj-$(CONFIG_FB_BWTWO) += bwtwofb.o sbusfb.o +obj-$(CONFIG_FB_CGTHREE) += cgthreefb.o sbusfb.o +obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o +obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o +obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o +obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o +obj-$(CONFIG_FB_MATROX) += matroxfb.o +obj-$(CONFIG_FB_VIRTUAL) += vfb.o # Generic Low Level Drivers -ifeq ($(CONFIG_FBCON_AFB),y) -OX_OBJS += fbcon-afb.o -else - ifeq ($(CONFIG_FBCON_AFB),m) - MX_OBJS += fbcon-afb.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB2),y) -OX_OBJS += fbcon-cfb2.o -else - ifeq ($(CONFIG_FBCON_CFB2),m) - MX_OBJS += fbcon-cfb2.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB4),y) -OX_OBJS += fbcon-cfb4.o -else - ifeq ($(CONFIG_FBCON_CFB4),m) - MX_OBJS += fbcon-cfb4.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB8),y) -OX_OBJS += fbcon-cfb8.o -else - ifeq ($(CONFIG_FBCON_CFB8),m) - MX_OBJS += fbcon-cfb8.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB16),y) -OX_OBJS += fbcon-cfb16.o -else - ifeq ($(CONFIG_FBCON_CFB16),m) - MX_OBJS += fbcon-cfb16.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB24),y) -OX_OBJS += fbcon-cfb24.o -else - ifeq ($(CONFIG_FBCON_CFB24),m) - MX_OBJS += fbcon-cfb24.o - endif -endif - -ifeq ($(CONFIG_FBCON_CFB32),y) -OX_OBJS += fbcon-cfb32.o -else - ifeq ($(CONFIG_FBCON_CFB32),m) - MX_OBJS += fbcon-cfb32.o - endif -endif - -ifeq ($(CONFIG_FBCON_ILBM),y) -OX_OBJS += fbcon-ilbm.o -else - ifeq ($(CONFIG_FBCON_ILBM),m) - MX_OBJS += fbcon-ilbm.o - endif -endif - -ifeq ($(CONFIG_FBCON_IPLAN2P2),y) -OX_OBJS += fbcon-iplan2p2.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P2),m) - MX_OBJS += fbcon-iplan2p2.o - endif -endif - -ifeq ($(CONFIG_FBCON_IPLAN2P4),y) -OX_OBJS += fbcon-iplan2p4.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P4),m) - MX_OBJS += fbcon-iplan2p4.o - endif -endif - -ifeq ($(CONFIG_FBCON_IPLAN2P8),y) -OX_OBJS += fbcon-iplan2p8.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P8),m) - MX_OBJS += fbcon-iplan2p8.o - endif -endif - -ifeq ($(CONFIG_FBCON_IPLAN2P16),y) -OX_OBJS += fbcon-iplan2p16.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P16),m) - MX_OBJS += fbcon-iplan2p16.o - endif -endif - -ifeq ($(CONFIG_FBCON_MAC),y) -OX_OBJS += fbcon-mac.o -else - ifeq ($(CONFIG_FBCON_MAC),m) - MX_OBJS += fbcon-mac.o - endif -endif - -ifeq ($(CONFIG_FBCON_MFB),y) -OX_OBJS += fbcon-mfb.o -else - ifeq ($(CONFIG_FBCON_MFB),m) - MX_OBJS += fbcon-mfb.o - endif -endif - -ifeq ($(CONFIG_FBCON_VGA_PLANES),y) -OX_OBJS += fbcon-vga-planes.o -else - ifeq ($(CONFIG_FBCON_VGA_PLANES),m) - MX_OBJS += fbcon-vga-planes.o - endif -endif +obj-$(CONFIG_FBCON_AFB) += fbcon-afb.o +obj-$(CONFIG_FBCON_CFB2) += fbcon-cfb2.o +obj-$(CONFIG_FBCON_CFB4) += fbcon-cfb4.o +obj-$(CONFIG_FBCON_CFB8) += fbcon-cfb8.o +obj-$(CONFIG_FBCON_CFB16) += fbcon-cfb16.o +obj-$(CONFIG_FBCON_CFB24) += fbcon-cfb24.o +obj-$(CONFIG_FBCON_CFB32) += fbcon-cfb32.o +obj-$(CONFIG_FBCON_ILBM) += fbcon-ilbm.o +obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o +obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o +obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o +obj-$(CONFIG_FBCON_IPLAN2P16) += fbcon-iplan2p16.o +obj-$(CONFIG_FBCON_MAC) += fbcon-mac.o +obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o +obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o -ifeq ($(CONFIG_FBCON_VGA),y) -OX_OBJS += fbcon-vga.o -else - ifeq ($(CONFIG_FBCON_VGA),m) - MX_OBJS += fbcon-vga.o - endif -endif +# Files that are both resident and modular: remove from modular. -# VGA Text Console +obj-m := $(filter-out $(obj-y), $(obj-m)) -ifdef CONFIG_VGA_CONSOLE -L_OBJS += vgacon.o -endif +# Take multi-part drivers out of obj-y and put components in. -# MDA Text Console +obj-y := $(filter-out $(list-multi), $(obj-y)) -ifeq ($(CONFIG_MDA_CONSOLE),y) -L_OBJS += mdacon.o -else - ifeq ($(CONFIG_MDA_CONSOLE),m) - M_OBJS += mdacon.o - endif -endif +# Translate to Rules.make lists. -# Newport Text Console +L_TARGET := video.a +# This is a nice idea but needs depmod altering +#MOD_LIST_NAME := VIDEO_MODULES -ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),y) -L_OBJS += newport_con.o vga_font.o -else - ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),m) - M_OBJS += newport_con.o vga_font.o - endif -endif +L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) +LX_OBJS := $(sort $(filter $(export-objs), $(obj-y))) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) include $(TOPDIR)/Rules.make diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 4bd6e8f7b1dd..568153a77674 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -674,39 +674,6 @@ fbmem_init(void) fb_drivers[i].init(); } - -int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, - const struct fb_info *fb_info) -{ -#if 0 - /* - * long long divisions .... $#%%#$ - */ - unsigned long long hpicos, vpicos; - const unsigned long long _1e12 = 1000000000000ULL; - const struct fb_monspecs *monspecs = &fb_info->monspecs; - - hpicos = (unsigned long long)htotal*(unsigned long long)pixclock; - vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos; - if (!vpicos) - return 0; - - if (monspecs->hfmin == 0) - return 1; - - if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 || - vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12) - return 0; -#endif - return 1; -} - -int fbmon_dpms(const struct fb_info *fb_info) -{ - return fb_info->monspecs.dpms; -} - - /* * Command line options */ diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c new file mode 100644 index 000000000000..42db1c2d318b --- /dev/null +++ b/drivers/video/fbmon.c @@ -0,0 +1,73 @@ +/* + * linux/drivers/video/fbmon.c + * + * Copyright (C) 1999 James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Notes: + * This code handles the different types of monitors that are out their. + * Most video cards for example can support a mode like 800x600 but fix + * frequency monitors can't. So the code here checks if the monitor can + * support the mode as well as the card can. Fbmonospecs takes on + * different meaning with different types of monitors. For multifrequency + * monitors fbmonospecs represents the range of frequencies the monitor + * can support. Only one fbmonospec needs to be allocated. The fbmonospecs + * pointer in fb_info points to this one. If you specific a mode that has + * timing greater than the allowed range then setting the video mode will + * fail. With multifrequency monitors you can set any mode you like as long + * as you have a programmable clock on the video card. + * With fixed frequency monitors you have only a SET of very narrow + * allowed frequency ranges. So for a fixed fequency monitor you have a + * array of fbmonospecs. The fbmonospecs in fb_info represents the + * monitor frequency for the CURRENT mode. If you change the mode and ask + * for fbmonospecs you will NOT get the same values as before. Note this + * is not true for multifrequency monitors where you do get the same + * fbmonospecs each time. Also the values in each fbmonospecs represent the + * very narrow frequency band for range. Well you can't have exactly the + * same frequencies from fixed monitor. So some tolerance is excepted. + * By DEFAULT all monitors are assumed fixed frequency since they are so + * easy to fry or screw up a mode with. Just try setting a 800x600 mode on + * one. After you boot you can run a simple program the tells what kind of + * monitor you have. If you have a multifrequency monitor then you can set + * any mode size you like as long as your video card has a programmable clock. + * By default also besides assuming you have a fixed frequency monitor it + * assumes the monitor only supports lower modes. This way for example you + * can't set a 1280x1024 mode on a fixed frequency monitor that can only + * support up to 1024x768. + * + */ +#include + +int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, + const struct fb_info *fb_info) +{ +#if 0 + /* + * long long divisions .... $#%%#$ + */ + unsigned long long hpicos, vpicos; + const unsigned long long _1e12 = 1000000000000ULL; + const struct fb_monspecs *monspecs = &fb_info->monspecs; + + hpicos = (unsigned long long)htotal*(unsigned long long)pixclock; + vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos; + if (!vpicos) + return 0; + + if (monspecs->hfmin == 0) + return 1; + + if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 || + vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12) + return 0; +#endif + return 1; +} + +int fbmon_dpms(const struct fb_info *fb_info) +{ + return fb_info->monspecs->dpms; +} diff --git a/fs/Config.in b/fs/Config.in index b15be4a0d54b..821f6c68e16f 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -12,14 +12,14 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS fi tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS -tristate 'Apple Macintosh filesystem support (EXPERIMENTAL)' CONFIG_HFS_FS -# msdos filesystems if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Apple Macintosh filesystem support (EXPERIMENTAL)' CONFIG_HFS_FS tristate 'BFS filesystem (read only) support (EXPERIMENTAL)' CONFIG_BFS_FS if [ "$CONFIG_BFS_FS" != "n" ]; then bool ' BFS filesystem write support (DANGEROUS)' CONFIG_BFS_FS_WRITE fi fi +# msdos filesystems tristate 'DOS FAT fs support' CONFIG_FAT_FS dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS dep_tristate ' UMSDOS: Unix-like filesystem on top of standard MSDOS filesystem' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index ca5d8e8cb446..45d21ff971c3 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -27,7 +27,7 @@ #include #include -#include +#include static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout_library(int fd); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 409806fbf7f4..70943239eb57 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include diff --git a/fs/exec.c b/fs/exec.c index a7ca3dfaa762..d26743c1548f 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #ifdef CONFIG_KMOD diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index 4ed7a9abe4e8..8ddba066de94 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -522,7 +522,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) if (!page) goto read_really; - ctl.cache = cache = (union ncp_dir_cache *) page_address(page); + ctl.cache = cache = (union ncp_dir_cache *) kmap(page); ctl.head = cache->head; if (!Page_Uptodate(page) || !ctl.head.eof) @@ -550,10 +550,10 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) ctl.page = ncp_get_cache_page(inode, ctl.ofs, 1); if (!ctl.page) goto invalid_cache; + ctl.cache = (union ncp_dir_cache *) + kmap(ctl.page); if (!Page_Uptodate(ctl.page)) goto invalid_cache; - ctl.cache = (union ncp_dir_cache *) - page_address(ctl.page); } while (ctl.idx < NCP_DIRCACHE_SIZE) { struct dentry *dent; @@ -575,6 +575,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) goto finished; } if (ctl.page) { + kunmap(ctl.page); SetPageUptodate(ctl.page); UnlockPage(ctl.page); page_cache_release(ctl.page); @@ -585,6 +586,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir) } invalid_cache: if (ctl.page) { + kunmap(ctl.page); UnlockPage(ctl.page); page_cache_release(ctl.page); ctl.page = NULL; @@ -614,12 +616,14 @@ read_really: ctl.head.eof = ctl.valid; finished: if (page) { + kunmap(page); cache->head = ctl.head; SetPageUptodate(page); UnlockPage(page); page_cache_release(page); } if (ctl.page) { + kunmap(ctl.page); SetPageUptodate(ctl.page); UnlockPage(ctl.page); page_cache_release(ctl.page); @@ -680,6 +684,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, if (ctl.idx >= NCP_DIRCACHE_SIZE) { if (ctl.page) { + kunmap(ctl.page); SetPageUptodate(ctl.page); UnlockPage(ctl.page); page_cache_release(ctl.page); @@ -690,7 +695,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, ctl.page = ncp_get_cache_page(inode, ctl.ofs, 0); if (ctl.page) ctl.cache = (union ncp_dir_cache *) - page_address(ctl.page); + kmap(ctl.page); } if (ctl.cache) { ctl.cache->dentry[ctl.idx] = newdent; diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 036e92e9378a..806c05d6e21f 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -43,10 +43,11 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, int bufsize; int pos; - page = alloc_page(GFP_KERNEL); + page = alloc_page(GFP_HIGHMEM); /* ncpfs has nothing against GFP_HIGHMEM + as long as recvmsg and memset works on it */ if (!page) return page; - pg_addr = page_address(page); + pg_addr = kmap(page); address &= PAGE_MASK; pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT); @@ -87,6 +88,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, if (already_read < PAGE_SIZE) memset((char*)(pg_addr + already_read), 0, PAGE_SIZE - already_read); + kunmap(page); return page; } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 149077fae1cd..d084b6e94a49 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -346,8 +346,9 @@ repeat: goto repeat; } + kmap(page); rd_args.fh = NFS_FH(dentry); - rd_res.buffer = (char *)page_address(page_cache); + rd_res.buffer = (char *)page_address(page); rd_res.bufsiz = PAGE_CACHE_SIZE; rd_res.cookie = *cookiep; do { @@ -365,6 +366,8 @@ repeat: goto error; SetPageUptodate(page); +unmap_out: + kunmap(page); unlock_out: UnlockPage(page); out: @@ -372,7 +375,7 @@ out: error: SetPageError(page); - goto unlock_out; + goto unmap_out; } /* Seek up to dirent assosciated with the passed in cookie, @@ -438,8 +441,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (!Page_Uptodate(page)) goto dirent_read_error; success: + kmap(page); filp->f_pos = nfs_do_filldir((__u32 *) page_address(page), filp->f_pos, dirent, filldir); + kunmap(page); page_cache_release(page); return 0; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index ab9b22683b8d..2028270fa2e7 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -171,7 +171,8 @@ static int nfs_write_one_page(struct file *file, struct page *page, unsigned lon { long status; - bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes); + bytes -= copy_from_user((u8*)kmap(page) + offset, buf, bytes); + kunmap(page); status = -EFAULT; if (bytes) { lock_kernel(); diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6b2e3d73a01c..f8d7040846aa 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -71,7 +71,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) { struct nfs_rreq rqst; unsigned long offset = page->index << PAGE_CACHE_SHIFT; - char *buffer = (char *) page_address(page); + char *buffer; int rsize = NFS_SERVER(inode)->rsize; int result, refresh = 0; int count = PAGE_SIZE; @@ -79,6 +79,12 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) dprintk("NFS: nfs_readpage_sync(%p)\n", page); + /* + * This works now because the socket layer never tries to DMA + * into this buffer directly. + */ + buffer = (char *) kmap(page); + do { if (count < rsize) rsize = count; @@ -116,6 +122,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) result = 0; io_error: + kunmap(page); UnlockPage(page); /* Note: we don't refresh if the call returned error */ if (refresh && result >= 0) @@ -152,6 +159,7 @@ nfs_readpage_result(struct rpc_task *task) fail++; dprintk("NFS: %d successful reads, %d failures\n", succ, fail); } + kunmap(page); UnlockPage(page); free_page(address); @@ -163,7 +171,7 @@ static inline int nfs_readpage_async(struct dentry *dentry, struct inode *inode, struct page *page) { - unsigned long address = page_address(page); + unsigned long address; struct nfs_rreq *req; int result = -1, flags; @@ -177,6 +185,7 @@ nfs_readpage_async(struct dentry *dentry, struct inode *inode, if (!req) goto out_defer; + address = kmap(page); /* Initialize request */ /* N.B. Will the dentry remain valid for life of request? */ nfs_readreq_setup(req, NFS_FH(dentry), page->index << PAGE_CACHE_SHIFT, @@ -200,6 +209,7 @@ out_defer: goto out; out_free: dprintk("NFS: failed to enqueue async READ request.\n"); + kunmap(page); kfree(req); goto out; } @@ -254,7 +264,7 @@ nfs_readpage(struct file *file, struct page *page) out_error: UnlockPage(page); out_free: - free_page(page_address(page)); + __free_page(page); out: unlock_kernel(); return error; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 1b1705ef2d23..7b522f58bb2d 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -80,6 +80,8 @@ repeat: goto repeat; } + kmap(page); + /* We place the length at the beginning of the page, * in host byte order, followed by the string. The * XDR response verification will NULL terminate it. @@ -91,6 +93,7 @@ repeat: goto error; SetPageUptodate(page); unlock_out: + kunmap(page); UnlockPage(page); out: return page; @@ -113,11 +116,12 @@ static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen) if (!Page_Uptodate(page)) goto readlink_read_error; success: - p = (u32 *) page_address(page); + p = (u32 *) kmap(page); len = *p++; if (len > buflen) len = buflen; copy_to_user(buffer, p, len); + kunmap(page); page_cache_release(page); return len; @@ -148,8 +152,9 @@ nfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) if (!Page_Uptodate(page)) goto followlink_read_error; success: - p = (u32 *) page_address(page); + p = (u32 *) kmap(page); result = lookup_dentry((char *) (p + 1), base, follow); + kunmap(page); page_cache_release(page); return result; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index abc048dc24a2..9a21edad7ffa 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -99,7 +99,7 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode, dentry->d_parent->d_name.name, dentry->d_name.name, count, page->index, offset); - buffer = (u8 *) page_address(page) + offset; + buffer = (u8 *) kmap(page) + offset; offset += page->index << PAGE_CACHE_SHIFT; do { @@ -132,6 +132,7 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode, } while (count); io_error: + kunmap(page); /* Note: we don't refresh if the call failed (fattr invalid) */ if (refresh && result >= 0) { /* See comments in nfs_wback_result */ @@ -314,6 +315,7 @@ create_write_request(struct file * file, struct page *page, unsigned int offset, wreq->wb_bytes = bytes; wreq->wb_count = 2; /* One for the IO, one for us */ + kmap(page); append_write_request(&NFS_WRITEBACK(inode), wreq); if (nr_write_requests++ > NFS_WRITEBACK_MAX*3/4) @@ -687,6 +689,7 @@ nfs_wback_result(struct rpc_task *task) if (WB_INVALIDATE(req)) ClearPageUptodate(page); + kunmap(page); __free_page(page); remove_write_request(&NFS_WRITEBACK(inode), req); nr_write_requests--; diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 885a7ce6b6e3..16cfb9a0aaf6 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -277,10 +277,6 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d return 1; /* halt enum */ } } - else - { - udf_debug("size=%d, nf_pos=%d, liu=%d, lfi=%d\n", size, nf_pos, liu, lfi); - } } } /* end while */ diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 20dbf9bb7e30..b8a94e8f57ea 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -84,7 +84,7 @@ Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size, } struct FileIdentDesc * -udf_fileident_read(struct inode *dir, int *nf_pos, +udf_fileident_read(struct inode *dir, loff_t *nf_pos, struct udf_fileident_bh *fibh, struct FileIdentDesc *cfi, lb_addr *bloc, Uint32 *extoffset, diff --git a/fs/udf/inode.c b/fs/udf/inode.c index a16cb18a751f..05e03def5dda 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -201,8 +201,8 @@ struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isd if (isdir) { struct udf_fileident_bh sfibh, dfibh; - int f_pos = UDF_I_EXT0OFFS(inode) >> 2; - int size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2; + loff_t f_pos = UDF_I_EXT0OFFS(inode) >> 2; + loff_t size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2; struct FileIdentDesc cfi, *sfi, *dfi; sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2; diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c index 2b68985f3e7d..0f763b5d10c4 100644 --- a/fs/udf/lowlevel.c +++ b/fs/udf/lowlevel.c @@ -123,7 +123,7 @@ udf_get_last_block(kdev_t dev, int *flags) BLKGETSIZE, (unsigned long) &lblock); - if (!ret && block != 0x7FFFFFFF) /* Hard Disk */ + if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */ { if (mult) lblock *= mult; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index ebe839797c21..ea921eeb3699 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -25,6 +25,8 @@ * */ +#include "udfdecl.h" + #if defined(__linux__) && defined(__KERNEL__) #include #include "udf_i.h" @@ -36,8 +38,6 @@ #include #endif -#include "udfdecl.h" - static inline int udf_match(int len, const char * const name, struct qstr *qs) { if (len != qs->len) @@ -333,10 +333,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, struct ustr unifilename; char name[UDF_NAME_LEN], fname[UDF_NAME_LEN]; int namelen; - int f_pos; + loff_t f_pos; int flen; char *nameptr; - int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2; + loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2; int nfidlen; Uint8 lfi; Uint16 liu; @@ -825,8 +825,8 @@ static int empty_dir(struct inode *dir) { struct FileIdentDesc *fi, cfi; struct udf_fileident_bh fibh; - int f_pos; - int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2; + loff_t f_pos; + loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2; int block; lb_addr bloc, eloc; Uint32 extoffset, elen, offset; diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 787c83d86528..48dec10c5a70 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -184,7 +184,7 @@ extern int udf_sync_file(struct file *, struct dentry *); /* directory.c */ extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *); -extern struct FileIdentDesc * udf_fileident_read(struct inode *, int *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **); +extern struct FileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **); #endif /* __KERNEL__ */ diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h index d17d108c73be..3b0f4c55b6c6 100644 --- a/include/asm-i386/highmem.h +++ b/include/asm-i386/highmem.h @@ -37,7 +37,20 @@ extern pte_t *pkmap_page_table; extern void kmap_init(void) __init; +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ #define PKMAP_BASE (0xff000000UL) +#ifdef CONFIG_X86_PAE +#define LAST_PKMAP 512 +#else +#define LAST_PKMAP 1024 +#endif +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) extern unsigned long FASTCALL(kmap_high(struct page *page)); extern void FASTCALL(kunmap_high(struct page *page)); diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h index 3f198d67e813..2c1633e15ec7 100644 --- a/include/asm-i386/io.h +++ b/include/asm-i386/io.h @@ -103,7 +103,6 @@ __OUTS(l) #ifdef __KERNEL__ -#include #include /* diff --git a/include/asm-i386/pgalloc-2level.h b/include/asm-i386/pgalloc-2level.h new file mode 100644 index 000000000000..4ff5ce3b7a11 --- /dev/null +++ b/include/asm-i386/pgalloc-2level.h @@ -0,0 +1,23 @@ +#ifndef _I386_PGALLOC_2LEVEL_H +#define _I386_PGALLOC_2LEVEL_H + +/* + * traditional i386 two-level paging, page table allocation routines: + */ + +extern __inline__ pmd_t *get_pmd_fast(void) +{ + return (pmd_t *)0; +} + +extern __inline__ void free_pmd_fast(pmd_t *pmd) { } +extern __inline__ void free_pmd_slow(pmd_t *pmd) { } + +extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) +{ + if (!pgd) + BUG(); + return (pmd_t *) pgd; +} + +#endif /* _I386_PGALLOC_2LEVEL_H */ diff --git a/include/asm-i386/pgalloc-3level.h b/include/asm-i386/pgalloc-3level.h new file mode 100644 index 000000000000..6e6bfdfe1aad --- /dev/null +++ b/include/asm-i386/pgalloc-3level.h @@ -0,0 +1,68 @@ +#ifndef _I386_PGALLOC_3LEVEL_H +#define _I386_PGALLOC_3LEVEL_H + +/* + * Intel Physical Address Extension (PAE) Mode - three-level page + * tables on PPro+ CPUs. Page-table allocation routines. + * + * Copyright (C) 1999 Ingo Molnar + */ + +extern __inline__ pmd_t *get_pmd_slow(void) +{ + pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL); + + if (ret) + memset(ret, 0, PAGE_SIZE); + return ret; +} + +extern __inline__ pmd_t *get_pmd_fast(void) +{ + unsigned long *ret; + + if ((ret = pmd_quicklist) != NULL) { + pmd_quicklist = (unsigned long *)(*ret); + ret[0] = 0; + pgtable_cache_size--; + } else + ret = (unsigned long *)get_pmd_slow(); + return (pmd_t *)ret; +} + +extern __inline__ void free_pmd_fast(pmd_t *pmd) +{ + *(unsigned long *)pmd = (unsigned long) pmd_quicklist; + pmd_quicklist = (unsigned long *) pmd; + pgtable_cache_size++; +} + +extern __inline__ void free_pmd_slow(pmd_t *pmd) +{ + free_page((unsigned long)pmd); +} + +extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) +{ + if (!pgd) + BUG(); + address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + if (pgd_none(*pgd)) { + pmd_t *page = get_pmd_fast(); + + if (!page) + page = get_pmd_slow(); + if (page) { + if (pgd_none(*pgd)) { + pgd_val(*pgd) = 1 + __pa(page); + __flush_tlb(); + return page + address; + } else + free_pmd_fast(page); + } else + return NULL; + } + return (pmd_t *)pgd_page(*pgd) + address; +} + +#endif /* _I386_PGALLOC_3LEVEL_H */ diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h new file mode 100644 index 000000000000..a82c5c081ada --- /dev/null +++ b/include/asm-i386/pgalloc.h @@ -0,0 +1,247 @@ +#ifndef _I386_PGALLOC_H +#define _I386_PGALLOC_H + +#include +#include +#include +#include + +#define pgd_quicklist (current_cpu_data.pgd_quick) +#define pmd_quicklist (current_cpu_data.pmd_quick) +#define pte_quicklist (current_cpu_data.pte_quick) +#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) + +#if CONFIG_X86_PAE +# include +#else +# include +#endif + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any. + */ + +extern __inline__ pgd_t *get_pgd_slow(void) +{ + pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL); + + if (ret) { +#if CONFIG_X86_PAE + int i; + for (i = 0; i < USER_PTRS_PER_PGD; i++) + __pgd_clear(ret + i); +#else + memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); +#endif + memcpy(ret + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + return ret; +} + +extern __inline__ pgd_t *get_pgd_fast(void) +{ + unsigned long *ret; + + if ((ret = pgd_quicklist) != NULL) { + pgd_quicklist = (unsigned long *)(*ret); + ret[0] = 0; + pgtable_cache_size--; + } else + ret = (unsigned long *)get_pgd_slow(); + return (pgd_t *)ret; +} + +extern __inline__ void free_pgd_fast(pgd_t *pgd) +{ + *(unsigned long *)pgd = (unsigned long) pgd_quicklist; + pgd_quicklist = (unsigned long *) pgd; + pgtable_cache_size++; +} + +extern __inline__ void free_pgd_slow(pgd_t *pgd) +{ + free_page((unsigned long)pgd); +} + +extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); +extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted); + +extern __inline__ pte_t *get_pte_fast(void) +{ + unsigned long *ret; + + if((ret = (unsigned long *)pte_quicklist) != NULL) { + pte_quicklist = (unsigned long *)(*ret); + ret[0] = ret[1]; + pgtable_cache_size--; + } + return (pte_t *)ret; +} + +extern __inline__ void free_pte_fast(pte_t *pte) +{ + *(unsigned long *)pte = (unsigned long) pte_quicklist; + pte_quicklist = (unsigned long *) pte; + pgtable_cache_size++; +} + +extern __inline__ void free_pte_slow(pte_t *pte) +{ + free_page((unsigned long)pte); +} + +#define pte_free_kernel(pte) free_pte_slow(pte) +#define pte_free(pte) free_pte_slow(pte) +#define pgd_free(pgd) free_pgd_slow(pgd) +#define pgd_alloc() get_pgd_fast() + +extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +{ + if (!pmd) + BUG(); + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t * page = (pte_t *) get_pte_fast(); + + if (!page) + return get_pte_kernel_slow(pmd, address); + pmd_val(*pmd) = _KERNPG_TABLE + __pa(page); + return page + address; + } + if (pmd_bad(*pmd)) { + __handle_bad_pmd_kernel(pmd); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + + if (pmd_none(*pmd)) + goto getnew; + if (pmd_bad(*pmd)) + goto fix; + return (pte_t *)pmd_page(*pmd) + address; +getnew: +{ + unsigned long page = (unsigned long) get_pte_fast(); + + if (!page) + return get_pte_slow(pmd, address); + pmd_val(*pmd) = _PAGE_TABLE + __pa(page); + return (pte_t *)page + address; +} +fix: + __handle_bad_pmd(pmd); + return NULL; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + * (In the PAE case we free the page.) + */ +#define pmd_free(pmd) free_pmd_slow(pmd) + +#define pmd_free_kernel pmd_free +#define pmd_alloc_kernel pmd_alloc + +extern int do_check_pgt_cache(int, int); + +extern inline void set_pgdir(unsigned long address, pgd_t entry) +{ + struct task_struct * p; + pgd_t *pgd; +#ifdef __SMP__ + int i; +#endif + + read_lock(&tasklist_lock); + for_each_task(p) { + if (!p->mm) + continue; + *pgd_offset(p->mm,address) = entry; + } + read_unlock(&tasklist_lock); +#ifndef __SMP__ + for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) + pgd[address >> PGDIR_SHIFT] = entry; +#else + /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can + modify pgd caches of other CPUs as well. -jj */ + for (i = 0; i < NR_CPUS; i++) + for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) + pgd[address >> PGDIR_SHIFT] = entry; +#endif +} + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * ..but the i386 has somewhat limited tlb flushing capabilities, + * and page-granular flushes are available only on i486 and up. + */ + +#ifndef __SMP__ + +#define flush_tlb() __flush_tlb() +#define flush_tlb_all() __flush_tlb() +#define local_flush_tlb() __flush_tlb() + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + if (mm == current->active_mm) + __flush_tlb(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long addr) +{ + if (vma->vm_mm == current->active_mm) + __flush_tlb_one(addr); +} + +static inline void flush_tlb_range(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + if (mm == current->active_mm) + __flush_tlb(); +} + +#else + +/* + * We aren't very clever about this yet - SMP could certainly + * avoid some global flushes.. + */ + +#include + +#define local_flush_tlb() \ + __flush_tlb() + +extern void flush_tlb_all(void); +extern void flush_tlb_current_task(void); +extern void flush_tlb_mm(struct mm_struct *); +extern void flush_tlb_page(struct vm_area_struct *, unsigned long); + +#define flush_tlb() flush_tlb_current_task() + +static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, unsigned long end) +{ + flush_tlb_mm(mm); +} + +#endif + +#endif /* _I386_PGALLOC_H */ diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h index 3ca3551d3179..23c688ce328b 100644 --- a/include/asm-i386/pgtable-2level.h +++ b/include/asm-i386/pgtable-2level.h @@ -42,19 +42,4 @@ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) return (pmd_t *) dir; } -extern __inline__ pmd_t *get_pmd_fast(void) -{ - return (pmd_t *)0; -} - -extern __inline__ void free_pmd_fast(pmd_t *pmd) { } -extern __inline__ void free_pmd_slow(pmd_t *pmd) { } - -extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) -{ - if (!pgd) - BUG(); - return (pmd_t *) pgd; -} - #endif /* _I386_PGTABLE_2LEVEL_H */ diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h index d9e813def315..51021a7ccee5 100644 --- a/include/asm-i386/pgtable-3level.h +++ b/include/asm-i386/pgtable-3level.h @@ -27,11 +27,11 @@ #define PTRS_PER_PTE 512 #define pte_ERROR(e) \ - printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e)) + printk("%s:%d: bad pte %p(%016Lx).\n", __FILE__, __LINE__, &(e), pte_val(e)) #define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %016Lx.\n", __FILE__, __LINE__, pmd_val(e)) + printk("%s:%d: bad pmd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pmd_val(e)) #define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %016Lx.\n", __FILE__, __LINE__, pgd_val(e)) + printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e)) /* * Subtle, in PAE mode we cannot have zeroes in the top level @@ -64,61 +64,4 @@ extern inline void pgd_clear (pgd_t * pgd) #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \ __pmd_offset(address)) -extern __inline__ pmd_t *get_pmd_slow(void) -{ - pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL); - - if (ret) - memset(ret, 0, PAGE_SIZE); - return ret; -} - -extern __inline__ pmd_t *get_pmd_fast(void) -{ - unsigned long *ret; - - if ((ret = pmd_quicklist) != NULL) { - pmd_quicklist = (unsigned long *)(*ret); - ret[0] = 0; - pgtable_cache_size--; - } else - ret = (unsigned long *)get_pmd_slow(); - return (pmd_t *)ret; -} - -extern __inline__ void free_pmd_fast(pmd_t *pmd) -{ - *(unsigned long *)pmd = (unsigned long) pmd_quicklist; - pmd_quicklist = (unsigned long *) pmd; - pgtable_cache_size++; -} - -extern __inline__ void free_pmd_slow(pmd_t *pmd) -{ - free_page((unsigned long)pmd); -} - -extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) -{ - if (!pgd) - BUG(); - address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = get_pmd_fast(); - - if (!page) - page = get_pmd_slow(); - if (page) { - if (pgd_none(*pgd)) { - pgd_val(*pgd) = 1 + __pa(page); - __flush_tlb(); - return page + address; - } else - free_pmd_fast(page); - } else - return NULL; - } - return (pmd_t *)pgd_page(*pgd) + address; -} - #endif /* _I386_PGTABLE_3LEVEL_H */ diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 9138abfc33c9..cec38b484709 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -27,19 +27,6 @@ extern pgd_t swapper_pg_dir[1024]; #define flush_page_to_ram(page) do { } while (0) #define flush_icache_range(start, end) do { } while (0) -/* - * TLB flushing: - * - * - flush_tlb() flushes the current mm struct TLBs - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(mm, start, end) flushes a range of pages - * - * ..but the i386 has somewhat limited tlb flushing capabilities, - * and page-granular flushes are available only on i486 and up. - */ - #define __flush_tlb() \ do { unsigned long tmpreg; __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3":"=r" (tmpreg) : :"memory"); } while (0) @@ -49,65 +36,9 @@ do { unsigned long tmpreg; __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3" #define __flush_tlb_one(addr) \ __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) #endif - -#ifndef __SMP__ - -#define flush_tlb() __flush_tlb() -#define flush_tlb_all() __flush_tlb() -#define local_flush_tlb() __flush_tlb() - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm == current->active_mm) - __flush_tlb(); -} - -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long addr) -{ - if (vma->vm_mm == current->active_mm) - __flush_tlb_one(addr); -} - -static inline void flush_tlb_range(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - if (mm == current->active_mm) - __flush_tlb(); -} - -#else - -/* - * We aren't very clever about this yet - SMP could certainly - * avoid some global flushes.. - */ - -#include - -#define local_flush_tlb() \ - __flush_tlb() -extern void flush_tlb_all(void); -extern void flush_tlb_current_task(void); -extern void flush_tlb_mm(struct mm_struct *); -extern void flush_tlb_page(struct vm_area_struct *, unsigned long); - -#define flush_tlb() flush_tlb_current_task() - -static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, unsigned long end) -{ - flush_tlb_mm(mm); -} - -#endif #endif /* !__ASSEMBLY__ */ -#define pgd_quicklist (current_cpu_data.pgd_quick) -#define pmd_quicklist (current_cpu_data.pmd_quick) -#define pte_quicklist (current_cpu_data.pte_quick) -#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) - /* * The Linux x86 paging architecture is 'compile-time dual-mode', it * implements both the traditional 2-level x86 page tables and the @@ -247,7 +178,8 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd); * Permanent address of a page. Obviously must never be * called on a highmem page. */ -#define page_address(page) ({ if (PageHighMem(page)) BUG(); PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT); }) +#define page_address(page) ({ if (!(page)->virtual) BUG(); (page)->virtual; }) +#define __page_address(page) ({ if (PageHighMem(page)) BUG(); PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT); }) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) #define pte_page(x) (mem_map+pte_pagenr(x)) @@ -277,14 +209,14 @@ extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pt * and a page entry and page directory to the page they refer to. */ -extern inline pte_t mk_pte(struct page *page, pgprot_t pgprot) -{ - pte_t __pte; - - pte_val(__pte) = (page-mem_map)*(unsigned long long)PAGE_SIZE + - pgprot_val(pgprot); - return __pte; -} +#define mk_pte(page,pgprot) \ +({ \ + pte_t __pte; \ + \ + pte_val(__pte) = ((page)-mem_map)*(unsigned long long)PAGE_SIZE + \ + pgprot_val(pgprot); \ + __pte; \ +}) /* This takes a physical page address that is used by the remapping functions */ #define mk_pte_phys(physpage, pgprot) \ @@ -316,183 +248,11 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \ __pte_offset(address)) -/* - * Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on ASN bits - * if any. - */ - -extern __inline__ pgd_t *get_pgd_slow(void) -{ - pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL); - - if (ret) { -#if 0 - /* - * On PAE allocating a whole page is overkill - we will - * either embedd this in mm_struct, or do a SLAB cache. - */ - memcpy(ret, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t)); -#endif -#if CONFIG_X86_PAE - int i; - for (i = 0; i < USER_PTRS_PER_PGD; i++) - __pgd_clear(ret + i); -#else - memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -#endif - memcpy(ret + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - } - return ret; -} - -extern __inline__ pgd_t *get_pgd_fast(void) -{ - unsigned long *ret; - - if ((ret = pgd_quicklist) != NULL) { - pgd_quicklist = (unsigned long *)(*ret); - ret[0] = 0; - pgtable_cache_size--; - } else - ret = (unsigned long *)get_pgd_slow(); - return (pgd_t *)ret; -} - -extern __inline__ void free_pgd_fast(pgd_t *pgd) -{ - *(unsigned long *)pgd = (unsigned long) pgd_quicklist; - pgd_quicklist = (unsigned long *) pgd; - pgtable_cache_size++; -} - -extern __inline__ void free_pgd_slow(pgd_t *pgd) -{ - free_page((unsigned long)pgd); -} - -extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted); -extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted); - -extern __inline__ pte_t *get_pte_fast(void) -{ - unsigned long *ret; - - if((ret = (unsigned long *)pte_quicklist) != NULL) { - pte_quicklist = (unsigned long *)(*ret); - ret[0] = ret[1]; - pgtable_cache_size--; - } - return (pte_t *)ret; -} - -extern __inline__ void free_pte_fast(pte_t *pte) -{ - *(unsigned long *)pte = (unsigned long) pte_quicklist; - pte_quicklist = (unsigned long *) pte; - pgtable_cache_size++; -} - -extern __inline__ void free_pte_slow(pte_t *pte) -{ - free_page((unsigned long)pte); -} - -#define pte_free_kernel(pte) free_pte_slow(pte) -#define pte_free(pte) free_pte_slow(pte) -#define pgd_free(pgd) free_pgd_slow(pgd) -#define pgd_alloc() get_pgd_fast() - -extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) -{ - if (!pmd) - BUG(); - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t * page = (pte_t *) get_pte_fast(); - - if (!page) - return get_pte_kernel_slow(pmd, address); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(page); - return page + address; - } - if (pmd_bad(*pmd)) { - __handle_bad_pmd_kernel(pmd); - return NULL; - } - return (pte_t *) pmd_page(*pmd) + address; -} - -extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) -{ - address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); - - if (pmd_none(*pmd)) - goto getnew; - if (pmd_bad(*pmd)) - goto fix; - return (pte_t *)pmd_page(*pmd) + address; -getnew: -{ - unsigned long page = (unsigned long) get_pte_fast(); - - if (!page) - return get_pte_slow(pmd, address); - pmd_val(*pmd) = _PAGE_TABLE + __pa(page); - return (pte_t *)page + address; -} -fix: - __handle_bad_pmd(pmd); - return NULL; -} - -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - * (In the PAE case we free the page.) - */ -#define pmd_free(pmd) free_pmd_slow(pmd) - -#define pmd_free_kernel pmd_free -#define pmd_alloc_kernel pmd_alloc - -extern int do_check_pgt_cache(int, int); - -extern inline void set_pgdir(unsigned long address, pgd_t entry) -{ - struct task_struct * p; - pgd_t *pgd; -#ifdef __SMP__ - int i; -#endif - - read_lock(&tasklist_lock); - for_each_task(p) { - if (!p->mm) - continue; - *pgd_offset(p->mm,address) = entry; - } - read_unlock(&tasklist_lock); -#ifndef __SMP__ - for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT] = entry; -#else - /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our callee, so we can - modify pgd caches of other CPUs as well. -jj */ - for (i = 0; i < NR_CPUS; i++) - for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd) - pgd[address >> PGDIR_SHIFT] = entry; -#endif -} - /* * The i386 doesn't have any external MMU info: the kernel page * tables contain all the necessary information. */ -extern inline void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ -} +#define update_mmu_cache(vma,address,pte) do { } while (0) /* Encode and de-code a swap entry */ #define SWP_TYPE(x) (((x).val >> 1) & 0x3f) diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index c789e769caca..9fd6df27e8ce 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -3,6 +3,7 @@ #include #include +#include /* * simple boot-time physical memory area allocator. diff --git a/include/linux/coda_proc.h b/include/linux/coda_proc.h index 7c4ca8a04688..99cee973f8a4 100644 --- a/include/linux/coda_proc.h +++ b/include/linux/coda_proc.h @@ -133,13 +133,13 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write, /* these functions are called to form the content of /proc/fs/coda/... files */ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, - int length, int dummy ); + int length); int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset, - int length, int dummy ); + int length); int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset, - int length, int dummy ); + int length); int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, - int length, int dummy ); + int length); #endif /* _CODA_PROC_H */ diff --git a/include/linux/fb.h b/include/linux/fb.h index 8c008b8de2ed..4bdbed5f74ce 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -408,18 +408,19 @@ extern int fbgen_switch(int con, struct fb_info *info); extern void fbgen_blank(int blank, struct fb_info *info); -/* drivers/char/fbmem.c */ +/* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(const struct fb_info *fb_info); -extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, - const struct fb_info *fb_info); -extern int fbmon_dpms(const struct fb_info *fb_info); - extern int num_registered_fb; extern struct fb_info *registered_fb[FB_MAX]; extern char con2fb_map[MAX_NR_CONSOLES]; +/* drivers/video/fbmon.c */ +extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, + const struct fb_info *fb_info); +extern int fbmon_dpms(const struct fb_info *fb_info); + /* drivers/video/fbcon.c */ extern struct display fb_display[MAX_NR_CONSOLES]; diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 4e8e98224681..1eb622eb2f10 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -2,8 +2,7 @@ #define _LINUX_HIGHMEM_H #include -#include -#include +#include #ifdef CONFIG_HIGHMEM @@ -24,7 +23,7 @@ extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig); extern inline unsigned int nr_free_highpages(void) { return 0; } #define prepare_highmem_swapout(page) page #define replace_with_highmem(page) page -#define kmap(page) page_address(page) +#define kmap(page) __page_address(page) #define kunmap(page) do { } while (0) #endif /* CONFIG_HIGHMEM */ diff --git a/include/linux/mm.h b/include/linux/mm.h index a62e7975fe9e..ddb92209d05a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -16,6 +16,7 @@ extern void * high_memory; extern int page_cluster; #include +#include #include /* @@ -118,6 +119,8 @@ typedef struct { unsigned long val; } swp_entry_t; +struct zone_struct; + /* * Try to keep the most commonly accessed fields in single cache lines * here (16 bytes or greater). This ordering should be particularly @@ -127,7 +130,6 @@ typedef struct { * is used for linear searches (eg. clock algorithm scans). */ typedef struct page { - /* these must be first (free area handling) */ struct list_head list; struct address_space *mapping; unsigned long index; @@ -139,6 +141,7 @@ typedef struct page { struct page **pprev_hash; struct buffer_head * buffers; unsigned long virtual; /* nonzero if kmapped */ + struct zone_struct *zone; } mem_map_t; #define get_page(p) atomic_inc(&(p)->count) @@ -283,19 +286,113 @@ typedef struct page { extern mem_map_t * mem_map; /* - * This is timing-critical - most of the time in getting a new page - * goes to clearing the page. If you want a page without the clearing - * overhead, just use __get_free_page() directly.. + * Free memory management - zoned buddy allocator. + */ + +#if CONFIG_AP1000 +/* the AP+ needs to allocate 8MB contiguous, aligned chunks of ram + for the ring buffers */ +#define MAX_ORDER 12 +#else +#define MAX_ORDER 10 +#endif + +typedef struct free_area_struct { + struct list_head free_list; + unsigned int * map; +} free_area_t; + +typedef struct zone_struct { + /* + * Commonly accessed fields: + */ + spinlock_t lock; + unsigned long offset; + unsigned long free_pages; + int low_on_memory; + unsigned long pages_low, pages_high; + + /* + * free areas of different sizes + */ + free_area_t free_area[MAX_ORDER]; + + /* + * rarely used fields: + */ + char * name; + unsigned long size; +} zone_t; + +#define ZONE_DMA 0 +#define ZONE_NORMAL 1 +#define ZONE_HIGHMEM 2 + +/* + * NUMA architectures will have more: + */ +#define MAX_NR_ZONES 3 + +/* + * One allocation request operates on a zonelist. A zonelist + * is a list of zones, the first one is the 'goal' of the + * allocation, the other zones are fallback zones, in decreasing + * priority. On NUMA we want to fall back on other CPU's zones + * as well. * - * We have two allocation namespaces - the *get*page*() variants - * return virtual kernel addresses to the allocated page(s), the - * alloc_page*() variants return 'struct page *'. + * Right now a zonelist takes up less than a cacheline. We never + * modify it apart from boot-up, and only a few indices are used, + * so despite the zonelist table being relatively big, the cache + * footprint of this construct is very small. + */ +typedef struct zonelist_struct { + zone_t * zones [MAX_NR_ZONES+1]; // NULL delimited + int gfp_mask; +} zonelist_t; + +#define NR_GFPINDEX 0x100 + +extern zonelist_t zonelists [NR_GFPINDEX]; + +/* + * There is only one page-allocator function, and two main namespaces to + * it. The alloc_page*() variants return 'struct page *' and as such + * can allocate highmem pages, the *get*page*() variants return + * virtual kernel addresses to the allocated page(s). */ -#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0) -#define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order)) -extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long order)); -extern struct page * FASTCALL(alloc_pages(int gfp_mask, unsigned long order)); -#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) +extern struct page * FASTCALL(__alloc_pages(zonelist_t *zonelist, unsigned long order)); + +extern inline struct page * alloc_pages(int gfp_mask, unsigned long order) +{ + /* temporary check. */ + if (zonelists[gfp_mask].gfp_mask != (gfp_mask)) + BUG(); + /* + * Gets optimized away by the compiler. + */ + if (order >= MAX_ORDER) + return NULL; + return __alloc_pages(zonelists+(gfp_mask), order); +} + +#define alloc_page(gfp_mask) \ + alloc_pages(gfp_mask, 0) + +extern inline unsigned long __get_free_pages (int gfp_mask, unsigned long order) +{ + struct page * page; + + page = alloc_pages(gfp_mask, order); + if (!page) + return 0; + return __page_address(page); +} + +#define __get_free_page(gfp_mask) \ + __get_free_pages((gfp_mask),0) + +#define __get_dma_pages(gfp_mask, order) \ + __get_free_pages((gfp_mask) | GFP_DMA,(order)) extern inline unsigned long get_zeroed_page(int gfp_mask) { @@ -312,11 +409,29 @@ extern inline unsigned long get_zeroed_page(int gfp_mask) */ #define get_free_page get_zeroed_page -/* memory.c & swap.c*/ +/* + * There is only one 'core' page-freeing function. + */ +extern void FASTCALL(__free_pages_ok(struct page * page, unsigned long order)); + +extern inline void __free_pages(struct page *page, unsigned long order) +{ + if (!put_page_testzero(page)) + return; + __free_pages_ok(page, order); +} + +#define __free_page(page) __free_pages(page, 0) + +extern inline void free_pages(unsigned long addr, unsigned long order) +{ + unsigned long map_nr = MAP_NR(addr); + + if (map_nr < max_mapnr) + __free_pages(mem_map + map_nr, order); +} #define free_page(addr) free_pages((addr),0) -extern int FASTCALL(free_pages(unsigned long addr, unsigned long order)); -extern int FASTCALL(__free_page(struct page *)); extern void show_free_areas(void); extern struct page * put_dirty_page(struct task_struct * tsk, struct page *page, @@ -398,7 +513,7 @@ extern void put_cached_page(unsigned long); #define GFP_DMA __GFP_DMA /* Flag - indicates that the buffer can be taken from high memory which is not - directly addressable by the kernel */ + permanently mapped by the kernel */ #define GFP_HIGHMEM __GFP_HIGHMEM @@ -447,7 +562,6 @@ extern struct vm_area_struct *find_extend_vma(struct task_struct *tsk, unsigned #define vmlist_modify_lock(mm) vmlist_access_lock(mm) #define vmlist_modify_unlock(mm) vmlist_access_unlock(mm) - #endif /* __KERNEL__ */ #endif diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 66b558627766..97a4b6200c86 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -13,6 +13,7 @@ #include #include +#include /* * The page cache can done in larger chunks than diff --git a/init/main.c b/init/main.c index c81acaeaa8ea..e7ab651139fa 100644 --- a/init/main.c +++ b/init/main.c @@ -479,7 +479,6 @@ asmlinkage void __init start_kernel(void) size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1; prof_buffer = (unsigned int *) alloc_bootmem(size); - memset(prof_buffer, 0, size); } kmem_cache_init(); diff --git a/kernel/fork.c b/kernel/fork.c index a90a6bc470ff..de0b59bac65d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 925f7aa37f0d..b6d502939e8e 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -92,10 +92,9 @@ EXPORT_SYMBOL(exit_fs); EXPORT_SYMBOL(exit_sighand); /* internal kernel memory management */ -EXPORT_SYMBOL(__get_free_pages); -EXPORT_SYMBOL(free_pages); -EXPORT_SYMBOL(alloc_pages); -EXPORT_SYMBOL(__free_page); +EXPORT_SYMBOL(__alloc_pages); +EXPORT_SYMBOL(__free_pages_ok); +EXPORT_SYMBOL(zonelists); EXPORT_SYMBOL(kmem_find_general_cachep); EXPORT_SYMBOL(kmem_cache_create); EXPORT_SYMBOL(kmem_cache_destroy); diff --git a/kernel/module.c b/kernel/module.c index 6f4ad977d846..0a7d5a42dfe3 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include /* diff --git a/mm/bootmem.c b/mm/bootmem.c index f5995516c2f4..270dfc8c99da 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -178,11 +178,11 @@ found: last_offset = offset+size; ret = phys_to_virt(last_pos*PAGE_SIZE + offset); } else { - size -= remaining_size; - areasize = (size+PAGE_SIZE-1)/PAGE_SIZE; + remaining_size = size - remaining_size; + areasize = (remaining_size+PAGE_SIZE-1)/PAGE_SIZE; ret = phys_to_virt(last_pos*PAGE_SIZE + offset); last_pos = start+areasize-1; - last_offset = size; + last_offset = remaining_size; } last_offset &= ~PAGE_MASK; } else { @@ -196,7 +196,7 @@ found: for (i = start; i < start+areasize; i++) if (test_and_set_bit(i, bootmem_map)) BUG(); - + memset(ret, 0, size); return ret; } diff --git a/mm/filemap.c b/mm/filemap.c index 3bb4d89deb9a..9cfe8f82a1f1 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/mm/highmem.c b/mm/highmem.c index f206026156e8..c97a61ece407 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -70,9 +70,9 @@ struct page * replace_with_highmem(struct page * page) return page; } - vaddr = kmap(page); + vaddr = kmap(highpage); copy_page((void *)vaddr, (void *)page_address(page)); - kunmap(page); + kunmap(highpage); /* Preserve the caching of the swap_entry. */ highpage->index = page->index; @@ -87,20 +87,6 @@ struct page * replace_with_highmem(struct page * page) return highpage; } -/* - * Right now we initialize only a single pte table. It can be extended - * easily, subsequent pte tables have to be allocated in one physical - * chunk of RAM. - */ -#ifdef CONFIG_X86_PAE -#define LAST_PKMAP 2048 -#else -#define LAST_PKMAP 4096 -#endif -#define LAST_PKMAP_MASK (LAST_PKMAP-1) -#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) -#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) - /* * Virtual_count is not a pure "count". * 0 means that it is not mapped, and has not been mapped @@ -135,7 +121,7 @@ static void flush_all_zero_pkmaps(void) pkmap_count[i] = 0; pte = pkmap_page_table[i]; if (pte_none(pte)) - continue; + BUG(); pte_clear(pkmap_page_table+i); page = pte_page(pte); page->virtual = 0; @@ -167,30 +153,27 @@ static unsigned long map_new_virtual(struct page *page) current->state = TASK_UNINTERRUPTIBLE; add_wait_queue(&pkmap_map_wait, &wait); spin_unlock(&kmap_lock); - // it's not quite possible to saturate the - // pkmap pool right now. - BUG(); schedule(); remove_wait_queue(&pkmap_map_wait, &wait); spin_lock(&kmap_lock); - } - /* Somebody else might have mapped it while we slept */ - if (page->virtual) - return page->virtual; + /* Somebody else might have mapped it while we slept */ + if (page->virtual) + return page->virtual; - /* Re-start */ - count = LAST_PKMAP; + /* Re-start */ + count = LAST_PKMAP; + } } vaddr = PKMAP_ADDR(last_pkmap_nr); pkmap_page_table[last_pkmap_nr] = mk_pte(page, kmap_prot); - /* * Subtle! For some reason if we dont do this TLB flush then * we get data corruption and weird behavior in dbench runs. * But invlpg this should not be necessery ... Any ideas? */ __flush_tlb_one(vaddr); + pkmap_count[last_pkmap_nr] = 1; page->virtual = vaddr; @@ -201,8 +184,6 @@ unsigned long kmap_high(struct page *page) { unsigned long vaddr; - if (!PageHighMem(page)) - BUG(); /* * For highmem pages, we can't trust "virtual" until * after we have the lock. diff --git a/mm/memory.c b/mm/memory.c index a4eb697173a6..4c82355daf16 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -39,14 +39,14 @@ #include #include #include -#include #include #include #include +#include +#include #include +#include -#include -#include unsigned long max_mapnr = 0; unsigned long num_physpages = 0; diff --git a/mm/mmap.c b/mm/mmap.c index 99e86653d12a..9ca811351db2 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -14,7 +14,7 @@ #include #include -#include +#include /* description of effects of mapping type and prot in current implementation. * this is due to the limited x86 page protection hardware. The expected diff --git a/mm/mprotect.c b/mm/mprotect.c index 4752806dea98..fd4249b1dafe 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -9,7 +9,7 @@ #include #include -#include +#include static inline void change_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, pgprot_t newprot) diff --git a/mm/mremap.c b/mm/mremap.c index 012ab79123b6..118aeac7bad6 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -11,7 +11,7 @@ #include #include -#include +#include extern int vm_enough_memory(long pages); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 95a2bc436fc5..99d730d97910 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -9,74 +9,25 @@ #include #include -#include #include #include #include -#include #include -#include #include -#include -#include /* for copy_to/from_user */ -#include - int nr_swap_pages = 0; int nr_lru_pages; LIST_HEAD(lru_cache); -/* - * Free area management - * - * The free_area_list arrays point to the queue heads of the free areas - * of different sizes - */ - -#if CONFIG_AP1000 -/* the AP+ needs to allocate 8MB contiguous, aligned chunks of ram - for the ring buffers */ -#define MAX_ORDER 12 -#else -#define MAX_ORDER 10 -#endif - -typedef struct free_area_struct { - struct list_head free_list; - unsigned int * map; -} free_area_t; - -#define ZONE_DMA 0 -#define ZONE_NORMAL 1 - -#ifdef CONFIG_HIGHMEM -# define ZONE_HIGHMEM 2 -# define NR_ZONES 3 -#else -# define NR_ZONES 2 -#endif - -typedef struct zone_struct { - spinlock_t lock; - unsigned long offset; - unsigned long size; - free_area_t free_area[MAX_ORDER]; - - unsigned long free_pages; - unsigned long pages_low, pages_high; - int low_on_memory; - char * name; -} zone_t; - -static zone_t zones[NR_ZONES] = +static zone_t zones [MAX_NR_ZONES] = { { name: "DMA" }, { name: "Normal" }, -#ifdef CONFIG_HIGHMEM { name: "HighMem" } -#endif }; +zonelist_t zonelists [NR_GFPINDEX]; + /* * Free_page() adds the page to the free lists. This is optimized for * fast normal cases (no error jumps taken normally). @@ -100,7 +51,7 @@ static zone_t zones[NR_ZONES] = /* * Temporary debugging check. */ -#define BAD_RANGE(zone,x) ((((x)-mem_map) < zone->offset) || (((x)-mem_map) >= zone->offset+zone->size)) +#define BAD_RANGE(zone,x) (((zone) != (x)->zone) || (((x)-mem_map) < (zone)->offset) || (((x)-mem_map) >= (zone)->offset+(zone)->size)) /* * Buddy system. Hairy. You really aren't expected to understand this @@ -108,43 +59,50 @@ static zone_t zones[NR_ZONES] = * Hint: -mask = 1+~mask */ -static inline void free_pages_ok (struct page *page, unsigned long map_nr, unsigned long order) +void __free_pages_ok (struct page *page, unsigned long order) { - struct free_area_struct *area; - unsigned long index, page_idx, mask, offset; - unsigned long flags; - struct page *buddy; + unsigned long index, page_idx, mask, flags; + free_area_t *area; + struct page *base; zone_t *zone; - int i; /* - * Which zone is this page belonging to. - * - * (NR_ZONES is low, and we do not want (yet) to introduce - * put page->zone, it increases the size of mem_map[] - * unnecesserily. This small loop is basically equivalent - * to the previous #ifdef jungle, speed-wise.) + * Subtle. We do not want to test this in the inlined part of + * __free_page() - it's a rare condition and just increases + * cache footprint unnecesserily. So we do an 'incorrect' + * decrement on page->count for reserved pages, but this part + * makes it safe. */ - i = NR_ZONES-1; - zone = zones + i; - for ( ; i >= 0; i--, zone--) - if (map_nr >= zone->offset) - break; + if (PageReserved(page)) + return; + + if (page-mem_map >= max_mapnr) + BUG(); + if (PageSwapCache(page)) + BUG(); + if (PageLocked(page)) + BUG(); + + zone = page->zone; mask = (~0UL) << order; - offset = zone->offset; - area = zone->free_area; - area += order; - page_idx = map_nr - zone->offset; - page_idx &= mask; + base = mem_map + zone->offset; + page_idx = page - base; + if (page_idx & ~mask) + BUG(); index = page_idx >> (1 + order); - mask = (~0UL) << order; + + area = zone->free_area + order; spin_lock_irqsave(&zone->lock, flags); zone->free_pages -= mask; while (mask + (1 << (MAX_ORDER-1))) { + struct page *buddy1, *buddy2; + + if (area >= zone->free_area + MAX_ORDER) + BUG(); if (!test_and_change_bit(index, area->map)) /* * the buddy page is still allocated. @@ -153,87 +111,52 @@ static inline void free_pages_ok (struct page *page, unsigned long map_nr, unsig /* * Move the buddy up one level. */ - buddy = mem_map + offset + (page_idx ^ -mask); - page = mem_map + offset + page_idx; - if (BAD_RANGE(zone,buddy)) + buddy1 = base + (page_idx ^ -mask); + buddy2 = base + page_idx; + if (BAD_RANGE(zone,buddy1)) BUG(); - if (BAD_RANGE(zone,page)) + if (BAD_RANGE(zone,buddy2)) BUG(); - memlist_del(&buddy->list); + memlist_del(&buddy1->list); mask <<= 1; area++; index >>= 1; page_idx &= mask; } - memlist_add_head(&mem_map[offset + page_idx].list, &area->free_list); + memlist_add_head(&(base + page_idx)->list, &area->free_list); spin_unlock_irqrestore(&zone->lock, flags); } -/* - * Some ugly macros to speed up __get_free_pages().. - */ #define MARK_USED(index, order, area) \ change_bit((index) >> (1+(order)), (area)->map) -#define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT)) - -int __free_page (struct page *page) -{ - if (!PageReserved(page) && put_page_testzero(page)) { - if (PageSwapCache(page)) - PAGE_BUG(page); - if (PageLocked(page)) - PAGE_BUG(page); - - free_pages_ok(page, page-mem_map, 0); - return 1; - } - return 0; -} - -int free_pages (unsigned long addr, unsigned long order) -{ - unsigned long map_nr = MAP_NR(addr); - - if (map_nr < max_mapnr) { - mem_map_t * map = mem_map + map_nr; - if (!PageReserved(map) && put_page_testzero(map)) { - if (PageSwapCache(map)) - PAGE_BUG(map); - if (PageLocked(map)) - PAGE_BUG(map); - free_pages_ok(map, map_nr, order); - return 1; - } - } - return 0; -} -static inline unsigned long EXPAND (zone_t *zone, struct page *map, unsigned long index, - int low, int high, struct free_area_struct * area) +static inline struct page * expand (zone_t *zone, struct page *page, + unsigned long index, int low, int high, free_area_t * area) { unsigned long size = 1 << high; while (high > low) { - if (BAD_RANGE(zone,map)) + if (BAD_RANGE(zone,page)) BUG(); area--; high--; size >>= 1; - memlist_add_head(&(map)->list, &(area)->free_list); + memlist_add_head(&(page)->list, &(area)->free_list); MARK_USED(index, high, area); index += size; - map += size; + page += size; } - set_page_count(map, 1); - return index; + if (BAD_RANGE(zone,page)) + BUG(); + return page; } static inline struct page * rmqueue (zone_t *zone, unsigned long order) { - struct free_area_struct * area = zone->free_area + order; - unsigned long curr_order = order, map_nr; + free_area_t * area = zone->free_area + order; + unsigned long curr_order = order; struct list_head *head, *curr; unsigned long flags; struct page *page; @@ -247,15 +170,17 @@ static inline struct page * rmqueue (zone_t *zone, unsigned long order) unsigned int index; page = memlist_entry(curr, struct page, list); + if (BAD_RANGE(zone,page)) + BUG(); memlist_del(curr); - map_nr = page - mem_map; - index = map_nr - zone->offset; + index = (page - mem_map) - zone->offset; MARK_USED(index, curr_order, area); zone->free_pages -= 1 << order; - map_nr = zone->offset + EXPAND(zone, page, index, order, curr_order, area); + + page = expand(zone, page, index, order, curr_order, area); spin_unlock_irqrestore(&zone->lock, flags); - page = mem_map + map_nr; + set_page_count(page, 1); if (BAD_RANGE(zone,page)) BUG(); return page; @@ -268,11 +193,14 @@ static inline struct page * rmqueue (zone_t *zone, unsigned long order) return NULL; } -static inline int balance_memory (zone_t *zone, int gfp_mask) +#define ZONE_BALANCED(zone) \ + (((zone)->free_pages > (zone)->pages_low) && (!(zone)->low_on_memory)) + +static inline int zone_balance_memory (zone_t *zone, int gfp_mask) { int freed; - if (zone->free_pages > zone->pages_low) { + if (zone->free_pages >= zone->pages_low) { if (!zone->low_on_memory) return 1; /* @@ -283,8 +211,16 @@ static inline int balance_memory (zone_t *zone, int gfp_mask) zone->low_on_memory = 0; return 1; } - } - zone->low_on_memory = 1; + } else + zone->low_on_memory = 1; + + /* + * In the atomic allocation case we only 'kick' the + * state machine, but do not try to free pages + * ourselves. + */ + if (!(gfp_mask & __GFP_WAIT)) + return 1; current->flags |= PF_MEMALLOC; freed = try_to_free_pages(gfp_mask); @@ -295,39 +231,96 @@ static inline int balance_memory (zone_t *zone, int gfp_mask) return 1; } -static inline struct page * __get_pages (zone_t *zone, unsigned int gfp_mask, - unsigned long order) +/* + * We are still balancing memory in a global way: + */ +static inline int balance_memory (int gfp_mask) { - struct page *page; + unsigned long free = nr_free_pages(); + static int low_on_memory = 0; + int freed; - if (order >= MAX_ORDER) - goto nopage; + if (free >= freepages.low) { + if (!low_on_memory) + return 1; + /* + * Simple hysteresis: exit 'low memory mode' if + * the upper limit has been reached: + */ + if (free >= freepages.high) { + low_on_memory = 0; + return 1; + } + } else + low_on_memory = 1; /* - * If anyone calls gfp from interrupts nonatomically then it - * will sooner or later tripped up by a schedule(). + * In the atomic allocation case we only 'kick' the + * state machine, but do not try to free pages + * ourselves. */ + if (!(gfp_mask & __GFP_WAIT)) + return 1; + + current->flags |= PF_MEMALLOC; + freed = try_to_free_pages(gfp_mask); + current->flags &= ~PF_MEMALLOC; + + if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH))) + return 0; + return 1; +} + +/* + * This is the 'heart' of the zoned buddy allocator: + */ +struct page * __alloc_pages (zonelist_t *zonelist, unsigned long order) +{ + zone_t **zone, *z; + struct page *page; + int gfp_mask; /* - * If this is a recursive call, we'd better - * do our best to just allocate things without - * further thought. - */ - if (!(current->flags & PF_MEMALLOC)) - if (!balance_memory(zone, gfp_mask)) - goto nopage; - /* + * (If anyone calls gfp from interrupts nonatomically then it + * will sooner or later tripped up by a schedule().) + * * We are falling back to lower-level zones if allocation - * in a higher zone fails. This assumes a hierarchical - * dependency between zones, which is true currently. If - * you need something else then move this loop outside - * this function, into the zone-specific allocator. + * in a higher zone fails. */ - do { - page = rmqueue(zone, order); - if (page) - return page; - } while (zone-- != zones) ; + zone = zonelist->zones; + gfp_mask = zonelist->gfp_mask; + for (;;) { + z = *(zone++); + if (!z) + break; + if (!z->size) + BUG(); + /* + * If this is a recursive call, we'd better + * do our best to just allocate things without + * further thought. + */ + if (!(current->flags & PF_MEMALLOC)) + /* + * fastpath + */ + if (!ZONE_BALANCED(z)) + goto balance; + /* + * This is an optimization for the 'higher order zone + * is empty' case - it can happen even in well-behaved + * systems, think the page-cache filling up all RAM. + * We skip over empty zones. (this is not exact because + * we do not take the spinlock and it's not exact for + * the higher order case, but will do it for most things.) + */ +ready: + if (z->free_pages) { + page = rmqueue(z, order); + if (page) + return page; + } + } /* * If we can schedule, do so, and make sure to yield. @@ -341,37 +334,14 @@ static inline struct page * __get_pages (zone_t *zone, unsigned int gfp_mask, nopage: return NULL; -} - -static inline zone_t * gfp_mask_to_zone (int gfp_mask) -{ - zone_t *zone; - -#if CONFIG_HIGHMEM - if (gfp_mask & __GFP_HIGHMEM) - zone = zones + ZONE_HIGHMEM; - else -#endif - if (gfp_mask & __GFP_DMA) - zone = zones + ZONE_DMA; - else - zone = zones + ZONE_NORMAL; - return zone; -} - -unsigned long __get_free_pages (int gfp_mask, unsigned long order) -{ - struct page *page; - - page = __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order); - if (!page) - return 0; - return page_address(page); -} -struct page * alloc_pages (int gfp_mask, unsigned long order) -{ - return __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order); +/* + * The main chunk of the balancing code is in this offline branch: + */ +balance: + if (!balance_memory(gfp_mask)) + goto nopage; + goto ready; } /* @@ -383,7 +353,7 @@ unsigned int nr_free_pages (void) zone_t *zone; sum = 0; - for (zone = zones; zone < zones+NR_ZONES; zone++) + for (zone = zones; zone < zones + MAX_NR_ZONES; zone++) sum += zone->free_pages; return sum; } @@ -420,8 +390,9 @@ void show_free_areas(void) unsigned type; printk("Free pages: %6dkB (%6dkB HighMem)\n", - nr_free_pages()<<(PAGE_SHIFT-10), - nr_free_highpages()<<(PAGE_SHIFT-10)); + nr_free_pages() << (PAGE_SHIFT-10), + nr_free_highpages() << (PAGE_SHIFT-10)); + printk("( Free: %d, lru_cache: %d (%d %d %d) )\n", nr_free_pages(), nr_lru_pages, @@ -429,25 +400,33 @@ void show_free_areas(void) freepages.low, freepages.high); - for (type = 0; type < NR_ZONES; type++) { + for (type = 0; type < MAX_NR_ZONES; type++) { + struct list_head *head, *curr; zone_t *zone = zones + type; - unsigned long total = 0; + unsigned long nr, total, flags; printk(" %s: ", zone->name); - for (order = 0; order < MAX_ORDER; order++) { - unsigned long i, nr; - - nr = 0; - for (i = 0; i < zone->size; i += 1<offset + i; - if (!page_count(page)) + + total = 0; + if (zone->size) { + spin_lock_irqsave(&zone->lock, flags); + for (order = 0; order < MAX_ORDER; order++) { + head = &(zone->free_area + order)->free_list; + curr = head; + nr = 0; + for (;;) { + curr = memlist_next(curr); + if (curr == head) + break; nr++; + } + total += nr * (1 << order); + printk("%lu*%lukB ", nr, + (PAGE_SIZE>>10) << order); } - total += nr * ((PAGE_SIZE>>10) << order); - printk("%lu*%lukB ", nr, (unsigned long)((PAGE_SIZE>>10) << order)); + spin_unlock_irqrestore(&zone->lock, flags); } - printk("= %lukB)\n", total); + printk("= %lukB)\n", total * (PAGE_SIZE>>10)); } #ifdef SWAP_CACHE_INFO @@ -455,6 +434,55 @@ void show_free_areas(void) #endif } +/* + * Builds allocation fallback zone lists. We are basically ready + * to do NUMA-allocations, only this function has to be modified + * and the zonelists array be made per-CPU. + */ +static inline void build_zonelists (void) +{ + int i, j, k; + + for (i = 0; i < NR_GFPINDEX; i++) { + zonelist_t *zonelist; + zone_t *zone; + + zonelist = zonelists + i; + memset(zonelist, 0, sizeof(*zonelist)); + + zonelist->gfp_mask = i; + j = 0; + k = ZONE_NORMAL; + if (i & __GFP_HIGHMEM) + k = ZONE_HIGHMEM; + if (i & __GFP_DMA) + k = ZONE_DMA; + + switch (k) { + default: + BUG(); + /* + * fallthrough: + */ + case ZONE_HIGHMEM: + zone = zones + ZONE_HIGHMEM; + if (zone->size) { +#ifndef CONFIG_HIGHMEM + BUG(); +#endif + zonelist->zones[j++] = zone; + } + case ZONE_NORMAL: + zone = zones + ZONE_NORMAL; + if (zone->size) + zonelist->zones[j++] = zone; + case ZONE_DMA: + zonelist->zones[j++] = zones + ZONE_DMA; + } + zonelist->zones[j++] = NULL; + } +} + #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1)) /* @@ -465,14 +493,18 @@ void show_free_areas(void) */ void __init free_area_init(unsigned int *zones_size) { - mem_map_t * p; + struct page * p; unsigned long i, j; unsigned long map_size; unsigned int totalpages, offset; totalpages = 0; - for (i = 0; i < NR_ZONES; i++) - totalpages += zones_size[i]; + for (i = 0; i < MAX_NR_ZONES; i++) { + unsigned long size = zones_size[i]; + if (size & ((1 << MAX_ORDER)-1)) + BUG(); + totalpages += size; + } printk("totalpages: %08x\n", totalpages); i = totalpages >> 7; @@ -498,7 +530,6 @@ void __init free_area_init(unsigned int *zones_size) */ map_size = totalpages*sizeof(struct page); mem_map = (struct page *) alloc_bootmem(map_size); - memset(mem_map, 0, map_size); /* * Initially all pages are reserved - free ones are freed @@ -514,31 +545,50 @@ void __init free_area_init(unsigned int *zones_size) } offset = 0; - for (j = 0; j < NR_ZONES; j++) { + for (j = 0; j < MAX_NR_ZONES; j++) { zone_t *zone = zones + j; unsigned long mask = -1; unsigned long size; size = zones_size[j]; + + printk("zone(%ld): %ld pages.\n", j, size); zone->size = size; + if (!size) + continue; + zone->offset = offset; - zone->pages_low = freepages.low; - zone->pages_high = freepages.high; + /* + * It's unnecessery to balance the high memory zone + */ + if (j != ZONE_HIGHMEM) { + zone->pages_low = freepages.low; + zone->pages_high = freepages.high; + } zone->low_on_memory = 0; + for (i = 0; i < size; i++) { + struct page *page = mem_map + offset + i; + page->zone = zone; + if (j != ZONE_HIGHMEM) + page->virtual = __page_address(page); + } + offset += size; for (i = 0; i < MAX_ORDER; i++) { unsigned long bitmap_size; - unsigned int * map; + memlist_init(&zone->free_area[i].free_list); mask += mask; size = (size + ~mask) & mask; bitmap_size = size >> i; bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = LONG_ALIGN(bitmap_size); - map = (unsigned int *) alloc_bootmem(bitmap_size); - zone->free_area[i].map = map; - memset((void *) map, 0, bitmap_size); + zone->free_area[i].map = + (unsigned int *) alloc_bootmem(bitmap_size); } + if (zone->size != size) + BUG(); } + build_zonelists(); } diff --git a/mm/slab.c b/mm/slab.c index 7b8c74dc69c2..b477cb41362c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1043,20 +1043,12 @@ static int __kmem_cache_shrink(kmem_cache_t *cachep) int kmem_cache_shrink(kmem_cache_t *cachep) { - if (!cachep) { - printk(KERN_ERR "kmem_shrink: NULL ptr\n"); - return 2; - } - if (in_interrupt()) { - printk(KERN_ERR "kmem_shrink: Called during int - %s\n", cachep->c_name); - return 2; - } - - if (!is_chained_kmem_cache(cachep)) { - printk(KERN_ERR "kmem_shrink: Invalid cache addr %p\n", - cachep); - return 2; - } + if (!cachep) + BUG(); + if (in_interrupt()) + BUG(); + if (!is_chained_kmem_cache(cachep)) + BUG(); return __kmem_cache_shrink(cachep); } diff --git a/mm/vmalloc.c b/mm/vmalloc.c index cfe60ab4062c..1bf39183b238 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -9,6 +9,7 @@ #include #include +#include struct vm_struct * vmlist = NULL; diff --git a/mm/vmscan.c b/mm/vmscan.c index 14f5dc44482a..cf8f5fa35c9d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -20,7 +20,7 @@ #include #include -#include +#include /* * The swap-out functions return 1 if they successfully @@ -505,7 +505,6 @@ int kswapd(void *unused) allocations (not GFP_HIGHMEM ones). */ if (nr_free_buffer_pages() >= freepages.high) break; - if (!do_try_to_free_pages(GFP_KSWAPD)) break; run_task_queue(&tq_disk); diff --git a/net/irda/irproc.c b/net/irda/irproc.c index 5aca4d996900..ee142e9af597 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -41,7 +41,7 @@ extern int discovery_proc_read(char *buf, char **start, off_t offset, int len); struct irda_entry { char *name; - int (*fn)(char*, char**, off_t, int, int); + int (*fn)(char*, char**, off_t, int); }; struct proc_dir_entry *proc_irda; diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 61930fedefd6..dece3100dc26 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -197,21 +197,21 @@ int __init wanrouter_proc_init (void) if (!proc_router) goto fail; - p = proc_create_proc_entry("config",0,proc_router); + p = create_proc_entry("config",0,proc_router); if (!p) goto fail_config; p->ops = &router_inode; - p->info = config_get_info; - p = proc_create_proc_entry("status",0,proc_router); + p->get_info = config_get_info; + p = create_proc_entry("status",0,proc_router); if (!p) goto fail_stat; p->ops = &router_inode; - p->info = status_get_info; + p->get_info = status_get_info; return 0; fail_stat: remove_proc_entry("config", proc_router); fail_config: - remove_proc_entry(proc_net, ROUTER_NAME); + remove_proc_entry(ROUTER_NAME, proc_net); fail: return -ENOMEM; } -- 2.39.5