From cb431d5eea4fae7a444e7dc4501594a0b1560737 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Tue, 27 Jan 2004 06:25:47 -0500 Subject: head.S: Add comment for HdrS ver 0x201 --- arch/sparc64/kernel/head.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 830b2efa48cc..b381db233a0b 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -57,8 +57,9 @@ bootup_user_stack: /* History: * - * 0x0202 : Supports kernel params string * 0x0300 : Supports being located at other than 0x4000 + * 0x0202 : Supports kernel params string + * 0x0201 : Supports reboot_command */ .half 0x0300 /* HdrS version */ -- cgit v1.2.3 From 32e6f97a7af39145df5d2eba56d4bc96f1e3b95f Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Tue, 27 Jan 2004 11:23:02 -0500 Subject: [SPARC64]: Changes to accomodate booting from non-phys_base memory --- arch/sparc64/kernel/setup.c | 17 +++++++++++ arch/sparc64/mm/init.c | 69 ++++++++++++++++++++++++++------------------- include/asm-sparc64/io.h | 2 +- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index c6ec788fde48..0942d15e8065 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CONFIG_IP_PNP #include @@ -522,6 +523,22 @@ void __init setup_arch(char **cmdline_p) } pfn_base = phys_base >> PAGE_SHIFT; + switch (tlb_type) { + default: + case spitfire: + kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent()); + kern_base &= _PAGE_PADDR_SF; + break; + + case cheetah: + case cheetah_plus: + kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); + kern_base &= _PAGE_PADDR; + break; + }; + + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; + if (!root_flags) root_mountflags &= ~MS_RDONLY; ROOT_DEV = old_decode_dev(root_dev); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index b42699887bf3..dc0a51a93e8c 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -47,8 +47,19 @@ unsigned long *sparc64_valid_addr_bitmap; /* Ugly, but necessary... -DaveM */ unsigned long phys_base; +unsigned long kern_base; +unsigned long kern_size; unsigned long pfn_base; +/* This is even uglier. We have a problem where the kernel may not be + * located at phys_base. However, initial __alloc_bootmem() calls need to + * be adjusted to be within the 4-8Megs that the kernel is mapped to, else + * those page mappings wont work. Things are ok after inherit_prom_mappings + * is called though. Dave says he'll clean this up some other time. + * -- BenC + */ +static unsigned long bootmap_base; + /* get_new_mmu_context() uses "cache + 1". */ spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED; unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; @@ -433,7 +444,7 @@ static void inherit_prom_mappings(void) n += 5 * sizeof(struct linux_prom_translation); for (tsz = 1; tsz < n; tsz <<= 1) /* empty */; - trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL); + trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base); if (trans == NULL) { prom_printf("inherit_prom_mappings: Cannot alloc translations.\n"); prom_halt(); @@ -453,7 +464,7 @@ static void inherit_prom_mappings(void) * in inherit_locked_prom_mappings()). */ #define OBP_PMD_SIZE 2048 - prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, 0UL); + prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base); if (prompmd == NULL) early_pgtable_allocfail("pmd"); memset(prompmd, 0, OBP_PMD_SIZE); @@ -471,7 +482,7 @@ static void inherit_prom_mappings(void) if (pmd_none(*pmdp)) { ptep = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE, - 0UL); + bootmap_base); if (ptep == NULL) early_pgtable_allocfail("pte"); memset(ptep, 0, BASE_PAGE_SIZE); @@ -1327,15 +1338,8 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) * image. The kernel is hard mapped below PAGE_OFFSET in a * 4MB locked TLB translation. */ - start_pfn = PAGE_ALIGN((unsigned long) _end) - - ((unsigned long) KERNBASE); - - /* Adjust up to the physical address where the kernel begins. */ - start_pfn += phys_base; + start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT; - /* Now shift down to get the real physical page frame number. */ - start_pfn >>= PAGE_SHIFT; - bootmap_pfn = start_pfn; end_pfn = end_of_phys_memory >> PAGE_SHIFT; @@ -1365,11 +1369,13 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) min_low_pfn = pfn_base; #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx], bpfn[%lx], mlpfn[%lx])\n", - start_pfn, bootmap_pfn, max_low_pfn); + prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", + min_low_pfn, bootmap_pfn, max_low_pfn); #endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); + bootmap_base = bootmap_pfn << PAGE_SHIFT; + /* Now register the available physical memory with the * allocator. */ @@ -1378,8 +1384,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n", i, sp_banks[i].base_addr, sp_banks[i].num_bytes); #endif - free_bootmem(sp_banks[i].base_addr, - sp_banks[i].num_bytes); + free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); } #ifdef CONFIG_BLK_DEV_INITRD @@ -1395,12 +1400,11 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) } #endif /* Reserve the kernel text/data/bss. */ - size = (start_pfn << PAGE_SHIFT) - phys_base; #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", phys_base, size); + prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size); #endif - reserve_bootmem(phys_base, size); - *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; + reserve_bootmem(kern_base, kern_size); + *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT; /* Reserve the bootmem map. We do not account for it * in pages_avail because we will release that memory @@ -1429,7 +1433,7 @@ void __init paging_init(void) extern pmd_t swapper_pmd_dir[1024]; extern unsigned int sparc64_vpte_patchme1[1]; extern unsigned int sparc64_vpte_patchme2[1]; - unsigned long alias_base = phys_base + PAGE_OFFSET; + unsigned long alias_base = kern_base + PAGE_OFFSET; unsigned long second_alias_page = 0; unsigned long pt, flags, end_pfn, pages_avail; unsigned long shift = alias_base - ((unsigned long)KERNBASE); @@ -1449,7 +1453,7 @@ void __init paging_init(void) * if this were not true we wouldn't boot up to this point * anyways. */ - pt = phys_base | _PAGE_VALID | _PAGE_SZ4MB; + pt = kern_base | _PAGE_VALID | _PAGE_SZ4MB; pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; local_irq_save(flags); if (tlb_type == spitfire) { @@ -1543,7 +1547,16 @@ void __init paging_init(void) } inherit_locked_prom_mappings(1); - + +#ifdef CONFIG_SUN_SERIAL + /* This does not logically belong here, but we need to call it at + * the moment we are able to use the bootmem allocator. This _has_ + * to be done after the prom_mappings above so since + * __alloc_bootmem() doesn't work correctly until then. + */ + sun_serial_setup(); +#endif + /* We only created DTLB mapping of this stuff. */ spitfire_flush_dtlb_nucleus_page(alias_base); if (second_alias_page) @@ -1714,17 +1727,15 @@ void __init mem_init(void) i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i += 1; sparc64_valid_addr_bitmap = (unsigned long *) - __alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL); + __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base); if (sparc64_valid_addr_bitmap == NULL) { prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); prom_halt(); } memset(sparc64_valid_addr_bitmap, 0, i << 3); - addr = PAGE_OFFSET + phys_base; - last = PAGE_ALIGN((unsigned long)_end) - - ((unsigned long) KERNBASE); - last += PAGE_OFFSET + phys_base; + addr = PAGE_OFFSET + kern_base; + last = PAGE_ALIGN(kern_size) + addr; while (addr < last) { set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); addr += PAGE_SIZE; @@ -1764,7 +1775,7 @@ void __init mem_init(void) /* Put empty_pg_dir on pgd_quicklist */ extern pgd_t empty_pg_dir[1024]; unsigned long addr = (unsigned long)empty_pg_dir; - unsigned long alias_base = phys_base + PAGE_OFFSET - + unsigned long alias_base = kern_base + PAGE_OFFSET - (long)(KERNBASE); memset(empty_pg_dir, 0, sizeof(empty_pg_dir)); @@ -1800,7 +1811,7 @@ void free_initmem (void) struct page *p; page = (addr + - ((unsigned long) __va(phys_base)) - + ((unsigned long) __va(kern_base)) - ((unsigned long) KERNBASE)); p = virt_to_page(page); diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h index 4cf6e15170f0..0745a2349ace 100644 --- a/include/asm-sparc64/io.h +++ b/include/asm-sparc64/io.h @@ -19,7 +19,7 @@ extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr); #define bus_to_virt bus_to_virt_not_defined_use_pci_map /* BIO layer definitions. */ -extern unsigned long phys_base; +extern unsigned long phys_base, kern_base, kern_size; #define page_to_phys(page) ((((page) - mem_map) << PAGE_SHIFT)+phys_base) #define BIO_VMERGE_BOUNDARY 8192 -- cgit v1.2.3 From 4b887d8a3d4f6a1cf9d52f627023c3e38b5dd048 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Tue, 27 Jan 2004 11:25:15 -0500 Subject: [SPARC64]: Add _end and _start to list of sections --- include/asm-sparc64/sections.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-sparc64/sections.h b/include/asm-sparc64/sections.h index e6dcceabffb2..1e74d704d433 100644 --- a/include/asm-sparc64/sections.h +++ b/include/asm-sparc64/sections.h @@ -4,4 +4,6 @@ /* nothing to see, move along */ #include +extern char _end[], _start[]; + #endif -- cgit v1.2.3 From 865feb8275c470cbbd67b283d8b8ac3aa64954f4 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Tue, 27 Jan 2004 22:01:27 +0000 Subject: [ARM PATCH] 1744/1: SA Cerfboard/cube update (flash) Patch from Frank Becker Minor updates to cerf flash partitioning. --- drivers/mtd/maps/sa1100-flash.c | 50 ++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 9bfef0fbe8ac..3ffedfa6a32a 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -154,50 +154,34 @@ static struct mtd_partition badge4_partitions[] = { #ifdef CONFIG_SA1100_CERF #ifdef CONFIG_SA1100_CERF_FLASH_32MB -static struct mtd_partition cerf_partitions[] = { - { - .name = "firmware", - .size = 0x00040000, - .offset = 0, - }, { - .name = "params", - .size = 0x00040000, - .offset = 0x00040000, - }, { - .name = "kernel", - .size = 0x00100000, - .offset = 0x00080000, - }, { - .name = "rootdisk", - .size = 0x01E80000, - .offset = 0x00180000, - } -}; +# define CERF_FLASH_SIZE 0x02000000 #elif defined CONFIG_SA1100_CERF_FLASH_16MB +# define CERF_FLASH_SIZE 0x01000000 +#elif defined CONFIG_SA1100_CERF_FLASH_8MB +# define CERF_FLASH_SIZE 0x00800000 +#else +# error "Undefined flash size for CERF in sa1100-flash.c" +#endif + static struct mtd_partition cerf_partitions[] = { { - .name = "firmware", + .name = "Bootloader", .size = 0x00020000, - .offset = 0, + .offset = 0x00000000, }, { - .name = "params", - .size = 0x00020000, + .name = "Params", + .size = 0x00040000, .offset = 0x00020000, }, { - .name = "kernel", + .name = "Kernel", .size = 0x00100000, - .offset = 0x00040000, + .offset = 0x00060000, }, { - .name = "rootdisk", - .size = 0x00EC0000, - .offset = 0x00140000, + .name = "Filesystem", + .size = CERF_FLASH_SIZE-0x00160000, + .offset = 0x00160000, } }; -#elif defined CONFIG_SA1100_CERF_FLASH_8MB -# error "Unwritten type definition" -#else -# error "Undefined memory orientation for CERF in sa1100-flash.c" -#endif #endif #ifdef CONFIG_SA1100_CONSUS -- cgit v1.2.3 From 123c725fe78d1100d994c3da32014bacd2a0f220 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Tue, 27 Jan 2004 22:04:31 +0000 Subject: [ARM PATCH] 1747/1: MIssing export for cpufreq Patch from Frank Becker cpufreq compiled as module complains: *** Warning: "sa11x0_getspeed" [drivers/cpufreq/cpufreq_userspace.ko] undefined! --- arch/arm/mach-sa1100/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 40d882dc1d33..8d1f52ef0e89 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -99,6 +99,7 @@ unsigned int sa11x0_getspeed(void) { return cclk_frequency_100khz[PPCR & 0xf] * 100; } +EXPORT_SYMBOL(sa11x0_getspeed); #else /* * We still need to provide this so building without cpufreq works. -- cgit v1.2.3 From 741249e9d23875be721a78c2dc0ccd06897bb711 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Tue, 27 Jan 2004 22:07:35 +0000 Subject: [ARM PATCH] 1748/1: SA Cerfcube update (base+pcmica) Patch from Frank Becker Resubmit with updates according to review notes from 1701/1. --- arch/arm/configs/cerfcube_defconfig | 753 +++++++++++++++++------------------- arch/arm/mach-sa1100/cerf.c | 78 ++-- drivers/pcmcia/sa1100_cerf.c | 45 +-- include/asm-arm/arch-sa1100/cerf.h | 121 +----- 4 files changed, 450 insertions(+), 547 deletions(-) diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig index 2d06764504d9..58159ec6049b 100644 --- a/arch/arm/configs/cerfcube_defconfig +++ b/arch/arm/configs/cerfcube_defconfig @@ -2,66 +2,94 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y # # System Type # +# CONFIG_ARCH_ADIFCC is not set # CONFIG_ARCH_ANAKIN is not set -# CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y # CONFIG_ARCH_SHARK is not set # -# Archimedes/A5000 Implementations +# CLPS711X/EP721X Implementations # # -# Archimedes/A5000 Implementations (select only ONE) +# Epxa10db # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set # # Footbridge Implementations # -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set + +# +# IOP3xx Implementation Options +# +# CONFIG_ARCH_IOP310 is not set +# CONFIG_ARCH_IOP321 is not set + +# +# IOP3xx Chipset Features +# + +# +# Intel PXA250/210 Implementations +# # # SA11x0 Implementations # # CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set # CONFIG_SA1100_ADSBITSY is not set # CONFIG_SA1100_BRUTUS is not set CONFIG_SA1100_CERF=y @@ -69,13 +97,17 @@ CONFIG_SA1100_CERF=y CONFIG_SA1100_CERF_FLASH_16MB=y # CONFIG_SA1100_CERF_FLASH_32MB is not set # CONFIG_SA1100_CERF_CPLD is not set +# CONFIG_SA1100_H3100 is not set # CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set # CONFIG_SA1100_EXTENEX1 is not set # CONFIG_SA1100_FLEXANET is not set # CONFIG_SA1100_FREEBIRD is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set # CONFIG_SA1100_GRAPHICSMASTER is not set +# CONFIG_SA1100_BADGE4 is not set # CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HACKKIT is not set # CONFIG_SA1100_HUW_WEBPANEL is not set # CONFIG_SA1100_ITSY is not set # CONFIG_SA1100_LART is not set @@ -83,84 +115,81 @@ CONFIG_SA1100_CERF_FLASH_16MB=y # CONFIG_SA1100_OMNIMETER is not set # CONFIG_SA1100_PANGOLIN is not set # CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_PT_SYSTEM3 is not set +# CONFIG_SA1100_SHANNON is not set # CONFIG_SA1100_SHERMAN is not set # CONFIG_SA1100_SIMPAD is not set # CONFIG_SA1100_PFS168 is not set # CONFIG_SA1100_VICTOR is not set # CONFIG_SA1100_XP860 is not set # CONFIG_SA1100_YOPY is not set -CONFIG_SA1100_USB=y -CONFIG_SA1100_USB_NETLINK=y -CONFIG_SA1100_USB_CHAR=y +# CONFIG_SA1100_STORK is not set +# CONFIG_SA1100_SSP is not set +CONFIG_SA1100_USB=m +CONFIG_SA1100_USB_NETLINK=m +# CONFIG_SA1100_USB_CHAR is not set # -# CLPS711X/EP721X Implementations +# Processor Type # -# CONFIG_ARCH_CDB89712 is not set -# CONFIG_ARCH_CLEP7312 is not set -# CONFIG_ARCH_EDB7211 is not set -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_EP7211 is not set -# CONFIG_ARCH_EP7212 is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set +CONFIG_CPU_SA1100=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4=y +CONFIG_CPU_CACHE_V4WB=y +CONFIG_CPU_TLB_V4WB=y +CONFIG_CPU_MINICACHE=y # -# Processor Type +# Processor Features # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_CPU_SA1100=y -# CONFIG_ARM_THUMB is not set -CONFIG_DISCONTIGMEM=y # # General setup # -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_DISCONTIGMEM=y +CONFIG_ISA=y +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_SA1110=y +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_24_API=y CONFIG_HOTPLUG=y # # PCMCIA/CardBus support # -CONFIG_PCMCIA=y +CONFIG_PCMCIA=m +# CONFIG_PCMCIA_DEBUG is not set # CONFIG_I82365 is not set # CONFIG_TCIC is not set -# CONFIG_PCMCIA_CLPS6700 is not set -CONFIG_PCMCIA_SA1100=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y +CONFIG_PCMCIA_SA1100=m # # At least one math emulation must be selected # -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -# CONFIG_BINFMT_AOUT is not set +# CONFIG_FPE_NWFPE is not set +CONFIG_FPE_FASTFPE=y CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set -# CONFIG_PM is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set +CONFIG_PM=y +# CONFIG_PREEMPT is not set # CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="console=ttySA0 root=/dev/mtdblock3 rw mem=32M" -# CONFIG_PFS168_CMDLINE is not set +CONFIG_CMDLINE="console=ttySA0,38400 root=/dev/mtdblock3 rootfstype=jffs2 rw mem=32M init=/linuxrc" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -177,17 +206,19 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # # User Modules And Translation Layers # -CONFIG_MTD_CHAR=y +CONFIG_MTD_CHAR=m CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers @@ -198,6 +229,7 @@ CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -206,47 +238,25 @@ CONFIG_MTD_CFI_INTELEXT=y # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_TQM8XXL is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_SOLUTIONENGINE is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set -# CONFIG_MTD_L440GX is not set # CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_CDB89712 is not set CONFIG_MTD_SA1100=y -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set +# CONFIG_MTD_EDB7312 is not set # # Self-contained MTD device drivers # -# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_LART is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -254,24 +264,19 @@ CONFIG_MTD_SA1100=y # CONFIG_MTD_NAND is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -279,47 +284,52 @@ CONFIG_BLK_DEV_INITRD=y # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_FILTER=y CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set # +# SCTP Configuration (EXPERIMENTAL) # -# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -332,8 +342,9 @@ CONFIG_INET=y # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -344,45 +355,35 @@ CONFIG_NETDEVICES=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_CERF_CS8900A=y +# CONFIG_MII is not set +# CONFIG_SMC91X is not set +# CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set +CONFIG_NET_PCI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_CS8900=m # CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -390,13 +391,12 @@ CONFIG_CERF_CS8900A=y # Wireless LAN (non-hamradio) # # CONFIG_NET_RADIO is not set +# CONFIG_HOSTAP is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -407,17 +407,7 @@ CONFIG_CERF_CS8900A=y # # PCMCIA network device support # -CONFIG_NET_PCMCIA=y -# CONFIG_PCMCIA_3C589 is not set -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -CONFIG_PCMCIA_PCNET=m -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_ARCNET_COM20020_CS is not set -# CONFIG_PCMCIA_IBMTR is not set -# CONFIG_NET_PCMCIA_RADIO is not set +# CONFIG_NET_PCMCIA is not set # # Amateur Radio support @@ -430,113 +420,110 @@ CONFIG_PCMCIA_PCNET=m # CONFIG_IRDA is not set # -# ATA/IDE/MFM/RLL support +# Bluetooth support # -CONFIG_IDE=y +# CONFIG_BT is not set # -# IDE, ATA and ATAPI Block devices +# ATA/ATAPI/MFM/RLL support # +CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDEDISK=m # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # # CONFIG_SCSI is not set # # I2O device support # -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set # -# Input core support +# Input device support # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_TSLIBDEV is not set # CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -# CONFIG_SERIAL_ANAKIN is not set -# CONFIG_SERIAL_ANAKIN_CONSOLE is not set -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=9600 -# CONFIG_SERIAL_8250 is not set -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_MANY_PORTS is not set -# CONFIG_SERIAL_8250_SHARE_IRQ is not set -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_HUB6 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=32 -# CONFIG_UCB1200 is not set -# CONFIG_TOUCHSCREEN_UCB1200 is not set -# CONFIG_AUDIO_UCB1200 is not set -# CONFIG_ADC_UCB1200 is not set -# CONFIG_TOUCHSCREEN_H3600 is not set -# CONFIG_PROFILER is not set -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set # # I2C support @@ -544,56 +531,68 @@ CONFIG_UNIX98_PTY_COUNT=32 # CONFIG_I2C is not set # -# L3 serial bus support -# -# CONFIG_L3 is not set -# CONFIG_L3_ALGOBIT is not set -# CONFIG_L3_BIT_SA1100_GPIO is not set -# CONFIG_BIT_SA1100_UCB1200 is not set - -# -# Other L3 adapters +# I2C Algorithms # -# CONFIG_L3_SA1111 is not set # -# L3 driver support +# I2C Hardware Bus support # -# CONFIG_L3_DRV_UDA1341 is not set -# CONFIG_BIT_SA1100_GPIO is not set # -# Mice +# I2C Hardware Sensors Chip support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +# CONFIG_I2C_SENSOR is not set # -# Joysticks +# L3 serial bus support # -# CONFIG_INPUT_GAMEPORT is not set +CONFIG_L3=m # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_SA1100_WATCHDOG=m +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_SA1100_RTC=y +# CONFIG_GEN_RTC is not set +# CONFIG_SA1100_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -605,101 +604,142 @@ CONFIG_SA1100_RTC=y # # PCMCIA character devices # +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # File systems # -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m # CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_UMSDOS_FS=y -CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=y -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y +CONFIG_NFS_FS=m CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -# CONFIG_SMB_FS is not set +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +CONFIG_SMB_NLS=y CONFIG_NLS=y # # Native Language Support # CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -720,8 +760,9 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ISO8859_1=m # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -737,15 +778,16 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_UTF8 is not set # -# Console drivers +# Graphics support # -CONFIG_PC_KEYMAP=y -# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set # -# Frame-buffer support +# Console display driver support # -# CONFIG_FB is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # # Sound @@ -753,121 +795,52 @@ CONFIG_PC_KEYMAP=y # CONFIG_SOUND is not set # -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers +# Misc devices # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set -# CONFIG_USB_OHCI_SA1111 is not set # -# USB Device Class drivers +# Multimedia Capabilities Port drivers # -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set +# CONFIG_MCP is not set # -# USB Human Interface Devices (HID) +# Console Switches # +# CONFIG_SWITCHES is not set # -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers +# USB support # -# CONFIG_USB_USS720 is not set +# CONFIG_USB_GADGET is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Bluetooth support +# Cryptographic options # -# CONFIG_BT is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -# CONFIG_DEBUG_LL is not set -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index b56a7f601a68..00af122c4819 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -1,48 +1,61 @@ /* * linux/arch/arm/mach-sa1100/cerf.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Apr-2003 : Removed some old PDA crud [FB] + * Oct-2003 : Added uart2 resource [FB] + * Jan-2004 : Removed io map for flash [FB] */ + #include #include #include #include +#include #include #include #include +#include #include #include #include +#include #include "generic.h" +static struct resource cerfuart2_resources[] = { + [0] = { + .start = 0x80030000, + .end = 0x8003ffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device cerfuart2_device = { + .name = "sa11x0-uart", + .id = 2, + .num_resources = ARRAY_SIZE(cerfuart2_resources), + .resource = cerfuart2_resources, +}; + +static struct platform_device *cerf_devices[] __initdata = { + &cerfuart2_device, +}; static void __init cerf_init_irq(void) { sa1100_init_irq(); - - /* Need to register these as rising edge interrupts - * For standard 16550 serial driver support - * Basically - I copied it from pfs168.c :) - */ -#ifdef CONFIG_SA1100_CERF_CPLD - /* PDA Full serial port */ - set_irq_type(IRQ_GPIO3, IRQT_RISING); - /* PDA Bluetooth */ - set_irq_type(IRQ_GPIO2, IRQT_RISING); -#endif /* CONFIG_SA1100_CERF_CPLD */ - - set_irq_type(IRQ_GPIO_UCB1200_IRQ, IRQT_RISING); + set_irq_type(CERF_ETH_IRQ, IRQT_RISING); } static struct map_desc cerf_io_desc[] __initdata = { /* virtual physical length type */ { 0xf0000000, 0x08000000, 0x00100000, MT_DEVICE } /* Crystal Ethernet Chip */ -#ifdef CONFIG_SA1100_CERF_CPLD - ,{ 0xf1000000, 0x40000000, 0x00100000, MT_DEVICE }, /* CPLD Chip */ - { 0xf2000000, 0x10000000, 0x00100000, MT_DEVICE }, /* CerfPDA Bluetooth */ - { 0xf3000000, 0x18000000, 0x00100000, MT_DEVICE } /* CerfPDA Serial */ -#endif }; static void __init cerf_map_io(void) @@ -51,21 +64,30 @@ static void __init cerf_map_io(void) iotable_init(cerf_io_desc, ARRAY_SIZE(cerf_io_desc)); sa1100_register_uart(0, 3); -#ifdef CONFIG_SA1100_CERF_IRDA_ENABLED - sa1100_register_uart(1, 1); -#else - sa1100_register_uart(1, 2); + sa1100_register_uart(1, 2); /* disable this and the uart2 device for sa1100_fir */ sa1100_register_uart(2, 1); -#endif /* set some GPDR bits here while it's safe */ - GPDR |= GPIO_CF_RESET; -#ifdef CONFIG_SA1100_CERF_CPLD - GPDR |= GPIO_PWR_SHUTDOWN; -#endif + GPDR |= CERF_GPIO_CF_RESET; } -MACHINE_START(CERF, "Intrinsyc's Cerf Family of Products") +static int __init cerf_init(void) +{ + int ret; + + if (!machine_is_cerf()) + return -ENODEV; + + ret = platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); + if (ret < 0) + return ret; + + return 0; +} + +arch_initcall(cerf_init); + +MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") MAINTAINER("support@intrinsyc.com") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(cerf_map_io) diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index 1f22aa2da907..cd671b6ed418 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c @@ -11,27 +11,25 @@ #include #include #include +#include #include #include #include +#include #include "sa1100_generic.h" -#ifdef CONFIG_SA1100_CERF_CPLD -#define CERF_SOCKET 0 -#else #define CERF_SOCKET 1 -#endif static struct pcmcia_irqs irqs[] = { - { CERF_SOCKET, IRQ_GPIO_CF_CD, "CF_CD" }, - { CERF_SOCKET, IRQ_GPIO_CF_BVD2, "CF_BVD2" }, - { CERF_SOCKET, IRQ_GPIO_CF_BVD1, "CF_BVD1" } + { CERF_SOCKET, CERF_IRQ_GPIO_CF_CD, "CF_CD" }, + { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD2, "CF_BVD2" }, + { CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD1, "CF_BVD1" } }; static int cerf_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt) { - skt->irq = IRQ_GPIO_CF_IRQ; + skt->irq = CERF_IRQ_GPIO_CF_IRQ; return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } @@ -46,13 +44,13 @@ cerf_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state * { unsigned long levels = GPLR; - state->detect=((levels & GPIO_CF_CD)==0)?1:0; - state->ready=(levels & GPIO_CF_IRQ)?1:0; - state->bvd1=(levels & GPIO_CF_BVD1)?1:0; - state->bvd2=(levels & GPIO_CF_BVD2)?1:0; - state->wrprot=0; - state->vs_3v=1; - state->vs_Xv=0; + state->detect = (levels & CERF_GPIO_CF_CD) ?0:1; + state->ready = (levels & CERF_GPIO_CF_IRQ) ?1:0; + state->bvd1 = (levels & CERF_GPIO_CF_BVD1)?1:0; + state->bvd2 = (levels & CERF_GPIO_CF_BVD2)?1:0; + state->wrprot = 0; + state->vs_3v = 1; + state->vs_Xv = 0; } static int @@ -61,13 +59,8 @@ cerf_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, { switch (state->Vcc) { case 0: - break; - case 50: case 33: -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_PWR_SHUTDOWN; -#endif break; default: @@ -77,13 +70,9 @@ cerf_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, } if (state->flags & SS_RESET) { -#ifdef CONFIG_SA1100_CERF_CPLD - GPSR = GPIO_CF_RESET; -#endif + GPSR = CERF_GPIO_CF_RESET; } else { -#ifdef CONFIG_SA1100_CERF_CPLD - GPCR = GPIO_CF_RESET; -#endif + GPCR = CERF_GPIO_CF_RESET; } return 0; @@ -101,8 +90,8 @@ static void cerf_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt) static struct pcmcia_low_level cerf_pcmcia_ops = { .owner = THIS_MODULE, - .init = cerf_pcmcia_hw_init, - .shutdown = cerf_pcmcia_hw_shutdown, + .hw_init = cerf_pcmcia_hw_init, + .hw_shutdown = cerf_pcmcia_hw_shutdown, .socket_state = cerf_pcmcia_socket_state, .configure_socket = cerf_pcmcia_configure_socket, diff --git a/include/asm-arm/arch-sa1100/cerf.h b/include/asm-arm/arch-sa1100/cerf.h index 7bdc6a296f18..356d5ba88991 100644 --- a/include/asm-arm/arch-sa1100/cerf.h +++ b/include/asm-arm/arch-sa1100/cerf.h @@ -1,110 +1,29 @@ +/* + * include/asm-arm/arch-sa1100/cerf.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Apr-2003 : Removed some old PDA crud [FB] + */ #ifndef _INCLUDE_CERF_H_ #define _INCLUDE_CERF_H_ #include -#ifdef CONFIG_SA1100_CERF_CPLD +#define CERF_ETH_IO 0xf0000000 +#define CERF_ETH_IRQ IRQ_GPIO26 +#define CERF_GPIO_CF_BVD2 GPIO_GPIO (19) +#define CERF_GPIO_CF_BVD1 GPIO_GPIO (20) +#define CERF_GPIO_CF_RESET GPIO_GPIO (21) +#define CERF_GPIO_CF_IRQ GPIO_GPIO (22) +#define CERF_GPIO_CF_CD GPIO_GPIO (23) -// Map sa1100fb.c to sa1100_frontlight.c - Not pretty, but necessary. -#define CERF_BACKLIGHT_ENABLE sa1100_fl_enable -#define CERF_BACKLIGHT_DISABLE sa1100_fl_disable - -// -// IO Pins for devices -// - -#define CERF_PDA_CPLD 0xf1000000 -#define CERF_PDA_CPLD_WRCLRINT (0x0) -#define CERF_PDA_CPLD_BACKLIGHT (0x2) -#define CERF_PDA_CPLD_SOUND_FREQ (0x4) -#define CERF_PDA_CPLD_KEYPAD_A (0x6) -#define CERF_PDA_CPLD_BATTFAULT (0x8) -#define CERF_PDA_CPLD_KEYPAD_B (0xa) -#define CERF_PDA_CPLD_SOUND_ENA (0xc) -#define CERF_PDA_CPLD_SOUND_RESET (0xe) - -#define GPIO_CF_BVD2 GPIO_GPIO (5) -#define GPIO_CF_BVD1 GPIO_GPIO (6) -#define GPIO_CF_RESET GPIO_GPIO (7) -#define GPIO_CF_IRQ GPIO_GPIO (8) -#define GPIO_CF_CD GPIO_GPIO (9) - -#define GPIO_PWR_SHUTDOWN GPIO_GPIO (25) - -#define UCB1200_GPIO_CONT_CS 0x0001 -#define UCB1200_GPIO_CONT_DOWN 0x0002 -#define UCB1200_GPIO_CONT_INC 0x0004 -#define UCB1200_GPIO_CONT_ENA 0x0008 -#define UCB1200_GPIO_LCD_RESET 0x0010 -#define UCB1200_GPIO_IRDA_ENABLE 0x0020 -#define UCB1200_GPIO_BT_ENABLE 0x0040 -#define UCB1200_GPIO_L3_DATA 0x0080 -#define UCB1200_GPIO_L3_CLOCK 0x0100 -#define UCB1200_GPIO_L3_MODE 0x0200 - -// -// IRQ for devices -// - -#define IRQ_UCB1200_CONT_CS IRQ_UCB1200_IO0 -#define IRQ_UCB1200_CONT_DOWN IRQ_UCB1200_IO1 -#define IRQ_UCB1200_CONT_INC IRQ_UCB1200_IO2 -#define IRQ_UCB1200_CONT_ENA IRQ_UCB1200_IO3 -#define IRQ_UCB1200_LCD_RESET IRQ_UCB1200_IO4 -#define IRQ_UCB1200_IRDA_ENABLE IRQ_UCB1200_IO5 -#define IRQ_UCB1200_BT_ENABLE IRQ_UCB1200_IO6 -#define IRQ_UCB1200_L3_DATA IRQ_UCB1200_IO7 -#define IRQ_UCB1200_L3_CLOCK IRQ_UCB1200_IO8 -#define IRQ_UCB1200_L3_MODE IRQ_UCB1200_IO9 - -#define IRQ_GPIO_CF_BVD2 IRQ_GPIO5 -#define IRQ_GPIO_CF_BVD1 IRQ_GPIO6 -#define IRQ_GPIO_CF_IRQ IRQ_GPIO8 -#define IRQ_GPIO_CF_CD IRQ_GPIO9 - -// -// Device parameters -// - -#define CERF_PDA_CPLD_SOUND_FREQ_8000 (0x01) -#define CERF_PDA_CPLD_SOUND_FREQ_11025 (0x05) -#define CERF_PDA_CPLD_SOUND_FREQ_16000 (0x02) -#define CERF_PDA_CPLD_SOUND_FREQ_22050 (0x06) -#define CERF_PDA_CPLD_SOUND_FREQ_32000 (0x03) -#define CERF_PDA_CPLD_SOUND_FREQ_44100 (0x07) -#define CERF_PDA_CPLD_SOUND_FREQ_48000 (0x0b) - -// -// General Functions -// - -#define CERF_PDA_CPLD_Get(x, y) (*((char*)(CERF_PDA_CPLD + (x))) & (y)) -#define CERF_PDA_CPLD_Set(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) | (y)) -#define CERF_PDA_CPLD_UnSet(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) & ~(y)) - - -#else // CONFIG_SA1100_CERF_CPLD - - -#define GPIO_CF_BVD2 GPIO_GPIO (19) -#define GPIO_CF_BVD1 GPIO_GPIO (20) -#define GPIO_CF_RESET 0 -#define GPIO_CF_IRQ GPIO_GPIO (22) -#define GPIO_CF_CD GPIO_GPIO (23) - -#define GPIO_LCD_RESET GPIO_GPIO (15) - -#define IRQ_GPIO_CF_BVD2 IRQ_GPIO19 -#define IRQ_GPIO_CF_BVD1 IRQ_GPIO20 -#define IRQ_GPIO_CF_IRQ IRQ_GPIO22 -#define IRQ_GPIO_CF_CD IRQ_GPIO23 - - -#endif // CONFIG_SA1100_CERF_CPLD - - -#define GPIO_UCB1200_IRQ GPIO_GPIO (18) -#define IRQ_GPIO_UCB1200_IRQ IRQ_GPIO18 +#define CERF_IRQ_GPIO_CF_BVD2 IRQ_GPIO19 +#define CERF_IRQ_GPIO_CF_BVD1 IRQ_GPIO20 +#define CERF_IRQ_GPIO_CF_IRQ IRQ_GPIO22 +#define CERF_IRQ_GPIO_CF_CD IRQ_GPIO23 #endif // _INCLUDE_CERF_H_ -- cgit v1.2.3 From a28efa63b580ed14edc4f8a285380d562a341b68 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Tue, 27 Jan 2004 22:11:07 +0000 Subject: [ARM PATCH] 1749/1: Remove warnings in csumpartialcopygeneric.S Patch from Dirk Behme Remove the following warnings from csumpartialcopygeneric.S: arch/arm/lib/csumpartialcopygeneric.S: Assembler messages: arch/arm/lib/csumpartialcopygeneric.S:142: Warning: shift of 0 ignored. arch/arm/lib/csumpartialcopygeneric.S:216: Warning: shift of 0 ignored. arch/arm/lib/csumpartialcopygeneric.S:268: Warning: shift of 0 ignored. arch/arm/lib/csumpartialcopygeneric.S:322: Warning: shift of 0 ignored. arch/arm/lib/csumpartialcopygeneric.S:328: Warning: shift of 0 ignored. This new patch is reviewed by Nicolas Pitre. --- arch/arm/lib/csumpartial.S | 6 ++-- arch/arm/lib/csumpartialcopygeneric.S | 38 ++++++++++++------------ arch/arm/lib/io-readsb.S | 56 +++++++++++++++++------------------ arch/arm/lib/uaccess.S | 24 +++++++-------- include/asm-arm/assembler.h | 18 +++++++++-- 5 files changed, 78 insertions(+), 64 deletions(-) diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S index 25c05f35fd8d..c5515f3be0ad 100644 --- a/arch/arm/lib/csumpartial.S +++ b/arch/arm/lib/csumpartial.S @@ -41,7 +41,7 @@ td3 .req lr tst buf, #1 @ odd address? ldrneb td0, [buf], #1 subne len, len, #1 - adcnes sum, sum, td0, lsl #byte(1) + adcnes sum, sum, td0, put_byte_1 .less4: tst len, #6 beq .less8_byte @@ -68,7 +68,7 @@ td3 .req lr .less8_byte: tst len, #1 @ odd number of bytes ldrneb td0, [buf], #1 @ include last byte - adcnes sum, sum, td0, lsl #byte(0) @ update checksum + adcnes sum, sum, td0, put_byte_0 @ update checksum .done: adc r0, sum, #0 @ collect up the last carry ldr td0, [sp], #4 @@ -80,7 +80,7 @@ td3 .req lr .not_aligned: tst buf, #1 @ odd address ldrneb td0, [buf], #1 @ make even subne len, len, #1 - adcnes sum, sum, td0, lsl #byte(1) @ update checksum + adcnes sum, sum, td0, put_byte_1 @ update checksum tst buf, #2 @ 32-bit aligned? #if __LINUX_ARM_ARCH__ >= 4 diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S index 350c636d14e0..b18b89715118 100644 --- a/arch/arm/lib/csumpartialcopygeneric.S +++ b/arch/arm/lib/csumpartialcopygeneric.S @@ -36,16 +36,16 @@ sum .req r3 load1b ip sub len, len, #1 - adcs sum, sum, ip, lsl #byte(1) @ update checksum + adcs sum, sum, ip, put_byte_1 @ update checksum strb ip, [dst], #1 tst dst, #2 moveq pc, lr @ dst is now 32bit aligned .dst_16bit: load2b r8, ip sub len, len, #2 - adcs sum, sum, r8, lsl #byte(0) + adcs sum, sum, r8, put_byte_0 strb r8, [dst], #1 - adcs sum, sum, ip, lsl #byte(1) + adcs sum, sum, ip, put_byte_1 strb ip, [dst], #1 mov pc, lr @ dst is now 32bit aligned @@ -63,16 +63,16 @@ sum .req r3 /* Align dst */ load1b ip sub len, len, #1 - adcs sum, sum, ip, lsl #byte(1) @ update checksum + adcs sum, sum, ip, put_byte_1 @ update checksum strb ip, [dst], #1 tst len, #6 beq .less8_byteonly 1: load2b r8, ip sub len, len, #2 - adcs sum, sum, r8, lsl #byte(0) + adcs sum, sum, r8, put_byte_0 strb r8, [dst], #1 - adcs sum, sum, ip, lsl #byte(1) + adcs sum, sum, ip, put_byte_1 strb ip, [dst], #1 .less8_aligned: tst len, #6 bne 1b @@ -80,7 +80,7 @@ sum .req r3 tst len, #1 beq .done load1b r8 - adcs sum, sum, r8, lsl #byte(0) @ update checksum + adcs sum, sum, r8, put_byte_0 @ update checksum strb r8, [dst], #1 b .done @@ -139,17 +139,17 @@ FN_ENTRY beq .done load1l r4 tst len, #2 - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 beq .exit adcs sum, sum, r4, push #16 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 - mov r5, r4, lsr #byte(2) + mov r5, r4, get_byte_2 .exit: tst len, #1 strneb r5, [dst], #1 andne r5, r5, #255 - adcnes sum, sum, r5, lsl #byte(0) + adcnes sum, sum, r5, put_byte_0 /* * If the dst pointer was not 16-bit aligned, we @@ -213,14 +213,14 @@ FN_ENTRY mov r4, r5, pull #8 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit adcs sum, sum, r4, push #16 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 - mov r5, r4, lsr #byte(2) + mov r5, r4, get_byte_2 b .exit .src2_aligned: mov r4, r5, pull #16 @@ -265,12 +265,12 @@ FN_ENTRY mov r4, r5, pull #16 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit adcs sum, sum, r4 strb r5, [dst], #1 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 strb r5, [dst], #1 tst len, #1 beq .done @@ -319,14 +319,14 @@ FN_ENTRY mov r4, r5, pull #24 4: ands len, len, #3 beq .done - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 tst len, #2 beq .exit strb r5, [dst], #1 adcs sum, sum, r4 load1l r4 - mov r5, r4, lsr #byte(0) + mov r5, r4, get_byte_0 strb r5, [dst], #1 adcs sum, sum, r4, push #24 - mov r5, r4, lsr #byte(1) + mov r5, r4, get_byte_1 b .exit diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S index 2b4f89834998..081ef749298a 100644 --- a/arch/arm/lib/io-readsb.S +++ b/arch/arm/lib/io-readsb.S @@ -37,35 +37,35 @@ ENTRY(__raw_readsb) .insb_16_lp: ldrb r3, [r0] ldrb r4, [r0] ldrb r5, [r0] - mov r3, r3, lsl #byte(0) + mov r3, r3, put_byte_0 ldrb r6, [r0] - orr r3, r3, r4, lsl #byte(1) + orr r3, r3, r4, put_byte_1 ldrb r4, [r0] - orr r3, r3, r5, lsl #byte(2) + orr r3, r3, r5, put_byte_2 ldrb r5, [r0] - orr r3, r3, r6, lsl #byte(3) + orr r3, r3, r6, put_byte_3 ldrb r6, [r0] - mov r4, r4, lsl #byte(0) + mov r4, r4, put_byte_0 ldrb ip, [r0] - orr r4, r4, r5, lsl #byte(1) + orr r4, r4, r5, put_byte_1 ldrb r5, [r0] - orr r4, r4, r6, lsl #byte(2) + orr r4, r4, r6, put_byte_2 ldrb r6, [r0] - orr r4, r4, ip, lsl #byte(3) + orr r4, r4, ip, put_byte_3 ldrb ip, [r0] - mov r5, r5, lsl #byte(0) + mov r5, r5, put_byte_0 ldrb lr, [r0] - orr r5, r5, r6, lsl #byte(1) + orr r5, r5, r6, put_byte_1 ldrb r6, [r0] - orr r5, r5, ip, lsl #byte(2) + orr r5, r5, ip, put_byte_2 ldrb ip, [r0] - orr r5, r5, lr, lsl #byte(3) + orr r5, r5, lr, put_byte_3 ldrb lr, [r0] - mov r6, r6, lsl #byte(0) - orr r6, r6, ip, lsl #byte(1) + mov r6, r6, put_byte_0 + orr r6, r6, ip, put_byte_1 ldrb ip, [r0] - orr r6, r6, lr, lsl #byte(2) - orr r6, r6, ip, lsl #byte(3) + orr r6, r6, lr, put_byte_2 + orr r6, r6, ip, put_byte_3 stmia r1!, {r3 - r6} subs r2, r2, #16 @@ -80,19 +80,19 @@ ENTRY(__raw_readsb) ldrb r3, [r0] ldrb r4, [r0] ldrb r5, [r0] - mov r3, r3, lsl #byte(0) + mov r3, r3, put_byte_0 ldrb r6, [r0] - orr r3, r3, r4, lsl #byte(1) + orr r3, r3, r4, put_byte_1 ldrb r4, [r0] - orr r3, r3, r5, lsl #byte(2) + orr r3, r3, r5, put_byte_2 ldrb r5, [r0] - orr r3, r3, r6, lsl #byte(3) + orr r3, r3, r6, put_byte_3 ldrb r6, [r0] - mov r4, r4, lsl #byte(0) + mov r4, r4, put_byte_0 ldrb ip, [r0] - orr r4, r4, r5, lsl #byte(1) - orr r4, r4, r6, lsl #byte(2) - orr r4, r4, ip, lsl #byte(3) + orr r4, r4, r5, put_byte_1 + orr r4, r4, r6, put_byte_2 + orr r4, r4, ip, put_byte_3 stmia r1!, {r3, r4} .insb_no_8: tst r2, #4 @@ -102,10 +102,10 @@ ENTRY(__raw_readsb) ldrb r4, [r0] ldrb r5, [r0] ldrb r6, [r0] - mov r3, r3, lsl #byte(0) - orr r3, r3, r4, lsl #byte(1) - orr r3, r3, r5, lsl #byte(2) - orr r3, r3, r6, lsl #byte(3) + mov r3, r3, put_byte_0 + orr r3, r3, r4, put_byte_1 + orr r3, r3, r5, put_byte_2 + orr r3, r3, r6, put_byte_3 str r3, [r1], #4 .insb_no_4: ands r2, r2, #3 diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index 9ca73aaa333a..d3ed0636c008 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -183,14 +183,14 @@ USER( strt r3, [r0], #4) @ May fault strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_1fupi -.c2u_1nowords: mov r3, r7, lsr #byte(1) +.c2u_1nowords: mov r3, r7, get_byte_1 teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r7, lsr #byte(2) + movge r3, r7, get_byte_2 USER( strgebt r3, [r0], #1) @ May fault - movgt r3, r7, lsr #byte(3) + movgt r3, r7, get_byte_3 USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished @@ -250,12 +250,12 @@ USER( strt r3, [r0], #4) @ May fault strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_2fupi -.c2u_2nowords: mov r3, r7, lsr #byte(2) +.c2u_2nowords: mov r3, r7, get_byte_2 teq ip, #0 beq .c2u_finished cmp ip, #2 USER( strbt r3, [r0], #1) @ May fault - movge r3, r7, lsr #byte(3) + movge r3, r7, get_byte_3 USER( strgebt r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 USER( strgtbt r3, [r0], #1) @ May fault @@ -317,7 +317,7 @@ USER( strt r3, [r0], #4) @ May fault strnet r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .c2u_3fupi -.c2u_3nowords: mov r3, r7, lsr #byte(3) +.c2u_3nowords: mov r3, r7, get_byte_3 teq ip, #0 beq .c2u_finished cmp ip, #2 @@ -496,14 +496,14 @@ USER( ldrnet r7, [r1], #4) @ May fault strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_1fupi -.cfu_1nowords: mov r3, r7, lsr #byte(1) +.cfu_1nowords: mov r3, r7, get_byte_1 teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r7, lsr #byte(2) + movge r3, r7, get_byte_2 strgeb r3, [r0], #1 - movgt r3, r7, lsr #byte(3) + movgt r3, r7, get_byte_3 strgtb r3, [r0], #1 b .cfu_finished @@ -563,12 +563,12 @@ USER( ldrnet r7, [r1], #4) @ May fault strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_2fupi -.cfu_2nowords: mov r3, r7, lsr #byte(2) +.cfu_2nowords: mov r3, r7, get_byte_2 teq ip, #0 beq .cfu_finished cmp ip, #2 strb r3, [r0], #1 - movge r3, r7, lsr #byte(3) + movge r3, r7, get_byte_3 strgeb r3, [r0], #1 USER( ldrgtbt r3, [r1], #0) @ May fault strgtb r3, [r0], #1 @@ -630,7 +630,7 @@ USER( ldrnet r7, [r1], #4) @ May fault strne r3, [r0], #4 ands ip, ip, #3 beq .cfu_3fupi -.cfu_3nowords: mov r3, r7, lsr #byte(3) +.cfu_3nowords: mov r3, r7, get_byte_3 teq ip, #0 beq .cfu_finished cmp ip, #2 diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h index 84ab93eb4643..69a28f96bee2 100644 --- a/include/asm-arm/assembler.h +++ b/include/asm-arm/assembler.h @@ -25,11 +25,25 @@ #ifndef __ARMEB__ #define pull lsr #define push lsl -#define byte(x) (x*8) +#define get_byte_0 lsl #0 +#define get_byte_1 lsr #8 +#define get_byte_2 lsr #16 +#define get_byte_3 lsr #24 +#define put_byte_0 lsl #0 +#define put_byte_1 lsl #8 +#define put_byte_2 lsl #16 +#define put_byte_3 lsl #24 #else #define pull lsl #define push lsr -#define byte(x) ((3-x)*8) +#define get_byte_0 lsr #24 +#define get_byte_1 lsr #16 +#define get_byte_2 lsr #8 +#define get_byte_3 lsl #0 +#define put_byte_0 lsl #24 +#define put_byte_1 lsl #16 +#define put_byte_2 lsl #8 +#define put_byte_3 lsl #0 #endif /* -- cgit v1.2.3 From 89a5508e982afdd6e5eca6b5609245363ed42982 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 28 Jan 2004 01:12:06 -0500 Subject: [SUNSAB]: Fixup sunsab_receive_chars for when serial console isn't open (no tty) --- drivers/serial/sunsab.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index afb27a2b50f3..6747b8bafe10 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -101,13 +101,16 @@ static void receive_chars(struct uart_sunsab_port *up, union sab82532_irq_status *stat, struct pt_regs *regs) { - struct tty_struct *tty = up->port.info->tty; + struct tty_struct *tty = NULL; unsigned char buf[32]; int saw_console_brk = 0; int free_fifo = 0; int count = 0; int i; + if (up->port.info != NULL) /* Unopened serial console */ + tty = up->port.info->tty; + /* Read number of BYTES (Character + Status) available. */ if (stat->sreg.isr0 & SAB82532_ISR0_RPF) { count = SAB82532_RECV_FIFO_SIZE; @@ -142,6 +145,11 @@ static void receive_chars(struct uart_sunsab_port *up, for (i = 0; i < count; i++) { unsigned char ch = buf[i]; + if (tty == NULL) { + uart_handle_sysrq_char(&up->port, ch, regs); + continue; + } + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) @@ -217,7 +225,8 @@ static void receive_chars(struct uart_sunsab_port *up, } } - tty_flip_buffer_push(tty); + if (tty) + tty_flip_buffer_push(tty); if (saw_console_brk) sun_do_break(); -- cgit v1.2.3 From 0dc316dee192a2e178d52b2a2324fbe18ed46f1c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Jan 2004 19:46:52 -0800 Subject: [SPARC64]: Remove interruptible_sleep_on() usage, with help from Tom Callaway. --- arch/sparc64/kernel/power.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index b7e865eb7154..b53ecb88a780 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -69,18 +69,26 @@ static int powerd(void *__unused) { static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; char *argv[] = { "/sbin/shutdown", "-h", "now", NULL }; + DECLARE_WAITQUEUE(wait, current); daemonize("powerd"); + add_wait_queue(&powerd_wait, &wait); again: - while (button_pressed == 0) { + for (;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + if (button_pressed) + break; flush_signals(current); - interruptible_sleep_on(&powerd_wait); + schedule(); } + __set_current_state(TASK_RUNNING); + remove_wait_queue(&powerd_wait, &wait); /* Ok, down we go... */ if (execve("/sbin/shutdown", argv, envp) < 0) { printk("powerd: shutdown execution failed\n"); + add_wait_queue(&powerd_wait, &wait); button_pressed = 0; goto again; } -- cgit v1.2.3 From b5849a353834172c4e11b494aa5df5c7bd37bd55 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 28 Jan 2004 22:26:16 -0800 Subject: [PATCH] Prevent PCI driver registration failure oopsing Greg, As discussed about six or so months ago, we agreed to hold off this patch until fairly late, due to its ability to catch duplicate PCI driver names. Please note that I haven't attempted to reproduce the problem with recent kernels, and that all ARM kernel patches released since then have had this patch in. I'm guessing this will actually be 2.6.1 material since it probably doesn't show for PCI drivers which are part of the kernel tree. If pci_register_driver fails, the register the PCI driver structure will not be registered with the driver model. pci_register_driver returns with negative value, and we then attempt to unregister the driver structure. This leads to an oops in the driver model. The driver model does not return the number of devices it successfully bound the driver to, and neither does pci_register_driver() return this information. Therefore, all of the code below is redundant. (There's a little redundancy left in drivers/pci/pci-driver.c but it is harmless unlike this block.) --- include/linux/pci.h | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index b88b9d3f5bfc..d6a87a2eb263 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -785,26 +785,7 @@ static inline int pci_module_init(struct pci_driver *drv) { int rc = pci_register_driver (drv); - if (rc > 0) - return 0; - - /* iff CONFIG_HOTPLUG and built into kernel, we should - * leave the driver around for future hotplug events. - * For the module case, a hotplug daemon of some sort - * should load a module in response to an insert event. */ -#if defined(CONFIG_HOTPLUG) && !defined(MODULE) - if (rc == 0) - return 0; -#else - if (rc == 0) - rc = -ENODEV; -#endif - - /* if we get here, we need to clean up pci driver instance - * and return some sort of error */ - pci_unregister_driver (drv); - - return rc; + return rc < 0 ? rc : 0; } /* -- cgit v1.2.3 From b2d9626753347dc71cd0213953d8c4ea511e30d5 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Wed, 28 Jan 2004 22:26:28 -0800 Subject: [PATCH] PCI Hotplug: Fixup pcihp_skeleton.c The functions are not named *_skel_*, so it seems useful not to call them with this. --- drivers/pci/hotplug/pcihp_skeleton.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index e78d99606699..08250839fa7e 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -370,10 +370,10 @@ static int init_slots (void) * Initilize the slot info structure with some known * good values. */ - info->power_status = get_skel_power_status(slot); - info->attention_status = get_skel_attention_status(slot); - info->latch_status = get_skel_latch_status(slot); - info->adapter_status = get_skel_adapter_status(slot); + info->power_status = get_power_status(slot); + info->attention_status = get_attention_status(slot); + info->latch_status = get_latch_status(slot); + info->adapter_status = get_adapter_status(slot); dbg ("registering slot %d\n", i); retval = pci_hp_register (slot->hotplug_slot); -- cgit v1.2.3 From 78d65a24de3cb781dae0f604680d48e1a295a641 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 28 Jan 2004 22:26:41 -0800 Subject: [PATCH] PCI Hotplug: Better reporting of PCI frequency / bus mode problems for acpi driver When plugging a 33MHz card into a bus that's running at 66MHz, I'd like to see a better error message than: acpiphp_glue: notify_handler: unknown event type 0x5 for \_SB_.SBA0.PCI4.S2F0 The following patch would give us: Device \_SB_.SBA0.PCI4.S2F0 cannot be configured due to a frequency mismatch which I think is clearer. --- drivers/pci/hotplug/acpiphp_glue.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 9f5591f21bea..bbf25f2b84ec 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -974,6 +974,21 @@ static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *con dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); break; + case ACPI_NOTIFY_FREQUENCY_MISMATCH: + printk(KERN_ERR "Device %s cannot be configured due" + " to a frequency mismatch\n", objname); + break; + + case ACPI_NOTIFY_BUS_MODE_MISMATCH: + printk(KERN_ERR "Device %s cannot be configured due" + " to a bus mode mismatch\n", objname); + break; + + case ACPI_NOTIFY_POWER_FAULT: + printk(KERN_ERR "Device %s has suffered a power fault\n", + objname); + break; + default: warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); break; -- cgit v1.2.3 From 68b308e82cafcd64e2a102b410b8db3077aae44d Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Wed, 28 Jan 2004 22:28:51 -0800 Subject: [PATCH] PCI: add pci_bus sysfs class This is needed to show pci bus topology to userspace properly. --- drivers/pci/bus.c | 2 + drivers/pci/probe.c | 114 ++++++++++++++++++++++++++++++++++++---------------- include/linux/pci.h | 6 ++- 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index ea4b43068b23..969ec4237fb2 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -116,6 +116,8 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) list_add_tail(&dev->subordinate->node, &dev->bus->children); spin_unlock(&pci_bus_lock); pci_bus_add_devices(dev->subordinate); + + sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge"); } } } diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9c91eaf646e3..749ddecd47af 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -6,6 +6,7 @@ #include #include #include +#include #undef DEBUG @@ -24,6 +25,39 @@ EXPORT_SYMBOL(pci_root_buses); LIST_HEAD(pci_devices); +/* + * PCI Bus Class + */ +static void release_pcibus_dev(struct class_device *class_dev) +{ + struct pci_bus *pci_bus = to_pci_bus(class_dev); + if (pci_bus->bridge) + put_device(pci_bus->bridge); + kfree(pci_bus); +} + +static struct class pcibus_class = { + .name = "pci_bus", + .release = &release_pcibus_dev, +}; + +static int __init pcibus_class_init(void) +{ + return class_register(&pcibus_class); +} +postcore_initcall(pcibus_class_init); + +/* + * PCI Bus Class Devices + */ +static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf) +{ + cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number); + + return sprintf(buf, "%lx\n", (unsigned long)cpumask); +} +static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL); + /* * Translate the low bits of the PCI base * to the resource type @@ -238,37 +272,40 @@ static struct pci_bus * __devinit pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) { struct pci_bus *child; + int i; /* * Allocate a new bus, and inherit stuff from the parent.. */ child = pci_alloc_bus(); + if (!child) + return NULL; - if (child) { - int i; - - child->self = bridge; - child->parent = parent; - child->ops = parent->ops; - child->sysdata = parent->sysdata; - child->dev = &bridge->dev; + child->self = bridge; + child->parent = parent; + child->ops = parent->ops; + child->sysdata = parent->sysdata; + child->bridge = get_device(&bridge->dev); - /* - * Set up the primary, secondary and subordinate - * bus numbers. - */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; - - /* Set up default resource pointers and names.. */ - for (i = 0; i < 4; i++) { - child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; - child->resource[i]->name = child->name; - } + child->class_dev.class = &pcibus_class; + sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr); + class_device_register(&child->class_dev); + class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity); - bridge->subordinate = child; + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = busnr; + child->primary = parent->secondary; + child->subordinate = 0xff; + + /* Set up default resource pointers and names.. */ + for (i = 0; i < 4; i++) { + child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; + child->resource[i]->name = child->name; } + bridge->subordinate = child; return child; } @@ -307,18 +344,17 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_name(dev), buses & 0xffffff, pass); if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { - unsigned int cmax; + unsigned int cmax, busnr; /* * Bus already configured by firmware, process it in the first * pass and just note the configuration. */ if (pass) return max; - child = pci_alloc_child_bus(bus, dev, 0); + busnr = (buses >> 8) & 0xFF; + child = pci_alloc_child_bus(bus, dev, busnr); child->primary = buses & 0xFF; - child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; - child->number = child->secondary; cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { @@ -508,7 +544,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) memset(dev, 0, sizeof(struct pci_dev)); dev->bus = bus; dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; + dev->dev.parent = bus->bridge; dev->dev.bus = &pci_bus_type; dev->devfn = devfn; dev->hdr_type = hdr_type & 0x7f; @@ -635,13 +671,14 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; + struct device *dev; b = pci_alloc_bus(); if (!b) return NULL; - b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL); - if (!b->dev){ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev){ kfree(b); return NULL; } @@ -652,17 +689,24 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, if (pci_find_bus(pci_domain_nr(b), bus)) { /* If we already got to this bus through a different bridge, ignore it */ DBG("PCI: Bus %02x already known\n", bus); - kfree(b->dev); + kfree(dev); kfree(b); return NULL; } - list_add_tail(&b->node, &pci_root_buses); - memset(b->dev,0,sizeof(*(b->dev))); - b->dev->parent = parent; - sprintf(b->dev->bus_id,"pci%04x:%02x", pci_domain_nr(b), bus); - device_register(b->dev); + memset(dev, 0, sizeof(*dev)); + dev->parent = parent; + sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus); + device_register(dev); + b->bridge = get_device(dev); + + b->class_dev.class = &pcibus_class; + sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus); + class_device_register(&b->class_dev); + class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity); + + sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge"); b->number = b->secondary = bus; b->resource[0] = &ioport_resource; diff --git a/include/linux/pci.h b/include/linux/pci.h index d6a87a2eb263..33980d0a753c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -473,10 +473,12 @@ struct pci_bus { char name[48]; - struct device * dev; + struct device *bridge; + struct class_device class_dev; }; -#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define to_pci_bus(n) container_of(n, struct pci_bus, class_dev) /* * Error values that may be returned by PCI functions. -- cgit v1.2.3 From 9648e089aaba09d60282558c69e598ae40254160 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 28 Jan 2004 22:32:13 -0800 Subject: [PATCH] PCI: add pci_get_slot() function tg3.c has a bug where it can find the wrong 5704 peer on a machine with PCI domains. The problem is that pci_find_slot() can't distinguish whether it has the correct domain or not. This patch fixes that problem by introducing pci_get_slot(). --- drivers/pci/search.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 366f1f16fb2f..aa900b17f2f7 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -103,6 +103,41 @@ pci_find_slot(unsigned int bus, unsigned int devfn) return NULL; } +/** + * pci_get_slot - locate PCI device for a given PCI slot + * @bus: PCI bus on which desired PCI device resides + * @devfn: encodes number of PCI slot in which the desired PCI + * device resides and the logical device number within that slot + * in case of multi-function devices. + * + * Given a PCI bus and slot/function number, the desired PCI device + * is located in the list of PCI devices. + * If the device is found, its reference count is increased and this + * function returns a pointer to its data structure. The caller must + * decrement the reference count by calling pci_dev_put(). + * If no device is found, %NULL is returned. + */ +struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) +{ + struct list_head *tmp; + struct pci_dev *dev; + + WARN_ON(in_interrupt()); + spin_lock(&pci_bus_lock); + + list_for_each(tmp, &bus->children) { + dev = pci_dev_b(tmp); + if (dev->devfn == devfn) + goto out; + } + + dev = NULL; + out: + pci_dev_get(dev); + spin_unlock(&pci_bus_lock); + return dev; +} + /** * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids @@ -319,3 +354,4 @@ EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); +EXPORT_SYMBOL(pci_get_slot); diff --git a/include/linux/pci.h b/include/linux/pci.h index 33980d0a753c..4178a8b148bb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -614,6 +614,8 @@ struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); +struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); + int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val); -- cgit v1.2.3 From 70d7e12080cf91ba31cc16f78600630bf839a1af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 Jan 2004 22:45:26 -0800 Subject: [PATCH] PCI: add .owner field to the config sysfs file to be "correct" This is in case others copy this code (which has already happened...) --- drivers/pci/pci-sysfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index f9af11a64bfd..fd94569cd910 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -160,6 +160,7 @@ static struct bin_attribute pci_config_attr = { .attr = { .name = "config", .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, }, .size = 256, .read = pci_read_config, -- cgit v1.2.3 From 73b6196bef941470fb5245284b03e9e9d9c0ff69 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 28 Jan 2004 22:46:48 -0800 Subject: [PATCH] PCI: fix pci_get_slot() bug On Wed, Dec 17, 2003 at 04:24:44PM -0800, Greg KH wrote: > I've applied the pci portions of this patch to my trees and will send it > on after 2.6.0 is out. James Bottomley found a bug in it; could you also apply: --- drivers/pci/search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/search.c b/drivers/pci/search.c index aa900b17f2f7..701a83be3b30 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -125,7 +125,7 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) WARN_ON(in_interrupt()); spin_lock(&pci_bus_lock); - list_for_each(tmp, &bus->children) { + list_for_each(tmp, &bus->devices) { dev = pci_dev_b(tmp); if (dev->devfn == devfn) goto out; -- cgit v1.2.3 From 98e2380e51ff74784165fa4254c17064e7290b9d Mon Sep 17 00:00:00 2001 From: Martin Hicks Date: Wed, 28 Jan 2004 23:34:24 -0800 Subject: [PATCH] PCI Hotplug: Trivial warning fix This just gets rid of a stupid compile warning. --- drivers/pci/hotplug/acpiphp_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index bbf25f2b84ec..8e9c0036be16 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -245,7 +245,9 @@ decode_acpi_resource (struct acpi_resource *resource, void *context) acpi_resource_to_address64(resource, &address); if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) { - dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, address.min_address_range, address.max_address_range); + dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type, + (unsigned long long)address.min_address_range, + (unsigned long long)address.max_address_range); res = acpiphp_make_resource(address.min_address_range, address.address_length); if (!res) { -- cgit v1.2.3 From 272b06a8ed5f18a44df8d56f1f656c339093fc48 Mon Sep 17 00:00:00 2001 From: Takayoshi Kochi Date: Wed, 28 Jan 2004 23:34:56 -0800 Subject: [PATCH] PCI Hotplug: add address file and fix acpiphp bugs This is the pending patch that adds 'address' file to show PCI-address and a few other minor fixes. As 2.6.0 is out, I'm resending the patch. Would you mind taking this? > > > Thanks. I had a little time to try your patch today. Sorry > > > to report that it isn't working for me. > > > > > > I first powered off (successfully the 1st time) a populated slot > > > and removed and reinserted the card into the same slot. The slot > > > powered back up but I was then unable to power it off. I believe > > > the following instruction that still exists in power_off_slot() > > > may be preventing the slot from being powered off more than once. > > > func->flags &= (~FUNC_EXISTS); > > > > > > I then tried to insert an adapter in an un-populated slot. For > > > some reason (which I don't understand yet) there was an enabling > > > error which I believe caused enable_device() to exit via a path > > > that bypassed the instruction that sets the FUNC_EXISTS flag. > > > I was then unable to power off the slot which I believe was due > > > to the FUNC_EXISTS flag not being set. > > > > > > I didn't have time to definitely confirmed the above theories. > > > I'll take a closer look at this tomorrow unless you are able > > > to diagnose using my vague clues :) > > > > It turns out that both of the above mentioned problems happened > > because the call to acpiphp_configure_slot() from enable_device() > > failed after inserting the card. When this happens enable_device() > > exits without setting the FUNC_EXISTS flag for any of the slot > > functions. Subsequent attempts to power off the same slot fail > > when power_off_slot() is unable to locate a function with both > > FUNC_HAS_EJ0 and FUNC_EXISTS flags set. > > > > The patch works okay when using a card that allows > > acpiphp_configure_slot() to succeed but I believe it should > > be improved to allow the slot to be powered off following > > device enablement errors. > > Thanks for testing and comments. > I really appreciate it. > > This problem turned out to be somewhat fragile state > transition: > > a lifecycle of a slot is (if there's no error) > > function state > ---------------------------------------------------- > 0 nothing > 1 power_on_slot() -> SLOT_POWERDON > 2 enable_device() -> SLOT_POWEREDON + SLOT_ENABLED > 3 disable_device() -> SLOT_POWEREDON > 4 power_off_slot() -> nothing > > but if any error occur during enable_device(), slot will remain > SLOT_POWERDON, but some functions on the card may not have > FUNC_EXISTS flags, which will eventually prevents powering > off in power_off_slot(), state transition from 1 to 4 directly. > I.e, the FUNC_EXISTS flag introduced more states to > complicate things. > > The FUNC_EXISTS flag was introduced after some discussion > between me and Irene Zubarev, but it has no more meaning > than that the function has corresponding 'pci_dev' structure. > So I eliminated the usage of FUNC_EXISTS and the result is > the patches attached to this mail (for both 2.4 and 2.6. > I think Greg already applied the 2.4 'cleanup' patch to his tree, > but it's not in Marcelo's release so I'm re-attaching to > this mail for anyone interested in this topic. It's identical > to the one I posted earlier). > These patches don't include Gary's patch in his post last week, > so please apply separately. > > Please note that current acpiphp driver cannot handle a > PCI card that has a PCI-to-PCI bridge on it (support > for such cards is incomplete). But if it's treated as > an error, it should be recoverable anyway. --- drivers/pci/hotplug/acpiphp.h | 5 ++-- drivers/pci/hotplug/acpiphp_core.c | 30 +++++++++++++++++++++--- drivers/pci/hotplug/acpiphp_glue.c | 32 ++++++++++++++++++-------- drivers/pci/hotplug/acpiphp_pci.c | 6 ++--- drivers/pci/hotplug/acpiphp_res.c | 3 +-- drivers/pci/hotplug/pci_hotplug.h | 6 +++++ drivers/pci/hotplug/pci_hotplug_core.c | 42 ++++++++++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 21 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 0c41e66a10b6..6d25ebf99fd5 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -201,7 +201,7 @@ struct acpiphp_func { #define SLOT_POWEREDON (0x00000001) #define SLOT_ENABLED (0x00000002) -#define SLOT_MULTIFUNCTION (x000000004) +#define SLOT_MULTIFUNCTION (0x00000004) /* function flags */ @@ -212,8 +212,6 @@ struct acpiphp_func { #define FUNC_HAS_PS2 (0x00000040) #define FUNC_HAS_PS3 (0x00000080) -#define FUNC_EXISTS (0x10000000) /* to make sure we call _EJ0 only for existing funcs */ - /* function prototypes */ /* acpiphp_glue.c */ @@ -231,6 +229,7 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); +extern u32 acpiphp_get_address (struct acpiphp_slot *slot); /* acpiphp_pci.c */ extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 544fb8976a0e..35f008c26b11 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -30,14 +30,14 @@ * */ -#include -#include +#include #include + +#include #include #include #include #include -#include #include "pci_hotplug.h" #include "acpiphp.h" @@ -71,6 +71,7 @@ static int set_attention_status (struct hotplug_slot *slot, u8 value); static int hardware_test (struct hotplug_slot *slot, u32 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); @@ -86,6 +87,7 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -322,6 +324,28 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) } +/** + * get_address - get pci address of a slot + * @hotplug_slot: slot to get status + * @busdev: pointer to struct pci_busdev (seg, bus, dev) + * + */ +static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = acpiphp_get_address(slot->acpi_slot); + + return retval; +} + + /* return dummy value because ACPI doesn't provide any method... */ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 8e9c0036be16..2ada5edfee0e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -26,12 +26,12 @@ * */ -#include -#include +#include #include + +#include #include #include -#include #include #include "../pci.h" @@ -686,7 +686,7 @@ static int power_on_slot (struct acpiphp_slot *slot) struct list_head *l; int retval = 0; - /* is this already enabled? */ + /* if already enabled, just skip */ if (slot->flags & SLOT_POWEREDON) goto err_exit; @@ -724,14 +724,14 @@ static int power_off_slot (struct acpiphp_slot *slot) int retval = 0; - /* is this already enabled? */ + /* if already disabled, just skip */ if ((slot->flags & SLOT_POWEREDON) == 0) goto err_exit; list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); - if (func->flags & (FUNC_HAS_PS3 | FUNC_EXISTS)) { + if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) { status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS3 failed\n", __FUNCTION__); @@ -745,7 +745,7 @@ static int power_off_slot (struct acpiphp_slot *slot) func = list_entry(l, struct acpiphp_func, sibling); /* We don't want to call _EJ0 on non-existing functions. */ - if (func->flags & (FUNC_HAS_EJ0 | FUNC_EXISTS)) { + if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) { /* _EJ0 method take one argument */ arg_list.count = 1; arg_list.pointer = &arg; @@ -758,7 +758,6 @@ static int power_off_slot (struct acpiphp_slot *slot) retval = -1; goto err_exit; } - func->flags &= (~FUNC_EXISTS); } } @@ -838,8 +837,6 @@ static int enable_device (struct acpiphp_slot *slot) retval = acpiphp_configure_function(func); if (retval) goto err_exit; - - func->flags |= FUNC_EXISTS; } slot->flags |= SLOT_ENABLED; @@ -1349,3 +1346,18 @@ u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot) return (sta == 0) ? 0 : 1; } + + +/* + * pci address (seg/bus/dev) + */ +u32 acpiphp_get_address (struct acpiphp_slot *slot) +{ + u32 address; + + address = ((slot->bridge->seg) << 16) | + ((slot->bridge->bus) << 8) | + slot->device; + + return address; +} diff --git a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c index 93eb2eff595f..9d9dabdcee9c 100644 --- a/drivers/pci/hotplug/acpiphp_pci.c +++ b/drivers/pci/hotplug/acpiphp_pci.c @@ -29,11 +29,11 @@ * */ -#include -#include +#include #include + +#include #include -#include #include #include "../pci.h" #include "pci_hotplug.h" diff --git a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c index 060095be3233..ba9cbb995030 100644 --- a/drivers/pci/hotplug/acpiphp_res.c +++ b/drivers/pci/hotplug/acpiphp_res.c @@ -29,7 +29,7 @@ * */ -#include +#include #include #include @@ -39,7 +39,6 @@ #include #include #include -#include #include #include diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 0c003145dd76..77fed093c002 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -74,6 +74,9 @@ struct hotplug_slot_attribute { * @get_adapter_status: Called to get see if an adapter is present in the slot or not. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. + * @get_address: Called to get pci address of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. * @get_max_bus_speed: Called to get the max bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. @@ -96,6 +99,7 @@ struct hotplug_slot_ops { int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); + int (*get_address) (struct hotplug_slot *slot, u32 *value); int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); }; @@ -106,6 +110,7 @@ struct hotplug_slot_ops { * @attention_status: if the attention light is enabled or not (1/0) * @latch_status: if the latch (if any) is open or closed (1/0) * @adapter_present: if there is a pci board present in the slot or not (1/0) + * @address: (domain << 16 | bus << 8 | dev) * * Used to notify the hotplug pci core of the status of a specific slot. */ @@ -114,6 +119,7 @@ struct hotplug_slot_info { u8 attention_status; u8 latch_status; u8 adapter_status; + u32 address; enum pci_bus_speed max_bus_speed; enum pci_bus_speed cur_bus_speed; }; diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 6732c33a8b51..64a539338701 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -159,6 +159,7 @@ GET_STATUS(power_status, u8) GET_STATUS(attention_status, u8) GET_STATUS(latch_status, u8) GET_STATUS(adapter_status, u8) +GET_STATUS(address, u32) GET_STATUS(max_bus_speed, enum pci_bus_speed) GET_STATUS(cur_bus_speed, enum pci_bus_speed) @@ -302,6 +303,28 @@ static struct hotplug_slot_attribute hotplug_slot_attr_presence = { .show = presence_read_file, }; +static ssize_t address_read_file (struct hotplug_slot *slot, char *buf) +{ + int retval; + u32 address; + + retval = get_address (slot, &address); + if (retval) + goto exit; + retval = sprintf (buf, "%04x:%02x:%02x\n", + (address >> 16) & 0xffff, + (address >> 8) & 0xff, + address & 0xff); + +exit: + return retval; +} + +static struct hotplug_slot_attribute hotplug_slot_attr_address = { + .attr = {.name = "address", .mode = S_IFREG | S_IRUGO}, + .show = address_read_file, +}; + static char *unknown_speed = "Unknown bus speed"; static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf) @@ -425,6 +448,15 @@ static int has_adapter_file (struct hotplug_slot *slot) return -ENOENT; } +static int has_address_file (struct hotplug_slot *slot) +{ + if ((!slot) || (!slot->ops)) + return -ENODEV; + if (slot->ops->get_address) + return 0; + return -ENOENT; +} + static int has_max_bus_speed_file (struct hotplug_slot *slot) { if ((!slot) || (!slot->ops)) @@ -466,6 +498,9 @@ static int fs_add_slot (struct hotplug_slot *slot) if (has_adapter_file(slot) == 0) sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if (has_address_file(slot) == 0) + sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if (has_max_bus_speed_file(slot) == 0) sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -492,6 +527,9 @@ static void fs_remove_slot (struct hotplug_slot *slot) if (has_adapter_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if (has_address_file(slot) == 0) + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if (has_max_bus_speed_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -612,6 +650,10 @@ int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info (slot->info->adapter_status != info->adapter_status)) sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if ((has_address_file(slot) == 0) && + (slot->info->address != info->address)) + sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if ((has_max_bus_speed_file(slot) == 0) && (slot->info->max_bus_speed != info->max_bus_speed)) sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); -- cgit v1.2.3 From 1e57188a787601f6ad4fa7970d4540fa41293a7d Mon Sep 17 00:00:00 2001 From: Linda Xie Date: Wed, 28 Jan 2004 23:35:19 -0800 Subject: [PATCH] PCI Hotplug: add unlimited PHP slot name lengths support --- drivers/pci/hotplug/pci_hotplug_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 64a539338701..10a2aae77222 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -571,7 +571,7 @@ int pci_hp_register (struct hotplug_slot *slot) if ((slot->info == NULL) || (slot->ops == NULL)) return -EINVAL; - strlcpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN); + kobject_set_name(&slot->kobj, slot->name); kobj_set_kset_s(slot, pci_hotplug_slots_subsys); /* this can fail if we have already registered a slot with the same name */ -- cgit v1.2.3 From 68e0f3a0c8af7b2006a850370978455ed67914ab Mon Sep 17 00:00:00 2001 From: Ralf Bächle Date: Wed, 28 Jan 2004 23:38:38 -0800 Subject: [PATCH] PCI: fix probing for some mips systems --- drivers/pci/probe.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 749ddecd47af..be87193cff59 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -337,12 +337,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max struct pci_bus *child; int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); u32 buses; + u16 bctl; pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", pci_name(dev), buses & 0xffffff, pass); + /* Disable MasterAbortMode during probing to avoid reporting + of bus errors (in some architectures) */ + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl); + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, + bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); + if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { unsigned int cmax, busnr; /* @@ -406,6 +413,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); } + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); + sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number); return max; -- cgit v1.2.3 From 66f070bafd53464d330435d4fc549cc7f6dea91c Mon Sep 17 00:00:00 2001 From: Leann Ogasawara Date: Thu, 29 Jan 2004 00:19:53 -0800 Subject: [PATCH] PCI hotplug: pcihp_zt5550.c ioremap/iounmap audit insert missing iounmap() --- drivers/pci/hotplug/cpcihp_zt5550.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 41873730bbba..2d7a988ad4f8 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -133,6 +133,8 @@ static int zt5550_hc_cleanup(void) { if(!hc_dev) return -ENODEV; + + iounmap(hc_registers); release_mem_region(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1)); return 0; -- cgit v1.2.3 From b323e1dfd14fa4fed77f9360f16e80f23ed917f3 Mon Sep 17 00:00:00 2001 From: John Rose Date: Thu, 29 Jan 2004 00:54:22 -0800 Subject: [PATCH] PCI: Allow pci hotplug drivers to initialize individual devices. This lets the PPC pci hotplug driver initialize single devices, not just entire slots. --- drivers/pci/probe.c | 66 ++++++++++++++++++++++++++++++++--------------------- include/linux/pci.h | 1 + 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index be87193cff59..50391a0fd11e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -580,6 +580,30 @@ pci_scan_device(struct pci_bus *bus, int devfn) return dev; } +struct pci_dev * __devinit +pci_scan_single_device(struct pci_bus *bus, int devfn) +{ + struct pci_dev *dev; + + dev = pci_scan_device(bus, devfn); + pci_scan_msi_device(dev); + + if (!dev) + return NULL; + + /* Fix up broken headers */ + pci_fixup_device(PCI_FIXUP_HEADER, dev); + + /* + * Add the device to our list of discovered devices + * and the bus list for fixup functions, etc. + */ + INIT_LIST_HEAD(&dev->global_list); + list_add_tail(&dev->bus_list, &bus->devices); + + return dev; +} + /** * pci_scan_slot - scan a PCI slot on a bus for devices. * @bus: PCI bus to scan @@ -596,34 +620,23 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) for (func = 0; func < 8; func++, devfn++) { struct pci_dev *dev; - dev = pci_scan_device(bus, devfn); - pci_scan_msi_device(dev); - if (func == 0) { - if (!dev) - break; + dev = pci_scan_single_device(bus, devfn); + if (dev) { + nr++; + + /* + * If this is a single function device, + * don't scan past the first function. + */ + if (!dev->multifunction) + if (func > 0) + dev->multifunction = 1; + else + break; } else { - if (!dev) - continue; - dev->multifunction = 1; + if (func == 0) + break; } - - /* Fix up broken headers */ - pci_fixup_device(PCI_FIXUP_HEADER, dev); - - /* - * Add the device to our list of discovered devices - * and the bus list for fixup functions, etc. - */ - INIT_LIST_HEAD(&dev->global_list); - list_add_tail(&dev->bus_list, &bus->devices); - nr++; - - /* - * If this is a single function device, - * don't scan past the first function. - */ - if (!dev->multifunction) - break; } return nr; } @@ -734,4 +747,5 @@ EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_bridge); +EXPORT_SYMBOL(pci_scan_single_device); #endif diff --git a/include/linux/pci.h b/include/linux/pci.h index 4178a8b148bb..3ffb95a8f4d2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -587,6 +587,7 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s return pci_scan_bus_parented(NULL, bus, ops, sysdata); } int pci_scan_slot(struct pci_bus *bus, int devfn); +struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn); void pci_bus_add_devices(struct pci_bus *bus); void pci_name_device(struct pci_dev *dev); char *pci_class_name(u32 class); -- cgit v1.2.3 From 6a1bd1266701eb84c11c5da96ec03fb1c0debc2c Mon Sep 17 00:00:00 2001 From: Kieran Morrissey Date: Thu, 29 Jan 2004 01:12:59 -0800 Subject: [PATCH] PCI: name length change - Changes gen-devlist.c to truncate long device names rather than reject the database - Changes PCI_NAME_SIZE to 96 (and PCI_NAME_HALF to 43) to allow all current pci.ids names to fit - Modifies gen-devlist.c to truncate at 89 characters rather than 79 - allows for two digit instance numbers to be added to the name as well while staying within the 96 characters allocated. No names in the current pci.ids are any longer than this. - Modifies names.c to no longer limit device name length when displaying both vendor and device name; the truncation is done by gen-devlist.c. --- drivers/pci/gen-devlist.c | 16 +++++++++------- drivers/pci/names.c | 3 +-- include/linux/pci.h | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/pci/gen-devlist.c b/drivers/pci/gen-devlist.c index c0c242010eba..372e2102581d 100644 --- a/drivers/pci/gen-devlist.c +++ b/drivers/pci/gen-devlist.c @@ -7,12 +7,13 @@ #include #include -#define MAX_NAME_SIZE 79 +#define MAX_NAME_SIZE 89 static void -pq(FILE *f, const char *c) +pq(FILE *f, const char *c, int len) { - while (*c) { + int i = 1; + while (*c && i != len) { if (*c == '"') fprintf(f, "\\\""); else { @@ -23,6 +24,7 @@ pq(FILE *f, const char *c) } } c++; + i++; } } @@ -72,13 +74,13 @@ main(void) if (bra && bra > c && bra[-1] == ' ') bra[-1] = 0; if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) { - fprintf(stderr, "Line %d: Device name too long\n", lino); + fprintf(stderr, "Line %d: Device name too long. Name truncated.\n", lino); fprintf(stderr, "%s\n", c); - return 1; + /*return 1;*/ } } fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1); - pq(devf, c); + pq(devf, c, MAX_NAME_SIZE - vendor_len - 1); fputs("\")\n", devf); } else goto err; break; @@ -107,7 +109,7 @@ main(void) return 1; } fprintf(devf, "VENDOR(%s,\"", vend); - pq(devf, c); + pq(devf, c, 0); fputs("\")\n", devf); mode = 1; } else { diff --git a/drivers/pci/names.c b/drivers/pci/names.c index eb707bf79dda..ad224aada7c9 100644 --- a/drivers/pci/names.c +++ b/drivers/pci/names.c @@ -86,8 +86,7 @@ void __devinit pci_name_device(struct pci_dev *dev) /* Full match */ match_device: { - char *n = name + sprintf(name, "%." PCI_NAME_HALF - "s %." PCI_NAME_HALF "s", + char *n = name + sprintf(name, "%s %s", vendor_p->name, device_p->name); int nr = device_p->seen + 1; device_p->seen = nr; diff --git a/include/linux/pci.h b/include/linux/pci.h index 3ffb95a8f4d2..bc51ca9edef1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -425,8 +425,8 @@ struct pci_dev { unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */ #ifdef CONFIG_PCI_NAMES -#define PCI_NAME_SIZE 50 -#define PCI_NAME_HALF __stringify(20) /* less than half to handle slop */ +#define PCI_NAME_SIZE 96 +#define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */ char pretty_name[PCI_NAME_SIZE]; /* pretty name for users to see */ #endif }; -- cgit v1.2.3 From 07d880ace2ca07545a6687eecadeedabf8f0aa6f Mon Sep 17 00:00:00 2001 From: Kieran Morrissey Date: Thu, 29 Jan 2004 01:13:13 -0800 Subject: [PATCH] PCI: pci.ids update - Replaces pci.ids with a snapshot from pciids.sf.net from 14 Jan 2004 --- drivers/pci/pci.ids | 961 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 721 insertions(+), 240 deletions(-) diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids index 519d412c9921..a6a1e268871a 100644 --- a/drivers/pci/pci.ids +++ b/drivers/pci/pci.ids @@ -7,7 +7,7 @@ # so if you have anything to contribute, please visit the home page or # send a diff -u against the most recent pci.ids to pci-ids@ucw.cz. # -# $Id: pci.ids,v 1.48 2002/12/26 13:03:41 mares Exp $ +# Daily snapshot on Wed 2004-01-14 11:00:17 # # Vendors, devices and subsystems. Please keep sorted. @@ -118,6 +118,8 @@ 0e11 7004 Embedded Ultra Wide SCSI Controller 1092 8760 FirePort 40 Dual SCSI Controller 1de1 3904 DC390F Ultra Wide SCSI Controller + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard 0010 53c895 0e11 4040 Integrated Array Controller 0e11 4048 Integrated Array Controller @@ -126,7 +128,10 @@ 0020 53c1010 Ultra3 SCSI Adapter 1de1 1020 DC-390U3W 0021 53c1010 66MHz Ultra3 SCSI Adapter - 0030 53c1030 + 4c53 1080 CT8 mainboard + 4c53 1300 P017 mezzanine (32-bit PMC) + 4c53 1310 P017 mezzanine (64-bit PMC) + 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI 1028 1010 LSI U320 SCSI Controller 0040 53c1035 008f 53c875J @@ -161,10 +166,17 @@ 0017 PROTO-3 PCI Prototyping board 9100 INI-9100/9100W SCSI Host 1002 ATI Technologies Inc + 4136 Radeon IGP 320 M + 4144 Radeon R300 AD [Radeon 9500 Pro] + 4145 Radeon R300 AE [Radeon 9500 Pro] + 4146 Radeon R300 AF [Radeon 9500 Pro] + 4147 Radeon R300 AG [FireGL Z1/X1] 4158 68800AX [Mach32] + 4164 Radeon R300 Secondary (DVI) output 4242 Radeon R200 BB [Radeon All in Wonder 8500DV] 1002 02aa Radeon 8500 AIW DV Edition 4336 Radeon Mobility U1 + 4337 Radeon IGP 340M 4354 215CT [Mach64 CT] 4358 210888CX [Mach64 CX] 4554 210888ET [Mach64 ET] @@ -214,6 +226,8 @@ 4752 Rage XL 1002 0008 Rage XL 1002 4752 Rage XL + 1002 8008 Rage XL + 1028 00ce PowerEdge 1400 1028 00d1 PowerEdge 2550 4753 Rage XC 1002 4753 Rage XC @@ -238,6 +252,8 @@ 10f1 0002 R250 If [Tachyon G9000 PRO] 148c 2039 R250 If [Radeon 9000 Pro "Evil Commando"] 1509 9a00 R250 If [Radeon 9000 "AT009"] +# New subdevice - 3D Prophet 9000 PCI by Hercules. AGP version probably would have same ID, so not specified. + 1681 0040 R250 If [3D prophet 9000] 174b 7176 R250 If [Sapphire Radeon 9000 Pro] 174b 7192 R250 If [Radeon 9000 "Atlantis"] 17af 2005 R250 If [Excalibur Radeon 9000 Pro] @@ -255,6 +271,7 @@ 4c44 3D Rage LT Pro AGP-66 4c45 Rage Mobility M3 AGP 4c46 Rage Mobility M3 AGP 2x + 1028 00b1 Latitude C600 4c47 3D Rage LT-G 215LG 4c49 3D Rage LT Pro 1002 0004 Rage LT Pro @@ -262,8 +279,11 @@ 1002 0044 Rage LT Pro 1002 4c49 Rage LT Pro 4c4d Rage Mobility P/M AGP 2x + 0e11 b111 Armada M700 + 0e11 b160 Armada E500 1002 0084 Xpert 98 AGP 2X (Mobility) 1014 0154 ThinkPad A20m + 1028 00aa Latitude CPt 4c4e Rage Mobility L AGP 2x 4c50 3D Rage LT Pro 1002 4c50 Rage LT Pro @@ -274,23 +294,33 @@ 4c57 Radeon Mobility M7 LW [Radeon Mobility 7500] 1014 0517 ThinkPad T30 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100) - 4c58 Radeon Mobility M7 LX [Radeon Mobility FireGL 7800] + 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4 + 4c58 Radeon RV200 LX [Mobility FireGL 7800 M7] 4c59 Radeon Mobility M6 LY 1014 0235 ThinkPad A30p (2653-64G) 1014 0239 ThinkPad X22/X23/X24 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 4c5a Radeon Mobility M6 LZ - 4c64 Radeon R250 Ld [Radeon Mobility 9000] - 4c65 Radeon R250 Le [Radeon Mobility 9000] - 4c66 Radeon R250 Lf [Radeon Mobility 9000] - 4c67 Radeon R250 Lg [Radeon Mobility 9000] + 4c64 Radeon R250 Ld [Radeon Mobility 9000 M9] + 4c65 Radeon R250 Le [Radeon Mobility 9000 M9] + 4c66 Radeon R250 Lf [Radeon Mobility 9000 M9] + 4c67 Radeon R250 Lg [Radeon Mobility 9000 M9] +# Secondary chip to the Lf + 4c6e Radeon R250 Ln [Radeon Mobility 9000 M9] [Secondary] 4d46 Rage Mobility M4 AGP 4d4c Rage Mobility M4 AGP - 4e44 Radeon R300 ND [Radeon 9700] - 4e45 Radeon R300 NE [Radeon 9700] + 4e44 Radeon R300 ND [Radeon 9700 Pro] + 4e45 Radeon R300 NE [Radeon 9500 Pro] + 1002 0002 Radeon R300 NE [Radeon 9500 Pro] 4e46 Radeon R300 NF [Radeon 9700] - 4e47 Radeon R300 NG [Radeon 9700] - 4e64 Radeon R300 [Radeon 9700] (Secondary) + 4e47 Radeon R300 NG [FireGL X1] + 4e48 Radeon R350 [Radeon 9800] + 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary) + 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary) + 1002 0003 Radeon R300 NE [Radeon 9500 Pro] + 4e66 Radeon R300 [Radeon 9700] (Secondary) + 4e67 Radeon R300 [FireGL X1] (Secondary) + 4e68 Radeon R350 [Radeon 9800] (Secondary) 5041 Rage 128 PA/PRO 5042 Rage 128 PB/PRO AGP 2x 5043 Rage 128 PC/PRO AGP 4x @@ -327,7 +357,7 @@ 5056 Rage 128 PV/PRO TMDS 5057 Rage 128 PW/PRO AGP 2x TMDS 5058 Rage 128 PX/PRO AGP 4x TMDS - 5144 Radeon R100 QD [Radeon 64 DDR] + 5144 Radeon R100 QD [Radeon 7200] 1002 0008 Radeon 7000/Radeon VE 1002 0009 Radeon 7000/Radeon 1002 000a Radeon 7000/Radeon @@ -345,8 +375,10 @@ 5146 Radeon R100 QF 5147 Radeon R100 QG 5148 Radeon R200 QH [Radeon 8500] - 1002 0152 FireGL 8800 - 1002 0172 FireGL 8700 + 1002 010a FireGL 8800 64Mb + 1002 0152 FireGL 8800 128Mb + 1002 0162 FireGL 8700 32Mb + 1002 0172 FireGL 8700 64Mb 5149 Radeon R200 QI 514a Radeon R200 QJ 514b Radeon R200 QK @@ -355,6 +387,9 @@ 1002 013a Radeon 8500 148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition] 174b 7149 Radeon R200 QL [Sapphire Radeon 8500 LE] + 514d Radeon R200 QM [Radeon 9100] + 514e Radeon R200 QN [Radeon 8500LE] + 514f Radeon R200 QO [Radeon 8500LE] 5157 Radeon RV200 QW [Radeon 7500] 1002 013a Radeon 7500 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR] @@ -365,7 +400,7 @@ 174b 7161 Radeon RV200 QW [Radeon 7500 LE] 17af 0202 RV200 QW [Excalibur Radeon 7500LE] 5158 Radeon RV200 QX [Radeon 7500] - 5159 Radeon VE QY + 5159 Radeon RV100 QY [Radeon 7000/VE] 1002 000a Radeon 7000/Radeon VE 1002 000b Radeon 7000 1002 0038 Radeon 7000/Radeon VE @@ -377,11 +412,13 @@ 148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display] 174b 7112 RV100 QY [Sapphire Radeon VE 7000] 1787 0202 RV100 QY [Excalibur Radeon 7000] - 515a Radeon VE QZ + 515a Radeon RV100 QZ [Radeon 7000/VE] 5168 Radeon R200 Qh 5169 Radeon R200 Qi 516a Radeon R200 Qj 516b Radeon R200 Qk +# This one is not in ATI documentation, but is in XFree86 source code + 516c Radeon R200 Ql 5245 Rage 128 RE/SG 1002 0008 Xpert 128 1002 0028 Rage 128 AIW @@ -401,6 +438,7 @@ 1002 0088 Xpert 99 5345 Rage 128 SE/4x 5346 Rage 128 SF/4x AGP 2x + 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL 5347 Rage 128 SG/4x AGP 4x 5348 Rage 128 SH 534b Rage 128 SK/4x @@ -431,7 +469,11 @@ 1002 5654 Mach64VT Reference 5655 264VT3 [Mach64 VT3] 5656 264VT4 [Mach64 VT4] - 700f U1/A3 AGP Bridge [IGP 320M] + 5961 Radeon RV280 [Radeon 9200] + 700f PCI Bridge [IGP 320M] + 7010 PCI Bridge [IGP 340M] + cab0 AGP Bridge [IGP 320M] + cab2 RS200/RS200M AGP Bridge [IGP 340M] 1003 ULSI Systems 0201 US201 1004 VLSI Technology Inc @@ -485,7 +527,14 @@ 0011 NS87560 National PCI System I/O 0012 USB Controller 0020 DP83815 (MacPhyter) Ethernet Controller + 1385 f311 FA311 / FA312 (FA311 with WoL HW) 0022 DP83820 10/100/1000 Ethernet Controller + 0028 CS5535 Host bridge + 002b CS5535 ISA bridge + 002d CS5535 IDE + 002e CS5535 Audio + 002f CS5535 USB + 0030 CS5535 Video 0500 SCx200 Bridge 0501 SCx200 SMI 0502 SCx200 IDE @@ -537,6 +586,7 @@ 0014 DECchip 21041 [Tulip Pass 3] 1186 0100 DE-530+ 0016 DGLPB [OPPO] + 0017 PV-PCI Graphics Controller (ZLXp-L) 0019 DECchip 21142/43 1011 500a DE500A Fast Ethernet 1011 500b DE500B Fast Ethernet @@ -567,6 +617,7 @@ 1374 0002 Cardbus Ethernet Card 10/100 1374 0007 Cardbus Ethernet Card 10/100 1374 0008 Cardbus Ethernet Card 10/100 + 1385 2100 FA510 1395 0001 10/100 Ethernet CardBus PC Card 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200) 8086 0001 EtherExpress PRO/100 Mobile CardBus 32 @@ -585,7 +636,9 @@ 0e11 4051 Integrated Smart Array 0e11 4058 Integrated Smart Array 103c 10c2 Hewlett-Packard NetRAID-4M - 12d9 000a VoIP PCI Gateway + 12d9 000a IP Telephony card + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 9005 0365 Adaptec 5400S 9005 1364 Dell PowerEdge RAID Controller 2 9005 1365 Dell PowerEdge RAID Controller 2 @@ -650,14 +703,17 @@ 001b GXT-150P 001c Carrera 001d 82G2675 - 0020 MCA + 0020 GXT1000 Graphics Adapter 0022 IBM27-82351 002d Python - 002e ServeRAID Controller +# [official name in AIX 5] + 002e SCSI RAID Adapter [ServeRAID] 1014 002e ServeRAID-3x 1014 022e ServeRAID-4H + 0031 2 Port Serial Adapter 0036 Miami 003a CPU to PCI Bridge + 003c GXT250P/GXT255P Graphics Adapter 003e 16/4 Token ring UTP/STP controller 1014 003e Token-Ring Adapter 1014 00cd Token-Ring Adapter + Wake-On-LAN @@ -675,23 +731,30 @@ 004f ATM Controller (14104f00) 0050 ATM Controller (14105000) 0053 25 MBit ATM Controller + 0054 GXT500P/GXT550P Graphics Adapter 0057 MPEG PCI Bridge 005c i82557B 10/100 + 005e GXT800P Graphics Adapter 007c ATM Controller (14107c00) 007d 3780IDSP [MWave] + 008e GXT3000P Graphics Adapter 0090 GXT 3000P 1014 008e GXT-3000P + 0091 SSA Adapter 0095 20H2999 PCI Docking Bridge 0096 Chukar chipset SCSI controller 1014 0097 iSeries 2778 DASD IOA 1014 0098 iSeries 2763 DASD IOA 1014 0099 iSeries 2748 DASD IOA + 009f PCI 4758 Cryptographic Accelerator 00a5 ATM Controller (1410a500) 00a6 ATM 155MBPS MM Controller (1410a600) 00b7 256-bit Graphics Rasterizer [Fire GL1] + 00b8 GXT2000P Graphics Adapter 00be ATM 622MBPS Controller (1410be00) 00dc Advanced Systems Management Adapter (ASMA) 00fc CPC710 Dual Bridge and Memory Controller (PCI-64) + 0104 Gigabit Ethernet-SX Adapter 0105 CPC710 Dual Bridge and Memory Controller (PCI-32) 010f Remote Supervisor Adapter (RSA) 0142 Yotta Video Compositor Input @@ -699,6 +762,14 @@ 0144 Yotta Video Compositor Output 1014 0145 Yotta Output Controller (ytout) 0156 405GP PLB to PCI Bridge + 015e 622Mbps ATM PCI Adapter + 0160 64bit/66MHz PCI ATM 155 MMF + 016e GXT4000P Graphics Adapter + 0170 GXT6000P Graphics Adapter + 017d GXT300P Graphics Adapter + 0180 Snipe chipset SCSI controller + 1014 0241 iSeries 2757 DASD IOA + 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780) 01a7 PCI-X to PCI-X Bridge 01bd ServeRAID Controller 1014 01be ServeRAID-4M @@ -708,6 +779,19 @@ 1014 022e ServeRAID-4H 1014 0258 ServeRAID-5i 1014 0259 ServeRAID-5i + 01c1 64bit/66MHz PCI ATM 155 UTP + 01e6 Cryptographic Accelerator + 01ff 10/100 Mbps Ethernet + 0219 Multiport Serial Adapter + 1014 021a Dual RVX + 1014 0251 Internal Modem/RVX + 1014 0252 Quad Internal Modem + 021b GXT6500P Graphics Adapter + 021c GXT4500P Graphics Adapter + 0233 GXT135P Graphics Adapter + 0266 PCI-X Dual Channel SCSI + 0268 Gigabit Ethernet-SX Adapter (PCI-X) + 0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X) 0302 XA-32 chipset [Summit] ffff MPIC-2 interrupt controller 1015 LSI Logic Corp of Canada @@ -770,9 +854,16 @@ 1259 2454 AT-2450v4 10Mb Ethernet Adapter 1259 2700 AT-2700TX 10/100 Fast Ethernet 1259 2701 AT-2700FX 100Mb Ethernet + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard 2001 79c978 [HomePNA] 1092 0a78 Multimedia Home Network Adapter 1668 0299 ActionLink Home Network Adapter + 2003 Am 1771 MBW [Alchemy] 2020 53c974 [PCscsi] 2040 79c974 3000 ELanSC520 Microcontroller @@ -817,6 +908,7 @@ 746b AMD-8111 ACPI 746d AMD-8111 AC97 Audio 746e AMD-8111 MC97 Modem + 756b AMD-8111 ACPI 1023 Trident Microsystems 0194 82C194 2000 4DWave DX @@ -939,13 +1031,15 @@ 1028 00d0 PowerEdge Expandable RAID Controller 3/Si 0005 PowerEdge Expandable RAID Controller 3/Di 0006 PowerEdge Expandable RAID Controller 3/Di - 0007 Remote Assistant Card 3 - 0008 PowerEdge Expandable RAID Controller 3/Di + 0007 Remote Access Controller:DRAC III + 0008 Remote Access Controller + 0009 BMC/SMIC device not present 000a PowerEdge Expandable RAID Controller 3 1028 0106 PowerEdge Expandable RAID Controller 3/Di 1028 011b PowerEdge Expandable RAID Controller 3/Di 1028 0121 PowerEdge Expandable RAID Controller 3/Di - 000c Embedded Systems Management Device 4 + 000c Remote Access Controller:ERA or ERA/O + 000d BMC/SMIC device 000e PowerEdge Expandable RAID Controller 000f PowerEdge Expandable RAID Controller 4/Di 1029 Siemens Nixdorf IS @@ -955,9 +1049,11 @@ 102b Matrox Graphics, Inc. # DJ: I've a suspicion that 0010 is a duplicate of 0d10. 0010 MGA-I [Impression?] + 0100 MGA 1064SG [Mystique] 0518 MGA-II [Athena] 0519 MGA 2064W [Millennium] 051a MGA 1064SG [Mystique] + 102b 0100 MGA-1064SG Mystique 102b 1100 MGA-1084SG Mystique 102b 1200 MGA-1084SG Mystique 1100 102b MGA-1084SG Mystique @@ -1081,6 +1177,12 @@ 00b8 F64310 00c0 F69000 HiQVideo 102c 00c0 F69000 HiQVideo + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard 00d0 F65545 00d8 F65545 00dc F65548 @@ -1092,6 +1194,11 @@ 00f4 F68554 HiQVision 00f5 F68555 0c30 F69030 + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard +# C5C project cancelled + 4c53 1080 CT8 mainboard 102d Wyse Technology Inc. 50dc 3328 Audio 102e Olivetti Advanced Technology @@ -1107,6 +1214,7 @@ 6057 MiroVideo DC10/DC30+ 1032 Compaq 1033 NEC Corporation + 0000 Vr4181A USB Host or Function Control Unit 0001 PCI to 486-like bus Bridge 0002 PCI to VL98 Bridge 0003 ATM Controller @@ -1147,9 +1255,11 @@ 00a6 VRC5477 AC97 00cd IEEE 1394 [OrangeLink] Host Controller 12ee 8011 Root hub + 00df Vr4131 00e0 USB 2.0 12ee 7001 Root hub 1799 0002 Root Hub + 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2] 1034 Framatome Connectors USA Inc. 1035 Comp. & Comm. Research Lab 1036 Future Domain Corp. @@ -1157,7 +1267,8 @@ 1037 Hitachi Micro Systems 1038 AMP, Inc 1039 Silicon Integrated Systems [SiS] - 0001 5591/5592 AGP +# This is what all my tests report. I don't know if this is equivalent to "5591/5592 AGP". + 0001 SiS 530 Virtual PCI-to-PCI bridge (AGP) 0002 SG86C202 0006 85C501/2/3 0008 85C503/5513 @@ -1167,8 +1278,12 @@ 1039 0000 SiS5597 SVGA (Shared RAM) 0204 82C204 0205 SG86C205 - 0300 300/200 + 0300 SiS300/305 PCI/AGP VGA Display Adapter 107d 2720 Leadtek WinFast VR300 + 0310 SiS315H PCI/AGP VGA Display Adapter + 0315 SiS315 PCI/AGP VGA Display Adapter + 0325 SiS315PRO PCI/AGP VGA Display Adapter + 0330 SiS330 [Xabre] PCI/AGP VGA Display Adapter 0406 85C501/2 0496 85C496 0530 530 Host @@ -1181,6 +1296,7 @@ 0635 635 Host 0645 SiS645 Host & Memory & AGP Controller 0646 SiS645DX Host & Memory & AGP Controller + 0648 SiS 645xx 0650 650 Host 0651 SiS651 Host 0730 730 Host @@ -1188,18 +1304,23 @@ 0735 735 Host 0740 740 Host 0745 745 Host + 0746 746 Host + 0755 SiS 755 Host Bridge 0900 SiS900 10/100 Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter + 1043 8035 CUSI-FX motherboard 0961 SiS961 [MuTIOL Media IO] 0962 SiS962 [MuTIOL Media IO] 3602 83C602 5107 5107 5300 SiS540 PCI Display Adapter + 5315 SiS550 AGP/VGA VGA Display Adapter 5401 486 PCI Chipset 5511 5511/5512 5513 5513 [IDE] 1019 0970 P6STP-FL motherboard 1039 5513 SiS5513 EIDE Controller (A,B step) + 1043 8035 CUSI-FX motherboard 5517 5517 5571 5571 5581 5581 Pentium Chipset @@ -1213,8 +1334,10 @@ 6236 6236 3D-AGP 6300 SiS630 GUI Accelerator+3D 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard 6306 SiS530 3D PCI/AGP 1039 6306 SiS530,620 GUI Accelerator+3D + 6325 SiS650/651/M650/740 PCI/AGP VGA Display Adapter 6326 86C326 5598/6326 1039 6326 SiS6326 GUI Accelerator 1092 0a50 SpeedStar A50 @@ -1222,14 +1345,14 @@ 1092 4910 SpeedStar A70 1092 4920 SpeedStar A70 1569 6326 SiS6326 GUI Accelerator - 7001 7001 + 7001 USB 1.0 Controller 1039 7000 Onboard USB Controller - 7002 SiS7002 USB 2.0 + 7002 USB 2.0 Controller 1509 7002 Onboard USB Controller 7007 FireWire Controller - 7012 SiS7012 PCI Audio Accelerator - 7013 56k Winmodem (Smart Link HAMR5600 compatible) - 7016 SiS7016 10/100 Ethernet Adapter + 7012 Sound Controller + 7013 Intel 537 [56k Winmodem] + 7016 10/100 Ethernet Adapter 1039 7016 SiS7016 10/100 Ethernet Adapter 7018 SiS PCI Audio Accelerator 1014 01b6 SiS PCI Audio Accelerator @@ -1254,6 +1377,7 @@ 15c5 0111 SiS PCI Audio Accelerator 270f a171 SiS PCI Audio Accelerator a0a0 0022 SiS PCI Audio Accelerator + 7019 SiS7019 Audio Accelerator 103a Seiko Epson Corporation 103b Tatung Co. of America 103c Hewlett-Packard Company @@ -1286,7 +1410,6 @@ 103c 1226 Keystone SP2 103c 1227 Powerbar SP2 103c 1282 Everest SP2 - 1054 PCI Local Bus Adapter 1064 79C970 PCnet Ethernet Controller 108b Visualize FXe 10c1 NetServer Smart IRQ Router @@ -1298,7 +1421,7 @@ 121c NetServer PCI COM Port Decoder 1229 zx1 System Bus Adapter 122a zx1 I/O Controller - 122e PCI-X/AGP Local Bus Adapter + 122e zx1 Local Bus Adapter 1290 Auxiliary Diva Serial Port 2910 E2910A PCIBus Exerciser 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer @@ -1307,13 +1430,15 @@ 1040 Accelgraphics Inc. 1041 Computrend 1042 Micron - 1000 FDC 37C665 - 1001 37C922 + 1000 PC Tech RZ1000 + 1001 PC Tech RZ1001 3000 Samurai_0 3010 Samurai_1 3020 Samurai_IDE 1043 Asustek Computer, Inc. 0675 ISDNLink P-IN100-ST-D + 4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner] + 4057 v8200 GeForce 3 1044 Distributed Processing Technology 1012 Domino RAID Engine a400 SmartCache/Raid I-IV Controller @@ -1375,7 +1500,7 @@ c832 82C832 c861 82C861 c895 82C895 - c935 EV1935 ECTIVA MachOne PCI Audio + c935 EV1935 ECTIVA MachOne PCIAudio d568 82C825 [Firebridge 2] d721 IDE [FireStar] 1046 IPC Corporation, Ltd. @@ -1385,14 +1510,24 @@ 1000 QuickStep 1000 3000 QuickStep 3000 1049 Fountain Technologies, Inc. -104a SGS Thomson Microelectronics +# # nee SGS Thomson Microelectronics +104a STMicroelectronics 0008 STG 2000X 0009 STG 1764X 0010 STG4000 [3D Prophet Kyro Series] + 0209 STPC Consumer/Industrial North- and Southbridge + 020a STPC Atlas/ConsumerS/Consumer IIA Northbridge +# From + 0210 STPC Atlas ISA Bridge + 021a STPC Consumer S Southbridge + 021b STPC Consumer IIA Southbridge + 0500 ST70137 [Unicorn] ADSL DMT Transceiver + 0564 STPC Client Northbridge 0981 DEC-Tulip compatible 10/100 Ethernet 1746 STG 1764X 2774 DEC-Tulip compatible 10/100 Ethernet 3520 MPEG-II decoder card + 55cc STPC Client Southbridge 104b BusLogic 0140 BT-946C (old) [multimaster 01] 1040 BT-946C (BA80C30) [MultiMaster 10] @@ -1401,6 +1536,7 @@ 0500 100 MBit LAN Controller 0508 TMS380C2X Compressor Interface 1000 Eagle i/f AS + 104c PCI1510 PC card Cardbus Controller 3d04 TVP4010 [Permedia] 3d07 TVP4020 [Permedia 2] 1011 4d10 Comet @@ -1444,7 +1580,11 @@ 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) 8027 PCI4451 IEEE-1394 Controller 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100) - 8400 USR2210 22Mbps Wireless PC Card + 8029 PCI4510 IEEE-1394 Controller + 8400 ACX 100 22Mbps Wireless Interface + 8401 ACX 100 22Mbps Wireless Interface +# OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi + 9000 Wireless Interface (of unknown type) a001 TDC1570 a100 TDC1561 a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f @@ -1460,7 +1600,9 @@ ac19 PCI1221 ac1a PCI1210 ac1b PCI1450 + 0e11 b113 Armada M700 ac1c PCI1225 + 0e11 b121 Armada E500 ac1d PCI1251A ac1e PCI1211 ac1f PCI1251B @@ -1474,15 +1616,18 @@ ac41 PCI4410 PC card Cardbus Controller ac42 PCI4451 PC card Cardbus Controller 1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100) + ac44 PCI4510 PC card Cardbus Controller ac50 PCI1410 PC card Cardbus Controller ac51 PCI1420 1014 023b ThinkPad T23 (2647-4MG) + 1028 00b1 Latitude C600 10cf 1095 Lifebook C6155 e4bf 1000 CP2-2-HIPHOP ac52 PCI1451 PC card Cardbus Controller ac53 PCI1421 PC card Cardbus Controller ac55 PCI1250 PC card Cardbus Controller 1014 0512 ThinkPad T30 + ac56 PCI1510 PC card Cardbus Controller ac60 PCI2040 PCI to DSP Bridge Controller fe00 FireWire Host Controller fe03 12C01A FireWire Host Controller @@ -1564,7 +1709,9 @@ 0d38 20263 105a 4d39 Fasttrak66 1275 20275 + 3318 PDC20318 (SATA150 TX4) 3376 PDC20376 + 1043 809e A7V8X motherboard 4d30 20267 105a 4d33 Ultra100 105a 4d39 Fasttrak100 @@ -1577,6 +1724,7 @@ 4d68 20268 105a 4d68 Ultra100TX2 4d69 20269 + 105a 4d68 Ultra133TX2 5275 PDC20276 IDE 105a 0275 SuperTrak SX6000 IDE 5300 DC5300 @@ -1584,6 +1732,7 @@ 6269 PDC20271 105a 6269 FastTrak TX2/TX2000 6621 PDC20621 [SX4000] 4 Channel IDE RAID Controller + 6629 PDC20619 FastTrak TX4000 RAID 7275 PDC20277 105b Foxconn International, Inc. 105c Wipro Infotech Limited @@ -1621,6 +1770,7 @@ 13cc 0009 Barco Metheus 5 Megapixel, Dual Head 13cc 000a Barco Metheus 5 Megapixel, Dual Head 5348 Revolution 4 + 105d 0037 Revolution IV-FP AGP (For SGI 1600SW) 105e Vtech Computers Ltd 105f Infotronic America Inc 1060 United Microelectronics [UMC] @@ -1669,6 +1819,7 @@ 0002 DAC960PD 0010 DAC960PX 0050 AcceleRAID 352/170/160 support Device + b166 Gemstone chipset SCSI controller ba55 eXtremeRAID 1100 support Device ba56 eXtremeRAID 2000/3000 support Device 106a Aten Research Inc @@ -1759,6 +1910,7 @@ 2100 QLA2100 64-bit Fibre Channel Adapter 1077 0001 QLA2100 64-bit Fibre Channel Adapter 2200 QLA2200 + 1077 0002 QLA2200 2300 QLA2300 64-bit FC-AL Adapter 2312 QLA2312 Fibre Channel Adapter 1078 Cyrix Corporation @@ -1856,7 +2008,6 @@ 8001 Schizo PCI Bus Module a000 Ultra IIi a001 Ultra IIe - a801 Tomatillo PCI Bus Module 108f Systemsoft 1090 Encore Computer Corporation 1091 Intergraph Corporation @@ -1896,6 +2047,8 @@ 1190 PCI-MIO-16E-4 1330 PCI-6031E 1350 PCI-6071E + 17d0 PCI-6503 + 2410 PCI-6733 2a60 PCI-6023E b001 IMAQ-PCI-1408 b011 IMAQ-PXI-1408 @@ -1911,6 +2064,7 @@ c831 PCI-GPIB bridge 1094 First International Computers [FIC] 1095 CMD Technology Inc + 0240 Adaptec AAR-1210SA SATA HostRAID Controller 0640 PCI0640 0643 PCI0643 0646 PCI0646 @@ -1925,6 +2079,7 @@ 1095 0670 USB0670 0673 USB0673 0680 PCI0680 + 3112 Silicon Image SiI 3112 SATARaid Controller 1096 Alacron 1097 Appian Technology 1098 Quantum Designs (H.K.) Ltd @@ -1944,8 +2099,10 @@ 036c Bt879(??) Video Capture 13e9 0070 Win/TV (Video Section) 036e Bt878 Video Capture - 0070 13eb WinTV/GO + 0070 13eb WinTV Series 0070 ff01 Viewcast Osprey 200 + 107d 6606 WinFast TV 2000 + 11bd 0012 PCTV pro (TV + FM stereo receiver) 11bd 001c PCTV Sat (DBC receiver) 127a 0001 Bt878 Mediastream Controller NTSC 127a 0002 Bt878 Mediastream Controller PAL BG @@ -1996,10 +2153,11 @@ 1851 1851 FlyVideo'98 EZ - video 1852 1852 FlyVideo'98 (with FM Tuner) 0878 Bt878 Audio Capture - 0070 13eb WinTV/GO + 0070 13eb WinTV Series 0070 ff01 Viewcast Osprey 200 1002 0001 TV-Wonder 1002 0003 TV-Wonder/VE + 11bd 0012 PCTV pro (TV + FM stereo receiver, audio section) 11bd 001c PCTV Sat (DBC receiver) 127a 0001 Bt878 Video Capture (Audio Section) 127a 0002 Bt878 Video Capture (Audio Section) @@ -2055,6 +2213,7 @@ 10a3 Everex Systems Inc 10a4 Globe Manufacturing Sales 10a5 Smart Link Ltd. + 3052 SmartPCI562 56K Modem 5449 SmartPCI561 modem 10a6 Informtech Industrial Ltd. 10a7 Benchmarq Microelectronics @@ -2070,6 +2229,7 @@ 0007 RPCEX 0008 DiVO VIP 0009 Alteon Gigabit Ethernet + 10a9 8002 Acenic Gigabit Ethernet 0010 AMP Video I/O 0011 GRIP 0012 SGH PSHAC GSN @@ -2081,6 +2241,7 @@ 1006 Dual JPEG 4 1007 Dual JPEG 5 1008 Cesium + 100a IOC4 I/O controller 2001 Fibre Channel 2002 ASDE 8001 O2 1394 @@ -2134,6 +2295,7 @@ 15ed 1001 Macrolink MCCS 16-port Serial 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap + 5654 5634 OpenLine4 Telephony Card d531 c002 PCIntelliCAN 2xSJA1000 CAN bus d84d 4006 EX-4006 1P d84d 4008 EX-4008 1P EPP/ECP @@ -2154,6 +2316,8 @@ d84d 4078 EX-4078 2S(16C552) RS-232+1P 9054 PCI <-> IOBus Bridge 10b5 2455 Wessex Techology PHIL-PCI + 10b5 2696 Innes Corp AM Radcap card + 12d9 0002 PCI Prosody Card rev 1.5 9060 9060 906d 9060SD 125c 0640 Aries 16000P @@ -2161,6 +2325,8 @@ 9080 9080 10b5 9080 9080 [real subsystem ID not set] 129d 0002 Aculab PCI Prosidy card + 12d9 0002 PCI Prosody Card + bb04 B&B 3PCIOSD1A Isolated PCI Serial 10b6 Madge Networks 0001 Smart 16/4 PCI Ringnode 0002 Smart 16/4 PCI Ringnode Mk2 @@ -2188,12 +2354,11 @@ 1001 Collage 155 ATM Server Adapter 10b7 3Com Corporation 0001 3c985 1000BaseSX (SX/TX) + 0910 3C910-A01 1006 MINI PCI type 3B Data Fax Modem 1007 Mini PCI 56k Winmodem 10b7 615c Mini PCI 56K Modem - 1700 Gigabit Ethernet Adapter - 10b7 0010 3Com 3C940 Gigabit LOM Ethernet Adapter - 10b7 0020 3Com 3C941 Gigabit LOM Ethernet Adapter + 1700 3c940 1000Base? 3390 3c339 TokenLink Velocity 3590 3c359 TokenLink Velocity XL 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B) @@ -2226,6 +2391,7 @@ 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus 6564 3CCFEM656 [id 6564] Cyclone CardBus 7646 3cSOHO100-TX Hurricane + 7770 3CRWE777 PCI(PLX) Wireless Adaptor [Airconnect] 7940 3c803 FDDILink UTP Controller 7980 3c804 FDDILink SAS Controller 7990 3c805 FDDILink DAS Controller @@ -2266,10 +2432,11 @@ 9058 3c905B-Combo [Deluxe Etherlink XL 10/100] 905a 3c905B-FX [Fast Etherlink XL FX 10/100] 9200 3c905C-TX/TX-M [Tornado] - 1028 0095 Integrated 3C905C-TX Fast Etherlink for PC Management NIC + 1028 0095 3C920 Integrated Fast Ethernet Controller + 1028 0097 3C920 Integrated Fast Ethernet Controller 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC 10b7 7000 10/100 Mini PCI Ethernet Adapter - 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9201 3C920B-EMB Integrated Fast Ethernet Controller 9300 3CSOHO100B-TX [910-A01] 9800 3c980-TX [Fast Etherlink XL Server Adapter] 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter @@ -2277,6 +2444,7 @@ 10b7 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra] 10b7 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra] 10b7 9805 3c980 10/100baseTX NIC [Python-T] + 10f1 2462 Thunder K7 S2462 9900 3C990-TX [Typhoon] 9902 3CR990-TX-95 [Typhoon 56-bit] 9903 3CR990-TX-97 [Typhoon 168-bit] @@ -2370,12 +2538,16 @@ 5251 M5251 P1394 OHCI 1.0 Controller 5253 M5253 P1394 OHCI 1.1 Controller 5261 M5261 Ethernet Controller + 5450 Lucent Technologies Soft Modem AMR 5451 M5451 PCI AC-Link Controller Audio Device 1014 0506 ThinkPad R30 5453 M5453 PCI AC-Link Controller Modem Device 5455 M5455 PCI AC-Link Controller Audio Device - 5457 M5457 AC-Link Modem Interface Controller - 5459 SmartPCI561 56K Modem + 5457 Intel 537 [M5457 AC-Link Modem] +# Same but more usefull for driver's lookup + 5459 SmartLink SmartPCI561 56K Modem +# SmartLink PCI SoftModem + 545a SmartLink SmartPCI563 56K Modem 5471 M5471 Memory Stick Controller 5473 M5473 SD-MMC Controller 7101 M7101 PMU @@ -2444,7 +2616,10 @@ 10c9 Dataexpert Corporation 10ca Fujitsu Microelectr., Inc. 10cb Omron Corporation -10cc Mentor ARC Inc +# nee Mentor ARC Inc +10cc Mai Logic Incorporated + 0660 Articia S Host Bridge + 0661 Articia S PCI Bridge 10cd Advanced System Products, Inc 1100 ASC1100 1200 ASC1200 [(abp940) Fast SCSI-II] @@ -2453,9 +2628,9 @@ 2300 ABP940-UW 2500 ABP940-U2W 10ce Radius -10cf Citicorp TTI +# nee Citicorp TTI +10cf Fujitsu Limited. 2001 mb86605 -10d0 Fujitsu Limited 10d1 FuturePlus Systems Corp. 10d2 Molex Incorporated 10d3 Jabil Circuit Inc @@ -2485,7 +2660,7 @@ 0008 NV1 [EDGE 3D] 0009 NV1 [EDGE 3D] 0010 NV2 [Mutara V08] - 0020 NV4 [Riva TnT] + 0020 NV4 [RIVA TNT] 1043 0200 V3400 TNT 1048 0c18 Erazor II SGRAM 1048 0c1b Erazor II @@ -2507,11 +2682,12 @@ 10de 0020 Riva TNT 1102 1015 Graphics Blaster CT6710 1102 1016 Graphics Blaster RIVA TNT - 0028 NV5 [Riva TnT2] + 0028 NV5 [RIVA TNT2/TNT2 Pro] 1043 0200 AGP-V3800 SGRAM 1043 0201 AGP-V3800 SDRAM 1043 0205 PCI-V3800 1043 4000 AGP-V3800PRO + 1048 0c21 Synergy II 1092 4804 Viper V770 1092 4a00 Viper V770 1092 4a02 Viper V770 Ultra @@ -2523,7 +2699,7 @@ 1102 1020 3D Blaster RIVA TNT2 1102 1026 3D Blaster RIVA TNT2 Digital 14af 5810 Maxi Gamer Xentor - 0029 NV5 [Riva TnT2 Ultra] + 0029 NV5 [RIVA TNT2 Ultra] 1043 0200 AGP-V3800 Deluxe 1043 0201 AGP-V3800 Ultra SDRAM 1043 0205 PCI-V3800 Ultra @@ -2533,17 +2709,18 @@ 14af 5820 Maxi Gamer Xentor 32 002a NV5 [Riva TnT2] 002b NV5 [Riva TnT2] - 002c NV6 [Vanta] + 002c NV6 [Vanta/Vanta LT] 1043 0200 AGP-V3800 Combat SDRAM 1043 0201 AGP-V3800 Combat 1092 6820 Viper V730 1102 1031 CT6938 VANTA 8MB 1102 1034 CT6894 VANTA 16MB 14af 5008 Maxi Gamer Phoenix 2 - 002d RIVA TNT2 Model 64 + 002d NV5M64 [RIVA TNT2 Model 64/Model 64 Pro] 1043 0200 AGP-V3800M 1043 0201 AGP-V3800M 1048 0c3a Erazor III LT + 10de 001e M64 AGP4x 1102 1023 CT6892 RIVA TNT2 Value 1102 1024 CT6932 RIVA TNT2 Value 32Mb 1102 102c CT6931 RIVA TNT2 Value [Jumper] @@ -2551,8 +2728,32 @@ 1554 1041 PixelView RIVA TNT2 M64 32MB 002e NV6 [Vanta] 002f NV6 [Vanta] - 00a0 NV5 [Riva TNT2] + 0060 nForce2 ISA Bridge + 1043 80ad A7N8X Mainboard + 0064 nForce2 SMBus (MCP) + 0065 nForce2 IDE + 0066 nForce2 Ethernet Controller + 0067 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + 0068 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + 006a nForce2 AC97 Audio Controler (MCP) + 006b nForce MultiMedia audio [Via VT82C686B] + 006c nForce2 External PCI Bridge + 006d nForce2 PCI Bridge + 006e nForce2 FireWire (IEEE 1394) Controller + 00a0 NV5 [Aladdin TNT2] 14af 5810 Maxi Gamer Xentor + 00d0 nForce3 LPC Bridge + 00d1 nForce3 Host Bridge + 00d2 nForce3 AGP Bridge + 00d4 nForce3 SMBus + 00d5 nForce3 IDE + 00d6 nForce3 Ethernet + 00d7 nForce3 USB 1.1 + 00d8 nForce3 USB 2.0 + 00da nForce3 Audio + 00dd nForce3 PCI Bridge 0100 NV10 [GeForce 256 SDR] 1043 0200 AGP-V6600 SGRAM 1043 0201 AGP-V6600 SDRAM @@ -2560,45 +2761,57 @@ 1043 4009 AGP-V6600 SDRAM 1102 102d CT6941 GeForce 256 14af 5022 3D Prophet SE - 0101 NV10 [GeForce 256 DDR] + 0101 NV10DDR [GeForce 256 DDR] 1043 0202 AGP-V6800 DDR 1043 400a AGP-V6800 DDR SGRAM 1043 400b AGP-V6800 DDR SDRAM + 107d 2822 WinFast GeForce 256 1102 102e CT6971 GeForce 256 DDR 14af 5021 3D Prophet DDR-DVI - 0103 NV10 [Quadro] - 0110 NV11 [GeForce2 MX] + 0103 NV10GL [Quadro] + 0110 NV11 [GeForce2 MX/MX 400] 1043 4015 AGP-V7100 Pro 1043 4031 V7100 Pro with TV output + 1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817] 14af 7102 3D Prophet II MX 14af 7103 3D Prophet II MX Dual-Display - 0111 NV11 [GeForce2 MX DDR] + 0111 NV11DDR [GeForce2 MX 100 DDR/200 DDR] 0112 NV11 [GeForce2 Go] - 0113 NV11 [GeForce2 MXR] - 0150 NV15 [GeForce2 GTS] + 0113 NV11GL [Quadro2 MXR/EX] + 0150 NV15 [GeForce2 GTS/Pro] 1043 4016 V7700 AGP Video Card 107d 2840 WinFast GeForce2 GTS with TV output 1462 8831 Creative GeForce2 Pro - 0151 NV15 [GeForce2 Ti] + 0151 NV15DDR [GeForce2 Ti] 1043 405f V7700Ti - 0152 NV15 [GeForce2 Ultra, Bladerunner] + 0152 NV15BR [GeForce2 Ultra, Bladerunner] 1048 0c56 GLADIAC Ultra - 0153 NV15 [Quadro2 Pro] - 0170 NV17 [GeForce4 MX460] - 0171 NV17 [GeForce4 MX440] + 0153 NV15GL [Quadro2 Pro] + 0170 NV17 [GeForce4 MX 460] + 0171 NV17 [GeForce4 MX 440] + 10b0 0002 Gainward Pro/600 TV 1462 8661 G4MX440-VTP - 0172 NV17 [GeForce4 MX420] - 0173 NV1x + 1462 8730 MX440SES-T (MS-8873) + 147b 8f00 Abit Siluro GeForce4MX440 + 0172 NV17 [GeForce4 MX 420] + 0173 NV17 [GeForce4 MX 440-SE] 0174 NV17 [GeForce4 440 Go] 0175 NV17 [GeForce4 420 Go] 0176 NV17 [GeForce4 420 Go 32M] - 0178 Quadro4 500XGL + 0178 NV17GL [Quadro4 550 XGL] 0179 NV17 [GeForce4 440 Go 64M] - 017a Quadro4 200/400NVS - 017b Quadro4 550XGL - 017c Quadro4 550 GoGL - 0181 NV18 [GeForce4 MX440 AGP 8x] - 01a0 NV15 [GeForce2 - nForce GPU] + 017a NV17GL [Quadro4 200/400 NVS] + 017b NV17GL [Quadro4 550 XGL] + 017c NV17GL [Quadro4 550 GoGL] + 0181 NV18 [GeForce4 MX 440 AGP 8x] + 1043 806f V9180 Magic + 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X + 0182 NV18 [GeForce4 MX 440SE AGP 8x] + 0183 NV18 [GeForce4 MX 420 AGP 8x] + 0188 NV18GL [Quadro4 580 XGL] + 018a NV18GL [Quadro4 NVS AGP 8x] + 018b NV18GL [Quadro4 380 XGL] + 01a0 NVCrush11 [GeForce2 MX Integrated Graphics] 01a4 nForce CPU bridge 01ab nForce 420 Memory Controller (DDR) 01ac nForce 220/420 Memory Controller @@ -2609,24 +2822,53 @@ 01b7 nForce AGP to PCI Bridge 01b8 nForce PCI-to-PCI bridge 01bc nForce IDE - 01c1 nForce MC97 Modem (Smart Link HAMR5600 compatible) + 01c1 Intel 537 [nForce MC97 Modem] 01c2 nForce USB Controller 01c3 nForce Ethernet Controller + 01e0 nForce2 AGP (different version?) + 01e8 nForce2 AGP + 01ea nForce2 Memory Controller 0 + 01eb nForce2 Memory Controller 1 + 01ec nForce2 Memory Controller 2 + 01ed nForce2 Memory Controller 3 + 01ee nForce2 Memory Controller 4 + 01ef nForce2 Memory Controller 5 + 01f0 NV18 [GeForce4 MX - nForce GPU] 0200 NV20 [GeForce3] 1043 402f AGP-V8200 DDR - 0201 NV20 [GeForce3 Ti200] - 0202 NV20 [GeForce3 Ti500] + 0201 NV20 [GeForce3 Ti 200] + 0202 NV20 [GeForce3 Ti 500] 1043 405b V8200 T5 1545 002f Xtasy 6964 - 0203 NV20 [Quadro DCC] - 0250 NV25 [GeForce4 Ti4600] - 0251 NV25 [GeForce4 Ti4400] - 0253 NV25 [GeForce4 Ti4200] + 0203 NV20DCC [Quadro DCC] + 0250 NV25 [GeForce4 Ti 4600] + 0251 NV25 [GeForce4 Ti 4400] + 0252 NV25 [GeForce4 Ti] + 0253 NV25 [GeForce4 Ti 4200] 107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI) 147b 8f09 Siluro (Dual VGA/TV-out/DVI) - 0258 Quadro4 900XGL - 0259 Quadro4 750XGL - 025b Quadro4 700XGL + 0258 NV25GL [Quadro4 900 XGL] + 0259 NV25GL [Quadro4 750 XGL] + 025b NV25GL [Quadro4 700 XGL] + 0280 NV28 [GeForce4 Ti 4800] + 0281 NV28 [GeForce4 Ti 4200 AGP 8x] + 0282 NV28 [GeForce4 Ti 4800 SE] + 0286 NV28 [GeForce4 Ti 4200 Go AGP 8x] + 0288 NV28GL [Quadro4 980 XGL] + 0289 NV28GL [Quadro4 780 XGL] + 0300 NV30 [GeForce FX] + 0301 NV30 [GeForce FX 5800 Ultra] + 0302 NV30 [GeForce FX 5800] + 0308 NV30GL [Quadro FX 2000] + 0309 NV30GL [Quadro FX 1000] + 0311 NV31 [GeForce FX 5600 Ultra] + 0312 NV31 [GeForce FX 5600] + 0321 NV34 [GeForce FX 5200 Ultra] + 0322 NV34 [GeForce FX 5200] + 032b NV34GL [Quadro FX 500] + 0330 NV35 [GeForce FX 5900 Ultra] + 0331 NV35 [GeForce FX 5900] + 0338 NV35GL [Quadro FX 3000] 10df Emulex Corporation 1ae5 LP6000 Fibre Channel Host Adapter f085 LP850 Fibre Channel Adapter @@ -2652,6 +2894,7 @@ 10e3 Tundra Semiconductor Corp. 0000 CA91C042 [Universe] 0860 CA91C860 [QSpan] + 0862 CA91C862A [QSpan-II] 10e4 Tandem Computers 10e5 Micro Industries Corporation 10e6 Gainbery Computer Products Inc. @@ -2672,6 +2915,7 @@ 811a PCI-IEEE1355-DS-DE Interface 8170 S5933 [Matchmaker] (Chipset Development Tool) 82db AJA HDNTV HD SDI Framestore + 8851 S5933 on Innes Corp FM Radio Capture card 10e9 Alps Electric Co., Ltd. 10ea Intergraphics Systems 1680 IGA-1680 @@ -2681,6 +2925,7 @@ 2010 CyberPro 2000A 5000 CyberPro 5000 5050 CyberPro 5050 + 5202 CyberPro 5202 10eb Artists Graphics 0101 3GA 8111 Twist3 Frame Grabber @@ -2719,6 +2964,7 @@ 8e2e 7100 KF-230TX/2 a0a0 0007 ALN-325C 8169 RTL-8169 + 1371 434e ProG-2000L 8197 SmartLAN56 56K Modem 10ed Ascii Corporation 7310 V7310 @@ -2729,6 +2975,7 @@ 3fc3 RME Digi96/8 Pad 3fc4 RME Digi9652 (Hammerfall) 3fc5 RME Hammerfall DSP + 8381 Ellips Santos Frame Grabber 10ef Racore Computer Products, Inc. 8154 M815x Token Ring Adapter 10f0 Peritek Corporation @@ -2777,6 +3024,8 @@ 1102 8040 CT4760 SBLive! 1102 8051 CT4850 SBLive! Value 1102 8061 SBLive! Player 5.1 + 1102 8064 SB Live! 5.1 Model SB0100 + 1102 8065 SBLive! 5.1 Digital Model SB0220 0004 SB Audigy 1102 0051 SB0090 Audigy Player 1102 0053 SB0090 Audigy Player/OEM @@ -2788,7 +3037,8 @@ 7003 SB Audigy MIDI/Game port 1102 0040 SB Audigy MIDI/Game Port 7004 [SB Live! Value] Input device controller - 8938 ES1371 + 8064 SB0100 [SBLive! 5.1 OEM] + 8938 Ectiva EV1938 1103 Triones Technologies, Inc. 0003 HPT343 # Revisions: 01=HPT366, 03=HPT370, 04=HPT370A, 05=HPT372 @@ -2799,6 +3049,7 @@ 0006 HPT302 0007 HPT371 0008 HPT374 + 0009 HPT372N 1104 RasterOps Corp. 1105 Sigma Designs, Inc. 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder @@ -2809,15 +3060,21 @@ 0130 VT6305 1394.A Controller 0305 VT8363/8365 [KT133/KM133] 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8042 A7V133/A7V133-C Mainboard 147b a401 KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard 0391 VT8371 [KX133] 0501 VT8501 [Apollo MVP4] 0505 VT82C505 - 0561 VT82C561 - 0571 VT82C586/B/686A/B PIPC Bus Master IDE +# Shares chip with :0576. The VT82C576M has :1571 instead of :0561. + 0561 VT82C576MV + 0571 VT82C586A/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 1019 0985 P6VXA Motherboard 1043 8052 VT8233A Bus Master ATA100/66/33 IDE - 1106 0571 VT8235 Bus Master ATA133/100/66/33 IDE + 1043 808c A7V8X motherboard + 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 1179 0001 Magnia Z310 + 1297 f641 FX41 motherboard 1458 5002 GA-7VAX Mainboard 0576 VT82C576 3V [Apollo Master] 0585 VT82C585VP [Apollo VP1/VPX] @@ -2831,24 +3088,36 @@ 0598 VT82C598 [Apollo MVP3] 0601 VT8601 [Apollo ProMedia] 0605 VT8605 [ProSavage PM133] + 1043 802c CUV4X mainboard 0680 VT82C680 [Apollo P6] 0686 VT82C686 [Apollo Super South] + 1019 0985 P6VXA Motherboard + 1043 802c CUV4X mainboard 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8040 A7M266 Mainboard 1043 8042 A7V133/A7V133-C Mainboard 1106 0000 VT82C686/A PCI to ISA Bridge 1106 0686 VT82C686/A PCI to ISA Bridge + 1179 0001 Magnia Z310 + 147b a702 KG7-Lite Mainboard 0691 VT82C693A/694x [Apollo PRO133x] + 1019 0985 P6VXA Motherboard + 1179 0001 Magnia Z310 1458 0691 VT82C691 Apollo Pro System Controller 0693 VT82C693 [Apollo Pro Plus] 0698 VT82C693A [Apollo Pro133 AGP] 0926 VT82C926 [Amazon] 1000 VT82C570MV 1106 VT82C570MV - 1571 VT82C416MV + 1571 VT82C576M/VT82C586 1595 VT82C595/97 [Apollo VP2/97] 3038 USB - 0925 1234 MVP3 USB Controller + 0925 1234 USB Controller + 1019 0985 P6VXA Motherboard + 1043 808c A7V8X motherboard + 1179 0001 Magnia Z310 + 1458 5004 GA-7VAX Mainboard 3040 VT82C586B ACPI 3043 VT86C100A [Rhine] 10bd 0000 VT86C100A Fast Ethernet Adapter @@ -2858,22 +3127,29 @@ 3050 VT82C596 Power Management 3051 VT82C596 Power Management 3057 VT82C686 [Apollo Super ACPI] + 1019 0985 P6VXA Motherboard 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard 1043 8040 A7M266 Mainboard 1043 8042 A7V133/A7V133-C Mainboard + 1179 0001 Magnia Z310 3058 VT82C686 AC97 Audio Controller 0e11 b194 Soundmax integrated digital audio + 1019 0985 P6VXA Motherboard 1106 4511 Onboard Audio on EP7KXA 1458 7600 Onboard Audio 1462 3091 MS-6309 Onboard Audio 15dd 7609 Onboard Audio - 3059 VT8233 AC97 Audio Controller + 3059 VT8233/A/8235 AC97 Audio Controller + 1043 8095 A7V8X Motherboard (Realtek ALC650 codec) + 1297 c160 FX41 motherboard (Realtek ALC650 codec) 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650) 3065 VT6102 [Rhine-II] 1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235 1186 1400 DFE-530TX rev A 1186 1401 DFE-530TX rev B - 3068 AC97 Modem Controller + 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B) + 3068 Intel 537 [AC97 Modem] 3074 VT8233 PCI to ISA Bridge 1043 8052 VT8233A 3091 VT8633 [Apollo Pro266] @@ -2884,11 +3160,18 @@ 3102 VT8662 Host Bridge 3103 VT8615 Host Bridge 3104 USB 2.0 + 1043 808c A7V8X motherboard + 1297 f641 FX41 motherboard 1458 5004 GA-7VAX Mainboard 3106 VT6105 [Rhine-III] 3109 VT8233C PCI to ISA Bridge 3112 VT8361 [KLE133] Host Bridge - 3116 VT8375 [KM266] Host Bridge + 3116 VT8375 [KM266/KL266] Host Bridge + 1297 f641 FX41 motherboard +# found on EPIA M6000/9000 mainboard + 3122 VT8623 [Apollo CLE266] integrated CastleRock graphics +# found on EPIA M6000/9000 mainboard + 3123 VT8623 [Apollo CLE266] 3128 VT8753 [P4X266 AGP] 3133 VT3133 Host Bridge 3147 VT8233A ISA Bridge @@ -2896,8 +3179,11 @@ 3156 P/KN266 Host Bridge 3168 VT8374 P4X400 Host Controller/AGP Bridge 3177 VT8235 ISA Bridge + 1043 808c A7V8X motherboard + 1297 f641 FX41 motherboard 1458 5001 GA-7VAX Mainboard 3189 VT8377 [KT400 AGP] Host Bridge + 1043 807f A7V8X motherboard 1458 5000 GA-7VAX Mainboard 5030 VT82C596 ACPI [Apollo PRO] 6100 VT85C100A [Rhine II] @@ -2909,6 +3195,7 @@ 8596 VT82C596 [Apollo PRO AGP] 8597 VT82C597 [Apollo VP3 AGP] 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP] + 1019 0985 P6VXA Motherboard 8601 VT8601 [Apollo ProMedia AGP] 8605 VT8605 [PM133 AGP] 8691 VT82C691 [Apollo Pro] @@ -2920,6 +3207,7 @@ b103 VT8615 AGP Bridge b112 VT8361 [KLE133] AGP Bridge b168 VT8235 PCI Bridge + b198 VT8237 PCI Bridge 1107 Stratus Computers 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) 1108 Proteon, Inc. @@ -2936,7 +3224,14 @@ 110a Siemens Nixdorf AG 0002 Pirahna 2-port 0005 Tulip controller, power management, switch extender + 0006 FSC PINC (I/O-APIC) + 0015 FSC Multiprocessor Interrupt Controller + 001d FSC Copernicus Management Controller + 007b FSC Remote Service Controller, mailbox device + 007c FSC Remote Service Controller, shared memory device + 007d FSC Remote Service Controller, SMIC device 2102 DSCC4 WAN adapter + 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) 4942 FPGA I-Bus Tracer for MBD 6120 SZB6120 110b Chromatic Research Inc. @@ -3102,10 +3397,16 @@ 0001 MVC IM-PCI Video frame grabber/processor 1130 Computervision 1131 Philips Semiconductors + 1561 USB 1.1 Host Controller + 1562 USB 2.0 Host Controller 3400 SmartPCI56(UCB1500) 56K Modem 7130 SAA7130 Video Broadcast Decoder + 5168 0138 LiveView FlyVideo 2000 + 7133 SAA7133 Audio+video broadcast decoder + 5168 0138 LifeView FlyVideo 3000 # PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl) 7134 SAA7134 + 7135 SAA7135 Audio+video broadcast decoder 7145 SAA7145 7146 SAA7146 114b 2003 DVRaptor Video Edit/Capture Card @@ -3124,24 +3425,59 @@ b921 EiconCard P92 b922 EiconCard P92 b923 EiconCard P92 - e001 DIVA 20PRO - 1133 e001 DIVA Pro 2.0 S/T - e002 DIVA 20 - 1133 e002 DIVA 2.0 S/T - e003 DIVA 20PRO_U - 1133 e003 DIVA Pro 2.0 U - e004 DIVA 20_U - 1133 e004 DIVA 2.0 U - e005 DIVA LOW - 1133 e005 DIVA 2.01 S/T - e00b Eicon Diva 2.02 - e010 DIVA Server BRI-2M - 1133 e010 DIVA Server BRI-2M - e012 DIVA Server BRI-8M - 1133 e012 DIVA Server BRI-8M - e014 DIVA Server PRI-30M - 1133 e014 DIVA Server PRI-30M - e018 DIVA Server BRI-2M/-2F + e001 Diva Pro 2.0 S/T + e002 Diva 2.0 S/T PCI + e003 Diva Pro 2.0 U + e004 Diva 2.0 U PCI + e005 Diva 2.01 S/T PCI + e006 Diva CT S/T PCI + e007 Diva CT U PCI + e008 Diva CT Lite S/T PCI + e009 Diva CT Lite U PCI + e00a Diva ISDN+V.90 PCI + e00b Diva 2.02 PCI S/T + e00c Diva 2.02 PCI U + e00d Diva ISDN Pro 3.0 PCI + e00e Diva ISDN+CT S/T PCI Rev 2 + e010 Diva Server BRI-2M PCI + 110a 0021 Fujitsu Siemens ISDN S0 + 8001 0014 Diva Server BRI-2M PCI Cornet NQ + e011 Diva Server BRI S/T Rev 2 + e012 Diva Server 4BRI-8M PCI + 8001 0014 Diva Server 4BRI-8M PCI Cornet NQ + e013 Diva Server 4BRI-8M Rev 2 + 8001 0014 Diva Server 4BRI-8M Cornet NQ 2 + e014 Diva Server PRI-30M PCI + 0008 0100 Diva Server PRI-30M PCI + 8001 0014 Diva Server PRI-30M PCI Cornet NQ + e015 DIVA Server PRI-30M 2.0 + 8001 0014 Diva Server PRI Cornet NQ 2 + e016 Diva Server Voice 4BRI PCI + 8001 0014 Diva Server PRI Cornet NQ + e017 Diva Server Voice 4BRI PCI Rev 2 + 8001 0014 Diva Server Voice 4BRI PCI Cornet NQ 2 + e018 Diva Server BRI 2M Revision 2 + 8001 0014 Diva Server BRI 2M Cornet NQ 2 + e019 Diva Server Voice PRI PCI Rev 2 + 8001 0014 Diva Server Voice PRI PCI Cornet NQ 2 + e01a Diva Server 2FX + e01b Diva Server BRI-2M Voice Revision 2 + 8001 0014 Diva Server BRI-2M Voice Cornet NQ 2 + e01c Diva Server PRI Rev 3.0 + 1133 1c01 Diva Server PRI/E1/T1-8 Rev 3.0 + 1133 1c02 Diva Server PRI/T1-24 Rev 3.0 + 1133 1c03 Diva Server PRI/E1-30 Rev 3.0 + 1133 1c04 Diva Server V-PRI/E1/T1 Rev 3.0 + 1133 1c05 Diva Server V-PRI/T1-24 Rev 3.0 + 1133 1c06 Diva Server V-PRI/E1-30 Rev 3.0 + 1133 1c07 Diva Server PRI/E1/T1-8 Cornet NQ 3 + 1133 1c08 Diva Server PRI/T1-24 Cornet NQ 3 + 1133 1c09 Diva Server PRI/E1-30 Cornet NQ 3 + 1133 1c0a Diva Server V-PRI/E1/T1 Cornet NQ 3 + 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ 3 + 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ 3 + e01e Diva Server 2PRI + e020 Diva Server 4PRI 1134 Mercury Computer Systems 0001 Raceway Bridge 1135 Fuji Xerox Co Ltd @@ -3209,37 +3545,24 @@ 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) 4200 Token Ring adapter - 4300 SK-98xx Gigabit Ethernet Server Adapter - 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - 1259 2970 Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - 1259 2971 Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - 1259 2972 Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - 1259 2973 Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - 1259 2974 Allied Telesyn AT-2971T Gigabit Ethernet Adapter - 1259 2975 Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - 1259 2976 Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - 1259 2977 Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - 4320 SK-98xx V2.0 Gigabit Ethernet Adapter - 1148 0121 Marvell RDK-8001 Adapter - 1148 0221 Marvell RDK-8002 Adapter - 1148 0321 Marvell RDK-8003 Adapter - 1148 0421 Marvell RDK-8004 Adapter - 1148 0621 Marvell RDK-8006 Adapter - 1148 0721 Marvell RDK-8007 Adapter - 1148 0821 Marvell RDK-8008 Adapter - 1148 0921 Marvell RDK-8009 Adapter - 1148 1121 Marvell RDK-8011 Adapter - 1148 1221 Marvell RDK-8012 Adapter - 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter + 4300 Gigabit Ethernet + 1148 9821 SK-9821 (1000Base-T single link) + 1148 9822 SK-9822 (1000Base-T dual link) + 1148 9841 SK-9841 (1000Base-LX single link) + 1148 9842 SK-9842 (1000Base-LX dual link) + 1148 9843 SK-9843 (1000Base-SX single link) + 1148 9844 SK-9844 (1000Base-SX dual link) + 1148 9861 SK-9861 (1000Base-SX VF45 single link) + 1148 9862 SK-9862 (1000Base-SX VF45 dual link) +# Information got from SysKonnekt + 1148 9871 SK-9871 (1000Base-ZX single link) +# Information got from SysKonnekt + 1148 9872 SK-9872 (1000Base-ZX dual link) + 1259 2970 AT-2970SX [Allied Telesyn] + 1259 2972 AT-2970T [Allied Telesyn] + 1259 2975 AT-2970SX [Allied Telesyn] + 1259 2977 AT-2970T [Allied Telesyn] + 4320 SK-98xx Gigabit Ethernet Server Adapter 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter @@ -3247,8 +3570,7 @@ 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter 1148 9521 SK-9521 10/100/1000Base-T Adapter - 4400 SK-9Dxx Gigabit Ethernet Adapter - 4500 SK-9Mxx Gigabit Ethernet Adapter + 4400 Gigabit Ethernet 1149 Win System Corporation 114a VMIC 5579 VMIPCI-5579 (Reflective Memory Card) @@ -3364,6 +3686,7 @@ 0001 Motion TPEG Recorder/Player with audio 1166 ServerWorks 0005 CNB20-LE Host Bridge + 0006 CNB20HE Host Bridge 0007 CNB20-LE Host Bridge 0008 CNB20HE Host Bridge 0009 CNB20LE Host Bridge @@ -3377,14 +3700,20 @@ 0017 GCNB-LE Host Bridge 0200 OSB4 South Bridge 0201 CSB5 South Bridge + 4c53 1080 CT8 mainboard 0203 CSB6 South Bridge 0211 OSB4 IDE Controller 0212 CSB5 IDE Controller + 4c53 1080 CT8 mainboard 0213 CSB6 RAID/IDE Controller 0220 OSB4/CSB5 OHCI USB Controller + 4c53 1080 CT8 mainboard 0221 CSB6 OHCI USB Controller 0225 GCLE Host Bridge +# cancelled + 4c53 1080 CT8 mainboard 0227 GCLE-2 Host Bridge + 4c53 1080 CT8 mainboard 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing @@ -3435,7 +3764,9 @@ 0465 RL5c465 0466 RL5c466 0475 RL5c475 + 144d c006 vpr Matrix 170B4 CardBus bridge 0476 RL5c476 II + 1014 0185 ThinkPad A/T/X Series 104d 80df Vaio PCG-FX403 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 0477 RL5c477 @@ -3444,7 +3775,9 @@ 0522 R5C522 IEEE 1394 Controller 1014 01cf ThinkPad A30p (2653-64G) 0551 R5C551 IEEE 1394 Controller + 144d c006 vpr Matrix 170B4 0552 R5C552 IEEE 1394 Controller + 1014 0511 ThinkPad A/T/X Series 1181 Telmatics International 1183 Fujikura Ltd 1184 Forks Inc @@ -3460,8 +3793,6 @@ 1340 DFE-690TXD CardBus PC Card 1561 DRP-32TXD Cardbus PC Card 4000 DL2K Ethernet - 4c00 Gigabit Ethernet Adapter - 1186 4c00 DGE-530T Gigabit Ethernet Adapter 1187 Advanced Technology Laboratories, Inc. 1188 Shima Seiki Manufacturing Ltd. 1189 Matsushita Electronics Co Ltd @@ -3539,9 +3870,6 @@ 11aa Actel 11ab Galileo Technology Ltd. 0146 GT-64010/64010A System Controller - 4146 GT-64111 System Controller - 4320 Gigabit Ethernet Adapter - 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter 4611 GT-64115 System Controller 4620 GT-64120/64120A/64121A System Controller 4801 GT-48001 @@ -3637,6 +3965,7 @@ 0443 LT WinModem 0444 LT WinModem 0445 LT WinModem + 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card) 0446 LT WinModem 0447 LT WinModem 0448 WinModem 56k @@ -3666,6 +3995,7 @@ 044e LT WinModem 044f V90 WildWire Modem 0450 LT WinModem + 1033 80a8 Versa Note Vxi 144f 4005 Magnia SG20 0451 LT WinModem 0452 LT WinModem @@ -3683,6 +4013,8 @@ 0480 Venus Modem (V90, 56KFlex) 5801 USB 5802 USS-312 USB Controller +# 4 port PCI USB Controller made by Agere (formely Lucent) + 5803 USS-344S USB Controller 5811 FW323 dead 0800 FireWire Host Bus Adapter 11c2 Sand Microelectronics @@ -3726,7 +4058,6 @@ 11d9 TEC Corporation 11da Novell 11db Sega Enterprises Ltd - 1234 Broadband Adapter 11dc Questra Corporation 11dd Crosfield Electronics Limited 11de Zoran Corporation @@ -3786,32 +4117,28 @@ 11fc Silicon Magic 11fd High Street Consultants 11fe Comtrol Corporation - 0001 Rocketport 32 port w/external I/F - 0002 Rocketport 8 port w/external I/F - 0003 Rocketport 16 port w/external I/F - 0004 Rocketport 4 port w/quad cable - 0005 Rocketport 8 port w/octa cable - 0006 Rocketport 8 port w/RJ11 connectors - 0007 Rocketport 4 port w/RJ11 connectors - 0008 Rocketport 8 port w/ DB78 SNI (Siemens) connector - 0009 Rocketport 16 port w/ DB78 SNI (Siemens) connector - 000a Rocketport Plus 4 port - 000b Rocketport Plus 8 port - 000c RocketModem 6 port - 000d RocketModem 4-port - 000e Rocketport Plus 2 port RS232 - 000f Rocketport Plus 2 port RS422 - 0801 Rocketport UPCI 32 port w/external I/F - 0802 Rocketport UPCI 8 port w/external I/F - 0803 Rocketport UPCI 16 port w/external I/F - 0805 Rocketport UPCI 8 port w/octa cable - 080C RocketModem III 8 port - 080D RocketModem III 4 port - 0903 Rocketport Compact PCI 16 port w/external I/F + 0001 RocketPort 8 Oct + 0002 RocketPort 8 Intf + 0003 RocketPort 16 Intf + 0004 RocketPort 32 Intf + 0005 RocketPort Octacable + 0006 RocketPort 8J + 0007 RocketPort 4-port + 0008 RocketPort 8-port + 0009 RocketPort 16-port + 000a RocketPort Plus Quadcable + 000b RocketPort Plus Octacable + 000c RocketPort 8-port Modem + 8015 RocketPort 4-port UART 16954 11ff Scion Corporation 1200 CSS Corporation 1201 Vista Controls Corp 1202 Network General Corp. + 4300 Gigabit Ethernet Adapter + 1202 9841 SK-9841 LX + 1202 9842 SK-9841 LX dual link + 1202 9843 SK-9843 SX + 1202 9844 SK-9843 SX dual link 1203 Bayer Corporation, Agfa Division 1204 Lattice Semiconductor Corporation 1205 Array Corporation @@ -3858,6 +4185,7 @@ 6933 OZ6933 Cardbus Controller 1025 1016 Travelmate 612 TX 6972 OZ6912 Cardbus Controller + 1179 0001 Magnia Z310 1218 Hybricon Corp. 1219 First Virtual Corporation 121a 3Dfx Interactive, Inc. @@ -3975,6 +4303,8 @@ 1242 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter 1242 656a FCX-6562 PCI-X Fibre Channel Adapter 4643 FCI-1063 Fibre Channel Adapter + 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter + 656a FCX-6562 PCI-X Fibre Channel Adapter 1243 Delphax 1244 AVM Audiovisuelles MKTG & Computer System GmbH 0700 B1 ISDN @@ -4035,6 +4365,7 @@ 1014 0166 ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard 125d 8888 Solo-1 Audio Adapter 1978 ES1978 Maestro 2E + 0e11 b112 Armada M700/E500 1033 803c ES1978 Maestro-2E Audiodrive 1033 8058 ES1978 Maestro-2E Audiodrive 1092 4000 Monster Sound MX400 @@ -4045,6 +4376,7 @@ 1989 ESS Modem 125d 1989 ESS Modem 1998 ES1983S Maestro-3i PCI Audio Accelerator + 1028 00b1 Latitude C600 1028 00e6 ES1983S Maestro-3i (Dell Inspiron 8100) 1999 ES1983S Maestro-3i PCI Modem Accelerator 199a ES1983S Maestro-3i PCI Audio Accelerator @@ -4067,8 +4399,9 @@ 3873 Prism 2.5 Wavelan chipset 1186 3501 DWL-520 Wireless PCI Adapter 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter - 1737 3874 WMP11 Wireless 802.11b PCI Adaptor + 1737 3874 WMP11 Wireless 802.11b PCI Adapter 8086 2513 Wireless 802.11b MiniPCI Adapter + 3890 D-Links DWL-g650 A1 8130 HMP8130 NTSC/PAL Video Decoder 8131 HMP8131 NTSC/PAL Video Decoder 1261 Matsushita-Kotobuki Electronics Industries, Ltd. @@ -4094,6 +4427,7 @@ 0710 SM710 LynxEM 0712 SM712 LynxEM+ 0720 SM720 Lynx3DM + 0730 SM731 Cougar3DR 0810 SM810 LynxE 0811 SM811 LynxE 0820 SM820 Lynx3D @@ -4104,6 +4438,7 @@ 1273 Hughes Network Systems 0002 DirecPC 1274 Ensoniq + 1171 ES1373 [AudioPCI] (also Creative Labs CT5803) 1371 ES1371 [AudioPCI-97] 0e11 0024 AudioPCI on Motherboard Compaq Deskpro 0e11 b1a7 ES1371, ES1373 AudioPCI @@ -4173,6 +4508,7 @@ 1277 Comstream 1278 Transtech Parallel Systems Ltd. 0701 TPE3/TM3 PowerPC Node + 0710 TPE5 PowerPC PCI board 1279 Transmeta Corporation 0295 Northbridge 0395 LongRun Northbridge @@ -4368,6 +4704,7 @@ 12ae 0001 Gigabit Ethernet-SX (Universal) 1410 0104 Gigabit Ethernet-SX PCI Adapter 0002 AceNIC Gigabit Ethernet (Copper) + 10a9 8002 Acenic Gigabit Ethernet 12ae 0002 Gigabit Ethernet-T (3C986-T) 12af TDK USA Corp 12b0 Jorge Scientific Corp @@ -4379,7 +4716,7 @@ 12b6 Natural Microsystems 12b7 Cognex Modular Vision Systems Div. - Acumen Inc. 12b8 Korg -12b9 US Robotics/3Com +12b9 5610 56K FaxModem 1006 WinModem 12b9 005c USR 56k Internal Voice WinModem (Model 3472) 12b9 005e USR 56k Internal WinModem (Models 662975) @@ -4462,16 +4799,20 @@ 00a0 ITNT2 12d3 Vingmed Sound A/S 12d4 Ulticom (Formerly DGM&S) + 0200 T1 Card 12d5 Equator Technologies 12d6 Analogic Corp 12d7 Biotronic SRL 12d8 Pericom Semiconductor 12d9 Aculab PLC + 0002 PCI Prosody + 0004 cPCI Prosody 12da True Time Inc. 12db Annapolis Micro Systems, Inc 12dc Symicron Computer Communication Ltd. 12dd Management Graphics 12de Rainbow Technologies + 0200 CryptoSwift CS200 12df SBS Technologies Inc 12e0 Chase Research 0010 ST16C654 Quad UART @@ -4584,6 +4925,7 @@ 0036 PCI-DAS64/M2/16 0037 PCI-DAS64/M3/16 004c PCI-DAS1000 + 004d PCI-QUAD04 1308 Jato Technologies Inc. 0001 NetCelerator Adapter 1308 0001 NetCelerator Adapter @@ -4669,8 +5011,13 @@ 132d Integrated Silicon Solution, Inc. 1330 MMC Networks 1331 Radisys Corp. + 8200 82600 Host Bridge + 8201 82600 IDE + 8202 82600 USB + 8210 82600 PCI Bridge 1332 Micro Memory 5415 MM-5415CN PCI Memory Module with Battery Backup + 5425 MM-5425CN PCI 64/66 Memory Module with Battery Backup 1334 Redcreek Communications, Inc 1335 Videomail, Inc 1337 Third Planet Publishing @@ -4696,6 +5043,7 @@ 134c Chori Joho System Co. Ltd 134d PCTel Inc 7890 HSP MicroModem 56 + 134d 0001 PCT789 adapter 7891 HSP MicroModem 56 134d 0001 HSP MicroModem 56 7892 HSP MicroModem 56 @@ -4755,13 +5103,12 @@ 1369 Digigram 136a High Soft Tech 136b Kawasaki Steel Corporation + ff01 KL5A72002 Motion JPEG 136c Adtek System Science Co Ltd 136d Gigalabs Inc 136f Applied Magic Inc 1370 ATL Products 1371 CNet Technology Inc - 434e GigaCard Network Adapter - 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) 1373 Silicon Vision Inc 1374 Silicom Ltd 1375 Argosystems Inc @@ -4782,6 +5129,7 @@ 1384 Reality Simulation Systems Inc 1385 Netgear 4100 802.11b Wireless Adapter (MA301) + 4105 MA311 802.11b wireless adapter 620a GA620 622a GA622 630a GA630 @@ -4891,6 +5239,8 @@ 13ce Cocom A/S 13cf Studio Audio & Video Ltd 13d0 Techsan Electronics Co Ltd +# http://www.b2c2inc.com/products/pc-specs.html + 2103 B2C2 Sky2PC PCI [SkyStar2] 13d1 Abocom Systems Inc ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter @@ -4919,7 +5269,7 @@ 13e6 Argosy research Inc 13e7 NAC Incorporated 13e8 Chip Express Corporation -13e9 Chip Express Corporation +13e9 Intraserver Technology Inc 13ea Dallas Semiconductor 13eb Hauppauge Computer Works Inc 13ec Zydacron Inc @@ -4941,9 +5291,11 @@ 13f6 0101 CMI8338-031 PCI Audio Device 0111 CM8738 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard 1043 8077 CMI8738 6-channel audio controller 1043 80e2 CMI8738 6ch-MX 13f6 0111 CMI8738/C3DX PCI Audio Device + 1681 a000 Gamesurround MUSE XL 0211 CM8738 13f7 Wildfire Communications 13f8 Ad Lib Multimedia Inc @@ -4967,8 +5319,6 @@ 0100 Lava Dual Serial 0101 Lava Quatro A 0102 Lava Quatro B - 0180 Lava Octo A - 0181 Lava Octo B 0200 Lava Port Plus 0201 Lava Quad A 0202 Lava Quad B @@ -5016,6 +5366,8 @@ 141e Fanuc Ltd 141f Visiontech Ltd 1420 Psion Dacom plc + 8002 Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part) + 8003 Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part) 1421 Ads Technologies Inc 1422 Ygrec Systems Co Ltd 1423 Custom Technology Corp. @@ -5090,7 +5442,7 @@ 0001 NextMove PCI 1460 DYNARC INC 1461 Avermedia Technologies Inc -1462 Micro-star International Co Ltd +1462 Micro-Star International Co., Ltd. 1463 Fast Corporation 1464 Interactive Circuits & Systems Ltd 1465 GN NETTEST Telecom DIV. @@ -5101,6 +5453,7 @@ 146a IFR 146b Parascan Technologies Ltd 146c Ruby Tech Corp. + 1430 FE-1430TX Fast Ethernet PCI Adapter 146d Tachyon, INC. 146e Williams Electronics Games, Inc. 146f Multi Dimensional Consulting Inc @@ -5151,6 +5504,7 @@ 149b SEIKO Instruments Inc 149c OVISLINK Corp. 149d NEWTEK Inc + 0001 Video Toaster for PC 149e Mapletree Networks Inc. 149f LECTRON Co Ltd 14a0 SOFTING GmBH @@ -5177,6 +5531,14 @@ 0000 DSL NIC 14b4 PHILIPS Business Electronics B.V. 14b5 Creamware GmBH + 0200 Scope + 0300 Pulsar + 0400 Pulsar2 + 0600 Pulsar2 + 0800 DSP-Board + 0900 DSP-Board + 0a00 DSP-Board + 0b00 DSP-Board 14b6 Quantum Data Corp. 14b7 PROXIM Inc 0001 Symphony 4110 @@ -5285,6 +5647,9 @@ 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T) 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX) 1028 0121 Broadcom BCM5701 1000Base-T + 10a9 8010 SGI IO9 Gigabit Ethernet (Copper) + 10a9 8011 SGI Gigabit Ethernet (Copper) + 10a9 8012 SGI Gigabit Ethernet (Fiber) 10b7 1004 3C996-SX 1000Base-SX 10b7 1006 3C996B-T 1000Base-T 10b7 1007 3C1000-T 1000Base-T @@ -5302,6 +5667,7 @@ 1647 NetXtreme BCM5703 Gigabit Ethernet 0e11 0099 NC7780 1000BaseTX 0e11 009a NC7770 1000BaseTX + 10a9 8010 SGI IO9 Gigabit Ethernet (Copper) 14e4 0009 BCM5703 1000BaseTX 14e4 000a BCM5703 1000BaseSX 14e4 000b BCM5703 1000BaseTX @@ -5314,13 +5680,9 @@ 10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X 10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X 1166 1648 NetXtreme CIOB-E 1000Base-T - 1649 NetXtreme BCM5704S Gigabit Ethernet 164d NetXtreme BCM5702FE Gigabit Ethernet 1653 NetXtreme BCM5705 Gigabit Ethernet - 1654 NetXtreme BCM5705 Gigabit Ethernet 165d NetXtreme BCM5705M Gigabit Ethernet - 165e NetXtreme BCM5705M Gigabit Ethernet - 166e NetXtreme BCM5705F Gigabit Ethernet 1696 NetXtreme BCM5782 Gigabit Ethernet 14e4 000d NetXtreme BCM5782 1000Base-T 169c NetXtreme BCM5788 Gigabit Ethernet @@ -5345,13 +5707,14 @@ 16c7 NetXtreme BCM5703 Gigabit Ethernet 14e4 0009 NetXtreme BCM5703 1000Base-T 14e4 000a NetXtreme BCM5703 1000Base-SX - 170d NetXtreme BCM5901 Gigabit Ethernet - 170e NetXtreme BCM5901 Gigabit Ethernet 4210 BCM4210 iLine10 HomePNA 2.0 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem 4212 BCM4212 v.90 56k modem 4301 BCM4301 802.11b + 4320 BCM94306 802.11g + 1737 4320 WPC54G 4401 BCM4401 100Base-T + 1043 80a8 A7V8X motherboard 4402 BCM4402 Integrated 10/100BaseT 4410 BCM4413 iLine32 HomePNA 2.0 4411 BCM4413 V.90 56k modem @@ -5440,6 +5803,9 @@ 122d 4302 Dell MP3930V-W(C) MiniPCI 1610 ADSL AccessRunner PCI Arbitration Device 1611 AccessRunner PCI ADSL Interface Device + 1620 ADSL AccessRunner V2 PCI Arbitration Device + 1621 AccessRunner V2 PCI ADSL Interface Device + 1622 AccessRunner V2 PCI ADSL Yukon WAN Adapter 1803 HCF 56k Modem 0e11 0023 623-LAN Grizzly 0e11 0043 623-LAN Yogi @@ -5505,11 +5871,6 @@ 14f1 2004 Dynalink 56PMi 8234 RS8234 ATM SAR Controller [ServiceSAR Plus] 14f2 MOBILITY Electronics - 0120 EV1000 bridge - 0121 EV1000 Parallel port - 0122 EV1000 Serial port - 0123 EV1000 Keyboard controller - 0124 EV1000 Mouse controller 14f3 BROADLOGIC 14f4 TOKYO Electronic Industry CO Ltd 14f5 SOPAC Ltd @@ -5582,6 +5943,8 @@ 1522 0400 RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem 1522 0500 RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem + 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem + 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem 1523 MUSIC Semiconductors 1524 ENE Technology Inc 1211 CB1211 Cardbus Controller @@ -5618,6 +5981,7 @@ 1541 MACHONE Communications 1542 VIVID Technology Inc 1543 SILICON Laboratories + 3052 Intel 537 [Winmodem] 4c22 Si3036 MC'97 DAA 1544 DCM DATA Systems 1545 VISIONTEK @@ -5858,6 +6222,7 @@ 1638 Standard Microsystems Corp [SMC] 1100 SMC2602W EZConnect / Addtron AWA-100 163c Smart Link Ltd. + 3052 SmartLink SmartPCI562 56K Modem 5449 SmartPCI561 Modem 1657 Brocade Communications Systems, Inc. 165a Epix Inc @@ -5871,6 +6236,8 @@ 16ab Global Sun Technology Inc 1102 PCMCIA-to-PCI Wireless Network Bridge 16be Creatix Polymedia GmbH +16ca CENATEK Inc + 0001 Rocket Drive DL 16ec U.S. Robotics 3685 Wireless Access PCI Adapter Model 022415 16f6 VideoTele.com, Inc. @@ -5879,16 +6246,10 @@ 170c YottaYotta Inc. 172a Accelerated Encryption 1737 Linksys - 1032 Gigabit Network Adapter - 1737 0015 EG1032 v2 Instant Gigabit Network Adapter - 1064 Gigabit Network Adapter - 1737 0016 EG1064 v2 Instant Gigabit Network Adapter 173b Altima (nee Broadcom) 03e8 AC1000 Gigabit Ethernet - 03e9 AC1001 Gigabit Ethernet 03ea AC9100 Gigabit Ethernet 173b 0001 AC1002 - 03eb AC1003 Gigabit Ethernet 1743 Peppercon AG 8139 ROL/F-100 Fast Ethernet Adapter with ROL 174b PC Partner Limited @@ -5904,6 +6265,8 @@ 0006 AMCC HOTlink 1799 Belkin 17af Hightech Information System Ltd. +17cc NetChip Technology, Inc + 2280 USB 2.0 1813 Ambient Technologies Inc 4000 HaM controllerless modem 16be 0001 V9x HAM Data Fax Modem @@ -5911,6 +6274,11 @@ 16be 0002 V9x HAM 1394 1851 Microtune, Inc. 1852 Anritsu Corp. +1888 Varisys Ltd + 0301 VMFX1 FPGA PMC module + 0601 VSM2 dual PMC carrier + 0710 VS14x series PowerPC PCI board + 0720 VS24x series PowerPC PCI board 1a08 Sierra semiconductor 0000 SC15064 1b13 Jaton Corp @@ -5923,7 +6291,12 @@ 2020 DC-390 690c 690c dc29 DC290 +1fc0 Tumsan Oy + 0300 E2200 Dual E1/Rawpipe Card +2000 Smart Link Ltd. 2001 Temporal Research Ltd +2003 Smart Link Ltd. +2004 Smart Link Ltd. 21c3 21st Century Computer Corp. 2348 Racore 2010 8142 100VG/AnyLAN @@ -5935,7 +6308,15 @@ 3000 Hansol Electronics Inc. 3142 Post Impression Systems. 3388 Hint Corp - 0021 HB1-SE33 PCI-PCI Bridge + 0013 HiNT HC4 PCI to ISDN bridge, Multimedia audio controller + 0014 HiNT HC4 PCI to ISDN bridge, Network controller + 0020 HB6 Universal PCI-PCI bridge (transparent mode) + 0021 HB6 Universal PCI-PCI bridge (non-transparent mode) + 4c53 1050 CT7 mainboard + 4c53 1080 CT8 mainboard + 4c53 3010 PPCI mezzanine (32-bit PMC) + 101a E.Band [AudioTrak Inca88] + 101b E.Band [AudioTrak Inca88] 8011 VXPro II Chipset 3388 8011 VXPro II Chipset CPU to PCI Bridge 8012 VXPro II Chipset @@ -5995,6 +6376,7 @@ 0100 AladdinCARD 0200 CPC 4444 Internext Compression Inc + 0803 iTVC15 MPEG-2 Encoder 4468 Bridgeport machines 4594 Cogetec Informatique Inc 45fb Baldor Electric Company @@ -6040,6 +6422,7 @@ 5143 Qualcomm Inc 5145 Ensoniq (Old) 3031 Concert AudioPCI +5168 Animation Technologies Inc. 5301 Alliance Semiconductor Corp. 0001 ProMotion aT3D 5333 S3 Inc. @@ -6150,6 +6533,7 @@ 8c12 86C270-294 Savage/IX-MV 1014 017f ThinkPad T20 8c13 86C270-294 Savage/IX + 1179 0001 Magnia Z310 8c22 SuperSavage MX/128 8c24 SuperSavage MX/64 8c26 SuperSavage MX/64C @@ -6160,10 +6544,10 @@ 8c2e SuperSavage IX/C SDR 1014 01fc ThinkPad T23 (2647-4MG) 8c2f SuperSavage IX/C DDR -# Integrated in VIA ProSavage PN133 North Bridge - 8d01 VT8603 [ProSavage PN133] AGP4X VGA Controller (Twister) + 8d01 86C380 [ProSavageDDR K4M266] 8d02 VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK) - 8d04 VT8751 [ProSavageDDR P4M266] VGA Controller + 8d03 VT8751 [ProSavageDDR P4M266] + 8d04 VT8375 [ProSavage8 KM266/KL266] 9102 86C410 Savage 2000 1092 5932 Viper II Z200 1092 5934 Viper II Z200 @@ -6175,6 +6559,7 @@ 1092 5a57 Viper II Z200 ca00 SonicVibes 544c Teralogic Inc + 0350 TL880-based HDTV/ATSC tuner 5455 Technische University Berlin 4458 S5933 5519 Cnet Technologies, Inc. @@ -6182,6 +6567,7 @@ 0001 I-30xx Scanner Interface 5555 Genroco, Inc 0003 TURBOstor HFP-832 [HiPPI NIC] +5654 VoiceTronix Pty Ltd 5700 Netpower 6356 UltraStor 6374 c't Magazin für Computertechnik @@ -6257,13 +6643,14 @@ 1029 82559 Ethernet Controller 1030 82559 InBusiness 10/100 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller - 1014 0209 ThinkPad A30p/T30 + 1014 0209 ThinkPad A/T/X Series 104d 80e7 Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 107b 5350 EtherExpress PRO/100 VE 1179 0001 EtherExpress PRO/100 VE 144d c000 EtherExpress PRO/100 VE 144d c001 EtherExpress PRO/100 VE 144d c003 EtherExpress PRO/100 VE + 144d c006 vpr Matrix 170B4 1032 82801CAM (ICH3) PRO/100 VE Ethernet Controller 1033 82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller 1034 82801CAM (ICH3) PRO/100 VM Ethernet Controller @@ -6279,18 +6666,20 @@ 103e 82801BD PRO/100 VM (MOB) Ethernet Controller 1040 536EP Data Fax Modem 16be 1040 V.9X DSP Data Fax Modem - 1048 82597EX 10GbE Ethernet Controller - 8086 a01f PRO/10GbE LR Server Adapter - 8086 a11f PRO/10GbE LR Server Adapter + 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter 1059 82551QM Ethernet Controller 1130 82815 815 Chipset Host Bridge and Memory Controller Hub 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard 104d 80df Vaio PCG-FX403 + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 1131 82815 815 Chipset AGP Bridge 1132 82815 CGC [Chipset Graphics Controller] 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 + 8086 4532 D815EEA2 Mainboard + 8086 4557 D815EGEW Mainboard 1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller 8086 1161 82806AA PCI64 Hub APIC 1162 Xscale 80200 Big Endian Companion Chip @@ -6475,6 +6864,7 @@ 8086 8000 82806AA PCI64 Hub Controller (HRes) 1460 82870P2 P64H2 Hub PCI Bridge 1461 82870P2 P64H2 I/OxAPIC + 15d9 3480 P4DP6 1462 82870P2 P64H2 Hot Plug Controller 1960 80960RP [i960RP Microprocessor] 101e 0431 MegaRAID 431 RAID Controller @@ -6526,23 +6916,33 @@ 2428 82801AB PCI Bridge 2440 82801BA ISA Bridge (LPC) 2442 82801BA/BAM USB (Hub #1) + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 2443 82801BA/BAM SMBus + 1014 01c6 Netvista A40/A40p 1025 1016 Travelmate 612 TX 1043 8027 TUSL2-C Mainboard 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 2444 82801BA/BAM USB (Hub #2) 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard 2445 82801BA/BAM AC'97 Audio + 1014 01c6 Netvista A40/A40p 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 1462 3370 STAC9721 AC 147b 0507 TH7II-RAID - 2446 82801BA/BAM AC'97 Modem + 8086 4557 D815EGEW Mainboard + 2446 Intel 537 [82801BA/BAM AC'97 Modem] 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 2448 82801BAM/CAM PCI Bridge @@ -6560,8 +6960,12 @@ 1014 023d EtherExpress PRO/100 VE 1014 0244 EtherExpress PRO/100 VE 1014 0245 EtherExpress PRO/100 VE + 1014 0265 PRO/100 VE Desktop Connection + 1014 0267 PRO/100 VE Desktop Connection + 1014 026a PRO/100 VE Desktop Connection 109f 315d EtherExpress PRO/100 VE 109f 3181 EtherExpress PRO/100 VE + 1179 ff01 PRO/100 VE Network Connection 1186 7801 EtherExpress PRO/100 VE 144d 2602 HomePNA 1M CNR 8086 3010 EtherExpress PRO/100 VE @@ -6577,10 +6981,13 @@ 1025 1016 Travelmate 612TX 104d 80df Vaio PCG-FX403 244b 82801BA IDE U100 + 1014 01c6 Netvista A40/A40p 1043 8027 TUSL2-C Mainboard 147b 0507 TH7II-RAID + 8086 4532 D815EEA2 mainboard + 8086 4557 D815EGEW Mainboard 244c 82801BAM ISA Bridge (LPC) - 244e 82801BA/CA/DB PCI Bridge + 244e 82801BA/CA/DB/EB PCI Bridge 2450 82801E ISA Bridge (LPC) 2452 82801E USB 2453 82801E SMBus @@ -6588,44 +6995,80 @@ 245b 82801E IDE U100 245d 82801E Ethernet Controller 1 245e 82801E PCI Bridge - 2480 82801CA ISA Bridge (LPC) + 2480 82801CA LPC Interface Controller 2482 82801CA/CAM USB (Hub #1) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2483 82801CA/CAM SMBus - 1014 0220 ThinkPad T23/A30p/T30 + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2483 82801CA/CAM SMBus Controller + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 2484 82801CA/CAM USB (Hub #2) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2485 82801CA/CAM AC'97 Audio + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2485 82801CA/CAM AC'97 Audio Controller 1014 0222 ThinkPad T23 (2647-4MG) or A30p (2653-64G) 1014 0508 ThinkPad T30 + 1014 051c ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 2486 82801CA/CAM AC'97 Modem - 1014 0223 ThinkPad A30p (2653-64G) + 144d c006 vpr Matrix 170B4 + 2486 82801CA/CAM AC'97 Modem Controller + 1014 0223 ThinkPad A/T/X Series 1014 0503 ThinkPad R31 2656BBG - 1014 051a ThinkPad T30 + 1014 051a ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 1179 0001 Toshiba Satellite 1110 Z15 internal Modem 134d 4c21 Dell Inspiron 2100 internal modem + 144d 2115 vpr Matrix 170B4 internal modem 14f1 5421 MD56ORD V.92 MDC Modem 2487 82801CA/CAM USB (Hub #3) - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 248a 82801CAM IDE U100 - 1014 0220 ThinkPad T23/A30p/T30 + 1014 0220 ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP - 248b 82801CA IDE U100 + 8086 1958 vpr Matrix 170B4 + 248b 82801CA Ultra ATA Storage Controller + 15d9 3480 P4DP6 248c 82801CAM ISA Bridge (LPC) - 24c0 82801DB ISA Bridge (LPC) + 24c0 82801DB LPC Interface Controller + 1462 5800 845PE Max (MS-6580) 24c2 82801DB USB (Hub #1) - 24c3 82801DB SMBus + 1462 5800 845PE Max (MS-6580) + 24c3 82801DB/DBM SMBus Controller + 1462 5800 845PE Max (MS-6580) 24c4 82801DB USB (Hub #2) - 24c5 82801DB AC'97 Audio - 24c6 82801DB AC'97 Modem + 1462 5800 845PE Max (MS-6580) + 24c5 82801DB AC'97 Audio Controller + 1462 5800 845PE Max (MS-6580) + 24c6 82801DB AC'97 Modem Controller 24c7 82801DB USB (Hub #3) - 24cb 82801DB ICH4 IDE - 24cd 82801DB USB EHCI Controller + 1462 5800 845PE Max (MS-6580) + 24ca 82801DBM Ultra ATA Storage Controller + 24cb 82801DB Ultra ATA Storage Controller + 1462 5800 845PE Max (MS-6580) + 24cc 82801DBM LPC Interface Controller + 24cd 82801DB USB2 + 1462 3981 845PE Max (MS-6580) Onboard USB EHCI Controller + 24d0 82801EB LPC Interface Controller + 24d1 82801EB Ultra ATA Storage Controller + 24d2 82801EB USB + 24d3 82801EB SMBus Controller + 24d4 82801EB USB + 24d5 82801EB AC'97 Audio Controller + 24d6 82801EB AC'97 Modem Controller + 24d7 82801EB USB + 24db 82801EB Ultra ATA Storage Controller + 24dc 82801EB LPC Interface Controller + 24dd 82801EB USB2 + 24de 82801EB USB 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1028 0095 Precision Workstation 220 Chipset 1043 801c P3C-2000 system chipset @@ -6641,24 +7084,48 @@ 2532 82850 850 (Tehama) Chipset AGP Bridge 2533 82860 860 (Wombat) Chipset AGP Bridge 2534 82860 860 (Wombat) Chipset PCI Bridge - 2540 e7500 [Plumas] DRAM Controller - 2541 e7500 [Plumas] DRAM Controller Error Reporting - 2543 e7500 [Plumas] HI_B Virtual PCI Bridge (F0) - 2544 e7500 [Plumas] HI_B Virtual PCI Bridge (F1) - 2545 e7500 [Plumas] HI_C Virtual PCI Bridge (F0) - 2546 e7500 [Plumas] HI_C Virtual PCI Bridge (F1) - 2547 e7500 [Plumas] HI_D Virtual PCI Bridge (F0) - 2548 e7500 [Plumas] HI_D Virtual PCI Bridge (F1) + 2540 E7500 Memory Controller Hub + 15d9 3480 P4DP6 + 2541 E7000 Series Host RASUM Controller + 15d9 3480 P4DP6 + 2543 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2544 E7000 Series Hub Interface B RASUM Controller + 2545 E7000 Series Hub Interface C PCI-to-PCI Bridge + 2546 E7000 Series Hub Interface C RASUM Controller + 2547 E7000 Series Hub Interface D PCI-to-PCI Bridge + 2548 E7000 Series Hub Interface D RASUM Controller + 254c E7501 Memory Controller Hub + 2550 E7505 Memory Controller Hub + 2551 E7000 Series RAS Controller + 2552 E7000 Series Processor to AGP Controller + 2553 E7000 Series Hub Interface B PCI-to-PCI Bridge + 2554 E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller + 255d E7205 Memory Controller Hub 2560 82845G/GL [Brookdale-G] Chipset Host Bridge + 1462 5800 845PE Max (MS-6580) 2561 82845G/GL [Brookdale-G] Chipset AGP Bridge 2562 82845G/GL [Brookdale-G] Chipset Integrated Graphics Device + 2570 82865G/PE/P Processor to I/O Controller + 2571 82865G/PE/P Processor to AGP Controller + 2572 82865G Integrated Graphics Device + 2573 82865G/PE/P Processor to PCI to CSA Bridge + 2576 82864G/PE/P Processor to I/O Memory Interface + 2578 82875P Memory Controller Hub + 2579 82875P Processor to AGP Controller + 257b 82875P Processor to PCI to CSA Bridge + 257e 82875P Processor to I/O Memory Interface 3092 Integrated RAID + 3340 82855PM Processor to I/O Controller + 3341 82855PM Processor to AGP Controller 3575 82830 830 Chipset Host Bridge - 1014 021d ThinkPad T23 (2647-4MG) or A30p (2653-64G) + 1014 021d ThinkPad A/T/X Series 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP 3576 82830 830 Chipset AGP Bridge 3577 82830 CGC [Chipset Graphics Controller] + 1014 0513 ThinkPad A/T/X Series 3578 82830 830 Chipset Host Bridge + 3580 82852/855GM Host Bridge + 3582 82852/855GM Integrated Graphics Device 5200 EtherExpress PRO/100 Intelligent Server 5201 EtherExpress PRO/100 Intelligent Server 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter @@ -6674,6 +7141,7 @@ 7113 82371AB/EB/MB PIIX4 ACPI 7120 82810 GMCH [Graphics Memory Controller Hub] 7121 82810 CGC [Chipset Graphics Controller] + 8086 4341 Cayman (CA810) Mainboard 7122 82810 DC-100 GMCH [Graphics Memory Controller Hub] 7123 82810 DC-100 CGC [Chipset Graphics Controller] 7124 82810E DC-133 GMCH [Graphics Memory Controller Hub] @@ -6685,6 +7153,7 @@ 7181 440LX/EX - 82443LX/EX AGP bridge 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge 0e11 0500 Armada 1750 Laptop System Chipset + 0e11 b110 Armada M700 1179 0001 Toshiba Tecra 8100 Laptop System Chipset 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) @@ -6761,9 +7230,6 @@ 5478 AIC-7850 5575 AVA-2930 5578 AIC-7855 - 5647 ANA-7711 TCP Offload Engine - 9004 7710 ANA-7711F TCP Offload Engine - Optical - 9004 7711 ANA-7711LP TCP Offload Engine - Copper 5675 AIC-755x 5678 AIC-7856 5775 AIC-755x @@ -6805,6 +7271,8 @@ 7478 AHA-2944/2944W / AIC-7874 7578 AHA-3944/3944W / AIC-7875 7678 AHA-4944W/UW / AIC-7876 + 7710 ANA-7711F Network Accelerator Card (NAC) - Optical + 7711 ANA-7711C Network Accelerator Card (NAC) - Copper 7778 AIC-787x 7810 AIC-7810 7815 AIC-7815 RAID+Memory Controller IC @@ -6881,6 +7349,8 @@ 9005 62a1 19160 Ultra160 SCSI Controller 0083 AIC-7892D U160/m 008f AIC-7892P U160/m + 1179 0001 Magnia Z310 + 15d9 9005 Onboard SCSI Host Adapter 00c0 AHA-3960D / AIC-7899A U160/m 0e11 f620 Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter 9005 f620 AHA-3960D U160/m @@ -6890,6 +7360,8 @@ 1028 00c5 PowerEdge 2550 00cf AIC-7899P U160/m 1028 00d1 PowerEdge 2550 + 10f1 2462 Thunder K7 S2462 + 15d9 9005 Onboard SCSI Host Adapter 0250 ServeRAID Controller 1014 0279 ServeRAID-xx 1014 028c ServeRAID-xx @@ -6906,11 +7378,18 @@ 8014 ASC-29320LP U320 801e AIC-7901A U320 801f AIC-7902 U320 + 8080 ASC-29320A U320 w/HostRAID + 808f AIC-7901 U320 w/HostRAID 8090 ASC-39320 U320 w/HostRAID 8091 ASC-39320D U320 w/HostRAID 8092 ASC-29320 U320 w/HostRAID 8093 ASC-29320B U320 w/HostRAID 8094 ASC-29320LP U320 w/HostRAID + 8095 ASC-39320(B) U320 w/HostRAID + 8096 ASC-39320A U320 w/HostRAID + 8097 ASC-29320ALP U320 w/HostRAID + 809c ASC-39320D(B) U320 w/HostRAID + 809d AIC-7902(B) U320 w/HostRAID 809e AIC-7901A U320 w/HostRAID 809f AIC-7902 U320 w/HostRAID 907f Atronics @@ -6953,7 +7432,7 @@ dead Indigita Corporation e000 Winbond e000 W89C940 e159 Tiger Jet Network Inc. - 0001 Model 300 128k [Catawba TJ] + 0001 Intel 537 0059 0001 128k ISDN-S/T Adapter 0059 0003 128k ISDN-U Adapter 0002 Tiger100APC ISDN chipset @@ -6999,7 +7478,9 @@ f1d0 AJA Video facd KONA HD SMPTE 292M I/O fa57 Fast Search & Transfer ASA febd Ultraview Corp. -feda Epigram Inc +feda Broadcom Inc (nee Epigram) + a0fa BCM4210 iLine10 HomePNA 2.0 + a10e BCM4230 iLine10 HomePNA 2.0 fffe VMWare Inc 0710 Virtual SVGA ffff Illegal Vendor ID -- cgit v1.2.3 From 215dd828d4965080b259760bbb940ba5c8f2632d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 29 Jan 2004 01:13:27 -0800 Subject: [PATCH] PCI: fix compiler warning in probe.c cause by PPC patch. --- drivers/pci/probe.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 50391a0fd11e..19c9f836e2f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -628,11 +628,13 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) * If this is a single function device, * don't scan past the first function. */ - if (!dev->multifunction) - if (func > 0) + if (!dev->multifunction) { + if (func > 0) { dev->multifunction = 1; - else + } else { break; + } + } } else { if (func == 0) break; -- cgit v1.2.3 From 87903ac513143420876cf1310e352a532157e035 Mon Sep 17 00:00:00 2001 From: Michael Schierl Date: Thu, 29 Jan 2004 06:08:53 -0800 Subject: [PATCH] [APM] Is this the correct way to fix suspend bug introduced This fixes my APM problems (without them my laptop, Acer TravelMate 210TEV (Celeron 700, 128 MB RAM), hangs after resuming from APM since 2.6.0-test4). Modified based on comments from Pavel Machek , who has acked the updated patch. --- arch/i386/kernel/apm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 2212132dacfb..75b2a8c4ae89 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -1201,6 +1201,7 @@ static int suspend(int vetoable) } device_suspend(3); + device_power_down(3); /* serialize with the timer interrupt */ write_seqlock_irq(&xtime_lock); @@ -1234,6 +1235,7 @@ static int suspend(int vetoable) if (err != APM_SUCCESS) apm_error("suspend", err); err = (err == APM_SUCCESS) ? 0 : -EIO; + device_power_up(); device_resume(); pm_send_all(PM_RESUME, (void *)0); queue_event(APM_NORMAL_RESUME, NULL); @@ -1252,6 +1254,7 @@ static void standby(void) { int err; + device_power_down(3); /* serialize with the timer interrupt */ write_seqlock_irq(&xtime_lock); /* If needed, notify drivers here */ @@ -1261,6 +1264,7 @@ static void standby(void) err = set_system_power_state(APM_STATE_STANDBY); if ((err != APM_SUCCESS) && (err != APM_NO_ERROR)) apm_error("standby", err); + device_power_up(); } static apm_event_t get_event(void) -- cgit v1.2.3 From a71d72ce287f506a799f953d373b554f119ef3a5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 29 Jan 2004 16:24:26 -0800 Subject: [PATCH] Validate ACPI CPU frequency values This is a simple fix for some of the problems with bad ACPI frequency values: Abort if the frequency field in _PSS is zero, as we're having a completely broken ACPI table then. A more complete overhaul of the acpi-cpufreq driver (where the cause of the problem lies) is in the latest acpi-test tree, but that's definitely something to be delayed for 2.6.3 -- and the same is true for the yet-to-be-written do_div64 conversion. --- arch/i386/kernel/cpu/cpufreq/acpi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c index f5b7830e48dd..7d77643a4ee1 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c @@ -208,6 +208,12 @@ acpi_processor_get_performance_states ( goto end; } + if (!px->core_frequency) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n")); + result = -EFAULT; + goto end; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", i, -- cgit v1.2.3 From 586a9edd0761e05d70c1711bfb3e778ecc7146bc Mon Sep 17 00:00:00 2001 From: Michael Hunold Date: Thu, 29 Jan 2004 16:24:38 -0800 Subject: [PATCH] dvb subsystem and saa7146 v4l fixes This fixes some issues in the dvb subsystem and some nasty things in the v4l saa7146 driver. [DVB] - dvb-core: aquire -> acquire spelling fix - nxt600 frontend: don't send zero-byte messages when probing the PLL type - Kconfig: add a note that says that the CI of the budget-CI card is not actually supported by the budget-CI driver - ttusb-dec: Check for presence of crc32 function. Make unknown types of packet less likely to cause packet loss. [V4L] - saa7146: use kernel mint_t()/max_t() instead of homebrewn stuff - saa7146: disable video clipping before capturing for sure to prevent black pictures - saa7146: make sure to disable the right video dma upon device close - saa7146: don't free resources if disabling an already disabled video overlay --- drivers/media/common/saa7146_hlp.c | 21 +++++++++------------ drivers/media/common/saa7146_video.c | 5 ++++- drivers/media/dvb/dvb-core/dvb_frontend.c | 8 ++++---- drivers/media/dvb/frontends/alps_tdmb7.c | 2 +- drivers/media/dvb/frontends/nxt6000.c | 18 +++++++++++++++--- drivers/media/dvb/ttpci/Kconfig | 3 +++ drivers/media/dvb/ttusb-dec/Kconfig | 1 + drivers/media/dvb/ttusb-dec/ttusb_dec.c | 5 +++-- 8 files changed, 40 insertions(+), 23 deletions(-) diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index 4495db4b3407..fffe73fd8812 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -1,10 +1,6 @@ +#include #include -#define my_min(type,x,y) \ - ({ type __x = (x), __y = (y); __x < __y ? __x: __y; }) -#define my_max(type,x,y) \ - ({ type __x = (x), __y = (y); __x > __y ? __x: __y; }) - static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) { /* clear out the necessary bits */ @@ -398,11 +394,11 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa b = y[i]+h[i]; /* insert left/right coordinates */ - pixel_list[ 2*i ] = my_min(int, l, width); - pixel_list[(2*i)+1] = my_min(int, r, width); + pixel_list[ 2*i ] = min_t(int, l, width); + pixel_list[(2*i)+1] = min_t(int, r, width); /* insert top/bottom coordinates */ - line_list[ 2*i ] = my_min(int, t, height); - line_list[(2*i)+1] = my_min(int, b, height); + line_list[ 2*i ] = min_t(int, t, height); + line_list[(2*i)+1] = min_t(int, b, height); } /* sort and eliminate lists */ @@ -411,9 +407,9 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa sort_and_eliminate( &line_list[0], &cnt_line ); /* calculate the number of used u32s */ - numdwords = my_max(int, (cnt_line+1), (cnt_pixel+1))*2; - numdwords = my_max(int, 4, numdwords); - numdwords = my_min(int, 64, numdwords); + numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2; + numdwords = max_t(int, 4, numdwords); + numdwords = min_t(int, 64, numdwords); /* fill up cliptable */ for(i = 0; i < cnt_pixel; i++) { @@ -1022,6 +1018,7 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field); saa7146_set_output_format(dev, sfmt->trans); + saa7146_disable_clipping(dev); if ( vv->last_field == V4L2_FIELD_INTERLACED ) { } else if ( vv->last_field == V4L2_FIELD_TOP ) { diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 49cf9d85a81a..c3e935d288d6 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -755,7 +755,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file) dmas = MASK_22 | MASK_21 | MASK_20; } else { resource = RESOURCE_DMA1_HPS; - dmas = MASK_20; + dmas = MASK_22; } saa7146_res_free(fh, resource); @@ -1110,6 +1110,9 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_D(("overlay is active, but in another open\n")); return -EAGAIN; } + } else { + DEB_D(("overlay is not active\n")); + return 0; } spin_lock_irqsave(&dev->slock,flags); err = saa7146_stop_preview(fh); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 256f2215b26a..84ad3312248f 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -67,7 +67,7 @@ struct dvb_frontend_data { pid_t thread_pid; unsigned long release_jiffies; unsigned long lost_sync_jiffies; - int aquire_signal; + int acquire_signal; int bending; int lnb_drift; int timeout_count; @@ -306,7 +306,7 @@ static int dvb_frontend_set_parameters (struct dvb_frontend_data *fe, fe->lost_sync_count = 0; fe->lost_sync_jiffies = jiffies; fe->lnb_drift = 0; - fe->aquire_signal = 1; + fe->acquire_signal = 1; if (fe->status & ~FE_TIMEDOUT) dvb_frontend_add_event (fe, 0); memcpy (&fe->parameters, param, @@ -467,13 +467,13 @@ static int dvb_frontend_thread (void *data) if (s & FE_HAS_LOCK) { fe->timeout_count = 0; fe->lost_sync_count = 0; - fe->aquire_signal = 0; + fe->acquire_signal = 0; } else { fe->lost_sync_count++; if (!(fe->info->caps & FE_CAN_RECOVER)) { if (!(fe->info->caps & FE_CAN_CLEAN_SETUP)) { if (fe->lost_sync_count < 10) { - if (fe->aquire_signal) + if (fe->acquire_signal) dvb_frontend_internal_ioctl( &fe->frontend, FE_RESET, NULL); diff --git a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c index b5ba20768698..072bc89076c9 100644 --- a/drivers/media/dvb/frontends/alps_tdmb7.c +++ b/drivers/media/dvb/frontends/alps_tdmb7.c @@ -374,7 +374,7 @@ static int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) cx22700_set_inversion (i2c, p->inversion); cx22700_set_tps (i2c, &p->u.ofdm); cx22700_writereg (i2c, 0x37, 0x01); /* PAL loop filter off */ - cx22700_writereg (i2c, 0x00, 0x01); /* restart aquire */ + cx22700_writereg (i2c, 0x00, 0x01); /* restart acquire */ break; } diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index 1e29fcef8d85..db739c8b5e8f 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -123,7 +123,19 @@ static u8 nxt6000_readreg(struct dvb_frontend *fe, u8 reg) struct nxt6000_config *nxt = FE2NXT(fe); return nxt6000_read(fe->i2c, nxt->demod_addr, reg); +} + +static int pll_test(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr) +{ + u8 buf [1]; + struct i2c_msg msg = {.addr = tuner_addr >> 1,.flags = I2C_M_RD,.buf = buf,.len = 1 }; + int ret; + nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + ret = i2c->xfer(i2c, &msg, 1); + nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ + + return (ret != 1) ? -EFAULT : 0; } static int pll_write(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr, u8 *buf, u8 len) @@ -833,21 +845,21 @@ static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data) if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE) continue; - if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) { + if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { nxt->tuner_addr = 0xC0; nxt->tuner_type = TUNER_TYPE_ALP510; nxt->clock_inversion = 1; dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr); - } else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC2, NULL, 0) == 0) { + } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC2) == 0) { nxt->tuner_addr = 0xC2; nxt->tuner_type = TUNER_TYPE_SP5659; nxt->clock_inversion = 0; dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr); - } else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) { + } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { nxt->tuner_addr = 0xC0; nxt->tuner_type = TUNER_TYPE_SP5730; nxt->clock_inversion = 0; diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 4f9facc24395..99647b5ffd2b 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -66,6 +66,9 @@ config DVB_BUDGET_CI (so called Budget- or Nova-PCI cards) without onboard MPEG2 decoder, but with onboard Common Interface connector. + Note: The Common Interface is not yet supported by this driver + due to lack of information from the vendor. + Say Y if you own such a card and want to use it. To compile this driver as a module, choose M here: the diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig index 90f0c26d9a8b..9fb8cd98332d 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/dvb/ttusb-dec/Kconfig @@ -2,6 +2,7 @@ config DVB_TTUSB_DEC tristate "Technotrend/Hauppauge USB DEC devices" depends on DVB_CORE && USB select FW_LOADER + select CRC32 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'DEC2000-t' diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 7aa1fe2cb326..9dd55595c0fc 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -552,13 +552,14 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b, break; case 3: - if (*b++ == 0x00) { + if (*b == 0x00) { dec->packet_state++; dec->packet_length = 0; - } else { + } else if (*b != 0xaa) { dec->packet_state = 0; } + b++; length--; break; -- cgit v1.2.3 From ae05f3fae32be240b8792c48351eefedb128f1f9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 29 Jan 2004 16:41:00 -0800 Subject: Fix sha256 padding block initializer to be static. Jakub points out that having an automatic array is not only bad for performance (and stack usage), gcc has also historically had lots of bugs here, and gcc-3.2.3 seems to miscompile it otherwise. --- crypto/sha256.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/sha256.c b/crypto/sha256.c index 030fe5cc6a64..8122872e414f 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -295,7 +295,7 @@ static void sha256_final(void* ctx, u8 *out) u8 bits[8]; unsigned int index, pad_len, t; int i, j; - const u8 padding[64] = { 0x80, }; + static const u8 padding[64] = { 0x80, }; /* Save number of bits */ t = sctx->count[0]; -- cgit v1.2.3 From 41754b1fab9c86a32b6804c6f365ddf3a9783322 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Jan 2004 14:49:14 +0000 Subject: [ARM] Eliminate tsk->used_math Remove usage of tsk->used_math on ARM, moving the status to an array of co-processor usage. (ARM can have up to 15 co-processors providing various extra facilities such as SIMD, VFP or FP.) --- arch/arm/kernel/asm-offsets.c | 1 - arch/arm/kernel/entry-armv.S | 50 ++++++++++++++++++++++++++++++++----------- arch/arm/kernel/process.c | 7 +++--- arch/arm/kernel/ptrace.c | 5 +++-- include/asm-arm/thread_info.h | 6 ++++-- 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 49562ecdf365..e2a5e3a76333 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -45,7 +45,6 @@ int main(void) { - DEFINE(TSK_USED_MATH, offsetof(struct task_struct, used_math)); DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index f20207dede1e..da2f8fa12d23 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -963,23 +963,46 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go * co-processor instructions. However, we have to watch out * for the ARM6/ARM7 SWI bug. * - * Emulators may wish to make use of the instruction value we - * prepared for them in r0. + * Emulators may wish to make use of the following registers: + * r0 - instruction opcode. + * r10 - this threads thread_info structure. */ call_fpe: enable_irq r10 @ Enable interrupts tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) - and r10, r0, #0x0f000000 @ mask out op-code bits - teqne r10, #0x0f000000 @ SWI (ARM6/7 bug)? + and r8, r0, #0x0f000000 @ mask out op-code bits + teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? #endif moveq pc, lr -do_fpe: get_thread_info r10 @ get current thread - ldr r4, [r10, #TI_TASK] @ get current task - mov r8, #1 - strb r8, [r4, #TSK_USED_MATH] @ set current->used_math - ldr r4, .LCfp + get_thread_info r10 @ get current thread + and r8, r0, #0x00000f00 @ mask out CP number + mov r7, #1 + add r6, r10, #TI_USED_CP + strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] + add pc, pc, r8, lsr #6 + mov r0, r0 + + mov pc, lr @ CP#0 + b do_fpe @ CP#1 (FPE) + b do_fpe @ CP#2 (FPE) + mov pc, lr @ CP#3 + mov pc, lr @ CP#4 + mov pc, lr @ CP#5 + mov pc, lr @ CP#6 + mov pc, lr @ CP#7 + mov pc, lr @ CP#8 + mov pc, lr @ CP#9 + mov pc, lr @ CP#10 (VFP) + mov pc, lr @ CP#11 (VFP) + mov pc, lr @ CP#12 + mov pc, lr @ CP#13 + mov pc, lr @ CP#14 (Debug) + mov pc, lr @ CP#15 (Control) + +do_fpe: ldr r4, .LCfp add r10, r10, #TI_FPSTATE @ r10 = workspace ldr pc, [r4] @ Call FP module USR entry point + /* * The FP module is called with these registers set: * r0 = instruction @@ -989,6 +1012,11 @@ do_fpe: get_thread_info r10 @ get current thread * lr = unrecognised FP instruction return address */ + .data +ENTRY(fp_enter) + .word fpe_not_present + .text + fpundefinstr: mov r0, sp adrsvc al, lr, ret_from_exception b do_undefinstr @@ -1016,10 +1044,6 @@ ENTRY(ret_from_exception) mov why, #0 b ret_to_user - .data -ENTRY(fp_enter) - .word fpe_not_present - .text /* * Register switch for ARMv3 and ARMv4 processors * r0 = previous thread_info, r1 = next thread_info diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 5084effd6005..84508f21ff68 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -307,8 +307,7 @@ void flush_thread(void) struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; - tsk->used_math = 0; - + memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); fp_init(&thread->fpstate); } @@ -344,12 +343,12 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { struct thread_info *thread = current_thread_info(); - int used_math = current->used_math; + int used_math = thread->used_cp[1] | thread->used_cp[2]; if (used_math) memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); - return used_math; + return used_math != 0; } /* diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3fafcf7e9e40..6450f55bd9b9 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -602,8 +602,9 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) */ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { - tsk->used_math = 1; - return copy_from_user(&tsk->thread_info->fpstate, ufp, + struct thread_info *thread = tsk->thread_info; + thread->used_cp[1] = thread->used_cp[2] = 1; + return copy_from_user(&thread->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index 642810a9ed84..16a541206166 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -51,8 +51,9 @@ struct thread_info { __u32 cpu; /* cpu */ __u32 cpu_domain; /* cpu domain */ struct cpu_context_save cpu_context; /* cpu context */ - struct restart_block restart_block; + __u8 used_cp[16]; /* thread used copro */ union fp_state fpstate; + struct restart_block restart_block; }; #define INIT_THREAD_INFO(tsk) \ @@ -107,7 +108,8 @@ extern void free_thread_info(struct thread_info *); #define TI_CPU 20 #define TI_CPU_DOMAIN 24 #define TI_CPU_SAVE 28 -#define TI_FPSTATE 76 +#define TI_USED_MATH 76 +#define TI_FPSTATE (TI_USED_MATH+16) #endif -- cgit v1.2.3 From 4abebca310b81db5b010f245786884c34d1428f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Jan 2004 15:27:03 +0000 Subject: [ARM] Fix bitops pointer qualifiers. According to x86, the pointers for bitops are supposed to be qualified with volatile. Make ARM bitops reflect this. --- include/asm-arm/bitops.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h index 917adde845ba..8ae0be984492 100644 --- a/include/asm-arm/bitops.h +++ b/include/asm-arm/bitops.h @@ -29,7 +29,7 @@ * * First, the atomic bitops. These use native endian. */ -static inline void ____atomic_set_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -41,7 +41,7 @@ static inline void ____atomic_set_bit(unsigned int bit, unsigned long *p) local_irq_restore(flags); } -static inline void ____atomic_clear_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -53,7 +53,7 @@ static inline void ____atomic_clear_bit(unsigned int bit, unsigned long *p) local_irq_restore(flags); } -static inline void ____atomic_change_bit(unsigned int bit, unsigned long *p) +static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); @@ -66,7 +66,7 @@ static inline void ____atomic_change_bit(unsigned int bit, unsigned long *p) } static inline int -____atomic_test_and_set_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -83,7 +83,7 @@ ____atomic_test_and_set_bit(unsigned int bit, unsigned long *p) } static inline int -____atomic_test_and_clear_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -100,7 +100,7 @@ ____atomic_test_and_clear_bit(unsigned int bit, unsigned long *p) } static inline int -____atomic_test_and_change_bit(unsigned int bit, unsigned long *p) +____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned int res; @@ -171,7 +171,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *p) /* * This routine doesn't need to be atomic. */ -static inline int __test_bit(int nr, const unsigned long * p) +static inline int __test_bit(int nr, const volatile unsigned long * p) { return (p[nr >> 5] >> (nr & 31)) & 1UL; } @@ -204,24 +204,24 @@ static inline int __test_bit(int nr, const unsigned long * p) /* * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. */ -extern void _set_bit_le(int nr, unsigned long * p); -extern void _clear_bit_le(int nr, unsigned long * p); -extern void _change_bit_le(int nr, unsigned long * p); -extern int _test_and_set_bit_le(int nr, unsigned long * p); -extern int _test_and_clear_bit_le(int nr, unsigned long * p); -extern int _test_and_change_bit_le(int nr, unsigned long * p); +extern void _set_bit_le(int nr, volatile unsigned long * p); +extern void _clear_bit_le(int nr, volatile unsigned long * p); +extern void _change_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_set_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p); +extern int _test_and_change_bit_le(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_le(void * p, unsigned size); extern int _find_next_zero_bit_le(void * p, int size, int offset); /* * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. */ -extern void _set_bit_be(int nr, unsigned long * p); -extern void _clear_bit_be(int nr, unsigned long * p); -extern void _change_bit_be(int nr, unsigned long * p); -extern int _test_and_set_bit_be(int nr, unsigned long * p); -extern int _test_and_clear_bit_be(int nr, unsigned long * p); -extern int _test_and_change_bit_be(int nr, unsigned long * p); +extern void _set_bit_be(int nr, volatile unsigned long * p); +extern void _clear_bit_be(int nr, volatile unsigned long * p); +extern void _change_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_set_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p); +extern int _test_and_change_bit_be(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_be(void * p, unsigned size); extern int _find_next_zero_bit_be(void * p, int size, int offset); -- cgit v1.2.3 From db1708fb0469f7968a91aa6dc31db9ef17f43200 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Jan 2004 15:51:00 +0000 Subject: [ARM] Add comments for newish functions in cacheflush.h --- include/asm-arm/cacheflush.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index a88a0d97e62c..ba660c9524c1 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -209,8 +209,21 @@ extern void dmac_flush_range(unsigned long, unsigned long); #endif +/* + * flush_cache_vmap() is used when creating mappings (eg, via vmap, + * vmalloc, ioremap etc) in kernel space for pages. Since the + * direct-mappings of these pages may contain cached data, we need + * to do a full cache flush to ensure that writebacks don't corrupt + * data placed into these pages via the new mappings. + */ #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() + +/* + * Copy user data from/to a page which is mapped into a different + * processes address space. Really, we want to allow our "user + * space" model to handle this. + */ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { memcpy(dst, src, len); \ flush_icache_user_range(vma, page, vaddr, len); \ -- cgit v1.2.3 From 87eb058e699842a294f4bfa64cb08ef20a675b49 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 30 Jan 2004 16:25:58 +0000 Subject: [ARM] Remove FP work-arounds. We used to have code to allow binaries linked against glibc to run, when glibc itself contained some FP instructions (for PCS stack frames for functions like printf and scanf) thereby allowing FP emulators like nwfpe to be built as modules. This has proved to be unreliable with later compilers, so support for this was dropped a while ago. Since no one complained, we can finally remove the dead code. (NB. a klibc based module-init-tools shouldn't suffer from this problem.) --- arch/arm/kernel/entry-armv.S | 44 +------------------------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index da2f8fa12d23..ef2e2304b384 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -673,48 +673,6 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE and r2, r6, #31 @ int mode b bad_mode -#if 1 /* defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE */ - /* The FPE is always present */ - .equ fpe_not_present, fpundefinstr -#else -wfs_mask_data: .word 0x0e200110 @ WFS/RFS - .word 0x0fef0fff - .word 0x0d000100 @ LDF [sp]/STF [sp] - .word 0x0d000100 @ LDF [fp]/STF [fp] - .word 0x0f000f00 - -/* We get here if an undefined instruction happens and the floating - * point emulator is not present. If the offending instruction was - * a WFS, we just perform a normal return as if we had emulated the - * operation. This is a hack to allow some basic userland binaries - * to run so that the emulator module proper can be loaded. --philb - */ -fpe_not_present: - adr r10, wfs_mask_data - ldmia r10, {r4, r5, r6, r7, r8} - ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #4 - mask_pc r10, r10 - ldrt r10, [r10] @ get instruction - and r5, r10, r5 - teq r5, r4 @ Is it WFS? - moveq pc, r9 - and r5, r10, r8 - teq r5, r6 @ Is it LDF/STF on sp or fp? - teqne r5, r7 - movne pc, lr - tst r10, #0x00200000 @ Does it have WB - moveq pc, r9 - and r4, r10, #255 @ get offset - and r6, r10, #0x000f0000 - tst r10, #0x00800000 @ +/- - ldr r5, [sp, r6, lsr #14] @ Load reg - rsbeq r4, r4, #0 - add r5, r5, r4, lsl #2 - str r5, [sp, r6, lsr #14] @ Save reg - mov pc, r9 -#endif - /* * SVC mode handlers */ @@ -1014,7 +972,7 @@ do_fpe: ldr r4, .LCfp .data ENTRY(fp_enter) - .word fpe_not_present + .word fpundefinstr .text fpundefinstr: mov r0, sp -- cgit v1.2.3 From 6f7d8d3501e8e86f3004b42926b240936e1e75f1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Jan 2004 19:21:01 -0800 Subject: [SPARC64]: Fix wakeup races in power.c, with help from Andrew Morton. --- arch/sparc64/kernel/power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index b53ecb88a780..bebec2e39398 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -29,8 +29,8 @@ static int button_pressed; static irqreturn_t power_handler(int irq, void *dev_id, struct pt_regs *regs) { if (button_pressed == 0) { - wake_up(&powerd_wait); button_pressed = 1; + wake_up(&powerd_wait); } /* FIXME: Check registers for status... */ @@ -86,10 +86,10 @@ again: remove_wait_queue(&powerd_wait, &wait); /* Ok, down we go... */ + button_pressed = 0; if (execve("/sbin/shutdown", argv, envp) < 0) { printk("powerd: shutdown execution failed\n"); add_wait_queue(&powerd_wait, &wait); - button_pressed = 0; goto again; } return 0; -- cgit v1.2.3 From f4cc08388419618118df13174a2938faa661c123 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Thu, 29 Jan 2004 20:13:47 -0800 Subject: [PATCH] PC300 update This forward ports a few important fixes from the 2.4 driver. This changes have been well tested. Changelog: - Update maintainer email address - Mark pci_device_id list with __devinitdata. - Set correct protocol type on packet receive (this caused the kernel to drop all packets received) - Add #ifdef DEBUG around debug printk() - ioctl: Add missing size checks before copying data from userspace. --- drivers/net/wan/pc300_drv.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 3280721c3002..58a7914967cc 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -6,9 +6,9 @@ static char rcsid[] = * pc300.c Cyclades-PC300(tm) Driver. * * Author: Ivan Passos - * Maintainer: Henrique Gobbi + * Maintainer: PC300 Maintainer * - * Copyright: (c) 1999-2002 Cyclades Corp. + * Copyright: (c) 1999-2003 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -252,7 +252,7 @@ static char rcsid[] = #undef PC300_DEBUG_RX #undef PC300_DEBUG_OTHER -static struct pci_device_id cpc_pci_dev_id[] = { +static struct pci_device_id cpc_pci_dev_id[] __devinitdata = { /* PC300/RSV or PC300/X21, 2 chan */ {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300}, /* PC300/RSV or PC300/X21, 1 chan */ @@ -1961,7 +1961,7 @@ void cpc_net_rx(hdlc_device * hdlc) } stats->rx_packets++; skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_HDLC); + skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } } @@ -2088,9 +2088,10 @@ static void sca_intr(pc300_t * card) } } if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { - -printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", - dev->name, ch, status, drx_stat, dsr_rx); +#ifdef PC300_DEBUG_INTR + printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n", + dev->name, ch, status, drx_stat, dsr_rx); +#endif cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe); } } @@ -2770,6 +2771,10 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) { return -EPERM; } + /* incorrect data len? */ + if (ifr->ifr_settings.size != size) { + return -ENOBUFS; + } if (copy_from_user(&conf->phys_settings, settings->ifs_ifsu.sync, size)) { @@ -2788,12 +2793,18 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case IF_IFACE_T1: case IF_IFACE_E1: { + const size_t te_size = sizeof(te1_settings); const size_t size = sizeof(sync_serial_settings); if (!capable(CAP_NET_ADMIN)) { return -EPERM; } - + + /* incorrect data len? */ + if (ifr->ifr_settings.size != te_size) { + return -ENOBUFS; + } + if (copy_from_user(&conf->phys_settings, settings->ifs_ifsu.te1, size)) { return -EFAULT; @@ -3667,12 +3678,10 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev) } static struct pci_driver cpc_driver = { - .name = "pc300", - .id_table = cpc_pci_dev_id, - .probe = cpc_init_one, - .remove = cpc_remove_one, - .suspend = NULL, - .resume = NULL, + .name = "pc300", + .id_table = cpc_pci_dev_id, + .probe = cpc_init_one, + .remove = __devexit_p(cpc_remove_one), }; static int __init cpc_init(void) @@ -3690,6 +3699,6 @@ module_exit(cpc_cleanup_module); MODULE_DESCRIPTION("Cyclades-PC300 cards driver"); MODULE_AUTHOR( "Author: Ivan Passos \r\n" - "Maintainer: Henrique Gobbi Date: Sat, 31 Jan 2004 09:47:51 +1100 Subject: [XFS] Christoph has signed over copyrights SGI Modid: xfs-linux:xfs-kern:165037a --- fs/xfs/support/mutex.h | 1 - fs/xfs/support/spin.h | 1 - fs/xfs/support/sv.h | 1 - 3 files changed, 3 deletions(-) diff --git a/fs/xfs/support/mutex.h b/fs/xfs/support/mutex.h index 3cdbff77f8fe..0b296bb944cb 100644 --- a/fs/xfs/support/mutex.h +++ b/fs/xfs/support/mutex.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/fs/xfs/support/spin.h b/fs/xfs/support/spin.h index b5bd2759d332..80a3a6bae568 100644 --- a/fs/xfs/support/spin.h +++ b/fs/xfs/support/spin.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/fs/xfs/support/sv.h b/fs/xfs/support/sv.h index bb38b1100cdb..821d3167e05b 100644 --- a/fs/xfs/support/sv.h +++ b/fs/xfs/support/sv.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as -- cgit v1.2.3 From 2c640f57dd9f4fcb284569e914f9d4674e2e149d Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Sat, 31 Jan 2004 10:54:04 +1100 Subject: [XFS] Fix a warning from some gcc variants after recent flags botch. SGI Modid: xfs-linux:xfs-kern:165646a --- fs/xfs/xfs_log_recover.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index f0d4e7136751..f028eac24642 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1531,7 +1531,7 @@ xlog_recover_reorder_trans( xlog_recover_item_t *first_item, *itemq, *itemq_next; xfs_buf_log_format_t *buf_f; xfs_buf_log_format_v1_t *obuf_f; - ushort flags; + ushort flags = 0; first_item = itemq = trans->r_itemq; trans->r_itemq = NULL; -- cgit v1.2.3 From eb8171b8cb011e3d0455dc44afaeea2e4402dc4f Mon Sep 17 00:00:00 2001 From: Russell Cattelan Date: Sat, 31 Jan 2004 12:07:59 +1100 Subject: [XFS] Move bits around to better manage common code. No functional change. --- fs/xfs/Makefile | 12 +- fs/xfs/linux/kmem.h | 189 ++++ fs/xfs/linux/mrlock.c | 274 ++++++ fs/xfs/linux/mrlock.h | 87 ++ fs/xfs/linux/mutex.h | 53 ++ fs/xfs/linux/sema.h | 67 ++ fs/xfs/linux/spin.h | 74 ++ fs/xfs/linux/sv.h | 89 ++ fs/xfs/linux/time.h | 51 ++ fs/xfs/linux/xfs_behavior.c | 218 ----- fs/xfs/linux/xfs_behavior.h | 204 ----- fs/xfs/linux/xfs_buf.c | 2110 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/linux/xfs_buf.h | 618 +++++++++++++ fs/xfs/linux/xfs_iomap.c | 795 ---------------- fs/xfs/linux/xfs_linux.h | 33 +- fs/xfs/pagebuf/page_buf.c | 2107 ------------------------------------------ fs/xfs/pagebuf/page_buf.h | 340 ------- fs/xfs/support/kmem.h | 189 ---- fs/xfs/support/ktrace.c | 4 +- fs/xfs/support/ktrace.h | 2 +- fs/xfs/support/mrlock.c | 274 ------ fs/xfs/support/mrlock.h | 87 -- fs/xfs/support/mutex.h | 53 -- fs/xfs/support/sema.h | 67 -- fs/xfs/support/spin.h | 74 -- fs/xfs/support/sv.h | 89 -- fs/xfs/support/time.h | 51 -- fs/xfs/support/uuid.c | 6 +- fs/xfs/xfs.h | 7 - fs/xfs/xfs_behavior.c | 218 +++++ fs/xfs/xfs_behavior.h | 204 +++++ fs/xfs/xfs_buf.h | 308 ------- fs/xfs/xfs_iomap.c | 795 ++++++++++++++++ 33 files changed, 4860 insertions(+), 4889 deletions(-) create mode 100644 fs/xfs/linux/kmem.h create mode 100644 fs/xfs/linux/mrlock.c create mode 100644 fs/xfs/linux/mrlock.h create mode 100644 fs/xfs/linux/mutex.h create mode 100644 fs/xfs/linux/sema.h create mode 100644 fs/xfs/linux/spin.h create mode 100644 fs/xfs/linux/sv.h create mode 100644 fs/xfs/linux/time.h delete mode 100644 fs/xfs/linux/xfs_behavior.c delete mode 100644 fs/xfs/linux/xfs_behavior.h create mode 100644 fs/xfs/linux/xfs_buf.c create mode 100644 fs/xfs/linux/xfs_buf.h delete mode 100644 fs/xfs/linux/xfs_iomap.c delete mode 100644 fs/xfs/pagebuf/page_buf.c delete mode 100644 fs/xfs/pagebuf/page_buf.h delete mode 100644 fs/xfs/support/kmem.h delete mode 100644 fs/xfs/support/mrlock.c delete mode 100644 fs/xfs/support/mrlock.h delete mode 100644 fs/xfs/support/mutex.h delete mode 100644 fs/xfs/support/sema.h delete mode 100644 fs/xfs/support/spin.h delete mode 100644 fs/xfs/support/sv.h delete mode 100644 fs/xfs/support/time.h create mode 100644 fs/xfs/xfs_behavior.c create mode 100644 fs/xfs/xfs_behavior.h delete mode 100644 fs/xfs/xfs_buf.h create mode 100644 fs/xfs/xfs_iomap.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 30c511e81a3c..5475efd6a2f7 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -30,7 +30,7 @@ # http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ # -EXTRA_CFLAGS += -Ifs/xfs -funsigned-char +EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux -funsigned-char ifeq ($(CONFIG_XFS_DEBUG),y) EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG -DXFSDEBUG @@ -83,6 +83,7 @@ xfs-y += xfs_alloc.o \ xfs_alloc_btree.o \ xfs_attr.o \ xfs_attr_leaf.o \ + xfs_behavior.o \ xfs_bit.o \ xfs_bmap.o \ xfs_bmap_btree.o \ @@ -106,6 +107,7 @@ xfs-y += xfs_alloc.o \ xfs_inode.o \ xfs_inode_item.o \ xfs_iocore.o \ + xfs_iomap.o \ xfs_itable.o \ xfs_dfrag.o \ xfs_log.o \ @@ -126,18 +128,15 @@ xfs-y += xfs_alloc.o \ xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o -# Objects in pagebuf/ -xfs-y += pagebuf/page_buf.o - # Objects in linux/ xfs-y += $(addprefix linux/, \ + mrlock.o \ xfs_aops.o \ - xfs_behavior.o \ + xfs_buf.o \ xfs_file.o \ xfs_fs_subr.o \ xfs_globals.o \ xfs_ioctl.o \ - xfs_iomap.o \ xfs_iops.o \ xfs_lrw.o \ xfs_super.o \ @@ -148,7 +147,6 @@ xfs-y += $(addprefix linux/, \ xfs-y += $(addprefix support/, \ debug.o \ move.o \ - mrlock.o \ qsort.o \ uuid.o) diff --git a/fs/xfs/linux/kmem.h b/fs/xfs/linux/kmem.h new file mode 100644 index 000000000000..a8fb09f2f604 --- /dev/null +++ b/fs/xfs/linux/kmem.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_KMEM_H__ +#define __XFS_SUPPORT_KMEM_H__ + +#include +#include +#include +#include + +/* + * Cutoff point to use vmalloc instead of kmalloc. + */ +#define MAX_SLAB_SIZE 0x10000 + +/* + * XFS uses slightly different names for these due to the + * IRIX heritage. + */ +#define kmem_zone kmem_cache_s +#define kmem_zone_t kmem_cache_t + +#define KM_SLEEP 0x0001 +#define KM_NOSLEEP 0x0002 +#define KM_NOFS 0x0004 + +typedef unsigned long xfs_pflags_t; + +#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) + +#define PFLAGS_SET_FSTRANS(STATEP) do { \ + *(STATEP) = current->flags; \ + current->flags |= PF_FSTRANS; \ +} while (0) + +#define PFLAGS_RESTORE(STATEP) do { \ + current->flags = *(STATEP); \ +} while (0) + +#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ + *(NSTATEP) = *(OSTATEP); \ +} while (0) + +/* + * XXX get rid of the unconditional __GFP_NOFAIL by adding + * a KM_FAIL flag and using it where we're allowed to fail. + */ +static __inline unsigned int +kmem_flags_convert(int flags) +{ + int lflags; + +#if DEBUG + if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) { + printk(KERN_WARNING + "XFS: memory allocation with wrong flags (%x)\n", flags); + BUG(); + } +#endif + + lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL); + + /* avoid recusive callbacks to filesystem during transactions */ + if (PFLAGS_TEST_FSTRANS()) + lflags &= ~__GFP_FS; + + return lflags; +} + +static __inline void * +kmem_alloc(size_t size, int flags) +{ + if (unlikely(MAX_SLAB_SIZE < size)) + /* Avoid doing filesystem sensitive stuff to get this */ + return __vmalloc(size, kmem_flags_convert(flags), PAGE_KERNEL); + return kmalloc(size, kmem_flags_convert(flags)); +} + +static __inline void * +kmem_zalloc(size_t size, int flags) +{ + void *ptr = kmem_alloc(size, flags); + if (likely(ptr != NULL)) + memset(ptr, 0, size); + return ptr; +} + +static __inline void +kmem_free(void *ptr, size_t size) +{ + if (unlikely((unsigned long)ptr < VMALLOC_START || + (unsigned long)ptr >= VMALLOC_END)) + kfree(ptr); + else + vfree(ptr); +} + +static __inline void * +kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags) +{ + void *new = kmem_alloc(newsize, flags); + + if (likely(ptr != NULL)) { + if (likely(new != NULL)) + memcpy(new, ptr, min(oldsize, newsize)); + kmem_free(ptr, oldsize); + } + + return new; +} + +static __inline kmem_zone_t * +kmem_zone_init(int size, char *zone_name) +{ + return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL); +} + +static __inline void * +kmem_zone_alloc(kmem_zone_t *zone, int flags) +{ + return kmem_cache_alloc(zone, kmem_flags_convert(flags)); +} + +static __inline void * +kmem_zone_zalloc(kmem_zone_t *zone, int flags) +{ + void *ptr = kmem_zone_alloc(zone, flags); + if (likely(ptr != NULL)) + memset(ptr, 0, kmem_cache_size(zone)); + return ptr; +} + +static __inline void +kmem_zone_free(kmem_zone_t *zone, void *ptr) +{ + kmem_cache_free(zone, ptr); +} + +typedef struct shrinker *kmem_shaker_t; +typedef int (*kmem_shake_func_t)(int, unsigned int); + +static __inline kmem_shaker_t +kmem_shake_register(kmem_shake_func_t sfunc) +{ + return set_shrinker(DEFAULT_SEEKS, sfunc); +} + +static __inline void +kmem_shake_deregister(kmem_shaker_t shrinker) +{ + remove_shrinker(shrinker); +} + +static __inline int +kmem_shake_allow(unsigned int gfp_mask) +{ + return (gfp_mask & __GFP_WAIT); +} + +#endif /* __XFS_SUPPORT_KMEM_H__ */ diff --git a/fs/xfs/linux/mrlock.c b/fs/xfs/linux/mrlock.c new file mode 100644 index 000000000000..5b5dae97af9c --- /dev/null +++ b/fs/xfs/linux/mrlock.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include +#include +#include +#include +#include + +#include "mrlock.h" + + +#if USE_RW_WAIT_QUEUE_SPINLOCK +# define wq_write_lock write_lock +#else +# define wq_write_lock spin_lock +#endif + +/* + * We don't seem to need lock_type (only one supported), name, or + * sequence. But, XFS will pass it so let's leave them here for now. + */ +/* ARGSUSED */ +void +mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence) +{ + mrp->mr_count = 0; + mrp->mr_reads_waiting = 0; + mrp->mr_writes_waiting = 0; + init_waitqueue_head(&mrp->mr_readerq); + init_waitqueue_head(&mrp->mr_writerq); + mrp->mr_lock = SPIN_LOCK_UNLOCKED; +} + +/* + * Macros to lock/unlock the mrlock_t. + */ + +#define MRLOCK(m) spin_lock(&(m)->mr_lock); +#define MRUNLOCK(m) spin_unlock(&(m)->mr_lock); + + +/* + * lock_wait should never be called in an interrupt thread. + * + * mrlocks can sleep (i.e. call schedule) and so they can't ever + * be called from an interrupt thread. + * + * threads that wake-up should also never be invoked from interrupt threads. + * + * But, waitqueue_lock is locked from interrupt threads - and we are + * called with interrupts disabled, so it is all OK. + */ + +/* ARGSUSED */ +void +lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw) +{ + DECLARE_WAITQUEUE( wait, current ); + + __set_current_state(TASK_UNINTERRUPTIBLE); + + spin_lock(&q->lock); + if (rw) { + __add_wait_queue_tail(q, &wait); + } else { + __add_wait_queue(q, &wait); + } + + spin_unlock(&q->lock); + spin_unlock(lock); + + schedule(); + + spin_lock(&q->lock); + __remove_wait_queue(q, &wait); + spin_unlock(&q->lock); + + spin_lock(lock); + + /* return with lock held */ +} + +/* ARGSUSED */ +void +mrfree(mrlock_t *mrp) +{ +} + +/* ARGSUSED */ +void +mrlock(mrlock_t *mrp, int type, int flags) +{ + if (type == MR_ACCESS) + mraccess(mrp); + else + mrupdate(mrp); +} + +/* ARGSUSED */ +void +mraccessf(mrlock_t *mrp, int flags) +{ + MRLOCK(mrp); + if(mrp->mr_writes_waiting > 0) { + mrp->mr_reads_waiting++; + lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); + mrp->mr_reads_waiting--; + } + while (mrp->mr_count < 0) { + mrp->mr_reads_waiting++; + lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); + mrp->mr_reads_waiting--; + } + mrp->mr_count++; + MRUNLOCK(mrp); +} + +/* ARGSUSED */ +void +mrupdatef(mrlock_t *mrp, int flags) +{ + MRLOCK(mrp); + while(mrp->mr_count) { + mrp->mr_writes_waiting++; + lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1); + mrp->mr_writes_waiting--; + } + + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); +} + +int +mrtryaccess(mrlock_t *mrp) +{ + MRLOCK(mrp); + /* + * If anyone is waiting for update access or the lock is held for update + * fail the request. + */ + if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) { + MRUNLOCK(mrp); + return 0; + } + mrp->mr_count++; + MRUNLOCK(mrp); + return 1; +} + +int +mrtrypromote(mrlock_t *mrp) +{ + MRLOCK(mrp); + + if(mrp->mr_count == 1) { /* We are the only thread with the lock */ + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); + return 1; + } + + MRUNLOCK(mrp); + return 0; +} + +int +mrtryupdate(mrlock_t *mrp) +{ + MRLOCK(mrp); + + if(mrp->mr_count) { + MRUNLOCK(mrp); + return 0; + } + + mrp->mr_count = -1; /* writer on it */ + MRUNLOCK(mrp); + return 1; +} + +static __inline__ void mrwake(mrlock_t *mrp) +{ + /* + * First, if the count is now 0, we need to wake-up anyone waiting. + */ + if (!mrp->mr_count) { + if (mrp->mr_writes_waiting) { /* Wake-up first writer waiting */ + wake_up(&mrp->mr_writerq); + } else if (mrp->mr_reads_waiting) { /* Wakeup any readers waiting */ + wake_up(&mrp->mr_readerq); + } + } +} + +void +mraccunlock(mrlock_t *mrp) +{ + MRLOCK(mrp); + mrp->mr_count--; + mrwake(mrp); + MRUNLOCK(mrp); +} + +void +mrunlock(mrlock_t *mrp) +{ + MRLOCK(mrp); + if (mrp->mr_count < 0) { + mrp->mr_count = 0; + } else { + mrp->mr_count--; + } + mrwake(mrp); + MRUNLOCK(mrp); +} + +int +ismrlocked(mrlock_t *mrp, int type) /* No need to lock since info can change */ +{ + if (type == MR_ACCESS) + return (mrp->mr_count > 0); /* Read lock */ + else if (type == MR_UPDATE) + return (mrp->mr_count < 0); /* Write lock */ + else if (type == (MR_UPDATE | MR_ACCESS)) + return (mrp->mr_count); /* Any type of lock held */ + else /* Any waiters */ + return (mrp->mr_reads_waiting | mrp->mr_writes_waiting); +} + +/* + * Demote from update to access. We better be the only thread with the + * lock in update mode so it should be easy to set to 1. + * Wake-up any readers waiting. + */ + +void +mrdemote(mrlock_t *mrp) +{ + MRLOCK(mrp); + mrp->mr_count = 1; + if (mrp->mr_reads_waiting) { /* Wakeup all readers waiting */ + wake_up(&mrp->mr_readerq); + } + MRUNLOCK(mrp); +} diff --git a/fs/xfs/linux/mrlock.h b/fs/xfs/linux/mrlock.h new file mode 100644 index 000000000000..b2a7b3ad5eff --- /dev/null +++ b/fs/xfs/linux/mrlock.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_MRLOCK_H__ +#define __XFS_SUPPORT_MRLOCK_H__ + +#include +#include +#include +#include + +/* + * Implement mrlocks on Linux that work for XFS. + * + * These are sleep locks and not spinlocks. If one wants read/write spinlocks, + * use read_lock, write_lock, ... see spinlock.h. + */ + +typedef struct mrlock_s { + int mr_count; + unsigned short mr_reads_waiting; + unsigned short mr_writes_waiting; + wait_queue_head_t mr_readerq; + wait_queue_head_t mr_writerq; + spinlock_t mr_lock; +} mrlock_t; + +#define MR_ACCESS 1 +#define MR_UPDATE 2 + +#define MRLOCK_BARRIER 0x1 +#define MRLOCK_ALLOW_EQUAL_PRI 0x8 + +/* + * mraccessf/mrupdatef take flags to be passed in while sleeping; + * only PLTWAIT is currently supported. + */ + +extern void mraccessf(mrlock_t *, int); +extern void mrupdatef(mrlock_t *, int); +extern void mrlock(mrlock_t *, int, int); +extern void mrunlock(mrlock_t *); +extern void mraccunlock(mrlock_t *); +extern int mrtryupdate(mrlock_t *); +extern int mrtryaccess(mrlock_t *); +extern int mrtrypromote(mrlock_t *); +extern void mrdemote(mrlock_t *); + +extern int ismrlocked(mrlock_t *, int); +extern void mrlock_init(mrlock_t *, int type, char *name, long sequence); +extern void mrfree(mrlock_t *); + +#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1) +#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ +#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ +#define mrislocked_access(mrp) ((mrp)->mr_count > 0) +#define mrislocked_update(mrp) ((mrp)->mr_count < 0) + +#endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff --git a/fs/xfs/linux/mutex.h b/fs/xfs/linux/mutex.h new file mode 100644 index 000000000000..0b296bb944cb --- /dev/null +++ b/fs/xfs/linux/mutex.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_MUTEX_H__ +#define __XFS_SUPPORT_MUTEX_H__ + +#include +#include + +/* + * Map the mutex'es from IRIX to Linux semaphores. + * + * Destroy just simply initializes to -99 which should block all other + * callers. + */ +#define MUTEX_DEFAULT 0x0 +typedef struct semaphore mutex_t; + +#define mutex_init(lock, type, name) sema_init(lock, 1) +#define mutex_destroy(lock) sema_init(lock, -99) +#define mutex_lock(lock, num) down(lock) +#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) +#define mutex_unlock(lock) up(lock) + +#endif /* __XFS_SUPPORT_MUTEX_H__ */ diff --git a/fs/xfs/linux/sema.h b/fs/xfs/linux/sema.h new file mode 100644 index 000000000000..30b67b4e1cbf --- /dev/null +++ b/fs/xfs/linux/sema.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SEMA_H__ +#define __XFS_SUPPORT_SEMA_H__ + +#include +#include +#include +#include + +/* + * sema_t structure just maps to struct semaphore in Linux kernel. + */ + +typedef struct semaphore sema_t; + +#define init_sema(sp, val, c, d) sema_init(sp, val) +#define initsema(sp, val) sema_init(sp, val) +#define initnsema(sp, val, name) sema_init(sp, val) +#define psema(sp, b) down(sp) +#define vsema(sp) up(sp) +#define valusema(sp) (atomic_read(&(sp)->count)) +#define freesema(sema) + +/* + * Map cpsema (try to get the sema) to down_trylock. We need to switch + * the return values since cpsema returns 1 (acquired) 0 (failed) and + * down_trylock returns the reverse 0 (acquired) 1 (failed). + */ + +#define cpsema(sp) (down_trylock(sp) ? 0 : 1) + +/* + * Didn't do cvsema(sp). Not sure how to map this to up/down/... + * It does a vsema if the values is < 0 other wise nothing. + */ + +#endif /* __XFS_SUPPORT_SEMA_H__ */ diff --git a/fs/xfs/linux/spin.h b/fs/xfs/linux/spin.h new file mode 100644 index 000000000000..80a3a6bae568 --- /dev/null +++ b/fs/xfs/linux/spin.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SPIN_H__ +#define __XFS_SUPPORT_SPIN_H__ + +#include /* preempt needs this */ +#include + +/* + * Map lock_t from IRIX to Linux spinlocks. + * + * Note that linux turns on/off spinlocks depending on CONFIG_SMP. + * We don't need to worry about SMP or not here. + */ + +#define SPLDECL(s) unsigned long s + +typedef spinlock_t lock_t; + +#define spinlock_init(lock, name) spin_lock_init(lock) +#define spinlock_destroy(lock) + +static inline unsigned long mutex_spinlock(lock_t *lock) +{ + spin_lock(lock); + return 0; +} + +/*ARGSUSED*/ +static inline void mutex_spinunlock(lock_t *lock, unsigned long s) +{ + spin_unlock(lock); +} + +static inline void nested_spinlock(lock_t *lock) +{ + spin_lock(lock); +} + +static inline void nested_spinunlock(lock_t *lock) +{ + spin_unlock(lock); +} + +#endif /* __XFS_SUPPORT_SPIN_H__ */ diff --git a/fs/xfs/linux/sv.h b/fs/xfs/linux/sv.h new file mode 100644 index 000000000000..821d3167e05b --- /dev/null +++ b/fs/xfs/linux/sv.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_SV_H__ +#define __XFS_SUPPORT_SV_H__ + +#include +#include +#include + +/* + * Synchronisation variables. + * + * (Parameters "pri", "svf" and "rts" are not implemented) + */ + +typedef struct sv_s { + wait_queue_head_t waiters; +} sv_t; + +#define SV_FIFO 0x0 /* sv_t is FIFO type */ +#define SV_LIFO 0x2 /* sv_t is LIFO type */ +#define SV_PRIO 0x4 /* sv_t is PRIO type */ +#define SV_KEYED 0x6 /* sv_t is KEYED type */ +#define SV_DEFAULT SV_FIFO + + +static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, + unsigned long timeout) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue_exclusive(&sv->waiters, &wait); + __set_current_state(state); + spin_unlock(lock); + + schedule_timeout(timeout); + + remove_wait_queue(&sv->waiters, &wait); +} + +#define init_sv(sv,type,name,flag) \ + init_waitqueue_head(&(sv)->waiters) +#define sv_init(sv,flag,name) \ + init_waitqueue_head(&(sv)->waiters) +#define sv_destroy(sv) \ + /*NOTHING*/ +#define sv_wait(sv, pri, lock, s) \ + _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) +#define sv_wait_sig(sv, pri, lock, s) \ + _sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) +#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \ + _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts)) +#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \ + _sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts)) +#define sv_signal(sv) \ + wake_up(&(sv)->waiters) +#define sv_broadcast(sv) \ + wake_up_all(&(sv)->waiters) + +#endif /* __XFS_SUPPORT_SV_H__ */ diff --git a/fs/xfs/linux/time.h b/fs/xfs/linux/time.h new file mode 100644 index 000000000000..109b5c0833f8 --- /dev/null +++ b/fs/xfs/linux/time.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_SUPPORT_TIME_H__ +#define __XFS_SUPPORT_TIME_H__ + +#include +#include + +typedef struct timespec timespec_t; + +static inline void delay(long ticks) +{ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(ticks); +} + +static inline void nanotime(struct timespec *tvp) +{ + *tvp = CURRENT_TIME; +} + +#endif /* __XFS_SUPPORT_TIME_H__ */ diff --git a/fs/xfs/linux/xfs_behavior.c b/fs/xfs/linux/xfs_behavior.c deleted file mode 100644 index 16088e175ecc..000000000000 --- a/fs/xfs/linux/xfs_behavior.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - * - */ -#include "xfs.h" - -/* - * Source file used to associate/disassociate behaviors with virtualized - * objects. See xfs_behavior.h for more information about behaviors, etc. - * - * The implementation is split between functions in this file and macros - * in xfs_behavior.h. - */ - -/* - * Insert a new behavior descriptor into a behavior chain. - * - * The behavior chain is ordered based on the 'position' number which - * lives in the first field of the ops vector (higher numbers first). - * - * Attemps to insert duplicate ops result in an EINVAL return code. - * Otherwise, return 0 to indicate success. - */ -int -bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - int position; - - /* - * Validate the position value of the new behavior. - */ - position = BHV_POSITION(bdp); - ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); - - /* - * Find location to insert behavior. Check for duplicates. - */ - prev = NULL; - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - /* Check for duplication. */ - if (curdesc->bd_ops == bdp->bd_ops) { - ASSERT(0); - return EINVAL; - } - - /* Find correct position */ - if (position >= BHV_POSITION(curdesc)) { - ASSERT(position != BHV_POSITION(curdesc)); - break; /* found it */ - } - - prev = curdesc; - } - - if (prev == NULL) { - /* insert at front of chain */ - bdp->bd_next = bhp->bh_first; - bhp->bh_first = bdp; - } else { - /* insert after prev */ - bdp->bd_next = prev->bd_next; - prev->bd_next = bdp; - } - - return 0; -} - -/* - * Remove a behavior descriptor from a position in a behavior chain; - * the postition is guaranteed not to be the first position. - * Should only be called by the bhv_remove() macro. - */ -void -bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - - ASSERT(bhp->bh_first != NULL); - ASSERT(bhp->bh_first->bd_next != NULL); - - prev = bhp->bh_first; - for (curdesc = bhp->bh_first->bd_next; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc == bdp) - break; /* found it */ - prev = curdesc; - } - - ASSERT(curdesc == bdp); - prev->bd_next = bdp->bd_next; /* remove from after prev */ -} - -/* - * Look for a specific ops vector on the specified behavior chain. - * Return the associated behavior descriptor. Or NULL, if not found. - */ -bhv_desc_t * -bhv_lookup(bhv_head_t *bhp, void *ops) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc->bd_ops == ops) - return curdesc; - } - - return NULL; -} - -/* - * Looks for the first behavior within a specified range of positions. - * Return the associated behavior descriptor. Or NULL, if none found. - */ -bhv_desc_t * -bhv_lookup_range(bhv_head_t *bhp, int low, int high) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - int position = BHV_POSITION(curdesc); - - if (position <= high) { - if (position >= low) - return curdesc; - return NULL; - } - } - - return NULL; -} - -/* - * Return the base behavior in the chain, or NULL if the chain - * is empty. - * - * The caller has not read locked the behavior chain, so acquire the - * lock before traversing the chain. - */ -bhv_desc_t * -bhv_base(bhv_head_t *bhp) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc->bd_next == NULL) { - return curdesc; - } - } - - return NULL; -} - -void -bhv_head_init( - bhv_head_t *bhp, - char *name) -{ - bhp->bh_first = NULL; -} - -void -bhv_insert_initial( - bhv_head_t *bhp, - bhv_desc_t *bdp) -{ - ASSERT(bhp->bh_first == NULL); - (bhp)->bh_first = bdp; -} - -void -bhv_head_destroy( - bhv_head_t *bhp) -{ - ASSERT(bhp->bh_first == NULL); -} diff --git a/fs/xfs/linux/xfs_behavior.h b/fs/xfs/linux/xfs_behavior.h deleted file mode 100644 index d5ed5a843921..000000000000 --- a/fs/xfs/linux/xfs_behavior.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_BEHAVIOR_H__ -#define __XFS_BEHAVIOR_H__ - -/* - * Header file used to associate behaviors with virtualized objects. - * - * A virtualized object is an internal, virtualized representation of - * OS entities such as persistent files, processes, or sockets. Examples - * of virtualized objects include vnodes, vprocs, and vsockets. Often - * a virtualized object is referred to simply as an "object." - * - * A behavior is essentially an implementation layer associated with - * an object. Multiple behaviors for an object are chained together, - * the order of chaining determining the order of invocation. Each - * behavior of a given object implements the same set of interfaces - * (e.g., the VOP interfaces). - * - * Behaviors may be dynamically inserted into an object's behavior chain, - * such that the addition is transparent to consumers that already have - * references to the object. Typically, a given behavior will be inserted - * at a particular location in the behavior chain. Insertion of new - * behaviors is synchronized with operations-in-progress (oip's) so that - * the oip's always see a consistent view of the chain. - * - * The term "interpostion" is used to refer to the act of inserting - * a behavior such that it interposes on (i.e., is inserted in front - * of) a particular other behavior. A key example of this is when a - * system implementing distributed single system image wishes to - * interpose a distribution layer (providing distributed coherency) - * in front of an object that is otherwise only accessed locally. - * - * Note that the traditional vnode/inode combination is simply a virtualized - * object that has exactly one associated behavior. - * - * Behavior synchronization is logic which is necessary under certain - * circumstances that there is no conflict between ongoing operations - * traversing the behavior chain and those dunamically modifying the - * behavior chain. Because behavior synchronization adds extra overhead - * to virtual operation invocation, we want to restrict, as much as - * we can, the requirement for this extra code, to those situations - * in which it is truly necessary. - * - * Behavior synchronization is needed whenever there's at least one class - * of object in the system for which: - * 1) multiple behaviors for a given object are supported, - * -- AND -- - * 2a) insertion of a new behavior can happen dynamically at any time during - * the life of an active object, - * -- AND -- - * 3a) insertion of a new behavior needs to synchronize with existing - * ops-in-progress. - * -- OR -- - * 3b) multiple different behaviors can be dynamically inserted at - * any time during the life of an active object - * -- OR -- - * 3c) removal of a behavior can occur at any time during the life of - * an active object. - * -- OR -- - * 2b) removal of a behavior can occur at any time during the life of an - * active object - * - */ - -struct bhv_head_lock; - -/* - * Behavior head. Head of the chain of behaviors. - * Contained within each virtualized object data structure. - */ -typedef struct bhv_head { - struct bhv_desc *bh_first; /* first behavior in chain */ - struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ -} bhv_head_t; - -/* - * Behavior descriptor. Descriptor associated with each behavior. - * Contained within the behavior's private data structure. - */ -typedef struct bhv_desc { - void *bd_pdata; /* private data for this behavior */ - void *bd_vobj; /* virtual object associated with */ - void *bd_ops; /* ops for this behavior */ - struct bhv_desc *bd_next; /* next behavior in chain */ -} bhv_desc_t; - -/* - * Behavior identity field. A behavior's identity determines the position - * where it lives within a behavior chain, and it's always the first field - * of the behavior's ops vector. The optional id field further identifies the - * subsystem responsible for the behavior. - */ -typedef struct bhv_identity { - __u16 bi_id; /* owning subsystem id */ - __u16 bi_position; /* position in chain */ -} bhv_identity_t; - -typedef bhv_identity_t bhv_position_t; - -#define BHV_IDENTITY_INIT(id,pos) {id, pos} -#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) - -/* - * Define boundaries of position values. - */ -#define BHV_POSITION_INVALID 0 /* invalid position number */ -#define BHV_POSITION_BASE 1 /* base (last) implementation layer */ -#define BHV_POSITION_TOP 63 /* top (first) implementation layer */ - -/* - * Plumbing macros. - */ -#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first) -#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next) -#define BHV_NEXTNULL(bdp) ((bdp)->bd_next) -#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj) -#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj) -#define BHV_PDATA(bdp) (bdp)->bd_pdata -#define BHV_OPS(bdp) (bdp)->bd_ops -#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) -#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) - -extern void bhv_head_init(bhv_head_t *, char *); -extern void bhv_head_destroy(bhv_head_t *); -extern int bhv_insert(bhv_head_t *, bhv_desc_t *); -extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); - -/* - * Initialize a new behavior descriptor. - * Arguments: - * bdp - pointer to behavior descriptor - * pdata - pointer to behavior's private data - * vobj - pointer to associated virtual object - * ops - pointer to ops for this behavior - */ -#define bhv_desc_init(bdp, pdata, vobj, ops) \ - { \ - (bdp)->bd_pdata = pdata; \ - (bdp)->bd_vobj = vobj; \ - (bdp)->bd_ops = ops; \ - (bdp)->bd_next = NULL; \ - } - -/* - * Remove a behavior descriptor from a behavior chain. - */ -#define bhv_remove(bhp, bdp) \ - { \ - if ((bhp)->bh_first == (bdp)) { \ - /* \ - * Remove from front of chain. \ - * Atomic wrt oip's. \ - */ \ - (bhp)->bh_first = (bdp)->bd_next; \ - } else { \ - /* remove from non-front of chain */ \ - bhv_remove_not_first(bhp, bdp); \ - } \ - (bdp)->bd_vobj = NULL; \ - } - -/* - * Behavior module prototypes. - */ -extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); -extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops); -extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); -extern bhv_desc_t * bhv_base(bhv_head_t *bhp); - -/* No bhv locking on Linux */ -#define bhv_lookup_unlocked bhv_lookup -#define bhv_base_unlocked bhv_base - -#endif /* __XFS_BEHAVIOR_H__ */ diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c new file mode 100644 index 000000000000..891fa4447f36 --- /dev/null +++ b/fs/xfs/linux/xfs_buf.c @@ -0,0 +1,2110 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +/* + * page_buf.c + * + * The page_buf module provides an abstract buffer cache model on top of + * the Linux page cache. Cached metadata blocks for a file system are + * hashed to the inode for the block device. The page_buf module + * assembles buffer (page_buf_t) objects on demand to aggregate such + * cached pages for I/O. + * + * + * Written by Steve Lord, Jim Mostek, Russell Cattelan + * and Rajagopal Ananthanarayanan ("ananth") at SGI. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "kmem.h" + +#include "xfs_types.h" +#include "xfs_cred.h" +#include "xfs_lrw.h" +#include "xfs_buf.h" + +#define BBSHIFT 9 +#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1) + +#ifndef GFP_READAHEAD +#define GFP_READAHEAD (__GFP_NOWARN|__GFP_NORETRY) +#endif + +/* + * File wide globals + */ + +STATIC kmem_cache_t *pagebuf_cache; +STATIC void pagebuf_daemon_wakeup(int); +STATIC void pagebuf_delwri_queue(page_buf_t *, int); +STATIC struct workqueue_struct *pagebuf_logio_workqueue; +STATIC struct workqueue_struct *pagebuf_dataio_workqueue; + +/* + * Pagebuf module configuration parameters, exported via + * /proc/sys/vm/pagebuf + */ + +typedef struct pb_sysctl_val { + int min; + int val; + int max; +} pb_sysctl_val_t; + +struct { + pb_sysctl_val_t flush_interval; /* interval between runs of the + * delwri flush daemon. */ + pb_sysctl_val_t age_buffer; /* time for buffer to age before + * we flush it. */ + pb_sysctl_val_t stats_clear; /* clear the pagebuf stats */ + pb_sysctl_val_t debug; /* debug tracing on or off */ +} pb_params = { + /* MIN DFLT MAX */ + .flush_interval = { HZ/2, HZ, 30*HZ }, + .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, + .stats_clear = { 0, 0, 1 }, + .debug = { 0, 0, 1 }, +}; + +enum { + PB_FLUSH_INT = 1, + PB_FLUSH_AGE = 2, + PB_STATS_CLEAR = 3, + PB_DEBUG = 4, +}; + +/* + * Pagebuf statistics variables + */ + +struct pbstats { + u_int32_t pb_get; + u_int32_t pb_create; + u_int32_t pb_get_locked; + u_int32_t pb_get_locked_waited; + u_int32_t pb_busy_locked; + u_int32_t pb_miss_locked; + u_int32_t pb_page_retries; + u_int32_t pb_page_found; + u_int32_t pb_get_read; +} pbstats; +DEFINE_PER_CPU(struct pbstats, pbstats); + +/* We don't disable preempt, not too worried about poking the + * wrong cpu's stat for now */ +#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++) + +/* + * Pagebuf debugging + */ + +#ifdef PAGEBUF_TRACE +void +pagebuf_trace( + page_buf_t *pb, + char *id, + void *data, + void *ra) +{ + if (!pb_params.debug.val) + return; + ktrace_enter(pagebuf_trace_buf, + pb, id, + (void *)(unsigned long)pb->pb_flags, + (void *)(unsigned long)pb->pb_hold.counter, + (void *)(unsigned long)pb->pb_sema.count.counter, + (void *)current, + data, ra, + (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff), + (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff), + (void *)(unsigned long)pb->pb_buffer_length, + NULL, NULL, NULL, NULL, NULL); +} +ktrace_t *pagebuf_trace_buf; +EXPORT_SYMBOL(pagebuf_trace_buf); +#define PAGEBUF_TRACE_SIZE 4096 +#define PB_TRACE(pb, id, data) \ + pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) +#else +#define PB_TRACE(pb, id, data) do { } while (0) +#endif + +#ifdef PAGEBUF_LOCK_TRACKING +# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid) +# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1) +# define PB_GET_OWNER(pb) ((pb)->pb_last_holder) +#else +# define PB_SET_OWNER(pb) do { } while (0) +# define PB_CLEAR_OWNER(pb) do { } while (0) +# define PB_GET_OWNER(pb) do { } while (0) +#endif + +/* + * Pagebuf allocation / freeing. + */ + +#define pb_to_gfp(flags) \ + (((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \ + ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) + +#define pagebuf_allocate(flags) \ + kmem_cache_alloc(pagebuf_cache, pb_to_gfp(flags)) +#define pagebuf_deallocate(pb) \ + kmem_cache_free(pagebuf_cache, (pb)); + +/* + * Pagebuf hashing + */ + +#define NBITS 8 +#define NHASH (1<pb_hash_index] + +STATIC int +_bhash( + struct block_device *bdev, + loff_t base) +{ + int bit, hval; + + base >>= 9; + base ^= (unsigned long)bdev / L1_CACHE_BYTES; + for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) { + hval ^= (int)base & (NHASH-1); + base >>= NBITS; + } + return hval; +} + +/* + * Mapping of multi-page buffers into contiguous virtual space + */ + +STATIC void *pagebuf_mapout_locked(page_buf_t *); + +typedef struct a_list { + void *vm_addr; + struct a_list *next; +} a_list_t; + +STATIC a_list_t *as_free_head; +STATIC int as_list_len; +STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED; + +/* + * Try to batch vunmaps because they are costly. + */ +STATIC void +free_address( + void *addr) +{ + a_list_t *aentry; + + aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC); + if (aentry) { + spin_lock(&as_lock); + aentry->next = as_free_head; + aentry->vm_addr = addr; + as_free_head = aentry; + as_list_len++; + spin_unlock(&as_lock); + } else { + vunmap(addr); + } +} + +STATIC void +purge_addresses(void) +{ + a_list_t *aentry, *old; + + if (as_free_head == NULL) + return; + + spin_lock(&as_lock); + aentry = as_free_head; + as_free_head = NULL; + as_list_len = 0; + spin_unlock(&as_lock); + + while ((old = aentry) != NULL) { + vunmap(aentry->vm_addr); + aentry = aentry->next; + kfree(old); + } +} + +/* + * Internal pagebuf object manipulation + */ + +STATIC void +_pagebuf_initialize( + page_buf_t *pb, + pb_target_t *target, + loff_t range_base, + size_t range_length, + page_buf_flags_t flags) +{ + /* + * We don't want certain flags to appear in pb->pb_flags. + */ + flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD); + + memset(pb, 0, sizeof(page_buf_t)); + atomic_set(&pb->pb_hold, 1); + init_MUTEX_LOCKED(&pb->pb_iodonesema); + INIT_LIST_HEAD(&pb->pb_list); + INIT_LIST_HEAD(&pb->pb_hash_list); + init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */ + PB_SET_OWNER(pb); + pb->pb_target = target; + pb->pb_file_offset = range_base; + /* + * Set buffer_length and count_desired to the same value initially. + * IO routines should use count_desired, which will be the same in + * most cases but may be reset (e.g. XFS recovery). + */ + pb->pb_buffer_length = pb->pb_count_desired = range_length; + pb->pb_flags = flags | PBF_NONE; + pb->pb_bn = PAGE_BUF_DADDR_NULL; + atomic_set(&pb->pb_pin_count, 0); + init_waitqueue_head(&pb->pb_waiters); + + PB_STATS_INC(pb_create); + PB_TRACE(pb, "initialize", target); +} + +/* + * Allocate a page array capable of holding a specified number + * of pages, and point the page buf at it. + */ +STATIC int +_pagebuf_get_pages( + page_buf_t *pb, + int page_count, + page_buf_flags_t flags) +{ + int gpf_mask = pb_to_gfp(flags); + + /* Make sure that we have a page list */ + if (pb->pb_pages == NULL) { + pb->pb_offset = page_buf_poff(pb->pb_file_offset); + pb->pb_page_count = page_count; + if (page_count <= PB_PAGES) { + pb->pb_pages = pb->pb_page_array; + } else { + pb->pb_pages = kmalloc(sizeof(struct page *) * + page_count, gpf_mask); + if (pb->pb_pages == NULL) + return -ENOMEM; + } + memset(pb->pb_pages, 0, sizeof(struct page *) * page_count); + } + return 0; +} + +/* + * Walk a pagebuf releasing all the pages contained within it. + */ +STATIC inline void +_pagebuf_freepages( + page_buf_t *pb) +{ + int buf_index; + + for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) { + struct page *page = pb->pb_pages[buf_index]; + + if (page) { + pb->pb_pages[buf_index] = NULL; + page_cache_release(page); + } + } +} + +/* + * _pagebuf_free_object + * + * _pagebuf_free_object releases the contents specified buffer. + * The modification state of any associated pages is left unchanged. + */ +void +_pagebuf_free_object( + pb_hash_t *hash, /* hash bucket for buffer */ + page_buf_t *pb) /* buffer to deallocate */ +{ + page_buf_flags_t pb_flags = pb->pb_flags; + + PB_TRACE(pb, "free_object", 0); + pb->pb_flags |= PBF_FREED; + + if (hash) { + if (!list_empty(&pb->pb_hash_list)) { + hash->pb_count--; + list_del_init(&pb->pb_hash_list); + } + spin_unlock(&hash->pb_hash_lock); + } + + if (!(pb_flags & PBF_FREED)) { + /* release any virtual mapping */ ; + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { + void *vaddr = pagebuf_mapout_locked(pb); + if (vaddr) { + free_address(vaddr); + } + } + + if (pb->pb_flags & _PBF_MEM_ALLOCATED) { + if (pb->pb_pages) { + /* release the pages in the address list */ + if ((pb->pb_pages[0]) && + (pb->pb_flags & _PBF_MEM_SLAB)) { + kfree(pb->pb_addr); + } else { + _pagebuf_freepages(pb); + } + if (pb->pb_pages != pb->pb_page_array) + kfree(pb->pb_pages); + pb->pb_pages = NULL; + } + pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); + } + } + + pagebuf_deallocate(pb); +} + +/* + * _pagebuf_lookup_pages + * + * _pagebuf_lookup_pages finds all pages which match the buffer + * in question and the range of file offsets supplied, + * and builds the page list for the buffer, if the + * page list is not already formed or if not all of the pages are + * already in the list. Invalid pages (pages which have not yet been + * read in from disk) are assigned for any pages which are not found. + */ +STATIC int +_pagebuf_lookup_pages( + page_buf_t *pb, + struct address_space *aspace, + page_buf_flags_t flags) +{ + loff_t next_buffer_offset; + unsigned long page_count, pi, index; + struct page *page; + int gfp_mask, retry_count = 5, rval = 0; + int all_mapped, good_pages, nbytes; + unsigned int blocksize, sectorshift; + size_t size, offset; + + + /* For pagebufs where we want to map an address, do not use + * highmem pages - so that we do not need to use kmap resources + * to access the data. + * + * For pages where the caller has indicated there may be resource + * contention (e.g. called from a transaction) do not flush + * delalloc pages to obtain memory. + */ + + if (flags & PBF_READ_AHEAD) { + gfp_mask = GFP_READAHEAD; + retry_count = 0; + } else if (flags & PBF_DONT_BLOCK) { + gfp_mask = GFP_NOFS; + } else if (flags & PBF_MAPPABLE) { + gfp_mask = GFP_KERNEL; + } else { + gfp_mask = GFP_HIGHUSER; + } + + next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length; + + good_pages = page_count = (page_buf_btoc(next_buffer_offset) - + page_buf_btoct(pb->pb_file_offset)); + + if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) { + /* Bring pages forward in cache */ + for (pi = 0; pi < page_count; pi++) { + mark_page_accessed(pb->pb_pages[pi]); + } + if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) { + all_mapped = 1; + goto mapit; + } + return 0; + } + + /* Ensure pb_pages field has been initialised */ + rval = _pagebuf_get_pages(pb, page_count, flags); + if (rval) + return rval; + + rval = pi = 0; + blocksize = pb->pb_target->pbr_bsize; + sectorshift = pb->pb_target->pbr_sshift; + size = pb->pb_count_desired; + offset = pb->pb_offset; + + /* Enter the pages in the page list */ + index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT; + for (all_mapped = 1; pi < page_count; pi++, index++) { + if (pb->pb_pages[pi] == 0) { + retry: + page = find_or_create_page(aspace, index, gfp_mask); + if (!page) { + if (--retry_count > 0) { + PB_STATS_INC(pb_page_retries); + pagebuf_daemon_wakeup(1); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(10); + goto retry; + } + rval = -ENOMEM; + all_mapped = 0; + continue; + } + PB_STATS_INC(pb_page_found); + mark_page_accessed(page); + pb->pb_pages[pi] = page; + } else { + page = pb->pb_pages[pi]; + lock_page(page); + } + + nbytes = PAGE_CACHE_SIZE - offset; + if (nbytes > size) + nbytes = size; + size -= nbytes; + + if (!PageUptodate(page)) { + if (blocksize == PAGE_CACHE_SIZE) { + if (flags & PBF_READ) + pb->pb_locked = 1; + good_pages--; + } else if (!PagePrivate(page)) { + unsigned long i, range; + + /* + * In this case page->private holds a bitmap + * of uptodate sectors within the page + */ + ASSERT(blocksize < PAGE_CACHE_SIZE); + range = (offset + nbytes) >> sectorshift; + for (i = offset >> sectorshift; i < range; i++) + if (!test_bit(i, &page->private)) + break; + if (i != range) + good_pages--; + } else { + good_pages--; + } + } + offset = 0; + } + + if (!pb->pb_locked) { + for (pi = 0; pi < page_count; pi++) { + if (pb->pb_pages[pi]) + unlock_page(pb->pb_pages[pi]); + } + } + +mapit: + pb->pb_flags |= _PBF_MEM_ALLOCATED; + if (all_mapped) { + pb->pb_flags |= _PBF_ALL_PAGES_MAPPED; + + /* A single page buffer is always mappable */ + if (page_count == 1) { + pb->pb_addr = (caddr_t) + page_address(pb->pb_pages[0]) + pb->pb_offset; + pb->pb_flags |= PBF_MAPPED; + } else if (flags & PBF_MAPPED) { + if (as_list_len > 64) + purge_addresses(); + pb->pb_addr = vmap(pb->pb_pages, page_count, + VM_MAP, PAGE_KERNEL); + if (pb->pb_addr == NULL) + return -ENOMEM; + pb->pb_addr += pb->pb_offset; + pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED; + } + } + /* If some pages were found with data in them + * we are not in PBF_NONE state. + */ + if (good_pages != 0) { + pb->pb_flags &= ~(PBF_NONE); + if (good_pages != page_count) { + pb->pb_flags |= PBF_PARTIAL; + } + } + + PB_TRACE(pb, "lookup_pages", (long)good_pages); + + return rval; +} + +/* + * Finding and Reading Buffers + */ + +/* + * _pagebuf_find + * + * Looks up, and creates if absent, a lockable buffer for + * a given range of an inode. The buffer is returned + * locked. If other overlapping buffers exist, they are + * released before the new buffer is created and locked, + * which may imply that this call will block until those buffers + * are unlocked. No I/O is implied by this call. + */ +STATIC page_buf_t * +_pagebuf_find( /* find buffer for block */ + pb_target_t *target,/* target for block */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags, /* PBF_TRYLOCK */ + page_buf_t *new_pb)/* newly allocated buffer */ +{ + loff_t range_base; + size_t range_length; + int hval; + pb_hash_t *h; + struct list_head *p; + page_buf_t *pb; + int not_locked; + + range_base = (ioff << BBSHIFT); + range_length = (isize << BBSHIFT); + + /* Ensure we never do IOs smaller than the sector size */ + BUG_ON(range_length < (1 << target->pbr_sshift)); + + /* Ensure we never do IOs that are not sector aligned */ + BUG_ON(range_base & (loff_t)target->pbr_smask); + + hval = _bhash(target->pbr_bdev, range_base); + h = &pbhash[hval]; + + spin_lock(&h->pb_hash_lock); + list_for_each(p, &h->pb_hash) { + pb = list_entry(p, page_buf_t, pb_hash_list); + + if ((target == pb->pb_target) && + (pb->pb_file_offset == range_base) && + (pb->pb_buffer_length == range_length)) { + if (pb->pb_flags & PBF_FREED) + break; + /* If we look at something bring it to the + * front of the list for next time + */ + list_del(&pb->pb_hash_list); + list_add(&pb->pb_hash_list, &h->pb_hash); + goto found; + } + } + + /* No match found */ + if (new_pb) { + _pagebuf_initialize(new_pb, target, range_base, + range_length, flags | _PBF_LOCKABLE); + new_pb->pb_hash_index = hval; + h->pb_count++; + list_add(&new_pb->pb_hash_list, &h->pb_hash); + } else { + PB_STATS_INC(pb_miss_locked); + } + + spin_unlock(&h->pb_hash_lock); + return (new_pb); + +found: + atomic_inc(&pb->pb_hold); + spin_unlock(&h->pb_hash_lock); + + /* Attempt to get the semaphore without sleeping, + * if this does not work then we need to drop the + * spinlock and do a hard attempt on the semaphore. + */ + not_locked = down_trylock(&pb->pb_sema); + if (not_locked) { + if (!(flags & PBF_TRYLOCK)) { + /* wait for buffer ownership */ + PB_TRACE(pb, "get_lock", 0); + pagebuf_lock(pb); + PB_STATS_INC(pb_get_locked_waited); + } else { + /* We asked for a trylock and failed, no need + * to look at file offset and length here, we + * know that this pagebuf at least overlaps our + * pagebuf and is locked, therefore our buffer + * either does not exist, or is this buffer + */ + + pagebuf_rele(pb); + PB_STATS_INC(pb_busy_locked); + return (NULL); + } + } else { + /* trylock worked */ + PB_SET_OWNER(pb); + } + + if (pb->pb_flags & PBF_STALE) + pb->pb_flags &= PBF_MAPPABLE | \ + PBF_MAPPED | \ + _PBF_LOCKABLE | \ + _PBF_ALL_PAGES_MAPPED | \ + _PBF_ADDR_ALLOCATED | \ + _PBF_MEM_ALLOCATED | \ + _PBF_MEM_SLAB; + PB_TRACE(pb, "got_lock", 0); + PB_STATS_INC(pb_get_locked); + return (pb); +} + + +/* + * pagebuf_find + * + * pagebuf_find returns a buffer matching the specified range of + * data for the specified target, if any of the relevant blocks + * are in memory. The buffer may have unallocated holes, if + * some, but not all, of the blocks are in memory. Even where + * pages are present in the buffer, not all of every page may be + * valid. + */ +page_buf_t * +pagebuf_find( /* find buffer for block */ + /* if the block is in memory */ + pb_target_t *target,/* target for block */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags) /* PBF_TRYLOCK */ +{ + return _pagebuf_find(target, ioff, isize, flags, NULL); +} + +/* + * pagebuf_get + * + * pagebuf_get assembles a buffer covering the specified range. + * Some or all of the blocks in the range may be valid. Storage + * in memory for all portions of the buffer will be allocated, + * although backing storage may not be. If PBF_READ is set in + * flags, pagebuf_iostart is called also. + */ +page_buf_t * +pagebuf_get( /* allocate a buffer */ + pb_target_t *target,/* target for buffer */ + loff_t ioff, /* starting offset of range */ + size_t isize, /* length of range */ + page_buf_flags_t flags) /* PBF_TRYLOCK */ +{ + page_buf_t *pb, *new_pb; + int error; + + new_pb = pagebuf_allocate(flags); + if (unlikely(!new_pb)) + return (NULL); + + pb = _pagebuf_find(target, ioff, isize, flags, new_pb); + if (pb != new_pb) { + pagebuf_deallocate(new_pb); + if (unlikely(!pb)) + return (NULL); + } + + PB_STATS_INC(pb_get); + + /* fill in any missing pages */ + error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags); + if (unlikely(error)) { + pagebuf_free(pb); + return (NULL); + } + + /* + * Always fill in the block number now, the mapped cases can do + * their own overlay of this later. + */ + pb->pb_bn = ioff; + pb->pb_count_desired = pb->pb_buffer_length; + + if (flags & PBF_READ) { + if (PBF_NOT_DONE(pb)) { + PB_TRACE(pb, "get_read", (unsigned long)flags); + PB_STATS_INC(pb_get_read); + pagebuf_iostart(pb, flags); + } else if (flags & PBF_ASYNC) { + PB_TRACE(pb, "get_read_async", (unsigned long)flags); + /* + * Read ahead call which is already satisfied, + * drop the buffer + */ + if (flags & (PBF_LOCK | PBF_TRYLOCK)) + pagebuf_unlock(pb); + pagebuf_rele(pb); + return NULL; + } else { + PB_TRACE(pb, "get_read_done", (unsigned long)flags); + /* We do not want read in the flags */ + pb->pb_flags &= ~PBF_READ; + } + } else { + PB_TRACE(pb, "get_write", (unsigned long)flags); + } + return (pb); +} + +/* + * Create a skeletal pagebuf (no pages associated with it). + */ +page_buf_t * +pagebuf_lookup( + struct pb_target *target, + loff_t ioff, + size_t isize, + page_buf_flags_t flags) +{ + page_buf_t *pb; + + pb = pagebuf_allocate(flags); + if (pb) { + _pagebuf_initialize(pb, target, ioff, isize, flags); + } + return pb; +} + +/* + * If we are not low on memory then do the readahead in a deadlock + * safe manner. + */ +void +pagebuf_readahead( + pb_target_t *target, + loff_t ioff, + size_t isize, + page_buf_flags_t flags) +{ + struct backing_dev_info *bdi; + + bdi = target->pbr_mapping->backing_dev_info; + if (bdi_read_congested(bdi)) + return; + if (bdi_write_congested(bdi)) + return; + + flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD); + pagebuf_get(target, ioff, isize, flags); +} + +page_buf_t * +pagebuf_get_empty( + size_t len, + pb_target_t *target) +{ + page_buf_t *pb; + + pb = pagebuf_allocate(_PBF_LOCKABLE); + if (pb) + _pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE); + return pb; +} + +static inline struct page * +mem_to_page( + void *addr) +{ + if (((unsigned long)addr < VMALLOC_START) || + ((unsigned long)addr >= VMALLOC_END)) { + return virt_to_page(addr); + } else { + return vmalloc_to_page(addr); + } +} + +int +pagebuf_associate_memory( + page_buf_t *pb, + void *mem, + size_t len) +{ + int rval; + int i = 0; + size_t ptr; + size_t end, end_cur; + off_t offset; + int page_count; + + page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; + offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); + if (offset && (len > PAGE_CACHE_SIZE)) + page_count++; + + /* Free any previous set of page pointers */ + if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) { + kfree(pb->pb_pages); + } + pb->pb_pages = NULL; + pb->pb_addr = mem; + + rval = _pagebuf_get_pages(pb, page_count, 0); + if (rval) + return rval; + + pb->pb_offset = offset; + ptr = (size_t) mem & PAGE_CACHE_MASK; + end = PAGE_CACHE_ALIGN((size_t) mem + len); + end_cur = end; + /* set up first page */ + pb->pb_pages[0] = mem_to_page(mem); + + ptr += PAGE_CACHE_SIZE; + pb->pb_page_count = ++i; + while (ptr < end) { + pb->pb_pages[i] = mem_to_page((void *)ptr); + pb->pb_page_count = ++i; + ptr += PAGE_CACHE_SIZE; + } + pb->pb_locked = 0; + + pb->pb_count_desired = pb->pb_buffer_length = len; + pb->pb_flags |= PBF_MAPPED; + + return 0; +} + +page_buf_t * +pagebuf_get_no_daddr( + size_t len, + pb_target_t *target) +{ + int rval; + void *rmem = NULL; + page_buf_flags_t flags = _PBF_LOCKABLE | PBF_FORCEIO; + page_buf_t *pb; + size_t tlen = 0; + + if (unlikely(len > 0x20000)) + return NULL; + + pb = pagebuf_allocate(flags); + if (!pb) + return NULL; + + _pagebuf_initialize(pb, target, 0, len, flags); + + do { + if (tlen == 0) { + tlen = len; /* first time */ + } else { + kfree(rmem); /* free the mem from the previous try */ + tlen <<= 1; /* double the size and try again */ + } + if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) { + pagebuf_free(pb); + return NULL; + } + } while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask)); + + if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) { + kfree(rmem); + pagebuf_free(pb); + return NULL; + } + /* otherwise pagebuf_free just ignores it */ + pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB); + PB_CLEAR_OWNER(pb); + up(&pb->pb_sema); /* Return unlocked pagebuf */ + + PB_TRACE(pb, "no_daddr", rmem); + + return pb; +} + + +/* + * pagebuf_hold + * + * Increment reference count on buffer, to hold the buffer concurrently + * with another thread which may release (free) the buffer asynchronously. + * + * Must hold the buffer already to call this function. + */ +void +pagebuf_hold( + page_buf_t *pb) +{ + atomic_inc(&pb->pb_hold); + PB_TRACE(pb, "hold", 0); +} + +/* + * pagebuf_free + * + * pagebuf_free releases the specified buffer. The modification + * state of any associated pages is left unchanged. + */ +void +pagebuf_free( + page_buf_t *pb) +{ + if (pb->pb_flags & _PBF_LOCKABLE) { + pb_hash_t *h = pb_hash(pb); + + spin_lock(&h->pb_hash_lock); + _pagebuf_free_object(h, pb); + } else { + _pagebuf_free_object(NULL, pb); + } +} + +/* + * pagebuf_rele + * + * pagebuf_rele releases a hold on the specified buffer. If the + * the hold count is 1, pagebuf_rele calls pagebuf_free. + */ +void +pagebuf_rele( + page_buf_t *pb) +{ + pb_hash_t *h; + + PB_TRACE(pb, "rele", pb->pb_relse); + if (pb->pb_flags & _PBF_LOCKABLE) { + h = pb_hash(pb); + spin_lock(&h->pb_hash_lock); + } else { + h = NULL; + } + + if (atomic_dec_and_test(&pb->pb_hold)) { + int do_free = 1; + + if (pb->pb_relse) { + atomic_inc(&pb->pb_hold); + if (h) + spin_unlock(&h->pb_hash_lock); + (*(pb->pb_relse)) (pb); + do_free = 0; + } + if (pb->pb_flags & PBF_DELWRI) { + pb->pb_flags |= PBF_ASYNC; + atomic_inc(&pb->pb_hold); + if (h && do_free) + spin_unlock(&h->pb_hash_lock); + pagebuf_delwri_queue(pb, 0); + do_free = 0; + } else if (pb->pb_flags & PBF_FS_MANAGED) { + if (h) + spin_unlock(&h->pb_hash_lock); + do_free = 0; + } + + if (do_free) { + _pagebuf_free_object(h, pb); + } + } else if (h) { + spin_unlock(&h->pb_hash_lock); + } +} + + +/* + * Mutual exclusion on buffers. Locking model: + * + * Buffers associated with inodes for which buffer locking + * is not enabled are not protected by semaphores, and are + * assumed to be exclusively owned by the caller. There is a + * spinlock in the buffer, used by the caller when concurrent + * access is possible. + */ + +/* + * pagebuf_cond_lock + * + * pagebuf_cond_lock locks a buffer object, if it is not already locked. + * Note that this in no way + * locks the underlying pages, so it is only useful for synchronizing + * concurrent use of page buffer objects, not for synchronizing independent + * access to the underlying pages. + */ +int +pagebuf_cond_lock( /* lock buffer, if not locked */ + /* returns -EBUSY if locked) */ + page_buf_t *pb) +{ + int locked; + + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + locked = down_trylock(&pb->pb_sema) == 0; + if (locked) { + PB_SET_OWNER(pb); + } + PB_TRACE(pb, "cond_lock", (long)locked); + return(locked ? 0 : -EBUSY); +} + +/* + * pagebuf_lock_value + * + * Return lock value for a pagebuf + */ +int +pagebuf_lock_value( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + return(atomic_read(&pb->pb_sema.count)); +} + +/* + * pagebuf_lock + * + * pagebuf_lock locks a buffer object. Note that this in no way + * locks the underlying pages, so it is only useful for synchronizing + * concurrent use of page buffer objects, not for synchronizing independent + * access to the underlying pages. + */ +int +pagebuf_lock( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + + PB_TRACE(pb, "lock", 0); + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + down(&pb->pb_sema); + PB_SET_OWNER(pb); + PB_TRACE(pb, "locked", 0); + return 0; +} + +/* + * pagebuf_unlock + * + * pagebuf_unlock releases the lock on the buffer object created by + * pagebuf_lock or pagebuf_cond_lock (not any + * pinning of underlying pages created by pagebuf_pin). + */ +void +pagebuf_unlock( /* unlock buffer */ + page_buf_t *pb) /* buffer to unlock */ +{ + ASSERT(pb->pb_flags & _PBF_LOCKABLE); + PB_CLEAR_OWNER(pb); + up(&pb->pb_sema); + PB_TRACE(pb, "unlock", 0); +} + + +/* + * Pinning Buffer Storage in Memory + */ + +/* + * pagebuf_pin + * + * pagebuf_pin locks all of the memory represented by a buffer in + * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for + * the same or different buffers affecting a given page, will + * properly count the number of outstanding "pin" requests. The + * buffer may be released after the pagebuf_pin and a different + * buffer used when calling pagebuf_unpin, if desired. + * pagebuf_pin should be used by the file system when it wants be + * assured that no attempt will be made to force the affected + * memory to disk. It does not assure that a given logical page + * will not be moved to a different physical page. + */ +void +pagebuf_pin( + page_buf_t *pb) +{ + atomic_inc(&pb->pb_pin_count); + PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter); +} + +/* + * pagebuf_unpin + * + * pagebuf_unpin reverses the locking of memory performed by + * pagebuf_pin. Note that both functions affected the logical + * pages associated with the buffer, not the buffer itself. + */ +void +pagebuf_unpin( + page_buf_t *pb) +{ + if (atomic_dec_and_test(&pb->pb_pin_count)) { + wake_up_all(&pb->pb_waiters); + } + PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter); +} + +int +pagebuf_ispin( + page_buf_t *pb) +{ + return atomic_read(&pb->pb_pin_count); +} + +/* + * pagebuf_wait_unpin + * + * pagebuf_wait_unpin waits until all of the memory associated + * with the buffer is not longer locked in memory. It returns + * immediately if none of the affected pages are locked. + */ +static inline void +_pagebuf_wait_unpin( + page_buf_t *pb) +{ + DECLARE_WAITQUEUE (wait, current); + + if (atomic_read(&pb->pb_pin_count) == 0) + return; + + add_wait_queue(&pb->pb_waiters, &wait); + for (;;) { + current->state = TASK_UNINTERRUPTIBLE; + if (atomic_read(&pb->pb_pin_count) == 0) + break; + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + schedule(); + } + remove_wait_queue(&pb->pb_waiters, &wait); + current->state = TASK_RUNNING; +} + +/* + * Buffer Utility Routines + */ + +/* + * pagebuf_iodone + * + * pagebuf_iodone marks a buffer for which I/O is in progress + * done with respect to that I/O. The pb_iodone routine, if + * present, will be called as a side-effect. + */ +void +pagebuf_iodone_work( + void *v) +{ + page_buf_t *pb = (page_buf_t *)v; + + if (pb->pb_iodone) { + (*(pb->pb_iodone)) (pb); + return; + } + + if (pb->pb_flags & PBF_ASYNC) { + if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse) + pagebuf_unlock(pb); + pagebuf_rele(pb); + } +} + +void +pagebuf_iodone( + page_buf_t *pb, + int dataio, + int schedule) +{ + pb->pb_flags &= ~(PBF_READ | PBF_WRITE); + if (pb->pb_error == 0) { + pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE); + } + + PB_TRACE(pb, "iodone", pb->pb_iodone); + + if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { + if (schedule) { + INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); + queue_work(dataio ? pagebuf_dataio_workqueue : + pagebuf_logio_workqueue, &pb->pb_iodone_work); + } else { + pagebuf_iodone_work(pb); + } + } else { + up(&pb->pb_iodonesema); + } +} + +/* + * pagebuf_ioerror + * + * pagebuf_ioerror sets the error code for a buffer. + */ +void +pagebuf_ioerror( /* mark/clear buffer error flag */ + page_buf_t *pb, /* buffer to mark */ + unsigned int error) /* error to store (0 if none) */ +{ + pb->pb_error = error; + PB_TRACE(pb, "ioerror", (unsigned long)error); +} + +/* + * pagebuf_iostart + * + * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. + * If necessary, it will arrange for any disk space allocation required, + * and it will break up the request if the block mappings require it. + * The pb_iodone routine in the buffer supplied will only be called + * when all of the subsidiary I/O requests, if any, have been completed. + * pagebuf_iostart calls the pagebuf_ioinitiate routine or + * pagebuf_iorequest, if the former routine is not defined, to start + * the I/O on a given low-level request. + */ +int +pagebuf_iostart( /* start I/O on a buffer */ + page_buf_t *pb, /* buffer to start */ + page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ + /* PBF_WRITE, PBF_DELWRI, */ + /* PBF_SYNC, PBF_DONT_BLOCK */ +{ + int status = 0; + + PB_TRACE(pb, "iostart", (unsigned long)flags); + + if (flags & PBF_DELWRI) { + pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); + pb->pb_flags |= flags & + (PBF_DELWRI | PBF_ASYNC | PBF_SYNC); + pagebuf_delwri_queue(pb, 1); + return status; + } + + pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \ + PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES); + pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ + PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES); + + BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL); + + /* For writes allow an alternate strategy routine to precede + * the actual I/O request (which may not be issued at all in + * a shutdown situation, for example). + */ + status = (flags & PBF_WRITE) ? + pagebuf_iostrategy(pb) : pagebuf_iorequest(pb); + + /* Wait for I/O if we are not an async request. + * Note: async I/O request completion will release the buffer, + * and that can already be done by this point. So using the + * buffer pointer from here on, after async I/O, is invalid. + */ + if (!status && !(flags & PBF_ASYNC)) + status = pagebuf_iowait(pb); + + return status; +} + +/* + * Helper routine for pagebuf_iorequest + */ + +STATIC __inline__ int +_pagebuf_iolocked( + page_buf_t *pb) +{ + ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE)); + if (pb->pb_flags & PBF_READ) + return pb->pb_locked; + return ((pb->pb_flags & _PBF_LOCKABLE) == 0); +} + +STATIC __inline__ void +_pagebuf_iodone( + page_buf_t *pb, + int schedule) +{ + if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { + pb->pb_locked = 0; + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule); + } +} + +STATIC int +bio_end_io_pagebuf( + struct bio *bio, + unsigned int bytes_done, + int error) +{ + page_buf_t *pb = (page_buf_t *)bio->bi_private; + unsigned int i, blocksize = pb->pb_target->pbr_bsize; + unsigned int sectorshift = pb->pb_target->pbr_sshift; + struct bio_vec *bvec = bio->bi_io_vec; + + if (bio->bi_size) + return 1; + + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) + pb->pb_error = EIO; + + for (i = 0; i < bio->bi_vcnt; i++, bvec++) { + struct page *page = bvec->bv_page; + + if (pb->pb_error) { + SetPageError(page); + } else if (blocksize == PAGE_CACHE_SIZE) { + SetPageUptodate(page); + } else if (!PagePrivate(page)) { + unsigned int j, range; + + ASSERT(blocksize < PAGE_CACHE_SIZE); + range = (bvec->bv_offset + bvec->bv_len) >> sectorshift; + for (j = bvec->bv_offset >> sectorshift; j < range; j++) + set_bit(j, &page->private); + if (page->private == (unsigned long)(PAGE_CACHE_SIZE-1)) + SetPageUptodate(page); + } + + if (_pagebuf_iolocked(pb)) { + unlock_page(page); + } + } + + _pagebuf_iodone(pb, 1); + bio_put(bio); + return 0; +} + +void +_pagebuf_ioapply( + page_buf_t *pb) +{ + int i, map_i, total_nr_pages, nr_pages; + struct bio *bio; + int offset = pb->pb_offset; + int size = pb->pb_count_desired; + sector_t sector = pb->pb_bn; + unsigned int blocksize = pb->pb_target->pbr_bsize; + int locking = _pagebuf_iolocked(pb); + + total_nr_pages = pb->pb_page_count; + map_i = 0; + + /* Special code path for reading a sub page size pagebuf in -- + * we populate up the whole page, and hence the other metadata + * in the same page. This optimization is only valid when the + * filesystem block size and the page size are equal. + */ + if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) && + (pb->pb_flags & PBF_READ) && locking && + (blocksize == PAGE_CACHE_SIZE)) { + bio = bio_alloc(GFP_NOIO, 1); + + bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_sector = sector - (offset >> BBSHIFT); + bio->bi_end_io = bio_end_io_pagebuf; + bio->bi_private = pb; + + bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0); + size = 0; + + atomic_inc(&pb->pb_io_remaining); + + goto submit_io; + } + + /* Lock down the pages which we need to for the request */ + if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) { + for (i = 0; size; i++) { + int nbytes = PAGE_CACHE_SIZE - offset; + struct page *page = pb->pb_pages[i]; + + if (nbytes > size) + nbytes = size; + + lock_page(page); + + size -= nbytes; + offset = 0; + } + offset = pb->pb_offset; + size = pb->pb_count_desired; + } + +next_chunk: + atomic_inc(&pb->pb_io_remaining); + nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); + if (nr_pages > total_nr_pages) + nr_pages = total_nr_pages; + + bio = bio_alloc(GFP_NOIO, nr_pages); + bio->bi_bdev = pb->pb_target->pbr_bdev; + bio->bi_sector = sector; + bio->bi_end_io = bio_end_io_pagebuf; + bio->bi_private = pb; + + for (; size && nr_pages; nr_pages--, map_i++) { + int nbytes = PAGE_CACHE_SIZE - offset; + + if (nbytes > size) + nbytes = size; + + if (bio_add_page(bio, pb->pb_pages[map_i], + nbytes, offset) < nbytes) + break; + + offset = 0; + sector += nbytes >> BBSHIFT; + size -= nbytes; + total_nr_pages--; + } + +submit_io: + if (likely(bio->bi_size)) { + submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio); + if (size) + goto next_chunk; + } else { + bio_put(bio); + pagebuf_ioerror(pb, EIO); + } + + if (pb->pb_flags & PBF_RUN_QUEUES) { + pb->pb_flags &= ~PBF_RUN_QUEUES; + if (atomic_read(&pb->pb_io_remaining) > 1) + blk_run_queues(); + } +} + +/* + * pagebuf_iorequest + * + * pagebuf_iorequest is the core I/O request routine. + * It assumes that the buffer is well-formed and + * mapped and ready for physical I/O, unlike + * pagebuf_iostart() and pagebuf_iophysio(). Those + * routines call the pagebuf_ioinitiate routine to start I/O, + * if it is present, or else call pagebuf_iorequest() + * directly if the pagebuf_ioinitiate routine is not present. + * + * This function will be responsible for ensuring access to the + * pages is restricted whilst I/O is in progress - for locking + * pagebufs the pagebuf lock is the mediator, for non-locking + * pagebufs the pages will be locked. In the locking case we + * need to use the pagebuf lock as multiple meta-data buffers + * will reference the same page. + */ +int +pagebuf_iorequest( /* start real I/O */ + page_buf_t *pb) /* buffer to convey to device */ +{ + PB_TRACE(pb, "iorequest", 0); + + if (pb->pb_flags & PBF_DELWRI) { + pagebuf_delwri_queue(pb, 1); + return 0; + } + + if (pb->pb_flags & PBF_WRITE) { + _pagebuf_wait_unpin(pb); + } + + pagebuf_hold(pb); + + /* Set the count to 1 initially, this will stop an I/O + * completion callout which happens before we have started + * all the I/O from calling pagebuf_iodone too early. + */ + atomic_set(&pb->pb_io_remaining, 1); + _pagebuf_ioapply(pb); + _pagebuf_iodone(pb, 0); + + pagebuf_rele(pb); + return 0; +} + +/* + * pagebuf_iowait + * + * pagebuf_iowait waits for I/O to complete on the buffer supplied. + * It returns immediately if no I/O is pending. In any case, it returns + * the error code, if any, or 0 if there is no error. + */ +int +pagebuf_iowait( + page_buf_t *pb) +{ + PB_TRACE(pb, "iowait", 0); + if (atomic_read(&pb->pb_io_remaining)) + blk_run_queues(); + down(&pb->pb_iodonesema); + PB_TRACE(pb, "iowaited", (long)pb->pb_error); + return pb->pb_error; +} + +STATIC void * +pagebuf_mapout_locked( + page_buf_t *pb) +{ + void *old_addr = NULL; + + if (pb->pb_flags & PBF_MAPPED) { + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) + old_addr = pb->pb_addr - pb->pb_offset; + pb->pb_addr = NULL; + pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED); + } + + return old_addr; /* Caller must free the address space, + * we are under a spin lock, probably + * not safe to do vfree here + */ +} + +caddr_t +pagebuf_offset( + page_buf_t *pb, + size_t offset) +{ + struct page *page; + + offset += pb->pb_offset; + + page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT]; + return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1)); +} + +/* + * pagebuf_iomove + * + * Move data into or out of a buffer. + */ +void +pagebuf_iomove( + page_buf_t *pb, /* buffer to process */ + size_t boff, /* starting buffer offset */ + size_t bsize, /* length to copy */ + caddr_t data, /* data address */ + page_buf_rw_t mode) /* read/write flag */ +{ + size_t bend, cpoff, csize; + struct page *page; + + bend = boff + bsize; + while (boff < bend) { + page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)]; + cpoff = page_buf_poff(boff + pb->pb_offset); + csize = min_t(size_t, + PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff); + + ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); + + switch (mode) { + case PBRW_ZERO: + memset(page_address(page) + cpoff, 0, csize); + break; + case PBRW_READ: + memcpy(data, page_address(page) + cpoff, csize); + break; + case PBRW_WRITE: + memcpy(page_address(page) + cpoff, data, csize); + } + + boff += csize; + data += csize; + } +} + + +/* + * Pagebuf delayed write buffer handling + */ + +STATIC int pbd_active = 1; +STATIC LIST_HEAD(pbd_delwrite_queue); +STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; + +STATIC void +pagebuf_delwri_queue( + page_buf_t *pb, + int unlock) +{ + PB_TRACE(pb, "delwri_q", (long)unlock); + spin_lock(&pbd_delwrite_lock); + /* If already in the queue, dequeue and place at tail */ + if (!list_empty(&pb->pb_list)) { + if (unlock) { + atomic_dec(&pb->pb_hold); + } + list_del(&pb->pb_list); + } + + list_add_tail(&pb->pb_list, &pbd_delwrite_queue); + pb->pb_flushtime = jiffies + pb_params.age_buffer.val; + spin_unlock(&pbd_delwrite_lock); + + if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) { + pagebuf_unlock(pb); + } +} + +void +pagebuf_delwri_dequeue( + page_buf_t *pb) +{ + PB_TRACE(pb, "delwri_uq", 0); + spin_lock(&pbd_delwrite_lock); + list_del_init(&pb->pb_list); + pb->pb_flags &= ~PBF_DELWRI; + spin_unlock(&pbd_delwrite_lock); +} + +STATIC void +pagebuf_runall_queues( + struct workqueue_struct *queue) +{ + flush_workqueue(queue); +} + +/* Defines for pagebuf daemon */ +DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); +STATIC int force_flush; + +STATIC void +pagebuf_daemon_wakeup( + int flag) +{ + force_flush = flag; + if (waitqueue_active(&pbd_waitq)) { + wake_up_interruptible(&pbd_waitq); + } +} + +typedef void (*timeout_fn)(unsigned long); + +STATIC int +pagebuf_daemon( + void *data) +{ + int count; + page_buf_t *pb; + struct list_head *curr, *next, tmp; + struct timer_list pb_daemon_timer = + TIMER_INITIALIZER((timeout_fn)pagebuf_daemon_wakeup, 0, 0); + + /* Set up the thread */ + daemonize("pagebufd"); + + current->flags |= PF_MEMALLOC; + + INIT_LIST_HEAD(&tmp); + do { + /* swsusp */ + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); + + if (pbd_active == 1) { + mod_timer(&pb_daemon_timer, + jiffies + pb_params.flush_interval.val); + interruptible_sleep_on(&pbd_waitq); + } + + if (pbd_active == 0) { + del_timer_sync(&pb_daemon_timer); + } + + spin_lock(&pbd_delwrite_lock); + + count = 0; + list_for_each_safe(curr, next, &pbd_delwrite_queue) { + pb = list_entry(curr, page_buf_t, pb_list); + + PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); + + if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) && + (((pb->pb_flags & _PBF_LOCKABLE) == 0) || + !pagebuf_cond_lock(pb))) { + + if (!force_flush && + time_before(jiffies, pb->pb_flushtime)) { + pagebuf_unlock(pb); + break; + } + + pb->pb_flags &= ~PBF_DELWRI; + pb->pb_flags |= PBF_WRITE; + + list_del(&pb->pb_list); + list_add(&pb->pb_list, &tmp); + + count++; + } + } + + spin_unlock(&pbd_delwrite_lock); + while (!list_empty(&tmp)) { + pb = list_entry(tmp.next, page_buf_t, pb_list); + list_del_init(&pb->pb_list); + + pagebuf_iostrategy(pb); + } + + if (as_list_len > 0) + purge_addresses(); + if (count) + blk_run_queues(); + + force_flush = 0; + } while (pbd_active == 1); + + pbd_active = -1; + wake_up_interruptible(&pbd_waitq); + + return 0; +} + +void +pagebuf_delwri_flush( + pb_target_t *target, + u_long flags, + int *pinptr) +{ + page_buf_t *pb; + struct list_head *curr, *next, tmp; + int pincount = 0; + int flush_cnt = 0; + + pagebuf_runall_queues(pagebuf_dataio_workqueue); + pagebuf_runall_queues(pagebuf_logio_workqueue); + + spin_lock(&pbd_delwrite_lock); + INIT_LIST_HEAD(&tmp); + + list_for_each_safe(curr, next, &pbd_delwrite_queue) { + pb = list_entry(curr, page_buf_t, pb_list); + + /* + * Skip other targets, markers and in progress buffers + */ + + if ((pb->pb_flags == 0) || (pb->pb_target != target) || + !(pb->pb_flags & PBF_DELWRI)) { + continue; + } + + PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb)); + if (pagebuf_ispin(pb)) { + pincount++; + continue; + } + + pb->pb_flags &= ~PBF_DELWRI; + pb->pb_flags |= PBF_WRITE; + list_move(&pb->pb_list, &tmp); + } + /* ok found all the items that can be worked on + * drop the lock and process the private list */ + spin_unlock(&pbd_delwrite_lock); + + list_for_each_safe(curr, next, &tmp) { + pb = list_entry(curr, page_buf_t, pb_list); + + if (flags & PBDF_WAIT) + pb->pb_flags &= ~PBF_ASYNC; + else + list_del_init(curr); + + pagebuf_lock(pb); + pagebuf_iostrategy(pb); + if (++flush_cnt > 32) { + blk_run_queues(); + flush_cnt = 0; + } + } + + blk_run_queues(); + + while (!list_empty(&tmp)) { + pb = list_entry(tmp.next, page_buf_t, pb_list); + + list_del_init(&pb->pb_list); + pagebuf_iowait(pb); + if (!pb->pb_relse) + pagebuf_unlock(pb); + pagebuf_rele(pb); + } + + if (pinptr) + *pinptr = pincount; +} + +STATIC int +pagebuf_daemon_start(void) +{ + int rval; + + pagebuf_logio_workqueue = create_workqueue("xfslogd"); + if (!pagebuf_logio_workqueue) + return -ENOMEM; + + pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); + if (!pagebuf_dataio_workqueue) { + destroy_workqueue(pagebuf_logio_workqueue); + return -ENOMEM; + } + + rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); + if (rval < 0) { + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); + } + + return rval; +} + +/* + * pagebuf_daemon_stop + * + * Note: do not mark as __exit, it is called from pagebuf_terminate. + */ +STATIC void +pagebuf_daemon_stop(void) +{ + pbd_active = 0; + wake_up_interruptible(&pbd_waitq); + wait_event_interruptible(pbd_waitq, pbd_active); + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); +} + + +/* + * Pagebuf sysctl interface + */ + +STATIC int +pb_stats_clear_handler( + ctl_table *ctl, + int write, + struct file *filp, + void *buffer, + size_t *lenp) +{ + int c, ret; + int *valp = ctl->data; + + ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); + + if (!ret && write && *valp) { + printk("XFS Clearing pbstats\n"); + for (c = 0; c < NR_CPUS; c++) { + if (!cpu_possible(c)) continue; + memset(&per_cpu(pbstats, c), 0, + sizeof(struct pbstats)); + } + pb_params.stats_clear.val = 0; + } + + return ret; +} + +STATIC struct ctl_table_header *pagebuf_table_header; + +STATIC ctl_table pagebuf_table[] = { + {PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.flush_interval.min, &pb_params.flush_interval.max}, + + {PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.age_buffer.min, &pb_params.age_buffer.max}, + + {PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val, + sizeof(int), 0644, NULL, &pb_stats_clear_handler, + &sysctl_intvec, NULL, + &pb_params.stats_clear.min, &pb_params.stats_clear.max}, + +#ifdef PAGEBUF_TRACE + {PB_DEBUG, "debug", &pb_params.debug.val, + sizeof(int), 0644, NULL, &proc_dointvec_minmax, + &sysctl_intvec, NULL, + &pb_params.debug.min, &pb_params.debug.max}, +#endif + {0} +}; + +STATIC ctl_table pagebuf_dir_table[] = { + {VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table}, + {0} +}; + +STATIC ctl_table pagebuf_root_table[] = { + {CTL_VM, "vm", NULL, 0, 0555, pagebuf_dir_table}, + {0} +}; + +#ifdef CONFIG_PROC_FS +STATIC int +pagebuf_readstats( + char *buffer, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + int c, i, len, val; + + len = 0; + len += sprintf(buffer + len, "pagebuf"); + for (i = 0; i < sizeof(struct pbstats) / sizeof(u_int32_t); i++) { + val = 0; + for (c = 0 ; c < NR_CPUS; c++) { + if (!cpu_possible(c)) continue; + val += *(((u_int32_t*)&per_cpu(pbstats, c) + i)); + } + len += sprintf(buffer + len, " %u", val); + } + buffer[len++] = '\n'; + + if (offset >= len) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if ((len -= offset) > count) + return count; + *eof = 1; + + return len; +} +#endif /* CONFIG_PROC_FS */ + +/* + * Initialization and Termination + */ + +int __init +pagebuf_init(void) +{ + int i; + + pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1); + +#ifdef CONFIG_PROC_FS + if (proc_mkdir("fs/pagebuf", 0)) + create_proc_read_entry( + "fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL); +#endif + + pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (pagebuf_cache == NULL) { + printk("pagebuf: couldn't init pagebuf cache\n"); + pagebuf_terminate(); + return -ENOMEM; + } + + for (i = 0; i < NHASH; i++) { + spin_lock_init(&pbhash[i].pb_hash_lock); + INIT_LIST_HEAD(&pbhash[i].pb_hash); + } + +#ifdef PAGEBUF_TRACE + pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); +#endif + + pagebuf_daemon_start(); + return 0; +} + + +/* + * pagebuf_terminate. + * + * Note: do not mark as __exit, this is also called from the __init code. + */ +void +pagebuf_terminate(void) +{ + pagebuf_daemon_stop(); + + kmem_cache_destroy(pagebuf_cache); + + unregister_sysctl_table(pagebuf_table_header); +#ifdef CONFIG_PROC_FS + remove_proc_entry("fs/pagebuf/stat", NULL); + remove_proc_entry("fs/pagebuf", NULL); +#endif +} + + +/* + * Module management (for kernel debugger module) + */ +EXPORT_SYMBOL(pagebuf_offset); +#ifdef DEBUG +EXPORT_SYMBOL(pbd_delwrite_queue); +#endif diff --git a/fs/xfs/linux/xfs_buf.h b/fs/xfs/linux/xfs_buf.h new file mode 100644 index 000000000000..809a845cb0fe --- /dev/null +++ b/fs/xfs/linux/xfs_buf.h @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +/* + * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI + */ + +#ifndef __XFS_BUF_H__ +#define __XFS_BUF_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Base types + */ + +/* daddr must be signed since -1 is used for bmaps that are not yet allocated */ +typedef loff_t page_buf_daddr_t; + +#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL)) + +#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) +#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) +#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) +#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) + +typedef enum page_buf_rw_e { + PBRW_READ = 1, /* transfer into target memory */ + PBRW_WRITE = 2, /* transfer from target memory */ + PBRW_ZERO = 3 /* Zero target memory */ +} page_buf_rw_t; + + +typedef enum page_buf_flags_e { /* pb_flags values */ + PBF_READ = (1 << 0), /* buffer intended for reading from device */ + PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ + PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ + PBF_PARTIAL = (1 << 3), /* buffer partially read */ + PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ + PBF_NONE = (1 << 5), /* buffer not read at all */ + PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ + PBF_FREED = (1 << 7), /* buffer has been freed and is invalid */ + PBF_SYNC = (1 << 8), /* force updates to disk */ + PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ + PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ + PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ + PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ + + /* flags used only as arguments to access routines */ + PBF_LOCK = (1 << 13), /* lock requested */ + PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait */ + PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ + + /* flags used only internally */ + _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ + _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ + _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ + _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ + _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */ + _PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated */ + + PBF_FORCEIO = (1 << 22), /* ignore any cache state */ + PBF_FLUSH = (1 << 23), /* flush disk write cache */ + PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead */ + PBF_RUN_QUEUES = (1 << 25), /* run block device task queue */ + +} page_buf_flags_t; + +#define PBF_UPDATE (PBF_READ | PBF_WRITE) +#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0) +#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0) + +typedef struct pb_target { + dev_t pbr_dev; + struct block_device *pbr_bdev; + struct address_space *pbr_mapping; + unsigned int pbr_bsize; + unsigned int pbr_sshift; + size_t pbr_smask; +} pb_target_t; + +/* + * page_buf_t: Buffer structure for page cache-based buffers + * + * This buffer structure is used by the page cache buffer management routines + * to refer to an assembly of pages forming a logical buffer. The actual + * I/O is performed with buffer_head or bio structures, as required by drivers, + * for drivers which do not understand this structure. The buffer structure is + * used on temporary basis only, and discarded when released. + * + * The real data storage is recorded in the page cache. Metadata is + * hashed to the inode for the block device on which the file system resides. + * File data is hashed to the inode for the file. Pages which are only + * partially filled with data have bits set in their block_map entry + * to indicate which disk blocks in the page are not valid. + */ + +struct page_buf_s; +typedef void (*page_buf_iodone_t)(struct page_buf_s *); + /* call-back function on I/O completion */ +typedef void (*page_buf_relse_t)(struct page_buf_s *); + /* call-back function on I/O completion */ +typedef int (*page_buf_bdstrat_t)(struct page_buf_s *); + +#define PB_PAGES 4 + +typedef struct page_buf_s { + struct semaphore pb_sema; /* semaphore for lockables */ + unsigned long pb_flushtime; /* time to flush pagebuf */ + atomic_t pb_pin_count; /* pin count */ + wait_queue_head_t pb_waiters; /* unpin waiters */ + struct list_head pb_list; + page_buf_flags_t pb_flags; /* status flags */ + struct list_head pb_hash_list; + struct pb_target *pb_target; /* logical object */ + atomic_t pb_hold; /* reference count */ + page_buf_daddr_t pb_bn; /* block number for I/O */ + loff_t pb_file_offset; /* offset in file */ + size_t pb_buffer_length; /* size of buffer in bytes */ + size_t pb_count_desired; /* desired transfer size */ + void *pb_addr; /* virtual address of buffer */ + struct work_struct pb_iodone_work; + atomic_t pb_io_remaining;/* #outstanding I/O requests */ + page_buf_iodone_t pb_iodone; /* I/O completion function */ + page_buf_relse_t pb_relse; /* releasing function */ + page_buf_bdstrat_t pb_strat; /* pre-write function */ + struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ + void *pb_fspriv; + void *pb_fspriv2; + void *pb_fspriv3; + unsigned short pb_error; /* error code on I/O */ + unsigned short pb_page_count; /* size of page array */ + unsigned short pb_offset; /* page offset in first page */ + unsigned char pb_locked; /* page array is locked */ + unsigned char pb_hash_index; /* hash table index */ + struct page **pb_pages; /* array of page pointers */ + struct page *pb_page_array[PB_PAGES]; /* inline pages */ +#ifdef PAGEBUF_LOCK_TRACKING + int pb_last_holder; +#endif +} page_buf_t; + + +/* Finding and Reading Buffers */ + +extern page_buf_t *pagebuf_find( /* find buffer for block if */ + /* the block is in memory */ + struct pb_target *, /* inode for block */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_LOCK */ + +extern page_buf_t *pagebuf_get( /* allocate a buffer */ + struct pb_target *, /* inode for buffer */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ + /* PBF_ASYNC */ + +extern page_buf_t *pagebuf_lookup( + struct pb_target *, + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ + /* PBF_FORCEIO, _PBF_LOCKABLE */ + +extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ + /* no memory or disk address */ + size_t len, + struct pb_target *); /* mount point "fake" inode */ + +extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ + /* without disk address */ + size_t len, + struct pb_target *); /* mount point "fake" inode */ + +extern int pagebuf_associate_memory( + page_buf_t *, + void *, + size_t); + +extern void pagebuf_hold( /* increment reference count */ + page_buf_t *); /* buffer to hold */ + +extern void pagebuf_readahead( /* read ahead into cache */ + struct pb_target *, /* target for buffer (or NULL) */ + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* additional read flags */ + +/* Releasing Buffers */ + +extern void pagebuf_free( /* deallocate a buffer */ + page_buf_t *); /* buffer to deallocate */ + +extern void pagebuf_rele( /* release hold on a buffer */ + page_buf_t *); /* buffer to release */ + +/* Locking and Unlocking Buffers */ + +extern int pagebuf_cond_lock( /* lock buffer, if not locked */ + /* (returns -EBUSY if locked) */ + page_buf_t *); /* buffer to lock */ + +extern int pagebuf_lock_value( /* return count on lock */ + page_buf_t *); /* buffer to check */ + +extern int pagebuf_lock( /* lock buffer */ + page_buf_t *); /* buffer to lock */ + +extern void pagebuf_unlock( /* unlock buffer */ + page_buf_t *); /* buffer to unlock */ + +/* Buffer Read and Write Routines */ + +extern void pagebuf_iodone( /* mark buffer I/O complete */ + page_buf_t *, /* buffer to mark */ + int, /* use data/log helper thread. */ + int); /* run completion locally, or in + * a helper thread. */ + +extern void pagebuf_ioerror( /* mark buffer in error (or not) */ + page_buf_t *, /* buffer to mark */ + unsigned int); /* error to store (0 if none) */ + +extern int pagebuf_iostart( /* start I/O on a buffer */ + page_buf_t *, /* buffer to start */ + page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ + /* PBF_READ, PBF_WRITE, */ + /* PBF_DELWRI, PBF_SYNC */ + +extern int pagebuf_iorequest( /* start real I/O */ + page_buf_t *); /* buffer to convey to device */ + +extern int pagebuf_iowait( /* wait for buffer I/O done */ + page_buf_t *); /* buffer to wait on */ + +extern void pagebuf_iomove( /* move data in/out of pagebuf */ + page_buf_t *, /* buffer to manipulate */ + size_t, /* starting buffer offset */ + size_t, /* length in buffer */ + caddr_t, /* data pointer */ + page_buf_rw_t); /* direction */ + +static inline int pagebuf_iostrategy(page_buf_t *pb) +{ + return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); +} + +static inline int pagebuf_geterror(page_buf_t *pb) +{ + return pb ? pb->pb_error : ENOMEM; +} + +/* Buffer Utility Routines */ + +extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ + page_buf_t *, /* buffer to offset into */ + size_t); /* offset */ + +/* Pinning Buffer Storage in Memory */ + +extern void pagebuf_pin( /* pin buffer in memory */ + page_buf_t *); /* buffer to pin */ + +extern void pagebuf_unpin( /* unpin buffered data */ + page_buf_t *); /* buffer to unpin */ + +extern int pagebuf_ispin( /* check if buffer is pinned */ + page_buf_t *); /* buffer to check */ + +/* Delayed Write Buffer Routines */ + +#define PBDF_WAIT 0x01 +extern void pagebuf_delwri_flush( + pb_target_t *, + unsigned long, + int *); + +extern void pagebuf_delwri_dequeue( + page_buf_t *); + +/* Buffer Daemon Setup Routines */ + +extern int pagebuf_init(void); +extern void pagebuf_terminate(void); + + +#ifdef PAGEBUF_TRACE +extern ktrace_t *pagebuf_trace_buf; +extern void pagebuf_trace( + page_buf_t *, /* buffer being traced */ + char *, /* description of operation */ + void *, /* arbitrary diagnostic value */ + void *); /* return address */ +#else +# define pagebuf_trace(pb, id, ptr, ra) do { } while (0) +#endif + +#define pagebuf_target_name(target) \ + ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) + + + + + +/* These are just for xfs_syncsub... it sets an internal variable + * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t + */ +#define XFS_B_ASYNC PBF_ASYNC +#define XFS_B_DELWRI PBF_DELWRI +#define XFS_B_READ PBF_READ +#define XFS_B_WRITE PBF_WRITE +#define XFS_B_STALE PBF_STALE + +#define XFS_BUF_TRYLOCK PBF_TRYLOCK +#define XFS_INCORE_TRYLOCK PBF_TRYLOCK +#define XFS_BUF_LOCK PBF_LOCK +#define XFS_BUF_MAPPED PBF_MAPPED + +#define BUF_BUSY PBF_DONT_BLOCK + +#define XFS_BUF_BFLAGS(x) ((x)->pb_flags) +#define XFS_BUF_ZEROFLAGS(x) \ + ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI)) + +#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) +#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) +#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) +#define XFS_BUF_SUPER_STALE(x) do { \ + XFS_BUF_STALE(x); \ + xfs_buf_undelay(x); \ + XFS_BUF_DONE(x); \ + } while (0) + +#define XFS_BUF_MANAGE PBF_FS_MANAGED +#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) + +static inline void xfs_buf_undelay(page_buf_t *pb) +{ + if (pb->pb_flags & PBF_DELWRI) { + if (pb->pb_list.next != &pb->pb_list) { + pagebuf_delwri_dequeue(pb); + pagebuf_rele(pb); + } else { + pb->pb_flags &= ~PBF_DELWRI; + } + } +} + +#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) +#define XFS_BUF_UNDELAYWRITE(x) xfs_buf_undelay(x) +#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) + +#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) +#define XFS_BUF_GETERROR(x) pagebuf_geterror(x) +#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) + +#define XFS_BUF_DONE(x) ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE)) +#define XFS_BUF_UNDONE(x) ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE) +#define XFS_BUF_ISDONE(x) (!(PBF_NOT_DONE(x))) + +#define XFS_BUF_BUSY(x) ((x)->pb_flags |= PBF_FORCEIO) +#define XFS_BUF_UNBUSY(x) ((x)->pb_flags &= ~PBF_FORCEIO) +#define XFS_BUF_ISBUSY(x) (1) + +#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) +#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) +#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) + +#define XFS_BUF_FLUSH(x) ((x)->pb_flags |= PBF_FLUSH) +#define XFS_BUF_UNFLUSH(x) ((x)->pb_flags &= ~PBF_FLUSH) +#define XFS_BUF_ISFLUSH(x) ((x)->pb_flags & PBF_FLUSH) + +#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") +#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") +#define XFS_BUF_ISSHUT(x) (0) + +#define XFS_BUF_HOLD(x) pagebuf_hold(x) +#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) +#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) +#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) + +#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) +#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) +#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) + +#define XFS_BUF_ISUNINITIAL(x) (0) +#define XFS_BUF_UNUNINITIAL(x) (0) + +#define XFS_BUF_BP_ISMAPPED(bp) 1 + +typedef struct page_buf_s xfs_buf_t; +#define xfs_buf page_buf_s + +typedef struct pb_target xfs_buftarg_t; +#define xfs_buftarg pb_target + +#define XFS_BUF_DATAIO(x) ((x)->pb_flags |= PBF_FS_DATAIOD) +#define XFS_BUF_UNDATAIO(x) ((x)->pb_flags &= ~PBF_FS_DATAIOD) + +#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone +#define XFS_BUF_SET_IODONE_FUNC(buf, func) \ + (buf)->pb_iodone = (func) +#define XFS_BUF_CLR_IODONE_FUNC(buf) \ + (buf)->pb_iodone = NULL +#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ + (buf)->pb_strat = (func) +#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ + (buf)->pb_strat = NULL + +#define XFS_BUF_FSPRIVATE(buf, type) \ + ((type)(buf)->pb_fspriv) +#define XFS_BUF_SET_FSPRIVATE(buf, value) \ + (buf)->pb_fspriv = (void *)(value) +#define XFS_BUF_FSPRIVATE2(buf, type) \ + ((type)(buf)->pb_fspriv2) +#define XFS_BUF_SET_FSPRIVATE2(buf, value) \ + (buf)->pb_fspriv2 = (void *)(value) +#define XFS_BUF_FSPRIVATE3(buf, type) \ + ((type)(buf)->pb_fspriv3) +#define XFS_BUF_SET_FSPRIVATE3(buf, value) \ + (buf)->pb_fspriv3 = (void *)(value) +#define XFS_BUF_SET_START(buf) + +#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ + (buf)->pb_relse = (value) + +#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) + +extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset) +{ + if (bp->pb_flags & PBF_MAPPED) + return XFS_BUF_PTR(bp) + offset; + return (xfs_caddr_t) pagebuf_offset(bp, offset); +} + +#define XFS_BUF_SET_PTR(bp, val, count) \ + pagebuf_associate_memory(bp, val, count) +#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) +#define XFS_BUF_SET_ADDR(bp, blk) \ + ((bp)->pb_bn = (page_buf_daddr_t)(blk)) +#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) +#define XFS_BUF_SET_OFFSET(bp, off) \ + ((bp)->pb_file_offset = (off)) +#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) +#define XFS_BUF_SET_COUNT(bp, cnt) \ + ((bp)->pb_count_desired = (cnt)) +#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) +#define XFS_BUF_SET_SIZE(bp, cnt) \ + ((bp)->pb_buffer_length = (cnt)) +#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) +#define XFS_BUF_SET_VTYPE(bp, type) +#define XFS_BUF_SET_REF(bp, ref) + +#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) + +#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) +#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) +#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) +#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) +#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); + +/* setup the buffer target from a buftarg structure */ +#define XFS_BUF_SET_TARGET(bp, target) \ + (bp)->pb_target = (target) +#define XFS_BUF_TARGET(bp) ((bp)->pb_target) +#define XFS_BUFTARG_NAME(target) \ + pagebuf_target_name(target) + +#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) +#define XFS_BUF_SET_VTYPE(bp, type) +#define XFS_BUF_SET_REF(bp, ref) + +#define xfs_buf_read(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE) +#define xfs_buf_get(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE) + +#define xfs_buf_read_flags(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_READ | PBF_MAPPABLE | flags) +#define xfs_buf_get_flags(target, blkno, len, flags) \ + pagebuf_get((target), (blkno), (len), \ + PBF_MAPPABLE | flags) + +static inline int xfs_bawrite(void *mp, page_buf_t *bp) +{ + bp->pb_fspriv3 = mp; + bp->pb_strat = xfs_bdstrat_cb; + xfs_buf_undelay(bp); + return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES); +} + +static inline void xfs_buf_relse(page_buf_t *bp) +{ + if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse) + pagebuf_unlock(bp); + pagebuf_rele(bp); +} + +#define xfs_bpin(bp) pagebuf_pin(bp) +#define xfs_bunpin(bp) pagebuf_unpin(bp) + +#define xfs_buftrace(id, bp) \ + pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) + +#define xfs_biodone(pb) \ + pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0) + +#define xfs_incore(buftarg,blkno,len,lockit) \ + pagebuf_find(buftarg, blkno ,len, lockit) + + +#define xfs_biomove(pb, off, len, data, rw) \ + pagebuf_iomove((pb), (off), (len), (data), \ + ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) + +#define xfs_biozero(pb, off, len) \ + pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) + + +static inline int XFS_bwrite(page_buf_t *pb) +{ + int iowait = (pb->pb_flags & PBF_ASYNC) == 0; + int error = 0; + + pb->pb_flags |= PBF_SYNC; + if (!iowait) + pb->pb_flags |= PBF_RUN_QUEUES; + + xfs_buf_undelay(pb); + pagebuf_iostrategy(pb); + if (iowait) { + error = pagebuf_iowait(pb); + xfs_buf_relse(pb); + } + return error; +} + +#define XFS_bdwrite(pb) \ + pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) + +static inline int xfs_bdwrite(void *mp, page_buf_t *bp) +{ + bp->pb_strat = xfs_bdstrat_cb; + bp->pb_fspriv3 = mp; + + return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); +} + +#define XFS_bdstrat(bp) pagebuf_iorequest(bp) + +#define xfs_iowait(pb) pagebuf_iowait(pb) + + +/* + * Go through all incore buffers, and release buffers + * if they belong to the given device. This is used in + * filesystem error handling to preserve the consistency + * of its metadata. + */ + +#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg) + +#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg) + +#define xfs_incore_relse(buftarg,delwri_only,wait) \ + xfs_relse_buftarg(buftarg) + +#define xfs_baread(target, rablkno, ralen) \ + pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) + +#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) +#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) +#define xfs_buf_free(bp) pagebuf_free(bp) + +#endif /* __XFS_BUF_H__ */ + diff --git a/fs/xfs/linux/xfs_iomap.c b/fs/xfs/linux/xfs_iomap.c deleted file mode 100644 index ae4818adb23e..000000000000 --- a/fs/xfs/linux/xfs_iomap.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include "xfs.h" - -#include "xfs_fs.h" -#include "xfs_inum.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_alloc.h" -#include "xfs_dmapi.h" -#include "xfs_quota.h" -#include "xfs_mount.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_bit.h" -#include "xfs_rtalloc.h" -#include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_rw.h" -#include "xfs_acl.h" -#include "xfs_cap.h" -#include "xfs_mac.h" -#include "xfs_attr.h" -#include "xfs_buf_item.h" -#include "xfs_trans_space.h" -#include "xfs_utils.h" -#include "xfs_iomap.h" - -#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ - << mp->m_writeio_log) -#define XFS_STRAT_WRITE_IMAPS 2 -#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP - -STATIC int -xfs_imap_to_bmap( - xfs_iocore_t *io, - xfs_off_t offset, - xfs_bmbt_irec_t *imap, - xfs_iomap_t *iomapp, - int imaps, /* Number of imap entries */ - int iomaps, /* Number of iomap entries */ - int flags) -{ - xfs_mount_t *mp; - xfs_fsize_t nisize; - int pbm; - xfs_fsblock_t start_block; - - mp = io->io_mount; - nisize = XFS_SIZE(mp, io); - if (io->io_new_size > nisize) - nisize = io->io_new_size; - - for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { - iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? - mp->m_rtdev_targp : mp->m_ddev_targp; - iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); - iomapp->iomap_delta = offset - iomapp->iomap_offset; - iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); - iomapp->iomap_flags = flags; - - start_block = imap->br_startblock; - if (start_block == HOLESTARTBLOCK) { - iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_HOLE; - } else if (start_block == DELAYSTARTBLOCK) { - iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_DELAY; - } else { - iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); - if (ISUNWRITTEN(imap)) - iomapp->iomap_flags |= IOMAP_UNWRITTEN; - } - - if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) { - iomapp->iomap_flags |= IOMAP_EOF; - } - - offset += iomapp->iomap_bsize - iomapp->iomap_delta; - } - return pbm; /* Return the number filled */ -} - -int -xfs_iomap( - xfs_iocore_t *io, - xfs_off_t offset, - ssize_t count, - int flags, - xfs_iomap_t *iomapp, - int *niomaps) -{ - xfs_mount_t *mp = io->io_mount; - xfs_fileoff_t offset_fsb, end_fsb; - int error = 0; - int lockmode = 0; - xfs_bmbt_irec_t imap; - int nimaps = 1; - int bmapi_flags = 0; - int iomap_flags = 0; - - if (XFS_FORCED_SHUTDOWN(mp)) - return XFS_ERROR(EIO); - - switch (flags & - (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | - BMAPI_UNWRITTEN | BMAPI_DEVICE)) { - case BMAPI_READ: - lockmode = XFS_LCK_MAP_SHARED(mp, io); - bmapi_flags = XFS_BMAPI_ENTIRE; - if (flags & BMAPI_IGNSTATE) - bmapi_flags |= XFS_BMAPI_IGSTATE; - break; - case BMAPI_WRITE: - lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; - bmapi_flags = 0; - XFS_ILOCK(mp, io, lockmode); - break; - case BMAPI_ALLOCATE: - lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; - bmapi_flags = XFS_BMAPI_ENTIRE; - /* Attempt non-blocking lock */ - if (flags & BMAPI_TRYLOCK) { - if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) - return XFS_ERROR(EAGAIN); - } else { - XFS_ILOCK(mp, io, lockmode); - } - break; - case BMAPI_UNWRITTEN: - goto phase2; - case BMAPI_DEVICE: - lockmode = XFS_LCK_MAP_SHARED(mp, io); - iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? - mp->m_rtdev_targp : mp->m_ddev_targp; - error = 0; - *niomaps = 1; - goto out; - default: - BUG(); - } - - ASSERT(offset <= mp->m_maxioffset); - if ((xfs_fsize_t)offset + count > mp->m_maxioffset) - count = mp->m_maxioffset - offset; - end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); - offset_fsb = XFS_B_TO_FSBT(mp, offset); - - error = XFS_BMAPI(mp, NULL, io, offset_fsb, - (xfs_filblks_t)(end_fsb - offset_fsb), - bmapi_flags, NULL, 0, &imap, - &nimaps, NULL); - - if (error) - goto out; - -phase2: - switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { - case BMAPI_WRITE: - /* If we found an extent, return it */ - if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) - break; - - if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { - error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, - count, flags, &imap, &nimaps, nimaps); - } else { - error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, - flags, &imap, &nimaps); - } - iomap_flags = IOMAP_NEW; - break; - case BMAPI_ALLOCATE: - /* If we found an extent, return it */ - XFS_IUNLOCK(mp, io, lockmode); - lockmode = 0; - - if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) - break; - - error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); - break; - case BMAPI_UNWRITTEN: - lockmode = 0; - error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); - nimaps = 0; - break; - } - - if (nimaps) { - *niomaps = xfs_imap_to_bmap(io, offset, &imap, - iomapp, nimaps, *niomaps, iomap_flags); - } else if (niomaps) { - *niomaps = 0; - } - -out: - if (lockmode) - XFS_IUNLOCK(mp, io, lockmode); - return XFS_ERROR(error); -} - -STATIC int -xfs_flush_space( - xfs_inode_t *ip, - int *fsynced, - int *ioflags) -{ - switch (*fsynced) { - case 0: - if (ip->i_delayed_blks) { - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_inode(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 1; - } else { - *ioflags |= BMAPI_SYNC; - *fsynced = 2; - } - return 0; - case 1: - *fsynced = 2; - *ioflags |= BMAPI_SYNC; - return 0; - case 2: - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_device(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 3; - return 0; - } - return 1; -} - -int -xfs_iomap_write_direct( - xfs_inode_t *ip, - loff_t offset, - size_t count, - int flags, - xfs_bmbt_irec_t *ret_imap, - int *nmaps, - int found) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_iocore_t *io = &ip->i_iocore; - xfs_fileoff_t offset_fsb; - xfs_fileoff_t last_fsb; - xfs_filblks_t count_fsb; - xfs_fsize_t isize; - xfs_fsblock_t firstfsb; - int nimaps, maps; - int error; - int bmapi_flag; - int rt; - xfs_trans_t *tp; - xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; - xfs_bmap_free_t free_list; - int aeof; - xfs_filblks_t datablocks; - int committed; - int numrtextents; - uint resblks; - - /* - * Make sure that the dquots are there. This doesn't hold - * the ilock across a disk read. - */ - - error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); - if (error) - return XFS_ERROR(error); - - maps = min(XFS_WRITE_IMAPS, *nmaps); - nimaps = maps; - - isize = ip->i_d.di_size; - aeof = (offset + count) > isize; - - if (io->io_new_size > isize) - isize = io->io_new_size; - - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - count_fsb = last_fsb - offset_fsb; - if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { - xfs_fileoff_t map_last_fsb; - - map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; - - if (map_last_fsb < last_fsb) { - last_fsb = map_last_fsb; - count_fsb = last_fsb - offset_fsb; - } - ASSERT(count_fsb > 0); - } - - /* - * determine if reserving space on - * the data or realtime partition. - */ - if ((rt = XFS_IS_REALTIME_INODE(ip))) { - int sbrtextsize, iprtextsize; - - sbrtextsize = mp->m_sb.sb_rextsize; - iprtextsize = - ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; - numrtextents = (count_fsb + iprtextsize - 1); - do_div(numrtextents, sbrtextsize); - datablocks = 0; - } else { - datablocks = count_fsb; - numrtextents = 0; - } - - /* - * allocate and setup the transaction - */ - xfs_iunlock(ip, XFS_ILOCK_EXCL); - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - - resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); - - error = xfs_trans_reserve(tp, resblks, - XFS_WRITE_LOG_RES(mp), numrtextents, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - - /* - * check for running out of space - */ - if (error) - /* - * Free the transaction structure. - */ - xfs_trans_cancel(tp, 0); - - xfs_ilock(ip, XFS_ILOCK_EXCL); - - if (error) - goto error_out; /* Don't return in above if .. trans .., - need lock to return */ - - if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { - error = (EDQUOT); - goto error1; - } - nimaps = 1; - - bmapi_flag = XFS_BMAPI_WRITE; - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) - bmapi_flag |= XFS_BMAPI_PREALLOC; - - /* - * issue the bmapi() call to allocate the blocks - */ - XFS_BMAP_INIT(&free_list, &firstfsb); - imapp = &imap[0]; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); - if (error) { - goto error0; - } - - /* - * complete the transaction - */ - - error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); - if (error) { - goto error0; - } - - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (error) { - goto error_out; - } - - /* copy any maps to caller's array and return any error. */ - if (nimaps == 0) { - error = (ENOSPC); - goto error_out; - } - - *ret_imap = imap[0]; - *nmaps = 1; - return 0; - - error0: /* Cancel bmap, unlock inode, and cancel trans */ - xfs_bmap_cancel(&free_list); - - error1: /* Just cancel transaction */ - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - *nmaps = 0; /* nothing set-up here */ - -error_out: - return XFS_ERROR(error); -} - -int -xfs_iomap_write_delay( - xfs_inode_t *ip, - loff_t offset, - size_t count, - int ioflag, - xfs_bmbt_irec_t *ret_imap, - int *nmaps) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_iocore_t *io = &ip->i_iocore; - xfs_fileoff_t offset_fsb; - xfs_fileoff_t last_fsb; - xfs_fsize_t isize; - xfs_fsblock_t firstblock; - int nimaps; - int error; - xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; - int aeof; - int fsynced = 0; - - ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); - - /* - * Make sure that the dquots are there. This doesn't hold - * the ilock across a disk read. - */ - - error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); - if (error) - return XFS_ERROR(error); - -retry: - isize = ip->i_d.di_size; - if (io->io_new_size > isize) { - isize = io->io_new_size; - } - - aeof = 0; - offset_fsb = XFS_B_TO_FSBT(mp, offset); - last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); - /* - * If the caller is doing a write at the end of the file, - * then extend the allocation (and the buffer used for the write) - * out to the file system's write iosize. We clean up any extra - * space left over when the file is closed in xfs_inactive(). - * - * We don't bother with this for sync writes, because we need - * to minimize the amount we write for good performance. - */ - if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { - xfs_off_t aligned_offset; - unsigned int iosize; - xfs_fileoff_t ioalign; - - iosize = mp->m_writeio_blocks; - aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); - ioalign = XFS_B_TO_FSBT(mp, aligned_offset); - last_fsb = ioalign + iosize; - aeof = 1; - } - - nimaps = XFS_WRITE_IMAPS; - firstblock = NULLFSBLOCK; - - /* - * roundup the allocation request to m_dalign boundary if file size - * is greater that 512K and we are allocating past the allocation eof - */ - if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) { - int eof; - xfs_fileoff_t new_last_fsb; - new_last_fsb = roundup_64(last_fsb, mp->m_dalign); - error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); - if (error) { - return error; - } - if (eof) { - last_fsb = new_last_fsb; - } - } - - error = xfs_bmapi(NULL, ip, offset_fsb, - (xfs_filblks_t)(last_fsb - offset_fsb), - XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | - XFS_BMAPI_ENTIRE, &firstblock, 1, imap, - &nimaps, NULL); - /* - * This can be EDQUOT, if nimaps == 0 - */ - if (error && (error != ENOSPC)) { - return XFS_ERROR(error); - } - /* - * If bmapi returned us nothing, and if we didn't get back EDQUOT, - * then we must have run out of space. - */ - - if (nimaps == 0) { - if (xfs_flush_space(ip, &fsynced, &ioflag)) - return XFS_ERROR(ENOSPC); - - error = 0; - goto retry; - } - - *ret_imap = imap[0]; - *nmaps = 1; - return 0; -} - -/* - * Pass in a delayed allocate extent, convert it to real extents; - * return to the caller the extent we create which maps on top of - * the originating callers request. - * - * Called without a lock on the inode. - */ -int -xfs_iomap_write_allocate( - xfs_inode_t *ip, - xfs_bmbt_irec_t *map, - int *retmap) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_fileoff_t offset_fsb, last_block; - xfs_fileoff_t end_fsb, map_start_fsb; - xfs_fsblock_t first_block; - xfs_bmap_free_t free_list; - xfs_filblks_t count_fsb; - xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS]; - xfs_trans_t *tp; - int i, nimaps, committed; - int error = 0; - int nres; - - *retmap = 0; - - /* - * Make sure that the dquots are there. - */ - - if ((error = XFS_QM_DQATTACH(mp, ip, 0))) - return XFS_ERROR(error); - - offset_fsb = map->br_startoff; - count_fsb = map->br_blockcount; - map_start_fsb = offset_fsb; - - XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); - - while (count_fsb != 0) { - /* - * Set up a transaction with which to allocate the - * backing store for the file. Do allocations in a - * loop until we get some space in the range we are - * interested in. The other space that might be allocated - * is in the delayed allocation extent on which we sit - * but before our buffer starts. - */ - - nimaps = 0; - while (nimaps == 0) { - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); - error = xfs_trans_reserve(tp, nres, - XFS_WRITE_LOG_RES(mp), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - - if (error == ENOSPC) { - error = xfs_trans_reserve(tp, 0, - XFS_WRITE_LOG_RES(mp), - 0, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - } - if (error) { - xfs_trans_cancel(tp, 0); - return XFS_ERROR(error); - } - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - XFS_BMAP_INIT(&free_list, &first_block); - - nimaps = XFS_STRAT_WRITE_IMAPS; - /* - * Ensure we don't go beyond eof - it is possible - * the extents changed since we did the read call, - * we dropped the ilock in the interim. - */ - - end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size); - xfs_bmap_last_offset(NULL, ip, &last_block, - XFS_DATA_FORK); - last_block = XFS_FILEOFF_MAX(last_block, end_fsb); - if ((map_start_fsb + count_fsb) > last_block) { - count_fsb = last_block - map_start_fsb; - if (count_fsb == 0) { - error = EAGAIN; - goto trans_cancel; - } - } - - /* Go get the actual blocks */ - error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, - XFS_BMAPI_WRITE, &first_block, 1, - imap, &nimaps, &free_list); - - if (error) - goto trans_cancel; - - error = xfs_bmap_finish(&tp, &free_list, - first_block, &committed); - - if (error) - goto trans_cancel; - - error = xfs_trans_commit(tp, - XFS_TRANS_RELEASE_LOG_RES, NULL); - - if (error) - goto error0; - - xfs_iunlock(ip, XFS_ILOCK_EXCL); - } - - /* - * See if we were able to allocate an extent that - * covers at least part of the callers request - */ - - for (i = 0; i < nimaps; i++) { - if ((map->br_startoff >= imap[i].br_startoff) && - (map->br_startoff < (imap[i].br_startoff + - imap[i].br_blockcount))) { - *map = imap[i]; - *retmap = 1; - XFS_STATS_INC(xs_xstrat_quick); - return 0; - } - count_fsb -= imap[i].br_blockcount; - } - - /* So far we have not mapped the requested part of the - * file, just surrounding data, try again. - */ - nimaps--; - offset_fsb = imap[nimaps].br_startoff + - imap[nimaps].br_blockcount; - map_start_fsb = offset_fsb; - } - -trans_cancel: - xfs_bmap_cancel(&free_list); - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); -error0: - xfs_iunlock(ip, XFS_ILOCK_EXCL); - return XFS_ERROR(error); -} - -int -xfs_iomap_write_unwritten( - xfs_inode_t *ip, - loff_t offset, - size_t count) -{ - xfs_mount_t *mp = ip->i_mount; - xfs_trans_t *tp; - xfs_fileoff_t offset_fsb; - xfs_filblks_t count_fsb; - xfs_filblks_t numblks_fsb; - xfs_bmbt_irec_t imap; - int committed; - int error; - int nres; - int nimaps; - xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; - - offset_fsb = XFS_B_TO_FSBT(mp, offset); - count_fsb = XFS_B_TO_FSB(mp, count); - - do { - nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); - - /* - * set up a transaction to convert the range of extents - * from unwritten to real. Do allocations in a loop until - * we have covered the range passed in. - */ - - tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - error = xfs_trans_reserve(tp, nres, - XFS_WRITE_LOG_RES(mp), 0, - XFS_TRANS_PERM_LOG_RES, - XFS_WRITE_LOG_COUNT); - if (error) { - xfs_trans_cancel(tp, 0); - goto error0; - } - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_ihold(tp, ip); - - /* - * Modify the unwritten extent state of the buffer. - */ - XFS_BMAP_INIT(&free_list, &firstfsb); - nimaps = 1; - error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, - XFS_BMAPI_WRITE, &firstfsb, - 1, &imap, &nimaps, &free_list); - if (error) - goto error_on_bmapi_transaction; - - error = xfs_bmap_finish(&(tp), &(free_list), - firstfsb, &committed); - if (error) - goto error_on_bmapi_transaction; - - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - if (error) - goto error0; - - if ((numblks_fsb = imap.br_blockcount) == 0) { - /* - * The numblks_fsb value should always get - * smaller, otherwise the loop is stuck. - */ - ASSERT(imap.br_blockcount); - break; - } - offset_fsb += numblks_fsb; - count_fsb -= numblks_fsb; - } while (count_fsb > 0); - - return 0; - -error_on_bmapi_transaction: - xfs_bmap_cancel(&free_list); - xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT)); - xfs_iunlock(ip, XFS_ILOCK_EXCL); -error0: - return XFS_ERROR(error); -} diff --git a/fs/xfs/linux/xfs_linux.h b/fs/xfs/linux/xfs_linux.h index 39b2fff855e3..1cf06f8ec8ff 100644 --- a/fs/xfs/linux/xfs_linux.h +++ b/fs/xfs/linux/xfs_linux.h @@ -55,19 +55,26 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* * Feature macros (disable/enable) diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c deleted file mode 100644 index 5508239e08fc..000000000000 --- a/fs/xfs/pagebuf/page_buf.c +++ /dev/null @@ -1,2107 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -/* - * page_buf.c - * - * The page_buf module provides an abstract buffer cache model on top of - * the Linux page cache. Cached metadata blocks for a file system are - * hashed to the inode for the block device. The page_buf module - * assembles buffer (page_buf_t) objects on demand to aggregate such - * cached pages for I/O. - * - * - * Written by Steve Lord, Jim Mostek, Russell Cattelan - * and Rajagopal Ananthanarayanan ("ananth") at SGI. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "page_buf.h" - -#define BBSHIFT 9 -#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1) - -#ifndef GFP_READAHEAD -#define GFP_READAHEAD (__GFP_NOWARN|__GFP_NORETRY) -#endif - -/* - * File wide globals - */ - -STATIC kmem_cache_t *pagebuf_cache; -STATIC void pagebuf_daemon_wakeup(int); -STATIC void pagebuf_delwri_queue(page_buf_t *, int); -STATIC struct workqueue_struct *pagebuf_logio_workqueue; -STATIC struct workqueue_struct *pagebuf_dataio_workqueue; - -/* - * Pagebuf module configuration parameters, exported via - * /proc/sys/vm/pagebuf - */ - -typedef struct pb_sysctl_val { - int min; - int val; - int max; -} pb_sysctl_val_t; - -struct { - pb_sysctl_val_t flush_interval; /* interval between runs of the - * delwri flush daemon. */ - pb_sysctl_val_t age_buffer; /* time for buffer to age before - * we flush it. */ - pb_sysctl_val_t stats_clear; /* clear the pagebuf stats */ - pb_sysctl_val_t debug; /* debug tracing on or off */ -} pb_params = { - /* MIN DFLT MAX */ - .flush_interval = { HZ/2, HZ, 30*HZ }, - .age_buffer = { 1*HZ, 15*HZ, 300*HZ }, - .stats_clear = { 0, 0, 1 }, - .debug = { 0, 0, 1 }, -}; - -enum { - PB_FLUSH_INT = 1, - PB_FLUSH_AGE = 2, - PB_STATS_CLEAR = 3, - PB_DEBUG = 4, -}; - -/* - * Pagebuf statistics variables - */ - -struct pbstats { - u_int32_t pb_get; - u_int32_t pb_create; - u_int32_t pb_get_locked; - u_int32_t pb_get_locked_waited; - u_int32_t pb_busy_locked; - u_int32_t pb_miss_locked; - u_int32_t pb_page_retries; - u_int32_t pb_page_found; - u_int32_t pb_get_read; -} pbstats; -DEFINE_PER_CPU(struct pbstats, pbstats); - -/* We don't disable preempt, not too worried about poking the - * wrong cpu's stat for now */ -#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++) - -/* - * Pagebuf debugging - */ - -#ifdef PAGEBUF_TRACE -void -pagebuf_trace( - page_buf_t *pb, - char *id, - void *data, - void *ra) -{ - if (!pb_params.debug.val) - return; - ktrace_enter(pagebuf_trace_buf, - pb, id, - (void *)(unsigned long)pb->pb_flags, - (void *)(unsigned long)pb->pb_hold.counter, - (void *)(unsigned long)pb->pb_sema.count.counter, - (void *)current, - data, ra, - (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff), - (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff), - (void *)(unsigned long)pb->pb_buffer_length, - NULL, NULL, NULL, NULL, NULL); -} -ktrace_t *pagebuf_trace_buf; -EXPORT_SYMBOL(pagebuf_trace_buf); -#define PAGEBUF_TRACE_SIZE 4096 -#define PB_TRACE(pb, id, data) \ - pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) -#else -#define PB_TRACE(pb, id, data) do { } while (0) -#endif - -#ifdef PAGEBUF_LOCK_TRACKING -# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid) -# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1) -# define PB_GET_OWNER(pb) ((pb)->pb_last_holder) -#else -# define PB_SET_OWNER(pb) do { } while (0) -# define PB_CLEAR_OWNER(pb) do { } while (0) -# define PB_GET_OWNER(pb) do { } while (0) -#endif - -/* - * Pagebuf allocation / freeing. - */ - -#define pb_to_gfp(flags) \ - (((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \ - ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) - -#define pagebuf_allocate(flags) \ - kmem_cache_alloc(pagebuf_cache, pb_to_gfp(flags)) -#define pagebuf_deallocate(pb) \ - kmem_cache_free(pagebuf_cache, (pb)); - -/* - * Pagebuf hashing - */ - -#define NBITS 8 -#define NHASH (1<pb_hash_index] - -STATIC int -_bhash( - struct block_device *bdev, - loff_t base) -{ - int bit, hval; - - base >>= 9; - base ^= (unsigned long)bdev / L1_CACHE_BYTES; - for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) { - hval ^= (int)base & (NHASH-1); - base >>= NBITS; - } - return hval; -} - -/* - * Mapping of multi-page buffers into contiguous virtual space - */ - -STATIC void *pagebuf_mapout_locked(page_buf_t *); - -typedef struct a_list { - void *vm_addr; - struct a_list *next; -} a_list_t; - -STATIC a_list_t *as_free_head; -STATIC int as_list_len; -STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED; - -/* - * Try to batch vunmaps because they are costly. - */ -STATIC void -free_address( - void *addr) -{ - a_list_t *aentry; - - aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC); - if (aentry) { - spin_lock(&as_lock); - aentry->next = as_free_head; - aentry->vm_addr = addr; - as_free_head = aentry; - as_list_len++; - spin_unlock(&as_lock); - } else { - vunmap(addr); - } -} - -STATIC void -purge_addresses(void) -{ - a_list_t *aentry, *old; - - if (as_free_head == NULL) - return; - - spin_lock(&as_lock); - aentry = as_free_head; - as_free_head = NULL; - as_list_len = 0; - spin_unlock(&as_lock); - - while ((old = aentry) != NULL) { - vunmap(aentry->vm_addr); - aentry = aentry->next; - kfree(old); - } -} - -/* - * Internal pagebuf object manipulation - */ - -STATIC void -_pagebuf_initialize( - page_buf_t *pb, - pb_target_t *target, - loff_t range_base, - size_t range_length, - page_buf_flags_t flags) -{ - /* - * We don't want certain flags to appear in pb->pb_flags. - */ - flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD); - - memset(pb, 0, sizeof(page_buf_t)); - atomic_set(&pb->pb_hold, 1); - init_MUTEX_LOCKED(&pb->pb_iodonesema); - INIT_LIST_HEAD(&pb->pb_list); - INIT_LIST_HEAD(&pb->pb_hash_list); - init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */ - PB_SET_OWNER(pb); - pb->pb_target = target; - pb->pb_file_offset = range_base; - /* - * Set buffer_length and count_desired to the same value initially. - * IO routines should use count_desired, which will be the same in - * most cases but may be reset (e.g. XFS recovery). - */ - pb->pb_buffer_length = pb->pb_count_desired = range_length; - pb->pb_flags = flags | PBF_NONE; - pb->pb_bn = PAGE_BUF_DADDR_NULL; - atomic_set(&pb->pb_pin_count, 0); - init_waitqueue_head(&pb->pb_waiters); - - PB_STATS_INC(pb_create); - PB_TRACE(pb, "initialize", target); -} - -/* - * Allocate a page array capable of holding a specified number - * of pages, and point the page buf at it. - */ -STATIC int -_pagebuf_get_pages( - page_buf_t *pb, - int page_count, - page_buf_flags_t flags) -{ - int gpf_mask = pb_to_gfp(flags); - - /* Make sure that we have a page list */ - if (pb->pb_pages == NULL) { - pb->pb_offset = page_buf_poff(pb->pb_file_offset); - pb->pb_page_count = page_count; - if (page_count <= PB_PAGES) { - pb->pb_pages = pb->pb_page_array; - } else { - pb->pb_pages = kmalloc(sizeof(struct page *) * - page_count, gpf_mask); - if (pb->pb_pages == NULL) - return -ENOMEM; - } - memset(pb->pb_pages, 0, sizeof(struct page *) * page_count); - } - return 0; -} - -/* - * Walk a pagebuf releasing all the pages contained within it. - */ -STATIC inline void -_pagebuf_freepages( - page_buf_t *pb) -{ - int buf_index; - - for (buf_index = 0; buf_index < pb->pb_page_count; buf_index++) { - struct page *page = pb->pb_pages[buf_index]; - - if (page) { - pb->pb_pages[buf_index] = NULL; - page_cache_release(page); - } - } -} - -/* - * _pagebuf_free_object - * - * _pagebuf_free_object releases the contents specified buffer. - * The modification state of any associated pages is left unchanged. - */ -void -_pagebuf_free_object( - pb_hash_t *hash, /* hash bucket for buffer */ - page_buf_t *pb) /* buffer to deallocate */ -{ - page_buf_flags_t pb_flags = pb->pb_flags; - - PB_TRACE(pb, "free_object", 0); - pb->pb_flags |= PBF_FREED; - - if (hash) { - if (!list_empty(&pb->pb_hash_list)) { - hash->pb_count--; - list_del_init(&pb->pb_hash_list); - } - spin_unlock(&hash->pb_hash_lock); - } - - if (!(pb_flags & PBF_FREED)) { - /* release any virtual mapping */ ; - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { - void *vaddr = pagebuf_mapout_locked(pb); - if (vaddr) { - free_address(vaddr); - } - } - - if (pb->pb_flags & _PBF_MEM_ALLOCATED) { - if (pb->pb_pages) { - /* release the pages in the address list */ - if ((pb->pb_pages[0]) && - (pb->pb_flags & _PBF_MEM_SLAB)) { - kfree(pb->pb_addr); - } else { - _pagebuf_freepages(pb); - } - if (pb->pb_pages != pb->pb_page_array) - kfree(pb->pb_pages); - pb->pb_pages = NULL; - } - pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); - } - } - - pagebuf_deallocate(pb); -} - -/* - * _pagebuf_lookup_pages - * - * _pagebuf_lookup_pages finds all pages which match the buffer - * in question and the range of file offsets supplied, - * and builds the page list for the buffer, if the - * page list is not already formed or if not all of the pages are - * already in the list. Invalid pages (pages which have not yet been - * read in from disk) are assigned for any pages which are not found. - */ -STATIC int -_pagebuf_lookup_pages( - page_buf_t *pb, - struct address_space *aspace, - page_buf_flags_t flags) -{ - loff_t next_buffer_offset; - unsigned long page_count, pi, index; - struct page *page; - int gfp_mask, retry_count = 5, rval = 0; - int all_mapped, good_pages, nbytes; - unsigned int blocksize, sectorshift; - size_t size, offset; - - - /* For pagebufs where we want to map an address, do not use - * highmem pages - so that we do not need to use kmap resources - * to access the data. - * - * For pages where the caller has indicated there may be resource - * contention (e.g. called from a transaction) do not flush - * delalloc pages to obtain memory. - */ - - if (flags & PBF_READ_AHEAD) { - gfp_mask = GFP_READAHEAD; - retry_count = 0; - } else if (flags & PBF_DONT_BLOCK) { - gfp_mask = GFP_NOFS; - } else if (flags & PBF_MAPPABLE) { - gfp_mask = GFP_KERNEL; - } else { - gfp_mask = GFP_HIGHUSER; - } - - next_buffer_offset = pb->pb_file_offset + pb->pb_buffer_length; - - good_pages = page_count = (page_buf_btoc(next_buffer_offset) - - page_buf_btoct(pb->pb_file_offset)); - - if (pb->pb_flags & _PBF_ALL_PAGES_MAPPED) { - /* Bring pages forward in cache */ - for (pi = 0; pi < page_count; pi++) { - mark_page_accessed(pb->pb_pages[pi]); - } - if ((flags & PBF_MAPPED) && !(pb->pb_flags & PBF_MAPPED)) { - all_mapped = 1; - goto mapit; - } - return 0; - } - - /* Ensure pb_pages field has been initialised */ - rval = _pagebuf_get_pages(pb, page_count, flags); - if (rval) - return rval; - - rval = pi = 0; - blocksize = pb->pb_target->pbr_bsize; - sectorshift = pb->pb_target->pbr_sshift; - size = pb->pb_count_desired; - offset = pb->pb_offset; - - /* Enter the pages in the page list */ - index = (pb->pb_file_offset - pb->pb_offset) >> PAGE_CACHE_SHIFT; - for (all_mapped = 1; pi < page_count; pi++, index++) { - if (pb->pb_pages[pi] == 0) { - retry: - page = find_or_create_page(aspace, index, gfp_mask); - if (!page) { - if (--retry_count > 0) { - PB_STATS_INC(pb_page_retries); - pagebuf_daemon_wakeup(1); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(10); - goto retry; - } - rval = -ENOMEM; - all_mapped = 0; - continue; - } - PB_STATS_INC(pb_page_found); - mark_page_accessed(page); - pb->pb_pages[pi] = page; - } else { - page = pb->pb_pages[pi]; - lock_page(page); - } - - nbytes = PAGE_CACHE_SIZE - offset; - if (nbytes > size) - nbytes = size; - size -= nbytes; - - if (!PageUptodate(page)) { - if (blocksize == PAGE_CACHE_SIZE) { - if (flags & PBF_READ) - pb->pb_locked = 1; - good_pages--; - } else if (!PagePrivate(page)) { - unsigned long i, range; - - /* - * In this case page->private holds a bitmap - * of uptodate sectors within the page - */ - ASSERT(blocksize < PAGE_CACHE_SIZE); - range = (offset + nbytes) >> sectorshift; - for (i = offset >> sectorshift; i < range; i++) - if (!test_bit(i, &page->private)) - break; - if (i != range) - good_pages--; - } else { - good_pages--; - } - } - offset = 0; - } - - if (!pb->pb_locked) { - for (pi = 0; pi < page_count; pi++) { - if (pb->pb_pages[pi]) - unlock_page(pb->pb_pages[pi]); - } - } - -mapit: - pb->pb_flags |= _PBF_MEM_ALLOCATED; - if (all_mapped) { - pb->pb_flags |= _PBF_ALL_PAGES_MAPPED; - - /* A single page buffer is always mappable */ - if (page_count == 1) { - pb->pb_addr = (caddr_t) - page_address(pb->pb_pages[0]) + pb->pb_offset; - pb->pb_flags |= PBF_MAPPED; - } else if (flags & PBF_MAPPED) { - if (as_list_len > 64) - purge_addresses(); - pb->pb_addr = vmap(pb->pb_pages, page_count, - VM_MAP, PAGE_KERNEL); - if (pb->pb_addr == NULL) - return -ENOMEM; - pb->pb_addr += pb->pb_offset; - pb->pb_flags |= PBF_MAPPED | _PBF_ADDR_ALLOCATED; - } - } - /* If some pages were found with data in them - * we are not in PBF_NONE state. - */ - if (good_pages != 0) { - pb->pb_flags &= ~(PBF_NONE); - if (good_pages != page_count) { - pb->pb_flags |= PBF_PARTIAL; - } - } - - PB_TRACE(pb, "lookup_pages", (long)good_pages); - - return rval; -} - -/* - * Finding and Reading Buffers - */ - -/* - * _pagebuf_find - * - * Looks up, and creates if absent, a lockable buffer for - * a given range of an inode. The buffer is returned - * locked. If other overlapping buffers exist, they are - * released before the new buffer is created and locked, - * which may imply that this call will block until those buffers - * are unlocked. No I/O is implied by this call. - */ -STATIC page_buf_t * -_pagebuf_find( /* find buffer for block */ - pb_target_t *target,/* target for block */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags, /* PBF_TRYLOCK */ - page_buf_t *new_pb)/* newly allocated buffer */ -{ - loff_t range_base; - size_t range_length; - int hval; - pb_hash_t *h; - struct list_head *p; - page_buf_t *pb; - int not_locked; - - range_base = (ioff << BBSHIFT); - range_length = (isize << BBSHIFT); - - /* Ensure we never do IOs smaller than the sector size */ - BUG_ON(range_length < (1 << target->pbr_sshift)); - - /* Ensure we never do IOs that are not sector aligned */ - BUG_ON(range_base & (loff_t)target->pbr_smask); - - hval = _bhash(target->pbr_bdev, range_base); - h = &pbhash[hval]; - - spin_lock(&h->pb_hash_lock); - list_for_each(p, &h->pb_hash) { - pb = list_entry(p, page_buf_t, pb_hash_list); - - if ((target == pb->pb_target) && - (pb->pb_file_offset == range_base) && - (pb->pb_buffer_length == range_length)) { - if (pb->pb_flags & PBF_FREED) - break; - /* If we look at something bring it to the - * front of the list for next time - */ - list_del(&pb->pb_hash_list); - list_add(&pb->pb_hash_list, &h->pb_hash); - goto found; - } - } - - /* No match found */ - if (new_pb) { - _pagebuf_initialize(new_pb, target, range_base, - range_length, flags | _PBF_LOCKABLE); - new_pb->pb_hash_index = hval; - h->pb_count++; - list_add(&new_pb->pb_hash_list, &h->pb_hash); - } else { - PB_STATS_INC(pb_miss_locked); - } - - spin_unlock(&h->pb_hash_lock); - return (new_pb); - -found: - atomic_inc(&pb->pb_hold); - spin_unlock(&h->pb_hash_lock); - - /* Attempt to get the semaphore without sleeping, - * if this does not work then we need to drop the - * spinlock and do a hard attempt on the semaphore. - */ - not_locked = down_trylock(&pb->pb_sema); - if (not_locked) { - if (!(flags & PBF_TRYLOCK)) { - /* wait for buffer ownership */ - PB_TRACE(pb, "get_lock", 0); - pagebuf_lock(pb); - PB_STATS_INC(pb_get_locked_waited); - } else { - /* We asked for a trylock and failed, no need - * to look at file offset and length here, we - * know that this pagebuf at least overlaps our - * pagebuf and is locked, therefore our buffer - * either does not exist, or is this buffer - */ - - pagebuf_rele(pb); - PB_STATS_INC(pb_busy_locked); - return (NULL); - } - } else { - /* trylock worked */ - PB_SET_OWNER(pb); - } - - if (pb->pb_flags & PBF_STALE) - pb->pb_flags &= PBF_MAPPABLE | \ - PBF_MAPPED | \ - _PBF_LOCKABLE | \ - _PBF_ALL_PAGES_MAPPED | \ - _PBF_ADDR_ALLOCATED | \ - _PBF_MEM_ALLOCATED | \ - _PBF_MEM_SLAB; - PB_TRACE(pb, "got_lock", 0); - PB_STATS_INC(pb_get_locked); - return (pb); -} - - -/* - * pagebuf_find - * - * pagebuf_find returns a buffer matching the specified range of - * data for the specified target, if any of the relevant blocks - * are in memory. The buffer may have unallocated holes, if - * some, but not all, of the blocks are in memory. Even where - * pages are present in the buffer, not all of every page may be - * valid. - */ -page_buf_t * -pagebuf_find( /* find buffer for block */ - /* if the block is in memory */ - pb_target_t *target,/* target for block */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags) /* PBF_TRYLOCK */ -{ - return _pagebuf_find(target, ioff, isize, flags, NULL); -} - -/* - * pagebuf_get - * - * pagebuf_get assembles a buffer covering the specified range. - * Some or all of the blocks in the range may be valid. Storage - * in memory for all portions of the buffer will be allocated, - * although backing storage may not be. If PBF_READ is set in - * flags, pagebuf_iostart is called also. - */ -page_buf_t * -pagebuf_get( /* allocate a buffer */ - pb_target_t *target,/* target for buffer */ - loff_t ioff, /* starting offset of range */ - size_t isize, /* length of range */ - page_buf_flags_t flags) /* PBF_TRYLOCK */ -{ - page_buf_t *pb, *new_pb; - int error; - - new_pb = pagebuf_allocate(flags); - if (unlikely(!new_pb)) - return (NULL); - - pb = _pagebuf_find(target, ioff, isize, flags, new_pb); - if (pb != new_pb) { - pagebuf_deallocate(new_pb); - if (unlikely(!pb)) - return (NULL); - } - - PB_STATS_INC(pb_get); - - /* fill in any missing pages */ - error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags); - if (unlikely(error)) { - pagebuf_free(pb); - return (NULL); - } - - /* - * Always fill in the block number now, the mapped cases can do - * their own overlay of this later. - */ - pb->pb_bn = ioff; - pb->pb_count_desired = pb->pb_buffer_length; - - if (flags & PBF_READ) { - if (PBF_NOT_DONE(pb)) { - PB_TRACE(pb, "get_read", (unsigned long)flags); - PB_STATS_INC(pb_get_read); - pagebuf_iostart(pb, flags); - } else if (flags & PBF_ASYNC) { - PB_TRACE(pb, "get_read_async", (unsigned long)flags); - /* - * Read ahead call which is already satisfied, - * drop the buffer - */ - if (flags & (PBF_LOCK | PBF_TRYLOCK)) - pagebuf_unlock(pb); - pagebuf_rele(pb); - return NULL; - } else { - PB_TRACE(pb, "get_read_done", (unsigned long)flags); - /* We do not want read in the flags */ - pb->pb_flags &= ~PBF_READ; - } - } else { - PB_TRACE(pb, "get_write", (unsigned long)flags); - } - return (pb); -} - -/* - * Create a skeletal pagebuf (no pages associated with it). - */ -page_buf_t * -pagebuf_lookup( - struct pb_target *target, - loff_t ioff, - size_t isize, - page_buf_flags_t flags) -{ - page_buf_t *pb; - - pb = pagebuf_allocate(flags); - if (pb) { - _pagebuf_initialize(pb, target, ioff, isize, flags); - } - return pb; -} - -/* - * If we are not low on memory then do the readahead in a deadlock - * safe manner. - */ -void -pagebuf_readahead( - pb_target_t *target, - loff_t ioff, - size_t isize, - page_buf_flags_t flags) -{ - struct backing_dev_info *bdi; - - bdi = target->pbr_mapping->backing_dev_info; - if (bdi_read_congested(bdi)) - return; - if (bdi_write_congested(bdi)) - return; - - flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD); - pagebuf_get(target, ioff, isize, flags); -} - -page_buf_t * -pagebuf_get_empty( - size_t len, - pb_target_t *target) -{ - page_buf_t *pb; - - pb = pagebuf_allocate(_PBF_LOCKABLE); - if (pb) - _pagebuf_initialize(pb, target, 0, len, _PBF_LOCKABLE); - return pb; -} - -static inline struct page * -mem_to_page( - void *addr) -{ - if (((unsigned long)addr < VMALLOC_START) || - ((unsigned long)addr >= VMALLOC_END)) { - return virt_to_page(addr); - } else { - return vmalloc_to_page(addr); - } -} - -int -pagebuf_associate_memory( - page_buf_t *pb, - void *mem, - size_t len) -{ - int rval; - int i = 0; - size_t ptr; - size_t end, end_cur; - off_t offset; - int page_count; - - page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; - offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); - if (offset && (len > PAGE_CACHE_SIZE)) - page_count++; - - /* Free any previous set of page pointers */ - if (pb->pb_pages && (pb->pb_pages != pb->pb_page_array)) { - kfree(pb->pb_pages); - } - pb->pb_pages = NULL; - pb->pb_addr = mem; - - rval = _pagebuf_get_pages(pb, page_count, 0); - if (rval) - return rval; - - pb->pb_offset = offset; - ptr = (size_t) mem & PAGE_CACHE_MASK; - end = PAGE_CACHE_ALIGN((size_t) mem + len); - end_cur = end; - /* set up first page */ - pb->pb_pages[0] = mem_to_page(mem); - - ptr += PAGE_CACHE_SIZE; - pb->pb_page_count = ++i; - while (ptr < end) { - pb->pb_pages[i] = mem_to_page((void *)ptr); - pb->pb_page_count = ++i; - ptr += PAGE_CACHE_SIZE; - } - pb->pb_locked = 0; - - pb->pb_count_desired = pb->pb_buffer_length = len; - pb->pb_flags |= PBF_MAPPED; - - return 0; -} - -page_buf_t * -pagebuf_get_no_daddr( - size_t len, - pb_target_t *target) -{ - int rval; - void *rmem = NULL; - page_buf_flags_t flags = _PBF_LOCKABLE | PBF_FORCEIO; - page_buf_t *pb; - size_t tlen = 0; - - if (unlikely(len > 0x20000)) - return NULL; - - pb = pagebuf_allocate(flags); - if (!pb) - return NULL; - - _pagebuf_initialize(pb, target, 0, len, flags); - - do { - if (tlen == 0) { - tlen = len; /* first time */ - } else { - kfree(rmem); /* free the mem from the previous try */ - tlen <<= 1; /* double the size and try again */ - } - if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) { - pagebuf_free(pb); - return NULL; - } - } while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask)); - - if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) { - kfree(rmem); - pagebuf_free(pb); - return NULL; - } - /* otherwise pagebuf_free just ignores it */ - pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB); - PB_CLEAR_OWNER(pb); - up(&pb->pb_sema); /* Return unlocked pagebuf */ - - PB_TRACE(pb, "no_daddr", rmem); - - return pb; -} - - -/* - * pagebuf_hold - * - * Increment reference count on buffer, to hold the buffer concurrently - * with another thread which may release (free) the buffer asynchronously. - * - * Must hold the buffer already to call this function. - */ -void -pagebuf_hold( - page_buf_t *pb) -{ - atomic_inc(&pb->pb_hold); - PB_TRACE(pb, "hold", 0); -} - -/* - * pagebuf_free - * - * pagebuf_free releases the specified buffer. The modification - * state of any associated pages is left unchanged. - */ -void -pagebuf_free( - page_buf_t *pb) -{ - if (pb->pb_flags & _PBF_LOCKABLE) { - pb_hash_t *h = pb_hash(pb); - - spin_lock(&h->pb_hash_lock); - _pagebuf_free_object(h, pb); - } else { - _pagebuf_free_object(NULL, pb); - } -} - -/* - * pagebuf_rele - * - * pagebuf_rele releases a hold on the specified buffer. If the - * the hold count is 1, pagebuf_rele calls pagebuf_free. - */ -void -pagebuf_rele( - page_buf_t *pb) -{ - pb_hash_t *h; - - PB_TRACE(pb, "rele", pb->pb_relse); - if (pb->pb_flags & _PBF_LOCKABLE) { - h = pb_hash(pb); - spin_lock(&h->pb_hash_lock); - } else { - h = NULL; - } - - if (atomic_dec_and_test(&pb->pb_hold)) { - int do_free = 1; - - if (pb->pb_relse) { - atomic_inc(&pb->pb_hold); - if (h) - spin_unlock(&h->pb_hash_lock); - (*(pb->pb_relse)) (pb); - do_free = 0; - } - if (pb->pb_flags & PBF_DELWRI) { - pb->pb_flags |= PBF_ASYNC; - atomic_inc(&pb->pb_hold); - if (h && do_free) - spin_unlock(&h->pb_hash_lock); - pagebuf_delwri_queue(pb, 0); - do_free = 0; - } else if (pb->pb_flags & PBF_FS_MANAGED) { - if (h) - spin_unlock(&h->pb_hash_lock); - do_free = 0; - } - - if (do_free) { - _pagebuf_free_object(h, pb); - } - } else if (h) { - spin_unlock(&h->pb_hash_lock); - } -} - - -/* - * Mutual exclusion on buffers. Locking model: - * - * Buffers associated with inodes for which buffer locking - * is not enabled are not protected by semaphores, and are - * assumed to be exclusively owned by the caller. There is a - * spinlock in the buffer, used by the caller when concurrent - * access is possible. - */ - -/* - * pagebuf_cond_lock - * - * pagebuf_cond_lock locks a buffer object, if it is not already locked. - * Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. - */ -int -pagebuf_cond_lock( /* lock buffer, if not locked */ - /* returns -EBUSY if locked) */ - page_buf_t *pb) -{ - int locked; - - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - locked = down_trylock(&pb->pb_sema) == 0; - if (locked) { - PB_SET_OWNER(pb); - } - PB_TRACE(pb, "cond_lock", (long)locked); - return(locked ? 0 : -EBUSY); -} - -/* - * pagebuf_lock_value - * - * Return lock value for a pagebuf - */ -int -pagebuf_lock_value( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - return(atomic_read(&pb->pb_sema.count)); -} - -/* - * pagebuf_lock - * - * pagebuf_lock locks a buffer object. Note that this in no way - * locks the underlying pages, so it is only useful for synchronizing - * concurrent use of page buffer objects, not for synchronizing independent - * access to the underlying pages. - */ -int -pagebuf_lock( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - - PB_TRACE(pb, "lock", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - down(&pb->pb_sema); - PB_SET_OWNER(pb); - PB_TRACE(pb, "locked", 0); - return 0; -} - -/* - * pagebuf_unlock - * - * pagebuf_unlock releases the lock on the buffer object created by - * pagebuf_lock or pagebuf_cond_lock (not any - * pinning of underlying pages created by pagebuf_pin). - */ -void -pagebuf_unlock( /* unlock buffer */ - page_buf_t *pb) /* buffer to unlock */ -{ - ASSERT(pb->pb_flags & _PBF_LOCKABLE); - PB_CLEAR_OWNER(pb); - up(&pb->pb_sema); - PB_TRACE(pb, "unlock", 0); -} - - -/* - * Pinning Buffer Storage in Memory - */ - -/* - * pagebuf_pin - * - * pagebuf_pin locks all of the memory represented by a buffer in - * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for - * the same or different buffers affecting a given page, will - * properly count the number of outstanding "pin" requests. The - * buffer may be released after the pagebuf_pin and a different - * buffer used when calling pagebuf_unpin, if desired. - * pagebuf_pin should be used by the file system when it wants be - * assured that no attempt will be made to force the affected - * memory to disk. It does not assure that a given logical page - * will not be moved to a different physical page. - */ -void -pagebuf_pin( - page_buf_t *pb) -{ - atomic_inc(&pb->pb_pin_count); - PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter); -} - -/* - * pagebuf_unpin - * - * pagebuf_unpin reverses the locking of memory performed by - * pagebuf_pin. Note that both functions affected the logical - * pages associated with the buffer, not the buffer itself. - */ -void -pagebuf_unpin( - page_buf_t *pb) -{ - if (atomic_dec_and_test(&pb->pb_pin_count)) { - wake_up_all(&pb->pb_waiters); - } - PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter); -} - -int -pagebuf_ispin( - page_buf_t *pb) -{ - return atomic_read(&pb->pb_pin_count); -} - -/* - * pagebuf_wait_unpin - * - * pagebuf_wait_unpin waits until all of the memory associated - * with the buffer is not longer locked in memory. It returns - * immediately if none of the affected pages are locked. - */ -static inline void -_pagebuf_wait_unpin( - page_buf_t *pb) -{ - DECLARE_WAITQUEUE (wait, current); - - if (atomic_read(&pb->pb_pin_count) == 0) - return; - - add_wait_queue(&pb->pb_waiters, &wait); - for (;;) { - current->state = TASK_UNINTERRUPTIBLE; - if (atomic_read(&pb->pb_pin_count) == 0) - break; - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - schedule(); - } - remove_wait_queue(&pb->pb_waiters, &wait); - current->state = TASK_RUNNING; -} - -/* - * Buffer Utility Routines - */ - -/* - * pagebuf_iodone - * - * pagebuf_iodone marks a buffer for which I/O is in progress - * done with respect to that I/O. The pb_iodone routine, if - * present, will be called as a side-effect. - */ -void -pagebuf_iodone_work( - void *v) -{ - page_buf_t *pb = (page_buf_t *)v; - - if (pb->pb_iodone) { - (*(pb->pb_iodone)) (pb); - return; - } - - if (pb->pb_flags & PBF_ASYNC) { - if ((pb->pb_flags & _PBF_LOCKABLE) && !pb->pb_relse) - pagebuf_unlock(pb); - pagebuf_rele(pb); - } -} - -void -pagebuf_iodone( - page_buf_t *pb, - int dataio, - int schedule) -{ - pb->pb_flags &= ~(PBF_READ | PBF_WRITE); - if (pb->pb_error == 0) { - pb->pb_flags &= ~(PBF_PARTIAL | PBF_NONE); - } - - PB_TRACE(pb, "iodone", pb->pb_iodone); - - if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { - if (schedule) { - INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); - queue_work(dataio ? pagebuf_dataio_workqueue : - pagebuf_logio_workqueue, &pb->pb_iodone_work); - } else { - pagebuf_iodone_work(pb); - } - } else { - up(&pb->pb_iodonesema); - } -} - -/* - * pagebuf_ioerror - * - * pagebuf_ioerror sets the error code for a buffer. - */ -void -pagebuf_ioerror( /* mark/clear buffer error flag */ - page_buf_t *pb, /* buffer to mark */ - unsigned int error) /* error to store (0 if none) */ -{ - pb->pb_error = error; - PB_TRACE(pb, "ioerror", (unsigned long)error); -} - -/* - * pagebuf_iostart - * - * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied. - * If necessary, it will arrange for any disk space allocation required, - * and it will break up the request if the block mappings require it. - * The pb_iodone routine in the buffer supplied will only be called - * when all of the subsidiary I/O requests, if any, have been completed. - * pagebuf_iostart calls the pagebuf_ioinitiate routine or - * pagebuf_iorequest, if the former routine is not defined, to start - * the I/O on a given low-level request. - */ -int -pagebuf_iostart( /* start I/O on a buffer */ - page_buf_t *pb, /* buffer to start */ - page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */ - /* PBF_WRITE, PBF_DELWRI, */ - /* PBF_SYNC, PBF_DONT_BLOCK */ -{ - int status = 0; - - PB_TRACE(pb, "iostart", (unsigned long)flags); - - if (flags & PBF_DELWRI) { - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC); - pb->pb_flags |= flags & - (PBF_DELWRI | PBF_ASYNC | PBF_SYNC); - pagebuf_delwri_queue(pb, 1); - return status; - } - - pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_DELWRI | PBF_READ_AHEAD | PBF_RUN_QUEUES); - pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \ - PBF_SYNC | PBF_READ_AHEAD | PBF_RUN_QUEUES); - - BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL); - - /* For writes allow an alternate strategy routine to precede - * the actual I/O request (which may not be issued at all in - * a shutdown situation, for example). - */ - status = (flags & PBF_WRITE) ? - pagebuf_iostrategy(pb) : pagebuf_iorequest(pb); - - /* Wait for I/O if we are not an async request. - * Note: async I/O request completion will release the buffer, - * and that can already be done by this point. So using the - * buffer pointer from here on, after async I/O, is invalid. - */ - if (!status && !(flags & PBF_ASYNC)) - status = pagebuf_iowait(pb); - - return status; -} - -/* - * Helper routine for pagebuf_iorequest - */ - -STATIC __inline__ int -_pagebuf_iolocked( - page_buf_t *pb) -{ - ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE)); - if (pb->pb_flags & PBF_READ) - return pb->pb_locked; - return ((pb->pb_flags & _PBF_LOCKABLE) == 0); -} - -STATIC __inline__ void -_pagebuf_iodone( - page_buf_t *pb, - int schedule) -{ - if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { - pb->pb_locked = 0; - pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), schedule); - } -} - -STATIC int -bio_end_io_pagebuf( - struct bio *bio, - unsigned int bytes_done, - int error) -{ - page_buf_t *pb = (page_buf_t *)bio->bi_private; - unsigned int i, blocksize = pb->pb_target->pbr_bsize; - unsigned int sectorshift = pb->pb_target->pbr_sshift; - struct bio_vec *bvec = bio->bi_io_vec; - - if (bio->bi_size) - return 1; - - if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) - pb->pb_error = EIO; - - for (i = 0; i < bio->bi_vcnt; i++, bvec++) { - struct page *page = bvec->bv_page; - - if (pb->pb_error) { - SetPageError(page); - } else if (blocksize == PAGE_CACHE_SIZE) { - SetPageUptodate(page); - } else if (!PagePrivate(page)) { - unsigned int j, range; - - ASSERT(blocksize < PAGE_CACHE_SIZE); - range = (bvec->bv_offset + bvec->bv_len) >> sectorshift; - for (j = bvec->bv_offset >> sectorshift; j < range; j++) - set_bit(j, &page->private); - if (page->private == (unsigned long)(PAGE_CACHE_SIZE-1)) - SetPageUptodate(page); - } - - if (_pagebuf_iolocked(pb)) { - unlock_page(page); - } - } - - _pagebuf_iodone(pb, 1); - bio_put(bio); - return 0; -} - -void -_pagebuf_ioapply( - page_buf_t *pb) -{ - int i, map_i, total_nr_pages, nr_pages; - struct bio *bio; - int offset = pb->pb_offset; - int size = pb->pb_count_desired; - sector_t sector = pb->pb_bn; - unsigned int blocksize = pb->pb_target->pbr_bsize; - int locking = _pagebuf_iolocked(pb); - - total_nr_pages = pb->pb_page_count; - map_i = 0; - - /* Special code path for reading a sub page size pagebuf in -- - * we populate up the whole page, and hence the other metadata - * in the same page. This optimization is only valid when the - * filesystem block size and the page size are equal. - */ - if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) && - (pb->pb_flags & PBF_READ) && locking && - (blocksize == PAGE_CACHE_SIZE)) { - bio = bio_alloc(GFP_NOIO, 1); - - bio->bi_bdev = pb->pb_target->pbr_bdev; - bio->bi_sector = sector - (offset >> BBSHIFT); - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; - - bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0); - size = 0; - - atomic_inc(&pb->pb_io_remaining); - - goto submit_io; - } - - /* Lock down the pages which we need to for the request */ - if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) { - for (i = 0; size; i++) { - int nbytes = PAGE_CACHE_SIZE - offset; - struct page *page = pb->pb_pages[i]; - - if (nbytes > size) - nbytes = size; - - lock_page(page); - - size -= nbytes; - offset = 0; - } - offset = pb->pb_offset; - size = pb->pb_count_desired; - } - -next_chunk: - atomic_inc(&pb->pb_io_remaining); - nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); - if (nr_pages > total_nr_pages) - nr_pages = total_nr_pages; - - bio = bio_alloc(GFP_NOIO, nr_pages); - bio->bi_bdev = pb->pb_target->pbr_bdev; - bio->bi_sector = sector; - bio->bi_end_io = bio_end_io_pagebuf; - bio->bi_private = pb; - - for (; size && nr_pages; nr_pages--, map_i++) { - int nbytes = PAGE_CACHE_SIZE - offset; - - if (nbytes > size) - nbytes = size; - - if (bio_add_page(bio, pb->pb_pages[map_i], - nbytes, offset) < nbytes) - break; - - offset = 0; - sector += nbytes >> BBSHIFT; - size -= nbytes; - total_nr_pages--; - } - -submit_io: - if (likely(bio->bi_size)) { - submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio); - if (size) - goto next_chunk; - } else { - bio_put(bio); - pagebuf_ioerror(pb, EIO); - } - - if (pb->pb_flags & PBF_RUN_QUEUES) { - pb->pb_flags &= ~PBF_RUN_QUEUES; - if (atomic_read(&pb->pb_io_remaining) > 1) - blk_run_queues(); - } -} - -/* - * pagebuf_iorequest - * - * pagebuf_iorequest is the core I/O request routine. - * It assumes that the buffer is well-formed and - * mapped and ready for physical I/O, unlike - * pagebuf_iostart() and pagebuf_iophysio(). Those - * routines call the pagebuf_ioinitiate routine to start I/O, - * if it is present, or else call pagebuf_iorequest() - * directly if the pagebuf_ioinitiate routine is not present. - * - * This function will be responsible for ensuring access to the - * pages is restricted whilst I/O is in progress - for locking - * pagebufs the pagebuf lock is the mediator, for non-locking - * pagebufs the pages will be locked. In the locking case we - * need to use the pagebuf lock as multiple meta-data buffers - * will reference the same page. - */ -int -pagebuf_iorequest( /* start real I/O */ - page_buf_t *pb) /* buffer to convey to device */ -{ - PB_TRACE(pb, "iorequest", 0); - - if (pb->pb_flags & PBF_DELWRI) { - pagebuf_delwri_queue(pb, 1); - return 0; - } - - if (pb->pb_flags & PBF_WRITE) { - _pagebuf_wait_unpin(pb); - } - - pagebuf_hold(pb); - - /* Set the count to 1 initially, this will stop an I/O - * completion callout which happens before we have started - * all the I/O from calling pagebuf_iodone too early. - */ - atomic_set(&pb->pb_io_remaining, 1); - _pagebuf_ioapply(pb); - _pagebuf_iodone(pb, 0); - - pagebuf_rele(pb); - return 0; -} - -/* - * pagebuf_iowait - * - * pagebuf_iowait waits for I/O to complete on the buffer supplied. - * It returns immediately if no I/O is pending. In any case, it returns - * the error code, if any, or 0 if there is no error. - */ -int -pagebuf_iowait( - page_buf_t *pb) -{ - PB_TRACE(pb, "iowait", 0); - if (atomic_read(&pb->pb_io_remaining)) - blk_run_queues(); - down(&pb->pb_iodonesema); - PB_TRACE(pb, "iowaited", (long)pb->pb_error); - return pb->pb_error; -} - -STATIC void * -pagebuf_mapout_locked( - page_buf_t *pb) -{ - void *old_addr = NULL; - - if (pb->pb_flags & PBF_MAPPED) { - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) - old_addr = pb->pb_addr - pb->pb_offset; - pb->pb_addr = NULL; - pb->pb_flags &= ~(PBF_MAPPED | _PBF_ADDR_ALLOCATED); - } - - return old_addr; /* Caller must free the address space, - * we are under a spin lock, probably - * not safe to do vfree here - */ -} - -caddr_t -pagebuf_offset( - page_buf_t *pb, - size_t offset) -{ - struct page *page; - - offset += pb->pb_offset; - - page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT]; - return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1)); -} - -/* - * pagebuf_iomove - * - * Move data into or out of a buffer. - */ -void -pagebuf_iomove( - page_buf_t *pb, /* buffer to process */ - size_t boff, /* starting buffer offset */ - size_t bsize, /* length to copy */ - caddr_t data, /* data address */ - page_buf_rw_t mode) /* read/write flag */ -{ - size_t bend, cpoff, csize; - struct page *page; - - bend = boff + bsize; - while (boff < bend) { - page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)]; - cpoff = page_buf_poff(boff + pb->pb_offset); - csize = min_t(size_t, - PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff); - - ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); - - switch (mode) { - case PBRW_ZERO: - memset(page_address(page) + cpoff, 0, csize); - break; - case PBRW_READ: - memcpy(data, page_address(page) + cpoff, csize); - break; - case PBRW_WRITE: - memcpy(page_address(page) + cpoff, data, csize); - } - - boff += csize; - data += csize; - } -} - - -/* - * Pagebuf delayed write buffer handling - */ - -STATIC int pbd_active = 1; -STATIC LIST_HEAD(pbd_delwrite_queue); -STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; - -STATIC void -pagebuf_delwri_queue( - page_buf_t *pb, - int unlock) -{ - PB_TRACE(pb, "delwri_q", (long)unlock); - spin_lock(&pbd_delwrite_lock); - /* If already in the queue, dequeue and place at tail */ - if (!list_empty(&pb->pb_list)) { - if (unlock) { - atomic_dec(&pb->pb_hold); - } - list_del(&pb->pb_list); - } - - list_add_tail(&pb->pb_list, &pbd_delwrite_queue); - pb->pb_flushtime = jiffies + pb_params.age_buffer.val; - spin_unlock(&pbd_delwrite_lock); - - if (unlock && (pb->pb_flags & _PBF_LOCKABLE)) { - pagebuf_unlock(pb); - } -} - -void -pagebuf_delwri_dequeue( - page_buf_t *pb) -{ - PB_TRACE(pb, "delwri_uq", 0); - spin_lock(&pbd_delwrite_lock); - list_del_init(&pb->pb_list); - pb->pb_flags &= ~PBF_DELWRI; - spin_unlock(&pbd_delwrite_lock); -} - -STATIC void -pagebuf_runall_queues( - struct workqueue_struct *queue) -{ - flush_workqueue(queue); -} - -/* Defines for pagebuf daemon */ -DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); -STATIC int force_flush; - -STATIC void -pagebuf_daemon_wakeup( - int flag) -{ - force_flush = flag; - if (waitqueue_active(&pbd_waitq)) { - wake_up_interruptible(&pbd_waitq); - } -} - -typedef void (*timeout_fn)(unsigned long); - -STATIC int -pagebuf_daemon( - void *data) -{ - int count; - page_buf_t *pb; - struct list_head *curr, *next, tmp; - struct timer_list pb_daemon_timer = - TIMER_INITIALIZER((timeout_fn)pagebuf_daemon_wakeup, 0, 0); - - /* Set up the thread */ - daemonize("pagebufd"); - - current->flags |= PF_MEMALLOC; - - INIT_LIST_HEAD(&tmp); - do { - /* swsusp */ - if (current->flags & PF_FREEZE) - refrigerator(PF_IOTHREAD); - - if (pbd_active == 1) { - mod_timer(&pb_daemon_timer, - jiffies + pb_params.flush_interval.val); - interruptible_sleep_on(&pbd_waitq); - } - - if (pbd_active == 0) { - del_timer_sync(&pb_daemon_timer); - } - - spin_lock(&pbd_delwrite_lock); - - count = 0; - list_for_each_safe(curr, next, &pbd_delwrite_queue) { - pb = list_entry(curr, page_buf_t, pb_list); - - PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb)); - - if ((pb->pb_flags & PBF_DELWRI) && !pagebuf_ispin(pb) && - (((pb->pb_flags & _PBF_LOCKABLE) == 0) || - !pagebuf_cond_lock(pb))) { - - if (!force_flush && - time_before(jiffies, pb->pb_flushtime)) { - pagebuf_unlock(pb); - break; - } - - pb->pb_flags &= ~PBF_DELWRI; - pb->pb_flags |= PBF_WRITE; - - list_del(&pb->pb_list); - list_add(&pb->pb_list, &tmp); - - count++; - } - } - - spin_unlock(&pbd_delwrite_lock); - while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, page_buf_t, pb_list); - list_del_init(&pb->pb_list); - - pagebuf_iostrategy(pb); - } - - if (as_list_len > 0) - purge_addresses(); - if (count) - blk_run_queues(); - - force_flush = 0; - } while (pbd_active == 1); - - pbd_active = -1; - wake_up_interruptible(&pbd_waitq); - - return 0; -} - -void -pagebuf_delwri_flush( - pb_target_t *target, - u_long flags, - int *pinptr) -{ - page_buf_t *pb; - struct list_head *curr, *next, tmp; - int pincount = 0; - int flush_cnt = 0; - - pagebuf_runall_queues(pagebuf_dataio_workqueue); - pagebuf_runall_queues(pagebuf_logio_workqueue); - - spin_lock(&pbd_delwrite_lock); - INIT_LIST_HEAD(&tmp); - - list_for_each_safe(curr, next, &pbd_delwrite_queue) { - pb = list_entry(curr, page_buf_t, pb_list); - - /* - * Skip other targets, markers and in progress buffers - */ - - if ((pb->pb_flags == 0) || (pb->pb_target != target) || - !(pb->pb_flags & PBF_DELWRI)) { - continue; - } - - PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb)); - if (pagebuf_ispin(pb)) { - pincount++; - continue; - } - - pb->pb_flags &= ~PBF_DELWRI; - pb->pb_flags |= PBF_WRITE; - list_move(&pb->pb_list, &tmp); - } - /* ok found all the items that can be worked on - * drop the lock and process the private list */ - spin_unlock(&pbd_delwrite_lock); - - list_for_each_safe(curr, next, &tmp) { - pb = list_entry(curr, page_buf_t, pb_list); - - if (flags & PBDF_WAIT) - pb->pb_flags &= ~PBF_ASYNC; - else - list_del_init(curr); - - pagebuf_lock(pb); - pagebuf_iostrategy(pb); - if (++flush_cnt > 32) { - blk_run_queues(); - flush_cnt = 0; - } - } - - blk_run_queues(); - - while (!list_empty(&tmp)) { - pb = list_entry(tmp.next, page_buf_t, pb_list); - - list_del_init(&pb->pb_list); - pagebuf_iowait(pb); - if (!pb->pb_relse) - pagebuf_unlock(pb); - pagebuf_rele(pb); - } - - if (pinptr) - *pinptr = pincount; -} - -STATIC int -pagebuf_daemon_start(void) -{ - int rval; - - pagebuf_logio_workqueue = create_workqueue("xfslogd"); - if (!pagebuf_logio_workqueue) - return -ENOMEM; - - pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); - if (!pagebuf_dataio_workqueue) { - destroy_workqueue(pagebuf_logio_workqueue); - return -ENOMEM; - } - - rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); - if (rval < 0) { - destroy_workqueue(pagebuf_logio_workqueue); - destroy_workqueue(pagebuf_dataio_workqueue); - } - - return rval; -} - -/* - * pagebuf_daemon_stop - * - * Note: do not mark as __exit, it is called from pagebuf_terminate. - */ -STATIC void -pagebuf_daemon_stop(void) -{ - pbd_active = 0; - wake_up_interruptible(&pbd_waitq); - wait_event_interruptible(pbd_waitq, pbd_active); - destroy_workqueue(pagebuf_logio_workqueue); - destroy_workqueue(pagebuf_dataio_workqueue); -} - - -/* - * Pagebuf sysctl interface - */ - -STATIC int -pb_stats_clear_handler( - ctl_table *ctl, - int write, - struct file *filp, - void *buffer, - size_t *lenp) -{ - int c, ret; - int *valp = ctl->data; - - ret = proc_dointvec_minmax(ctl, write, filp, buffer, lenp); - - if (!ret && write && *valp) { - printk("XFS Clearing pbstats\n"); - for (c = 0; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; - memset(&per_cpu(pbstats, c), 0, - sizeof(struct pbstats)); - } - pb_params.stats_clear.val = 0; - } - - return ret; -} - -STATIC struct ctl_table_header *pagebuf_table_header; - -STATIC ctl_table pagebuf_table[] = { - {PB_FLUSH_INT, "flush_int", &pb_params.flush_interval.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.flush_interval.min, &pb_params.flush_interval.max}, - - {PB_FLUSH_AGE, "flush_age", &pb_params.age_buffer.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.age_buffer.min, &pb_params.age_buffer.max}, - - {PB_STATS_CLEAR, "stats_clear", &pb_params.stats_clear.val, - sizeof(int), 0644, NULL, &pb_stats_clear_handler, - &sysctl_intvec, NULL, - &pb_params.stats_clear.min, &pb_params.stats_clear.max}, - -#ifdef PAGEBUF_TRACE - {PB_DEBUG, "debug", &pb_params.debug.val, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, - &sysctl_intvec, NULL, - &pb_params.debug.min, &pb_params.debug.max}, -#endif - {0} -}; - -STATIC ctl_table pagebuf_dir_table[] = { - {VM_PAGEBUF, "pagebuf", NULL, 0, 0555, pagebuf_table}, - {0} -}; - -STATIC ctl_table pagebuf_root_table[] = { - {CTL_VM, "vm", NULL, 0, 0555, pagebuf_dir_table}, - {0} -}; - -#ifdef CONFIG_PROC_FS -STATIC int -pagebuf_readstats( - char *buffer, - char **start, - off_t offset, - int count, - int *eof, - void *data) -{ - int c, i, len, val; - - len = 0; - len += sprintf(buffer + len, "pagebuf"); - for (i = 0; i < sizeof(struct pbstats) / sizeof(u_int32_t); i++) { - val = 0; - for (c = 0 ; c < NR_CPUS; c++) { - if (!cpu_possible(c)) continue; - val += *(((u_int32_t*)&per_cpu(pbstats, c) + i)); - } - len += sprintf(buffer + len, " %u", val); - } - buffer[len++] = '\n'; - - if (offset >= len) { - *start = buffer; - *eof = 1; - return 0; - } - *start = buffer + offset; - if ((len -= offset) > count) - return count; - *eof = 1; - - return len; -} -#endif /* CONFIG_PROC_FS */ - -/* - * Initialization and Termination - */ - -int __init -pagebuf_init(void) -{ - int i; - - pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1); - -#ifdef CONFIG_PROC_FS - if (proc_mkdir("fs/pagebuf", 0)) - create_proc_read_entry( - "fs/pagebuf/stat", 0, 0, pagebuf_readstats, NULL); -#endif - - pagebuf_cache = kmem_cache_create("page_buf_t", sizeof(page_buf_t), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (pagebuf_cache == NULL) { - printk("pagebuf: couldn't init pagebuf cache\n"); - pagebuf_terminate(); - return -ENOMEM; - } - - for (i = 0; i < NHASH; i++) { - spin_lock_init(&pbhash[i].pb_hash_lock); - INIT_LIST_HEAD(&pbhash[i].pb_hash); - } - -#ifdef PAGEBUF_TRACE - pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP); -#endif - - pagebuf_daemon_start(); - return 0; -} - - -/* - * pagebuf_terminate. - * - * Note: do not mark as __exit, this is also called from the __init code. - */ -void -pagebuf_terminate(void) -{ - pagebuf_daemon_stop(); - - kmem_cache_destroy(pagebuf_cache); - - unregister_sysctl_table(pagebuf_table_header); -#ifdef CONFIG_PROC_FS - remove_proc_entry("fs/pagebuf/stat", NULL); - remove_proc_entry("fs/pagebuf", NULL); -#endif -} - - -/* - * Module management (for kernel debugger module) - */ -EXPORT_SYMBOL(pagebuf_offset); -#ifdef DEBUG -EXPORT_SYMBOL(pbd_delwrite_queue); -#endif diff --git a/fs/xfs/pagebuf/page_buf.h b/fs/xfs/pagebuf/page_buf.h deleted file mode 100644 index ef7895f0904a..000000000000 --- a/fs/xfs/pagebuf/page_buf.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -/* - * Written by Steve Lord, Jim Mostek, Russell Cattelan at SGI - */ - -#ifndef __PAGE_BUF_H__ -#define __PAGE_BUF_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Base types - */ - -/* daddr must be signed since -1 is used for bmaps that are not yet allocated */ -typedef loff_t page_buf_daddr_t; - -#define PAGE_BUF_DADDR_NULL ((page_buf_daddr_t) (-1LL)) - -#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE) -#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) -#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT) -#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK) - -typedef enum page_buf_rw_e { - PBRW_READ = 1, /* transfer into target memory */ - PBRW_WRITE = 2, /* transfer from target memory */ - PBRW_ZERO = 3 /* Zero target memory */ -} page_buf_rw_t; - - -typedef enum page_buf_flags_e { /* pb_flags values */ - PBF_READ = (1 << 0), /* buffer intended for reading from device */ - PBF_WRITE = (1 << 1), /* buffer intended for writing to device */ - PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */ - PBF_PARTIAL = (1 << 3), /* buffer partially read */ - PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ - PBF_NONE = (1 << 5), /* buffer not read at all */ - PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ - PBF_FREED = (1 << 7), /* buffer has been freed and is invalid */ - PBF_SYNC = (1 << 8), /* force updates to disk */ - PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ - PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ - PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */ - PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */ - - /* flags used only as arguments to access routines */ - PBF_LOCK = (1 << 13), /* lock requested */ - PBF_TRYLOCK = (1 << 14), /* lock requested, but do not wait */ - PBF_DONT_BLOCK = (1 << 15), /* do not block in current thread */ - - /* flags used only internally */ - _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ - _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ - _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ - _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ - _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */ - _PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated */ - - PBF_FORCEIO = (1 << 22), /* ignore any cache state */ - PBF_FLUSH = (1 << 23), /* flush disk write cache */ - PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead */ - PBF_RUN_QUEUES = (1 << 25), /* run block device task queue */ - -} page_buf_flags_t; - -#define PBF_UPDATE (PBF_READ | PBF_WRITE) -#define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0) -#define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0) - -typedef struct pb_target { - dev_t pbr_dev; - struct block_device *pbr_bdev; - struct address_space *pbr_mapping; - unsigned int pbr_bsize; - unsigned int pbr_sshift; - size_t pbr_smask; -} pb_target_t; - -/* - * page_buf_t: Buffer structure for page cache-based buffers - * - * This buffer structure is used by the page cache buffer management routines - * to refer to an assembly of pages forming a logical buffer. The actual - * I/O is performed with buffer_head or bio structures, as required by drivers, - * for drivers which do not understand this structure. The buffer structure is - * used on temporary basis only, and discarded when released. - * - * The real data storage is recorded in the page cache. Metadata is - * hashed to the inode for the block device on which the file system resides. - * File data is hashed to the inode for the file. Pages which are only - * partially filled with data have bits set in their block_map entry - * to indicate which disk blocks in the page are not valid. - */ - -struct page_buf_s; -typedef void (*page_buf_iodone_t)(struct page_buf_s *); - /* call-back function on I/O completion */ -typedef void (*page_buf_relse_t)(struct page_buf_s *); - /* call-back function on I/O completion */ -typedef int (*page_buf_bdstrat_t)(struct page_buf_s *); - -#define PB_PAGES 4 - -typedef struct page_buf_s { - struct semaphore pb_sema; /* semaphore for lockables */ - unsigned long pb_flushtime; /* time to flush pagebuf */ - atomic_t pb_pin_count; /* pin count */ - wait_queue_head_t pb_waiters; /* unpin waiters */ - struct list_head pb_list; - page_buf_flags_t pb_flags; /* status flags */ - struct list_head pb_hash_list; - struct pb_target *pb_target; /* logical object */ - atomic_t pb_hold; /* reference count */ - page_buf_daddr_t pb_bn; /* block number for I/O */ - loff_t pb_file_offset; /* offset in file */ - size_t pb_buffer_length; /* size of buffer in bytes */ - size_t pb_count_desired; /* desired transfer size */ - void *pb_addr; /* virtual address of buffer */ - struct work_struct pb_iodone_work; - atomic_t pb_io_remaining;/* #outstanding I/O requests */ - page_buf_iodone_t pb_iodone; /* I/O completion function */ - page_buf_relse_t pb_relse; /* releasing function */ - page_buf_bdstrat_t pb_strat; /* pre-write function */ - struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */ - void *pb_fspriv; - void *pb_fspriv2; - void *pb_fspriv3; - unsigned short pb_error; /* error code on I/O */ - unsigned short pb_page_count; /* size of page array */ - unsigned short pb_offset; /* page offset in first page */ - unsigned char pb_locked; /* page array is locked */ - unsigned char pb_hash_index; /* hash table index */ - struct page **pb_pages; /* array of page pointers */ - struct page *pb_page_array[PB_PAGES]; /* inline pages */ -#ifdef PAGEBUF_LOCK_TRACKING - int pb_last_holder; -#endif -} page_buf_t; - - -/* Finding and Reading Buffers */ - -extern page_buf_t *pagebuf_find( /* find buffer for block if */ - /* the block is in memory */ - struct pb_target *, /* inode for block */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK */ - -extern page_buf_t *pagebuf_get( /* allocate a buffer */ - struct pb_target *, /* inode for buffer */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ - /* PBF_ASYNC */ - -extern page_buf_t *pagebuf_lookup( - struct pb_target *, - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ - /* PBF_FORCEIO, _PBF_LOCKABLE */ - -extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ - /* no memory or disk address */ - size_t len, - struct pb_target *); /* mount point "fake" inode */ - -extern page_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */ - /* without disk address */ - size_t len, - struct pb_target *); /* mount point "fake" inode */ - -extern int pagebuf_associate_memory( - page_buf_t *, - void *, - size_t); - -extern void pagebuf_hold( /* increment reference count */ - page_buf_t *); /* buffer to hold */ - -extern void pagebuf_readahead( /* read ahead into cache */ - struct pb_target *, /* target for buffer (or NULL) */ - loff_t, /* starting offset of range */ - size_t, /* length of range */ - page_buf_flags_t); /* additional read flags */ - -/* Releasing Buffers */ - -extern void pagebuf_free( /* deallocate a buffer */ - page_buf_t *); /* buffer to deallocate */ - -extern void pagebuf_rele( /* release hold on a buffer */ - page_buf_t *); /* buffer to release */ - -/* Locking and Unlocking Buffers */ - -extern int pagebuf_cond_lock( /* lock buffer, if not locked */ - /* (returns -EBUSY if locked) */ - page_buf_t *); /* buffer to lock */ - -extern int pagebuf_lock_value( /* return count on lock */ - page_buf_t *); /* buffer to check */ - -extern int pagebuf_lock( /* lock buffer */ - page_buf_t *); /* buffer to lock */ - -extern void pagebuf_unlock( /* unlock buffer */ - page_buf_t *); /* buffer to unlock */ - -/* Buffer Read and Write Routines */ - -extern void pagebuf_iodone( /* mark buffer I/O complete */ - page_buf_t *, /* buffer to mark */ - int, /* use data/log helper thread. */ - int); /* run completion locally, or in - * a helper thread. */ - -extern void pagebuf_ioerror( /* mark buffer in error (or not) */ - page_buf_t *, /* buffer to mark */ - unsigned int); /* error to store (0 if none) */ - -extern int pagebuf_iostart( /* start I/O on a buffer */ - page_buf_t *, /* buffer to start */ - page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */ - /* PBF_READ, PBF_WRITE, */ - /* PBF_DELWRI, PBF_SYNC */ - -extern int pagebuf_iorequest( /* start real I/O */ - page_buf_t *); /* buffer to convey to device */ - -extern int pagebuf_iowait( /* wait for buffer I/O done */ - page_buf_t *); /* buffer to wait on */ - -extern void pagebuf_iomove( /* move data in/out of pagebuf */ - page_buf_t *, /* buffer to manipulate */ - size_t, /* starting buffer offset */ - size_t, /* length in buffer */ - caddr_t, /* data pointer */ - page_buf_rw_t); /* direction */ - -static inline int pagebuf_iostrategy(page_buf_t *pb) -{ - return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb); -} - -static inline int pagebuf_geterror(page_buf_t *pb) -{ - return pb ? pb->pb_error : ENOMEM; -} - -/* Buffer Utility Routines */ - -extern caddr_t pagebuf_offset( /* pointer at offset in buffer */ - page_buf_t *, /* buffer to offset into */ - size_t); /* offset */ - -/* Pinning Buffer Storage in Memory */ - -extern void pagebuf_pin( /* pin buffer in memory */ - page_buf_t *); /* buffer to pin */ - -extern void pagebuf_unpin( /* unpin buffered data */ - page_buf_t *); /* buffer to unpin */ - -extern int pagebuf_ispin( /* check if buffer is pinned */ - page_buf_t *); /* buffer to check */ - -/* Delayed Write Buffer Routines */ - -#define PBDF_WAIT 0x01 -extern void pagebuf_delwri_flush( - pb_target_t *, - unsigned long, - int *); - -extern void pagebuf_delwri_dequeue( - page_buf_t *); - -/* Buffer Daemon Setup Routines */ - -extern int pagebuf_init(void); -extern void pagebuf_terminate(void); - - -#ifdef PAGEBUF_TRACE -extern ktrace_t *pagebuf_trace_buf; -extern void pagebuf_trace( - page_buf_t *, /* buffer being traced */ - char *, /* description of operation */ - void *, /* arbitrary diagnostic value */ - void *); /* return address */ -#else -# define pagebuf_trace(pb, id, ptr, ra) do { } while (0) -#endif - -#define pagebuf_target_name(target) \ - ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; }) - -#endif /* __PAGE_BUF_H__ */ diff --git a/fs/xfs/support/kmem.h b/fs/xfs/support/kmem.h deleted file mode 100644 index a8fb09f2f604..000000000000 --- a/fs/xfs/support/kmem.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_KMEM_H__ -#define __XFS_SUPPORT_KMEM_H__ - -#include -#include -#include -#include - -/* - * Cutoff point to use vmalloc instead of kmalloc. - */ -#define MAX_SLAB_SIZE 0x10000 - -/* - * XFS uses slightly different names for these due to the - * IRIX heritage. - */ -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t - -#define KM_SLEEP 0x0001 -#define KM_NOSLEEP 0x0002 -#define KM_NOFS 0x0004 - -typedef unsigned long xfs_pflags_t; - -#define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) - -#define PFLAGS_SET_FSTRANS(STATEP) do { \ - *(STATEP) = current->flags; \ - current->flags |= PF_FSTRANS; \ -} while (0) - -#define PFLAGS_RESTORE(STATEP) do { \ - current->flags = *(STATEP); \ -} while (0) - -#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ - *(NSTATEP) = *(OSTATEP); \ -} while (0) - -/* - * XXX get rid of the unconditional __GFP_NOFAIL by adding - * a KM_FAIL flag and using it where we're allowed to fail. - */ -static __inline unsigned int -kmem_flags_convert(int flags) -{ - int lflags; - -#if DEBUG - if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) { - printk(KERN_WARNING - "XFS: memory allocation with wrong flags (%x)\n", flags); - BUG(); - } -#endif - - lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL); - - /* avoid recusive callbacks to filesystem during transactions */ - if (PFLAGS_TEST_FSTRANS()) - lflags &= ~__GFP_FS; - - return lflags; -} - -static __inline void * -kmem_alloc(size_t size, int flags) -{ - if (unlikely(MAX_SLAB_SIZE < size)) - /* Avoid doing filesystem sensitive stuff to get this */ - return __vmalloc(size, kmem_flags_convert(flags), PAGE_KERNEL); - return kmalloc(size, kmem_flags_convert(flags)); -} - -static __inline void * -kmem_zalloc(size_t size, int flags) -{ - void *ptr = kmem_alloc(size, flags); - if (likely(ptr != NULL)) - memset(ptr, 0, size); - return ptr; -} - -static __inline void -kmem_free(void *ptr, size_t size) -{ - if (unlikely((unsigned long)ptr < VMALLOC_START || - (unsigned long)ptr >= VMALLOC_END)) - kfree(ptr); - else - vfree(ptr); -} - -static __inline void * -kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags) -{ - void *new = kmem_alloc(newsize, flags); - - if (likely(ptr != NULL)) { - if (likely(new != NULL)) - memcpy(new, ptr, min(oldsize, newsize)); - kmem_free(ptr, oldsize); - } - - return new; -} - -static __inline kmem_zone_t * -kmem_zone_init(int size, char *zone_name) -{ - return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL); -} - -static __inline void * -kmem_zone_alloc(kmem_zone_t *zone, int flags) -{ - return kmem_cache_alloc(zone, kmem_flags_convert(flags)); -} - -static __inline void * -kmem_zone_zalloc(kmem_zone_t *zone, int flags) -{ - void *ptr = kmem_zone_alloc(zone, flags); - if (likely(ptr != NULL)) - memset(ptr, 0, kmem_cache_size(zone)); - return ptr; -} - -static __inline void -kmem_zone_free(kmem_zone_t *zone, void *ptr) -{ - kmem_cache_free(zone, ptr); -} - -typedef struct shrinker *kmem_shaker_t; -typedef int (*kmem_shake_func_t)(int, unsigned int); - -static __inline kmem_shaker_t -kmem_shake_register(kmem_shake_func_t sfunc) -{ - return set_shrinker(DEFAULT_SEEKS, sfunc); -} - -static __inline void -kmem_shake_deregister(kmem_shaker_t shrinker) -{ - remove_shrinker(shrinker); -} - -static __inline int -kmem_shake_allow(unsigned int gfp_mask) -{ - return (gfp_mask & __GFP_WAIT); -} - -#endif /* __XFS_SUPPORT_KMEM_H__ */ diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c index ad4033e14614..e776812da8bc 100644 --- a/fs/xfs/support/ktrace.c +++ b/fs/xfs/support/ktrace.c @@ -35,8 +35,8 @@ #include #include -#include "kmem.h" -#include "spin.h" +#include +#include #include "debug.h" #include "ktrace.h" diff --git a/fs/xfs/support/ktrace.h b/fs/xfs/support/ktrace.h index b566ef8fa756..92d1a1a5d04b 100644 --- a/fs/xfs/support/ktrace.h +++ b/fs/xfs/support/ktrace.h @@ -32,7 +32,7 @@ #ifndef __XFS_SUPPORT_KTRACE_H__ #define __XFS_SUPPORT_KTRACE_H__ -#include +#include /* * Trace buffer entry structure. diff --git a/fs/xfs/support/mrlock.c b/fs/xfs/support/mrlock.c deleted file mode 100644 index 5b5dae97af9c..000000000000 --- a/fs/xfs/support/mrlock.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include -#include -#include -#include -#include - -#include "mrlock.h" - - -#if USE_RW_WAIT_QUEUE_SPINLOCK -# define wq_write_lock write_lock -#else -# define wq_write_lock spin_lock -#endif - -/* - * We don't seem to need lock_type (only one supported), name, or - * sequence. But, XFS will pass it so let's leave them here for now. - */ -/* ARGSUSED */ -void -mrlock_init(mrlock_t *mrp, int lock_type, char *name, long sequence) -{ - mrp->mr_count = 0; - mrp->mr_reads_waiting = 0; - mrp->mr_writes_waiting = 0; - init_waitqueue_head(&mrp->mr_readerq); - init_waitqueue_head(&mrp->mr_writerq); - mrp->mr_lock = SPIN_LOCK_UNLOCKED; -} - -/* - * Macros to lock/unlock the mrlock_t. - */ - -#define MRLOCK(m) spin_lock(&(m)->mr_lock); -#define MRUNLOCK(m) spin_unlock(&(m)->mr_lock); - - -/* - * lock_wait should never be called in an interrupt thread. - * - * mrlocks can sleep (i.e. call schedule) and so they can't ever - * be called from an interrupt thread. - * - * threads that wake-up should also never be invoked from interrupt threads. - * - * But, waitqueue_lock is locked from interrupt threads - and we are - * called with interrupts disabled, so it is all OK. - */ - -/* ARGSUSED */ -void -lock_wait(wait_queue_head_t *q, spinlock_t *lock, int rw) -{ - DECLARE_WAITQUEUE( wait, current ); - - __set_current_state(TASK_UNINTERRUPTIBLE); - - spin_lock(&q->lock); - if (rw) { - __add_wait_queue_tail(q, &wait); - } else { - __add_wait_queue(q, &wait); - } - - spin_unlock(&q->lock); - spin_unlock(lock); - - schedule(); - - spin_lock(&q->lock); - __remove_wait_queue(q, &wait); - spin_unlock(&q->lock); - - spin_lock(lock); - - /* return with lock held */ -} - -/* ARGSUSED */ -void -mrfree(mrlock_t *mrp) -{ -} - -/* ARGSUSED */ -void -mrlock(mrlock_t *mrp, int type, int flags) -{ - if (type == MR_ACCESS) - mraccess(mrp); - else - mrupdate(mrp); -} - -/* ARGSUSED */ -void -mraccessf(mrlock_t *mrp, int flags) -{ - MRLOCK(mrp); - if(mrp->mr_writes_waiting > 0) { - mrp->mr_reads_waiting++; - lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); - mrp->mr_reads_waiting--; - } - while (mrp->mr_count < 0) { - mrp->mr_reads_waiting++; - lock_wait(&mrp->mr_readerq, &mrp->mr_lock, 0); - mrp->mr_reads_waiting--; - } - mrp->mr_count++; - MRUNLOCK(mrp); -} - -/* ARGSUSED */ -void -mrupdatef(mrlock_t *mrp, int flags) -{ - MRLOCK(mrp); - while(mrp->mr_count) { - mrp->mr_writes_waiting++; - lock_wait(&mrp->mr_writerq, &mrp->mr_lock, 1); - mrp->mr_writes_waiting--; - } - - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); -} - -int -mrtryaccess(mrlock_t *mrp) -{ - MRLOCK(mrp); - /* - * If anyone is waiting for update access or the lock is held for update - * fail the request. - */ - if(mrp->mr_writes_waiting > 0 || mrp->mr_count < 0) { - MRUNLOCK(mrp); - return 0; - } - mrp->mr_count++; - MRUNLOCK(mrp); - return 1; -} - -int -mrtrypromote(mrlock_t *mrp) -{ - MRLOCK(mrp); - - if(mrp->mr_count == 1) { /* We are the only thread with the lock */ - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); - return 1; - } - - MRUNLOCK(mrp); - return 0; -} - -int -mrtryupdate(mrlock_t *mrp) -{ - MRLOCK(mrp); - - if(mrp->mr_count) { - MRUNLOCK(mrp); - return 0; - } - - mrp->mr_count = -1; /* writer on it */ - MRUNLOCK(mrp); - return 1; -} - -static __inline__ void mrwake(mrlock_t *mrp) -{ - /* - * First, if the count is now 0, we need to wake-up anyone waiting. - */ - if (!mrp->mr_count) { - if (mrp->mr_writes_waiting) { /* Wake-up first writer waiting */ - wake_up(&mrp->mr_writerq); - } else if (mrp->mr_reads_waiting) { /* Wakeup any readers waiting */ - wake_up(&mrp->mr_readerq); - } - } -} - -void -mraccunlock(mrlock_t *mrp) -{ - MRLOCK(mrp); - mrp->mr_count--; - mrwake(mrp); - MRUNLOCK(mrp); -} - -void -mrunlock(mrlock_t *mrp) -{ - MRLOCK(mrp); - if (mrp->mr_count < 0) { - mrp->mr_count = 0; - } else { - mrp->mr_count--; - } - mrwake(mrp); - MRUNLOCK(mrp); -} - -int -ismrlocked(mrlock_t *mrp, int type) /* No need to lock since info can change */ -{ - if (type == MR_ACCESS) - return (mrp->mr_count > 0); /* Read lock */ - else if (type == MR_UPDATE) - return (mrp->mr_count < 0); /* Write lock */ - else if (type == (MR_UPDATE | MR_ACCESS)) - return (mrp->mr_count); /* Any type of lock held */ - else /* Any waiters */ - return (mrp->mr_reads_waiting | mrp->mr_writes_waiting); -} - -/* - * Demote from update to access. We better be the only thread with the - * lock in update mode so it should be easy to set to 1. - * Wake-up any readers waiting. - */ - -void -mrdemote(mrlock_t *mrp) -{ - MRLOCK(mrp); - mrp->mr_count = 1; - if (mrp->mr_reads_waiting) { /* Wakeup all readers waiting */ - wake_up(&mrp->mr_readerq); - } - MRUNLOCK(mrp); -} diff --git a/fs/xfs/support/mrlock.h b/fs/xfs/support/mrlock.h deleted file mode 100644 index b2a7b3ad5eff..000000000000 --- a/fs/xfs/support/mrlock.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_MRLOCK_H__ -#define __XFS_SUPPORT_MRLOCK_H__ - -#include -#include -#include -#include - -/* - * Implement mrlocks on Linux that work for XFS. - * - * These are sleep locks and not spinlocks. If one wants read/write spinlocks, - * use read_lock, write_lock, ... see spinlock.h. - */ - -typedef struct mrlock_s { - int mr_count; - unsigned short mr_reads_waiting; - unsigned short mr_writes_waiting; - wait_queue_head_t mr_readerq; - wait_queue_head_t mr_writerq; - spinlock_t mr_lock; -} mrlock_t; - -#define MR_ACCESS 1 -#define MR_UPDATE 2 - -#define MRLOCK_BARRIER 0x1 -#define MRLOCK_ALLOW_EQUAL_PRI 0x8 - -/* - * mraccessf/mrupdatef take flags to be passed in while sleeping; - * only PLTWAIT is currently supported. - */ - -extern void mraccessf(mrlock_t *, int); -extern void mrupdatef(mrlock_t *, int); -extern void mrlock(mrlock_t *, int, int); -extern void mrunlock(mrlock_t *); -extern void mraccunlock(mrlock_t *); -extern int mrtryupdate(mrlock_t *); -extern int mrtryaccess(mrlock_t *); -extern int mrtrypromote(mrlock_t *); -extern void mrdemote(mrlock_t *); - -extern int ismrlocked(mrlock_t *, int); -extern void mrlock_init(mrlock_t *, int type, char *name, long sequence); -extern void mrfree(mrlock_t *); - -#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1) -#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */ -#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */ -#define mrislocked_access(mrp) ((mrp)->mr_count > 0) -#define mrislocked_update(mrp) ((mrp)->mr_count < 0) - -#endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff --git a/fs/xfs/support/mutex.h b/fs/xfs/support/mutex.h deleted file mode 100644 index 0b296bb944cb..000000000000 --- a/fs/xfs/support/mutex.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_MUTEX_H__ -#define __XFS_SUPPORT_MUTEX_H__ - -#include -#include - -/* - * Map the mutex'es from IRIX to Linux semaphores. - * - * Destroy just simply initializes to -99 which should block all other - * callers. - */ -#define MUTEX_DEFAULT 0x0 -typedef struct semaphore mutex_t; - -#define mutex_init(lock, type, name) sema_init(lock, 1) -#define mutex_destroy(lock) sema_init(lock, -99) -#define mutex_lock(lock, num) down(lock) -#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) -#define mutex_unlock(lock) up(lock) - -#endif /* __XFS_SUPPORT_MUTEX_H__ */ diff --git a/fs/xfs/support/sema.h b/fs/xfs/support/sema.h deleted file mode 100644 index 30b67b4e1cbf..000000000000 --- a/fs/xfs/support/sema.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SEMA_H__ -#define __XFS_SUPPORT_SEMA_H__ - -#include -#include -#include -#include - -/* - * sema_t structure just maps to struct semaphore in Linux kernel. - */ - -typedef struct semaphore sema_t; - -#define init_sema(sp, val, c, d) sema_init(sp, val) -#define initsema(sp, val) sema_init(sp, val) -#define initnsema(sp, val, name) sema_init(sp, val) -#define psema(sp, b) down(sp) -#define vsema(sp) up(sp) -#define valusema(sp) (atomic_read(&(sp)->count)) -#define freesema(sema) - -/* - * Map cpsema (try to get the sema) to down_trylock. We need to switch - * the return values since cpsema returns 1 (acquired) 0 (failed) and - * down_trylock returns the reverse 0 (acquired) 1 (failed). - */ - -#define cpsema(sp) (down_trylock(sp) ? 0 : 1) - -/* - * Didn't do cvsema(sp). Not sure how to map this to up/down/... - * It does a vsema if the values is < 0 other wise nothing. - */ - -#endif /* __XFS_SUPPORT_SEMA_H__ */ diff --git a/fs/xfs/support/spin.h b/fs/xfs/support/spin.h deleted file mode 100644 index 80a3a6bae568..000000000000 --- a/fs/xfs/support/spin.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SPIN_H__ -#define __XFS_SUPPORT_SPIN_H__ - -#include /* preempt needs this */ -#include - -/* - * Map lock_t from IRIX to Linux spinlocks. - * - * Note that linux turns on/off spinlocks depending on CONFIG_SMP. - * We don't need to worry about SMP or not here. - */ - -#define SPLDECL(s) unsigned long s - -typedef spinlock_t lock_t; - -#define spinlock_init(lock, name) spin_lock_init(lock) -#define spinlock_destroy(lock) - -static inline unsigned long mutex_spinlock(lock_t *lock) -{ - spin_lock(lock); - return 0; -} - -/*ARGSUSED*/ -static inline void mutex_spinunlock(lock_t *lock, unsigned long s) -{ - spin_unlock(lock); -} - -static inline void nested_spinlock(lock_t *lock) -{ - spin_lock(lock); -} - -static inline void nested_spinunlock(lock_t *lock) -{ - spin_unlock(lock); -} - -#endif /* __XFS_SUPPORT_SPIN_H__ */ diff --git a/fs/xfs/support/sv.h b/fs/xfs/support/sv.h deleted file mode 100644 index 821d3167e05b..000000000000 --- a/fs/xfs/support/sv.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SV_H__ -#define __XFS_SUPPORT_SV_H__ - -#include -#include -#include - -/* - * Synchronisation variables. - * - * (Parameters "pri", "svf" and "rts" are not implemented) - */ - -typedef struct sv_s { - wait_queue_head_t waiters; -} sv_t; - -#define SV_FIFO 0x0 /* sv_t is FIFO type */ -#define SV_LIFO 0x2 /* sv_t is LIFO type */ -#define SV_PRIO 0x4 /* sv_t is PRIO type */ -#define SV_KEYED 0x6 /* sv_t is KEYED type */ -#define SV_DEFAULT SV_FIFO - - -static inline void _sv_wait(sv_t *sv, spinlock_t *lock, int state, - unsigned long timeout) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue_exclusive(&sv->waiters, &wait); - __set_current_state(state); - spin_unlock(lock); - - schedule_timeout(timeout); - - remove_wait_queue(&sv->waiters, &wait); -} - -#define init_sv(sv,type,name,flag) \ - init_waitqueue_head(&(sv)->waiters) -#define sv_init(sv,flag,name) \ - init_waitqueue_head(&(sv)->waiters) -#define sv_destroy(sv) \ - /*NOTHING*/ -#define sv_wait(sv, pri, lock, s) \ - _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) -#define sv_wait_sig(sv, pri, lock, s) \ - _sv_wait(sv, lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT) -#define sv_timedwait(sv, pri, lock, s, svf, ts, rts) \ - _sv_wait(sv, lock, TASK_UNINTERRUPTIBLE, timespec_to_jiffies(ts)) -#define sv_timedwait_sig(sv, pri, lock, s, svf, ts, rts) \ - _sv_wait(sv, lock, TASK_INTERRUPTIBLE, timespec_to_jiffies(ts)) -#define sv_signal(sv) \ - wake_up(&(sv)->waiters) -#define sv_broadcast(sv) \ - wake_up_all(&(sv)->waiters) - -#endif /* __XFS_SUPPORT_SV_H__ */ diff --git a/fs/xfs/support/time.h b/fs/xfs/support/time.h deleted file mode 100644 index 109b5c0833f8..000000000000 --- a/fs/xfs/support/time.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_TIME_H__ -#define __XFS_SUPPORT_TIME_H__ - -#include -#include - -typedef struct timespec timespec_t; - -static inline void delay(long ticks) -{ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(ticks); -} - -static inline void nanotime(struct timespec *tvp) -{ - *tvp = CURRENT_TIME; -} - -#endif /* __XFS_SUPPORT_TIME_H__ */ diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index a13aedbdddc9..7e44857648ab 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c @@ -33,11 +33,11 @@ #include #include #include -#include "time.h" +#include +#include +#include #include "uuid.h" -#include "kmem.h" #include "debug.h" -#include "mutex.h" static mutex_t uuid_monitor; static int uuid_table_size; diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index f9cfa5afa8cf..d916806daf77 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -38,18 +38,11 @@ #include -#include -#include #include -#include -#include #include -#include -#include #include #include #include -#include #include diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c new file mode 100644 index 000000000000..16088e175ecc --- /dev/null +++ b/fs/xfs/xfs_behavior.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + * + */ +#include "xfs.h" + +/* + * Source file used to associate/disassociate behaviors with virtualized + * objects. See xfs_behavior.h for more information about behaviors, etc. + * + * The implementation is split between functions in this file and macros + * in xfs_behavior.h. + */ + +/* + * Insert a new behavior descriptor into a behavior chain. + * + * The behavior chain is ordered based on the 'position' number which + * lives in the first field of the ops vector (higher numbers first). + * + * Attemps to insert duplicate ops result in an EINVAL return code. + * Otherwise, return 0 to indicate success. + */ +int +bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) +{ + bhv_desc_t *curdesc, *prev; + int position; + + /* + * Validate the position value of the new behavior. + */ + position = BHV_POSITION(bdp); + ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); + + /* + * Find location to insert behavior. Check for duplicates. + */ + prev = NULL; + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + /* Check for duplication. */ + if (curdesc->bd_ops == bdp->bd_ops) { + ASSERT(0); + return EINVAL; + } + + /* Find correct position */ + if (position >= BHV_POSITION(curdesc)) { + ASSERT(position != BHV_POSITION(curdesc)); + break; /* found it */ + } + + prev = curdesc; + } + + if (prev == NULL) { + /* insert at front of chain */ + bdp->bd_next = bhp->bh_first; + bhp->bh_first = bdp; + } else { + /* insert after prev */ + bdp->bd_next = prev->bd_next; + prev->bd_next = bdp; + } + + return 0; +} + +/* + * Remove a behavior descriptor from a position in a behavior chain; + * the postition is guaranteed not to be the first position. + * Should only be called by the bhv_remove() macro. + */ +void +bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) +{ + bhv_desc_t *curdesc, *prev; + + ASSERT(bhp->bh_first != NULL); + ASSERT(bhp->bh_first->bd_next != NULL); + + prev = bhp->bh_first; + for (curdesc = bhp->bh_first->bd_next; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc == bdp) + break; /* found it */ + prev = curdesc; + } + + ASSERT(curdesc == bdp); + prev->bd_next = bdp->bd_next; /* remove from after prev */ +} + +/* + * Look for a specific ops vector on the specified behavior chain. + * Return the associated behavior descriptor. Or NULL, if not found. + */ +bhv_desc_t * +bhv_lookup(bhv_head_t *bhp, void *ops) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc->bd_ops == ops) + return curdesc; + } + + return NULL; +} + +/* + * Looks for the first behavior within a specified range of positions. + * Return the associated behavior descriptor. Or NULL, if none found. + */ +bhv_desc_t * +bhv_lookup_range(bhv_head_t *bhp, int low, int high) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + int position = BHV_POSITION(curdesc); + + if (position <= high) { + if (position >= low) + return curdesc; + return NULL; + } + } + + return NULL; +} + +/* + * Return the base behavior in the chain, or NULL if the chain + * is empty. + * + * The caller has not read locked the behavior chain, so acquire the + * lock before traversing the chain. + */ +bhv_desc_t * +bhv_base(bhv_head_t *bhp) +{ + bhv_desc_t *curdesc; + + for (curdesc = bhp->bh_first; + curdesc != NULL; + curdesc = curdesc->bd_next) { + + if (curdesc->bd_next == NULL) { + return curdesc; + } + } + + return NULL; +} + +void +bhv_head_init( + bhv_head_t *bhp, + char *name) +{ + bhp->bh_first = NULL; +} + +void +bhv_insert_initial( + bhv_head_t *bhp, + bhv_desc_t *bdp) +{ + ASSERT(bhp->bh_first == NULL); + (bhp)->bh_first = bdp; +} + +void +bhv_head_destroy( + bhv_head_t *bhp) +{ + ASSERT(bhp->bh_first == NULL); +} diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h new file mode 100644 index 000000000000..d5ed5a843921 --- /dev/null +++ b/fs/xfs/xfs_behavior.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XFS_BEHAVIOR_H__ +#define __XFS_BEHAVIOR_H__ + +/* + * Header file used to associate behaviors with virtualized objects. + * + * A virtualized object is an internal, virtualized representation of + * OS entities such as persistent files, processes, or sockets. Examples + * of virtualized objects include vnodes, vprocs, and vsockets. Often + * a virtualized object is referred to simply as an "object." + * + * A behavior is essentially an implementation layer associated with + * an object. Multiple behaviors for an object are chained together, + * the order of chaining determining the order of invocation. Each + * behavior of a given object implements the same set of interfaces + * (e.g., the VOP interfaces). + * + * Behaviors may be dynamically inserted into an object's behavior chain, + * such that the addition is transparent to consumers that already have + * references to the object. Typically, a given behavior will be inserted + * at a particular location in the behavior chain. Insertion of new + * behaviors is synchronized with operations-in-progress (oip's) so that + * the oip's always see a consistent view of the chain. + * + * The term "interpostion" is used to refer to the act of inserting + * a behavior such that it interposes on (i.e., is inserted in front + * of) a particular other behavior. A key example of this is when a + * system implementing distributed single system image wishes to + * interpose a distribution layer (providing distributed coherency) + * in front of an object that is otherwise only accessed locally. + * + * Note that the traditional vnode/inode combination is simply a virtualized + * object that has exactly one associated behavior. + * + * Behavior synchronization is logic which is necessary under certain + * circumstances that there is no conflict between ongoing operations + * traversing the behavior chain and those dunamically modifying the + * behavior chain. Because behavior synchronization adds extra overhead + * to virtual operation invocation, we want to restrict, as much as + * we can, the requirement for this extra code, to those situations + * in which it is truly necessary. + * + * Behavior synchronization is needed whenever there's at least one class + * of object in the system for which: + * 1) multiple behaviors for a given object are supported, + * -- AND -- + * 2a) insertion of a new behavior can happen dynamically at any time during + * the life of an active object, + * -- AND -- + * 3a) insertion of a new behavior needs to synchronize with existing + * ops-in-progress. + * -- OR -- + * 3b) multiple different behaviors can be dynamically inserted at + * any time during the life of an active object + * -- OR -- + * 3c) removal of a behavior can occur at any time during the life of + * an active object. + * -- OR -- + * 2b) removal of a behavior can occur at any time during the life of an + * active object + * + */ + +struct bhv_head_lock; + +/* + * Behavior head. Head of the chain of behaviors. + * Contained within each virtualized object data structure. + */ +typedef struct bhv_head { + struct bhv_desc *bh_first; /* first behavior in chain */ + struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ +} bhv_head_t; + +/* + * Behavior descriptor. Descriptor associated with each behavior. + * Contained within the behavior's private data structure. + */ +typedef struct bhv_desc { + void *bd_pdata; /* private data for this behavior */ + void *bd_vobj; /* virtual object associated with */ + void *bd_ops; /* ops for this behavior */ + struct bhv_desc *bd_next; /* next behavior in chain */ +} bhv_desc_t; + +/* + * Behavior identity field. A behavior's identity determines the position + * where it lives within a behavior chain, and it's always the first field + * of the behavior's ops vector. The optional id field further identifies the + * subsystem responsible for the behavior. + */ +typedef struct bhv_identity { + __u16 bi_id; /* owning subsystem id */ + __u16 bi_position; /* position in chain */ +} bhv_identity_t; + +typedef bhv_identity_t bhv_position_t; + +#define BHV_IDENTITY_INIT(id,pos) {id, pos} +#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) + +/* + * Define boundaries of position values. + */ +#define BHV_POSITION_INVALID 0 /* invalid position number */ +#define BHV_POSITION_BASE 1 /* base (last) implementation layer */ +#define BHV_POSITION_TOP 63 /* top (first) implementation layer */ + +/* + * Plumbing macros. + */ +#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first) +#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next) +#define BHV_NEXTNULL(bdp) ((bdp)->bd_next) +#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj) +#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj) +#define BHV_PDATA(bdp) (bdp)->bd_pdata +#define BHV_OPS(bdp) (bdp)->bd_ops +#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) +#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) + +extern void bhv_head_init(bhv_head_t *, char *); +extern void bhv_head_destroy(bhv_head_t *); +extern int bhv_insert(bhv_head_t *, bhv_desc_t *); +extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); + +/* + * Initialize a new behavior descriptor. + * Arguments: + * bdp - pointer to behavior descriptor + * pdata - pointer to behavior's private data + * vobj - pointer to associated virtual object + * ops - pointer to ops for this behavior + */ +#define bhv_desc_init(bdp, pdata, vobj, ops) \ + { \ + (bdp)->bd_pdata = pdata; \ + (bdp)->bd_vobj = vobj; \ + (bdp)->bd_ops = ops; \ + (bdp)->bd_next = NULL; \ + } + +/* + * Remove a behavior descriptor from a behavior chain. + */ +#define bhv_remove(bhp, bdp) \ + { \ + if ((bhp)->bh_first == (bdp)) { \ + /* \ + * Remove from front of chain. \ + * Atomic wrt oip's. \ + */ \ + (bhp)->bh_first = (bdp)->bd_next; \ + } else { \ + /* remove from non-front of chain */ \ + bhv_remove_not_first(bhp, bdp); \ + } \ + (bdp)->bd_vobj = NULL; \ + } + +/* + * Behavior module prototypes. + */ +extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); +extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops); +extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); +extern bhv_desc_t * bhv_base(bhv_head_t *bhp); + +/* No bhv locking on Linux */ +#define bhv_lookup_unlocked bhv_lookup +#define bhv_base_unlocked bhv_base + +#endif /* __XFS_BEHAVIOR_H__ */ diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h deleted file mode 100644 index 42544597e856..000000000000 --- a/fs/xfs/xfs_buf.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_BUF_H__ -#define __XFS_BUF_H__ - -/* These are just for xfs_syncsub... it sets an internal variable - * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t - */ -#define XFS_B_ASYNC PBF_ASYNC -#define XFS_B_DELWRI PBF_DELWRI -#define XFS_B_READ PBF_READ -#define XFS_B_WRITE PBF_WRITE -#define XFS_B_STALE PBF_STALE - -#define XFS_BUF_TRYLOCK PBF_TRYLOCK -#define XFS_INCORE_TRYLOCK PBF_TRYLOCK -#define XFS_BUF_LOCK PBF_LOCK -#define XFS_BUF_MAPPED PBF_MAPPED - -#define BUF_BUSY PBF_DONT_BLOCK - -#define XFS_BUF_BFLAGS(x) ((x)->pb_flags) -#define XFS_BUF_ZEROFLAGS(x) \ - ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_DELWRI)) - -#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE) -#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE) -#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE) -#define XFS_BUF_SUPER_STALE(x) do { \ - XFS_BUF_STALE(x); \ - xfs_buf_undelay(x); \ - XFS_BUF_DONE(x); \ - } while (0) - -#define XFS_BUF_MANAGE PBF_FS_MANAGED -#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED) - -static inline void xfs_buf_undelay(page_buf_t *pb) -{ - if (pb->pb_flags & PBF_DELWRI) { - if (pb->pb_list.next != &pb->pb_list) { - pagebuf_delwri_dequeue(pb); - pagebuf_rele(pb); - } else { - pb->pb_flags &= ~PBF_DELWRI; - } - } -} - -#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI) -#define XFS_BUF_UNDELAYWRITE(x) xfs_buf_undelay(x) -#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI) - -#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no) -#define XFS_BUF_GETERROR(x) pagebuf_geterror(x) -#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0) - -#define XFS_BUF_DONE(x) ((x)->pb_flags &= ~(PBF_PARTIAL|PBF_NONE)) -#define XFS_BUF_UNDONE(x) ((x)->pb_flags |= PBF_PARTIAL|PBF_NONE) -#define XFS_BUF_ISDONE(x) (!(PBF_NOT_DONE(x))) - -#define XFS_BUF_BUSY(x) ((x)->pb_flags |= PBF_FORCEIO) -#define XFS_BUF_UNBUSY(x) ((x)->pb_flags &= ~PBF_FORCEIO) -#define XFS_BUF_ISBUSY(x) (1) - -#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC) -#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC) -#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC) - -#define XFS_BUF_FLUSH(x) ((x)->pb_flags |= PBF_FLUSH) -#define XFS_BUF_UNFLUSH(x) ((x)->pb_flags &= ~PBF_FLUSH) -#define XFS_BUF_ISFLUSH(x) ((x)->pb_flags & PBF_FLUSH) - -#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n") -#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n") -#define XFS_BUF_ISSHUT(x) (0) - -#define XFS_BUF_HOLD(x) pagebuf_hold(x) -#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ) -#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ) -#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ) - -#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE) -#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE) -#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE) - -#define XFS_BUF_ISUNINITIAL(x) (0) -#define XFS_BUF_UNUNINITIAL(x) (0) - -#define XFS_BUF_BP_ISMAPPED(bp) 1 - -typedef struct page_buf_s xfs_buf_t; -#define xfs_buf page_buf_s - -typedef struct pb_target xfs_buftarg_t; -#define xfs_buftarg pb_target - -#define XFS_BUF_DATAIO(x) ((x)->pb_flags |= PBF_FS_DATAIOD) -#define XFS_BUF_UNDATAIO(x) ((x)->pb_flags &= ~PBF_FS_DATAIOD) - -#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone -#define XFS_BUF_SET_IODONE_FUNC(buf, func) \ - (buf)->pb_iodone = (func) -#define XFS_BUF_CLR_IODONE_FUNC(buf) \ - (buf)->pb_iodone = NULL -#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \ - (buf)->pb_strat = (func) -#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \ - (buf)->pb_strat = NULL - -#define XFS_BUF_FSPRIVATE(buf, type) \ - ((type)(buf)->pb_fspriv) -#define XFS_BUF_SET_FSPRIVATE(buf, value) \ - (buf)->pb_fspriv = (void *)(value) -#define XFS_BUF_FSPRIVATE2(buf, type) \ - ((type)(buf)->pb_fspriv2) -#define XFS_BUF_SET_FSPRIVATE2(buf, value) \ - (buf)->pb_fspriv2 = (void *)(value) -#define XFS_BUF_FSPRIVATE3(buf, type) \ - ((type)(buf)->pb_fspriv3) -#define XFS_BUF_SET_FSPRIVATE3(buf, value) \ - (buf)->pb_fspriv3 = (void *)(value) -#define XFS_BUF_SET_START(buf) - -#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \ - (buf)->pb_relse = (value) - -#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr) - -extern inline xfs_caddr_t xfs_buf_offset(page_buf_t *bp, size_t offset) -{ - if (bp->pb_flags & PBF_MAPPED) - return XFS_BUF_PTR(bp) + offset; - return (xfs_caddr_t) pagebuf_offset(bp, offset); -} - -#define XFS_BUF_SET_PTR(bp, val, count) \ - pagebuf_associate_memory(bp, val, count) -#define XFS_BUF_ADDR(bp) ((bp)->pb_bn) -#define XFS_BUF_SET_ADDR(bp, blk) \ - ((bp)->pb_bn = (page_buf_daddr_t)(blk)) -#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) -#define XFS_BUF_SET_OFFSET(bp, off) \ - ((bp)->pb_file_offset = (off)) -#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) -#define XFS_BUF_SET_COUNT(bp, cnt) \ - ((bp)->pb_count_desired = (cnt)) -#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) -#define XFS_BUF_SET_SIZE(bp, cnt) \ - ((bp)->pb_buffer_length = (cnt)) -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp) - -#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp) -#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0) -#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp) -#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp) -#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema); - -/* setup the buffer target from a buftarg structure */ -#define XFS_BUF_SET_TARGET(bp, target) \ - (bp)->pb_target = (target) -#define XFS_BUF_TARGET(bp) ((bp)->pb_target) -#define XFS_BUFTARG_NAME(target) \ - pagebuf_target_name(target) - -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) -#define XFS_BUF_SET_VTYPE(bp, type) -#define XFS_BUF_SET_REF(bp, ref) - -#define xfs_buf_read(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_READ | PBF_MAPPED | PBF_MAPPABLE) -#define xfs_buf_get(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_LOCK | PBF_MAPPED | PBF_MAPPABLE) - -#define xfs_buf_read_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_READ | PBF_MAPPABLE | flags) -#define xfs_buf_get_flags(target, blkno, len, flags) \ - pagebuf_get((target), (blkno), (len), \ - PBF_MAPPABLE | flags) - -static inline int xfs_bawrite(void *mp, page_buf_t *bp) -{ - bp->pb_fspriv3 = mp; - bp->pb_strat = xfs_bdstrat_cb; - xfs_buf_undelay(bp); - return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES); -} - -static inline void xfs_buf_relse(page_buf_t *bp) -{ - if ((bp->pb_flags & _PBF_LOCKABLE) && !bp->pb_relse) - pagebuf_unlock(bp); - pagebuf_rele(bp); -} - -#define xfs_bpin(bp) pagebuf_pin(bp) -#define xfs_bunpin(bp) pagebuf_unpin(bp) - -#define xfs_buftrace(id, bp) \ - pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0)) - -#define xfs_biodone(pb) \ - pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 0) - -#define xfs_incore(buftarg,blkno,len,lockit) \ - pagebuf_find(buftarg, blkno ,len, lockit) - - -#define xfs_biomove(pb, off, len, data, rw) \ - pagebuf_iomove((pb), (off), (len), (data), \ - ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ) - -#define xfs_biozero(pb, off, len) \ - pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO) - - -static inline int XFS_bwrite(page_buf_t *pb) -{ - int iowait = (pb->pb_flags & PBF_ASYNC) == 0; - int error = 0; - - pb->pb_flags |= PBF_SYNC; - if (!iowait) - pb->pb_flags |= PBF_RUN_QUEUES; - - xfs_buf_undelay(pb); - pagebuf_iostrategy(pb); - if (iowait) { - error = pagebuf_iowait(pb); - xfs_buf_relse(pb); - } - return error; -} - -#define XFS_bdwrite(pb) \ - pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC) - -static inline int xfs_bdwrite(void *mp, page_buf_t *bp) -{ - bp->pb_strat = xfs_bdstrat_cb; - bp->pb_fspriv3 = mp; - - return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC); -} - -#define XFS_bdstrat(bp) pagebuf_iorequest(bp) - -#define xfs_iowait(pb) pagebuf_iowait(pb) - - -/* - * Go through all incore buffers, and release buffers - * if they belong to the given device. This is used in - * filesystem error handling to preserve the consistency - * of its metadata. - */ - -#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg) - -#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg) - -#define xfs_incore_relse(buftarg,delwri_only,wait) \ - xfs_relse_buftarg(buftarg) - -#define xfs_baread(target, rablkno, ralen) \ - pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK) - -#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target)) -#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target)) -#define xfs_buf_free(bp) pagebuf_free(bp) - -#endif /* __XFS_BUF_H__ */ diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c new file mode 100644 index 000000000000..ae4818adb23e --- /dev/null +++ b/fs/xfs/xfs_iomap.c @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include "xfs.h" + +#include "xfs_fs.h" +#include "xfs_inum.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_dir.h" +#include "xfs_dir2.h" +#include "xfs_alloc.h" +#include "xfs_dmapi.h" +#include "xfs_quota.h" +#include "xfs_mount.h" +#include "xfs_alloc_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_btree.h" +#include "xfs_ialloc.h" +#include "xfs_attr_sf.h" +#include "xfs_dir_sf.h" +#include "xfs_dir2_sf.h" +#include "xfs_dinode.h" +#include "xfs_inode.h" +#include "xfs_bmap.h" +#include "xfs_bit.h" +#include "xfs_rtalloc.h" +#include "xfs_error.h" +#include "xfs_itable.h" +#include "xfs_rw.h" +#include "xfs_acl.h" +#include "xfs_cap.h" +#include "xfs_mac.h" +#include "xfs_attr.h" +#include "xfs_buf_item.h" +#include "xfs_trans_space.h" +#include "xfs_utils.h" +#include "xfs_iomap.h" + +#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ + << mp->m_writeio_log) +#define XFS_STRAT_WRITE_IMAPS 2 +#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAP + +STATIC int +xfs_imap_to_bmap( + xfs_iocore_t *io, + xfs_off_t offset, + xfs_bmbt_irec_t *imap, + xfs_iomap_t *iomapp, + int imaps, /* Number of imap entries */ + int iomaps, /* Number of iomap entries */ + int flags) +{ + xfs_mount_t *mp; + xfs_fsize_t nisize; + int pbm; + xfs_fsblock_t start_block; + + mp = io->io_mount; + nisize = XFS_SIZE(mp, io); + if (io->io_new_size > nisize) + nisize = io->io_new_size; + + for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { + iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? + mp->m_rtdev_targp : mp->m_ddev_targp; + iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); + iomapp->iomap_delta = offset - iomapp->iomap_offset; + iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); + iomapp->iomap_flags = flags; + + start_block = imap->br_startblock; + if (start_block == HOLESTARTBLOCK) { + iomapp->iomap_bn = IOMAP_DADDR_NULL; + iomapp->iomap_flags = IOMAP_HOLE; + } else if (start_block == DELAYSTARTBLOCK) { + iomapp->iomap_bn = IOMAP_DADDR_NULL; + iomapp->iomap_flags = IOMAP_DELAY; + } else { + iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); + if (ISUNWRITTEN(imap)) + iomapp->iomap_flags |= IOMAP_UNWRITTEN; + } + + if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) { + iomapp->iomap_flags |= IOMAP_EOF; + } + + offset += iomapp->iomap_bsize - iomapp->iomap_delta; + } + return pbm; /* Return the number filled */ +} + +int +xfs_iomap( + xfs_iocore_t *io, + xfs_off_t offset, + ssize_t count, + int flags, + xfs_iomap_t *iomapp, + int *niomaps) +{ + xfs_mount_t *mp = io->io_mount; + xfs_fileoff_t offset_fsb, end_fsb; + int error = 0; + int lockmode = 0; + xfs_bmbt_irec_t imap; + int nimaps = 1; + int bmapi_flags = 0; + int iomap_flags = 0; + + if (XFS_FORCED_SHUTDOWN(mp)) + return XFS_ERROR(EIO); + + switch (flags & + (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | + BMAPI_UNWRITTEN | BMAPI_DEVICE)) { + case BMAPI_READ: + lockmode = XFS_LCK_MAP_SHARED(mp, io); + bmapi_flags = XFS_BMAPI_ENTIRE; + if (flags & BMAPI_IGNSTATE) + bmapi_flags |= XFS_BMAPI_IGSTATE; + break; + case BMAPI_WRITE: + lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; + bmapi_flags = 0; + XFS_ILOCK(mp, io, lockmode); + break; + case BMAPI_ALLOCATE: + lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; + bmapi_flags = XFS_BMAPI_ENTIRE; + /* Attempt non-blocking lock */ + if (flags & BMAPI_TRYLOCK) { + if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) + return XFS_ERROR(EAGAIN); + } else { + XFS_ILOCK(mp, io, lockmode); + } + break; + case BMAPI_UNWRITTEN: + goto phase2; + case BMAPI_DEVICE: + lockmode = XFS_LCK_MAP_SHARED(mp, io); + iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? + mp->m_rtdev_targp : mp->m_ddev_targp; + error = 0; + *niomaps = 1; + goto out; + default: + BUG(); + } + + ASSERT(offset <= mp->m_maxioffset); + if ((xfs_fsize_t)offset + count > mp->m_maxioffset) + count = mp->m_maxioffset - offset; + end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); + offset_fsb = XFS_B_TO_FSBT(mp, offset); + + error = XFS_BMAPI(mp, NULL, io, offset_fsb, + (xfs_filblks_t)(end_fsb - offset_fsb), + bmapi_flags, NULL, 0, &imap, + &nimaps, NULL); + + if (error) + goto out; + +phase2: + switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { + case BMAPI_WRITE: + /* If we found an extent, return it */ + if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) + break; + + if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { + error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, + count, flags, &imap, &nimaps, nimaps); + } else { + error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, + flags, &imap, &nimaps); + } + iomap_flags = IOMAP_NEW; + break; + case BMAPI_ALLOCATE: + /* If we found an extent, return it */ + XFS_IUNLOCK(mp, io, lockmode); + lockmode = 0; + + if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) + break; + + error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); + break; + case BMAPI_UNWRITTEN: + lockmode = 0; + error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); + nimaps = 0; + break; + } + + if (nimaps) { + *niomaps = xfs_imap_to_bmap(io, offset, &imap, + iomapp, nimaps, *niomaps, iomap_flags); + } else if (niomaps) { + *niomaps = 0; + } + +out: + if (lockmode) + XFS_IUNLOCK(mp, io, lockmode); + return XFS_ERROR(error); +} + +STATIC int +xfs_flush_space( + xfs_inode_t *ip, + int *fsynced, + int *ioflags) +{ + switch (*fsynced) { + case 0: + if (ip->i_delayed_blks) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_flush_inode(ip); + xfs_ilock(ip, XFS_ILOCK_EXCL); + *fsynced = 1; + } else { + *ioflags |= BMAPI_SYNC; + *fsynced = 2; + } + return 0; + case 1: + *fsynced = 2; + *ioflags |= BMAPI_SYNC; + return 0; + case 2: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_flush_device(ip); + xfs_ilock(ip, XFS_ILOCK_EXCL); + *fsynced = 3; + return 0; + } + return 1; +} + +int +xfs_iomap_write_direct( + xfs_inode_t *ip, + loff_t offset, + size_t count, + int flags, + xfs_bmbt_irec_t *ret_imap, + int *nmaps, + int found) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t last_fsb; + xfs_filblks_t count_fsb; + xfs_fsize_t isize; + xfs_fsblock_t firstfsb; + int nimaps, maps; + int error; + int bmapi_flag; + int rt; + xfs_trans_t *tp; + xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; + xfs_bmap_free_t free_list; + int aeof; + xfs_filblks_t datablocks; + int committed; + int numrtextents; + uint resblks; + + /* + * Make sure that the dquots are there. This doesn't hold + * the ilock across a disk read. + */ + + error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); + + maps = min(XFS_WRITE_IMAPS, *nmaps); + nimaps = maps; + + isize = ip->i_d.di_size; + aeof = (offset + count) > isize; + + if (io->io_new_size > isize) + isize = io->io_new_size; + + offset_fsb = XFS_B_TO_FSBT(mp, offset); + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); + count_fsb = last_fsb - offset_fsb; + if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { + xfs_fileoff_t map_last_fsb; + + map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; + + if (map_last_fsb < last_fsb) { + last_fsb = map_last_fsb; + count_fsb = last_fsb - offset_fsb; + } + ASSERT(count_fsb > 0); + } + + /* + * determine if reserving space on + * the data or realtime partition. + */ + if ((rt = XFS_IS_REALTIME_INODE(ip))) { + int sbrtextsize, iprtextsize; + + sbrtextsize = mp->m_sb.sb_rextsize; + iprtextsize = + ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; + numrtextents = (count_fsb + iprtextsize - 1); + do_div(numrtextents, sbrtextsize); + datablocks = 0; + } else { + datablocks = count_fsb; + numrtextents = 0; + } + + /* + * allocate and setup the transaction + */ + xfs_iunlock(ip, XFS_ILOCK_EXCL); + tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); + + resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); + + error = xfs_trans_reserve(tp, resblks, + XFS_WRITE_LOG_RES(mp), numrtextents, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + + /* + * check for running out of space + */ + if (error) + /* + * Free the transaction structure. + */ + xfs_trans_cancel(tp, 0); + + xfs_ilock(ip, XFS_ILOCK_EXCL); + + if (error) + goto error_out; /* Don't return in above if .. trans .., + need lock to return */ + + if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { + error = (EDQUOT); + goto error1; + } + nimaps = 1; + + bmapi_flag = XFS_BMAPI_WRITE; + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) + bmapi_flag |= XFS_BMAPI_PREALLOC; + + /* + * issue the bmapi() call to allocate the blocks + */ + XFS_BMAP_INIT(&free_list, &firstfsb); + imapp = &imap[0]; + error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, + bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); + if (error) { + goto error0; + } + + /* + * complete the transaction + */ + + error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); + if (error) { + goto error0; + } + + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); + if (error) { + goto error_out; + } + + /* copy any maps to caller's array and return any error. */ + if (nimaps == 0) { + error = (ENOSPC); + goto error_out; + } + + *ret_imap = imap[0]; + *nmaps = 1; + return 0; + + error0: /* Cancel bmap, unlock inode, and cancel trans */ + xfs_bmap_cancel(&free_list); + + error1: /* Just cancel transaction */ + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); + *nmaps = 0; /* nothing set-up here */ + +error_out: + return XFS_ERROR(error); +} + +int +xfs_iomap_write_delay( + xfs_inode_t *ip, + loff_t offset, + size_t count, + int ioflag, + xfs_bmbt_irec_t *ret_imap, + int *nmaps) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t last_fsb; + xfs_fsize_t isize; + xfs_fsblock_t firstblock; + int nimaps; + int error; + xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; + int aeof; + int fsynced = 0; + + ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); + + /* + * Make sure that the dquots are there. This doesn't hold + * the ilock across a disk read. + */ + + error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); + if (error) + return XFS_ERROR(error); + +retry: + isize = ip->i_d.di_size; + if (io->io_new_size > isize) { + isize = io->io_new_size; + } + + aeof = 0; + offset_fsb = XFS_B_TO_FSBT(mp, offset); + last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); + /* + * If the caller is doing a write at the end of the file, + * then extend the allocation (and the buffer used for the write) + * out to the file system's write iosize. We clean up any extra + * space left over when the file is closed in xfs_inactive(). + * + * We don't bother with this for sync writes, because we need + * to minimize the amount we write for good performance. + */ + if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { + xfs_off_t aligned_offset; + unsigned int iosize; + xfs_fileoff_t ioalign; + + iosize = mp->m_writeio_blocks; + aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); + ioalign = XFS_B_TO_FSBT(mp, aligned_offset); + last_fsb = ioalign + iosize; + aeof = 1; + } + + nimaps = XFS_WRITE_IMAPS; + firstblock = NULLFSBLOCK; + + /* + * roundup the allocation request to m_dalign boundary if file size + * is greater that 512K and we are allocating past the allocation eof + */ + if (mp->m_dalign && (isize >= mp->m_dalign) && aeof) { + int eof; + xfs_fileoff_t new_last_fsb; + new_last_fsb = roundup_64(last_fsb, mp->m_dalign); + error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); + if (error) { + return error; + } + if (eof) { + last_fsb = new_last_fsb; + } + } + + error = xfs_bmapi(NULL, ip, offset_fsb, + (xfs_filblks_t)(last_fsb - offset_fsb), + XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | + XFS_BMAPI_ENTIRE, &firstblock, 1, imap, + &nimaps, NULL); + /* + * This can be EDQUOT, if nimaps == 0 + */ + if (error && (error != ENOSPC)) { + return XFS_ERROR(error); + } + /* + * If bmapi returned us nothing, and if we didn't get back EDQUOT, + * then we must have run out of space. + */ + + if (nimaps == 0) { + if (xfs_flush_space(ip, &fsynced, &ioflag)) + return XFS_ERROR(ENOSPC); + + error = 0; + goto retry; + } + + *ret_imap = imap[0]; + *nmaps = 1; + return 0; +} + +/* + * Pass in a delayed allocate extent, convert it to real extents; + * return to the caller the extent we create which maps on top of + * the originating callers request. + * + * Called without a lock on the inode. + */ +int +xfs_iomap_write_allocate( + xfs_inode_t *ip, + xfs_bmbt_irec_t *map, + int *retmap) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_fileoff_t offset_fsb, last_block; + xfs_fileoff_t end_fsb, map_start_fsb; + xfs_fsblock_t first_block; + xfs_bmap_free_t free_list; + xfs_filblks_t count_fsb; + xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS]; + xfs_trans_t *tp; + int i, nimaps, committed; + int error = 0; + int nres; + + *retmap = 0; + + /* + * Make sure that the dquots are there. + */ + + if ((error = XFS_QM_DQATTACH(mp, ip, 0))) + return XFS_ERROR(error); + + offset_fsb = map->br_startoff; + count_fsb = map->br_blockcount; + map_start_fsb = offset_fsb; + + XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); + + while (count_fsb != 0) { + /* + * Set up a transaction with which to allocate the + * backing store for the file. Do allocations in a + * loop until we get some space in the range we are + * interested in. The other space that might be allocated + * is in the delayed allocation extent on which we sit + * but before our buffer starts. + */ + + nimaps = 0; + while (nimaps == 0) { + tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); + error = xfs_trans_reserve(tp, nres, + XFS_WRITE_LOG_RES(mp), + 0, XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + + if (error == ENOSPC) { + error = xfs_trans_reserve(tp, 0, + XFS_WRITE_LOG_RES(mp), + 0, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + } + if (error) { + xfs_trans_cancel(tp, 0); + return XFS_ERROR(error); + } + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + XFS_BMAP_INIT(&free_list, &first_block); + + nimaps = XFS_STRAT_WRITE_IMAPS; + /* + * Ensure we don't go beyond eof - it is possible + * the extents changed since we did the read call, + * we dropped the ilock in the interim. + */ + + end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size); + xfs_bmap_last_offset(NULL, ip, &last_block, + XFS_DATA_FORK); + last_block = XFS_FILEOFF_MAX(last_block, end_fsb); + if ((map_start_fsb + count_fsb) > last_block) { + count_fsb = last_block - map_start_fsb; + if (count_fsb == 0) { + error = EAGAIN; + goto trans_cancel; + } + } + + /* Go get the actual blocks */ + error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, + XFS_BMAPI_WRITE, &first_block, 1, + imap, &nimaps, &free_list); + + if (error) + goto trans_cancel; + + error = xfs_bmap_finish(&tp, &free_list, + first_block, &committed); + + if (error) + goto trans_cancel; + + error = xfs_trans_commit(tp, + XFS_TRANS_RELEASE_LOG_RES, NULL); + + if (error) + goto error0; + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + } + + /* + * See if we were able to allocate an extent that + * covers at least part of the callers request + */ + + for (i = 0; i < nimaps; i++) { + if ((map->br_startoff >= imap[i].br_startoff) && + (map->br_startoff < (imap[i].br_startoff + + imap[i].br_blockcount))) { + *map = imap[i]; + *retmap = 1; + XFS_STATS_INC(xs_xstrat_quick); + return 0; + } + count_fsb -= imap[i].br_blockcount; + } + + /* So far we have not mapped the requested part of the + * file, just surrounding data, try again. + */ + nimaps--; + offset_fsb = imap[nimaps].br_startoff + + imap[nimaps].br_blockcount; + map_start_fsb = offset_fsb; + } + +trans_cancel: + xfs_bmap_cancel(&free_list); + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); +error0: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return XFS_ERROR(error); +} + +int +xfs_iomap_write_unwritten( + xfs_inode_t *ip, + loff_t offset, + size_t count) +{ + xfs_mount_t *mp = ip->i_mount; + xfs_trans_t *tp; + xfs_fileoff_t offset_fsb; + xfs_filblks_t count_fsb; + xfs_filblks_t numblks_fsb; + xfs_bmbt_irec_t imap; + int committed; + int error; + int nres; + int nimaps; + xfs_fsblock_t firstfsb; + xfs_bmap_free_t free_list; + + offset_fsb = XFS_B_TO_FSBT(mp, offset); + count_fsb = XFS_B_TO_FSB(mp, count); + + do { + nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); + + /* + * set up a transaction to convert the range of extents + * from unwritten to real. Do allocations in a loop until + * we have covered the range passed in. + */ + + tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + error = xfs_trans_reserve(tp, nres, + XFS_WRITE_LOG_RES(mp), 0, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + if (error) { + xfs_trans_cancel(tp, 0); + goto error0; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_ihold(tp, ip); + + /* + * Modify the unwritten extent state of the buffer. + */ + XFS_BMAP_INIT(&free_list, &firstfsb); + nimaps = 1; + error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, + XFS_BMAPI_WRITE, &firstfsb, + 1, &imap, &nimaps, &free_list); + if (error) + goto error_on_bmapi_transaction; + + error = xfs_bmap_finish(&(tp), &(free_list), + firstfsb, &committed); + if (error) + goto error_on_bmapi_transaction; + + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (error) + goto error0; + + if ((numblks_fsb = imap.br_blockcount) == 0) { + /* + * The numblks_fsb value should always get + * smaller, otherwise the loop is stuck. + */ + ASSERT(imap.br_blockcount); + break; + } + offset_fsb += numblks_fsb; + count_fsb -= numblks_fsb; + } while (count_fsb > 0); + + return 0; + +error_on_bmapi_transaction: + xfs_bmap_cancel(&free_list); + xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT)); + xfs_iunlock(ip, XFS_ILOCK_EXCL); +error0: + return XFS_ERROR(error); +} -- cgit v1.2.3 From 9a5c2c0c3f73eee29aac15a26200060d29b7bd6f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 31 Jan 2004 12:13:08 +1100 Subject: [XFS] Small ktrace fixes SGI Modid: xfs-linux:xfs-kern:164115a --- fs/xfs/linux/xfs_buf.c | 4 ++++ fs/xfs/xfs_attr.c | 3 +-- fs/xfs/xfs_bmap_btree.c | 2 +- fs/xfs/xfs_dir.c | 2 +- fs/xfs/xfs_dir2_trace.c | 4 +--- fs/xfs/xfs_vfsops.c | 19 +++++++++++++++++++ 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index 891fa4447f36..b575fbbae709 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -2091,6 +2091,10 @@ pagebuf_terminate(void) { pagebuf_daemon_stop(); +#ifdef PAGEBUF_TRACE + ktrace_free(pagebuf_trace_buf); +#endif + kmem_cache_destroy(pagebuf_cache); unregister_sysctl_table(pagebuf_table_header); diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 229674c01bf8..088cb2321ee2 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -106,12 +106,11 @@ STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ #define ATTR_RMTVALUE_TRANSBLKS 8 /* max # of blks in a transaction */ -#if defined(DEBUG) +#if defined(XFS_ATTR_TRACE) ktrace_t *xfs_attr_trace_buf; #endif - /*======================================================================== * Overall external interface routines. *========================================================================*/ diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 44cfa392eab1..788e80064936 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -61,7 +61,7 @@ #include "xfs_error.h" #include "xfs_quota.h" -#ifdef DEBUG +#if defined(XFS_BMBT_TRACE) ktrace_t *xfs_bmbt_trace_buf; #endif diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c index 5e4ad55f3c24..3ea04f9ac231 100644 --- a/fs/xfs/xfs_dir.c +++ b/fs/xfs/xfs_dir.c @@ -162,7 +162,7 @@ STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, xfs_dir_put_t put); STATIC int xfs_dir_node_replace(xfs_da_args_t *args); -#if defined(DEBUG) +#if defined(XFS_DIR_TRACE) ktrace_t *xfs_dir_trace_buf; #endif diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c index 41b87fa14945..c6747162f251 100644 --- a/fs/xfs/xfs_dir2_trace.c +++ b/fs/xfs/xfs_dir2_trace.c @@ -49,11 +49,9 @@ #include "xfs_da_btree.h" #include "xfs_dir2_trace.h" -#ifdef DEBUG +#ifdef XFS_DIR2_TRACE ktrace_t *xfs_dir2_trace_buf; -#endif /* DEBUG */ -#ifdef XFS_DIR2_TRACE /* * Enter something in the trace buffers. */ diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 4bae0b60977e..2ecd9b3dc74d 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -171,6 +171,25 @@ xfs_cleanup(void) xfs_sysctl_unregister(); xfs_refcache_destroy(); +#ifdef XFS_DIR2_TRACE + ktrace_free(xfs_dir2_trace_buf); +#endif +#ifdef XFS_ATTR_TRACE + ktrace_free(xfs_attr_trace_buf); +#endif +#ifdef XFS_DIR_TRACE + ktrace_free(xfs_dir_trace_buf); +#endif +#ifdef XFS_BMBT_TRACE + ktrace_free(xfs_bmbt_trace_buf); +#endif +#ifdef XFS_BMAP_TRACE + ktrace_free(xfs_bmap_trace_buf); +#endif +#ifdef XFS_ALLOC_TRACE + ktrace_free(xfs_alloc_trace_buf); +#endif + kmem_cache_destroy(xfs_bmap_free_item_zone); kmem_cache_destroy(xfs_btree_cur_zone); kmem_cache_destroy(xfs_inode_zone); -- cgit v1.2.3 From dd68c5dece4306b3a257a1651dd59110eb808c6e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 31 Jan 2004 12:17:49 +1100 Subject: [XFS] Simplify pagebuf_rele / pagebuf_free SGI Modid: xfs-linux:xfs-kern:165500a --- fs/xfs/linux/xfs_buf.c | 61 ++++++++++---------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index b575fbbae709..a6c09faca0b0 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -207,7 +207,6 @@ EXPORT_SYMBOL(pagebuf_trace_buf); typedef struct { struct list_head pb_hash; - int pb_count; spinlock_t pb_hash_lock; } pb_hash_t; @@ -378,26 +377,27 @@ _pagebuf_freepages( } /* - * _pagebuf_free_object + * pagebuf_free * - * _pagebuf_free_object releases the contents specified buffer. - * The modification state of any associated pages is left unchanged. + * pagebuf_free releases the specified buffer. The modification + * state of any associated pages is left unchanged. */ void -_pagebuf_free_object( - pb_hash_t *hash, /* hash bucket for buffer */ - page_buf_t *pb) /* buffer to deallocate */ +pagebuf_free( + page_buf_t *pb) { page_buf_flags_t pb_flags = pb->pb_flags; + pb_hash_t *hash; PB_TRACE(pb, "free_object", 0); pb->pb_flags |= PBF_FREED; - if (hash) { - if (!list_empty(&pb->pb_hash_list)) { - hash->pb_count--; + if (pb->pb_flags & _PBF_LOCKABLE) { + hash = pb_hash(pb); + + spin_lock(&hash->pb_hash_lock); + if (!list_empty(&pb->pb_hash_list)) list_del_init(&pb->pb_hash_list); - } spin_unlock(&hash->pb_hash_lock); } @@ -668,7 +668,6 @@ _pagebuf_find( /* find buffer for block */ _pagebuf_initialize(new_pb, target, range_base, range_length, flags | _PBF_LOCKABLE); new_pb->pb_hash_index = hval; - h->pb_count++; list_add(&new_pb->pb_hash_list, &h->pb_hash); } else { PB_STATS_INC(pb_miss_locked); @@ -999,26 +998,6 @@ pagebuf_hold( PB_TRACE(pb, "hold", 0); } -/* - * pagebuf_free - * - * pagebuf_free releases the specified buffer. The modification - * state of any associated pages is left unchanged. - */ -void -pagebuf_free( - page_buf_t *pb) -{ - if (pb->pb_flags & _PBF_LOCKABLE) { - pb_hash_t *h = pb_hash(pb); - - spin_lock(&h->pb_hash_lock); - _pagebuf_free_object(h, pb); - } else { - _pagebuf_free_object(NULL, pb); - } -} - /* * pagebuf_rele * @@ -1029,44 +1008,28 @@ void pagebuf_rele( page_buf_t *pb) { - pb_hash_t *h; - PB_TRACE(pb, "rele", pb->pb_relse); - if (pb->pb_flags & _PBF_LOCKABLE) { - h = pb_hash(pb); - spin_lock(&h->pb_hash_lock); - } else { - h = NULL; - } if (atomic_dec_and_test(&pb->pb_hold)) { int do_free = 1; if (pb->pb_relse) { atomic_inc(&pb->pb_hold); - if (h) - spin_unlock(&h->pb_hash_lock); (*(pb->pb_relse)) (pb); do_free = 0; } if (pb->pb_flags & PBF_DELWRI) { pb->pb_flags |= PBF_ASYNC; atomic_inc(&pb->pb_hold); - if (h && do_free) - spin_unlock(&h->pb_hash_lock); pagebuf_delwri_queue(pb, 0); do_free = 0; } else if (pb->pb_flags & PBF_FS_MANAGED) { - if (h) - spin_unlock(&h->pb_hash_lock); do_free = 0; } if (do_free) { - _pagebuf_free_object(h, pb); + pagebuf_free(pb); } - } else if (h) { - spin_unlock(&h->pb_hash_lock); } } -- cgit v1.2.3 From 20bc7252ca14b4311ed255f5859184e86a5d1e28 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Sat, 31 Jan 2004 12:21:20 +1100 Subject: [XFS] Revert botched merge where KM_NOFS check was unintentionally dropped. SGI Modid: xfs-linux:xfs-kern:165631a --- fs/xfs/linux/kmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/linux/kmem.h b/fs/xfs/linux/kmem.h index a8fb09f2f604..a75bdd210884 100644 --- a/fs/xfs/linux/kmem.h +++ b/fs/xfs/linux/kmem.h @@ -90,7 +90,7 @@ kmem_flags_convert(int flags) lflags = (flags & KM_NOSLEEP) ? GFP_ATOMIC : (GFP_KERNEL|__GFP_NOFAIL); /* avoid recusive callbacks to filesystem during transactions */ - if (PFLAGS_TEST_FSTRANS()) + if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) lflags &= ~__GFP_FS; return lflags; -- cgit v1.2.3 From bd997c62b77d1a72ac39e8b7e3595585db342589 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Sat, 31 Jan 2004 12:25:16 +1100 Subject: [XFS] Add the security extended attributes namespace. SGI Modid: xfs-linux:xfs-kern:165638a --- fs/xfs/linux/xfs_super.h | 9 +++++++++ fs/xfs/xfs_attr.c | 20 +++++++++++++++++++- fs/xfs/xfs_attr.h | 4 +++- fs/xfs/xfs_attr_leaf.c | 45 +++++++++++++++++++++++++++++++++++---------- fs/xfs/xfs_attr_leaf.h | 8 +++++--- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/fs/xfs/linux/xfs_super.h b/fs/xfs/linux/xfs_super.h index d2238a9f6db5..2716ad9296fb 100644 --- a/fs/xfs/linux/xfs_super.h +++ b/fs/xfs/linux/xfs_super.h @@ -60,6 +60,14 @@ # define set_posix_acl_flag(sb) do { } while (0) #endif +#ifdef CONFIG_XFS_SECURITY +# define XFS_SECURITY_STRING "security attrs, " +# define ENOSECURITY 0 +#else +# define XFS_SECURITY_STRING +# define ENOSECURITY EOPNOTSUPP +#endif + #ifdef CONFIG_XFS_RT # define XFS_REALTIME_STRING "realtime, " #else @@ -89,6 +97,7 @@ #endif #define XFS_BUILD_OPTIONS XFS_ACL_STRING \ + XFS_SECURITY_STRING \ XFS_REALTIME_STRING \ XFS_BIGFS_STRING \ XFS_TRACE_STRING \ diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 088cb2321ee2..898de3642fec 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -2587,6 +2587,14 @@ attr_trusted_capable( return 0; } +STATIC int +attr_secure_capable( + struct vnode *vp, + cred_t *cred) +{ + return -ENOSECURITY; +} + STATIC int attr_system_set( struct vnode *vp, char *name, void *data, size_t size, int xflags) @@ -2650,6 +2658,16 @@ struct attrnames attr_trusted = { .attr_capable = attr_trusted_capable, }; +struct attrnames attr_secure = { + .attr_name = "security.", + .attr_namelen = sizeof("security.") - 1, + .attr_flag = ATTR_SECURE, + .attr_get = attr_generic_get, + .attr_set = attr_generic_set, + .attr_remove = attr_generic_remove, + .attr_capable = attr_secure_capable, +}; + struct attrnames attr_user = { .attr_name = "user.", .attr_namelen = sizeof("user.") - 1, @@ -2660,4 +2678,4 @@ struct attrnames attr_user = { }; struct attrnames *attr_namespaces[] = - { &attr_system, &attr_trusted, &attr_user }; + { &attr_system, &attr_trusted, &attr_secure, &attr_user }; diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index a7e05c671917..c83011f9706d 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -69,8 +69,9 @@ typedef struct attrnames { attrcapable_t attr_capable; } attrnames_t; -#define ATTR_NAMECOUNT 3 +#define ATTR_NAMECOUNT 4 extern struct attrnames attr_user; +extern struct attrnames attr_secure; extern struct attrnames attr_system; extern struct attrnames attr_trusted; extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; @@ -86,6 +87,7 @@ extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ #define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */ +#define ATTR_SECURE 0x0008 /* use attrs in security namespace */ #define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ #define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */ diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 06e386f3539a..22f38db4ee9a 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -159,6 +159,9 @@ xfs_attr_shortform_add(xfs_da_args_t *args) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -173,7 +176,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args) sfe->namelen = args->namelen; INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen); - sfe->flags = (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; + sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : + ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); memcpy(sfe->nameval, args->name, args->namelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); INT_MOD(sf->hdr.count, ARCH_CONVERT, 1); @@ -209,6 +213,9 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) continue; if (memcmp(sfe->nameval, args->name, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -253,6 +260,9 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -281,6 +291,9 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args) continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((sfe->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -369,7 +382,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); nargs.hashval = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); - nargs.flags = (sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; + nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : + ((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ ASSERT(error == ENOATTR); error = xfs_attr_leaf_add(bp, &nargs); @@ -446,14 +460,15 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { attrnames_t *namesp; - namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && !(context->flags & ATTR_KERNFULLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; } + namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure: + ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (context->flags & ATTR_KERNOVAL) { ASSERT(context->flags & ATTR_KERNAMELS); context->count += namesp->attr_namelen + @@ -548,8 +563,9 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) for ( ; i < nsbuf; i++, sbp++) { attrnames_t *namesp; - namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; + namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure : + ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) { cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT); @@ -668,7 +684,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) nargs.value = (char *)&name_loc->nameval[nargs.namelen]; nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); - nargs.flags = (entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; + nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE : + ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0); xfs_attr_shortform_add(&nargs); } error = 0; @@ -963,7 +980,8 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) + INT_GET(map->size, ARCH_CONVERT)); INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); entry->flags = tmp ? XFS_ATTR_LOCAL : 0; - entry->flags |= (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; + entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE : + ((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0); if (args->rename) { entry->flags |= XFS_ATTR_INCOMPLETE; if ((args->blkno2 == args->blkno) && @@ -1881,6 +1899,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((entry->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -1893,6 +1914,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) if (memcmp(args->name, (char *)name_rmt->name, args->namelen) != 0) continue; + if (((args->flags & ATTR_SECURE) != 0) != + ((entry->flags & XFS_ATTR_SECURE) != 0)) + continue; if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) continue; @@ -2290,8 +2314,9 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) !(context->flags & ATTR_KERNFULLS)) continue; /* skip non-matching entries */ - namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : - &attr_user; + namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure : + ((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : + &attr_user); if (entry->flags & XFS_ATTR_LOCAL) { name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 8f2b36c7356c..97bac75c6064 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -73,9 +73,9 @@ struct xfs_trans; * to work "forw"ard. If none matches, continue with the "forw"ard leaf * nodes until the hash key changes or the attribute name is found. * - * We store the fact that an attribute is a ROOT versus USER attribute in + * We store the fact that an attribute is a ROOT/USER/SECURE attribute in * the leaf_entry. The namespaces are independent only because we also look - * at the root/user bit when we are looking for a matching attribute name. + * at the namespace bit when we are looking for a matching attribute name. * * We also store a "incomplete" bit in the leaf_entry. It shows that an * attribute is in the middle of being created and should not be shown to @@ -102,7 +102,7 @@ typedef struct xfs_attr_leafblock { struct xfs_attr_leaf_entry { /* sorted on key, not name */ xfs_dahash_t hashval; /* hash value of name */ __uint16_t nameidx; /* index into buffer of name/value */ - __uint8_t flags; /* LOCAL, ROOT and INCOMPLETE flags */ + __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ __uint8_t pad2; /* unused pad byte */ } entries[1]; /* variable sized array */ struct xfs_attr_leaf_name_local { @@ -130,9 +130,11 @@ typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t; */ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) /* -- cgit v1.2.3 From 876a4fb3540bc66542c2b3632f967552b4c5bd4d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 31 Jan 2004 12:29:35 +1100 Subject: [XFS] Don't fail pagebuf allocations SGI Modid: xfs-linux:xfs-kern:165648a --- fs/xfs/linux/xfs_buf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index a6c09faca0b0..07edfd524785 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -193,10 +193,14 @@ EXPORT_SYMBOL(pagebuf_trace_buf); (((flags) & PBF_READ_AHEAD) ? GFP_READAHEAD : \ ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) +#define pb_to_km(flags) \ + (((flags) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) + + #define pagebuf_allocate(flags) \ - kmem_cache_alloc(pagebuf_cache, pb_to_gfp(flags)) + kmem_zone_alloc(pagebuf_cache, pb_to_km(flags)) #define pagebuf_deallocate(pb) \ - kmem_cache_free(pagebuf_cache, (pb)); + kmem_zone_free(pagebuf_cache, (pb)); /* * Pagebuf hashing -- cgit v1.2.3 From e63a85b63e8f445808d1e9a5e1d168e9996b49b3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 31 Jan 2004 12:33:34 +1100 Subject: [XFS] Stop using sleep_on SGI Modid: xfs-linux:xfs-kern:165673a --- fs/xfs/linux/xfs_buf.c | 53 ++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index 07edfd524785..4805c2e4318a 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -81,7 +81,7 @@ */ STATIC kmem_cache_t *pagebuf_cache; -STATIC void pagebuf_daemon_wakeup(int); +STATIC void pagebuf_daemon_wakeup(void); STATIC void pagebuf_delwri_queue(page_buf_t *, int); STATIC struct workqueue_struct *pagebuf_logio_workqueue; STATIC struct workqueue_struct *pagebuf_dataio_workqueue; @@ -516,7 +516,7 @@ _pagebuf_lookup_pages( if (!page) { if (--retry_count > 0) { PB_STATS_INC(pb_page_retries); - pagebuf_daemon_wakeup(1); + pagebuf_daemon_wakeup(); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(10); goto retry; @@ -1646,7 +1646,6 @@ pagebuf_iomove( * Pagebuf delayed write buffer handling */ -STATIC int pbd_active = 1; STATIC LIST_HEAD(pbd_delwrite_queue); STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED; @@ -1693,21 +1692,19 @@ pagebuf_runall_queues( } /* Defines for pagebuf daemon */ -DECLARE_WAIT_QUEUE_HEAD(pbd_waitq); +STATIC DECLARE_COMPLETION(pagebuf_daemon_done); +STATIC struct task_struct *pagebuf_daemon_task; +STATIC int pagebuf_daemon_active; STATIC int force_flush; STATIC void -pagebuf_daemon_wakeup( - int flag) +pagebuf_daemon_wakeup(void) { - force_flush = flag; - if (waitqueue_active(&pbd_waitq)) { - wake_up_interruptible(&pbd_waitq); - } + force_flush = 1; + barrier(); + wake_up_process(pagebuf_daemon_task); } -typedef void (*timeout_fn)(unsigned long); - STATIC int pagebuf_daemon( void *data) @@ -1715,29 +1712,23 @@ pagebuf_daemon( int count; page_buf_t *pb; struct list_head *curr, *next, tmp; - struct timer_list pb_daemon_timer = - TIMER_INITIALIZER((timeout_fn)pagebuf_daemon_wakeup, 0, 0); /* Set up the thread */ daemonize("pagebufd"); - current->flags |= PF_MEMALLOC; + pagebuf_daemon_task = current; + pagebuf_daemon_active = 1; + barrier(); + INIT_LIST_HEAD(&tmp); do { /* swsusp */ if (current->flags & PF_FREEZE) refrigerator(PF_IOTHREAD); - if (pbd_active == 1) { - mod_timer(&pb_daemon_timer, - jiffies + pb_params.flush_interval.val); - interruptible_sleep_on(&pbd_waitq); - } - - if (pbd_active == 0) { - del_timer_sync(&pb_daemon_timer); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(pb_params.flush_interval.val); spin_lock(&pbd_delwrite_lock); @@ -1781,12 +1772,9 @@ pagebuf_daemon( blk_run_queues(); force_flush = 0; - } while (pbd_active == 1); - - pbd_active = -1; - wake_up_interruptible(&pbd_waitq); + } while (pagebuf_daemon_active); - return 0; + complete_and_exit(&pagebuf_daemon_done, 0); } void @@ -1896,9 +1884,10 @@ pagebuf_daemon_start(void) STATIC void pagebuf_daemon_stop(void) { - pbd_active = 0; - wake_up_interruptible(&pbd_waitq); - wait_event_interruptible(pbd_waitq, pbd_active); + pagebuf_daemon_active = 0; + barrier(); + wait_for_completion(&pagebuf_daemon_done); + destroy_workqueue(pagebuf_logio_workqueue); destroy_workqueue(pagebuf_dataio_workqueue); } -- cgit v1.2.3 From 1b7447bf48d9711322191605b3f8bef66c6ab899 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 31 Jan 2004 12:36:57 +1100 Subject: [XFS] Plug a pagebuf race that got bigger with the recent cleanup SGI Modid: xfs-linux:xfs-kern:165722a --- fs/xfs/linux/xfs_buf.c | 69 +++++++++++++++++++++++++------------------------- fs/xfs/linux/xfs_buf.h | 2 -- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index 4805c2e4318a..c4fba9f269c8 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -390,45 +390,46 @@ void pagebuf_free( page_buf_t *pb) { - page_buf_flags_t pb_flags = pb->pb_flags; - pb_hash_t *hash; - - PB_TRACE(pb, "free_object", 0); - pb->pb_flags |= PBF_FREED; + PB_TRACE(pb, "free", 0); if (pb->pb_flags & _PBF_LOCKABLE) { - hash = pb_hash(pb); + pb_hash_t *hash = pb_hash(pb); spin_lock(&hash->pb_hash_lock); - if (!list_empty(&pb->pb_hash_list)) + /* + * Someone grabbed a reference while we weren't looking, + * try again later. + */ + if (unlikely(atomic_read(&pb->pb_hold))) { + spin_unlock(&hash->pb_hash_lock); + return; + } else if (!list_empty(&pb->pb_hash_list)) list_del_init(&pb->pb_hash_list); spin_unlock(&hash->pb_hash_lock); } - if (!(pb_flags & PBF_FREED)) { - /* release any virtual mapping */ ; - if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { - void *vaddr = pagebuf_mapout_locked(pb); - if (vaddr) { - free_address(vaddr); - } + /* release any virtual mapping */ ; + if (pb->pb_flags & _PBF_ADDR_ALLOCATED) { + void *vaddr = pagebuf_mapout_locked(pb); + if (vaddr) { + free_address(vaddr); } + } - if (pb->pb_flags & _PBF_MEM_ALLOCATED) { - if (pb->pb_pages) { - /* release the pages in the address list */ - if ((pb->pb_pages[0]) && - (pb->pb_flags & _PBF_MEM_SLAB)) { - kfree(pb->pb_addr); - } else { - _pagebuf_freepages(pb); - } - if (pb->pb_pages != pb->pb_page_array) - kfree(pb->pb_pages); - pb->pb_pages = NULL; + if (pb->pb_flags & _PBF_MEM_ALLOCATED) { + if (pb->pb_pages) { + /* release the pages in the address list */ + if ((pb->pb_pages[0]) && + (pb->pb_flags & _PBF_MEM_SLAB)) { + kfree(pb->pb_addr); + } else { + _pagebuf_freepages(pb); } - pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); + if (pb->pb_pages != pb->pb_page_array) + kfree(pb->pb_pages); + pb->pb_pages = NULL; } + pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB); } pagebuf_deallocate(pb); @@ -653,16 +654,15 @@ _pagebuf_find( /* find buffer for block */ list_for_each(p, &h->pb_hash) { pb = list_entry(p, page_buf_t, pb_hash_list); - if ((target == pb->pb_target) && - (pb->pb_file_offset == range_base) && - (pb->pb_buffer_length == range_length)) { - if (pb->pb_flags & PBF_FREED) - break; + if (pb->pb_target == target && + pb->pb_file_offset == range_base && + pb->pb_buffer_length == range_length && + atomic_read(&pb->pb_hold)) { /* If we look at something bring it to the * front of the list for next time */ - list_del(&pb->pb_hash_list); - list_add(&pb->pb_hash_list, &h->pb_hash); + atomic_inc(&pb->pb_hold); + list_move(&pb->pb_hash_list, &h->pb_hash); goto found; } } @@ -681,7 +681,6 @@ _pagebuf_find( /* find buffer for block */ return (new_pb); found: - atomic_inc(&pb->pb_hold); spin_unlock(&h->pb_hash_lock); /* Attempt to get the semaphore without sleeping, diff --git a/fs/xfs/linux/xfs_buf.h b/fs/xfs/linux/xfs_buf.h index 809a845cb0fe..d8a481857e42 100644 --- a/fs/xfs/linux/xfs_buf.h +++ b/fs/xfs/linux/xfs_buf.h @@ -76,7 +76,6 @@ typedef enum page_buf_flags_e { /* pb_flags values */ PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ PBF_NONE = (1 << 5), /* buffer not read at all */ PBF_DELWRI = (1 << 6), /* buffer has dirty pages */ - PBF_FREED = (1 << 7), /* buffer has been freed and is invalid */ PBF_SYNC = (1 << 8), /* force updates to disk */ PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */ PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */ @@ -90,7 +89,6 @@ typedef enum page_buf_flags_e { /* pb_flags values */ /* flags used only internally */ _PBF_LOCKABLE = (1 << 16), /* page_buf_t may be locked */ - _PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads */ _PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped */ _PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated */ _PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated */ -- cgit v1.2.3 From 2dc452001c3301af96e5d3750f8b4e9d83273cd8 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Sat, 31 Jan 2004 13:04:45 +1100 Subject: [XFS] Remove no-longer-needed debug symbol exports. --- fs/xfs/linux/xfs_buf.c | 11 ------ fs/xfs/linux/xfs_globals.c | 86 ++-------------------------------------------- fs/xfs/quota/xfs_qm.c | 1 - fs/xfs/support/ktrace.c | 3 -- 4 files changed, 3 insertions(+), 98 deletions(-) diff --git a/fs/xfs/linux/xfs_buf.c b/fs/xfs/linux/xfs_buf.c index c4fba9f269c8..6fe563ca046a 100644 --- a/fs/xfs/linux/xfs_buf.c +++ b/fs/xfs/linux/xfs_buf.c @@ -45,7 +45,6 @@ * */ -#include #include #include #include @@ -167,7 +166,6 @@ pagebuf_trace( NULL, NULL, NULL, NULL, NULL); } ktrace_t *pagebuf_trace_buf; -EXPORT_SYMBOL(pagebuf_trace_buf); #define PAGEBUF_TRACE_SIZE 4096 #define PB_TRACE(pb, id, data) \ pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0)) @@ -2058,12 +2056,3 @@ pagebuf_terminate(void) remove_proc_entry("fs/pagebuf", NULL); #endif } - - -/* - * Module management (for kernel debugger module) - */ -EXPORT_SYMBOL(pagebuf_offset); -#ifdef DEBUG -EXPORT_SYMBOL(pbd_delwrite_queue); -#endif diff --git a/fs/xfs/linux/xfs_globals.c b/fs/xfs/linux/xfs_globals.c index 5f17264fe4d9..9267e539fd13 100644 --- a/fs/xfs/linux/xfs_globals.c +++ b/fs/xfs/linux/xfs_globals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -36,57 +36,8 @@ */ #include "xfs.h" - -#include "xfs_fs.h" -#include "xfs_buf.h" -#include "xfs_inum.h" -#include "xfs_log.h" -#include "xfs_clnt.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_imap.h" -#include "xfs_alloc.h" -#include "xfs_dmapi.h" -#include "xfs_quota.h" -#include "xfs_mount.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_bit.h" -#include "xfs_rtalloc.h" -#include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_rw.h" -#include "xfs_da_btree.h" -#include "xfs_dir_leaf.h" -#include "xfs_dir2_data.h" -#include "xfs_dir2_leaf.h" -#include "xfs_dir2_block.h" -#include "xfs_dir2_node.h" -#include "xfs_dir2_trace.h" -#include "xfs_acl.h" -#include "xfs_cap.h" -#include "xfs_mac.h" -#include "xfs_attr.h" -#include "xfs_attr_leaf.h" -#include "xfs_inode_item.h" -#include "xfs_buf_item.h" -#include "xfs_extfree_item.h" -#include "xfs_log_priv.h" -#include "xfs_trans_priv.h" -#include "xfs_trans_space.h" -#include "xfs_utils.h" +#include "xfs_cred.h" +#include "xfs_sysctl.h" /* * System memory size - used to scale certain data structures in XFS. @@ -117,34 +68,3 @@ xfs_param_t xfs_params = { */ cred_t sys_cred_val, *sys_cred = &sys_cred_val; -/* - * Export symbols used for XFS debugging - */ -EXPORT_SYMBOL(xfs_next_bit); -EXPORT_SYMBOL(xfs_contig_bits); -EXPORT_SYMBOL(xfs_bmbt_get_all); -#if ARCH_CONVERT != ARCH_NOCONVERT -EXPORT_SYMBOL(xfs_bmbt_disk_get_all); -#endif - -/* - * Export symbols used for XFS tracing - */ -#ifdef XFS_ALLOC_TRACE -EXPORT_SYMBOL(xfs_alloc_trace_buf); -#endif -#ifdef XFS_BMAP_TRACE -EXPORT_SYMBOL(xfs_bmap_trace_buf); -#endif -#ifdef XFS_BMBT_TRACE -EXPORT_SYMBOL(xfs_bmbt_trace_buf); -#endif -#ifdef XFS_ATTR_TRACE -EXPORT_SYMBOL(xfs_attr_trace_buf); -#endif -#ifdef XFS_DIR2_TRACE -EXPORT_SYMBOL(xfs_dir2_trace_buf); -#endif -#ifdef XFS_DIR_TRACE -EXPORT_SYMBOL(xfs_dir_trace_buf); -#endif diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 0f853a505b81..9633b155dcf4 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -78,7 +78,6 @@ */ mutex_t xfs_Gqm_lock; struct xfs_qm *xfs_Gqm; -EXPORT_SYMBOL(xfs_Gqm); /* used by xfsidbg */ kmem_zone_t *qm_dqzone; kmem_zone_t *qm_dqtrxzone; diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c index e776812da8bc..0190ad2f86d3 100644 --- a/fs/xfs/support/ktrace.c +++ b/fs/xfs/support/ktrace.c @@ -30,7 +30,6 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include #include #include @@ -273,7 +272,6 @@ ktrace_first(ktrace_t *ktp, ktrace_snap_t *ktsp) } return ktep; } -EXPORT_SYMBOL(ktrace_first); /* * ktrace_next() @@ -308,7 +306,6 @@ ktrace_next( return ktep; } -EXPORT_SYMBOL(ktrace_next); /* * ktrace_skip() -- cgit v1.2.3 From 20abba2cca5779805a8220a56a71e1ecdc29aac6 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Sat, 31 Jan 2004 14:43:00 +1100 Subject: [XFS] Sync up some missing header updates from local XFS tree. --- fs/xfs/linux/xfs_linux.h | 46 ++++++++++++++++++++++++++++++++++++++-------- fs/xfs/support/uuid.c | 9 +-------- fs/xfs/xfs.h | 13 ------------- fs/xfs/xfs_types.h | 18 ------------------ 4 files changed, 39 insertions(+), 47 deletions(-) diff --git a/fs/xfs/linux/xfs_linux.h b/fs/xfs/linux/xfs_linux.h index 1cf06f8ec8ff..c6631b45d6af 100644 --- a/fs/xfs/linux/xfs_linux.h +++ b/fs/xfs/linux/xfs_linux.h @@ -32,6 +32,44 @@ #ifndef __XFS_LINUX__ #define __XFS_LINUX__ +#include +#include + +/* + * Some types are conditional depending on the target system. + * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. + * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well + * as requiring XFS_BIG_BLKNOS to be set. + */ +#if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) +# define XFS_BIG_BLKNOS 1 +# if BITS_PER_LONG == 64 +# define XFS_BIG_INUMS 1 +# else +# define XFS_BIG_INUMS 0 +# endif +#else +# define XFS_BIG_BLKNOS 0 +# define XFS_BIG_INUMS 0 +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + #include #include #include @@ -55,14 +93,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include - #include #include #include diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index 7e44857648ab..81f40cfcb267 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c @@ -30,14 +30,7 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include -#include -#include -#include -#include -#include -#include "uuid.h" -#include "debug.h" +#include static mutex_t uuid_monitor; static int uuid_table_size; diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index d916806daf77..0e9354961621 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -32,21 +32,8 @@ #ifndef __XFS_H__ #define __XFS_H__ -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - #include #include -#include #endif /* __XFS_H__ */ diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 9ba24c9e9dad..8d6aac75047c 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h @@ -75,24 +75,6 @@ typedef __uint64_t __psunsigned_t; #error BITS_PER_LONG must be 32 or 64 #endif -/* - * Some types are conditional depending on the target system. - * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. - * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well - * as requiring XFS_BIG_BLKNOS to be set. - */ -#if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) -# define XFS_BIG_BLKNOS 1 -# if BITS_PER_LONG == 64 -# define XFS_BIG_INUMS 1 -# else -# define XFS_BIG_INUMS 0 -# endif -#else -# define XFS_BIG_BLKNOS 0 -# define XFS_BIG_INUMS 0 -#endif - #endif /* __KERNEL__ */ typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */ -- cgit v1.2.3 From 7704432ccf8f798830e8543105a548a064f34c71 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Jan 2004 01:30:07 -0800 Subject: Linux 2.6.2-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a466cfcf02c5..fb0f5d458dae 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 2 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc3 # *DOCUMENTATION* # To see a list of typical targets execute "make help" -- cgit v1.2.3 From 5f99d385f8450d1a567b9fb05f4f078cc6a71bb5 Mon Sep 17 00:00:00 2001 From: Mirko Lindner Date: Fri, 30 Jan 2004 15:11:03 -0500 Subject: [PATCH] sk98lin: Reset Xmac when stopping the port * Clear the Xmac fifo before stopping the port --- drivers/net/sk98lin/h/skversion.h | 10 +++++----- drivers/net/sk98lin/skge.c | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h index e9b11d64eff6..c9be206fae60 100644 --- a/drivers/net/sk98lin/h/skversion.h +++ b/drivers/net/sk98lin/h/skversion.h @@ -61,14 +61,14 @@ #ifdef lint static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.21 PL: 01"; + "@(#)SK-BUILD: 6.22 PL: 01"; #endif /* !defined(lint) */ -#define BOOT_STRING "sk98lin: Network Device Driver v6.21\n" \ - "(C)Copyright 1999-2003 Marvell(R)." +#define BOOT_STRING "sk98lin: Network Device Driver v6.22\n" \ + "(C)Copyright 1999-2004 Marvell(R)." -#define VER_STRING "6.21" +#define VER_STRING "6.22" #define DRIVER_FILE_NAME "sk98lin" -#define DRIVER_REL_DATE "Dec-15-2003" +#define DRIVER_REL_DATE "Jan-30-2004" diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 32cf0c1be5fa..390c31b2ac9b 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -2,8 +2,8 @@ * * Name: skge.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.42 $ - * Date: $Date: 2003/12/12 10:05:43 $ + * Version: $Revision: 1.43 $ + * Date: $Date: 2004/01/29 15:47:07 $ * Purpose: The main driver source module * ******************************************************************************/ @@ -41,6 +41,9 @@ * History: * * $Log: skge.c,v $ + * Revision 1.43 2004/01/29 15:47:07 mlindner + * Fix: Reset Xmac when stopping the port + * * Revision 1.42 2003/12/12 10:05:43 mlindner * Fix: Format of error message corrected * @@ -2154,6 +2157,7 @@ struct SK_NET_DEVICE *dev) EvPara.Para32[0] = pNet->NetNr; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); @@ -5002,6 +5006,7 @@ SK_BOOL DualNet; spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; spin_unlock_irqrestore( -- cgit v1.2.3 From a72ffca549526edd29121e06fff5a013773ca9c7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:56:03 -0800 Subject: [PATCH] ppc32: watchdog definition fixes From: Tom Rini Correct the defines for MC146818 RTCs, reg c is interrupts, reg d is not watchdog (it's valid time & nvram). --- include/asm-ppc/todc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h index 0419f2803ecd..5a9e53c21eba 100644 --- a/include/asm-ppc/todc.h +++ b/include/asm-ppc/todc.h @@ -290,8 +290,8 @@ typedef struct { #define TODC_TYPE_MC146818_SECONDS 0x00 #define TODC_TYPE_MC146818_CNTL_B 0x0a #define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_MC146818_WATCHDOG 0x0c -#define TODC_TYPE_MC146818_INTERRUPTS 0x0d +#define TODC_TYPE_MC146818_WATCHDOG 0 +#define TODC_TYPE_MC146818_INTERRUPTS 0x0c #define TODC_TYPE_MC146818_ALARM_DATE 0xff #define TODC_TYPE_MC146818_ALARM_HOUR 0x05 #define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 -- cgit v1.2.3 From d29df610b087713c1e245b3cdd8cbf88e2b1f326 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:56:15 -0800 Subject: [PATCH] ppc64: add missing include guards, from Nathan Lynch From: Anton Blanchard add missing include guards, from Nathan Lynch --- include/asm-ppc64/bugs.h | 4 ++++ include/asm-ppc64/hvcall.h | 3 +++ include/asm-ppc64/percpu.h | 6 +++--- include/asm-ppc64/ppc_asm.h | 4 ++++ include/asm-ppc64/ptrace-common.h | 4 ++++ include/asm-ppc64/serial.h | 6 +++++- 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/asm-ppc64/bugs.h b/include/asm-ppc64/bugs.h index 3b95d97ab75d..861074b3cf71 100644 --- a/include/asm-ppc64/bugs.h +++ b/include/asm-ppc64/bugs.h @@ -3,6 +3,10 @@ * bugs. * */ +#ifndef _ASM_PPC64_BUGS_H +#define _ASM_PPC64_BUGS_H static void check_bugs(void) { } + +#endif /* _ASM_PPC64_BUGS_H */ diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h index d963feaa077c..13b78b8fc2b4 100644 --- a/include/asm-ppc64/hvcall.h +++ b/include/asm-ppc64/hvcall.h @@ -1,3 +1,5 @@ +#ifndef _PPC64_HVCALL_H +#define _PPC64_HVCALL_H #define H_Success 0 #define H_Busy 1 /* Hardware busy -- retry later */ @@ -138,3 +140,4 @@ long plpar_hcall_4out(unsigned long opcode, unsigned long *out3, unsigned long *out4); +#endif /* _PPC64_HVCALL_H */ diff --git a/include/asm-ppc64/percpu.h b/include/asm-ppc64/percpu.h index 5764afa4b6a4..60a659a4ce1f 100644 --- a/include/asm-ppc64/percpu.h +++ b/include/asm-ppc64/percpu.h @@ -1,6 +1,6 @@ -#ifndef __ARCH_I386_PERCPU__ -#define __ARCH_I386_PERCPU__ +#ifndef __ARCH_PPC64_PERCPU__ +#define __ARCH_PPC64_PERCPU__ #include -#endif /* __ARCH_I386_PERCPU__ */ +#endif /* __ARCH_PPC64_PERCPU__ */ diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h index a33d6347bd63..6ac08bb267e0 100644 --- a/include/asm-ppc64/ppc_asm.h +++ b/include/asm-ppc64/ppc_asm.h @@ -11,6 +11,8 @@ * 2 of the License, or (at your option) any later version. */ +#ifndef _PPC64_PPC_ASM_H +#define _PPC64_PPC_ASM_H /* * Macros for storing registers into and loading registers from * exception frames. @@ -238,3 +240,5 @@ #define vr29 29 #define vr30 30 #define vr31 31 + +#endif /* _PPC64_PPC_ASM_H */ diff --git a/include/asm-ppc64/ptrace-common.h b/include/asm-ppc64/ptrace-common.h index b3295b1bf992..3dbd3e5847b3 100644 --- a/include/asm-ppc64/ptrace-common.h +++ b/include/asm-ppc64/ptrace-common.h @@ -9,6 +9,8 @@ * this archive for more details. */ +#ifndef _PPC64_PTRACE_COMMON_H +#define _PPC64_PTRACE_COMMON_H /* * Set of msr bits that gdb can change on behalf of a process. */ @@ -64,3 +66,5 @@ static inline void clear_single_step(struct task_struct *task) if (regs != NULL) regs->msr &= ~MSR_SE; } + +#endif /* _PPC64_PTRACE_COMMON_H */ diff --git a/include/asm-ppc64/serial.h b/include/asm-ppc64/serial.h index 64c4e0eef700..edf5886c24c3 100644 --- a/include/asm-ppc64/serial.h +++ b/include/asm-ppc64/serial.h @@ -1,6 +1,8 @@ /* - * include/asm-ppc/serial.h + * include/asm-ppc64/serial.h */ +#ifndef _PPC64_SERIAL_H +#define _PPC64_SERIAL_H #include @@ -124,3 +126,5 @@ EXTRA_SERIAL_PORT_DEFNS \ HUB6_SERIAL_PORT_DFNS \ MCA_SERIAL_PORT_DFNS + +#endif /* _PPC64_SERIAL_H */ -- cgit v1.2.3 From f18a90120091c8dec478aca861ccbf624d67b1de Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:56:28 -0800 Subject: [PATCH] ppc64: lparcfg_write From: Anton Blanchard Add lparcfg_write() for changing SPLPAR system parameters --- arch/ppc64/kernel/lparcfg.c | 107 +++++++++++++++++++++++++++++++++++++++++++- include/asm-ppc64/hvcall.h | 1 + 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index 501076d6dd49..c41d5bbae084 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -5,6 +5,8 @@ * Copyright (c) 2003 Dave Engebretsen * Will Schmidt willschm@us.ibm.com * SPLPAR updates, Copyright (c) 2003 Will Schmidt IBM Corporation. + * Nathan Lynch nathanl@austin.ibm.com + * Added lparcfg_write, Copyright (C) 2004 Nathan Lynch IBM Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,6 +35,9 @@ static struct proc_dir_entry *proc_ppc64_lparcfg; #define LPARCFG_BUFF_SIZE 4096 #ifdef CONFIG_PPC_ISERIES + +#define lparcfg_write NULL + static unsigned char e2a(unsigned char x) { switch (x) { @@ -383,6 +388,99 @@ static int lparcfg_data(unsigned char *buf, unsigned long size) } return 0; } + +/* + * Interface for changing system parameters (variable capacity weight + * and entitled capacity). Format of input is "param_name=value"; + * anything after value is ignored. Valid parameters at this time are + * "partition_entitled_capacity" and "capacity_weight". We use + * H_SET_PPP to alter parameters. + * + * This function should be invoked only on systems with + * FW_FEATURE_SPLPAR. + */ +static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t count, loff_t *off) +{ + char *kbuf; + char *tmp; + u64 new_entitled, *new_entitled_ptr = &new_entitled; + u8 new_weight, *new_weight_ptr = &new_weight; + + unsigned long current_entitled; /* parameters for h_get_ppp */ + unsigned long dummy; + unsigned long resource; + u8 current_weight; + + ssize_t retval = -ENOMEM; + + kbuf = kmalloc(count, GFP_KERNEL); + if (!kbuf) + goto out; + + retval = -EFAULT; + if (copy_from_user(kbuf, buf, count)) + goto out; + + retval = -EINVAL; + kbuf[count - 1] = '\0'; + tmp = strchr(kbuf, '='); + if (!tmp) + goto out; + + *tmp++ = '\0'; + + if (!strcmp(kbuf, "partition_entitled_capacity")) { + char *endp; + *new_entitled_ptr = (u64)simple_strtoul(tmp, &endp, 10); + if (endp == tmp) + goto out; + new_weight_ptr = ¤t_weight; + } else if (!strcmp(kbuf, "capacity_weight")) { + char *endp; + *new_weight_ptr = (u8)simple_strtoul(tmp, &endp, 10); + if (endp == tmp) + goto out; + new_entitled_ptr = ¤t_entitled; + } else + goto out; + + /* Get our current parameters */ + retval = h_get_ppp(¤t_entitled, &dummy, &dummy, &resource); + if (retval) { + retval = -EIO; + goto out; + } + + current_weight = (resource>>5*8)&0xFF; + + pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", + __FUNCTION__, current_entitled, current_weight); + + pr_debug("%s: new_entitled = %lu, new_weight = %lu\n", + __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); + + retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, + *new_weight_ptr); + + if (retval == H_Success || retval == H_Constrained) { + retval = count; + } else if (retval == H_Busy) { + retval = -EBUSY; + } else if (retval == H_Hardware) { + retval = -EIO; + } else if (retval == H_Parameter) { + retval = -EINVAL; + } else { + printk(KERN_WARNING "%s: received unknown hv return code %ld", + __FUNCTION__, retval); + retval = -EIO; + } + +out: + kfree(kbuf); + return retval; +} + #endif /* CONFIG_PPC_PSERIES */ @@ -442,8 +540,15 @@ struct file_operations lparcfg_fops = { int __init lparcfg_init(void) { struct proc_dir_entry *ent; + mode_t mode = S_IRUSR; + + /* Allow writing if we have FW_FEATURE_SPLPAR */ + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + lparcfg_fops.write = lparcfg_write; + mode |= S_IWUSR; + } - ent = create_proc_entry("ppc64/lparcfg", S_IRUSR, NULL); + ent = create_proc_entry("ppc64/lparcfg", mode, NULL); if (ent) { ent->proc_fops = &lparcfg_fops; ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL); diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h index 13b78b8fc2b4..5ddaf5474166 100644 --- a/include/asm-ppc64/hvcall.h +++ b/include/asm-ppc64/hvcall.h @@ -3,6 +3,7 @@ #define H_Success 0 #define H_Busy 1 /* Hardware busy -- retry later */ +#define H_Constrained 4 /* Resource request constrained to max allowed */ #define H_Hardware -1 /* Hardware error */ #define H_Function -2 /* Function not supported */ #define H_Privilege -3 /* Caller not privileged */ -- cgit v1.2.3 From 13bbb0504ae0b319dc7082c1a746db622f068f79 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:56:46 -0800 Subject: [PATCH] ppc64: fixes for compile with CONFIG_PROC_DEVICETREE=n, from Nathan Lynch From: Anton Blanchard - nop out proc_device_tree_add_node if CONFIG_PROC_DEVICETREE=n - stubs for procfs-related functions when CONFIG_PROC_DEVICETREE=n --- arch/ppc64/kernel/prom.c | 12 ++++++++++++ include/linux/proc_fs.h | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index fc8cf79ca315..6ca6e63cd5f3 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -2560,6 +2560,7 @@ int of_remove_node(struct device_node *np) return 0; } +#ifdef CONFIG_PROC_DEVICETREE /* * Add a node to /proc/device-tree. */ @@ -2592,6 +2593,17 @@ static void remove_node_proc_entries(struct device_node *np) if (np->pde) remove_proc_entry(np->pde->name, parent->pde); } +#else /* !CONFIG_PROC_DEVICETREE */ +static void add_node_proc_entries(struct device_node *np) +{ + return; +} + +static void remove_node_proc_entries(struct device_node *np) +{ + return; +} +#endif /* CONFIG_PROC_DEVICETREE */ /* * Fix up the uninitialized fields in a new device node: diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 2b3c8dadb1fb..8b8a6c0b37f3 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -133,8 +133,14 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver); */ struct device_node; extern void proc_device_tree_init(void); +#ifdef CONFIG_PROC_DEVICETREE extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); - +#else /* !CONFIG_PROC_DEVICETREE */ +static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) +{ + return; +} +#endif /* CONFIG_PROC_DEVICETREE */ /* * proc_rtas.c */ -- cgit v1.2.3 From 6016190fc5d9b3f3fcdc2d67c521b0475b8c7c13 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:57:06 -0800 Subject: [PATCH] ppc64: missing set_fs(KERNEL_DS) in ppc32_timer_create, from Marcus Meissner From: Anton Blanchard Small obvious fix to ppc32_timer_create. Since sys_timer_create access structures we pass on the stack, we need set_fs(KERNEL_DS). --- arch/ppc64/kernel/sys_ppc32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index 5f81ce807dcc..b71b5e8248ed 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -2845,6 +2845,7 @@ long ppc32_timer_create(clockid_t clock, return -EFAULT; savefs = get_fs(); + set_fs(KERNEL_DS); err = sys_timer_create(clock, &event, &t); set_fs(savefs); -- cgit v1.2.3 From 7892828dcf3b1dd81790e810ecc1ea71c38e945d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:57:29 -0800 Subject: [PATCH] ppc64: defconfig update From: Anton Blanchard --- arch/ppc64/defconfig | 202 +++++++++++++++++++++++++++------------------------ 1 file changed, 106 insertions(+), 96 deletions(-) diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig index 40dc0b93728c..4769c33c3cec 100644 --- a/arch/ppc64/defconfig +++ b/arch/ppc64/defconfig @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit # +CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_ISA_DMA=y @@ -14,7 +15,8 @@ CONFIG_FORCE_MAX_ZONEORDER=13 # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_BROKEN is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y # # General setup @@ -33,6 +35,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -51,21 +54,23 @@ CONFIG_OBSOLETE_MODPARM=y CONFIG_PPC_PSERIES=y CONFIG_PPC=y CONFIG_PPC64=y +CONFIG_ALTIVEC=y +# CONFIG_POWER4_ONLY is not set CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y CONFIG_NR_CPUS=32 # CONFIG_HMT is not set # CONFIG_DISCONTIGMEM is not set -# CONFIG_RTAS_FLASH is not set -CONFIG_SCANLOG=y CONFIG_PPC_RTAS=y +CONFIG_RTAS_FLASH=m +CONFIG_SCANLOG=m +CONFIG_LPARCFG=y # # General setup # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y @@ -74,6 +79,10 @@ CONFIG_PCI_NAMES=y CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set +# +# Device Drivers +# + # # Generic Driver Options # @@ -117,6 +126,7 @@ CONFIG_BLK_DEV_INITRD=y # SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -145,9 +155,9 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set @@ -155,18 +165,21 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INIA100 is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX_CONFIG=y +CONFIG_SCSI_QLA2XXX=y +CONFIG_SCSI_QLA21XX=y +CONFIG_SCSI_QLA22XX=y +CONFIG_SCSI_QLA23XX=y # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set @@ -181,6 +194,7 @@ CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID5=y +# CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set CONFIG_BLK_DEV_DM=y CONFIG_DM_IOCTL_V4=y @@ -240,7 +254,9 @@ CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -268,7 +284,6 @@ CONFIG_DUMMY=m CONFIG_BONDING=m # CONFIG_EQUALIZER is not set CONFIG_TUN=m -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) @@ -292,6 +307,7 @@ CONFIG_PCNET32=y # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=y @@ -303,7 +319,6 @@ CONFIG_E100=y # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # @@ -344,10 +359,10 @@ CONFIG_PPPOE=m # CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # +# CONFIG_TR is not set # CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -365,6 +380,11 @@ CONFIG_PPPOE=m # # CONFIG_IRDA is not set +# +# Bluetooth support +# +# CONFIG_BT is not set + # # ISDN subsystem # @@ -433,6 +453,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -444,20 +465,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 CONFIG_HVC_CONSOLE=y -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - # # Mice # @@ -483,11 +490,15 @@ CONFIG_HVC_CONSOLE=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=y -# CONFIG_HANGCHECK_TIMER is not set +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices @@ -499,6 +510,67 @@ CONFIG_RAW_DRIVER=y # # CONFIG_DVB is not set +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G450=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_MULTIHEAD=y +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_GADGET is not set + # # File systems # @@ -551,11 +623,14 @@ CONFIG_VFAT_FS=y # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y # @@ -580,6 +655,7 @@ CONFIG_CRAMFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y CONFIG_NFSD_V4=y @@ -602,11 +678,11 @@ CONFIG_CIFS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set @@ -646,72 +722,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set -# -# Graphics support -# -CONFIG_FB=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_OF=y -# CONFIG_FB_CT65550 is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_S3TRIO is not set -# CONFIG_FB_VGA16 is not set -# CONFIG_FB_RIVA is not set -CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_PCI_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - # # Profiling support # -- cgit v1.2.3 From ea23458e4a33988547bc74addbb18ca7fc853d41 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:57:58 -0800 Subject: [PATCH] ppc64: Use preferred_console to select a reasonable default console From: Anton Blanchard Lets make a decent attempt to find out where your console is. The new preferred_console stuff is pretty nice. --- arch/ppc64/kernel/setup.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index 9f4d27328b16..27292d6cfd2a 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c @@ -38,6 +38,7 @@ #include #include #include +#include #include extern unsigned long klimit; @@ -430,8 +431,58 @@ void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, } } - #ifdef CONFIG_PPC_PSERIES +static int __init set_preferred_console(void) +{ + struct device_node *prom_stdout; + char *name; + + /* The user has requested a console so this is already set up. */ + if (strstr(cmd_line, "console=")) + return -EBUSY; + + prom_stdout = find_path_device(of_stdout_device); + if (!prom_stdout) + return -ENODEV; + + name = (char *)get_property(prom_stdout, "name", NULL); + if (!name) + return -ENODEV; + + if (strcmp(name, "serial") == 0) { + int i; + u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i); + if (i > 8) { + int offset; + switch (reg[1]) { + case 0x3f8: + offset = 0; + break; + case 0x2f8: + offset = 1; + break; + case 0x898: + offset = 2; + break; + case 0x890: + offset = 3; + break; + default: + /* We dont recognise the serial port */ + return -ENODEV; + } + + return add_preferred_console("ttyS", offset, NULL); + } + } else if (strcmp(name, "vty") == 0) { + /* pSeries LPAR virtual console */ + return add_preferred_console("hvc", 0, NULL); + } + + return -ENODEV; +} +console_initcall(set_preferred_console); + int parse_bootinfo(void) { struct bi_record *rec; -- cgit v1.2.3 From f5786cb050ace564c1dd07a0467d2e224de58937 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:58:34 -0800 Subject: [PATCH] ppc64: add/remove config.h From: Anton Blanchard --- arch/ppc64/kernel/asm-offsets.c | 1 + arch/ppc64/kernel/iSeries_VpdInfo.c | 1 + arch/ppc64/kernel/lparcfg.c | 1 + arch/ppc64/kernel/proc_ppc64.c | 1 + arch/ppc64/kernel/rtas_flash.c | 2 -- arch/ppc64/kernel/signal.c | 1 + arch/ppc64/kernel/signal32.c | 1 + arch/ppc64/kernel/sys_ppc32.c | 1 + arch/ppc64/kernel/viopath.c | 1 - arch/ppc64/mm/hash_low.S | 1 - arch/ppc64/mm/hugetlbpage.c | 1 - arch/ppc64/xmon/start.c | 1 + include/asm-ppc64/cputable.h | 2 ++ include/asm-ppc64/mmu.h | 1 + include/asm-ppc64/mmu_context.h | 1 + include/asm-ppc64/pgtable.h | 1 + include/asm-ppc64/processor.h | 1 + 17 files changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 38bcdcac3c3b..98e8d373b1a5 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -13,6 +13,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c index 5173cee43a14..016462aaf61c 100644 --- a/arch/ppc64/kernel/iSeries_VpdInfo.c +++ b/arch/ppc64/kernel/iSeries_VpdInfo.c @@ -25,6 +25,7 @@ /* Ported to ppc64, August 20, 2001 */ /* End Change Activity */ /************************************************************************/ +#include #include #include #include diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index c41d5bbae084..df6aa551b028 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -17,6 +17,7 @@ * keyword - value pairs that specify the configuration of the partition. */ +#include #include #include #include diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c index d8b70f96f539..25605d5e0b01 100644 --- a/arch/ppc64/kernel/proc_ppc64.c +++ b/arch/ppc64/kernel/proc_ppc64.c @@ -27,6 +27,7 @@ * End Change Activity */ +#include #include #include #include diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c index 25bd5da3274d..fc42b535a3a5 100644 --- a/arch/ppc64/kernel/rtas_flash.c +++ b/arch/ppc64/kernel/rtas_flash.c @@ -14,8 +14,6 @@ */ #include - -#include #include #include #include diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c index f5f336f5feb5..9e01dd3f3eb3 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/ppc64/kernel/signal.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index 8bcf79b2e195..54f41394680e 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index b71b5e8248ed..e5a832aa89bb 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c index 4448dc806fac..ca7b8eaac38e 100644 --- a/arch/ppc64/kernel/viopath.c +++ b/arch/ppc64/kernel/viopath.c @@ -28,7 +28,6 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include #include #include #include diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S index a25f6373a595..0ea88a0fa2a0 100644 --- a/arch/ppc64/mm/hash_low.S +++ b/arch/ppc64/mm/hash_low.S @@ -10,7 +10,6 @@ * described in the kernel's COPYING file. */ -#include #include #include #include diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c index eed5c1ca5bbb..738adc97e478 100644 --- a/arch/ppc64/mm/hugetlbpage.c +++ b/arch/ppc64/mm/hugetlbpage.c @@ -7,7 +7,6 @@ * Copyright (C) 2002, Rohit Seth */ -#include #include #include #include diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c index 85cb27421bd1..02e6940b1784 100644 --- a/arch/ppc64/xmon/start.c +++ b/arch/ppc64/xmon/start.c @@ -6,6 +6,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h index 15206be6a46e..e3c4ad343254 100644 --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -15,6 +15,8 @@ #ifndef __ASM_PPC_CPUTABLE_H #define __ASM_PPC_CPUTABLE_H +#include + /* Exposed to userland CPU features - Must match ppc32 definitions */ #define PPC_FEATURE_32 0x80000000 #define PPC_FEATURE_64 0x40000000 diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index 8ae3a400e131..95f3f8b4fbfd 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -13,6 +13,7 @@ #ifndef _PPC64_MMU_H_ #define _PPC64_MMU_H_ +#include #include #ifndef __ASSEMBLY__ diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 11a399c33086..48893d641bdc 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -1,6 +1,7 @@ #ifndef __PPC64_MMU_CONTEXT_H #define __PPC64_MMU_CONTEXT_H +#include #include #include #include diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index 5cefc49da027..061505d38a73 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -7,6 +7,7 @@ */ #ifndef __ASSEMBLY__ +#include #include #include /* For TASK_SIZE */ #include diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index 9ec883bf1c7c..ffb684f7ab71 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -12,6 +12,7 @@ #include #ifndef __ASSEMBLY__ +#include #include #include #include -- cgit v1.2.3 From 6d8cdd4b2f88453493962d1a85da4bab79b16c9d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:59:07 -0800 Subject: [PATCH] ppc64: export memchr and csum_partial From: Anton Blanchard --- arch/ppc64/kernel/ppc_ksyms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index cc01d78363c4..f353677843ff 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -83,7 +83,7 @@ EXPORT_SYMBOL(__up); EXPORT_SYMBOL(naca); EXPORT_SYMBOL(__down); -/* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */ +EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(ip_fast_csum); EXPORT_SYMBOL(csum_tcpudp_magic); @@ -191,12 +191,12 @@ EXPORT_SYMBOL(find_all_nodes); EXPORT_SYMBOL(get_property); #endif - EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(memscan); EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL_NOVERS(memchr); EXPORT_SYMBOL(abs); -- cgit v1.2.3 From 79c5772415858a62d1bcd2e368abd1e66560f2da Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 17:59:52 -0800 Subject: [PATCH] ppc64: fix && vs & bugs in lparcfg, from Julie DeWandel From: Anton Blanchard --- arch/ppc64/kernel/lparcfg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index df6aa551b028..7ff67beec366 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -332,7 +332,7 @@ static int lparcfg_data(unsigned char *buf, unsigned long size) system_potential_processors = get_splpar_potential_characteristics(); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%d\n", - (h_resource >> 2*8) && 0xffff); + (h_resource >> 2*8) & 0xffff); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", system_potential_processors); @@ -373,16 +373,16 @@ static int lparcfg_data(unsigned char *buf, unsigned long size) if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "pool=%d\n", (h_aggregation >> 0*8)&&0xffff); + "pool=%d\n", (h_aggregation >> 0*8)&0xffff); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "pool_capacity=%d\n", (h_resource >> 3*8) &&0xffff); + "pool_capacity=%d\n", (h_resource >> 3*8) &0xffff); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "group=%d\n", (h_aggregation >> 2*8)&&0xffff); + "group=%d\n", (h_aggregation >> 2*8)&0xffff); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, - "capped=%d\n", (h_resource >> 6*8)&&0x40); + "capped=%d\n", (h_resource >> 6*8)&0x40); n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF); -- cgit v1.2.3 From 326f372c368ddefb3275ce087be603a1f4cfd923 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:00:40 -0800 Subject: [PATCH] ppc64: SLB rewrite From: Anton Blanchard The current SLB handling code has a number of problems: - We loop trying to find an empty SLB entry before deciding to cast one out. On large working sets this really hurts since the SLB is always full and we end up looping through all 64 entries unnecessarily. - During castout we currently invalidate the entry we are replacing. This is to avoid a nasty race where the entry is in the ERAT but not the SLB and another cpu does a tlbie that removes the ERAT at a critical point. If this race is fixed the SLB can be removed. - The SLB prefault code doesnt work properly The following patch addresses all the above concerns and adds some more optimisations: - feature nop out some segment table only code - slb invalidate the kernel segment on context switch (avoids us having to slb invalidate at each cast out) - optimise flush on context switch, the lazy tlb stuff avoids it being called when going from userspace to kernel thread, but it gets called when going to kernel thread to userspace. In many cases we are returning to the same userspace task, we now check for this and avoid the flush - use the optimised POWER4 mtcrf where possible --- arch/ppc64/kernel/head.S | 157 +++++++++------ arch/ppc64/kernel/pacaData.c | 1 - arch/ppc64/kernel/process.c | 24 +++ arch/ppc64/kernel/stab.c | 436 ++++++++++++++++++++++------------------ include/asm-ppc64/cputable.h | 9 +- include/asm-ppc64/mmu.h | 8 - include/asm-ppc64/mmu_context.h | 11 +- include/asm-ppc64/paca.h | 23 +-- 8 files changed, 386 insertions(+), 283 deletions(-) diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index c1c0c5022cea..6a16bfac8ad5 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -646,12 +646,14 @@ fast_exception_return: */ .globl DataAccess_common DataAccess_common: +BEGIN_FTR_SECTION mfspr r22,DAR srdi r22,r22,60 cmpi 0,r22,0xc /* Segment fault on a bolted segment. Go off and map that segment. */ beq- .do_stab_bolted +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) stab_bolted_user_return: EXCEPTION_PROLOG_COMMON ld r3,_DSISR(r1) @@ -661,10 +663,12 @@ stab_bolted_user_return: rlwinm r4,r3,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */ ld r3,_DAR(r1) /* into the hash table */ +BEGIN_FTR_SECTION beq+ 2f /* If so handle it */ li r4,0x300 /* Trap number */ bl .do_stab_SI b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) 2: li r5,0x300 bl .do_hash_page_DSI /* Try to handle as hpte fault */ @@ -690,7 +694,7 @@ DataAccessSLB_common: EXCEPTION_PROLOG_COMMON ld r3,_DAR(r1) li r4,0x380 /* Exception vector */ - bl .ste_allocate + bl .slb_allocate or. r3,r3,r3 /* Check return code */ beq fast_exception_return /* Return if we succeeded */ addi r3,r1,STACK_FRAME_OVERHEAD @@ -705,12 +709,14 @@ DataAccessSLB_common: InstructionAccess_common: EXCEPTION_PROLOG_COMMON +BEGIN_FTR_SECTION andis. r0,r23,0x0020 /* no ste found? */ beq+ 2f mr r3,r22 /* SRR0 at interrupt */ li r4,0x400 /* Trap number */ bl .do_stab_SI b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) 2: mr r3,r22 li r5,0x400 @@ -730,7 +736,7 @@ InstructionAccessSLB_common: EXCEPTION_PROLOG_COMMON mr r3,r22 /* SRR0 = NIA */ li r4,0x480 /* Exception vector */ - bl .ste_allocate + bl .slb_allocate or. r3,r3,r3 /* Check return code */ beq+ fast_exception_return /* Return if we succeeded */ @@ -1006,48 +1012,27 @@ _GLOBAL(do_stab_bolted) * r20 - r23, SRR0 and SRR1 are saved in the exception frame. * We assume we aren't going to take any exceptions during this procedure. */ +/* XXX note fix masking in get_kernel_vsid to match */ _GLOBAL(do_slb_bolted) - stw r23,EX_CCR(r21) /* save CR in exc. frame */ + stw r23,EX_CCR(r21) /* save CR in exc. frame */ - /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ - mfspr r21,DAR - rldicl r20,r21,36,32 /* Permits a full 32b of ESID */ - rldicr r20,r20,15,48 - rldicl r21,r21,4,60 - or r20,r20,r21 - - li r21,9 /* VSID_RANDOMIZER */ - sldi r21,r21,32 - oris r21,r21,58231 - ori r21,r21,39831 - - mulld r20,r20,r21 - clrldi r20,r20,28 /* r20 = vsid */ - - /* Search the SLB for a free entry */ - li r22,1 -1: - slbmfee r23,r22 - rldicl r23,r23,37,63 - cmpwi r23,0 - beq 4f /* Found an invalid entry */ - - addi r22,r22,1 - cmpldi r22,64 - blt 1b + /* + * We take the next entry, round robin. Previously we tried + * to find a free slot first but that took too long. Unfortunately + * we dont have any LRU information to help us choose a slot. + */ - /* No free entry - just take the next entry, round-robin */ - /* XXX we should get the number of SLB entries from the naca */ + /* r20 = paca */ + /* use a cpu feature mask if we ever change our slb size */ SLB_NUM_ENTRIES = 64 -2: mfspr r21,SPRG3 - ld r22,PACASTABRR(r21) - addi r23,r22,1 - cmpdi r23,SLB_NUM_ENTRIES - blt 3f - li r23,1 -3: std r23,PACASTABRR(r21) +1: ld r22,PACASTABRR(r20) + addi r21,r22,1 + cmpdi r21,SLB_NUM_ENTRIES + blt+ 2f + li r21,1 /* dont touch bolted slot 0 */ +2: std r21,PACASTABRR(r20) - /* r20 = vsid, r22 = entry */ + /* r20 = paca, r22 = entry */ /* * Never cast out the segment for our kernel stack. Since we @@ -1056,48 +1041,86 @@ SLB_NUM_ENTRIES = 64 * which gets invalidated due to a tlbie from another cpu at a * non recoverable point (after setting srr0/1) - Anton */ - slbmfee r23,r22 - srdi r23,r23,28 + slbmfee r21,r22 + srdi r21,r21,27 /* * This is incorrect (r1 is not the kernel stack) if we entered * from userspace but there is no critical window from userspace * so this should be OK. Also if we cast out the userspace stack * segment while in userspace we will fault it straight back in. */ - srdi r21,r1,28 - cmpd r21,r23 - beq- 2b - - /* Put together the vsid portion of the entry. */ -4: li r21,0 - rldimi r21,r20,12,0 - ori r20,r21,1024 - ori r20,r20,128 /* set class bit for kernel region */ -#ifndef CONFIG_PPC_ISERIES - ori r20,r20,256 /* map kernel region with large ptes */ -#endif + srdi r23,r1,27 + ori r23,r23,1 + cmpd r23,r21 + beq- 1b + + /* r20 = paca, r22 = entry */ + + /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ + mfspr r21,DAR + rldicl r23,r21,36,51 + sldi r23,r23,15 + srdi r21,r21,60 + or r23,r23,r21 + + /* VSID_RANDOMIZER */ + li r21,9 + sldi r21,r21,32 + oris r21,r21,58231 + ori r21,r21,39831 + + /* vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK */ + mulld r23,r23,r21 + clrldi r23,r23,28 + + /* r20 = paca, r22 = entry, r23 = vsid */ + + /* Put together slb word1 */ + sldi r23,r23,12 + +BEGIN_FTR_SECTION + /* set kp and c bits */ + ori r23,r23,0x480 +END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) +BEGIN_FTR_SECTION + /* set kp, l and c bits */ + ori r23,r23,0x580 +END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) + + /* r20 = paca, r22 = entry, r23 = slb word1 */ + + /* Put together slb word0 */ + mfspr r21,DAR + rldicr r21,r21,0,35 /* get the new esid */ + oris r21,r21,2048 /* set valid bit */ + rldimi r21,r22,0,52 /* insert entry */ - /* Put together the esid portion of the entry. */ - mfspr r21,DAR /* Get the new esid */ - rldicl r21,r21,36,28 /* Permits a full 36b of ESID */ - li r23,0 - rldimi r23,r21,28,0 /* Insert esid */ - oris r21,r23,2048 /* valid bit */ - rldimi r21,r22,0,52 /* Insert entry */ + /* r20 = paca, r21 = slb word0, r23 = slb word1 */ /* * No need for an isync before or after this slbmte. The exception * we enter with and the rfid we exit with are context synchronizing . */ - slbmte r20,r21 + slbmte r23,r21 /* All done -- return from exception. */ - mfsprg r20,3 /* Load the PACA pointer */ - ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */ - addi r21,r21,EXC_FRAME_SIZE + ld r21,PACAEXCSP(r20) /* Get the exception frame pointer */ + addi r21,r21,EXC_FRAME_SIZE lwz r23,EX_CCR(r21) /* get saved CR */ /* note that this is almost identical to maskable_exception_exit */ - mtcr r23 /* restore CR */ + + /* + * Until everyone updates binutils hardwire the POWER4 optimised + * single field mtcrf + */ +#if 0 + .machine push + .machine "power4" + mtcrf 0x80,r23 + .machine pop +#else + .long 0x7ef80120 +#endif mfmsr r22 li r23, MSR_RI @@ -1107,10 +1130,10 @@ SLB_NUM_ENTRIES = 64 ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ mtspr SRR0,r22 - mtspr SRR1,r23 + mtspr SRR1,r23 ld r22,EX_R22(r21) /* restore r22 and r23 */ ld r23,EX_R23(r21) - mfspr r20,SPRG2 + ld r20,EX_R20(r21) mfspr r21,SPRG1 rfid diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 1cc6e4d910e5..422254f349e4 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -41,7 +41,6 @@ struct systemcfg *systemcfg; .xStab_data = { \ .real = (asrr), /* Real pointer to segment table */ \ .virt = (asrv), /* Virt pointer to segment table */ \ - .next_round_robin = 1 /* Round robin index */ \ }, \ .lpQueuePtr = (lpq), /* &xItLpQueue, */ \ /* .xRtas = { \ diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 041827788def..320b0b2e7e88 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c @@ -151,7 +151,31 @@ struct task_struct *__switch_to(struct task_struct *prev, local_irq_save(flags); last = _switch(old_thread, new_thread); + + /* + * force our kernel stack out of the ERAT and SLB, this is to + * avoid the race where we it hangs around in the ERAT but not the + * SLB and the ERAT gets invalidated at just the wrong moment by + * another CPU doing a tlbie. + * + * We definitely dont want to flush our bolted segment, so check + * for that first. + */ + if ((cur_cpu_spec->cpu_features & CPU_FTR_SLB) && + GET_ESID((unsigned long)_get_SP()) != GET_ESID(PAGE_OFFSET)) { + union { + unsigned long word0; + slb_dword0 data; + } esid_data; + + esid_data.word0 = 0; + /* class bit is in valid field for slbie instruction */ + esid_data.data.v = 1; + esid_data.data.esid = GET_ESID((unsigned long)_get_SP()); + asm volatile("isync; slbie %0; isync" : : "r" (esid_data)); + } local_irq_restore(flags); + return last; } diff --git a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c index 656a347c22b2..65b340d3e08e 100644 --- a/arch/ppc64/kernel/stab.c +++ b/arch/ppc64/kernel/stab.c @@ -12,8 +12,6 @@ * 2 of the License, or (at your option) any later version. */ -/* XXX Note: Changes for bolted region have not been merged - Anton */ - #include #include #include @@ -59,6 +57,15 @@ void stab_initialize(unsigned long stab) } } +/* Both the segment table and SLB code uses the following cache */ +#define NR_STAB_CACHE_ENTRIES 8 +DEFINE_PER_CPU(long, stab_cache_ptr); +DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]); + +/* + * Segment table stuff + */ + /* * Create a segment table entry for the given esid/vsid pair. */ @@ -91,14 +98,8 @@ int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) /* * Could not find empty entry, pick one with a round robin selection. - * Search all entries in the two groups. Note that the first time - * we get here, we start with entry 1 so the initializer - * can be common with the SLB castout code. + * Search all entries in the two groups. */ - - /* This assumes we never castout when initializing the stab. */ - PMC_SW_PROCESSOR(stab_capacity_castouts); - castout_entry = get_paca()->xStab_data.next_round_robin; for (i = 0; i < 16; i++) { if (castout_entry < 8) { @@ -123,23 +124,169 @@ int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) /* Modify the old entry to the new value. */ /* Force previous translations to complete. DRENG */ - asm volatile("isync" : : : "memory" ); + asm volatile("isync" : : : "memory"); castout_ste->dw0.dw0.v = 0; - asm volatile("sync" : : : "memory" ); /* Order update */ + asm volatile("sync" : : : "memory"); /* Order update */ castout_ste->dw1.dw1.vsid = vsid; old_esid = castout_ste->dw0.dw0.esid; castout_ste->dw0.dw0.esid = esid; castout_ste->dw0.dw0.kp = 1; - asm volatile("eieio" : : : "memory" ); /* Order update */ + asm volatile("eieio" : : : "memory"); /* Order update */ castout_ste->dw0.dw0.v = 1; asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); /* Ensure completion of slbie */ - asm volatile("sync" : : : "memory" ); + asm volatile("sync" : : : "memory"); return (global_entry | (castout_entry & 0x7)); } +static inline void __ste_allocate(unsigned long esid, unsigned long vsid, + mm_context_t context) +{ + unsigned char stab_entry; + unsigned long *offset; + int region_id = REGION_ID(esid << SID_SHIFT); + + stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid); + + if (region_id != USER_REGION_ID) + return; + + offset = &__get_cpu_var(stab_cache_ptr); + if (*offset < NR_STAB_CACHE_ENTRIES) { + __get_cpu_var(stab_cache[*offset]) = stab_entry; + } + (*offset)++; +} + +/* + * Allocate a segment table entry for the given ea. + */ +int ste_allocate(unsigned long ea) +{ + unsigned long vsid, esid; + mm_context_t context; + + /* Check for invalid effective addresses. */ + if (!IS_VALID_EA(ea)) + return 1; + + /* Kernel or user address? */ + if (REGION_ID(ea) >= KERNEL_REGION_ID) { + vsid = get_kernel_vsid(ea); + context = REGION_ID(ea); + } else { + if (!current->mm) + return 1; + + context = current->mm->context; + vsid = get_vsid(context, ea); + } + + esid = GET_ESID(ea); + __ste_allocate(esid, vsid, context); + /* Order update */ + asm volatile("sync":::"memory"); + + return 0; +} + +/* + * preload some userspace segments into the segment table. + */ +static void preload_stab(struct task_struct *tsk, struct mm_struct *mm) +{ + unsigned long pc = KSTK_EIP(tsk); + unsigned long stack = KSTK_ESP(tsk); + unsigned long unmapped_base; + unsigned long pc_esid = GET_ESID(pc); + unsigned long stack_esid = GET_ESID(stack); + unsigned long unmapped_base_esid; + unsigned long vsid; + + if (test_tsk_thread_flag(tsk, TIF_32BIT)) + unmapped_base = TASK_UNMAPPED_BASE_USER32; + else + unmapped_base = TASK_UNMAPPED_BASE_USER64; + + unmapped_base_esid = GET_ESID(unmapped_base); + + if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, pc); + __ste_allocate(pc_esid, vsid, mm->context); + + if (pc_esid == stack_esid) + return; + + if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, stack); + __ste_allocate(stack_esid, vsid, mm->context); + + if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid) + return; + + if (!IS_VALID_EA(unmapped_base) || + (REGION_ID(unmapped_base) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, unmapped_base); + __ste_allocate(unmapped_base_esid, vsid, mm->context); + + /* Order update */ + asm volatile("sync" : : : "memory"); +} + +/* Flush all user entries from the segment table of the current processor. */ +void flush_stab(struct task_struct *tsk, struct mm_struct *mm) +{ + STE *stab = (STE *) get_paca()->xStab_data.virt; + STE *ste; + unsigned long *offset = &__get_cpu_var(stab_cache_ptr); + + /* Force previous translations to complete. DRENG */ + asm volatile("isync" : : : "memory"); + + if (*offset <= NR_STAB_CACHE_ENTRIES) { + int i; + + for (i = 0; i < *offset; i++) { + ste = stab + __get_cpu_var(stab_cache[i]); + ste->dw0.dw0.v = 0; + } + + asm volatile("sync; slbia; sync":::"memory"); + } else { + unsigned long entry; + + /* Invalidate all entries. */ + ste = stab; + + /* Never flush the first entry. */ + ste += 1; + for (entry = 1; + entry < (PAGE_SIZE / sizeof(STE)); + entry++, ste++) { + unsigned long ea; + ea = ste->dw0.dw0.esid << SID_SHIFT; + if (ea < KERNELBASE) { + ste->dw0.dw0.v = 0; + } + } + + asm volatile("sync; slbia; sync":::"memory"); + } + + *offset = 0; + + preload_stab(tsk, mm); +} + +/* + * SLB stuff + */ + /* * Create a segment buffer entry for the given esid/vsid pair. * @@ -160,22 +307,11 @@ void make_slbe(unsigned long esid, unsigned long vsid, int large, } vsid_data; /* - * Find an empty entry, if one exists. Must start at 0 because - * we use this code to load SLB entry 0 at boot. - */ - for (entry = 0; entry < naca->slb_size; entry++) { - asm volatile("slbmfee %0,%1" - : "=r" (esid_data) : "r" (entry)); - if (!esid_data.data.v) - goto write_entry; - } - - /* - * Could not find empty entry, pick one with a round robin selection. + * We take the next entry, round robin. Previously we tried + * to find a free slot first but that took too long. Unfortunately + * we dont have any LRU information to help us choose a slot. */ - PMC_SW_PROCESSOR(stab_capacity_castouts); - /* * Never cast out the segment for our kernel stack. Since we * dont invalidate the ERAT we could have a valid translation @@ -190,13 +326,13 @@ void make_slbe(unsigned long esid, unsigned long vsid, int large, if (castout_entry >= naca->slb_size) castout_entry = 1; asm volatile("slbmfee %0,%1" : "=r" (esid_data) : "r" (entry)); - } while (esid_data.data.esid == GET_ESID((unsigned long)_get_SP())); + } while (esid_data.data.v && + esid_data.data.esid == GET_ESID((unsigned long)_get_SP())); get_paca()->xStab_data.next_round_robin = castout_entry; /* slbie not needed as the previous mapping is still valid. */ -write_entry: /* * Write the new SLB entry. */ @@ -220,211 +356,129 @@ write_entry: asm volatile("slbmte %0,%1" : : "r" (vsid_data), "r" (esid_data)); } -static inline void __ste_allocate(unsigned long esid, unsigned long vsid, - int kernel_segment, mm_context_t context) +static inline void __slb_allocate(unsigned long esid, unsigned long vsid, + mm_context_t context) { - if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { - int large = 0; + int large = 0; + int region_id = REGION_ID(esid << SID_SHIFT); + unsigned long *offset; -#ifndef CONFIG_PPC_ISERIES - if (REGION_ID(esid << SID_SHIFT) == KERNEL_REGION_ID) + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) { + if (region_id == KERNEL_REGION_ID) large = 1; - else if (REGION_ID(esid << SID_SHIFT) == USER_REGION_ID) + else if (region_id == USER_REGION_ID) large = in_hugepage_area(context, esid << SID_SHIFT); -#endif - make_slbe(esid, vsid, large, kernel_segment); - } else { - unsigned char top_entry, stab_entry, *segments; - - stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid); - PMC_SW_PROCESSOR_A(stab_entry_use, stab_entry & 0xf); - - segments = get_paca()->xSegments; - top_entry = get_paca()->stab_cache_pointer; - if (!kernel_segment && top_entry < STAB_CACHE_SIZE) { - segments[top_entry] = stab_entry; - if (top_entry == STAB_CACHE_SIZE) - top_entry = 0xff; - top_entry++; - get_paca()->stab_cache_pointer = top_entry; - } } + + make_slbe(esid, vsid, large, region_id != USER_REGION_ID); + + if (region_id != USER_REGION_ID) + return; + + offset = &__get_cpu_var(stab_cache_ptr); + if (*offset < NR_STAB_CACHE_ENTRIES) { + __get_cpu_var(stab_cache[*offset]) = esid; + } + (*offset)++; } /* * Allocate a segment table entry for the given ea. */ -int ste_allocate(unsigned long ea) +int slb_allocate(unsigned long ea) { unsigned long vsid, esid; - int kernel_segment = 0; mm_context_t context; - PMC_SW_PROCESSOR(stab_faults); - /* Check for invalid effective addresses. */ - if (!IS_VALID_EA(ea)) + if (unlikely(!IS_VALID_EA(ea))) return 1; /* Kernel or user address? */ if (REGION_ID(ea) >= KERNEL_REGION_ID) { - kernel_segment = 1; - vsid = get_kernel_vsid(ea); context = REGION_ID(ea); + vsid = get_kernel_vsid(ea); } else { - if (! current->mm) + if (unlikely(!current->mm)) return 1; context = current->mm->context; - vsid = get_vsid(context, ea); } esid = GET_ESID(ea); - __ste_allocate(esid, vsid, kernel_segment, context); - if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { - /* Order update */ - asm volatile("sync":::"memory"); - } + __slb_allocate(esid, vsid, context); return 0; } -unsigned long ppc64_preload_all_segments; -unsigned long ppc64_stab_preload = 1; -#define STAB_PRESSURE 0 -#define USE_SLBIE_ON_STAB 0 - /* - * preload all 16 segments for a 32 bit process and the PC and SP segments - * for a 64 bit process. + * preload some userspace segments into the SLB. */ -static void preload_stab(struct task_struct *tsk, struct mm_struct *mm) +static void preload_slb(struct task_struct *tsk, struct mm_struct *mm) { - if (ppc64_preload_all_segments && - test_tsk_thread_flag(tsk, TIF_32BIT)) { - unsigned long esid, vsid; - - for (esid = 0; esid < 16; esid++) { - unsigned long ea = esid << SID_SHIFT; - vsid = get_vsid(mm->context, ea); - __ste_allocate(esid, vsid, 0, mm->context); - } - } else { - unsigned long pc = KSTK_EIP(tsk); - unsigned long stack = KSTK_ESP(tsk); - unsigned long pc_segment = pc & ~SID_MASK; - unsigned long stack_segment = stack & ~SID_MASK; - unsigned long vsid; - - if (pc) { - if (!IS_VALID_EA(pc) || - (REGION_ID(pc) >= KERNEL_REGION_ID)) - return; - vsid = get_vsid(mm->context, pc); - __ste_allocate(GET_ESID(pc), vsid, 0, mm->context); - } - - if (stack && (pc_segment != stack_segment)) { - if (!IS_VALID_EA(stack) || - (REGION_ID(stack) >= KERNEL_REGION_ID)) - return; - vsid = get_vsid(mm->context, stack); - __ste_allocate(GET_ESID(stack), vsid, 0, mm->context); - } - } - - if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { - /* Order update */ - asm volatile("sync" : : : "memory"); - } + unsigned long pc = KSTK_EIP(tsk); + unsigned long stack = KSTK_ESP(tsk); + unsigned long unmapped_base; + unsigned long pc_esid = GET_ESID(pc); + unsigned long stack_esid = GET_ESID(stack); + unsigned long unmapped_base_esid; + unsigned long vsid; + + if (test_tsk_thread_flag(tsk, TIF_32BIT)) + unmapped_base = TASK_UNMAPPED_BASE_USER32; + else + unmapped_base = TASK_UNMAPPED_BASE_USER64; + + unmapped_base_esid = GET_ESID(unmapped_base); + + if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, pc); + __slb_allocate(pc_esid, vsid, mm->context); + + if (pc_esid == stack_esid) + return; + + if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, stack); + __slb_allocate(stack_esid, vsid, mm->context); + + if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid) + return; + + if (!IS_VALID_EA(unmapped_base) || + (REGION_ID(unmapped_base) >= KERNEL_REGION_ID)) + return; + vsid = get_vsid(mm->context, unmapped_base); + __slb_allocate(unmapped_base_esid, vsid, mm->context); } /* Flush all user entries from the segment table of the current processor. */ -void flush_stab(struct task_struct *tsk, struct mm_struct *mm) +void flush_slb(struct task_struct *tsk, struct mm_struct *mm) { - if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { - /* - * XXX disable 32bit slb invalidate optimisation until we fix - * the issue where a 32bit app execed out of a 64bit app can - * cause segments above 4GB not to be flushed - Anton - */ - if (0 && !STAB_PRESSURE && test_thread_flag(TIF_32BIT)) { - union { - unsigned long word0; - slb_dword0 data; - } esid_data; - unsigned long esid; - - asm volatile("isync" : : : "memory"); - for (esid = 0; esid < 16; esid++) { - esid_data.word0 = 0; - esid_data.data.esid = esid; - asm volatile("slbie %0" : : "r" (esid_data)); - } - asm volatile("isync" : : : "memory"); - } else { - asm volatile("isync; slbia; isync":::"memory"); - } + unsigned long *offset = &__get_cpu_var(stab_cache_ptr); - PMC_SW_PROCESSOR(stab_invalidations); - } else { - STE *stab = (STE *) get_paca()->xStab_data.virt; - STE *ste; - unsigned long flags; + if (*offset <= NR_STAB_CACHE_ENTRIES) { + int i; + union { + unsigned long word0; + slb_dword0 data; + } esid_data; - /* Force previous translations to complete. DRENG */ asm volatile("isync" : : : "memory"); - - local_irq_save(flags); - if (get_paca()->stab_cache_pointer != 0xff && !STAB_PRESSURE) { - int i; - unsigned char *segments = get_paca()->xSegments; - - for (i = 0; i < get_paca()->stab_cache_pointer; i++) { - ste = stab + segments[i]; - ste->dw0.dw0.v = 0; - PMC_SW_PROCESSOR(stab_invalidations); - } - -#if USE_SLBIE_ON_STAB - asm volatile("sync":::"memory"); - for (i = 0; i < get_paca()->stab_cache_pointer; i++) { - ste = stab + segments[i]; - asm volatile("slbie %0" : : - "r" (ste->dw0.dw0.esid << SID_SHIFT)); - } - asm volatile("sync":::"memory"); -#else - asm volatile("sync; slbia; sync":::"memory"); -#endif - - } else { - unsigned long entry; - - /* Invalidate all entries. */ - ste = stab; - - /* Never flush the first entry. */ - ste += 1; - for (entry = 1; - entry < (PAGE_SIZE / sizeof(STE)); - entry++, ste++) { - unsigned long ea; - ea = ste->dw0.dw0.esid << SID_SHIFT; - if (STAB_PRESSURE || ea < KERNELBASE) { - ste->dw0.dw0.v = 0; - PMC_SW_PROCESSOR(stab_invalidations); - } - } - - asm volatile("sync; slbia; sync":::"memory"); + for (i = 0; i < *offset; i++) { + esid_data.word0 = 0; + esid_data.data.esid = __get_cpu_var(stab_cache[i]); + asm volatile("slbie %0" : : "r" (esid_data)); } - - get_paca()->stab_cache_pointer = 0; - local_irq_restore(flags); + asm volatile("isync" : : : "memory"); + } else { + asm volatile("isync; slbia; isync" : : : "memory"); } - if (ppc64_stab_preload) - preload_stab(tsk, mm); + *offset = 0; + + preload_slb(tsk, mm); } diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h index e3c4ad343254..99c3abfba704 100644 --- a/include/asm-ppc64/cputable.h +++ b/include/asm-ppc64/cputable.h @@ -135,10 +135,17 @@ extern firmware_feature_t firmware_features_table[]; #define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) -#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_SLB | CPU_FTR_16M_PAGE | \ +#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ CPU_FTR_NODSISRALIGN) +/* iSeries doesn't support large pages */ +#ifdef CONFIG_PPC_ISERIES +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) +#else +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) +#endif + #define COMMON_PPC64_FW (0) #endif diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index 95f3f8b4fbfd..3ecacc7de85f 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -27,14 +27,6 @@ typedef unsigned long mm_context_t; #define CONTEXT_LOW_HPAGES 0 #endif -/* - * Define the size of the cache used for segment table entries. The first - * entry is used as a cache pointer, therefore the actual number of entries - * stored is one less than defined here. Do not change this value without - * considering the impact it will have on the layout of the paca in paca.h. - */ -#define STAB_CACHE_SIZE 16 - /* * Hardware Segment Lookaside Buffer Entry * This structure has been padded out to two 64b doublewords (actual SLBE's are diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 48893d641bdc..cdaf8abac564 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -139,6 +139,7 @@ destroy_context(struct mm_struct *mm) } extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm); +extern void flush_slb(struct task_struct *tsk, struct mm_struct *mm); /* * switch_mm is the entry point called from the architecture independent @@ -154,7 +155,15 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) : : ); #endif /* CONFIG_ALTIVEC */ - flush_stab(tsk, next); + + /* No need to flush userspace segments if the mm doesnt change */ + if (prev == next) + return; + + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) + flush_slb(tsk, next); + else + flush_stab(tsk, next); cpu_set(smp_processor_id(), next->cpu_vm_mask); } diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h index d41818ab9a83..1babe35028d5 100644 --- a/include/asm-ppc64/paca.h +++ b/include/asm-ppc64/paca.h @@ -63,20 +63,15 @@ struct paca_struct { u16 xPacaIndex; /* Logical processor number 0x18 */ u16 xHwProcNum; /* Physical processor number 0x1A */ u32 default_decr; /* Default decrementer value 0x1c */ - u64 unused1; - u64 xKsave; /* Saved Kernel stack addr or zero 0x28 */ - u64 pvr; /* Processor version register 0x30 */ - u8 *exception_sp; /* 0x38 */ - - struct ItLpQueue *lpQueuePtr; /* LpQueue handled by this processor 0x40 */ - u64 xTOC; /* Kernel TOC address 0x48 */ - STAB xStab_data; /* Segment table information 0x50,0x58,0x60 */ - u8 xSegments[STAB_CACHE_SIZE]; /* Cache of used stab entries 0x68,0x70 */ - u8 xProcEnabled; /* 1=soft enabled 0x78 */ - u8 unused2; - u8 prof_enabled; /* 1=iSeries profiling enabled 0x7A */ - u8 stab_cache_pointer; - u8 resv1[4]; /* 0x7B-0x7F */ + u64 xKsave; /* Saved Kernel stack addr or zero 0x20 */ + u64 pvr; /* Processor version register 0x28 */ + struct ItLpQueue *lpQueuePtr; /* LpQueue handled by this processor 0x30 */ + u64 xTOC; /* Kernel TOC address 0x38 */ + STAB xStab_data; /* Segment table information 0x40,0x48,0x50 */ + u8 *exception_sp; /* 0x58 */ + u8 xProcEnabled; /* 0x59 */ + u8 prof_enabled; /* 1=iSeries profiling enabled 0x60 */ + u8 resv1[30]; /* 0x61-0x7F */ /*===================================================================================== * CACHE_LINE_2 0x0080 - 0x00FF -- cgit v1.2.3 From 0f61dbcdfc9e896119f2c236470f6e3d12fe1197 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:01:33 -0800 Subject: [PATCH] ppc64: use CONFIG_MAGIC_SYSRQ around xmon sysrq code From: Anton Blanchard --- arch/ppc64/xmon/start.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c index 02e6940b1784..f26a22c53700 100644 --- a/arch/ppc64/xmon/start.c +++ b/arch/ppc64/xmon/start.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -29,11 +30,14 @@ static inline unsigned int readtb(void) return ret; } +#ifdef CONFIG_MAGIC_SYSRQ + static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { xmon(pt_regs); } + static struct sysrq_key_op sysrq_xmon_op = { .handler = sysrq_handle_xmon, @@ -41,11 +45,15 @@ static struct sysrq_key_op sysrq_xmon_op = .action_msg = "Entering xmon\n", }; +#endif /* CONFIG_MAGIC_SYSRQ */ + void xmon_map_scc(void) { +#ifdef CONFIG_MAGIC_SYSRQ /* This maybe isn't the best place to register sysrq 'x' */ __sysrq_put_key_op('x', &sysrq_xmon_op); +#endif /* CONFIG_MAGIC_SYSRQ */ } int -- cgit v1.2.3 From 36de3f33d2f21e11cc306bee909e3801cfe8d133 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:02:26 -0800 Subject: [PATCH] Trivial cleanups to hugepage support From: David Gibson These are some trivial cleanups to the hugepage ppc64 support --- arch/ppc64/mm/hugetlbpage.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c index 738adc97e478..78ba33722c02 100644 --- a/arch/ppc64/mm/hugetlbpage.c +++ b/arch/ppc64/mm/hugetlbpage.c @@ -654,10 +654,9 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long hpteflags, prpn, flags; long slot; - ea &= ~(HPAGE_SIZE-1); - /* We have to find the first hugepte in the batch, since * that's the one that will store the HPTE flags */ + ea &= HPAGE_MASK; ptep = hugepte_offset(mm, ea); /* Search the Linux page table for a match with va */ @@ -885,10 +884,11 @@ static int __init hugetlb_init(void) spin_unlock(&htlbpage_lock); } htlbpage_max = htlbpage_free = htlbpage_total = i; - printk("Total HugeTLB memory allocated, %d\n", htlbpage_free); + printk(KERN_INFO "Total HugeTLB memory allocated, %d\n", + htlbpage_free); } else { htlbpage_max = 0; - printk("CPU does not support HugeTLB\n"); + printk(KERN_INFO "CPU does not support HugeTLB\n"); } return 0; -- cgit v1.2.3 From 7e9281439b93791b9c4ca77676d3e9a96c8ea621 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:03:17 -0800 Subject: [PATCH] s390: general update. From: Martin Schwidefsky s390 general update: - Add archhelp for "make image". - 32-bit execve fix. - Export some symbols: sys_ioctl, put_files_struct & ccw_device_work. - Minor cleanups in arch/s390/mm/init.c & drivers/s390/net/ctctty.c. --- arch/s390/Makefile | 5 +++++ arch/s390/defconfig | 1 + arch/s390/kernel/compat_linux.c | 3 ++- arch/s390/kernel/s390_ksyms.c | 2 ++ arch/s390/mm/init.c | 2 -- drivers/s390/cio/device.c | 1 + drivers/s390/net/ctctty.c | 6 ++---- kernel/exit.c | 2 ++ 8 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 81250a2008ff..d18a5731e31f 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -70,3 +70,8 @@ include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s $(call filechk,gen-asm-offsets) CLEAN_FILES += include/asm-$(ARCH)/offsets.h + +# Don't use tabs in echo arguments +define archhelp + echo '* image - Kernel image for IPL ($(boot)/image)' +endef diff --git a/arch/s390/defconfig b/arch/s390/defconfig index ce3b02fbb3d9..948d0185779a 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -147,6 +147,7 @@ CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m +# CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m # CONFIG_BLK_DEV_DM is not set diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 777ce28f8343..29c533625f77 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -1912,7 +1912,8 @@ out: security_bprm_free(&bprm); out_mm: - mmdrop(bprm.mm); + if (bprm.mm) + mmdrop(bprm.mm); out_file: if (bprm.file) { diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 39f83cbbebd2..478425fe8de4 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -74,4 +75,5 @@ EXPORT_SYMBOL(console_device); EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); +EXPORT_SYMBOL(sys_ioctl); diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index ab0e614f77fc..b894f76f377d 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -79,8 +79,6 @@ extern unsigned long __init_end; * paging_init() sets up the page tables */ -unsigned long last_valid_pfn; - #ifndef CONFIG_ARCH_S390X void __init paging_init(void) { diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 626265708777..dfcf65396505 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -908,3 +908,4 @@ EXPORT_SYMBOL(ccw_driver_register); EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); EXPORT_SYMBOL(ccw_bus_type); +EXPORT_SYMBOL(ccw_device_work); diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 4c9aae83fb81..1be60e7bbc4e 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.14 2003/10/06 11:33:33 mschwide Exp $ + * $Id: ctctty.c,v 1.15 2004/01/26 10:21:01 mschwide Exp $ * * CTC / ESCON network driver, tty interface. * @@ -759,9 +759,7 @@ ctc_tty_ioctl(struct tty_struct *tty, struct file *file, info->line); #endif error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg); - if (error) - return error; - return 0; + return error; case TIOCSSOFTCAR: #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME, diff --git a/kernel/exit.c b/kernel/exit.c index 34956331ad0f..374b01755aa4 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -403,6 +403,8 @@ void put_files_struct(struct files_struct *files) } } +EXPORT_SYMBOL(put_files_struct); + static inline void __exit_files(struct task_struct *tsk) { struct files_struct * files = tsk->files; -- cgit v1.2.3 From e4f06bee55391b48006ee436d7ce808fb6b92801 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:04:17 -0800 Subject: [PATCH] s390: inline assembly constraints. From: Martin Schwidefsky s390 inline assembly bug-fixes: - Add memory barriers to spinlocks, atomic variable functions and to test_and_{set,clear,change}_bit. - Add "=m" and "m" contraints to tell gcc that the content of a variable is in fact used. - Replace "+m" constraints by "=m" on the output and "m" on the input list. - Use c-implemtation for ffz and __ffs. - Use generic c-implemtation for ffs and fls. --- include/asm-s390/atomic.h | 21 ++-- include/asm-s390/bitops.h | 223 +++++++++++-------------------------------- include/asm-s390/byteorder.h | 6 +- include/asm-s390/checksum.h | 4 +- include/asm-s390/div64.h | 4 +- include/asm-s390/pgtable.h | 8 +- include/asm-s390/processor.h | 39 ++++---- include/asm-s390/rwsem.h | 147 ++++++++++++++-------------- include/asm-s390/semaphore.h | 6 +- include/asm-s390/spinlock.h | 64 +++++++------ include/asm-s390/system.h | 97 ++++++++++--------- include/asm-s390/timex.h | 4 +- include/asm-s390/tlbflush.h | 2 +- include/asm-s390/uaccess.h | 4 +- 14 files changed, 271 insertions(+), 358 deletions(-) diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index 069d34122c9a..1544a74f1609 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h @@ -1,7 +1,6 @@ #ifndef __ARCH_S390_ATOMIC__ #define __ARCH_S390_ATOMIC__ -#ifdef __KERNEL__ /* * include/asm-s390/atomic.h * @@ -27,6 +26,8 @@ typedef struct { } __attribute__ ((aligned (4))) atomic_t; #define ATOMIC_INIT(i) { (i) } +#ifdef __KERNEL__ + #define __CS_LOOP(ptr, op_val, op_string) ({ \ typeof(ptr->counter) old_val, new_val; \ __asm__ __volatile__(" l %0,0(%3)\n" \ @@ -35,8 +36,10 @@ typedef struct { " cs %0,%1,0(%3)\n" \ " jl 0b" \ : "=&d" (old_val), "=&d" (new_val), \ - "+m" (((atomic_t *)(ptr))->counter) \ - : "a" (ptr), "d" (op_val) : "cc" ); \ + "=m" (((atomic_t *)(ptr))->counter) \ + : "a" (ptr), "d" (op_val), \ + "m" (((atomic_t *)(ptr))->counter) \ + : "cc", "memory" ); \ new_val; \ }) #define atomic_read(v) ((v)->counter) @@ -106,8 +109,10 @@ typedef struct { " csg %0,%1,0(%3)\n" \ " jl 0b" \ : "=&d" (old_val), "=&d" (new_val), \ - "+m" (((atomic_t *)(ptr))->counter) \ - : "a" (ptr), "d" (op_val) : "cc" ); \ + "=m" (((atomic_t *)(ptr))->counter) \ + : "a" (ptr), "d" (op_val), \ + "m" (((atomic_t *)(ptr))->counter) \ + : "cc", "memory" ); \ new_val; \ }) #define atomic64_read(v) ((v)->counter) @@ -182,9 +187,9 @@ atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v) " ipm %0\n" " srl %0,28\n" "0:" - : "=&d" (retval), "+m" (v->counter) - : "a" (v), "d" (expected_oldval) , "d" (new_val) - : "cc" ); + : "=&d" (retval), "=m" (v->counter) + : "a" (v), "d" (expected_oldval) , "d" (new_val), + "m" (v->counter) : "cc", "memory" ); return retval; } diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 8de69aa8ec35..2e1129ae7d22 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -13,6 +13,7 @@ * */ #include +#include /* * 32 bit bitops format: @@ -109,6 +110,8 @@ extern const char _sb_findmap[]; #endif /* __s390x__ */ +#define __BITOPS_BARRIER() __asm__ __volatile__ ( "" : : : "memory" ) + #ifdef CONFIG_SMP /* * SMP safe set_bit routine based on compare and swap (CS) @@ -189,6 +192,7 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); /* Do the atomic update. */ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR); + __BITOPS_BARRIER(); return (old & mask) != 0; } @@ -211,6 +215,7 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1))); /* Do the atomic update. */ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND); + __BITOPS_BARRIER(); return (old ^ new) != 0; } @@ -233,6 +238,7 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); /* Do the atomic update. */ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR); + __BITOPS_BARRIER(); return (old & mask) != 0; } #endif /* CONFIG_SMP */ @@ -435,7 +441,7 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr) asm volatile("oc 0(1,%1),0(%2)" : "=m" (*(char *) addr) : "a" (addr), "a" (_oi_bitmap + (nr & 7)), - "m" (*(char *) addr) : "cc" ); + "m" (*(char *) addr) : "cc", "memory" ); return (ch >> (nr & 7)) & 1; } #define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y) @@ -454,7 +460,7 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr) asm volatile("nc 0(1,%1),0(%2)" : "=m" (*(char *) addr) : "a" (addr), "a" (_ni_bitmap + (nr & 7)), - "m" (*(char *) addr) : "cc" ); + "m" (*(char *) addr) : "cc", "memory" ); return (ch >> (nr & 7)) & 1; } #define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y) @@ -473,7 +479,7 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr) asm volatile("xc 0(1,%1),0(%2)" : "=m" (*(char *) addr) : "a" (addr), "a" (_oi_bitmap + (nr & 7)), - "m" (*(char *) addr) : "cc" ); + "m" (*(char *) addr) : "cc", "memory" ); return (ch >> (nr & 7)) & 1; } #define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y) @@ -681,59 +687,6 @@ find_next_bit (unsigned long * addr, int size, int offset) return (offset + res); } -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -static inline unsigned long ffz(unsigned long word) -{ - unsigned long reg; - int result; - - __asm__(" slr %0,%0\n" - " lhi %2,0xff\n" - " tml %1,0xffff\n" - " jno 0f\n" - " ahi %0,16\n" - " srl %1,16\n" - "0: tml %1,0x00ff\n" - " jno 1f\n" - " ahi %0,8\n" - " srl %1,8\n" - "1: nr %1,%2\n" - " ic %1,0(%1,%3)\n" - " alr %0,%1" - : "=&d" (result), "+a" (word), "=&d" (reg) - : "a" (&_zb_findmap) : "cc" ); - return result; -} - -/* - * __ffs = find first bit in word. Undefined if no bit exists, - * so code should check against 0UL first.. - */ -static inline unsigned long __ffs (unsigned long word) -{ - unsigned long reg, result; - - __asm__(" slr %0,%0\n" - " lhi %2,0xff\n" - " tml %1,0xffff\n" - " jnz 0f\n" - " ahi %0,16\n" - " srl %1,16\n" - "0: tml %1,0x00ff\n" - " jnz 1f\n" - " ahi %0,8\n" - " srl %1,8\n" - "1: nr %1,%2\n" - " ic %1,0(%1,%3)\n" - " alr %0,%1" - : "=&d" (result), "+a" (word), "=&d" (reg) - : "a" (&_sb_findmap) : "cc" ); - return result; -} - #else /* __s390x__ */ /* @@ -910,35 +863,31 @@ find_next_bit (unsigned long * addr, unsigned long size, unsigned long offset) return (offset + res); } +#endif /* __s390x__ */ + /* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ static inline unsigned long ffz(unsigned long word) { - unsigned long reg, result; - - __asm__(" lhi %2,-1\n" - " slgr %0,%0\n" - " clr %1,%2\n" - " jne 0f\n" - " aghi %0,32\n" - " srlg %1,%1,32\n" - "0: lghi %2,0xff\n" - " tmll %1,0xffff\n" - " jno 1f\n" - " aghi %0,16\n" - " srlg %1,%1,16\n" - "1: tmll %1,0x00ff\n" - " jno 2f\n" - " aghi %0,8\n" - " srlg %1,%1,8\n" - "2: ngr %1,%2\n" - " ic %1,0(%1,%3)\n" - " algr %0,%1" - : "=&d" (result), "+a" (word), "=&d" (reg) - : "a" (&_zb_findmap) : "cc" ); - return result; + unsigned long bit = 0; + +#ifdef __s390x__ + if (likely((word & 0xffffffff) == 0xffffffff)) { + word >>= 32; + bit += 32; + } +#endif + if (likely((word & 0xffff) == 0xffff)) { + word >>= 16; + bit += 16; + } + if (likely((word & 0xff) == 0xff)) { + word >>= 8; + bit += 8; + } + return bit + _zb_findmap[word & 0xff]; } /* @@ -947,31 +896,24 @@ static inline unsigned long ffz(unsigned long word) */ static inline unsigned long __ffs (unsigned long word) { - unsigned long reg, result; - - __asm__(" slgr %0,%0\n" - " ltr %1,%1\n" - " jnz 0f\n" - " aghi %0,32\n" - " srlg %1,%1,32\n" - "0: lghi %2,0xff\n" - " tmll %1,0xffff\n" - " jnz 1f\n" - " aghi %0,16\n" - " srlg %1,%1,16\n" - "1: tmll %1,0x00ff\n" - " jnz 2f\n" - " aghi %0,8\n" - " srlg %1,%1,8\n" - "2: ngr %1,%2\n" - " ic %1,0(%1,%3)\n" - " algr %0,%1" - : "=&d" (result), "+a" (word), "=&d" (reg) - : "a" (&_sb_findmap) : "cc" ); - return result; -} + unsigned long bit = 0; -#endif /* __s390x__ */ +#ifdef __s390x__ + if (likely((word & 0xffffffff) == 0)) { + word >>= 32; + bit += 32; + } +#endif + if (likely((word & 0xffff) == 0)) { + word >>= 16; + bit += 16; + } + if (likely((word & 0xff) == 0)) { + word >>= 8; + bit += 8; + } + return bit + _sb_findmap[word & 0xff]; +} /* * Every architecture must define this function. It's the fastest @@ -989,68 +931,12 @@ static inline int sched_find_first_bit(unsigned long *b) * the libc and compiler builtin ffs routines, therefore * differs in spirit from the above ffz (man ffs). */ -extern inline int ffs (int x) -{ - int r = 1; - - if (x == 0) - return 0; - __asm__(" tml %1,0xffff\n" - " jnz 0f\n" - " srl %1,16\n" - " ahi %0,16\n" - "0: tml %1,0x00ff\n" - " jnz 1f\n" - " srl %1,8\n" - " ahi %0,8\n" - "1: tml %1,0x000f\n" - " jnz 2f\n" - " srl %1,4\n" - " ahi %0,4\n" - "2: tml %1,0x0003\n" - " jnz 3f\n" - " srl %1,2\n" - " ahi %0,2\n" - "3: tml %1,0x0001\n" - " jnz 4f\n" - " ahi %0,1\n" - "4:" - : "=&d" (r), "+d" (x) : : "cc" ); - return r; -} +#define ffs(x) generic_ffs(x) /* * fls: find last bit set. */ -static __inline__ int fls(int x) -{ - int r = 32; - - if (x == 0) - return 0; - __asm__(" tmh %1,0xffff\n" - " jz 0f\n" - " sll %1,16\n" - " ahi %0,-16\n" - "0: tmh %1,0xff00\n" - " jz 1f\n" - " sll %1,8\n" - " ahi %0,-8\n" - "1: tmh %1,0xf000\n" - " jz 2f\n" - " sll %1,4\n" - " ahi %0,-4\n" - "2: tmh %1,0xc000\n" - " jz 3f\n" - " sll %1,2\n" - " ahi %0,-2\n" - "3: tmh %1,0x8000\n" - " jz 4f\n" - " ahi %0,-1\n" - "4:" - : "+d" (r), "+d" (x) : : "cc" ); - return r; -} +#define fls(x) generic_fls(x) /* * hweightN: returns the hamming weight (i.e. the number @@ -1273,11 +1159,16 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset) /* Bitmap functions for the minix filesystem. */ /* FIXME !!! */ -#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) -#define minix_set_bit(nr,addr) set_bit(nr,addr) -#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) +#define minix_test_and_set_bit(nr,addr) \ + test_and_set_bit(nr,(unsigned long *)addr) +#define minix_set_bit(nr,addr) \ + set_bit(nr,(unsigned long *)addr) +#define minix_test_and_clear_bit(nr,addr) \ + test_and_clear_bit(nr,(unsigned long *)addr) +#define minix_test_bit(nr,addr) \ + test_bit(nr,(unsigned long *)addr) +#define minix_find_first_zero_bit(addr,size) \ + find_first_zero_bit(addr,size) #endif /* __KERNEL__ */ diff --git a/include/asm-s390/byteorder.h b/include/asm-s390/byteorder.h index afa7332e6d30..43b0645bacd8 100644 --- a/include/asm-s390/byteorder.h +++ b/include/asm-s390/byteorder.h @@ -50,7 +50,7 @@ static __inline__ __u32 ___arch__swab32p(__u32 *x) " icm %0,4,2(%1)\n" " icm %0,2,1(%1)\n" " ic %0,0(%1)" - : "=&d" (result) : "a" (x) : "cc" ); + : "=&d" (result) : "a" (x), "m" (*x) : "cc" ); #else /* __s390x__ */ " lrv %0,%1" : "=d" (result) : "m" (*x) ); @@ -67,7 +67,7 @@ static __inline__ __u32 ___arch__swab32(__u32 x) __asm__ __volatile__ ( " lrvr %0,%1" - : "=d" (result) : "d" (x) ); + : "=d" (result) : "d" (x), "m" (x) ); return result; #endif /* __s390x__ */ } @@ -85,7 +85,7 @@ static __inline__ __u16 ___arch__swab16p(__u16 *x) #ifndef __s390x__ " icm %0,2,1(%1)\n" " ic %0,0(%1)\n" - : "=&d" (result) : "a" (x) : "cc" ); + : "=&d" (result) : "a" (x), "m" (*x) : "cc" ); #else /* __s390x__ */ " lrvh %0,%1" : "=d" (result) : "m" (*x) ); diff --git a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h index fc5c512aed04..468da9644700 100644 --- a/include/asm-s390/checksum.h +++ b/include/asm-s390/checksum.h @@ -42,7 +42,7 @@ csum_partial(const unsigned char * buff, int len, unsigned int sum) __asm__ __volatile__ ( "0: cksm %0,%1\n" /* do checksum on longs */ " jo 0b\n" - : "+&d" (sum), "+&a" (rp) : : "cc" ); + : "+&d" (sum), "+&a" (rp) : : "cc", "memory" ); #else /* __s390x__ */ __asm__ __volatile__ ( " lgr 2,%1\n" /* address in gpr 2 */ @@ -51,7 +51,7 @@ csum_partial(const unsigned char * buff, int len, unsigned int sum) " jo 0b\n" : "+&d" (sum) : "d" (buff), "d" (len) - : "cc", "2", "3" ); + : "cc", "memory", "2", "3" ); #endif /* __s390x__ */ return sum; } diff --git a/include/asm-s390/div64.h b/include/asm-s390/div64.h index 0c5f739832f1..af098dc3cf59 100644 --- a/include/asm-s390/div64.h +++ b/include/asm-s390/div64.h @@ -36,8 +36,8 @@ " ahi 1,1\n" \ "1: st 1,4+%1\n" \ " lr %0,0" \ - : "=d" (__r), "+m" (__n) \ - : "d" (base) : "0", "1", "2", "cc" ); \ + : "=d" (__r), "=m" (__n) \ + : "d" (base), "m" (__n) : "0", "1", "2", "cc" ); \ (n) = (__n); \ __r; \ }) diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 1c032e955535..06a30c75548e 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -553,11 +553,15 @@ ptep_clear_flush(struct vm_area_struct *vma, if (!(pte_val(pte) & _PAGE_INVALID)) { /* S390 has 1mb segments, we are emulating 4MB segments */ pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00); - __asm__ __volatile__ ("ipte %0,%1" : : "a" (pto), "a" (address)); + __asm__ __volatile__ ("ipte %2,%3" + : "=m" (*ptep) : "m" (*ptep), + "a" (pto), "a" (address) ); } #else /* __s390x__ */ if (!(pte_val(pte) & _PAGE_INVALID)) - __asm__ __volatile__ ("ipte %0,%1" : : "a" (ptep), "a" (address)); + __asm__ __volatile__ ("ipte %2,%3" + : "=m" (*ptep) : "m" (*ptep), + "a" (ptep), "a" (address) ); #endif /* __s390x__ */ pte_clear(ptep); return pte; diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index d1f0be745c46..e904644c3ace 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h @@ -66,7 +66,7 @@ extern struct task_struct *last_task_used_math; #else /* __s390x__ */ -# define TASK_SIZE (0x20000000000UL) +# define TASK_SIZE (0x40000000000UL) # define TASK31_SIZE (0x80000000UL) # define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ (TASK31_SIZE / 2) : (TASK_SIZE / 2)) @@ -200,14 +200,14 @@ static inline void __load_psw_mask (unsigned long mask) " st %0,4(%1)\n" " lpsw 0(%1)\n" "1:" - : "=&d" (addr) : "a" (&psw) : "memory", "cc" ); + : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" ); #else /* __s390x__ */ asm volatile ( " larl %0,1f\n" " stg %0,8(%1)\n" " lpswe 0(%1)\n" "1:" - : "=&d" (addr) : "a" (&psw) : "memory", "cc" ); + : "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc" ); #endif /* __s390x__ */ } @@ -229,14 +229,16 @@ static inline void enabled_wait(void) " oi 4(%1),0x80\n" " lpsw 0(%1)\n" "1:" - : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" ); + : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw) + : "memory", "cc" ); #else /* __s390x__ */ asm volatile ( " larl %0,0f\n" " stg %0,8(%1)\n" " lpswe 0(%1)\n" "0:" - : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" ); + : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw) + : "memory", "cc" ); #endif /* __s390x__ */ } @@ -247,7 +249,7 @@ static inline void enabled_wait(void) static inline void disabled_wait(unsigned long code) { char psw_buffer[2*sizeof(psw_t)]; - char ctl_buf[4]; + unsigned long ctl_buf; psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1) & -sizeof(psw_t)); @@ -258,9 +260,9 @@ static inline void disabled_wait(unsigned long code) * the processor is dead afterwards */ #ifndef __s390x__ - asm volatile (" stctl 0,0,0(%1)\n" - " ni 0(%1),0xef\n" /* switch off protection */ - " lctl 0,0,0(%1)\n" + asm volatile (" stctl 0,0,0(%2)\n" + " ni 0(%2),0xef\n" /* switch off protection */ + " lctl 0,0,0(%2)\n" " stpt 0xd8\n" /* store timer */ " stckc 0xe0\n" /* store clock comparator */ " stpx 0x108\n" /* store prefix register */ @@ -271,13 +273,14 @@ static inline void disabled_wait(unsigned long code) " std 6,0x178\n" /* store f6 */ " stm 0,15,0x180\n" /* store general registers */ " stctl 0,15,0x1c0\n" /* store control registers */ - " oi 0(%1),0x10\n" /* fake protection bit */ - " lpsw 0(%0)" - : : "a" (dw_psw), "a" (&ctl_buf) : "cc" ); + " oi 0x1c0,0x10\n" /* fake protection bit */ + " lpsw 0(%1)" + : "=m" (ctl_buf) + : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" ); #else /* __s390x__ */ - asm volatile (" stctg 0,0,0(%1)\n" - " ni 4(%1),0xef\n" /* switch off protection */ - " lctlg 0,0,0(%1)\n" + asm volatile (" stctg 0,0,0(%2)\n" + " ni 4(%2),0xef\n" /* switch off protection */ + " lctlg 0,0,0(%2)\n" " lghi 1,0x1000\n" " stpt 0x328(1)\n" /* store timer */ " stckc 0x330(1)\n" /* store clock comparator */ @@ -303,8 +306,10 @@ static inline void disabled_wait(unsigned long code) " stmg 0,15,0x280(1)\n" /* store general registers */ " stctg 0,15,0x380(1)\n" /* store control registers */ " oi 0x384(1),0x10\n" /* fake protection bit */ - " lpswe 0(%0)" - : : "a" (dw_psw), "a" (&ctl_buf) : "cc", "0", "1"); + " lpswe 0(%1)" + : "=m" (ctl_buf) + : "a" (dw_psw), "a" (&ctl_buf), + "m" (dw_psw) : "cc", "0", "1"); #endif /* __s390x__ */ } diff --git a/include/asm-s390/rwsem.h b/include/asm-s390/rwsem.h index ef612dd92ca5..8c0cebbfc034 100644 --- a/include/asm-s390/rwsem.h +++ b/include/asm-s390/rwsem.h @@ -102,21 +102,21 @@ static inline void __down_read(struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " ahi %1,%3\n" - " cs %0,%1,0(%2)\n" + " ahi %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " aghi %1,%3\n" - " csg %0,%1,0(%2)\n" + " aghi %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS) - : "cc", "memory" ); + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), + "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" ); if (old < 0) rwsem_down_read_failed(sem); } @@ -130,25 +130,25 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: ltr %1,%0\n" " jm 1f\n" - " ahi %1,%3\n" - " cs %0,%1,0(%2)\n" + " ahi %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b\n" "1:" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: ltgr %1,%0\n" " jm 1f\n" - " aghi %1,%3\n" - " csg %0,%1,0(%2)\n" + " aghi %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b\n" "1:" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS) - : "cc", "memory" ); + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), + "i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" ); return old >= 0 ? 1 : 0; } @@ -162,20 +162,20 @@ static inline void __down_write(struct rw_semaphore *sem) tmp = RWSEM_ACTIVE_WRITE_BIAS; __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " a %1,%3\n" - " cs %0,%1,0(%2)\n" + " a %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " ag %1,%3\n" - " csg %0,%1,0(%2)\n" + " ag %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "m" (tmp) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), "m" (tmp) : "cc", "memory" ); if (old != 0) rwsem_down_write_failed(sem); @@ -190,22 +190,22 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%1)\n" + " l %0,0(%2)\n" "0: ltr %0,%0\n" " jnz 1f\n" - " cs %0,%2,0(%1)\n" + " cs %0,%4,0(%2)\n" " jl 0b\n" #else /* __s390x__ */ - " lg %0,0(%1)\n" + " lg %0,0(%2)\n" "0: ltgr %0,%0\n" " jnz 1f\n" - " csg %0,%2,0(%1)\n" + " csg %0,%4,0(%2)\n" " jl 0b\n" #endif /* __s390x__ */ "1:" - : "=&d" (old) - : "a" (&sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS) - : "cc", "memory" ); + : "=&d" (old), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), + "d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory" ); return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0; } @@ -218,20 +218,21 @@ static inline void __up_read(struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " ahi %1,%3\n" - " cs %0,%1,0(%2)\n" + " ahi %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " aghi %1,%3\n" - " csg %0,%1,0(%2)\n" + " aghi %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), + "i" (-RWSEM_ACTIVE_READ_BIAS) : "cc", "memory" ); if (new < 0) if ((new & RWSEM_ACTIVE_MASK) == 0) @@ -248,20 +249,20 @@ static inline void __up_write(struct rw_semaphore *sem) tmp = -RWSEM_ACTIVE_WRITE_BIAS; __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " a %1,%3\n" - " cs %0,%1,0(%2)\n" + " a %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " ag %1,%3\n" - " csg %0,%1,0(%2)\n" + " ag %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "m" (tmp) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), "m" (tmp) : "cc", "memory" ); if (new < 0) if ((new & RWSEM_ACTIVE_MASK) == 0) @@ -278,20 +279,20 @@ static inline void __downgrade_write(struct rw_semaphore *sem) tmp = -RWSEM_WAITING_BIAS; __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " a %1,%3\n" - " cs %0,%1,0(%2)\n" + " a %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " ag %1,%3\n" - " csg %0,%1,0(%2)\n" + " ag %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "m" (tmp) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), "m" (tmp) : "cc", "memory" ); if (new > 1) rwsem_downgrade_wake(sem); @@ -306,20 +307,20 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " ar %1,%3\n" - " cs %0,%1,0(%2)\n" + " ar %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " agr %1,%3\n" - " csg %0,%1,0(%2)\n" + " agr %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "d" (delta) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), "d" (delta) : "cc", "memory" ); } @@ -332,20 +333,20 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) __asm__ __volatile__( #ifndef __s390x__ - " l %0,0(%2)\n" + " l %0,0(%3)\n" "0: lr %1,%0\n" - " ar %1,%3\n" - " cs %0,%1,0(%2)\n" + " ar %1,%5\n" + " cs %0,%1,0(%3)\n" " jl 0b" #else /* __s390x__ */ - " lg %0,0(%2)\n" + " lg %0,0(%3)\n" "0: lgr %1,%0\n" - " agr %1,%3\n" - " csg %0,%1,0(%2)\n" + " agr %1,%5\n" + " csg %0,%1,0(%3)\n" " jl 0b" #endif /* __s390x__ */ - : "=&d" (old), "=&d" (new) - : "a" (&sem->count), "d" (delta) + : "=&d" (old), "=&d" (new), "=m" (sem->count) + : "a" (&sem->count), "m" (sem->count), "d" (delta) : "cc", "memory" ); return new; } diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h index 5720dea2459f..873def6f363a 100644 --- a/include/asm-s390/semaphore.h +++ b/include/asm-s390/semaphore.h @@ -95,9 +95,9 @@ static inline int down_trylock(struct semaphore * sem) " cs %0,%1,0(%3)\n" " jl 0b\n" "1:" - : "=&d" (old_val), "=&d" (new_val), - "+m" (sem->count.counter) - : "a" (&sem->count.counter) : "cc" ); + : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter) + : "a" (&sem->count.counter), "m" (sem->count.counter) + : "cc", "memory" ); return old_val <= 0; } diff --git a/include/asm-s390/spinlock.h b/include/asm-s390/spinlock.h index 2d4d6e75469e..00981f815f30 100644 --- a/include/asm-s390/spinlock.h +++ b/include/asm-s390/spinlock.h @@ -57,8 +57,9 @@ extern inline void _raw_spin_lock(spinlock_t *lp) "1: slr %1,%1\n" " cs %1,%0,0(%3)\n" " jl 0b\n" - : "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock) - : "a" (&lp->lock) : "cc" ); + : "=&d" (reg1), "=&d" (reg2), "=m" (lp->lock) + : "a" (&lp->lock), "m" (lp->lock) + : "cc", "memory" ); #else /* __s390x__ */ unsigned long reg1, reg2; __asm__ __volatile(" bras %1,1f\n" @@ -66,9 +67,9 @@ extern inline void _raw_spin_lock(spinlock_t *lp) "1: slr %0,%0\n" " cs %0,%1,0(%3)\n" " jl 0b\n" - : "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock) - : "a" (&lp->lock), "i" (__DIAG44_OPERAND) - : "cc" ); + : "=&d" (reg1), "=&d" (reg2), "=m" (lp->lock) + : "a" (&lp->lock), "i" (__DIAG44_OPERAND), + "m" (lp->lock) : "cc", "memory" ); #endif /* __s390x__ */ } @@ -82,8 +83,9 @@ extern inline int _raw_spin_trylock(spinlock_t *lp) __asm__ __volatile(" slr %0,%0\n" " basr %1,0\n" "0: cs %0,%1,0(%3)" - : "=&d" (result), "=&d" (reg), "+m" (lp->lock) - : "a" (&lp->lock) : "cc" ); + : "=&d" (result), "=&d" (reg), "=m" (lp->lock) + : "a" (&lp->lock), "m" (lp->lock) + : "cc", "memory" ); return !result; } @@ -93,7 +95,8 @@ extern inline void _raw_spin_unlock(spinlock_t *lp) __asm__ __volatile("cs %0,%3,0(%4)" : "=d" (old), "=m" (lp->lock) - : "0" (lp->lock), "d" (0), "a" (lp) : "cc" ); + : "0" (lp->lock), "d" (0), "a" (lp) + : "cc", "memory" ); } /* @@ -126,8 +129,8 @@ typedef struct { " la 3,1(2)\n" /* one more reader */ \ " cs 2,3,0(%1)\n" /* try to write new value */ \ " jl 0b" \ - : "+m" ((rw)->lock) : "a" (&(rw)->lock) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) : "a" (&(rw)->lock), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #else /* __s390x__ */ #define _raw_read_lock(rw) \ asm volatile(" lg 2,0(%1)\n" \ @@ -137,9 +140,9 @@ typedef struct { " la 3,1(2)\n" /* one more reader */ \ " csg 2,3,0(%1)\n" /* try to write new value */ \ " jl 0b" \ - : "+m" ((rw)->lock) \ - : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) \ + : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #endif /* __s390x__ */ #ifndef __s390x__ @@ -151,8 +154,8 @@ typedef struct { " ahi 3,-1\n" /* one less reader */ \ " cs 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) : "a" (&(rw)->lock) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) : "a" (&(rw)->lock), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #else /* __s390x__ */ #define _raw_read_unlock(rw) \ asm volatile(" lg 2,0(%1)\n" \ @@ -162,9 +165,9 @@ typedef struct { " bctgr 3,0\n" /* one less reader */ \ " csg 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) \ - : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) \ + : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #endif /* __s390x__ */ #ifndef __s390x__ @@ -176,8 +179,8 @@ typedef struct { "1: slr 2,2\n" /* old lock value must be 0 */ \ " cs 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) : "a" (&(rw)->lock) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) : "a" (&(rw)->lock), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #else /* __s390x__ */ #define _raw_write_lock(rw) \ asm volatile(" llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \ @@ -186,9 +189,9 @@ typedef struct { "1: slgr 2,2\n" /* old lock value must be 0 */ \ " csg 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) \ - : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) \ + : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #endif /* __s390x__ */ #ifndef __s390x__ @@ -200,8 +203,8 @@ typedef struct { " sll 2,31\n" /* old lock value must be 0x80000000 */ \ " cs 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) : "a" (&(rw)->lock) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) : "a" (&(rw)->lock), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #else /* __s390x__ */ #define _raw_write_unlock(rw) \ asm volatile(" slgr 3,3\n" /* new lock value = 0 */ \ @@ -210,9 +213,9 @@ typedef struct { "1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\ " csg 2,3,0(%1)\n" \ " jl 0b" \ - : "+m" ((rw)->lock) \ - : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \ - : "2", "3", "cc" ) + : "=m" ((rw)->lock) \ + : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND), \ + "m" ((rw)->lock) : "2", "3", "cc", "memory" ) #endif /* __s390x__ */ extern inline int _raw_write_trylock(rwlock_t *rw) @@ -230,8 +233,9 @@ extern inline int _raw_write_trylock(rwlock_t *rw) " llihh %1,0x8000\n" "0: csg %0,%1,0(%3)\n" #endif /* __s390x__ */ - : "=&d" (result), "=&d" (reg), "+m" (rw->lock) - : "a" (&rw->lock) : "cc" ); + : "=&d" (result), "=&d" (reg), "=m" (rw->lock) + : "a" (&rw->lock), "m" (rw->lock) + : "cc", "memory" ); return result == 0; } diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 6fa181437837..7050547bc622 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h @@ -32,28 +32,28 @@ extern struct task_struct *__switch_to(void *, void *); static inline void save_fp_regs(s390_fp_regs *fpregs) { asm volatile ( - " std 0,8(%0)\n" - " std 2,24(%0)\n" - " std 4,40(%0)\n" - " std 6,56(%0)" - : : "a" (fpregs) : "memory" ); + " std 0,8(%1)\n" + " std 2,24(%1)\n" + " std 4,40(%1)\n" + " std 6,56(%1)" + : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" ); if (!MACHINE_HAS_IEEE) return; asm volatile( - " stfpc 0(%0)\n" - " std 1,16(%0)\n" - " std 3,32(%0)\n" - " std 5,48(%0)\n" - " std 7,64(%0)\n" - " std 8,72(%0)\n" - " std 9,80(%0)\n" - " std 10,88(%0)\n" - " std 11,96(%0)\n" - " std 12,104(%0)\n" - " std 13,112(%0)\n" - " std 14,120(%0)\n" - " std 15,128(%0)\n" - : : "a" (fpregs) : "memory" ); + " stfpc 0(%1)\n" + " std 1,16(%1)\n" + " std 3,32(%1)\n" + " std 5,48(%1)\n" + " std 7,64(%1)\n" + " std 8,72(%1)\n" + " std 9,80(%1)\n" + " std 10,88(%1)\n" + " std 11,96(%1)\n" + " std 12,104(%1)\n" + " std 13,112(%1)\n" + " std 14,120(%1)\n" + " std 15,128(%1)\n" + : "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory" ); } static inline void restore_fp_regs(s390_fp_regs *fpregs) @@ -63,7 +63,7 @@ static inline void restore_fp_regs(s390_fp_regs *fpregs) " ld 2,24(%0)\n" " ld 4,40(%0)\n" " ld 6,56(%0)" - : : "a" (fpregs)); + : : "a" (fpregs), "m" (*fpregs) ); if (!MACHINE_HAS_IEEE) return; asm volatile( @@ -80,7 +80,7 @@ static inline void restore_fp_regs(s390_fp_regs *fpregs) " ld 13,112(%0)\n" " ld 14,120(%0)\n" " ld 15,128(%0)\n" - : : "a" (fpregs)); + : : "a" (fpregs), "m" (*fpregs) ); } #define switch_to(prev,next,last) do { \ @@ -107,15 +107,15 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) shift = (3 ^ (addr & 3)) << 3; addr ^= addr & 3; asm volatile( - " l %0,0(%3)\n" + " l %0,0(%4)\n" "0: lr 0,%0\n" - " nr 0,%2\n" - " or 0,%1\n" - " cs %0,0,0(%3)\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,0(%4)\n" " jl 0b\n" - : "=&d" (old) - : "d" (x << shift), "d" (~(255 << shift)), "a" (addr) - : "memory", "cc", "0" ); + : "=&d" (old), "=m" (*(int *) addr) + : "d" (x << shift), "d" (~(255 << shift)), "a" (addr), + "m" (*(int *) addr) : "memory", "cc", "0" ); x = old >> shift; break; case 2: @@ -123,34 +123,36 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) shift = (2 ^ (addr & 2)) << 3; addr ^= addr & 2; asm volatile( - " l %0,0(%3)\n" + " l %0,0(%4)\n" "0: lr 0,%0\n" - " nr 0,%2\n" - " or 0,%1\n" - " cs %0,0,0(%3)\n" + " nr 0,%3\n" + " or 0,%2\n" + " cs %0,0,0(%4)\n" " jl 0b\n" - : "=&d" (old) - : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr) - : "memory", "cc", "0" ); + : "=&d" (old), "=m" (*(int *) addr) + : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr), + "m" (*(int *) addr) : "memory", "cc", "0" ); x = old >> shift; break; case 4: asm volatile ( - " l %0,0(%2)\n" - "0: cs %0,%1,0(%2)\n" + " l %0,0(%3)\n" + "0: cs %0,%2,0(%3)\n" " jl 0b\n" - : "=&d" (old) : "d" (x), "a" (ptr) - : "memory", "cc", "0" ); + : "=&d" (old), "=m" (*(int *) ptr) + : "d" (x), "a" (ptr), "m" (*(int *) ptr) + : "memory", "cc" ); x = old; break; #ifdef __s390x__ case 8: asm volatile ( - " lg %0,0(%2)\n" - "0: csg %0,%1,0(%2)\n" + " lg %0,0(%3)\n" + "0: csg %0,%2,0(%3)\n" " jl 0b\n" - : "=&d" (old) : "d" (x), "a" (ptr) - : "memory", "cc", "0" ); + : "=&d" (old), "=m" (*(long *) ptr) + : "d" (x), "a" (ptr), "m" (*(long *) ptr) + : "memory", "cc" ); x = old; break; #endif /* __s390x__ */ @@ -268,7 +270,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) #define local_irq_enable() ({ \ unsigned long __dummy; \ __asm__ __volatile__ ( \ - "stosm 0(%1),0x03" : "=m" (__dummy) : "a" (&__dummy) ); \ + "stosm 0(%1),0x03" \ + : "=m" (__dummy) : "a" (&__dummy) : "memory" ); \ }) #define local_irq_disable() ({ \ @@ -279,10 +282,10 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) }) #define local_save_flags(x) \ - __asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x) ) + __asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) ) #define local_irq_restore(x) \ - __asm__ __volatile__("ssm 0(%0)" : : "a" (&x) : "memory") + __asm__ __volatile__("ssm 0(%0)" : : "a" (&x), "m" (x) : "memory") #define irqs_disabled() \ ({ \ @@ -294,7 +297,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) #ifdef __s390x__ #define __load_psw(psw) \ - __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw) : "cc" ); + __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" ); #define __ctl_load(array, low, high) ({ \ __asm__ __volatile__ ( \ diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h index faf919e03b97..226acd000639 100644 --- a/include/asm-s390/timex.h +++ b/include/asm-s390/timex.h @@ -25,7 +25,7 @@ static inline cycles_t get_cycles(void) { cycles_t cycles; - __asm__("stck 0(%0)" : : "a" (&(cycles)) : "memory", "cc"); + __asm__("stck 0(%1)" : "=m" (cycles) : "a" (&cycles) : "cc"); return cycles >> 2; } @@ -33,7 +33,7 @@ static inline unsigned long long get_clock (void) { unsigned long long clk; - __asm__("stck 0(%0)" : : "a" (&(clk)) : "memory", "cc"); + __asm__("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc"); return clk; } diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h index 2b76fa728abb..1bb73b0e61fa 100644 --- a/include/asm-s390/tlbflush.h +++ b/include/asm-s390/tlbflush.h @@ -85,7 +85,7 @@ static inline void global_flush_tlb(void) " slr 2,2\n" " slr 3,3\n" " csp 2,%0" - : : "a" (addr) : "cc", "2", "3" ); + : : "a" (addr), "m" (dummy) : "cc", "2", "3" ); } } diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index e6a325948da5..845211fca609 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -124,8 +124,8 @@ struct exception_table_entry "1:\n" \ __uaccess_fixup \ : "=&d" (err) \ - : "a" (__to),"a" (__from),"K" (-EFAULT),"0" (0) \ - : "cc" ); \ + : "a" (__to),"a" (__from),"K" (-EFAULT),"0" (0),\ + "m" (x) : "cc" ); \ }) #else /* __s390x__ */ -- cgit v1.2.3 From e7d1d6cd8e12e123bb9e70e731f662fbbbe51f53 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:05:21 -0800 Subject: [PATCH] s390: sclp bug fixes. From: Martin Schwidefsky SCLP console/tty fixes: - Fix incorrect state change of SCLP_RUNNING flag in interrupt handler - Suppress emission of empty buffers to prevent stack overflow - Fix off by one error in sclp_write (used to return # of chars written + 1) - Prevent sclp_tty_write_string from waiting in interrupt (during flush) - Fix deadlock after TIOCSCLPSNL ioctl - Fix sclp_tty_chars_in_buffer calculation --- drivers/s390/char/sclp.c | 5 +++-- drivers/s390/char/sclp_con.c | 3 ++- drivers/s390/char/sclp_rw.c | 2 +- drivers/s390/char/sclp_tty.c | 24 ++++++++++++++++++------ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 2aaf356845ac..0e5fc8964479 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -315,8 +315,9 @@ sclp_interrupt_handler(struct pt_regs *regs, __u16 code) /* Head queue a read sccb if an event buffer is pending */ if (evbuf_pending) __sclp_unconditional_read(); - /* Now clear the running bit */ - clear_bit(SCLP_RUNNING, &sclp_status); + /* Now clear the running bit if SCLP indicated a finished SCCB */ + if (finished_sccb != 0U) + clear_bit(SCLP_RUNNING, &sclp_status); spin_unlock(&sclp_lock); /* and start next request on the queue */ sclp_start_request(); diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index d393ab443057..5a76bea84aa3 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -149,7 +149,8 @@ sclp_console_write(struct console *console, const char *message, count -= written; } while (count > 0); /* Setup timer to output current console buffer after 1/10 second */ - if (sclp_conbuf != NULL && !timer_pending(&sclp_con_timer)) { + if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 && + !timer_pending(&sclp_con_timer)) { init_timer(&sclp_con_timer); sclp_con_timer.function = sclp_console_timeout; sclp_con_timer.data = 0UL; diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index b4cdc4e42da7..296f60d95ef6 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c @@ -274,7 +274,7 @@ sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count) if (buffer->current_line != NULL) sclp_finalize_mto(buffer); /* skip the rest of the message including the 0 byte */ - i_msg = count; + i_msg = count - 1; break; default: /* no escape character */ /* do not output unprintable characters */ diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 94daea2fb396..d9c5911bf4f9 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "ctrlchar.h" @@ -337,8 +338,11 @@ sclp_tty_write_string(const unsigned char *str, int count) if (sclp_ttybuf == NULL) { while (list_empty(&sclp_tty_pages)) { spin_unlock_irqrestore(&sclp_tty_lock, flags); - wait_event(sclp_tty_waitq, - !list_empty(&sclp_tty_pages)); + if (in_interrupt()) + sclp_sync_wait(); + else + wait_event(sclp_tty_waitq, + !list_empty(&sclp_tty_pages)); spin_lock_irqsave(&sclp_tty_lock, flags); } page = sclp_tty_pages.next; @@ -366,7 +370,9 @@ sclp_tty_write_string(const unsigned char *str, int count) } while (count > 0); /* Setup timer to output current console buffer after 1/10 second */ if (sclp_ioctls.final_nl) { - if (sclp_ttybuf != NULL && !timer_pending(&sclp_tty_timer)) { + if (sclp_ttybuf != NULL && + sclp_chars_in_buffer(sclp_ttybuf) != 0 && + !timer_pending(&sclp_tty_timer)) { init_timer(&sclp_tty_timer); sclp_tty_timer.function = sclp_tty_timeout; sclp_tty_timer.data = 0UL; @@ -374,8 +380,14 @@ sclp_tty_write_string(const unsigned char *str, int count) add_timer(&sclp_tty_timer); } } else { - __sclp_ttybuf_emit(sclp_ttybuf); - sclp_ttybuf = NULL; + if (sclp_ttybuf != NULL && + sclp_chars_in_buffer(sclp_ttybuf) != 0) { + buf = sclp_ttybuf; + sclp_ttybuf = NULL; + spin_unlock_irqrestore(&sclp_tty_lock, flags); + __sclp_ttybuf_emit(buf); + spin_lock_irqsave(&sclp_tty_lock, flags); + } } spin_unlock_irqrestore(&sclp_tty_lock, flags); } @@ -471,7 +483,7 @@ sclp_tty_chars_in_buffer(struct tty_struct *tty) count = sclp_chars_in_buffer(sclp_ttybuf); list_for_each(l, &sclp_tty_outqueue) { t = list_entry(l, struct sclp_buffer, list); - count += sclp_chars_in_buffer(sclp_ttybuf); + count += sclp_chars_in_buffer(t); } spin_unlock_irqrestore(&sclp_tty_lock, flags); return count; -- cgit v1.2.3 From 4093261b82b7dbe3be34d38e106a3de9ffffa771 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 18:06:29 -0800 Subject: [PATCH] RAID-6: x86-64 crash workaround From: "H. Peter Anvin" Apparently, on x86-64, the stack isn't always aligned properly (16 bytes) in the kernel at the moment. This causes the RAID-6 code to crash the system. This patch is a workaround for that; the right thing is to muck with the assembly entrypoints to enforce proper stack alignment. However, that's not anything I feel comfortable doing in an evening, especially since I don't have a machine on which I can test the resulting kernels. --- drivers/md/raid6x86.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 0579c764dd09..41867a6903d6 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -32,18 +32,20 @@ typedef struct { /* N.B.: For SSE we only save %xmm0-%xmm7 even for x86-64, since the code doesn't know about the additional x86-64 registers */ typedef struct { - unsigned int sarea[8*4]; - unsigned int cr0; + unsigned int sarea[8*4+2]; + unsigned long cr0; } raid6_sse_save_t __attribute__((aligned(16))); /* This is for x86-64-specific code which uses all 16 XMM registers */ typedef struct { - unsigned int sarea[16*4]; + unsigned int sarea[16*4+2]; unsigned long cr0; } raid6_sse16_save_t __attribute__((aligned(16))); -/* On x86-64 the stack is 16-byte aligned */ -#define SAREA(x) (x->sarea) +/* On x86-64 the stack *SHOULD* be 16-byte aligned, but currently this + is buggy in the kernel and it's only 8-byte aligned in places, so + we need to do this anyway. Sigh. */ +#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) #else /* __i386__ */ @@ -60,6 +62,7 @@ typedef struct { unsigned long cr0; } raid6_sse_save_t; +/* Find the 16-byte aligned save area */ #define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) #endif -- cgit v1.2.3 From 9d3e58e32d6f6b1f5b532c0c8ee11fdcfbfedabd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Jan 2004 19:46:20 -0800 Subject: Upgrade x86 defconfig to something less ancient. --- arch/i386/defconfig | 424 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 250 insertions(+), 174 deletions(-) diff --git a/arch/i386/defconfig b/arch/i386/defconfig index b490262ee20a..8f2ebb733c59 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -10,7 +10,8 @@ CONFIG_GENERIC_ISA_DMA=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_BROKEN is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y # # General setup @@ -20,6 +21,7 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_FUTEX=y @@ -27,6 +29,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -79,7 +82,8 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_GOOD_APIC=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_USE_PPRO_CHECKSUM=y -# CONFIG_HUGETLB_PAGE is not set +# CONFIG_HPET_TIMER is not set +# CONFIG_HPET_EMULATE_RTC is not set CONFIG_SMP=y CONFIG_NR_CPUS=8 CONFIG_PREEMPT=y @@ -100,20 +104,22 @@ CONFIG_NOHIGHMEM=y # CONFIG_HIGHMEM64G is not set # CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y +# CONFIG_EFI is not set CONFIG_HAVE_DEC_LOCK=y # # Power management options (ACPI, APM) # CONFIG_PM=y -# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SOFTWARE_SUSPEND=y +# CONFIG_PM_DISK is not set # # ACPI (Advanced Configuration and Power Interface) Support # -CONFIG_ACPI_HT=y CONFIG_ACPI=y CONFIG_ACPI_BOOT=y +CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_SLEEP=y CONFIG_ACPI_SLEEP_PROC_FS=y CONFIG_ACPI_AC=y @@ -126,11 +132,11 @@ CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_TOSHIBA is not set # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_RELAXED_AML is not set # # APM (Advanced Power Management) BIOS Support @@ -151,6 +157,7 @@ CONFIG_PCI=y CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y +# CONFIG_PCI_USE_VECTOR is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y CONFIG_ISA=y @@ -173,12 +180,14 @@ CONFIG_PCMCIA_PROBE=y # # Executable file formats # -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_MISC=y +# +# Device Drivers +# + # # Generic Driver Options # @@ -262,7 +271,6 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set @@ -300,6 +308,7 @@ CONFIG_IDEDMA_AUTO=y # SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -330,11 +339,14 @@ CONFIG_SCSI_REPORT_LUNS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_SVW is not set +CONFIG_SCSI_ATA_PIIX=y +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_VIA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set @@ -346,22 +358,21 @@ CONFIG_SCSI_REPORT_LUNS=y # CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_SYM53C8XX is not set # CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SEAGATE is not set +CONFIG_SCSI_QLA2XXX_CONFIG=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA23XX is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -402,7 +413,7 @@ CONFIG_IEEE1394=y # # -# Texas Instruments PCILynx requires I2C bit-banging +# Texas Instruments PCILynx requires I2C # CONFIG_IEEE1394_OHCI1394=y @@ -447,10 +458,67 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set -# CONFIG_NETFILTER is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +# CONFIG_IP_NF_FTP is not set +# CONFIG_IP_NF_IRC is not set +# CONFIG_IP_NF_TFTP is not set +# CONFIG_IP_NF_AMANDA is not set +CONFIG_IP_NF_QUEUE=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_LIMIT=y +CONFIG_IP_NF_MATCH_IPRANGE=y +CONFIG_IP_NF_MATCH_MAC=y +CONFIG_IP_NF_MATCH_PKTTYPE=y +CONFIG_IP_NF_MATCH_MARK=y +CONFIG_IP_NF_MATCH_MULTIPORT=y +CONFIG_IP_NF_MATCH_TOS=y +CONFIG_IP_NF_MATCH_RECENT=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_DSCP=y +CONFIG_IP_NF_MATCH_AH_ESP=y +CONFIG_IP_NF_MATCH_LENGTH=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_MATCH_TCPMSS=y +CONFIG_IP_NF_MATCH_HELPER=y +CONFIG_IP_NF_MATCH_STATE=y +CONFIG_IP_NF_MATCH_CONNTRACK=y +CONFIG_IP_NF_MATCH_OWNER=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_SAME=y +# CONFIG_IP_NF_NAT_LOCAL is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_TOS=y +CONFIG_IP_NF_TARGET_ECN=y +CONFIG_IP_NF_TARGET_DSCP=y +CONFIG_IP_NF_TARGET_MARK=y +CONFIG_IP_NF_TARGET_CLASSIFY=y +CONFIG_IP_NF_TARGET_LOG=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_IP_NF_TARGET_TCPMSS=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y # # SCTP Configuration (EXPERIMENTAL) @@ -459,7 +527,9 @@ CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -487,14 +557,13 @@ CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -517,6 +586,7 @@ CONFIG_NET_PCI=y # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_CS89x0 is not set # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set @@ -567,8 +637,9 @@ CONFIG_8139TOO=y # CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # +# CONFIG_TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -588,6 +659,11 @@ CONFIG_8139TOO=y # # CONFIG_IRDA is not set +# +# Bluetooth support +# +# CONFIG_BT is not set + # # ISDN subsystem # @@ -659,6 +735,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_CONSOLE is not set # CONFIG_SERIAL_8250_ACPI is not set +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -672,20 +749,6 @@ CONFIG_PRINTER=y # CONFIG_PPDEV is not set # CONFIG_TIPAR is not set -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - # # Mice # @@ -713,7 +776,6 @@ CONFIG_PRINTER=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set CONFIG_AGP=y # CONFIG_AGP_ALI is not set # CONFIG_AGP_ATI is not set @@ -732,10 +794,16 @@ CONFIG_DRM=y # CONFIG_DRM_I810 is not set CONFIG_DRM_I830=y # CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set # CONFIG_MWAVE is not set # CONFIG_RAW_DRIVER is not set # CONFIG_HANGCHECK_TIMER is not set +# +# I2C support +# +# CONFIG_I2C is not set + # # Multimedia devices # @@ -746,138 +814,6 @@ CONFIG_DRM_I830=y # # CONFIG_DVB is not set -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -CONFIG_UDF_FS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - # # Graphics support # @@ -1057,7 +993,6 @@ CONFIG_USB_HIDINPUT=y # # USB Network adaptors # -# CONFIG_USB_AX8817X is not set # CONFIG_USB_CATC is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set @@ -1077,30 +1012,170 @@ CONFIG_USB_HIDINPUT=y # # USB Miscellaneous drivers # +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set # CONFIG_USB_TIGL is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_BRLVGER is not set # CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set # CONFIG_USB_TEST is not set + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set # -# Bluetooth support +# File systems # -# CONFIG_BT is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Profiling support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y -CONFIG_FRAME_POINTER=y +# CONFIG_FRAME_POINTER is not set CONFIG_X86_FIND_SMP_CONFIG=y CONFIG_X86_MPPARSE=y @@ -1117,8 +1192,9 @@ CONFIG_X86_MPPARSE=y # # Library routines # -# CONFIG_CRC32 is not set +CONFIG_CRC32=y CONFIG_X86_SMP=y CONFIG_X86_HT=y CONFIG_X86_BIOS_REBOOT=y CONFIG_X86_TRAMPOLINE=y +CONFIG_PC=y -- cgit v1.2.3 From 4b29eb07dad89c5ca87389265659eedd3bfe56a0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Jan 2004 20:22:51 -0800 Subject: [PATCH] ppc32: MBX MAC address fix From Tom Rini On the MBX the kernel made an assumption about where the MAC address would be in the VPD (Vital Product Data). However, the documentation for the firmware (EPPC-Bug) describes the format of the VPD and makes no guarrantees about the location of any VPD record. It does however describe the format of each record type and the MAC address record will be of type '08' and of size 6. This changes the code so that instead of assuming a position, it searches for the record, which I assume is also what EPPC-Bug does. --- arch/ppc/boot/simple/embed_config.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c index 8b0c82bbefb6..3c3b31c98819 100644 --- a/arch/ppc/boot/simple/embed_config.c +++ b/arch/ppc/boot/simple/embed_config.c @@ -50,7 +50,7 @@ embed_config(bd_t **bdp) { u_char *mp; u_char eebuf[128]; - int i; + int i = 8; bd_t *bd; bd = *bdp; @@ -62,11 +62,21 @@ embed_config(bd_t **bdp) /* All we are looking for is the Ethernet MAC address. The * first 8 bytes are 'MOTOROLA', so check for part of that. + * Next, the VPD describes a MAC 'packet' as being of type 08 + * and size 06. So we look for that and the MAC must follow. + * If there are more than one, we still only care about the first. * If it's there, assume we have a valid MAC address. If not, * grab our default one. */ - if ((*(uint *)eebuf) == 0x4d4f544f) - mp = &eebuf[0x4c]; + if ((*(uint *)eebuf) == 0x4d4f544f) { + while (i < 127 && !(eebuf[i] == 0x08 && eebuf[i + 1] == 0x06)) + i += eebuf[i + 1] + 2; /* skip this packet */ + + if (i == 127) /* Couldn't find. */ + mp = (u_char *)def_enet_addr; + else + mp = &eebuf[i + 2]; + } else mp = (u_char *)def_enet_addr; -- cgit v1.2.3 From d113a0e9e6f5651e1195a126d70b898b13b3d9f6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Jan 2004 21:33:13 -0800 Subject: Make EHCI have a 20ms power-on to power-good timeout. This should fix some picky USB devices. --- drivers/usb/host/ehci-hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6dbf4e3cc4e3..fb258264b3fe 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -113,7 +113,7 @@ ehci_hub_descriptor ( u16 temp; desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = 0; /* FIXME: f(system power) */ + desc->bPwrOn2PwrGood = 10; /* FIXME: f(system power) */ desc->bHubContrCurrent = 0; desc->bNbrPorts = ports; -- cgit v1.2.3 From 52dd1e0407d0f11dd3581798f5906b9120a255b0 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Sat, 31 Jan 2004 22:56:12 -0500 Subject: IEEE1394(r1112): Adds a "ieee1394_guid" attribute to the scsi device for sbp2. --- drivers/ieee1394/sbp2.c | 36 +++++++++++++++++++++++++++++------- drivers/ieee1394/sbp2.h | 3 +++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index ce5fefc322eb..ce336f39a881 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -745,6 +745,7 @@ static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) SBP2_ERR("failed to add scsi host"); scsi_host_put(hi->scsi_host); hpsb_destroy_hostinfo(&sbp2_highlevel, host); + return NULL; } return hi; @@ -990,6 +991,9 @@ alloc_fail: return PTR_ERR(sdev); } + sdev->hostdata = scsi_id; + scsi_id->sdev = sdev; + return 0; } @@ -999,7 +1003,6 @@ alloc_fail: static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi = scsi_id->hi; - struct scsi_device *sdev; SBP2_DEBUG("sbp2_remove_device"); @@ -1007,12 +1010,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); /* Remove it from the scsi layer now */ - /* XXX(hch): why can't we simply cache the scsi_device - in struct scsi_id_instance_data? */ - sdev = scsi_device_lookup(hi->scsi_host, 0, scsi_id->id, 0); - if (sdev) { - scsi_remove_device(sdev); - scsi_device_put(sdev); + if (scsi_id->sdev) { + scsi_remove_device(scsi_id->sdev); + scsi_device_put(scsi_id->sdev); } sbp2util_remove_command_orb_pool(scsi_id); @@ -2849,6 +2849,27 @@ static const char *sbp2scsi_info (struct Scsi_Host *host) return "SCSI emulation for IEEE-1394 SBP-2 Devices"; } +static ssize_t sbp2_sysfs_ieee1394_guid_show(struct device *dev, char *buf) +{ + struct scsi_device *sdev; + struct scsi_id_instance_data *scsi_id; + + if (!(sdev = to_scsi_device(dev))) + return 0; + + if (!(scsi_id = sdev->hostdata)) + return 0; + + return sprintf(buf, "%016Lx\n", (unsigned long long)scsi_id->ne->guid); +} + +static DEVICE_ATTR(ieee1394_guid, S_IRUGO, sbp2_sysfs_ieee1394_guid_show, NULL); + +static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { + &dev_attr_ieee1394_guid, + NULL +}; + MODULE_AUTHOR("Ben Collins "); MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); @@ -2871,6 +2892,7 @@ static Scsi_Host_Template scsi_driver_template = { .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, .can_queue = SBP2_MAX_SCSI_QUEUE, .emulated = 1, + .sdev_attrs = sbp2_sysfs_sdev_attrs, }; static int sbp2_module_init(void) diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 9831784cd7b5..b96400c041ed 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -410,6 +410,9 @@ struct scsi_id_instance_data { /* A backlink to our host_info */ struct sbp2scsi_host_info *hi; + /* The scsi_device associated with this scsi_id */ + struct scsi_device *sdev; + /* Device specific workarounds/brokeness */ u32 workarounds; }; -- cgit v1.2.3 From 0b460a61f40e9b5047403c5daaccbc759d4564cf Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Sat, 31 Jan 2004 22:58:02 -0500 Subject: IEEE1394(r1116): Make sure to unregister addr space when a driver is removed. --- drivers/ieee1394/highlevel.c | 69 +++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 74078ad6a918..77c3623c00ce 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -261,30 +261,46 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl) return; } +static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host) +{ + unsigned long flags; + struct list_head *lh, *next; + struct hpsb_address_serve *as; + + if (hl->remove_host) + hl->remove_host(host); + + /* Remove any addresses that are matched for this highlevel driver + * and this particular host. */ + write_lock_irqsave(&addr_space_lock, flags); + list_for_each_safe (lh, next, &hl->addr_list) { + as = list_entry(lh, struct hpsb_address_serve, addr_list); + + if (as->host != host) + continue; + + if (!list_empty(&as->addr_list)) { + list_del(&as->as_list); + list_del(&as->addr_list); + kfree(as); + } + } + write_unlock_irqrestore(&addr_space_lock, flags); + + hpsb_destroy_hostinfo(hl, host); +} + static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data) { struct hpsb_highlevel *hl = __data; - hl->remove_host(host); - hpsb_destroy_hostinfo(hl, host); + __unregister_host(hl, host); return 0; } void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) { - struct list_head *lh, *next; - struct hpsb_address_serve *as; - unsigned long flags; - - write_lock_irqsave(&addr_space_lock, flags); - list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, addr_list); - list_del(&as->as_list); - kfree(as); - } - write_unlock_irqrestore(&addr_space_lock, flags); - write_lock(&hl_irqs_lock); list_del(&hl->irq_list); write_unlock(&hl_irqs_lock); @@ -293,8 +309,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) list_del(&hl->hl_list); up_write(&hl_drivers_sem); - if (hl->remove_host) - nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); + nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); } int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, @@ -435,29 +450,11 @@ void highlevel_add_host(struct hpsb_host *host) void highlevel_remove_host(struct hpsb_host *host) { struct hpsb_highlevel *hl; - struct list_head *lh, *next; - struct hpsb_address_serve *as; - unsigned long flags; down_read(&hl_drivers_sem); - list_for_each_entry(hl, &hl_drivers, hl_list) { - if (hl->remove_host) { - hl->remove_host(host); - hpsb_destroy_hostinfo(hl, host); - } - } + list_for_each_entry(hl, &hl_drivers, hl_list) + __unregister_host(hl, host); up_read(&hl_drivers_sem); - - /* Free up 1394 address space left behind by high level drivers. */ - write_lock_irqsave(&addr_space_lock, flags); - list_for_each_safe (lh, next, &host->addr_space) { - as = list_entry(lh, struct hpsb_address_serve, as_list); - if (!list_empty(&as->addr_list)) { - list_del(&as->addr_list); - kfree(as); - } - } - write_unlock_irqrestore(&addr_space_lock, flags); } void highlevel_host_reset(struct hpsb_host *host) -- cgit v1.2.3 From 4a9c380d2bed9fc2dcb9c85b3e4c2807ad65d480 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 31 Jan 2004 20:49:23 -0800 Subject: [PATCH] fix the build for NR_CPUS > 4*BITS_PER_LONG You can't just cast cpumasks. It doesn't compile if NR_CPUS is greater than 4 * BITS_PER_LONG. --- drivers/pci/probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 19c9f836e2f9..7ff393b53a28 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -53,8 +53,12 @@ postcore_initcall(pcibus_class_init); static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf) { cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number); + int ret; - return sprintf(buf, "%lx\n", (unsigned long)cpumask); + ret = cpumask_snprintf(buf, PAGE_SIZE, cpumask); + if (ret < PAGE_SIZE) + buf[ret++] = '\n'; + return ret; } static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL); -- cgit v1.2.3 From a50de1c422207d617a063da7c89d25593c362705 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sat, 31 Jan 2004 20:50:52 -0800 Subject: [PATCH] fix issues with loading PCI IDE drivers as modules From: Davin McCall Set hwif->chipset to ide_forced if it was forced by kernel parameters. Set hwif->chipset to ide_generic for hwifs controlled by generic IDE code, so they wont be taken by setup_pci.c:ide_match_hwif(). Patch also fixes /proc/ide/ideX/model to report "generic" instead of "(none)" for default hwifs. This has been in -mm since 2.6.1-mm1. --- drivers/ide/ide-probe.c | 2 ++ drivers/ide/ide-proc.c | 4 +++- drivers/ide/ide.c | 2 +- drivers/ide/pci/cmd640.c | 2 +- drivers/ide/setup-pci.c | 2 +- include/linux/ide.h | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ef80249cda49..59d3da8c6e48 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1343,6 +1343,8 @@ int ideprobe_init (void) int unit; if (!hwif->present) continue; + if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) + hwif->chipset = ide_generic; for (unit = 0; unit < MAX_DRIVES; ++unit) if (hwif->drives[unit].present) ata_attach(&hwif->drives[unit]); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 49b754b86efa..323eeb79f0eb 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -348,8 +348,10 @@ static int proc_ide_read_imodel int len; const char *name; + /* + * Neither ide_unknown nor ide_forced should be set at this point. + */ switch (hwif->chipset) { - case ide_unknown: name = "(none)"; break; case ide_generic: name = "generic"; break; case ide_pci: name = "pci"; break; case ide_cmd640: name = "cmd640"; break; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bf2282aa9c7a..01134b2e1bb0 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -2179,7 +2179,7 @@ int __init ide_setup (char *s) memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->irq = vals[2]; hwif->noprobe = 0; - hwif->chipset = ide_generic; + hwif->chipset = ide_forced; goto done; case 0: goto bad_option; diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 08a74cdb6605..0eac8ee64d2e 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -419,7 +419,7 @@ static void __init setup_device_ptrs (void) cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ for (i = 0; i < MAX_HWIFS; i++) { ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { + if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) { if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) cmd_hwif0 = hwif; else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index e0ed9c0493f9..a2ff75859e45 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -59,7 +59,7 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char for (h = 0; h < MAX_HWIFS; ++h) { hwif = &ide_hwifs[h]; if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_generic) + if (hwif->chipset == ide_forced) return hwif; /* a perfect match */ } } diff --git a/include/linux/ide.h b/include/linux/ide.h index a9c107b8716d..ea10e916d9eb 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -279,7 +279,7 @@ typedef enum { ide_unknown, ide_generic, ide_pci, ide_pdc4030, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, ide_pmac, ide_etrax100, ide_acorn, - ide_pc9800 + ide_pc9800, ide_forced } hwif_chipset_t; /* -- cgit v1.2.3 From ff9e1135aec3bd1e9230593880e24a018dbdf789 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 1 Feb 2004 00:17:10 -0800 Subject: [COMPAT]: Fix TUNSETIFF ioctl compat, it takes an ifreq ptr not an int. Thanks to Eric Brower for spotting this. --- fs/compat_ioctl.c | 1 + include/linux/compat_ioctl.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e8b5a1330506..b2048a804995 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -3093,6 +3093,7 @@ HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(TUNSETIFF, dev_ifsioc) HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index 553442de3ecf..3c2fb5fae259 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -192,7 +192,6 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) /* Big T */ COMPATIBLE_IOCTL(TUNSETNOCSUM) COMPATIBLE_IOCTL(TUNSETDEBUG) -COMPATIBLE_IOCTL(TUNSETIFF) COMPATIBLE_IOCTL(TUNSETPERSIST) COMPATIBLE_IOCTL(TUNSETOWNER) /* Big V */ -- cgit v1.2.3 From b1c76c1cb272f5dedf0264a58904b544c6ce56fb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 1 Feb 2004 02:17:14 -0800 Subject: [PATCH] fix/improve modular IDE This has been in -mm since 2.6.1-mm5 - IDE can be used as module again (compiles and works), this fixes bugzilla bugs #576 and #1700 - separate module for probing is no longer required - generic/default host driver is available as ide_generic module This contains the build fixes by Adrian Bunk and Andrew Morton. --- drivers/block/ll_rw_blk.c | 2 ++ drivers/ide/Kconfig | 6 ++++++ drivers/ide/Makefile | 38 +++++++++++++++++++++++++---------- drivers/ide/ide-generic.c | 34 +++++++++++++++++++++++++++++++ drivers/ide/ide-probe.c | 25 ++--------------------- drivers/ide/ide.c | 49 ++++++--------------------------------------- drivers/ide/legacy/Makefile | 7 ------- drivers/ide/pci/Makefile | 1 - drivers/ide/ppc/Makefile | 6 ------ include/linux/ide.h | 1 - 10 files changed, 77 insertions(+), 92 deletions(-) create mode 100644 drivers/ide/ide-generic.c delete mode 100644 drivers/ide/ppc/Makefile diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index c23382abd4f5..c3974ba569ae 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -145,6 +145,8 @@ void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) q->activity_data = data; } +EXPORT_SYMBOL(blk_queue_activity_fn); + /** * blk_queue_prep_rq - set a prepare_request function for queue * @q: queue diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 7889c28de3db..f58c227813c5 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -296,6 +296,12 @@ config IDE_TASKFILE_IO comment "IDE chipset support/bugfixes" +config IDE_GENERIC + tristate "generic/default IDE chipset support" + default y + help + If unsure, say Y. + config BLK_DEV_CMD640 bool "CMD640 chipset bugfix/support" depends on X86 diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index ac76a4308ed1..488c784ce670 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -13,22 +13,38 @@ EXTRA_CFLAGS += -Idrivers/ide obj-$(CONFIG_BLK_DEV_IDE) += pci/ +ide-core-y += ide.o ide-default.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ + ide-taskfile.o + +ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o + # Core IDE code - must come before legacy +ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o +ide-core-$(CONFIG_BLK_DEV_IDEDMA_PCI) += ide-dma.o +ide-core-$(CONFIG_BLK_DEV_IDE_TCQ) += ide-tcq.o +ide-core-$(CONFIG_PROC_FS) += ide-proc.o +ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o + +# built-in only drivers from legacy/ +ide-core-$(CONFIG_BLK_DEV_IDE_PC9800) += legacy/pc9800.o +ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o +ide-core-$(CONFIG_BLK_DEV_FALCON_IDE) += legacy/falconide.o +ide-core-$(CONFIG_BLK_DEV_GAYLE) += legacy/gayle.o +ide-core-$(CONFIG_BLK_DEV_MAC_IDE) += legacy/macide.o +ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o + +# built-in only drivers from ppc/ +ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o +ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o +ide-core-$(CONFIG_BLK_DEV_IDE_SWARM) += ppc/swarm.o + +obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o +obj-$(CONFIG_IDE_GENERIC) += ide-generic.o -obj-$(CONFIG_BLK_DEV_IDE) += ide-io.o ide-probe.o ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-default.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o -obj-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o -obj-$(CONFIG_BLK_DEV_IDEDMA_PCI) += ide-dma.o -obj-$(CONFIG_BLK_DEV_IDE_TCQ) += ide-tcq.o -obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o - -ifeq ($(CONFIG_BLK_DEV_IDE),y) -obj-$(CONFIG_PROC_FS) += ide-proc.o -endif - -obj-$(CONFIG_BLK_DEV_IDE) += legacy/ ppc/ arm/ +obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ obj-$(CONFIG_BLK_DEV_HD) += legacy/ diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c new file mode 100644 index 000000000000..ee27933152d1 --- /dev/null +++ b/drivers/ide/ide-generic.c @@ -0,0 +1,34 @@ +/* + * generic/default IDE host driver + * + * Copyright (C) 2004 Bartlomiej Zolnierkiewicz + * This code was split off from ide.c. See it for original copyrights. + * + * May be copied or modified under the terms of the GNU General Public License. + */ + +#include +#include +#include +#include + +static int __init ide_generic_init(void) +{ + MOD_INC_USE_COUNT; + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) + ide_get_lock(NULL, NULL); /* for atari only */ + + (void)ideprobe_init(); + + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) + ide_release_lock(); /* for atari only */ + +#ifdef CONFIG_PROC_FS + create_proc_ide_interfaces(); +#endif + return 0; +} + +module_init(ide_generic_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 59d3da8c6e48..2d75b2cf8bb5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1322,8 +1322,7 @@ int ideprobe_init (void) { unsigned int index; int probe[MAX_HWIFS]; - - MOD_INC_USE_COUNT; + memset(probe, 0, MAX_HWIFS * sizeof(int)); for (index = 0; index < MAX_HWIFS; ++index) probe[index] = !ide_hwifs[index].present; @@ -1350,27 +1349,7 @@ int ideprobe_init (void) ata_attach(&hwif->drives[unit]); } } - if (!ide_probe) - ide_probe = &ideprobe_init; - MOD_DEC_USE_COUNT; return 0; } -#ifdef MODULE -int init_module (void) -{ - unsigned int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - ideprobe_init(); - create_proc_ide_interfaces(); - return 0; -} - -void cleanup_module (void) -{ - ide_probe = NULL; -} -MODULE_LICENSE("GPL"); -#endif /* MODULE */ +EXPORT_SYMBOL_GPL(ideprobe_init); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 01134b2e1bb0..25b79a70ee02 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -153,7 +153,6 @@ #include #include #include -#include #include #include @@ -191,8 +190,6 @@ int noautodma = 1; EXPORT_SYMBOL(noautodma); EXPORT_SYMBOL(ide_bus_type); -int (*ide_probe)(void); - /* * This is declared extern in ide.h, for access by other IDE modules: */ @@ -443,21 +440,6 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) EXPORT_SYMBOL(ide_dump_status); - - -void ide_probe_module (void) -{ - if (!ide_probe) { -#if defined(CONFIG_KMOD) && defined(CONFIG_BLK_DEV_IDE_MODULE) - (void) request_module("ide-probe-mod"); -#endif /* (CONFIG_KMOD) && (CONFIG_BLK_DEV_IDE_MODULE) */ - } else { - (void)ide_probe(); - } -} - -EXPORT_SYMBOL(ide_probe_module); - static int ide_open (struct inode * inode, struct file * filp) { return -ENXIO; @@ -1033,7 +1015,7 @@ found: hwif->chipset = hw->chipset; if (!initializing) { - ide_probe_module(); + probe_hwif_init(hwif); #ifdef CONFIG_PROC_FS create_proc_ide_interfaces(); #endif @@ -2276,28 +2258,6 @@ static void __init probe_for_hwifs (void) #endif /* CONFIG_BLK_DEV_IDEPNP */ } -void __init ide_init_builtin_drivers (void) -{ - /* - * Probe for special PCI and other "known" interface chipsets - */ - probe_for_hwifs (); - -#ifdef CONFIG_BLK_DEV_IDE - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) - ide_get_lock(NULL, NULL); /* for atari only */ - - (void) ideprobe_init(); - - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) - ide_release_lock(); /* for atari only */ -#endif /* CONFIG_BLK_DEV_IDE */ - -#ifdef CONFIG_PROC_FS - proc_ide_create(); -#endif -} - /* * Actually unregister the subdriver. Called with the * request lock dropped. @@ -2558,7 +2518,6 @@ EXPORT_SYMBOL(ide_fops); */ EXPORT_SYMBOL(ide_lock); -EXPORT_SYMBOL(ide_probe); struct bus_type ide_bus_type = { .name = "ide", @@ -2601,9 +2560,13 @@ int __init ide_init (void) #endif initializing = 1; - ide_init_builtin_drivers(); + /* Probe for special PCI and other "known" interface chipsets. */ + probe_for_hwifs(); initializing = 0; +#ifdef CONFIG_PROC_FS + proc_ide_create(); +#endif return 0; } diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index 9d3feaf52fb4..ad8ae32b8193 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -2,17 +2,10 @@ obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -obj-$(CONFIG_BLK_DEV_IDE_PC9800) += pc9800.o obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o -obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o -obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o -obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o -obj-$(CONFIG_BLK_DEV_MAC_IDE) += macide.o -obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o - obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o # Last of all diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 3d2e1213fa11..ddaee15b1d52 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_BLK_DEV_ADMA100) += adma100.o obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o -obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile deleted file mode 100644 index 6fc3fa38f1c7..000000000000 --- a/drivers/ide/ppc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o -obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o -obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o - -EXTRA_CFLAGS := -Idrivers/ide diff --git a/include/linux/ide.h b/include/linux/ide.h index ea10e916d9eb..ef73baf33fc8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1231,7 +1231,6 @@ typedef struct ide_devices_s { */ #ifndef _IDE_C extern ide_hwif_t ide_hwifs[]; /* master data repository */ -extern int (*ide_probe)(void); extern ide_devices_t *idedisk; extern ide_devices_t *idecd; -- cgit v1.2.3