From c9b9226830bdc88e57166ec7355bccda28eb95f5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 Feb 2002 17:53:24 -0800 Subject: v2.4.0.11 -> v2.4.0.12 - Get non-cpuid Cyrix probing right (it's not a NexGen) - Jens Axboe: cdrom tray status and queing cleanups - AGP GART: don't disable VIA, and allow i815 with external AGP - Coda: use iget4() in order to have big inode numbers without clashes. - Fix UDF writepage() page locking - NIIBE Yutaka: SuperH update - Martin Diehl and others: SiS pirq routing fixes - Andy Grover: ACPI update - Andrea Arkangeli: LVM update - Ingo Molnar: RAID cleanups - David Miller: sparc and networking updates - Make NFS really be able to handle large files --- Documentation/Configure.help | 23 -- MAINTAINERS | 6 + Makefile | 2 +- arch/i386/kernel/pci-irq.c | 113 +++++- arch/i386/kernel/setup.c | 6 +- arch/sh/boot/compressed/head.S | 2 +- arch/sh/kernel/entry.S | 738 +++++++++++++++++++----------------- arch/sh/kernel/fpu.c | 212 +++++------ arch/sh/kernel/head.S | 44 +-- arch/sh/kernel/irq.c | 2 +- arch/sh/kernel/irq_imask.c | 8 +- arch/sh/kernel/process.c | 32 +- arch/sh/kernel/setup.c | 4 +- arch/sh/kernel/sh_bios.c | 18 +- arch/sh/kernel/sh_ksyms.c | 5 +- arch/sh/kernel/signal.c | 4 +- arch/sh/kernel/traps.c | 445 +++++++++++++++++++++- arch/sh/lib/checksum.S | 157 ++++---- arch/sh/lib/delay.c | 6 +- arch/sh/mm/cache.c | 16 + arch/sparc/kernel/entry.S | 3 +- arch/sparc64/defconfig | 2 + arch/sparc64/kernel/smp.c | 4 +- drivers/acpi/acpi_ksyms.c | 8 - drivers/acpi/common/cmalloc.c | 2 +- drivers/acpi/common/cmxface.c | 16 +- drivers/acpi/cpu.c | 51 +-- drivers/acpi/dispatcher/dsmthdat.c | 45 ++- drivers/acpi/dispatcher/dswexec.c | 4 +- drivers/acpi/driver.c | 28 +- drivers/acpi/ec.c | 2 - drivers/acpi/hardware/hwacpi.c | 50 +-- drivers/acpi/hardware/hwcpu32.c | 709 ---------------------------------- drivers/acpi/hardware/hwgpe.c | 3 +- drivers/acpi/hardware/hwregs.c | 47 +-- drivers/acpi/hardware/hwsleep.c | 189 +++++++++ drivers/acpi/hardware/hwtimer.c | 196 ++++++++++ drivers/acpi/hardware/hwxface.c | 595 ----------------------------- drivers/acpi/include/accommon.h | 2 +- drivers/acpi/include/acconfig.h | 4 +- drivers/acpi/include/achware.h | 96 +---- drivers/acpi/include/acinterp.h | 70 +++- drivers/acpi/include/aclocal.h | 24 +- drivers/acpi/include/acoutput.h | 3 +- drivers/acpi/include/acpiosxf.h | 4 + drivers/acpi/include/acpixf.h | 4 + drivers/acpi/include/actbl2.h | 4 +- drivers/acpi/include/actypes.h | 7 +- drivers/acpi/interpreter/amconvrt.c | 135 ++++++- drivers/acpi/interpreter/amfield.c | 7 +- drivers/acpi/interpreter/amfldio.c | 22 +- drivers/acpi/interpreter/amresolv.c | 4 +- drivers/acpi/interpreter/amstore.c | 449 ++++++++++++++++------ drivers/acpi/interpreter/amstoren.c | 488 +++++------------------- drivers/acpi/interpreter/amstorob.c | 522 +++++++++++++++---------- drivers/acpi/namespace/nssearch.c | 4 +- drivers/acpi/namespace/nsutils.c | 2 +- drivers/acpi/parser/psparse.c | 6 +- drivers/acpi/parser/psxface.c | 8 +- drivers/acpi/sys.c | 66 +--- drivers/acpi/table.c | 21 +- drivers/acpi/tables/tbconvrt.c | 4 +- drivers/block/ll_rw_blk.c | 41 +- drivers/cdrom/cdrom.c | 4 +- drivers/char/agp/agpgart_be.c | 11 +- drivers/i2o/i2o_block.c | 5 - drivers/ide/ide-cd.c | 37 +- drivers/isdn/hisax/config.c | 4 +- drivers/md/Config.in | 5 - drivers/md/lvm-snap.c | 32 +- drivers/md/lvm-snap.h | 47 +++ drivers/md/lvm.c | 632 ++++++++++++------------------ drivers/md/md.c | 112 +++--- drivers/net/pcnet32.c | 2 + drivers/net/pppoe.c | 3 +- drivers/sbus/sbus.c | 14 +- drivers/scsi/ibmmca.c | 9 +- drivers/scsi/sr.c | 2 +- drivers/sound/trix.c | 1 - drivers/video/sbusfb.c | 6 +- fs/coda/cnode.c | 62 ++- fs/exec.c | 2 - fs/partitions/msdos.c | 6 +- fs/udf/file.c | 1 + fs/udf/inode.c | 1 - include/asm-sh/current.h | 2 +- include/asm-sh/pgtable.h | 6 +- include/asm-sh/sh_bios.h | 2 + include/asm-sh/system.h | 65 ++-- include/linux/acpi.h | 13 - include/linux/dn.h | 1 - include/linux/lvm.h | 68 +--- include/linux/nfs_xdr.h | 4 +- include/linux/raid/md_u.h | 1 + include/linux/rtc.h | 2 +- include/net/dn.h | 1 - kernel/ksyms.c | 1 + mm/mmap.c | 4 +- net/decnet/af_decnet.c | 25 +- net/ipv4/netfilter/ip_nat_core.c | 21 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 13 +- net/ipv4/netfilter/iptable_mangle.c | 6 +- net/irda/af_irda.c | 3 +- 103 files changed, 3289 insertions(+), 3741 deletions(-) delete mode 100644 drivers/acpi/hardware/hwcpu32.c create mode 100644 drivers/acpi/hardware/hwsleep.c create mode 100644 drivers/acpi/hardware/hwtimer.c delete mode 100644 drivers/acpi/hardware/hwxface.c create mode 100644 drivers/md/lvm-snap.h diff --git a/Documentation/Configure.help b/Documentation/Configure.help index bfe48e9ba811..297f2465fe48 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -1450,15 +1450,6 @@ CONFIG_BLK_DEV_LVM want), say M here and read Documentation/modules.txt. The module will be called lvm-mod.o. -Logical Volume Manager /proc file system information -CONFIG_LVM_PROC_FS - If you say Y here, you are able to access overall Logical Volume - Manager, Volume Group, Logical and Physical Volume information in - /proc/lvm. - - To use this option, you have to check, that the "/proc file system - support" (CONFIG_PROC_FS) is enabled too. - Multiple devices driver support CONFIG_BLK_DEV_MD This driver lets you combine several hard disk partitions into one @@ -1565,20 +1556,6 @@ CONFIG_MD_RAID5 If unsure, say Y. -RAID Boot support -CONFIG_MD_BOOT - To boot with an initial raid volume (any type) you can select - autodetect, or answer Y here and appropriate options to the kernel - at boot time. - For lilo and loadlin options see the file Documentation/md.txt. - -RAID AutoDetect support -CONFIG_AUTODETECT_RAID - An alternative to "Raid Boot support" is autodetect support. - With this selected, any partitons of type 0xFD will be considered for - inclusion in a RAID array. Information in the RAID-superblock on - the partition will determine how it is included. - Support for Acer PICA 1 chipset CONFIG_ACER_PICA_61 This is a machine with a R4400 133/150 MHz CPU. To compile a Linux diff --git a/MAINTAINERS b/MAINTAINERS index 492d15a40e50..e30666fb7ac2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -196,6 +196,12 @@ L: linux-kernel@vger.kernel.org W: http://www.ocston.org/~tigran/patches/bfs S: Maintained +BLOCK LAYER +P: Jens Axboe +M: axboe@suse.de +L: linux-kernel@vger.kernel.org +S: Maintained + BTTV VIDEO4LINUX DRIVER P: Gerd Knorr M: kraxel@goldbach.in-berlin.de diff --git a/Makefile b/Makefile index 5c35d263b899..95228549037e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 1 -EXTRAVERSION =-pre11 +EXTRAVERSION =-pre12 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c index bd2bf22d39d0..8281e3f8272d 100644 --- a/arch/i386/kernel/pci-irq.c +++ b/arch/i386/kernel/pci-irq.c @@ -234,22 +234,107 @@ static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, return 1; } +/* + * PIRQ routing for SiS 85C503 router used in several SiS chipsets + * According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997) + * the related registers work as follows: + * + * general: one byte per re-routable IRQ, + * bit 7 IRQ mapping enabled (0) or disabled (1) + * bits [6:4] reserved + * bits [3:0] IRQ to map to + * allowed: 3-7, 9-12, 14-15 + * reserved: 0, 1, 2, 8, 13 + * + * individual registers in device config space: + * + * 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case + * + * 0x61: IDEIRQ: bits as in general case - but: + * bits [6:5] must be written 01 + * bit 4 channel-select primary (0), secondary (1) + * + * 0x62: USBIRQ: bits as in general case - but: + * bit 4 OHCI function disabled (0), enabled (1) + * + * 0x6a: ACPI/SCI IRQ - bits as in general case + * + * 0x7e: Data Acq. Module IRQ - bits as in general case + * + * Apparently there are systems implementing PCI routing table using both + * link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets + * like 0x62 as link values for USBIRQ e.g. So there is no simple + * "register = offset + pirq" relation. + * Currently we support PCI INTA..D and USBIRQ and try our best to handle + * both link mappings. + * IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS). + */ + static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { u8 x; - int reg = 0x41 + (pirq - 'A') ; - - pci_read_config_byte(router, reg, &x); + int reg = pirq; + + switch(pirq) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + reg += 0x40; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x62: + pci_read_config_byte(router, reg, &x); + if (reg != 0x62) + break; + if (!(x & 0x40)) + return 0; + break; + case 0x61: + case 0x6a: + case 0x7e: + printk("SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n"); + return 0; + default: + printk("SiS router pirq escape (%d)\n", pirq); + return 0; + } return (x & 0x80) ? 0 : (x & 0x0f); } static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { u8 x; - int reg = 0x41 + (pirq - 'A') ; - - pci_read_config_byte(router, reg, &x); - x = (pirq & 0x20) ? 0 : (irq & 0x0f); + int reg = pirq; + + switch(pirq) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + reg += 0x40; + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x62: + x = (irq&0x0f) ? (irq&0x0f) : 0x80; + if (reg != 0x62) + break; + /* always mark OHCI enabled, as nothing else knows about this */ + x |= 0x40; + break; + case 0x61: + case 0x6a: + case 0x7e: + printk("advanced SiS pirq mapping not yet implemented\n"); + return 0; + default: + printk("SiS router pirq escape (%d)\n", pirq); + return 0; + } pci_write_config_byte(router, reg, x); return 1; @@ -462,18 +547,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) irq = pirq & 0xf; DBG(" -> hardcoded IRQ %d\n", irq); msg = "Hardcoded"; - if (dev->irq && dev->irq != irq) { - printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n"); - return 0; - } } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) { DBG(" -> got IRQ %d\n", irq); msg = "Found"; - /* We refuse to override the dev->irq information. Give a warning! */ - if (dev->irq && dev->irq != irq) { - printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n"); - return 0; - } } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { DBG(" -> assigning IRQ %d", newirq); if (r->set(pirq_router_dev, dev, pirq, newirq)) { @@ -504,6 +580,11 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) if (!info) continue; if (info->irq[pin].link == pirq) { + /* We refuse to override the dev->irq information. Give a warning! */ + if (dev2->irq && dev2->irq != irq) { + printk("IRQ routing conflict in pirq table for device %s\n", dev2->slot_name); + continue; + } dev2->irq = irq; pirq_penalty[irq]++; if (dev != dev2) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 0ea0d89e9b33..2c3f61f7fc36 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1401,9 +1401,6 @@ static void __init init_centaur(struct cpuinfo_x86 *c) wrmsr (0x1107, lo, hi); set_bit(X86_FEATURE_CX8, &c->x86_capability); - rdmsr (0x80000001, lo, hi); - if (hi & (1<<31)) - set_bit(X86_FEATURE_3DNOW, &c->x86_capability); get_model_name(c); display_cacheinfo(c); @@ -1874,7 +1871,8 @@ static int __init id_and_try_enable_cpuid(struct cpuinfo_x86 *c) /* Detect Cyrix with disabled CPUID */ if ( c->x86 == 4 && test_cyrix_52div() ) { strcpy(c->x86_vendor_id, "CyrixInstead"); - } + c->x86_vendor = X86_VENDOR_CYRIX; + } else /* Detect NexGen with old hypercode */ if ( deep_magic_nexgen_probe() ) { diff --git a/arch/sh/boot/compressed/head.S b/arch/sh/boot/compressed/head.S index 75d8b4ef9581..0edf490851c4 100644 --- a/arch/sh/boot/compressed/head.S +++ b/arch/sh/boot/compressed/head.S @@ -43,7 +43,7 @@ bss_start_addr: end_addr: .long _end init_sr: - .long 0x40000000 /* Privileged mode, Bank=0, Block=0, I3-I0=0 */ + .long 0x400000F0 /* Privileged mode, Bank=0, Block=0, IMASK=0xF */ init_stack_addr: .long stack_start decompress_kernel_addr: diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index 37d29a6c40ad..f2756f72c81d 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -36,23 +36,23 @@ * NOTE: This code uses a convention that instructions in the delay slot * of a transfer-control instruction are indented by an extra space, thus: * - * jmp @$k0 ! control-transfer instruction - * ldc $k1, $ssr ! delay slot + * jmp @k0 ! control-transfer instruction + * ldc k1, ssr ! delay slot * * Stack layout in 'ret_from_syscall': * ptrace needs to have all regs on the stack. * if the order here is changed, it needs to be * updated in ptrace.c and ptrace.h * - * $r0 + * r0 * ... - * $r15 = stack pointer - * $spc - * $pr - * $ssr - * $gbr - * $mach - * $macl + * r15 = stack pointer + * spc + * pr + * ssr + * gbr + * mach + * macl * syscall # * */ @@ -88,16 +88,16 @@ MMU_TEA = 0xff00000c ! TLB Exception Address Register #endif /* Offsets to the stack */ -R0 = 0 /* Return value. New ABI also arg4 */ -R1 = 4 /* New ABI: arg5 */ -R2 = 8 /* New ABI: arg6 */ -R3 = 12 /* New ABI: syscall_nr */ -R4 = 16 /* New ABI: arg0 */ -R5 = 20 /* New ABI: arg1 */ -R6 = 24 /* New ABI: arg2 */ -R7 = 28 /* New ABI: arg3 */ -SP = (15*4) -SR = (16*4+8) +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_SR = (16*4+8) SYSCALL_NR = (16*4+6*4) @@ -140,117 +140,139 @@ SYSCALL_NR = (16*4+6*4) ! #define STI() \ - mov.l __INV_IMASK, $r11; \ - stc $sr, $r10; \ - and $r11, $r10; \ - stc $k_g_imask, $r11; \ - or $r11, $r10; \ - ldc $r10, $sr + mov.l __INV_IMASK, r11; \ + stc sr, r10; \ + and r11, r10; \ + stc k_g_imask, r11; \ + or r11, r10; \ + ldc r10, sr .align 2 tlb_miss_load: bra call_dpf - mov #0, $r5 + mov #0, r5 .align 2 tlb_miss_store: bra call_dpf - mov #1, $r5 + mov #1, r5 .align 2 initial_page_write: bra call_dpf - mov #1, $r5 + mov #1, r5 .align 2 tlb_protection_violation_load: bra call_dpf - mov #0, $r5 + mov #0, r5 .align 2 tlb_protection_violation_store: bra call_dpf - mov #1, $r5 + mov #1, r5 call_dpf: - mov.l 1f, $r0 - mov $r5, $r8 - mov.l @$r0, $r6 - mov $r6, $r9 - mov.l 2f, $r0 - sts $pr, $r10 - jsr @$r0 - mov $r15, $r4 + mov.l 1f, r0 + mov r5, r8 + mov.l @r0, r6 + mov r6, r9 + mov.l 2f, r0 + sts pr, r10 + jsr @r0 + mov r15, r4 ! - tst #0xff, $r0 + tst #0xff, r0 bf/s 0f - lds $r10, $pr + lds r10, pr rts nop 0: STI() - mov.l 3f, $r0 - mov $r9, $r6 - mov $r8, $r5 - jmp @$r0 - mov $r15, $r4 + mov.l 3f, r0 + mov r9, r6 + mov r8, r5 + jmp @r0 + mov r15, r4 .align 2 1: .long MMU_TEA 2: .long SYMBOL_NAME(__do_page_fault) 3: .long SYMBOL_NAME(do_page_fault) + .align 2 +address_error_load: + bra call_dae + mov #0,r5 ! writeaccess = 0 + + .align 2 +address_error_store: + bra call_dae + mov #1,r5 ! writeaccess = 1 + +call_dae: + mov.l 1f, r0 + mov.l @r0, r6 ! address + mov.l 2f, r0 + jmp @r0 + mov r15, r4 ! regs + + .align 2 +1: .long MMU_TEA +2: .long SYMBOL_NAME(do_address_error) + #if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) .align 2 /* Unwind the stack and jmp to the debug entry */ debug_kernel: - mov.l @$r15+, $r0 - mov.l @$r15+, $r1 - mov.l @$r15+, $r2 - mov.l @$r15+, $r3 - mov.l @$r15+, $r4 - mov.l @$r15+, $r5 - mov.l @$r15+, $r6 - mov.l @$r15+, $r7 - stc $sr, $r8 - mov.l 1f, $r9 ! BL =1, RB=1, IMASK=0x0F - or $r9, $r8 - ldc $r8, $sr ! here, change the register bank - mov.l @$r15+, $r8 - mov.l @$r15+, $r9 - mov.l @$r15+, $r10 - mov.l @$r15+, $r11 - mov.l @$r15+, $r12 - mov.l @$r15+, $r13 - mov.l @$r15+, $r14 - mov.l @$r15+, $k0 - ldc.l @$r15+, $spc - lds.l @$r15+, $pr - mov.l @$r15+, $k1 - ldc.l @$r15+, $gbr - lds.l @$r15+, $mach - lds.l @$r15+, $macl - mov $k0, $r15 + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + stc sr, r8 + mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F + or r9, r8 + ldc r8, sr ! here, change the register bank + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + mov.l @r15+, k0 + ldc.l @r15+, spc + lds.l @r15+, pr + mov.l @r15+, k1 + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + mov k0, r15 ! - mov.l 2f, $k0 - jmp @$k0 - ldc $k1, $ssr + mov.l 2f, k0 + mov.l @k0, k0 + jmp @k0 + ldc k1, ssr .align 2 1: .long 0x300000f0 -2: .long CONFIG_GDB_STUB_VBR + 0x100 +2: .long SYMBOL_NAME(gdb_vbr_vector) #endif .align 2 debug_trap: #if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) - mov #SR, $r0 - mov.l @($r0,$r15), $r0 ! get status register - shll $r0 - shll $r0 ! kernel space? + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? bt/s debug_kernel #endif - mov.l @$r15, $r0 - mov.l 1f, $r8 - jmp @$r8 + mov.l @r15, r0 + mov.l 1f, r8 + jmp @r8 nop .align 2 @@ -260,8 +282,8 @@ debug_trap: error: ! STI() - mov.l 1f, $r0 - jmp @$r0 + mov.l 1f, r0 + jmp @r0 nop .align 2 1: .long SYMBOL_NAME(do_exception_error) @@ -272,7 +294,7 @@ error: ! ENTRY(ret_from_fork) bra SYMBOL_NAME(ret_from_syscall) - add #4, $r15 ! pop down bogus r0 (see switch_to MACRO) + add #4, r15 ! pop down bogus r0 (see switch_to MACRO) /* * Old syscall interface: @@ -305,90 +327,90 @@ ENTRY(ret_from_fork) */ system_call: - mov.l __TRA, $r9 - mov.l @$r9, $r8 + mov.l __TRA, r9 + mov.l @r9, r8 ! ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x20, $r9 - extu.b $r9, $r9 - shll2 $r9 - cmp/hs $r9, $r8 + mov #0x20, r9 + extu.b r9, r9 + shll2 r9 + cmp/hs r9, r8 bt debug_trap ! - mov #SYSCALL_NR, $r14 - add $r15, $r14 + mov #SYSCALL_NR, r14 + add r15, r14 ! #ifdef COMPAT_OLD_SYSCALL_ABI - mov #0x40, $r9 - cmp/hs $r9, $r8 + mov #0x40, r9 + cmp/hs r9, r8 bf/s old_abi_system_call nop #endif ! New Syscall ABI - add #-0x40, $r8 - shlr2 $r8 - shll8 $r8 - shll8 $r8 ! $r8 = num_args<<16 - mov $r3, $r10 - or $r8, $r10 ! Encode syscall # and # of arguments - mov.l $r10, @$r14 ! set syscall_nr + add #-0x40, r8 + shlr2 r8 + shll8 r8 + shll8 r8 ! r8 = num_args<<16 + mov r3, r10 + or r8, r10 ! Encode syscall # and # of arguments + mov.l r10, @r14 ! set syscall_nr STI() ! - stc $k_current, $r11 - mov.l @(tsk_ptrace,$r11), $r10 ! Is current PTRACE_SYSCALL'd? - mov #PT_TRACESYS, $r11 - tst $r11, $r10 + stc k_current, r11 + mov.l @(tsk_ptrace,r11), r10 ! Is current PTRACE_SYSCALL'd? + mov #PT_TRACESYS, r11 + tst r11, r10 bt 5f ! Yes it is traced. - mov.l __syscall_trace, $r11 ! Call syscall_trace() which notifies - jsr @$r11 ! superior (will chomp $R[0-7]) + mov.l __syscall_trace, r11 ! Call syscall_trace() which notifies + jsr @r11 ! superior (will chomp R[0-7]) nop - ! Reload $R0-$R4 from kernel stack, where the + ! Reload R0-R4 from kernel stack, where the ! parent may have modified them using - ! ptrace(POKEUSR). (Note that $R0-$R2 are + ! ptrace(POKEUSR). (Note that R0-R2 are ! used by the system call handler directly ! from the kernel stack anyway, so don't need ! to be reloaded here.) This allows the parent ! to rewrite system calls and args on the fly. - mov.l @(R4,$r15), $r4 ! arg0 - mov.l @(R5,$r15), $r5 - mov.l @(R6,$r15), $r6 - mov.l @(R7,$r15), $r7 ! arg3 - mov.l @(R3,$r15), $r3 ! syscall_nr + mov.l @(OFF_R4,r15), r4 ! arg0 + mov.l @(OFF_R5,r15), r5 + mov.l @(OFF_R6,r15), r6 + mov.l @(OFF_R7,r15), r7 ! arg3 + mov.l @(OFF_R3,r15), r3 ! syscall_nr ! Arrange for syscall_trace() to be called ! again as the system call returns. - mov.l __syscall_ret_trace, $r10 + mov.l __syscall_ret_trace, r10 bra 6f - lds $r10, $pr + lds r10, pr ! No it isn't traced. ! Arrange for normal system call return. -5: mov.l __syscall_ret, $r10 - lds $r10, $pr +5: mov.l __syscall_ret, r10 + lds r10, pr ! Call the system call handler through the table. ! (both normal and ptrace'd) ! First check for bad syscall number -6: mov $r3, $r9 - mov.l __n_sys, $r10 - cmp/hs $r10, $r9 +6: mov r3, r9 + mov.l __n_sys, r10 + cmp/hs r10, r9 bf 2f ! Bad syscall number rts ! go to syscall_ret or syscall_ret_trace - mov #-ENOSYS, $r0 + mov #-ENOSYS, r0 ! Good syscall number -2: shll2 $r9 ! x4 - mov.l __sct, $r11 - add $r11, $r9 - mov.l @$r9, $r11 - jmp @$r11 ! jump to specific syscall handler +2: shll2 r9 ! x4 + mov.l __sct, r11 + add r11, r9 + mov.l @r9, r11 + jmp @r11 ! jump to specific syscall handler nop ! In case of trace syscall_ret_trace: - mov.l $r0, @(R0,$r15) ! save the return value - mov.l __syscall_trace, $r1 - mova SYMBOL_NAME(ret_from_syscall), $r0 - jmp @$r1 ! Call syscall_trace() which notifies superior - lds $r0, $pr ! Then return to ret_from_syscall() + mov.l r0, @(OFF_R0,r15) ! save the return value + mov.l __syscall_trace, r1 + mova SYMBOL_NAME(ret_from_syscall), r0 + jmp @r1 ! Call syscall_trace() which notifies superior + lds r0, pr ! Then return to ret_from_syscall() @@ -396,41 +418,41 @@ syscall_ret_trace: ! Handle old ABI system call. ! Note that ptrace(SYSCALL) is not supported for the old ABI. ! At this point: -! $r0, $r4-7 as per ABI -! $r8 = value of TRA register (= num_args<<2) -! $r14 = points to SYSCALL_NR in stack frame +! r0, r4-7 as per ABI +! r8 = value of TRA register (= num_args<<2) +! r14 = points to SYSCALL_NR in stack frame old_abi_system_call: - mov $r0, $r9 ! Save system call number in $r9 + mov r0, r9 ! Save system call number in r9 ! ! arrange for return which pops stack - mov.l __old_abi_syscall_ret, $r10 - lds $r10, $pr + mov.l __old_abi_syscall_ret, r10 + lds r10, pr ! Build the stack frame if TRA > 0 - mov $r8, $r10 - cmp/pl $r10 + mov r8, r10 + cmp/pl r10 bf 0f - mov.l @(SP,$r15), $r0 ! get original user stack -7: add #-4, $r10 -4: mov.l @($r0,$r10), $r1 ! May cause address error exception.. - mov.l $r1, @-$r15 - cmp/pl $r10 + mov.l @(OFF_SP,r15), r0 ! get original user stack +7: add #-4, r10 +4: mov.l @(r0,r10), r1 ! May cause address error exception.. + mov.l r1, @-r15 + cmp/pl r10 bt 7b 0: - mov.l $r9, @$r14 ! set syscall_nr + mov.l r9, @r14 ! set syscall_nr STI() ! Call the system call handler through the table. ! First check for bad syscall number - mov.l __n_sys, $r10 - cmp/hs $r10, $r9 + mov.l __n_sys, r10 + cmp/hs r10, r9 bf 2f ! Bad syscall number rts ! return to old_abi_syscall_ret - mov #-ENOSYS, $r0 + mov #-ENOSYS, r0 ! Good syscall number -2: shll2 $r9 ! x4 - mov.l __sct, $r11 - add $r11, $r9 - mov.l @$r9, $r11 - jmp @$r11 ! call specific syscall handler, +2: shll2 r9 ! x4 + mov.l __sct, r11 + add r11, r9 + mov.l @r9, r11 + jmp @r11 ! call specific syscall handler, nop .align 2 @@ -440,16 +462,16 @@ __old_abi_syscall_ret: ! This code gets called on address error exception when copying ! syscall arguments from user stack to kernel stack. It is ! supposed to return -EINVAL through old_abi_syscall_ret, but it - ! appears to have been broken for a long time in that the $r0 - ! return value will be saved into the kernel stack relative to $r15 - ! but the value of $r15 is not correct partway through the loop. - ! So the user prog is returned its old $r0 value, not -EINVAL. + ! appears to have been broken for a long time in that the r0 + ! return value will be saved into the kernel stack relative to r15 + ! but the value of r15 is not correct partway through the loop. + ! So the user prog is returned its old r0 value, not -EINVAL. ! Greg Banks 28 Aug 2000. .section .fixup,"ax" fixup_syscall_argerr: - ! First get $r15 back to + ! First get r15 back to rts - mov #-EINVAL, $r0 + mov #-EINVAL, r0 .previous .section __ex_table, "a" @@ -473,18 +495,18 @@ __syscall_ret: .align 2 reschedule: - mova SYMBOL_NAME(ret_from_syscall), $r0 - mov.l 1f, $r1 - jmp @$r1 - lds $r0, $pr + mova SYMBOL_NAME(ret_from_syscall), r0 + mov.l 1f, r1 + jmp @r1 + lds r0, pr .align 2 1: .long SYMBOL_NAME(schedule) ENTRY(ret_from_irq) - mov #SR, $r0 - mov.l @($r0,$r15), $r0 ! get status register - shll $r0 - shll $r0 ! kernel space? + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon ! STI() @@ -492,10 +514,10 @@ ENTRY(ret_from_irq) nop ENTRY(ret_from_exception) - mov #SR, $r0 - mov.l @($r0,$r15), $r0 ! get status register - shll $r0 - shll $r0 ! kernel space? + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon ! STI() @@ -508,38 +530,38 @@ __INV_IMASK: .align 2 #ifdef COMPAT_OLD_SYSCALL_ABI old_abi_syscall_ret: - add $r8, $r15 ! pop off the arguments + add r8, r15 ! pop off the arguments /* fall through */ #endif syscall_ret: - mov.l $r0, @(R0,$r15) ! save the return value + mov.l r0, @(OFF_R0,r15) ! save the return value /* fall through */ ENTRY(ret_from_syscall) - mov.l __irq_stat, $r0 ! softirq_active - mov.l @$r0, $r1 - mov.l @(4,$r0), $r2 ! softirq_mask - tst $r2, $r1 + mov.l __irq_stat, r0 ! softirq_active + mov.l @r0, r1 + mov.l @(4,r0), r2 ! softirq_mask + tst r2, r1 bt ret_with_reschedule handle_softirq: - mov.l __do_softirq, $r0 - jsr @$r0 + mov.l __do_softirq, r0 + jsr @r0 nop ret_with_reschedule: - stc $k_current, $r1 - mov.l @(need_resched,$r1), $r0 - tst #0xff, $r0 + stc k_current, r1 + mov.l @(need_resched,r1), r0 + tst #0xff, r0 bf reschedule - mov.l @(sigpending,$r1), $r0 - tst #0xff, $r0 + mov.l @(sigpending,r1), r0 + tst #0xff, r0 bt restore_all signal_return: - mov $r15, $r4 - mov #0, $r5 - mov.l __do_signal, $r1 - mova restore_all, $r0 - jmp @$r1 - lds $r0, $pr + mov r15, r4 + mov #0, r5 + mov.l __do_signal, r1 + mova restore_all, r0 + jmp @r1 + lds r0, pr .align 2 __do_signal: .long SYMBOL_NAME(do_signal) @@ -551,108 +573,108 @@ __do_softirq: .align 2 restore_all: #if defined(__SH4__) - mov.l __fpu_prepare_fd, $r0 - jsr @$r0 - stc $sr, $r4 + mov.l __fpu_prepare_fd, r0 + jsr @r0 + stc sr, r4 #endif ! - mov.l @$r15+, $r0 - mov.l @$r15+, $r1 - mov.l @$r15+, $r2 - mov.l @$r15+, $r3 - mov.l @$r15+, $r4 - mov.l @$r15+, $r5 - mov.l @$r15+, $r6 - mov.l @$r15+, $r7 + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 ! - stc $sr, $r8 - mov.l __blrb_flags, $r9 ! BL =1, RB=1 - or $r9, $r8 - ldc $r8, $sr ! here, change the register bank + stc sr, r8 + mov.l __blrb_flags, r9 ! BL =1, RB=1 + or r9, r8 + ldc r8, sr ! here, change the register bank ! - mov.l @$r15+, $r8 - mov.l @$r15+, $r9 - mov.l @$r15+, $r10 - mov.l @$r15+, $r11 - mov.l @$r15+, $r12 - mov.l @$r15+, $r13 - mov.l @$r15+, $r14 - mov.l @$r15+, $k4 ! original stack pointer - ldc.l @$r15+, $spc - lds.l @$r15+, $pr - mov.l @$r15+, $k3 ! original SR - ldc.l @$r15+, $gbr - lds.l @$r15+, $mach - lds.l @$r15+, $macl - add #4, $r15 ! Skip syscall number + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + mov.l @r15+, k4 ! original stack pointer + ldc.l @r15+, spc + lds.l @r15+, pr + mov.l @r15+, k3 ! original SR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + add #4, r15 ! Skip syscall number ! ! Calculate new SR value - mov $k3, $k2 ! original SR value - mov.l 1f, $k1 - stc $sr, $k0 - and $k1, $k0 ! Get current FD-bit - mov.l 2f, $k1 - and $k1, $k2 ! Mask orignal SR value - or $k0, $k2 ! Inherit current FD-bit + mov k3, k2 ! original SR value + mov.l 1f, k1 + stc sr, k0 + and k1, k0 ! Get current FD-bit + mov.l 2f, k1 + and k1, k2 ! Mask orignal SR value + or k0, k2 ! Inherit current FD-bit ! - mov $k3, $k0 ! Calculate IMASK-bits - shlr2 $k0 - and #0x3c, $k0 - cmp/eq #0x3c, $k0 + mov k3, k0 ! Calculate IMASK-bits + shlr2 k0 + and #0x3c, k0 + cmp/eq #0x3c, k0 bt/s 7f - shll2 $k0 - mov $g_imask, $k0 + shll2 k0 + mov g_imask, k0 ! -7: or $k0, $k2 ! Set the IMASK-bits - ldc $k2, $ssr +7: or k0, k2 ! Set the IMASK-bits + ldc k2, ssr ! #if defined(__SH4__) - shll $k2 - shll $k2 + shll k2 + shll k2 bf 9f ! user mode /* Kernel to kernel transition */ - mov.l 1f, $k1 - tst $k1, $k3 + mov.l 1f, k1 + tst k1, k3 bf 9f ! it hadn't FPU ! Kernel to kernel and FPU was used ! There's the case we don't get FPU now - stc $sr, $k2 - tst $k1, $k2 + stc sr, k2 + tst k1, k2 bt 8f ! We need to grab FPU here - xor $k1, $k2 - ldc $k2, $sr ! Grab FPU - mov.l __init_task_flags, $k1 - mov.l @$k1, $k2 - mov.l __PF_USEDFPU, $k0 - or $k0, $k2 - mov.l $k2, @$k1 ! Set init_task.flags |= PF_USEDFPU + xor k1, k2 + ldc k2, sr ! Grab FPU + mov.l __init_task_flags, k1 + mov.l @k1, k2 + mov.l __PF_USEDFPU, k0 + or k0, k2 + mov.l k2, @k1 ! Set init_task.flags |= PF_USEDFPU ! ! Restoring FPU... ! -8: mov.l 3f, $k1 - lds $k1, $fpscr - fmov.s @$r15+, $fr0 - fmov.s @$r15+, $fr1 - fmov.s @$r15+, $fr2 - fmov.s @$r15+, $fr3 - fmov.s @$r15+, $fr4 - fmov.s @$r15+, $fr5 - fmov.s @$r15+, $fr6 - fmov.s @$r15+, $fr7 - fmov.s @$r15+, $fr8 - fmov.s @$r15+, $fr9 - fmov.s @$r15+, $fr10 - fmov.s @$r15+, $fr11 - fmov.s @$r15+, $fr12 - fmov.s @$r15+, $fr13 - fmov.s @$r15+, $fr14 - fmov.s @$r15+, $fr15 - lds.l @$r15+, $fpscr - lds.l @$r15+, $fpul +8: mov.l 3f, k1 + lds k1, fpscr + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul 9: #endif - mov $k4, $r15 + mov k4, r15 rte nop @@ -680,10 +702,10 @@ ENTRY(vbr_base) ! .balign 256,0,256 general_exception: - mov.l 1f, $k2 - mov.l 2f, $k3 + mov.l 1f, k2 + mov.l 2f, k3 bra handle_exception - mov.l @$k2, $k2 + mov.l @k2, k2 .align 2 2: .long SYMBOL_NAME(ret_from_exception) 1: .long EXPEVT @@ -691,17 +713,17 @@ general_exception: ! .balign 1024,0,1024 tlb_miss: - mov.l 1f, $k2 - mov.l 4f, $k3 + mov.l 1f, k2 + mov.l 4f, k3 bra handle_exception - mov.l @$k2, $k2 + mov.l @k2, k2 ! .balign 512,0,512 interrupt: - mov.l 2f, $k2 - mov.l 3f, $k3 + mov.l 2f, k2 + mov.l 3f, k3 bra handle_exception - mov.l @$k2, $k2 + mov.l @k2, k2 .align 2 1: .long EXPEVT @@ -715,102 +737,102 @@ handle_exception: ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. ! - stc $ssr, $k0 ! from kernel space? - shll $k0 ! Check MD bit (bit30) by shifting it into the T bit - shll $k0 + stc ssr, k0 ! from kernel space? + shll k0 ! Check MD bit (bit30) by shifting it into the T bit + shll k0 #if defined(__SH4__) bf/s 8f ! it's from user to kernel transition - mov $r15, $k0 ! save original stack to k0 + mov r15, k0 ! save original stack to k0 /* It's a kernel to kernel transition. */ /* Is the FPU disabled? */ - mov.l 2f, $k1 - stc $ssr, $k0 - tst $k1, $k0 - mov.l 4f, $k1 + mov.l 2f, k1 + stc ssr, k0 + tst k1, k0 + mov.l 4f, k1 bf/s 9f ! FPU is not enabled, no need to save it - mov $r15, $k0 ! save original stack to k0 + mov r15, k0 ! save original stack to k0 ! FPU is enabled, save it ! /* XXX: Need to save another bank of FPU if all FPU feature is used */ ! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */ - sts.l $fpul, @-$r15 - sts.l $fpscr, @-$r15 - mov.l 6f, $k1 - lds $k1, $fpscr - mov.l 3f, $k1 - fmov.s $fr15, @-$r15 - fmov.s $fr14, @-$r15 - fmov.s $fr13, @-$r15 - fmov.s $fr12, @-$r15 - fmov.s $fr11, @-$r15 - fmov.s $fr10, @-$r15 - fmov.s $fr9, @-$r15 - fmov.s $fr8, @-$r15 - fmov.s $fr7, @-$r15 - fmov.s $fr6, @-$r15 - fmov.s $fr5, @-$r15 - fmov.s $fr4, @-$r15 - fmov.s $fr3, @-$r15 - fmov.s $fr2, @-$r15 - fmov.s $fr1, @-$r15 + sts.l fpul, @-r15 + sts.l fpscr, @-r15 + mov.l 6f, k1 + lds k1, fpscr + mov.l 3f, k1 + fmov.s fr15, @-r15 + fmov.s fr14, @-r15 + fmov.s fr13, @-r15 + fmov.s fr12, @-r15 + fmov.s fr11, @-r15 + fmov.s fr10, @-r15 + fmov.s fr9, @-r15 + fmov.s fr8, @-r15 + fmov.s fr7, @-r15 + fmov.s fr6, @-r15 + fmov.s fr5, @-r15 + fmov.s fr4, @-r15 + fmov.s fr3, @-r15 + fmov.s fr2, @-r15 + fmov.s fr1, @-r15 bra 9f - fmov.s $fr0, @-$r15 + fmov.s fr0, @-r15 #else - mov.l 3f, $k1 + mov.l 3f, k1 bt/s 9f ! it's a kernel to kernel transition, and skip the FPU save. - mov $r15, $k0 ! save original stack to k0 anyway + mov r15, k0 ! save original stack to k0 anyway #endif 8: /* User space to kernel */ - mov #0x20, $k1 - shll8 $k1 ! $k1 <= 8192 == THREAD_SIZE - add $current, $k1 - mov $k1, $r15 ! change to kernel stack + mov #0x20, k1 + shll8 k1 ! k1 <= 8192 == THREAD_SIZE + add current, k1 + mov k1, r15 ! change to kernel stack ! - mov.l 4f, $k1 ! let kernel release FPU + mov.l 4f, k1 ! let kernel release FPU 9: ! Save the user registers on the stack. ! At this point, k1 should have been set to the new SR value - mov #-1, $k4 - mov.l $k4, @-$r15 ! syscall_nr (default: -1) + mov #-1, k4 + mov.l k4, @-r15 ! syscall_nr (default: -1) ! - sts.l $macl, @-$r15 - sts.l $mach, @-$r15 - stc.l $gbr, @-$r15 - stc.l $ssr, @-$r15 - sts.l $pr, @-$r15 - stc.l $spc, @-$r15 + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + stc.l ssr, @-r15 + sts.l pr, @-r15 + stc.l spc, @-r15 ! - lds $k3, $pr ! Set the return address to pr + lds k3, pr ! Set the return address to pr ! - mov.l $k0, @-$r15 ! save orignal stack - mov.l $r14, @-$r15 - mov.l $r13, @-$r15 - mov.l $r12, @-$r15 - mov.l $r11, @-$r15 - mov.l $r10, @-$r15 - mov.l $r9, @-$r15 - mov.l $r8, @-$r15 + mov.l k0, @-r15 ! save orignal stack + mov.l r14, @-r15 + mov.l r13, @-r15 + mov.l r12, @-r15 + mov.l r11, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 ! - stc $sr, $r8 ! Back to normal register bank, and - or $k1, $r8 ! Block all interrupts, may release FPU - mov.l 5f, $k1 - and $k1, $r8 ! ... - ldc $r8, $sr ! ...changed here. + stc sr, r8 ! Back to normal register bank, and + or k1, r8 ! Block all interrupts, may release FPU + mov.l 5f, k1 + and k1, r8 ! ... + ldc r8, sr ! ...changed here. ! - mov.l $r7, @-$r15 - mov.l $r6, @-$r15 - mov.l $r5, @-$r15 - mov.l $r4, @-$r15 - mov.l $r3, @-$r15 - mov.l $r2, @-$r15 - mov.l $r1, @-$r15 - mov.l $r0, @-$r15 + mov.l r7, @-r15 + mov.l r6, @-r15 + mov.l r5, @-r15 + mov.l r4, @-r15 + mov.l r3, @-r15 + mov.l r2, @-r15 + mov.l r1, @-r15 + mov.l r0, @-r15 ! Then, dispatch to the handler, according to the exception code. - stc $k_ex_code, $r8 - shlr2 $r8 - shlr $r8 - mov.l 1f, $r9 - add $r8, $r9 - mov.l @$r9, $r9 - jmp @$r9 + stc k_ex_code, r8 + shlr2 r8 + shlr r8 + mov.l 1f, r9 + add r8, r9 + mov.l @r9, r9 + jmp @r9 nop .align 2 1: .long SYMBOL_NAME(exception_handling_table) @@ -833,8 +855,8 @@ ENTRY(exception_handling_table) .long initial_page_write .long tlb_protection_violation_load .long tlb_protection_violation_store - .long error ! address_error_load (filled by trap_init) - .long error ! address_error_store (filled by trap_init) + .long address_error_load + .long address_error_store #if defined(__SH4__) .long SYMBOL_NAME(do_fpu_error) #else diff --git a/arch/sh/kernel/fpu.c b/arch/sh/kernel/fpu.c index cbeb60d31186..9036b20c015c 100644 --- a/arch/sh/kernel/fpu.c +++ b/arch/sh/kernel/fpu.c @@ -21,43 +21,43 @@ void save_fpu(struct task_struct *tsk) { - asm volatile("sts.l $fpul, @-%0\n\t" - "sts.l $fpscr, @-%0\n\t" - "lds %1, $fpscr\n\t" + asm volatile("sts.l fpul, @-%0\n\t" + "sts.l fpscr, @-%0\n\t" + "lds %1, fpscr\n\t" "frchg\n\t" - "fmov.s $fr15, @-%0\n\t" - "fmov.s $fr14, @-%0\n\t" - "fmov.s $fr13, @-%0\n\t" - "fmov.s $fr12, @-%0\n\t" - "fmov.s $fr11, @-%0\n\t" - "fmov.s $fr10, @-%0\n\t" - "fmov.s $fr9, @-%0\n\t" - "fmov.s $fr8, @-%0\n\t" - "fmov.s $fr7, @-%0\n\t" - "fmov.s $fr6, @-%0\n\t" - "fmov.s $fr5, @-%0\n\t" - "fmov.s $fr4, @-%0\n\t" - "fmov.s $fr3, @-%0\n\t" - "fmov.s $fr2, @-%0\n\t" - "fmov.s $fr1, @-%0\n\t" - "fmov.s $fr0, @-%0\n\t" + "fmov.s fr15, @-%0\n\t" + "fmov.s fr14, @-%0\n\t" + "fmov.s fr13, @-%0\n\t" + "fmov.s fr12, @-%0\n\t" + "fmov.s fr11, @-%0\n\t" + "fmov.s fr10, @-%0\n\t" + "fmov.s fr9, @-%0\n\t" + "fmov.s fr8, @-%0\n\t" + "fmov.s fr7, @-%0\n\t" + "fmov.s fr6, @-%0\n\t" + "fmov.s fr5, @-%0\n\t" + "fmov.s fr4, @-%0\n\t" + "fmov.s fr3, @-%0\n\t" + "fmov.s fr2, @-%0\n\t" + "fmov.s fr1, @-%0\n\t" + "fmov.s fr0, @-%0\n\t" "frchg\n\t" - "fmov.s $fr15, @-%0\n\t" - "fmov.s $fr14, @-%0\n\t" - "fmov.s $fr13, @-%0\n\t" - "fmov.s $fr12, @-%0\n\t" - "fmov.s $fr11, @-%0\n\t" - "fmov.s $fr10, @-%0\n\t" - "fmov.s $fr9, @-%0\n\t" - "fmov.s $fr8, @-%0\n\t" - "fmov.s $fr7, @-%0\n\t" - "fmov.s $fr6, @-%0\n\t" - "fmov.s $fr5, @-%0\n\t" - "fmov.s $fr4, @-%0\n\t" - "fmov.s $fr3, @-%0\n\t" - "fmov.s $fr2, @-%0\n\t" - "fmov.s $fr1, @-%0\n\t" - "fmov.s $fr0, @-%0" + "fmov.s fr15, @-%0\n\t" + "fmov.s fr14, @-%0\n\t" + "fmov.s fr13, @-%0\n\t" + "fmov.s fr12, @-%0\n\t" + "fmov.s fr11, @-%0\n\t" + "fmov.s fr10, @-%0\n\t" + "fmov.s fr9, @-%0\n\t" + "fmov.s fr8, @-%0\n\t" + "fmov.s fr7, @-%0\n\t" + "fmov.s fr6, @-%0\n\t" + "fmov.s fr5, @-%0\n\t" + "fmov.s fr4, @-%0\n\t" + "fmov.s fr3, @-%0\n\t" + "fmov.s fr2, @-%0\n\t" + "fmov.s fr1, @-%0\n\t" + "fmov.s fr0, @-%0" : /* no output */ : "r" ((char *)(&tsk->thread.fpu.hard.status)), "r" (FPSCR_INIT) @@ -70,43 +70,43 @@ save_fpu(struct task_struct *tsk) static void restore_fpu(struct task_struct *tsk) { - asm volatile("lds %1, $fpscr\n\t" - "fmov.s @%0+, $fr0\n\t" - "fmov.s @%0+, $fr1\n\t" - "fmov.s @%0+, $fr2\n\t" - "fmov.s @%0+, $fr3\n\t" - "fmov.s @%0+, $fr4\n\t" - "fmov.s @%0+, $fr5\n\t" - "fmov.s @%0+, $fr6\n\t" - "fmov.s @%0+, $fr7\n\t" - "fmov.s @%0+, $fr8\n\t" - "fmov.s @%0+, $fr9\n\t" - "fmov.s @%0+, $fr10\n\t" - "fmov.s @%0+, $fr11\n\t" - "fmov.s @%0+, $fr12\n\t" - "fmov.s @%0+, $fr13\n\t" - "fmov.s @%0+, $fr14\n\t" - "fmov.s @%0+, $fr15\n\t" + asm volatile("lds %1, fpscr\n\t" + "fmov.s @%0+, fr0\n\t" + "fmov.s @%0+, fr1\n\t" + "fmov.s @%0+, fr2\n\t" + "fmov.s @%0+, fr3\n\t" + "fmov.s @%0+, fr4\n\t" + "fmov.s @%0+, fr5\n\t" + "fmov.s @%0+, fr6\n\t" + "fmov.s @%0+, fr7\n\t" + "fmov.s @%0+, fr8\n\t" + "fmov.s @%0+, fr9\n\t" + "fmov.s @%0+, fr10\n\t" + "fmov.s @%0+, fr11\n\t" + "fmov.s @%0+, fr12\n\t" + "fmov.s @%0+, fr13\n\t" + "fmov.s @%0+, fr14\n\t" + "fmov.s @%0+, fr15\n\t" "frchg\n\t" - "fmov.s @%0+, $fr0\n\t" - "fmov.s @%0+, $fr1\n\t" - "fmov.s @%0+, $fr2\n\t" - "fmov.s @%0+, $fr3\n\t" - "fmov.s @%0+, $fr4\n\t" - "fmov.s @%0+, $fr5\n\t" - "fmov.s @%0+, $fr6\n\t" - "fmov.s @%0+, $fr7\n\t" - "fmov.s @%0+, $fr8\n\t" - "fmov.s @%0+, $fr9\n\t" - "fmov.s @%0+, $fr10\n\t" - "fmov.s @%0+, $fr11\n\t" - "fmov.s @%0+, $fr12\n\t" - "fmov.s @%0+, $fr13\n\t" - "fmov.s @%0+, $fr14\n\t" - "fmov.s @%0+, $fr15\n\t" + "fmov.s @%0+, fr0\n\t" + "fmov.s @%0+, fr1\n\t" + "fmov.s @%0+, fr2\n\t" + "fmov.s @%0+, fr3\n\t" + "fmov.s @%0+, fr4\n\t" + "fmov.s @%0+, fr5\n\t" + "fmov.s @%0+, fr6\n\t" + "fmov.s @%0+, fr7\n\t" + "fmov.s @%0+, fr8\n\t" + "fmov.s @%0+, fr9\n\t" + "fmov.s @%0+, fr10\n\t" + "fmov.s @%0+, fr11\n\t" + "fmov.s @%0+, fr12\n\t" + "fmov.s @%0+, fr13\n\t" + "fmov.s @%0+, fr14\n\t" + "fmov.s @%0+, fr15\n\t" "frchg\n\t" - "lds.l @%0+, $fpscr\n\t" - "lds.l @%0+, $fpul\n\t" + "lds.l @%0+, fpscr\n\t" + "lds.l @%0+, fpul\n\t" : /* no output */ : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT) : "memory"); @@ -120,41 +120,41 @@ restore_fpu(struct task_struct *tsk) void fpu_init(void) { - asm volatile("lds %0, $fpul\n\t" - "lds %1, $fpscr\n\t" - "fsts $fpul, $fr0\n\t" - "fsts $fpul, $fr1\n\t" - "fsts $fpul, $fr2\n\t" - "fsts $fpul, $fr3\n\t" - "fsts $fpul, $fr4\n\t" - "fsts $fpul, $fr5\n\t" - "fsts $fpul, $fr6\n\t" - "fsts $fpul, $fr7\n\t" - "fsts $fpul, $fr8\n\t" - "fsts $fpul, $fr9\n\t" - "fsts $fpul, $fr10\n\t" - "fsts $fpul, $fr11\n\t" - "fsts $fpul, $fr12\n\t" - "fsts $fpul, $fr13\n\t" - "fsts $fpul, $fr14\n\t" - "fsts $fpul, $fr15\n\t" + asm volatile("lds %0, fpul\n\t" + "lds %1, fpscr\n\t" + "fsts fpul, fr0\n\t" + "fsts fpul, fr1\n\t" + "fsts fpul, fr2\n\t" + "fsts fpul, fr3\n\t" + "fsts fpul, fr4\n\t" + "fsts fpul, fr5\n\t" + "fsts fpul, fr6\n\t" + "fsts fpul, fr7\n\t" + "fsts fpul, fr8\n\t" + "fsts fpul, fr9\n\t" + "fsts fpul, fr10\n\t" + "fsts fpul, fr11\n\t" + "fsts fpul, fr12\n\t" + "fsts fpul, fr13\n\t" + "fsts fpul, fr14\n\t" + "fsts fpul, fr15\n\t" "frchg\n\t" - "fsts $fpul, $fr0\n\t" - "fsts $fpul, $fr1\n\t" - "fsts $fpul, $fr2\n\t" - "fsts $fpul, $fr3\n\t" - "fsts $fpul, $fr4\n\t" - "fsts $fpul, $fr5\n\t" - "fsts $fpul, $fr6\n\t" - "fsts $fpul, $fr7\n\t" - "fsts $fpul, $fr8\n\t" - "fsts $fpul, $fr9\n\t" - "fsts $fpul, $fr10\n\t" - "fsts $fpul, $fr11\n\t" - "fsts $fpul, $fr12\n\t" - "fsts $fpul, $fr13\n\t" - "fsts $fpul, $fr14\n\t" - "fsts $fpul, $fr15\n\t" + "fsts fpul, fr0\n\t" + "fsts fpul, fr1\n\t" + "fsts fpul, fr2\n\t" + "fsts fpul, fr3\n\t" + "fsts fpul, fr4\n\t" + "fsts fpul, fr5\n\t" + "fsts fpul, fr6\n\t" + "fsts fpul, fr7\n\t" + "fsts fpul, fr8\n\t" + "fsts fpul, fr9\n\t" + "fsts fpul, fr10\n\t" + "fsts fpul, fr11\n\t" + "fsts fpul, fr12\n\t" + "fsts fpul, fr13\n\t" + "fsts fpul, fr14\n\t" + "fsts fpul, fr15\n\t" "frchg" : /* no output */ : "r" (0), "r" (FPSCR_INIT)); @@ -192,9 +192,9 @@ do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, * * There's race condition in __cli: * - * (1) $SR --> register + * (1) SR --> register * (2) Set IMASK of register - * (3) $SR <-- register + * (3) SR <-- register * * Between (1) and (2), or (2) and (3) getting * interrupt, and interrupt handler (or diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f1ac6fd17b07..73c13dc7d917 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -37,40 +37,40 @@ ENTRY(empty_zero_page) */ ENTRY(_stext) ! Initialize Status Register - mov.l 1f, $r0 ! MD=1, RB=0, BL=0, IMASK=0xF - ldc $r0, $sr + mov.l 1f, r0 ! MD=1, RB=0, BL=0, IMASK=0xF + ldc r0, sr ! Initialize global interrupt mask - mov #0, $r0 - ldc $r0, $r6_bank + mov #0, r0 + ldc r0, r6_bank ! - mov.l 2f, $r0 - mov $r0, $r15 ! Set initial r15 (stack pointer) - mov #0x20, $r1 ! - shll8 $r1 ! $r1 = 8192 - sub $r1, $r0 ! - ldc $r0, $r7_bank ! ... and init_task + mov.l 2f, r0 + mov r0, r15 ! Set initial r15 (stack pointer) + mov #0x20, r1 ! + shll8 r1 ! r1 = 8192 + sub r1, r0 ! + ldc r0, r7_bank ! ... and init_task ! #if defined(__SH4__) ! Initialize fpu - mov.l 7f, $r0 - jsr @$r0 + mov.l 7f, r0 + jsr @r0 nop #endif ! Enable cache - mov.l 6f, $r0 - jsr @$r0 + mov.l 6f, r0 + jsr @r0 nop ! Clear BSS area - mov.l 3f, $r1 - add #4, $r1 - mov.l 4f, $r2 - mov #0, $r0 -9: cmp/hs $r2, $r1 + mov.l 3f, r1 + add #4, r1 + mov.l 4f, r2 + mov #0, r0 +9: cmp/hs r2, r1 bf/s 9b ! while (r1 < r2) - mov.l $r0,@-$r2 + mov.l r0,@-r2 ! Start kernel - mov.l 5f, $r0 - jmp @$r0 + mov.l 5f, r0 + jmp @r0 nop .balign 4 diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 6451c4c9effe..200148320965 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -235,7 +235,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned int status; /* Get IRQ number */ - asm volatile("stc $r2_bank, %0\n\t" + asm volatile("stc r2_bank, %0\n\t" "shlr2 %0\n\t" "shlr2 %0\n\t" "shlr %0\n\t" diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c index 27d91b372c8f..d0b3aea9fe10 100644 --- a/arch/sh/kernel/irq_imask.c +++ b/arch/sh/kernel/irq_imask.c @@ -59,16 +59,16 @@ void static inline set_interrupt_registers(int ip) { unsigned long __dummy; - asm volatile("ldc %2, $r6_bank\n\t" - "stc $sr, %0\n\t" + asm volatile("ldc %2, r6_bank\n\t" + "stc sr, %0\n\t" "and #0xf0, %0\n\t" "shlr2 %0\n\t" "cmp/eq #0x3c, %0\n\t" "bt/s 1f ! CLI-ed\n\t" - " stc $sr, %0\n\t" + " stc sr, %0\n\t" "and %1, %0\n\t" "or %2, %0\n\t" - "ldc %0, $sr\n" + "ldc %0, sr\n" "1:" : "=&z" (__dummy) : "r" (~0xf0), "r" (ip << 4) diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index c7511093bef6..1ce22f0fd3f7 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -14,6 +14,8 @@ #define __KERNEL_SYSCALLS__ #include +#include + #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include #include @@ -39,8 +42,9 @@ #include #include #include - -#include +#ifdef CONFIG_SH_STANDARD_BIOS +#include +#endif static int hlt_counter=0; @@ -79,11 +83,17 @@ void cpu_idle(void *unused) } void machine_restart(char * __unused) -{ /* Need to set MMU_TTB?? */ +{ +#ifdef CONFIG_SH_STANDARD_BIOS + sh_bios_shutdown(1); +#endif } void machine_halt(void) { +#ifdef CONFIG_SH_STANDARD_BIOS + sh_bios_shutdown(0); +#endif } void machine_power_off(void) @@ -93,7 +103,7 @@ void machine_power_off(void) void show_regs(struct pt_regs * regs) { printk("\n"); - printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08lx\n", + printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08x\n", regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA)); printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", regs->regs[0],regs->regs[1], @@ -144,12 +154,12 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) register unsigned long __sc9 __asm__ ("r9") = (long) fn; __asm__("trapa #0x12\n\t" /* Linux/SH system call */ - "tst #0xff, $r0\n\t" /* child or parent? */ + "tst #0xff, r0\n\t" /* child or parent? */ "bf 1f\n\t" /* parent - jump */ - "jsr @$r9\n\t" /* call fn */ - " mov $r8, $r4\n\t" /* push argument */ - "mov $r0, $r4\n\t" /* return value to arg of exit */ - "mov %1, $r3\n\t" /* exit */ + "jsr @r9\n\t" /* call fn */ + " mov r8, r4\n\t" /* push argument */ + "mov r0, r4\n\t" /* return value to arg of exit */ + "mov %1, r3\n\t" /* exit */ "trapa #0x11\n" "1:" : "=z" (__sc0) @@ -285,7 +295,7 @@ void __switch_to(struct task_struct *prev, struct task_struct *next) * Restore the kernel mode register * k7 (r7_bank1) */ - asm volatile("ldc %0, $r7_bank" + asm volatile("ldc %0, r7_bank" : /* no output */ :"r" (next)); } @@ -376,7 +386,7 @@ unsigned long get_wchan(struct task_struct *p) asmlinkage void print_syscall(int x) { unsigned long flags, sr; - asm("stc $sr, %0": "=r" (sr)); + asm("stc sr, %0": "=r" (sr)); save_and_cli(flags); printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32, (current->flags&PF_USEDFPU)?'C':' ', diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 8dad245df35e..b6fb1e9a8c90 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -503,8 +503,8 @@ int get_cpuinfo(char *buffer) "cache size\t: 8K-byte/16K-byte\n"); #endif p += sprintf(p, "bogomips\t: %lu.%02lu\n\n", - (loops_per_jiffy+2500)/(500000/HZ), - ((loops_per_jiffy+2500)/(5000/HZ)) % 100); + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); p += sprintf(p, "Machine: %s\n", sh_mv.mv_name); #define PRINT_CLOCK(name, value) \ diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index 81a56b960ace..f72f71b988db 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -1,4 +1,4 @@ -/* $Id: sh_bios.c,v 1.3 2000/09/30 03:43:30 gniibe Exp $ +/* $Id: sh_bios.c,v 1.5 2001/01/08 08:42:32 gniibe Exp $ * * linux/arch/sh/kernel/sh_bios.c * C interface for trapping into the standard LinuxSH BIOS. @@ -7,13 +7,12 @@ * */ -#include #include -#ifdef CONFIG_SH_STANDARD_BIOS - #define BIOS_CALL_CONSOLE_WRITE 0 -#define BIOS_CALL_READ_BLOCK 1 /* not implemented */ +#define BIOS_CALL_READ_BLOCK 1 +#define BIOS_CALL_ETH_NODE_ADDR 10 +#define BIOS_CALL_SHUTDOWN 11 #define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ #define BIOS_CALL_GDB_GET_MODE_PTR 0xfe #define BIOS_CALL_GDB_DETACH 0xff @@ -66,5 +65,12 @@ void sh_bios_gdb_detach(void) sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); } -#endif +void sh_bios_get_node_addr (unsigned char *node_addr) +{ + sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); +} +void sh_bios_shutdown(unsigned int how) +{ + sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); +} diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 2b0298699bb4..2bdcd75ea8cb 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -64,10 +64,11 @@ EXPORT_SYMBOL(get_vm_area); #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name) /* These symbols are generated by the compiler itself */ +DECLARE_EXPORT(__udivsi3); +DECLARE_EXPORT(__sdivsi3); + #ifdef __SH4__ -DECLARE_EXPORT(__udivsi3_i4); -DECLARE_EXPORT(__sdivsi3_i4); DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__ashrdi3); diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 1e3cb5277c04..9095c5c791fc 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -431,7 +431,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, current->comm, current->pid, frame, regs->pc, regs->pr); #endif - flush_icache_range(regs->pr, regs->pr+4); + flush_cache_sigtramp(regs->pr); return; give_sigsegv: @@ -505,7 +505,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->pc, regs->pr); #endif - flush_icache_range(regs->pr, regs->pr+4); + flush_cache_sigtramp(regs->pr); return; give_sigsegv: diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 4aeaf8efa0c7..a13d26dab8bf 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -2,7 +2,9 @@ * * linux/arch/sh/traps.c * - * SuperH version: Copyright (C) 1999 Niibe Yutaka + * SuperH version: Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2000 David Howells */ /* @@ -35,7 +37,7 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ { \ unsigned long error_code; \ \ - asm volatile("stc $r2_bank, %0": "=r" (error_code)); \ + asm volatile("stc r2_bank, %0": "=r" (error_code)); \ sti(); \ tsk->thread.error_code = error_code; \ tsk->thread.trap_no = trapnr; \ @@ -69,7 +71,16 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e die(str, regs, err); } -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) +static int handle_unaligned_notify_count = 10; + +/* + * try and fix up kernelspace address errors + * - userspace errors just cause EFAULT to be returned, resulting in SEGV + * - kernel/userspace interfaces cause a jump to an appropriate handler + * - other kernel errors are bad + * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault + */ +static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) { if (!user_mode(regs)) { @@ -77,14 +88,407 @@ static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) fixup = search_exception_table(regs->pc); if (fixup) { regs->pc = fixup; - return; + return 0; } die(str, regs, err); } + return -EFAULT; +} + +/* + * handle an instruction that does an unaligned memory access by emulating the + * desired behaviour + * - note that PC _may not_ point to the faulting instruction + * (if that instruction is in a branch delay slot) + * - return 0 if emulation okay, -EFAULT on existential error + */ +static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) +{ + int ret, index, count; + unsigned long *rm, *rn; + unsigned char *src, *dst; + + index = (instruction>>8)&15; /* 0x0F00 */ + rn = ®s->regs[index]; + + index = (instruction>>4)&15; /* 0x00F0 */ + rm = ®s->regs[index]; + + count = 1<<(instruction&3); + + ret = -EFAULT; + switch (instruction>>12) { + case 0: /* mov.[bwl] to/from memory via r0+rn */ + if (instruction & 8) { + /* from memory */ + src = (unsigned char*) *rm; + src += regs->regs[0]; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + +#ifdef __LITTLE_ENDIAN__ + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + dst += 4-count; + + if (__copy_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + } else { + /* to memory */ + src = (unsigned char*) rm; +#if !defined(__LITTLE_ENDIAN__) + src += 4-count; +#endif + dst = (unsigned char*) *rn; + dst += regs->regs[0]; + + if (copy_to_user(dst, src, count)) + goto fetch_fault; + } + ret = 0; + break; + + case 1: /* mov.l Rm,@(disp,Rn) */ + src = (unsigned char*) rm; + dst = (unsigned char*) *rn; + dst += (instruction&0x000F)<<2; + + if (copy_to_user(dst,src,4)) + goto fetch_fault; + ret = 0; + break; + + case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ + if (instruction & 4) + *rn -= count; + src = (unsigned char*) rm; + dst = (unsigned char*) *rn; +#if !defined(__LITTLE_ENDIAN__) + src += 4-count; +#endif + if (copy_to_user(dst, src, count)) + goto fetch_fault; + ret = 0; + break; + + case 5: /* mov.l @(disp,Rm),Rn */ + src = (unsigned char*) *rm; + src += (instruction&0x000F)<<2; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + + if (copy_from_user(dst,src,4)) + goto fetch_fault; + ret = 0; + break; + + case 6: /* mov.[bwl] from memory, possibly with post-increment */ + src = (unsigned char*) *rm; + if (instruction & 4) + *rm += count; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + +#ifdef __LITTLE_ENDIAN__ + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + dst += 4-count; + + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + ret = 0; + break; + + case 8: + switch ((instruction&0xFF00)>>8) { + case 0x81: /* mov.w R0,@(disp,Rn) */ + src = (unsigned char*) ®s->regs[0]; +#if !defined(__LITTLE_ENDIAN__) + src += 2; +#endif + dst = (unsigned char*) *rm; /* called Rn in the spec */ + dst += (instruction&0x000F)<<1; + + if (copy_to_user(dst, src, 2)) + goto fetch_fault; + ret = 0; + break; + + case 0x85: /* mov.w @(disp,Rm),R0 */ + src = (unsigned char*) *rm; + src += (instruction&0x000F)<<1; + dst = (unsigned char*) ®s->regs[0]; + *(unsigned long*)dst = 0; + +#if !defined(__LITTLE_ENDIAN__) + dst += 2; +#endif + + if (copy_from_user(dst, src, 2)) + goto fetch_fault; + +#ifdef __LITTLE_ENDIAN__ + if (dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + if (dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + ret = 0; + break; + } + break; + } + return ret; + + fetch_fault: + /* Argh. Address not only misaligned but also non-existent. + * Raise an EFAULT and see if it's trapped + */ + return die_if_no_fixup("Fault in unaligned fixup", regs, 0); +} + +/* + * emulate the instruction in the delay slot + * - fetches the instruction from PC+2 + */ +static inline int handle_unaligned_delayslot(struct pt_regs *regs) +{ + u16 instruction; + + if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) { + /* the instruction-fetch faulted */ + if (user_mode(regs)) + return -EFAULT; + + /* kernel */ + die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); + } + + return handle_unaligned_ins(instruction,regs); +} + +/* + * handle an instruction that does an unaligned memory access + * - have to be careful of branch delay-slot instructions that fault + * - if the branch would be taken PC points to the branch + * - if the branch would not be taken, PC points to delay-slot + * - return 0 if handled, -EFAULT if failed (may not return if in kernel) + */ +static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) +{ + u_int rm; + int ret, index; + + index = (instruction>>8)&15; /* 0x0F00 */ + rm = regs->regs[index]; + + /* shout about the first ten userspace fixups */ + if (user_mode(regs) && handle_unaligned_notify_count>0) { + handle_unaligned_notify_count--; + + printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + current->comm,current->pid,(u16*)regs->pc,instruction); + } + + ret = -EFAULT; + switch (instruction&0xF000) { + case 0x0000: + if (instruction==0x000B) { + /* rts */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc = regs->pr; + } + else if ((instruction&0x00FF)==0x0023) { + /* braf @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += rm + 4; + } + else if ((instruction&0x00FF)==0x0003) { + /* bsrf @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc += rm + 4; + } + } + else { + /* mov.[bwl] to/from memory via r0+rn */ + goto simple; + } + break; + + case 0x1000: /* mov.l Rm,@(disp,Rn) */ + goto simple; + + case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */ + goto simple; + + case 0x4000: + if ((instruction&0x00FF)==0x002B) { + /* jmp @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc = rm; + } + else if ((instruction&0x00FF)==0x000B) { + /* jsr @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc = rm; + } + } + else { + /* mov.[bwl] to/from memory via r0+rn */ + goto simple; + } + break; + + case 0x5000: /* mov.l @(disp,Rm),Rn */ + goto simple; + + case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */ + goto simple; + + case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */ + switch (instruction&0x0F00) { + case 0x0100: /* mov.w R0,@(disp,Rm) */ + goto simple; + case 0x0500: /* mov.w @(disp,Rm),R0 */ + goto simple; + case 0x0B00: /* bf lab - no delayslot*/ + break; + case 0x0F00: /* bf/s lab */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += (instruction&0x00FF)*2 + 4; + break; + case 0x0900: /* bt lab - no delayslot */ + break; + case 0x0D00: /* bt/s lab */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += (instruction&0x00FF)*2 + 4; + break; + } + break; + + case 0xA000: /* bra label */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += (instruction&0x0FFF)*2 + 4; + break; + + case 0xB000: /* bsr label */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc += (instruction&0x0FFF)*2 + 4; + } + break; + } + return ret; + + /* handle non-delay-slot instruction */ + simple: + ret = handle_unaligned_ins(instruction,regs); + if (ret==0) + regs->pc += 2; + return ret; +} + +/* + * Handle various address error exceptions + */ +asmlinkage void do_address_error(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) +{ + unsigned long error_code; + mm_segment_t oldfs; + u16 instruction; + int tmp; + + asm volatile("stc r2_bank,%0": "=r" (error_code)); + + oldfs = get_fs(); + + if (user_mode(regs)) { + sti(); + current->thread.error_code = error_code; + current->thread.trap_no = (writeaccess) ? 8 : 7; + + /* bad PC is not something we can fix */ + if (regs->pc & 1) + goto uspace_segv; + + set_fs(USER_DS); + if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { + /* Argh. Fault on the instruction itself. + This should never happen non-SMP + */ + set_fs(oldfs); + goto uspace_segv; + } + + tmp = handle_unaligned_access(instruction, regs); + set_fs(oldfs); + + if (tmp==0) + return; /* sorted */ + + uspace_segv: + printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); + force_sig(SIGSEGV, current); + } else { + if (regs->pc & 1) + die("unaligned program counter", regs, error_code); + + set_fs(KERNEL_DS); + if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { + /* Argh. Fault on the instruction itself. + This should never happen non-SMP + */ + set_fs(oldfs); + die("insn faulting in do_address_error", regs, 0); + } + + handle_unaligned_access(instruction, regs); + set_fs(oldfs); + } } -DO_ERROR( 7, SIGSEGV, "address error (load)", address_error_load, current) -DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current) DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) @@ -93,25 +497,42 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, struct pt_regs regs) { long ex; - asm volatile("stc $r2_bank, %0" : "=r" (ex)); + asm volatile("stc r2_bank, %0" : "=r" (ex)); die_if_kernel("exception", ®s, ex); } +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) +void *gdb_vbr_vector; +#endif + void __init trap_init(void) { extern void *vbr_base; extern void *exception_handling_table[14]; - exception_handling_table[7] = (void *)do_address_error_load; - exception_handling_table[8] = (void *)do_address_error_store; exception_handling_table[12] = (void *)do_reserved_inst; exception_handling_table[13] = (void *)do_illegal_slot_inst; +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) + /* + * Read the old value of the VBR register to initialise + * the vector through which debug and BIOS traps are + * delegated by the Linux trap handler. + */ + { + register unsigned long vbr; + asm volatile("stc vbr, %0" : "=r" (vbr)); + gdb_vbr_vector = (void *)(vbr + 0x100); + printk("Setting GDB trap vector to 0x%08lx\n", + (unsigned long)gdb_vbr_vector); + } +#endif + /* NOTE: The VBR value should be at P1 (or P2, virtural "fixed" address space). It's definitely should not in physical address. */ - asm volatile("ldc %0, $vbr" + asm volatile("ldc %0, vbr" : /* no output */ : "r" (&vbr_base) : "memory"); @@ -123,8 +544,8 @@ void dump_stack(void) unsigned long *end; unsigned long *p; - asm("mov $r15, %0" : "=r" (start)); - asm("stc $r7_bank, %0" : "=r" (end)); + asm("mov r15, %0" : "=r" (start)); + asm("stc r7_bank, %0" : "=r" (end)); end += 8192/4; printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end); diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S index c7e96a394fae..9d8e0f47627c 100644 --- a/arch/sh/lib/checksum.S +++ b/arch/sh/lib/checksum.S @@ -49,99 +49,99 @@ ENTRY(csum_partial) * Fortunately, it is easy to convert 2-byte alignment to 4-byte * alignment for the unrolled loop. */ - mov $r5, $r1 - mov $r4, $r0 - tst #2, $r0 ! Check alignment. + mov r5, r1 + mov r4, r0 + tst #2, r0 ! Check alignment. bt 2f ! Jump if alignment is ok. ! - add #-2, $r5 ! Alignment uses up two bytes. - cmp/pz $r5 ! + add #-2, r5 ! Alignment uses up two bytes. + cmp/pz r5 ! bt/s 1f ! Jump if we had at least two bytes. clrt bra 6f - add #2, $r5 ! $r5 was < 2. Deal with it. + add #2, r5 ! r5 was < 2. Deal with it. 1: - mov.w @$r4+, $r0 - extu.w $r0, $r0 - addc $r0, $r6 + mov.w @r4+, r0 + extu.w r0, r0 + addc r0, r6 bf 2f - add #1, $r6 + add #1, r6 2: - mov #-5, $r0 - shld $r0, $r5 - tst $r5, $r5 + mov #-5, r0 + shld r0, r5 + tst r5, r5 bt/s 4f ! if it's =0, go to 4f clrt .align 2 3: - mov.l @$r4+, $r0 - mov.l @$r4+, $r2 - mov.l @$r4+, $r3 - addc $r0, $r6 - mov.l @$r4+, $r0 - addc $r2, $r6 - mov.l @$r4+, $r2 - addc $r3, $r6 - mov.l @$r4+, $r3 - addc $r0, $r6 - mov.l @$r4+, $r0 - addc $r2, $r6 - mov.l @$r4+, $r2 - addc $r3, $r6 - addc $r0, $r6 - addc $r2, $r6 - movt $r0 - dt $r5 + mov.l @r4+, r0 + mov.l @r4+, r2 + mov.l @r4+, r3 + addc r0, r6 + mov.l @r4+, r0 + addc r2, r6 + mov.l @r4+, r2 + addc r3, r6 + mov.l @r4+, r3 + addc r0, r6 + mov.l @r4+, r0 + addc r2, r6 + mov.l @r4+, r2 + addc r3, r6 + addc r0, r6 + addc r2, r6 + movt r0 + dt r5 bf/s 3b - cmp/eq #1, $r0 - ! here, we know $r5==0 - addc $r5, $r6 ! add carry to $r6 + cmp/eq #1, r0 + ! here, we know r5==0 + addc r5, r6 ! add carry to r6 4: - mov $r1, $r0 - and #0x1c, $r0 - tst $r0, $r0 + mov r1, r0 + and #0x1c, r0 + tst r0, r0 bt/s 6f - mov $r0, $r5 - shlr2 $r5 - mov #0, $r2 + mov r0, r5 + shlr2 r5 + mov #0, r2 5: - addc $r2, $r6 - mov.l @$r4+, $r2 - movt $r0 - dt $r5 + addc r2, r6 + mov.l @r4+, r2 + movt r0 + dt r5 bf/s 5b - cmp/eq #1, $r0 - addc $r2, $r6 - addc $r5, $r6 ! $r5==0 here, so it means add carry-bit + cmp/eq #1, r0 + addc r2, r6 + addc r5, r6 ! r5==0 here, so it means add carry-bit 6: - mov $r1, $r5 - mov #3, $r0 - and $r0, $r5 - tst $r5, $r5 + mov r1, r5 + mov #3, r0 + and r0, r5 + tst r5, r5 bt 9f ! if it's =0 go to 9f - mov #2, $r1 - cmp/hs $r1, $r5 + mov #2, r1 + cmp/hs r1, r5 bf 7f - mov.w @r4+, $r0 - extu.w $r0, $r0 - cmp/eq $r1, $r5 + mov.w @r4+, r0 + extu.w r0, r0 + cmp/eq r1, r5 bt/s 8f clrt - shll16 $r0 - addc $r0, $r6 + shll16 r0 + addc r0, r6 7: - mov.b @$r4+, $r0 - extu.b $r0, $r0 + mov.b @r4+, r0 + extu.b r0, r0 #ifndef __LITTLE_ENDIAN__ - shll8 $r0 + shll8 r0 #endif 8: - addc $r0, $r6 - mov #0, $r0 - addc $r0, $r6 + addc r0, r6 + mov #0, r0 + addc r0, r6 9: rts - mov $r6, $r0 + mov r6, r0 /* unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, @@ -159,14 +159,14 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, * them all but there's no guarantee. */ -#define SRC(x,y) \ - 9999: x,y; \ +#define SRC(...) \ + 9999: __VA_ARGS__ ; \ .section __ex_table, "a"; \ .long 9999b, 6001f ; \ .previous -#define DST(x,y) \ - 9999: x,y; \ +#define DST(...) \ + 9999: __VA_ARGS__ ; \ .section __ex_table, "a"; \ .long 9999b, 6002f ; \ .previous @@ -202,7 +202,7 @@ ENTRY(csum_partial_copy_generic) bt/s 1f clrt bra 4f - add #2,r6 ! $r6 was < 2. Deal with it. + add #2,r6 ! r6 was < 2. Deal with it. 3: ! Handle different src and dest alinments. ! This is not common, so simple byte by byte copy will do. @@ -211,7 +211,8 @@ ENTRY(csum_partial_copy_generic) tst r6, r6 bt 4f clrt -SRC(5: mov.b @r4+,r0 ) +5: +SRC( mov.b @r4+,r0 ) DST( mov.b r0,@r5 ) add #1, r5 SRC( mov.b @r4+,r1 ) @@ -244,7 +245,8 @@ DST( mov.b r1,@r5 ) ! src and dest equally aligned, but to a two byte boundary. ! Handle first two bytes as a special case .align 5 -SRC(1: mov.w @r4+,r0 ) +1: +SRC( mov.w @r4+,r0 ) DST( mov.w r0,@r5 ) add #2,r5 extu.w r0,r0 @@ -258,7 +260,8 @@ DST( mov.w r0,@r5 ) tst r6,r6 bt/s 2f clrt -SRC(1: mov.l @r4+,r0 ) +1: +SRC( mov.l @r4+,r0 ) SRC( mov.l @r4+,r1 ) addc r0,r7 DST( mov.l r0,@r5 ) @@ -276,7 +279,7 @@ DST( mov.l r0,@r5 ) DST( mov.l r1,@r5 ) add #4,r5 -SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r0 ) SRC( mov.l @r4+,r1 ) addc r0,r7 DST( mov.l r0,@r5 ) @@ -307,7 +310,8 @@ DST( mov.l r1,@r5 ) bf/s 4f clrt shlr2 r6 -SRC(3: mov.l @r4+,r0 ) +3: +SRC( mov.l @r4+,r0 ) addc r0,r7 DST( mov.l r0,@r5 ) add #4,r5 @@ -334,7 +338,8 @@ DST( mov.w r0,@r5 ) clrt shll16 r0 addc r0,r7 -SRC(5: mov.b @r4+,r0 ) +5: +SRC( mov.b @r4+,r0 ) DST( mov.b r0,@r5 ) extu.b r0,r0 #ifndef __LITTLE_ENDIAN__ diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c index 790fd180847c..e1fcc970f0e2 100644 --- a/arch/sh/lib/delay.c +++ b/arch/sh/lib/delay.c @@ -21,7 +21,11 @@ void __delay(unsigned long loops) inline void __const_udelay(unsigned long xloops) { - xloops *= current_cpu_data.loops_per_jiffy; + __asm__("dmulu.l %0, %2\n\t" + "sts mach, %0" + : "=r" (xloops) + : "0" (xloops), "r" (current_cpu_data.loops_per_jiffy) + : "macl", "mach"); __delay(xloops * HZ); } diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index ab63535e4dcc..2ea37e723e25 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -243,6 +243,22 @@ void flush_icache_range(unsigned long start, unsigned long end) restore_flags(flags); } +/* + * Write back the D-cache and purge the I-cache for signal trampoline. + */ +void flush_cache_sigtramp(unsigned long addr) +{ + unsigned long v, index; + + v = addr & ~(L1_CACHE_BYTES-1); + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + + index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK); + ctrl_outl(0, index); /* Clear out Valid-bit */ +} + /* * Invalidate the I-cache of the page (don't need to write back D-cache). * diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 70bbda891868..47fcf6226033 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.168 2001/01/01 01:46:15 davem Exp $ +/* $Id: entry.S,v 1.169 2001/01/25 21:47:20 davem Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -999,6 +999,7 @@ C_LABEL(invalid_segment_patch1): ld [%l4 + 0x18], %l3 inc %l3 ! sun4c_kernel_ring.num_entries++ + st %l3, [%l4 + 0x18] b 4f ld [%l6 + 0x08], %l5 diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index c777356b3a63..d80f93cf6155 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -416,6 +416,8 @@ CONFIG_DRM_FFB=m # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set CONFIG_AFFS_FS=m diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 25f6ecff3306..76045d0d2b27 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -290,8 +290,8 @@ void __init smp_boot_cpus(void) } printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, - (bogosum + 2500)/500000, - ((bogosum + 2500)/5000)%100); + bogosum/(500000/HZ), + (bogosum/(5000/HZ))%100); smp_activated = 1; smp_num_cpus = cpucount + 1; } diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c index 13f4fe0e78fc..8e1774c9a99d 100644 --- a/drivers/acpi/acpi_ksyms.c +++ b/drivers/acpi/acpi_ksyms.c @@ -81,11 +81,3 @@ EXPORT_SYMBOL(acpi_set_current_resources); EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); - -EXPORT_SYMBOL(acpi_get_processor_throttling_info); -EXPORT_SYMBOL(acpi_get_processor_throttling_state); -EXPORT_SYMBOL(acpi_set_processor_throttling_state); - -EXPORT_SYMBOL(acpi_get_processor_cx_info); -EXPORT_SYMBOL(acpi_set_processor_sleep_state); -EXPORT_SYMBOL(acpi_processor_sleep); diff --git a/drivers/acpi/common/cmalloc.c b/drivers/acpi/common/cmalloc.c index 880376433130..d8514698fbec 100644 --- a/drivers/acpi/common/cmalloc.c +++ b/drivers/acpi/common/cmalloc.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: cmalloc - local memory allocation routines - * $Revision: 83 $ + * $Revision: 84 $ * *****************************************************************************/ diff --git a/drivers/acpi/common/cmxface.c b/drivers/acpi/common/cmxface.c index c968fecfa5fa..ce87b50d273d 100644 --- a/drivers/acpi/common/cmxface.c +++ b/drivers/acpi/common/cmxface.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: cmxface - External interfaces for "global" ACPI functions - * $Revision: 58 $ + * $Revision: 62 $ * *****************************************************************************/ @@ -304,16 +304,22 @@ acpi_get_system_info ( out_buffer->length = sizeof (ACPI_SYSTEM_INFO); info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer; - /* TBD [Future]: need a version number, or use the version string */ - info_ptr->acpi_ca_version = 0x1234; + info_ptr->acpi_ca_version = ACPI_CA_VERSION; /* System flags (ACPI capabilities) */ info_ptr->flags = acpi_gbl_system_flags; /* Timer resolution - 24 or 32 bits */ - - info_ptr->timer_resolution = acpi_hw_pmt_resolution (); + if (!acpi_gbl_FADT) { + info_ptr->timer_resolution = 0; + } + else if (acpi_gbl_FADT->tmr_val_ext == 0) { + info_ptr->timer_resolution = 24; + } + else { + info_ptr->timer_resolution = 32; + } /* Clear the reserved fields */ diff --git a/drivers/acpi/cpu.c b/drivers/acpi/cpu.c index 00ec59da5214..3e4adcee2b79 100644 --- a/drivers/acpi/cpu.c +++ b/drivers/acpi/cpu.c @@ -39,6 +39,9 @@ static int acpi_c3_tested = 0; static int acpi_max_c_state = 1; static int acpi_pm_tmr_len; +#define MAX_C2_LATENCY 100 +#define MAX_C3_LATENCY 1000 + /* * Clear busmaster activity flag */ @@ -251,10 +254,7 @@ static ACPI_STATUS acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value) { ACPI_OBJECT obj; - ACPI_CX_STATE lat[4]; - ACPI_CPU_THROTTLING_STATE throttle[ACPI_MAX_THROTTLE]; ACPI_BUFFER buf; - int i, count; buf.length = sizeof(obj); buf.pointer = &obj; @@ -273,41 +273,28 @@ acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value) acpi_pblk = obj.processor.pblk_address; - buf.length = sizeof(lat); - buf.pointer = lat; - if (!ACPI_SUCCESS(acpi_get_processor_cx_info(handle, &buf))) - return AE_OK; + if (acpi_fadt.plvl2_lat + && acpi_fadt.plvl2_lat <= MAX_C2_LATENCY) { + acpi_c2_exit_latency + = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat); + acpi_c2_enter_latency + = ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); + acpi_max_c_state = 2; - if (lat[2].latency < MAX_CX_STATE_LATENCY) { printk(KERN_INFO "ACPI: System firmware supports: C2"); - acpi_c2_exit_latency = lat[2].latency; - acpi_max_c_state = 2; - if (lat[3].latency < MAX_CX_STATE_LATENCY) { - printk(" C3"); - acpi_c3_exit_latency = lat[3].latency; + if (acpi_fadt.plvl3_lat + && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) { + acpi_c3_exit_latency + = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat); + acpi_c3_enter_latency + = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5); acpi_max_c_state = 3; - } - printk("\n"); - } - memset(throttle, 0, sizeof(throttle)); - buf.length = sizeof(throttle); - buf.pointer = throttle; - - if (!ACPI_SUCCESS(acpi_get_processor_throttling_info(handle, &buf))) - return AE_OK; - - for (i = 0, count = 0; i < ACPI_MAX_THROTTLE; i++) { - if (throttle[i].percent_of_clock) - count++; - } - - /* 0% throttled really doesn't count */ - count--; + printk(" C3"); + } - if (count > 0) { - DEBUG_PRINT(ACPI_INFO, ("%d throttling states\n", count)); + printk("\n"); } return AE_OK; diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index 24b7386b4c26..dfaa2a103216 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsmthdat - control method arguments and local variables - * $Revision: 38 $ + * $Revision: 39 $ * ******************************************************************************/ @@ -40,7 +40,7 @@ * * FUNCTION: Acpi_ds_method_data_init * - * PARAMETERS: *Obj_desc + * PARAMETERS: Walk_state - Current walk state object * * RETURN: Status * @@ -97,7 +97,7 @@ acpi_ds_method_data_init ( * * FUNCTION: Acpi_ds_method_data_delete_all * - * PARAMETERS: None + * PARAMETERS: Walk_state - Current walk state object * * RETURN: Status * @@ -153,7 +153,9 @@ acpi_ds_method_data_delete_all ( * * FUNCTION: Acpi_ds_method_data_init_args * - * PARAMETERS: None + * PARAMETERS: *Params - Pointer to a parameter list for the method + * Max_param_count - The arg count for this method + * Walk_state - Current walk state object * * RETURN: Status * @@ -214,6 +216,7 @@ acpi_ds_method_data_init_args ( * Index - Which local_var or argument to get * Entry - Pointer to where a pointer to the stack * entry is returned. + * Walk_state - Current walk state object * * RETURN: Status * @@ -276,6 +279,7 @@ acpi_ds_method_data_get_entry ( * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument to get * Object - Object to be inserted into the stack entry + * Walk_state - Current walk state object * * RETURN: Status * @@ -320,6 +324,7 @@ acpi_ds_method_data_set_entry ( * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument whose type * to get + * Walk_state - Current walk state object * * RETURN: Data type of selected Arg or Local * Used only in Exec_monadic2()/Type_op. @@ -366,6 +371,7 @@ acpi_ds_method_data_get_type ( * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument whose type * to get + * Walk_state - Current walk state object * * RETURN: Get the Node associated with a local or arg. * @@ -418,7 +424,8 @@ acpi_ds_method_data_get_nte ( * * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument to get - * *Dest_desc - Descriptor into which selected Arg + * Walk_state - Current walk state object + * *Dest_desc - Ptr to Descriptor into which selected Arg * or Local value should be copied * * RETURN: Status @@ -474,10 +481,12 @@ acpi_ds_method_data_get_value ( switch (type) { case MTH_TYPE_ARG: + return (AE_AML_UNINITIALIZED_ARG); break; case MTH_TYPE_LOCAL: + return (AE_AML_UNINITIALIZED_LOCAL); break; } @@ -502,6 +511,7 @@ acpi_ds_method_data_get_value ( * * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument to delete + * Walk_state - Current walk state object * * RETURN: Status * @@ -548,7 +558,6 @@ acpi_ds_method_data_delete_value ( * Decrement the reference count by one to balance the * increment when the object was stored in the slot. */ - acpi_cm_remove_reference (object); } @@ -563,18 +572,14 @@ acpi_ds_method_data_delete_value ( * * PARAMETERS: Type - Either MTH_TYPE_LOCAL or MTH_TYPE_ARG * Index - Which local_var or argument to set - * *Src_desc - Value to be stored - * *Dest_desc - Descriptor into which *Src_desc - * can be copied, or NULL if one must - * be allocated for the purpose. If - * provided, this descriptor will be - * used for the new value. + * Src_desc - Value to be stored + * Walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed * as the new value for the Arg or Local and the reference count - * is incremented. + * for Src_desc is incremented. * ******************************************************************************/ @@ -644,7 +649,6 @@ acpi_ds_method_data_set_value ( * Store this object into the Node * (do the indirect store) */ - status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc, src_desc->common.type); return (status); @@ -652,10 +656,18 @@ acpi_ds_method_data_set_value ( /* - * Otherwise, just delete the existing object - * before storing the new one + * Perform "Implicit conversion" of the new object to the type of the + * existing object */ + status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + /* + * Delete the existing object + * before storing the new one + */ acpi_ds_method_data_delete_value (type, index, walk_state); } @@ -666,7 +678,6 @@ acpi_ds_method_data_set_value ( * Install the new object in the stack entry * (increments the object reference count by one) */ - status = acpi_ds_method_data_set_entry (type, index, src_desc, walk_state); if (ACPI_FAILURE (status)) { goto cleanup; diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 6f0a8668c440..a2e1b73d3658 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -2,7 +2,7 @@ * * Module Name: dswexec - Dispatcher method execution callbacks; * dispatch to interpreter. - * $Revision: 54 $ + * $Revision: 55 $ * *****************************************************************************/ @@ -330,6 +330,8 @@ acpi_ds_exec_end_op ( walk_state->num_operands = 0; walk_state->return_desc = NULL; + walk_state->op_info = op_info; + walk_state->opcode = opcode; /* Call debugger for single step support (DEBUG build only) */ diff --git a/drivers/acpi/driver.c b/drivers/acpi/driver.c index 222598120b6c..241528fc6cb9 100644 --- a/drivers/acpi/driver.c +++ b/drivers/acpi/driver.c @@ -55,7 +55,7 @@ struct acpi_run_entry static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; static volatile u32 acpi_event_status = 0; -static volatile acpi_sstate_t acpi_event_state = ACPI_S0; +static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0; static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); static volatile int acpi_thread_pid = -1; @@ -243,7 +243,7 @@ acpi_do_event(ctl_table * ctl, /* * Enter system sleep state */ -static int +/*static int acpi_do_sleep(ctl_table * ctl, int write, struct file *file, @@ -257,13 +257,13 @@ acpi_do_sleep(ctl_table * ctl, } } else { - int status = acpi_enter_sx(ACPI_S1); + int status = acpi_enter_sx(ACPI_STATE_S1); if (status) return status; } file->f_pos += *len; return 0; -} +}*/ /* @@ -382,7 +382,8 @@ static struct ctl_table acpi_table[] = &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency), 0644, NULL, &acpi_do_ulong}, - {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, +/* until it actually works */ +/* {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/ {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, @@ -415,7 +416,9 @@ static struct ctl_table acpi_dir_table[] = static int acpi_thread(void *context) { - ACPI_PHYSICAL_ADDRESS rsdp_phys; + ACPI_PHYSICAL_ADDRESS rsdp_phys; + ACPI_BUFFER buffer; + ACPI_SYSTEM_INFO sys_info; /* * initialize @@ -437,8 +440,6 @@ acpi_thread(void *context) rsdp_phys = efi.acpi; #endif - printk(KERN_ERR "ACPI: System description tables found\n"); - if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys))) return -ENODEV; @@ -448,6 +449,17 @@ acpi_thread(void *context) return -ENODEV; } + buffer.length = sizeof(sys_info); + buffer.pointer = &sys_info; + + if (!ACPI_SUCCESS (acpi_get_system_info(&buffer))) { + printk(KERN_ERR "ACPI: Could not get system info\n"); + acpi_terminate(); + return -ENODEV; + } + + printk(KERN_INFO "ACPI: Core Subsystem version [%x]\n", sys_info.acpi_ca_version); + if (!ACPI_SUCCESS(acpi_enable_subsystem(ACPI_FULL_INITIALIZATION))) { printk(KERN_ERR "ACPI: Subsystem enable failed\n"); acpi_terminate(); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 8bedfac6c59b..5e42683c6ac2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -400,8 +400,6 @@ ec_region_setup ( { FUNCTION_TRACE("acpi_ec_region_setup"); - printk("acpi_ec_region_setup\n"); - if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index 28e25368541c..304d3dec6d3b 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -1,7 +1,8 @@ + /****************************************************************************** * - * Module Name: hwacpi - ACPI hardware functions - mode and timer - * $Revision: 35 $ + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * $Revision: 36 $ * *****************************************************************************/ @@ -304,48 +305,3 @@ acpi_hw_get_mode_capabilities (void) } -/****************************************************************************** - * - * FUNCTION: Acpi_hw_pmt_ticks - * - * PARAMETERS: none - * - * RETURN: Current value of the ACPI PMT (timer) - * - * DESCRIPTION: Obtains current value of ACPI PMT - * - ******************************************************************************/ - -u32 -acpi_hw_pmt_ticks (void) -{ - u32 ticks; - - ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)); - - return (ticks); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_hw_pmt_resolution - * - * PARAMETERS: none - * - * RETURN: Number of bits of resolution in the PMT (either 24 or 32) - * - * DESCRIPTION: Obtains resolution of the ACPI PMT (either 24bit or 32bit) - * - ******************************************************************************/ - -u32 -acpi_hw_pmt_resolution (void) -{ - if (0 == acpi_gbl_FADT->tmr_val_ext) { - return (24); - } - - return (32); -} - diff --git a/drivers/acpi/hardware/hwcpu32.c b/drivers/acpi/hardware/hwcpu32.c deleted file mode 100644 index 380db25e3c62..000000000000 --- a/drivers/acpi/hardware/hwcpu32.c +++ /dev/null @@ -1,709 +0,0 @@ -/****************************************************************************** - * - * Name: hwcpu32.c - CPU support for IA32 (Throttling, Cx_states) - * $Revision: 42 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "acpi.h" -#include "acnamesp.h" -#include "achware.h" - -#define _COMPONENT HARDWARE - MODULE_NAME ("Hwcpu32") - - -#define BIT_4 0x10 /* TBD: [investigate] is this correct? */ - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_enter_c1 - * - * PARAMETERS: Pblk_address - Address of the processor control block - * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep - * - * RETURN: Function status. - * - * DESCRIPTION: Set C1 state on IA32 processor (halt) - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_enter_c1( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks) -{ - u32 timer = 0; - - - if (!pm_timer_ticks) { - /* - * Enter C1: - * --------- - */ - enable(); - halt(); - *pm_timer_ticks = ACPI_UINT32_MAX; - } - else { - timer = acpi_hw_pmt_ticks (); - - /* - * Enter C1: - * --------- - */ - enable (); - halt (); - - /* - * Compute Time in C1: - * ------------------- - */ - timer = acpi_hw_pmt_ticks () - timer; - - *pm_timer_ticks = timer; - } - - return (AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_enter_c2 - * - * PARAMETERS: Pblk_address - Address of the processor control block - * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep - * - * RETURN: - * - * DESCRIPTION: Set C2 state on IA32 processor - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_enter_c2( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks) -{ - u32 timer = 0; - - - if (!pblk_address || !pm_timer_ticks) { - return (AE_BAD_PARAMETER); - } - - /* - * Disable interrupts before all C2/C3 transitions. - */ - disable (); - - timer = acpi_hw_pmt_ticks (); - - /* - * Enter C2: - * --------- - * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition. - */ - acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4)); - - /* - * Perform Dummy Op: - * ----------------- - * We have to do something useless after reading LVL2 because chipsets - * cannot guarantee that STPCLK# gets asserted in time to freeze execution. - */ - acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); - - /* - * Compute Time in C2: - * ------------------- - */ - timer = acpi_hw_pmt_ticks () - timer; - - *pm_timer_ticks = timer; - - /* - * Re-enable interrupts after coming out of C2/C3. - */ - enable (); - - return (AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_enter_c3 - * - * PARAMETERS: Pblk_address - Address of the processor control block - * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep - * - * RETURN: Status of function - * - * DESCRIPTION: Set C3 state on IA32 processor (UP only, cache coherency via - * disabling bus mastering) - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_enter_c3( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks) -{ - u32 timer = 0; - u32 bus_master_status = 0; - - - if (!pblk_address || !pm_timer_ticks) { - return (AE_BAD_PARAMETER); - } - - /* - * Check the BM_STS bit, if it is set, do not enter C3 - * but clear the bit (with a write) and exit, telling - * the calling module that we spent zero time in C3. - * If bus mastering continues, this action should - * eventually cause a demotion to C2 - */ - if (1 == (bus_master_status = - acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, BM_STS))) - { - /* - * Clear the BM_STS bit by setting it. - */ - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1); - *pm_timer_ticks = 0; - return (AE_OK); - } - - /* - * Disable interrupts before all C2/C3 transitions. - */ - disable(); - - /* - * Disable Bus Mastering: - * ---------------------- - * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. - */ - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1); - - /* - * Get the timer base before entering C state - */ - timer = acpi_hw_pmt_ticks (); - - /* - * Enter C3: - * --------- - * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition. - */ - acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5)); - - /* - * Perform Dummy Op: - * ----------------- - * We have to do something useless after reading LVL3 because chipsets - * cannot guarantee that STPCLK# gets asserted in time to freeze execution. - */ - acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); - /* - * Immediately compute the time in the C state - */ - timer = acpi_hw_pmt_ticks() - timer; - - /* - * Re-Enable Bus Mastering: - * ------------------------ - * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. - */ - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0); - - /* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */ - - *pm_timer_ticks = timer; - - /* - * Re-enable interrupts after coming out of C2/C3. - */ - enable(); - - return (AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_enter_cx - * - * PARAMETERS: Processor_handle - handle of the processor - * - * RETURN: Status of function - * - * DESCRIPTION: Invoke the currently active processor Cx handler to put this - * processor to sleep. - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_enter_cx ( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks) -{ - - if (!acpi_hw_cx_handlers[acpi_hw_active_cx_state]) { - return (AE_SUPPORT); - } - - return (acpi_hw_cx_handlers[acpi_hw_active_cx_state] (pblk_address, pm_timer_ticks)); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_set_cx - * - * PARAMETERS: State - value (1-3) of the Cx state to 'make active' - * - * RETURN: Function status. - * - * DESCRIPTION: Sets the state to use during calls to Acpi_hw_enter_cx(). - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_set_cx ( - u32 cx_state) -{ - /* - * Supported State? - * ---------------- - */ - if ((cx_state < 1) || (cx_state > 3)) { - return (AE_BAD_PARAMETER); - } - - if (!acpi_hw_cx_handlers[cx_state]) { - return (AE_SUPPORT); - } - - /* - * New Cx State? - * ------------- - * We only care when moving from one state to another... - */ - if (acpi_hw_active_cx_state == cx_state) { - return (AE_OK); - } - - /* - * Prepare to Use New State: - * ------------------------- - * If the new Cx_state is C3, the BM_RLD bit must be set to allow - * the generation of a bus master requets to cause the processor - * in the C3 state to transition to the C0 state. - */ - switch (cx_state) - { - case 3: - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1); - break; - } - - /* - * Clean up from Old State: - * ------------------------ - * If the old Cx_state was C3, the BM_RLD bit is reset. When the - * bit is reset, the generation of a bus master request does not - * effect any processor in the C3 state. - */ - switch (acpi_hw_active_cx_state) - { - case 3: - acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0); - break; - } - - /* - * Enable: - * ------- - */ - acpi_hw_active_cx_state = cx_state; - - return (AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_get_cx_info - * - * PARAMETERS: Cx_states - Information (latencies) on all Cx states - * - * RETURN: Status of function - * - * DESCRIPTION: This function is called both to initialize Cx handling - * and retrieve the current Cx information (latency values). - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_get_cx_info ( - u32 cx_states[]) -{ - u8 SMP_system = FALSE; - - - if (!cx_states) { - return(AE_BAD_PARAMETER); - } - - /* - * TBD: [Unhandled] need to init SMP_system using info from the MAPIC - * table. - */ - - /* - * Set Defaults: - * ------------- - * C0 and C1 support is implied (but what about that PROC_C1 register - * in the FADT?!?!). Set C2/C3 to max. latency (not supported until - * proven otherwise). - */ - cx_states[0] = 0; - cx_states[1] = 0; - cx_states[2] = MAX_CX_STATE_LATENCY; - cx_states[3] = MAX_CX_STATE_LATENCY; - - /* - * C2 Supported? - * ------------- - * We're only supporting C2 when the latency is <= 100 microseconds, - * and on SMP systems when P_LVL2_UP (which indicates C2 only on UP) - * is not set. - */ - if (acpi_gbl_FADT->plvl2_lat <= 100) { - if (!SMP_system) { - acpi_hw_cx_handlers[2] = acpi_hw_enter_c2; - cx_states[2] = acpi_gbl_FADT->plvl2_lat; - } - - else if (!acpi_gbl_FADT->plvl2_up) { - acpi_hw_cx_handlers[2] = acpi_hw_enter_c2; - cx_states[2] = acpi_gbl_FADT->plvl2_lat; - } - } - - /* - * C3 Supported? - * ------------- - * We're only supporting C3 on UP systems when the latency is - * <= 1000 microseconds and that include the ability to disable - * Bus Mastering while in C3 (ARB_DIS) but allows Bus Mastering - * requests to wake the system from C3 (BM_RLD). Note his method - * of maintaining cache coherency (disabling of bus mastering) - * cannot be used on SMP systems, and flushing caches (e.g. WBINVD) - * is simply too costly (at this time). - */ - if (acpi_gbl_FADT->plvl3_lat <= 1000) { - if (!SMP_system && (acpi_gbl_FADT->Xpm2_cnt_blk.address && - acpi_gbl_FADT->pm2_cnt_len)) - { - acpi_hw_cx_handlers[3] = acpi_hw_enter_c3; - cx_states[3] = acpi_gbl_FADT->plvl3_lat; - } - } - - return(AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_get_cx_handler - * - * PARAMETERS: State - the Cx state - * Handler - pointer to location for the returned handler - * - * RETURN: Status of function - * - * DESCRIPTION: This function is called to get an installed Cx state handler. - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_get_cx_handler ( - u32 cx_state, - ACPI_C_STATE_HANDLER *handler) -{ - - if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) { - return(AE_BAD_PARAMETER); - } - - *handler = acpi_hw_cx_handlers[cx_state]; - - return(AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_hw_set_cx_handler - * - * PARAMETERS: Cx_state - the Cx state - * Handler - new Cx state handler - * - * RETURN: Status of function - * - * DESCRIPTION: This function is called to install a new Cx state handler. - * - ****************************************************************************/ - -ACPI_STATUS -acpi_hw_set_cx_handler ( - u32 cx_state, - ACPI_C_STATE_HANDLER handler) -{ - - if ((cx_state == 0) || (cx_state >= MAX_CX_STATES) || !handler) { - return(AE_BAD_PARAMETER); - } - - acpi_hw_cx_handlers[cx_state] = handler; - - return(AE_OK); -} - - -/************************************************************************** - * - * FUNCTION: Acpi_hw_local_pow - * - * PARAMETERS: x,y operands - * - * RETURN: result - * - * DESCRIPTION: Compute x ^ y - * - *************************************************************************/ - -NATIVE_UINT -acpi_hw_local_pow ( - NATIVE_UINT x, - NATIVE_UINT y) -{ - NATIVE_UINT i; - NATIVE_UINT result = 1; - - - for (i = 0; i < y; i++) { - result = result * x; - } - - return (result); -} - - -/************************************************************************** - * - * FUNCTION: Acpi_hw_enable_throttling - * - * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control) - * register - * - * RETURN: none - * - * DESCRIPTION: Enable throttling by setting the THT_EN bit. - * - *************************************************************************/ - -void -acpi_hw_enable_throttling ( - ACPI_IO_ADDRESS pblk_address) -{ - u32 pblk_value; - - - pblk_value = acpi_os_in32 (pblk_address); - pblk_value = pblk_value | BIT_4; - acpi_os_out32 (pblk_address, pblk_value); - - return; -} - - -/************************************************************************** - * - * FUNCTION: Acpi_hw_disable_throttling - * - * PARAMETERS: Pblk_address - Address of Pcnt (Processor Control) - * register - * - * RETURN: none - * - * DESCRIPTION:Disable throttling by clearing the THT_EN bit - * - *************************************************************************/ - -void -acpi_hw_disable_throttling ( - ACPI_IO_ADDRESS pblk_address) -{ - u32 pblk_value; - - - pblk_value = acpi_os_in32 (pblk_address); - pblk_value = pblk_value & (~(u32)BIT_4); - acpi_os_out32 (pblk_address, pblk_value); - - return; -} - - -/************************************************************************** - * - * FUNCTION: Acpi_hw_get_duty_cycle - * - * PARAMETERS: Duty_offset Pcnt register duty cycle field offset - * Pblk_address Pcnt register address in chipset - * Num_throttle_states # of CPU throttle states this system - * supports - * - * RETURN: none - * - * DESCRIPTION: Get the duty cycle from the chipset - * - *************************************************************************/ - -u32 -acpi_hw_get_duty_cycle ( - u8 duty_offset, - ACPI_IO_ADDRESS pblk_address, - u32 num_throttle_states) -{ - NATIVE_UINT index; - u32 duty32_value; - u32 pcnt_mask_off_duty_field; - - - /* - * Use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)] - * and then shift it into the right position - */ - pcnt_mask_off_duty_field = num_throttle_states - 1; - - /* - * Read in the current value from the port - */ - duty32_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address); - - /* - * Shift the the value to LSB - */ - for (index = 0; index < (NATIVE_UINT) duty_offset; index++) { - duty32_value = duty32_value >> 1; - } - - /* - * Get the duty field only - */ - duty32_value = duty32_value & pcnt_mask_off_duty_field; - - return ((u32) duty32_value); -} - - -/************************************************************************** - * - * FUNCTION: Acpi_hw_program_duty_cycle - * - * PARAMETERS: Duty_offset Pcnt register duty cycle field offset - * Duty_cycle duty cycle to program into chipset - * Pblk_address Pcnt register address in chipset - * Num_throttle_states # of CPU throttle states this system - * supports - * - * RETURN: none - * - * DESCRIPTION: Program chipset with specified duty cycle by bit-shifting the - * duty cycle bits to the appropriate offset, reading the duty - * cycle register, OR-ing in the duty cycle, and writing it to - * the Pcnt register. - * - *************************************************************************/ - -void -acpi_hw_program_duty_cycle ( - u8 duty_offset, - u32 duty_cycle, - ACPI_IO_ADDRESS pblk_address, - u32 num_throttle_states) -{ - NATIVE_UINT index; - u32 duty32_value; - u32 pcnt_mask_off_duty_field; - u32 port_value; - - - /* - * valid Duty_cycle passed - */ - duty32_value = duty_cycle; - - /* - * use Num_throttle_states - 1 as mask [ex. 8 - 1 = 7 (Fh)] - * and then shift it into the right position - */ - pcnt_mask_off_duty_field = num_throttle_states - 1; - - /* - * Shift the mask - */ - for (index = 0; index < (NATIVE_UINT) duty_offset; index++) { - pcnt_mask_off_duty_field = pcnt_mask_off_duty_field << 1; - duty32_value = duty32_value << 1; - } - - /* - * Read in the current value from the port - */ - port_value = acpi_os_in32 ((ACPI_IO_ADDRESS) pblk_address); - - /* - * Mask off the duty field so we don't OR in junk! - */ - port_value = port_value & (~pcnt_mask_off_duty_field); - - /* - * OR in the bits we want to write out to the port - */ - port_value = (port_value | duty32_value) & (~(u32)BIT_4); - - /* - * write it to the port - */ - acpi_os_out32 ((ACPI_IO_ADDRESS) pblk_address, port_value); - - return; -} diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index b2a621e47523..b7b777df6337 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -1,7 +1,8 @@ + /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions - * $Revision: 27 $ + * $Revision: 28 $ * *****************************************************************************/ diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index cbb98ec78364..fc96c51fbe8a 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -3,7 +3,7 @@ * * Module Name: hwregs - Read/write access functions for the various ACPI * control and status registers. - * $Revision: 87 $ + * $Revision: 88 $ * ******************************************************************************/ @@ -37,7 +37,7 @@ /* This matches the #defines in actypes.h. */ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_", - "\\_S4_","\\_S4_b","\\_S5_"}; + "\\_S4_","\\_S5_","\\_S4_b"}; /******************************************************************************* @@ -53,7 +53,7 @@ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_"," * ******************************************************************************/ -static u32 +u32 acpi_hw_get_bit_shift ( u32 mask) { @@ -581,13 +581,8 @@ acpi_hw_register_read ( case PM1_CONTROL: /* 16-bit access */ - if (register_id != SLP_TYPE_B) { - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - } - - if (register_id != SLP_TYPE_A) { - value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - } + value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; @@ -696,30 +691,20 @@ acpi_hw_register_write ( case PM1_CONTROL: /* 16-bit access */ - /* - * If SLP_TYP_A or SLP_TYP_B, only write to one reg block. - * Otherwise, write to both. - */ - if (register_id == SLP_TYPE_A) { - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - } - else if (register_id == SLP_TYPE_B) { - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - } - else { - /* disable/re-enable interrupts if sleeping */ - if (register_id == SLP_EN) { - disable(); - } + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + break; - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); - acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); - if (register_id == SLP_EN) { - enable(); - } - } + case PM1_a_CONTROL: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + break; + + + case PM1_b_CONTROL: /* 16-bit access */ + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); break; diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c new file mode 100644 index 000000000000..892c721c6a0d --- /dev/null +++ b/drivers/acpi/hardware/hwsleep.c @@ -0,0 +1,189 @@ + +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * $Revision: 5 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "acnamesp.h" +#include "achware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwsleep") + + +/****************************************************************************** + * + * FUNCTION: Acpi_set_firmware_waking_vector + * + * PARAMETERS: Physical_address - Physical address of ACPI real mode + * entry point. + * + * RETURN: AE_OK or AE_ERROR + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS physical_address) +{ + + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Set the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address; + } + else { + *acpi_gbl_FACS->firmware_waking_vector = physical_address; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_firmware_waking_vector + * + * PARAMETERS: *Physical_address - Output buffer where contents of + * the Firmware_waking_vector field of + * the FACS will be stored. + * + * RETURN: Status + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS *physical_address) +{ + + + if (!physical_address) { + return (AE_BAD_PARAMETER); + } + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Get the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector; + } + else { + *physical_address = *acpi_gbl_FACS->firmware_waking_vector; + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_enter_sleep_state + * + * PARAMETERS: Sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enter_sleep_state ( + u8 sleep_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u8 type_a; + u8 type_b; + u16 PM1_acontrol; + u16 PM1_bcontrol; + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + + status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b); + + if (!ACPI_SUCCESS(status)) { + return status; + } + + /* run the _PTS and _GTS methods */ + MEMSET(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + MEMSET(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); + acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL); + + /* clear wake status */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); + + PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL); + + /* mask off SLP_EN and SLP_TYP fields */ + PM1_acontrol &= 0xC3FF; + + /* mask in SLP_EN */ + PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + + PM1_bcontrol = PM1_acontrol; + + /* mask in SLP_TYP */ + PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + + /* the old version was disabling interrupts. let's try it without + * and see how that works + */ + /*disable();*/ + + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol); + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol); + + /*enable();*/ + + return (AE_OK); +} diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c new file mode 100644 index 000000000000..b7f529ccf67c --- /dev/null +++ b/drivers/acpi/hardware/hwtimer.c @@ -0,0 +1,196 @@ + +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * $Revision: 4 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "achware.h" + +#define _COMPONENT HARDWARE + MODULE_NAME ("hwtimer") + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_resolution + * + * PARAMETERS: none + * + * RETURN: Number of bits of resolution in the PM Timer (24 or 32). + * + * DESCRIPTION: Obtains resolution of the ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_resolution ( + u32 *resolution) +{ + if (!resolution) { + return (AE_BAD_PARAMETER); + } + + if (0 == acpi_gbl_FADT->tmr_val_ext) { + *resolution = 24; + } + else { + *resolution = 32; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer + * + * PARAMETERS: none + * + * RETURN: Current value of the ACPI PM Timer (in ticks). + * + * DESCRIPTION: Obtains current value of ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer ( + u32 *ticks) +{ + if (!ticks) { + return (AE_BAD_PARAMETER); + } + + *ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_duration + * + * PARAMETERS: Start_ticks + * End_ticks + * Time_elapsed + * + * RETURN: Time_elapsed + * + * DESCRIPTION: Computes the time elapsed (in microseconds) between two + * PM Timer time stamps, taking into account the possibility of + * rollovers, the timer resolution, and timer frequency. + * + * The PM Timer's clock ticks at roughly 3.6 times per + * _microsecond_, and its clock continues through Cx state + * transitions (unlike many CPU timestamp counters) -- making it + * a versatile and accurate timer. + * + * Note that this function accomodates only a single timer + * rollover. Thus for 24-bit timers, this function should only + * be used for calculating durations less than ~4.6 seconds + * (~20 hours for 32-bit timers). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_duration ( + u32 start_ticks, + u32 end_ticks, + u32 *time_elapsed) +{ + u32 delta_ticks = 0; + u32 seconds = 0; + u32 milliseconds = 0; + u32 microseconds = 0; + u32 remainder = 0; + + if (!time_elapsed) { + return (AE_BAD_PARAMETER); + } + + /* + * Compute Tick Delta: + * ------------------- + * Handle timer rollovers on 24- versus 32-bit timers. + */ + if (start_ticks < end_ticks) { + delta_ticks = end_ticks - start_ticks; + } + else if (start_ticks > end_ticks) { + /* 24-bit Timer */ + if (0 == acpi_gbl_FADT->tmr_val_ext) { + delta_ticks = (0x00FFFFFF - start_ticks) + end_ticks; + } + /* 32-bit Timer */ + else { + delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; + } + } + + /* + * Compute Duration: + * ----------------- + * Since certain compilers (gcc/Linux, argh!) don't support 64-bit + * divides in kernel-space we have to do some trickery to preserve + * accuracy while using 32-bit math. + * + * TODO: Change to use 64-bit math when supported. + * + * The process is as follows: + * 1. Compute the number of seconds by dividing Delta Ticks by + * the timer frequency. + * 2. Compute the number of milliseconds in the remainder from step #1 + * by multiplying by 1000 and then dividing by the timer frequency. + * 3. Compute the number of microseconds in the remainder from step #2 + * by multiplying by 1000 and then dividing by the timer frequency. + * 4. Add the results from steps 1, 2, and 3 to get the total duration. + * + * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be + * 1199864031 microseconds. This is computed as follows: + * Step #1: Seconds = 1199; Remainder = 3092840 + * Step #2: Milliseconds = 864; Remainder = 113120 + * Step #3: Microseconds = 31; Remainder = + */ + + /* Step #1 */ + seconds = delta_ticks / PM_TIMER_FREQUENCY; + remainder = delta_ticks % PM_TIMER_FREQUENCY; + + /* Step #2 */ + milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + remainder = (remainder * 1000) % PM_TIMER_FREQUENCY; + + /* Step #3 */ + microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + + /* Step #4 */ + *time_elapsed = seconds * 1000000; + *time_elapsed += milliseconds * 1000; + *time_elapsed += microseconds; + + return (AE_OK); +} + + diff --git a/drivers/acpi/hardware/hwxface.c b/drivers/acpi/hardware/hwxface.c deleted file mode 100644 index 35194cae38c6..000000000000 --- a/drivers/acpi/hardware/hwxface.c +++ /dev/null @@ -1,595 +0,0 @@ - -/****************************************************************************** - * - * Name: hwxface.c - Hardware access external interfaces - * $Revision: 38 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000, 2001 R. Byron Moore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "acpi.h" -#include "acnamesp.h" -#include "achware.h" - -#define _COMPONENT HARDWARE - MODULE_NAME ("hwxface") - - -/****************************************************************************** - * - * Hardware globals - * - ******************************************************************************/ - - -ACPI_C_STATE_HANDLER acpi_hw_cx_handlers[MAX_CX_STATES] = - {NULL, acpi_hw_enter_c1, NULL, NULL}; - -u32 acpi_hw_active_cx_state = 1; - - -/**************************************************************************** - * - * FUNCTION: Acpi_get_processor_throttling_info - * - * PARAMETERS: Processor_handle - handle for the cpu to get info about - * User_buffer - caller supplied buffer - * - * RETURN: Status of function - * - * DESCRIPTION: Get throttling capabilities for the processor, this routine - * builds the data directly into the callers buffer - * - ****************************************************************************/ - -ACPI_STATUS -acpi_get_processor_throttling_info ( - ACPI_HANDLE processor_handle, - ACPI_BUFFER *user_buffer) -{ - NATIVE_UINT percent_step; - NATIVE_UINT next_percent; - NATIVE_UINT num_throttle_states; - NATIVE_UINT buffer_space_needed; - NATIVE_UINT i; - u8 duty_width; - ACPI_NAMESPACE_NODE *cpu_node; - ACPI_OPERAND_OBJECT *cpu_obj; - ACPI_CPU_THROTTLING_STATE *state_ptr; - - - /* - * Have to at least have a buffer to return info in - */ - if (!user_buffer) { - return(AE_BAD_PARAMETER); - } - - /* - * Convert and validate the device handle - */ - - cpu_node = acpi_ns_convert_handle_to_entry (processor_handle); - if (!cpu_node) { - return (AE_BAD_PARAMETER); - } - - /* - * Check for an existing internal object - */ - - cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node); - if (!cpu_obj) { - return (AE_NOT_FOUND); - } - - /* - * (Duty Width on IA-64 is zero) - */ - duty_width = acpi_gbl_FADT->duty_width; - - /* - * P0 must always have a P_BLK all others may be null - * in either case, we can't throttle a processor that has no P_BLK - * - * Also if no Duty width, one state and it is 100% - * - */ - if (!cpu_obj->processor.length || !duty_width || - (ACPI_UINT16_MAX < cpu_obj->processor.address)) - { - /* - * Acpi_even though we can't throttle, we still have one state (100%) - */ - num_throttle_states = 1; - } - - else { - num_throttle_states = (int) acpi_hw_local_pow (2,duty_width); - } - - buffer_space_needed = num_throttle_states * sizeof (ACPI_CPU_THROTTLING_STATE); - - if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) { - user_buffer->length = buffer_space_needed; - return (AE_BUFFER_OVERFLOW); - } - - user_buffer->length = buffer_space_needed; - state_ptr = (ACPI_CPU_THROTTLING_STATE *) user_buffer->pointer; - percent_step = 1000 / num_throttle_states; - - /* - * Build each entry in the buffer. Note that we're using the value - * 1000 and dividing each state by 10 to better avoid round-off - * accumulation. Also note that the throttling STATES are ordered - * sequentially from 100% (state 0) on down (e.g. 87.5% = state 1), - * which is exactly opposite from duty cycle values (12.5% = state 1). - */ - for (i = 0, next_percent = 1000; i < num_throttle_states; i++) { - state_ptr[i].state_number = i; - state_ptr[i].percent_of_clock = next_percent / 10; - next_percent -= percent_step; - } - - return(AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_get_processor_throttling_state - * - * PARAMETERS: Processor_handle - handle for the cpu to throttle - * Throttle_state - throttling state to enter - * - * RETURN: Status of function - * - * DESCRIPTION: Get current hardware throttling state - * - ****************************************************************************/ - -ACPI_STATUS -acpi_get_processor_throttling_state ( - ACPI_HANDLE processor_handle, - u32 *throttle_state) -{ - ACPI_NAMESPACE_NODE *cpu_node; - ACPI_OPERAND_OBJECT *cpu_obj; - u32 num_throttle_states; - u32 duty_cycle; - u8 duty_offset; - u8 duty_width; - - - /* Convert and validate the device handle */ - - cpu_node = acpi_ns_convert_handle_to_entry (processor_handle); - if (!cpu_node || !throttle_state) { - return (AE_BAD_PARAMETER); - } - - /* Check for an existing internal object */ - - cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node); - if (!cpu_obj) { - return (AE_NOT_FOUND); - } - - /* - * No Duty fields in IA64 tables - */ - duty_offset = acpi_gbl_FADT->duty_offset; - duty_width = acpi_gbl_FADT->duty_width; - - /* - * Must have a valid P_BLK P0 must have a P_BLK all others may be null - * in either case, we can't thottle a processor that has no P_BLK - * that means we are in the only supported state (0 - 100%) - * - * also, if Duty_width is zero there are no additional states - */ - if (!cpu_obj->processor.length || !duty_width || - (ACPI_UINT16_MAX < cpu_obj->processor.address)) - { - *throttle_state = 0; - return(AE_OK); - } - - num_throttle_states = (u32) acpi_hw_local_pow (2,duty_width); - - /* - * Get the current duty cycle value. - */ - duty_cycle = acpi_hw_get_duty_cycle (duty_offset, - cpu_obj->processor.address, - num_throttle_states); - - /* - * Convert duty cycle to throttling state (invert). - */ - if (duty_cycle == 0) { - *throttle_state = 0; - } - - else { - *throttle_state = num_throttle_states - duty_cycle; - } - - return(AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_set_processor_throttling_state - * - * PARAMETERS: Processor_handle - handle for the cpu to throttle - * Throttle_state - throttling state to enter - * - * RETURN: Status of function - * - * DESCRIPTION: Set hardware into requested throttling state, the handle - * passed in must have a valid P_BLK - * - ****************************************************************************/ - -ACPI_STATUS -acpi_set_processor_throttling_state ( - ACPI_HANDLE processor_handle, - u32 throttle_state) -{ - ACPI_NAMESPACE_NODE *cpu_node; - ACPI_OPERAND_OBJECT *cpu_obj; - u32 num_throttle_states = 0; - u8 duty_offset; - u8 duty_width; - u32 duty_cycle = 0; - - - /* Convert and validate the device handle */ - - cpu_node = acpi_ns_convert_handle_to_entry (processor_handle); - if (!cpu_node) { - return (AE_BAD_PARAMETER); - } - - /* Check for an existing internal object */ - - cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node); - if (!cpu_obj) { - return (AE_NOT_FOUND); - } - - /* - * No Duty fields in IA64 tables - */ - duty_offset = acpi_gbl_FADT->duty_offset; - duty_width = acpi_gbl_FADT->duty_width; - - /* - * Must have a valid P_BLK P0 must have a P_BLK all others may be null - * in either case, we can't thottle a processor that has no P_BLK - * that means we are in the only supported state (0 - 100%) - * - * also, if Duty_width is zero there are no additional states - */ - if (!cpu_obj->processor.length || !duty_width || - (ACPI_UINT16_MAX < cpu_obj->processor.address)) - { - /* - * If caller wants to set the state to the only state we handle - * we're done. - */ - if (throttle_state == 0) { - return (AE_OK); - } - - /* - * Can't set this state - */ - return (AE_SUPPORT); - } - - num_throttle_states = (u32) acpi_hw_local_pow (2,duty_width); - - /* - * Convert throttling state to duty cycle (invert). - */ - if (throttle_state > 0) { - duty_cycle = num_throttle_states - throttle_state; - } - - /* - * Turn off throttling (don't muck with the h/w while throttling). - */ - acpi_hw_disable_throttling (cpu_obj->processor.address); - - /* - * Program the throttling state. - */ - acpi_hw_program_duty_cycle (duty_offset, duty_cycle, - cpu_obj->processor.address, num_throttle_states); - - /* - * Only enable throttling for non-zero states (0 - 100%) - */ - if (throttle_state) { - acpi_hw_enable_throttling (cpu_obj->processor.address); - } - - return(AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_get_processor_cx_info - * - * PARAMETERS: Processor_handle - handle for the cpu return info about - * User_buffer - caller supplied buffer - * - * RETURN: Status of function - * - * DESCRIPTION: Get Cx state latencies, this routine - * builds the data directly into the callers buffer - * - * - ****************************************************************************/ - -ACPI_STATUS -acpi_get_processor_cx_info ( - ACPI_HANDLE processor_handle, - ACPI_BUFFER *user_buffer) -{ - ACPI_STATUS status = AE_OK; - u32 cx_state_latencies[4] = {0, 0, 0, 0}; - NATIVE_UINT buffer_space_needed = 0; - ACPI_CX_STATE *state_ptr = NULL; - NATIVE_UINT i = 0; - - - /* - * Have to at least have a buffer to return info in - */ - if (!user_buffer) { - return (AE_BAD_PARAMETER); - } - - status = acpi_hw_get_cx_info (cx_state_latencies); - if (ACPI_FAILURE (status)) { - return (status); - } - - buffer_space_needed = 4 * sizeof (ACPI_CX_STATE); - - if ((user_buffer->length < buffer_space_needed) || !user_buffer->pointer) { - user_buffer->length = buffer_space_needed; - return (AE_BUFFER_OVERFLOW); - } - - user_buffer->length = buffer_space_needed; - - state_ptr = (ACPI_CX_STATE *) user_buffer->pointer; - - for (i = 0; i < 4; i++) { - state_ptr[i].state_number = i; - state_ptr[i].latency = cx_state_latencies[i]; - } - - return (AE_OK); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_set_processor_sleep_state - * - * PARAMETERS: Processor_handle - handle for the cpu return info about - * Cx_state - the Cx sleeping state (C1-C3) to make - * 'active' - * - * RETURN: Status of function - * - * DESCRIPTION: Sets which Cx state will be used during calls to - * Acpi_processor_sleep () - * - ****************************************************************************/ - -ACPI_STATUS -acpi_set_processor_sleep_state ( - ACPI_HANDLE processor_handle, - u32 cx_state) -{ - ACPI_STATUS status; - - - status = acpi_hw_set_cx (cx_state); - - return (status); -} - - -/**************************************************************************** - * - * FUNCTION: Acpi_processor_sleep - * - * PARAMETERS: Processor_handle - handle for the cpu to put to sleep (Cx) - * Time_sleeping - time (in microseconds) elapsed while - * sleeping - * - * RETURN: Status of function - * - * DESCRIPTION: Puts the processor into the currently active sleep state (Cx) - * - ****************************************************************************/ - -ACPI_STATUS -acpi_processor_sleep ( - ACPI_HANDLE processor_handle, - u32 *pm_timer_ticks) -{ - ACPI_NAMESPACE_NODE *cpu_node = NULL; - ACPI_OPERAND_OBJECT *cpu_obj = NULL; - ACPI_IO_ADDRESS address = 0; - - - /* - * Convert Processor_handle to Pblk_addres... - */ - - /* Convert and validate the device handle */ - - cpu_node = acpi_ns_convert_handle_to_entry (processor_handle); - if (!cpu_node) { - return (AE_BAD_PARAMETER); - } - - /* Check for an existing internal object */ - - cpu_obj = acpi_ns_get_attached_object ((ACPI_HANDLE) cpu_node); - if (!cpu_obj) { - return (AE_NOT_FOUND); - } - - /* Get the processor register block (P_BLK) address */ - - address = cpu_obj->processor.address; - if (!cpu_obj->processor.length) { - /* Ensure a NULL addresss (note that P_BLK isn't required for C1) */ - - address = 0; - } - - /* - * Enter the currently active Cx sleep state. - */ - return (acpi_hw_enter_cx (address, pm_timer_ticks)); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_get_timer - * - * PARAMETERS: none - * - * RETURN: Current value of the ACPI PMT (timer) - * - * DESCRIPTION: Obtains current value of ACPI PMT - * - ******************************************************************************/ - -ACPI_STATUS -acpi_get_timer ( - u32 *out_ticks) -{ - - if (!out_ticks) { - return (AE_BAD_PARAMETER); - } - - *out_ticks = acpi_hw_pmt_ticks (); - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_set_firmware_waking_vector - * - * PARAMETERS: Physical_address - Physical address of ACPI real mode - * entry point. - * - * RETURN: AE_OK or AE_ERROR - * - * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS - * - ******************************************************************************/ - -ACPI_STATUS -acpi_set_firmware_waking_vector ( - ACPI_PHYSICAL_ADDRESS physical_address) -{ - - - /* Make sure that we have an FACS */ - - if (!acpi_gbl_FACS) { - return (AE_NO_ACPI_TABLES); - } - - /* Set the vector */ - - if (acpi_gbl_FACS->vector_width == 32) { - * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address; - } - else { - *acpi_gbl_FACS->firmware_waking_vector = physical_address; - } - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_get_firmware_waking_vector - * - * PARAMETERS: *Physical_address - Output buffer where contents of - * the Firmware_waking_vector field of - * the FACS will be stored. - * - * RETURN: Status - * - * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS - * - ******************************************************************************/ - -ACPI_STATUS -acpi_get_firmware_waking_vector ( - ACPI_PHYSICAL_ADDRESS *physical_address) -{ - - - if (!physical_address) { - return (AE_BAD_PARAMETER); - } - - /* Make sure that we have an FACS */ - - if (!acpi_gbl_FACS) { - return (AE_NO_ACPI_TABLES); - } - - /* Get the vector */ - - if (acpi_gbl_FACS->vector_width == 32) { - *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector; - } - else { - *physical_address = *acpi_gbl_FACS->firmware_waking_vector; - } - - return (AE_OK); -} - - diff --git a/drivers/acpi/include/accommon.h b/drivers/acpi/include/accommon.h index b657b6d9eee6..61d54a220dcc 100644 --- a/drivers/acpi/include/accommon.h +++ b/drivers/acpi/include/accommon.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 86 $ + * $Revision: 87 $ * *****************************************************************************/ diff --git a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h index d5ab95dfb600..ea9be649d745 100644 --- a/drivers/acpi/include/acconfig.h +++ b/drivers/acpi/include/acconfig.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 51 $ + * $Revision: 53 $ * *****************************************************************************/ @@ -53,7 +53,7 @@ /* Version string */ -#define ACPI_CA_VERSION __DATE__ +#define ACPI_CA_VERSION 0x20010125 /* Maximum objects in the various object caches */ diff --git a/drivers/acpi/include/achware.h b/drivers/acpi/include/achware.h index 24b767cc939d..efb97bd2fdb8 100644 --- a/drivers/acpi/include/achware.h +++ b/drivers/acpi/include/achware.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: achware.h -- hardware specific interfaces - * $Revision: 50 $ + * $Revision: 53 $ * *****************************************************************************/ @@ -27,6 +27,10 @@ #define __ACHWARE_H__ +/* PM Timer ticks per second (HZ) */ +#define PM_TIMER_FREQUENCY 3579545 + + /* Prototypes */ @@ -92,6 +96,10 @@ void acpi_hw_clear_acpi_status ( void); +u32 +acpi_hw_get_bit_shift ( + u32 mask); + /* GPE support */ @@ -121,89 +129,21 @@ acpi_hw_obtain_sleep_type_register_data ( u8 *slp_typ_b); -/* Cx State Prototypes */ - -ACPI_STATUS -acpi_hw_enter_c1( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks); - -ACPI_STATUS -acpi_hw_enter_c2( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks); - -ACPI_STATUS -acpi_hw_enter_c3( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks); - -ACPI_STATUS -acpi_hw_enter_cx ( - ACPI_IO_ADDRESS pblk_address, - u32 *pm_timer_ticks); - -ACPI_STATUS -acpi_hw_set_cx ( - u32 cx_state); - -ACPI_STATUS -acpi_hw_get_cx_info ( - u32 cx_states[]); +/* ACPI Timer prototypes */ ACPI_STATUS -acpi_hw_get_cx_handler ( - u32 cx_state, - ACPI_C_STATE_HANDLER *handler); +acpi_get_timer_resolution ( + u32 *resolution); ACPI_STATUS -acpi_hw_set_cx_handler ( - u32 cx_state, - ACPI_C_STATE_HANDLER handler); - - -/* Throttling Prototypes */ - -void -acpi_hw_enable_throttling ( - ACPI_IO_ADDRESS pblk_address); - -void -acpi_hw_disable_throttling ( - ACPI_IO_ADDRESS pblk_address); - -u32 -acpi_hw_get_duty_cycle ( - u8 duty_offset, - ACPI_IO_ADDRESS pblk_address, - u32 num_throttle_states); - -void -acpi_hw_program_duty_cycle ( - u8 duty_offset, - u32 duty_cycle, - ACPI_IO_ADDRESS pblk_address, - u32 num_throttle_states); - -NATIVE_UINT -acpi_hw_local_pow ( - NATIVE_UINT x, - NATIVE_UINT y); - - -/* ACPI Timer prototypes */ - -u32 -acpi_hw_pmt_ticks ( - void); - -u32 -acpi_hw_pmt_resolution ( - void); +acpi_get_timer ( + u32 *ticks); ACPI_STATUS -acpi_get_timer ( - u32 *out_ticks); +acpi_get_timer_duration ( + u32 start_ticks, + u32 end_ticks, + u32 *time_elapsed); #endif /* __ACHWARE_H__ */ diff --git a/drivers/acpi/include/acinterp.h b/drivers/acpi/include/acinterp.h index ffeb5682f96e..6eb571e5fae0 100644 --- a/drivers/acpi/include/acinterp.h +++ b/drivers/acpi/include/acinterp.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acinterp.h - Interpreter subcomponent prototypes and defines - * $Revision: 89 $ + * $Revision: 91 $ * *****************************************************************************/ @@ -88,6 +88,12 @@ acpi_aml_convert_to_string ( ACPI_OPERAND_OBJECT **obj_desc, ACPI_WALK_STATE *walk_state); +ACPI_STATUS +acpi_aml_convert_to_target_type ( + OBJECT_TYPE_INTERNAL destination_type, + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state); + /* * amfield - ACPI AML (p-code) execution - field manipulation @@ -438,17 +444,75 @@ acpi_aml_exec_store ( ACPI_WALK_STATE *walk_state); ACPI_STATUS -acpi_aml_store_object_to_object ( +acpi_aml_store_object_to_index ( ACPI_OPERAND_OBJECT *val_desc, ACPI_OPERAND_OBJECT *dest_desc, ACPI_WALK_STATE *walk_state); ACPI_STATUS acpi_aml_store_object_to_node ( - ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *source_desc, ACPI_NAMESPACE_NODE *node, ACPI_WALK_STATE *walk_state); +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state); + + +/* + * + */ + +ACPI_STATUS +acpi_aml_resolve_object ( + ACPI_OPERAND_OBJECT **source_desc_ptr, + OBJECT_TYPE_INTERNAL target_type, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_store_object ( + ACPI_OPERAND_OBJECT *source_desc, + OBJECT_TYPE_INTERNAL target_type, + ACPI_OPERAND_OBJECT **target_desc_ptr, + ACPI_WALK_STATE *walk_state); + + +/* + * amcopy - object copy + */ + +ACPI_STATUS +acpi_aml_copy_buffer_to_buffer ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_string_to_string ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_integer_to_index_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_integer_to_bank_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_data_to_named_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node); + +ACPI_STATUS +acpi_aml_copy_integer_to_field_unit ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); /* * amutils - interpreter/scanner utilities diff --git a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h index 99da2a422741..2d931387ed90 100644 --- a/drivers/acpi/include/aclocal.h +++ b/drivers/acpi/include/aclocal.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 97 $ + * $Revision: 100 $ * *****************************************************************************/ @@ -74,7 +74,7 @@ typedef u32 ACPI_MUTEX_HANDLE; #define NUM_MTX MAX_MTX+1 -#ifdef ACPI_DEBUG +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) #ifdef DEFINE_ACPI_GLOBALS /* Names for the mutexes used in the subsystem */ @@ -593,6 +593,7 @@ typedef struct acpi_walk_state ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */ ACPI_PARSE_STATE *parser_state; /* Current state of parser */ u8 *aml_last_while; + ACPI_OPCODE_INFO *op_info; /* Info on current opcode */ ACPI_PARSE_DOWNWARDS descending_callback; ACPI_PARSE_UPWARDS ascending_callback; @@ -607,6 +608,7 @@ typedef struct acpi_walk_state u32 parse_flags; u8 walk_type; u8 return_used; + u16 opcode; /* Current AML opcode */ u32 prev_arg_types; /* Debug support */ @@ -730,14 +732,16 @@ typedef struct acpi_get_devices_info #define PM1_STS 0x0100 #define PM1_EN 0x0200 #define PM1_CONTROL 0x0300 -#define PM2_CONTROL 0x0400 -#define PM_TIMER 0x0500 -#define PROCESSOR_BLOCK 0x0600 -#define GPE0_STS_BLOCK 0x0700 -#define GPE0_EN_BLOCK 0x0800 -#define GPE1_STS_BLOCK 0x0900 -#define GPE1_EN_BLOCK 0x0A00 -#define SMI_CMD_BLOCK 0x0B00 +#define PM1_a_CONTROL 0x0400 +#define PM1_b_CONTROL 0x0500 +#define PM2_CONTROL 0x0600 +#define PM_TIMER 0x0700 +#define PROCESSOR_BLOCK 0x0800 +#define GPE0_STS_BLOCK 0x0900 +#define GPE0_EN_BLOCK 0x0A00 +#define GPE1_STS_BLOCK 0x0B00 +#define GPE1_EN_BLOCK 0x0C00 +#define SMI_CMD_BLOCK 0x0D00 /* * Address space bitmasks for mmio or io spaces diff --git a/drivers/acpi/include/acoutput.h b/drivers/acpi/include/acoutput.h index 8e79f788cc96..5c20943cba89 100644 --- a/drivers/acpi/include/acoutput.h +++ b/drivers/acpi/include/acoutput.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acoutput.h -- debug output - * $Revision: 68 $ + * $Revision: 69 $ * *****************************************************************************/ @@ -58,6 +58,7 @@ #define BATTERY 0x00040000 #define DEBUGGER 0x00100000 +#define COMPILER 0x00200000 #define ALL_COMPONENTS 0x001FFFFF #define COMPONENT_DEFAULT (ALL_COMPONENTS) diff --git a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h index c2b3ed79edcf..ee289f33e9b9 100644 --- a/drivers/acpi/include/acpiosxf.h +++ b/drivers/acpi/include/acpiosxf.h @@ -121,6 +121,10 @@ acpi_os_unmap_memory ( void *logical_address, u32 length); +ACPI_STATUS +acpi_os_get_physical_address ( + void *logical_address, + ACPI_PHYSICAL_ADDRESS *physical_address); /* * Interrupt handlers diff --git a/drivers/acpi/include/acpixf.h b/drivers/acpi/include/acpixf.h index 76c7fe26b800..8d293818f908 100644 --- a/drivers/acpi/include/acpixf.h +++ b/drivers/acpi/include/acpixf.h @@ -284,6 +284,10 @@ ACPI_STATUS acpi_get_firmware_waking_vector ( ACPI_PHYSICAL_ADDRESS *physical_address); +ACPI_STATUS +acpi_enter_sleep_state ( + u8 sleep_state); + ACPI_STATUS acpi_get_processor_throttling_info ( ACPI_HANDLE processor_handle, diff --git a/drivers/acpi/include/actbl2.h b/drivers/acpi/include/actbl2.h index d36555b3f759..0a05efa1caf2 100644 --- a/drivers/acpi/include/actbl2.h +++ b/drivers/acpi/include/actbl2.h @@ -142,8 +142,8 @@ typedef struct u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ u16 flush_size; /* number of flush strides that need to be read */ u16 flush_stride; /* Processor's memory cache line width, in bytes */ - u8 duty_offset; /* Processor’s duty cycle index in processor's P_CNT reg*/ - u8 duty_width; /* Processor’s duty cycle value bit width in P_CNT register.*/ + u8 duty_offset; /* Processor_’s duty cycle index in processor's P_CNT reg*/ + u8 duty_width; /* Processor_’s duty cycle value bit width in P_CNT register.*/ u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ u8 century; /* index to century in RTC CMOS RAM */ diff --git a/drivers/acpi/include/actypes.h b/drivers/acpi/include/actypes.h index 06cc0f33124a..826fc89018ad 100644 --- a/drivers/acpi/include/actypes.h +++ b/drivers/acpi/include/actypes.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actypes.h - Common data types for the entire ACPI subsystem - * $Revision: 162 $ + * $Revision: 163 $ * *****************************************************************************/ @@ -249,8 +249,9 @@ typedef UINT64 ACPI_INTEGER; #define ACPI_STATE_S2 (u8) 2 #define ACPI_STATE_S3 (u8) 3 #define ACPI_STATE_S4 (u8) 4 -#define ACPI_STATE_S4_bIOS (u8) 5 -#define ACPI_STATE_S5 (u8) 6 +#define ACPI_STATE_S5 (u8) 5 +/* let's pretend S4_bIOS didn't exist for now. ASG */ +#define ACPI_STATE_S4_bIOS (u8) 6 #define ACPI_S_STATES_MAX ACPI_STATE_S5 diff --git a/drivers/acpi/interpreter/amconvrt.c b/drivers/acpi/interpreter/amconvrt.c index 3519553e8615..4c895c7eded0 100644 --- a/drivers/acpi/interpreter/amconvrt.c +++ b/drivers/acpi/interpreter/amconvrt.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amconvrt - Object conversion routines - * $Revision: 2 $ + * $Revision: 3 $ * *****************************************************************************/ @@ -37,6 +37,121 @@ MODULE_NAME ("amconvrt") +/******************************************************************************* + * + * FUNCTION: Acpi_aml_convert_to_target_type + * + * PARAMETERS: *Obj_desc - Object to be converted. + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_convert_to_target_type ( + OBJECT_TYPE_INTERNAL destination_type, + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + /* + * If required by the target, + * perform implicit conversion on the source before we store it. + */ + + switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) + { + case ARGI_SIMPLE_TARGET: + case ARGI_FIXED_TARGET: + case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ + + switch (destination_type) + { + case INTERNAL_TYPE_DEF_FIELD: + /* + * Named field can always handle conversions + */ + break; + + default: + /* No conversion allowed for these types */ + + if (destination_type != (*obj_desc)->common.type) { + status = AE_TYPE; + } + } + break; + + + case ARGI_TARGETREF: + + switch (destination_type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_FIELD_UNIT: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + /* + * These types require an Integer operand. We can convert + * a Buffer or a String to an Integer if necessary. + */ + status = acpi_aml_convert_to_integer (obj_desc, walk_state); + break; + + + case ACPI_TYPE_STRING: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_aml_convert_to_string (obj_desc, walk_state); + break; + + + case ACPI_TYPE_BUFFER: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_aml_convert_to_buffer (obj_desc, walk_state); + break; + } + break; + + + case ARGI_REFERENCE: + /* + * Create_xxxx_field cases - we are storing the field object into the name + */ + break; + + + default: + status = AE_AML_INTERNAL; + } + + + /* + * Source-to-Target conversion semantics: + * + * If conversion to the target type cannot be performed, then simply + * overwrite the target with the new object and type. + */ + if (status == AE_TYPE) { + status = AE_OK; + } + + return (status); +} + + /******************************************************************************* * * FUNCTION: Acpi_aml_convert_to_integer @@ -159,7 +274,11 @@ acpi_aml_convert_to_integer ( /* Save the Result, delete original descriptor, store new descriptor */ ret_desc->integer.value = result; - acpi_cm_remove_reference (*obj_desc); + + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; return (AE_OK); @@ -234,7 +353,9 @@ acpi_aml_convert_to_buffer ( /* Return the new buffer descriptor */ - acpi_cm_remove_reference (*obj_desc); + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } *obj_desc = ret_desc; break; @@ -330,7 +451,9 @@ acpi_aml_convert_to_string ( /* Return the new buffer descriptor */ - acpi_cm_remove_reference (*obj_desc); + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } *obj_desc = ret_desc; return (AE_OK); @@ -380,7 +503,9 @@ acpi_aml_convert_to_string ( /* Return the new buffer descriptor */ - acpi_cm_remove_reference (*obj_desc); + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } *obj_desc = ret_desc; break; diff --git a/drivers/acpi/interpreter/amfield.c b/drivers/acpi/interpreter/amfield.c index b722d8107204..3ed442c95f7d 100644 --- a/drivers/acpi/interpreter/amfield.c +++ b/drivers/acpi/interpreter/amfield.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 76 $ + * $Revision: 77 $ * *****************************************************************************/ @@ -174,7 +174,8 @@ acpi_aml_access_named_field ( u32 byte_field_length; - /* Basic data checking */ + /* Parameter validation */ + if ((!named_field) || (ACPI_READ == mode && !buffer)) { return (AE_AML_INTERNAL); } @@ -227,7 +228,7 @@ acpi_aml_access_named_field ( /* TBD: should these round down to a power of 2? */ - if (DIV_8(bit_granularity) > byte_field_length) { + if (DIV_8 (bit_granularity) > byte_field_length) { bit_granularity = MUL_8(byte_field_length); } diff --git a/drivers/acpi/interpreter/amfldio.c b/drivers/acpi/interpreter/amfldio.c index 535be8c45fb6..d16cd3d9b51d 100644 --- a/drivers/acpi/interpreter/amfldio.c +++ b/drivers/acpi/interpreter/amfldio.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: amfldio - Aml Field I/O - * $Revision: 35 $ + * $Revision: 37 $ * *****************************************************************************/ @@ -405,8 +405,6 @@ acpi_aml_write_field_data_with_update_rule ( merged_value = field_value; - /* Check if update rule needs to be applied (not if mask is all ones) */ - /* Decode the update rule */ @@ -415,13 +413,17 @@ acpi_aml_write_field_data_with_update_rule ( case UPDATE_PRESERVE: - /* - * Read the current contents of the byte/word/dword containing - * the field, and merge with the new field value. - */ - status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, - bit_granularity, ¤t_value); - merged_value |= (current_value & ~mask); + /* Check if update rule needs to be applied (not if mask is all ones) */ + + if (((1 << bit_granularity) -1) & ~mask) { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, + bit_granularity, ¤t_value); + merged_value |= (current_value & ~mask); + } break; diff --git a/drivers/acpi/interpreter/amresolv.c b/drivers/acpi/interpreter/amresolv.c index c63424e10003..c08a4731cb01 100644 --- a/drivers/acpi/interpreter/amresolv.c +++ b/drivers/acpi/interpreter/amresolv.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: amresolv - AML Interpreter object resolution - * $Revision: 80 $ + * $Revision: 81 $ * *****************************************************************************/ @@ -150,7 +150,7 @@ acpi_aml_get_field_unit_value ( * * RETURN: Status * - * DESCRIPTION: Convert Reference entries on Obj_stack to Rvalues + * DESCRIPTION: Convert Reference objects to values * ******************************************************************************/ diff --git a/drivers/acpi/interpreter/amstore.c b/drivers/acpi/interpreter/amstore.c index 9c780e9ac570..9f350bb29d24 100644 --- a/drivers/acpi/interpreter/amstore.c +++ b/drivers/acpi/interpreter/amstore.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: amstore - AML Interpreter object store support - * $Revision: 119 $ + * $Revision: 121 $ * *****************************************************************************/ @@ -64,12 +64,7 @@ acpi_aml_exec_store ( ACPI_WALK_STATE *walk_state) { ACPI_STATUS status = AE_OK; - ACPI_OPERAND_OBJECT *delete_dest_desc = NULL; - ACPI_OPERAND_OBJECT *tmp_desc; - ACPI_NAMESPACE_NODE *node = NULL; - u8 value = 0; - u32 length; - u32 i; + ACPI_OPERAND_OBJECT *ref_desc = dest_desc; /* Validate parameters */ @@ -78,27 +73,23 @@ acpi_aml_exec_store ( return (AE_AML_NO_OPERAND); } - /* Examine the datatype of the Dest_desc */ + /* Dest_desc can be either a namespace node or an ACPI object */ if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { - /* Dest is an ACPI_HANDLE, create a new object */ - - node = (ACPI_NAMESPACE_NODE *) dest_desc; - dest_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); - if (!dest_desc) { - /* Allocation failure */ - - return (AE_NO_MEMORY); - } + /* + * Dest is a namespace node, + * Storing an object into a Name "container" + */ + status = acpi_aml_store_object_to_node (val_desc, + (ACPI_NAMESPACE_NODE *) dest_desc, walk_state); - /* Build a new Reference wrapper around the handle */ + /* All done, that's it */ - dest_desc->reference.op_code = AML_NAME_OP; - dest_desc->reference.object = node; + return (status); } - /* Destination object must be of type Reference */ + /* Destination object must be an object of type Reference */ if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { /* Destination is not an Reference */ @@ -106,36 +97,130 @@ acpi_aml_exec_store ( return (AE_AML_OPERAND_TYPE); } - /* Examine the Reference opcode */ - switch (dest_desc->reference.op_code) + /* + * Examine the Reference opcode. These cases are handled: + * + * 1) Store to Name (Change the object associated with a name) + * 2) Store to an indexed area of a Buffer or Package + * 3) Store to a Method Local or Arg + * 4) Store to the debug object + * 5) Store to a constant -- a noop + */ + + switch (ref_desc->reference.op_code) { case AML_NAME_OP: - /* - * Storing into a Name - */ - delete_dest_desc = dest_desc; - status = acpi_aml_store_object_to_node (val_desc, dest_desc->reference.object, - walk_state); + /* Storing an object into a Name "container" */ - break; /* Case Name_op */ + status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object, + walk_state); + break; case AML_INDEX_OP: - delete_dest_desc = dest_desc; + /* Storing to an Index (pointer into a packager or buffer) */ + + status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state); + break; + + + case AML_LOCAL_OP: + + status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL, + (ref_desc->reference.offset), val_desc, walk_state); + break; + + + case AML_ARG_OP: + + status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, + (ref_desc->reference.offset), val_desc, walk_state); + break; + + + case AML_DEBUG_OP: /* - * Valid source value and destination reference pointer. + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see ACPI Specification * - * ACPI Specification 1.0B section 15.2.3.4.2.13: - * Destination should point to either a buffer or a package + * TBD: print known object types "prettier". */ + break; + + + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + /* - * Actually, storing to a package is not so simple. The source must be + * Storing to a constant is a no-op -- see ACPI Specification + * Delete the reference descriptor, however + */ + break; + + + default: + + /* TBD: [Restructure] use object dump routine !! */ + + status = AE_AML_INTERNAL; + break; + + } /* switch (Ref_desc->Reference.Op_code) */ + + + /* Always delete the reference descriptor object */ + + if (ref_desc) { + acpi_cm_remove_reference (ref_desc); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_index + * + * PARAMETERS: *Val_desc - Value to be stored + * *Node - Named object to recieve the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_index ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + u32 length; + u32 i; + u8 value = 0; + + + /* + * Destination must be a reference pointer, and + * must point to either a buffer or a package + */ + + switch (dest_desc->reference.target_type) + { + case ACPI_TYPE_PACKAGE: + /* + * Storing to a package element is not simple. The source must be * evaluated and converted to the type of the destination and then the * source is copied into the destination - we can't just point to the * source object. @@ -145,8 +230,8 @@ acpi_aml_exec_store ( * The object at *(Dest_desc->Reference.Where) is the * element within the package that is to be modified. */ - tmp_desc = *(dest_desc->reference.where); - if (tmp_desc) { + obj_desc = *(dest_desc->reference.where); + if (obj_desc) { /* * If the Destination element is a package, we will delete * that object and construct a new one. @@ -155,41 +240,39 @@ acpi_aml_exec_store ( * to be packages? * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE) */ - if (tmp_desc->common.type == ACPI_TYPE_PACKAGE) { + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { /* * Take away the reference for being part of a package and * delete */ - acpi_cm_remove_reference (tmp_desc); - acpi_cm_remove_reference (tmp_desc); + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc); - tmp_desc = NULL; + obj_desc = NULL; } } - if (!tmp_desc) { + if (!obj_desc) { /* - * If the Tmp_desc is NULL, that means an uninitialized package - * has been used as a destination, therefore, we must create - * the destination element to match the type of the source - * element NOTE: Val_desc can be of any type. + * If the Obj_desc is NULL, it means that an uninitialized package + * element has been used as a destination (this is OK), therefore, + * we must create the destination element to match the type of the + * source element NOTE: Val_desc can be of any type. */ - tmp_desc = acpi_cm_create_internal_object (val_desc->common.type); - if (!tmp_desc) { - status = AE_NO_MEMORY; - goto cleanup; + obj_desc = acpi_cm_create_internal_object (val_desc->common.type); + if (!obj_desc) { + return (AE_NO_MEMORY); } /* * If the source is a package, copy the source to the new dest */ - if (ACPI_TYPE_PACKAGE == tmp_desc->common.type) { + if (ACPI_TYPE_PACKAGE == obj_desc->common.type) { status = acpi_aml_build_copy_internal_package_object ( - val_desc, tmp_desc, walk_state); + val_desc, obj_desc, walk_state); if (ACPI_FAILURE (status)) { - acpi_cm_remove_reference (tmp_desc); - tmp_desc = NULL; - goto cleanup; + acpi_cm_remove_reference (obj_desc); + return (status); } } @@ -199,38 +282,31 @@ acpi_aml_exec_store ( * part of the parent package */ - *(dest_desc->reference.where) = tmp_desc; - acpi_cm_add_reference (tmp_desc); + *(dest_desc->reference.where) = obj_desc; + acpi_cm_add_reference (obj_desc); } - if (ACPI_TYPE_PACKAGE != tmp_desc->common.type) { + if (ACPI_TYPE_PACKAGE != obj_desc->common.type) { /* * The destination element is not a package, so we need to * convert the contents of the source (Val_desc) and copy into - * the destination (Tmp_desc) + * the destination (Obj_desc) */ - status = acpi_aml_store_object_to_object (val_desc, tmp_desc, + status = acpi_aml_store_object_to_object (val_desc, obj_desc, walk_state); if (ACPI_FAILURE (status)) { /* * An error occurrered when copying the internal object * so delete the reference. */ - status = AE_AML_OPERAND_TYPE; + return (AE_AML_OPERAND_TYPE); } } - - break; } + break; - /* - * Check that the destination is a Buffer Field type - */ - if (dest_desc->reference.target_type != ACPI_TYPE_BUFFER_FIELD) { - status = AE_AML_OPERAND_TYPE; - break; - } + case ACPI_TYPE_BUFFER_FIELD: /* * Storing into a buffer at a location defined by an Index. * @@ -239,13 +315,11 @@ acpi_aml_exec_store ( */ /* - * Set the Tmp_desc to the destination object and type check. + * Set the Obj_desc to the destination object and type check. */ - tmp_desc = dest_desc->reference.object; - - if (tmp_desc->common.type != ACPI_TYPE_BUFFER) { - status = AE_AML_OPERAND_TYPE; - break; + obj_desc = dest_desc->reference.object; + if (obj_desc->common.type != ACPI_TYPE_BUFFER) { + return (AE_AML_OPERAND_TYPE); } /* @@ -256,15 +330,15 @@ acpi_aml_exec_store ( switch (val_desc->common.type) { /* - * If the type is Integer, the Length is 4. + * If the type is Integer, assign bytewise * This loop to assign each of the elements is somewhat - * backward because of the Big Endian-ness of IA-64 + * backward because of the Big Endian-ness of IA-64 */ case ACPI_TYPE_INTEGER: - length = 4; + length = sizeof (ACPI_INTEGER); for (i = length; i != 0; i--) { value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1))); - tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; } break; @@ -276,7 +350,7 @@ acpi_aml_exec_store ( length = val_desc->buffer.length; for (i = 0; i < length; i++) { value = *(val_desc->buffer.pointer + i); - tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; } break; @@ -288,7 +362,7 @@ acpi_aml_exec_store ( length = val_desc->string.length; for (i = 0; i < length; i++) { value = *(val_desc->string.pointer + i); - tmp_desc->buffer.pointer[dest_desc->reference.offset] = value; + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; } break; @@ -299,80 +373,207 @@ acpi_aml_exec_store ( status = AE_AML_OPERAND_TYPE; break; } + break; - /* - * If we had an error, break out of this case statement. - */ - if (ACPI_FAILURE (status)) { - break; - } - - /* - * Set the return pointer - */ - dest_desc = tmp_desc; + default: + status = AE_AML_OPERAND_TYPE; break; + } - case AML_ZERO_OP: - case AML_ONE_OP: - case AML_ONES_OP: - /* - * Storing to a constant is a no-op -- see ACPI Specification - * Delete the result descriptor. - */ + return (status); +} - delete_dest_desc = dest_desc; - break; + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_node + * + * PARAMETERS: *Source_desc - Value to be stored + * *Node - Named object to recieve the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * NOTE: the global lock is acquired early. This will result + * in the global lock being held a bit longer. Also, if the + * function fails during set up we may get the lock when we + * don't really need it. I don't think we care. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_node ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *target_desc; + OBJECT_TYPE_INTERNAL target_type = ACPI_TYPE_ANY; - case AML_LOCAL_OP: + /* + * Assuming the parameters were already validated + */ + ACPI_ASSERT((node) && (source_desc)); - status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL, - (dest_desc->reference.offset), val_desc, walk_state); - delete_dest_desc = dest_desc; - break; + /* + * Get current type of the node, and object attached to Node + */ + target_type = acpi_ns_get_type (node); + target_desc = acpi_ns_get_attached_object (node); - case AML_ARG_OP: - status = acpi_ds_method_data_set_value (MTH_TYPE_ARG, - (dest_desc->reference.offset), val_desc, walk_state); - delete_dest_desc = dest_desc; + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_aml_resolve_object (&source_desc, target_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Do the actual store operation + */ + switch (target_type) + { + case INTERNAL_TYPE_DEF_FIELD: + + /* Raw data copy for target types Integer/String/Buffer */ + + status = acpi_aml_copy_data_to_named_field (source_desc, node); break; - case AML_DEBUG_OP: + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + case ACPI_TYPE_FIELD_UNIT: /* - * Storing to the Debug object causes the value stored to be - * displayed and otherwise has no effect -- see ACPI Specification + * These target types are all of type Integer/String/Buffer, and + * therefore support implicit conversion before the store. + * + * Copy and/or convert the source object to a new target object */ + status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } - delete_dest_desc = dest_desc; + /* + * Store the new Target_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Source_desc reference count is incremented by Attach_object. + */ + status = acpi_ns_attach_object (node, target_desc, target_type); break; default: - /* TBD: [Restructure] use object dump routine !! */ + /* No conversions for all other types. Just attach the source object */ - delete_dest_desc = dest_desc; - status = AE_AML_INTERNAL; + status = acpi_ns_attach_object (node, source_desc, source_desc->common.type); - } /* switch(Dest_desc->Reference.Op_code) */ + break; + } -cleanup: + return (status); +} - /* Cleanup and exit*/ - if (delete_dest_desc) { - acpi_cm_remove_reference (delete_dest_desc); +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_object + * + * PARAMETERS: *Source_desc - Value to be stored + * *Dest_desc - Object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store an object to another object. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * and Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type; + + + /* + * Assuming the parameters are valid! + */ + ACPI_ASSERT((dest_desc) && (source_desc)); + + + /* + * From this interface, we only support Integers/Strings/Buffers + */ + switch (destination_type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + break; + + default: + return (AE_NOT_IMPLEMENTED); } + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Copy and/or convert the source object to the destination object + */ + status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state); + + return (status); } - diff --git a/drivers/acpi/interpreter/amstoren.c b/drivers/acpi/interpreter/amstoren.c index 6e3d0c7e0282..eb62ed2f1b1a 100644 --- a/drivers/acpi/interpreter/amstoren.c +++ b/drivers/acpi/interpreter/amstoren.c @@ -2,8 +2,8 @@ /****************************************************************************** * * Module Name: amstoren - AML Interpreter object store support, - * Store to Node (namespace object) - * $Revision: 26 $ + * Store to Node (namespace object) + * $Revision: 28 $ * *****************************************************************************/ @@ -41,127 +41,72 @@ /******************************************************************************* * - * FUNCTION: Acpi_aml_store_object_to_node + * FUNCTION: Acpi_aml_resolve_object * - * PARAMETERS: *Val_desc - Value to be stored - * *Node - Named object to recieve the value + * PARAMETERS: Source_desc_ptr - Pointer to the source object + * Target_type - Current type of the target + * Walk_state - Current walk state * - * RETURN: Status - * - * DESCRIPTION: Store the object to the named object. - * - * The Assignment of an object to a named object is handled here - * The val passed in will replace the current value (if any) - * with the input value. + * RETURN: Status, resolved object in Source_desc_ptr. * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. - * - * NOTE: the global lock is acquired early. This will result - * in the global lock being held a bit longer. Also, if the - * function fails during set up we may get the lock when we - * don't really need it. I don't think we care. + * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * it and return the actual object in the Source_desc_ptr. * ******************************************************************************/ ACPI_STATUS -acpi_aml_store_object_to_node ( - ACPI_OPERAND_OBJECT *val_desc, - ACPI_NAMESPACE_NODE *node, +acpi_aml_resolve_object ( + ACPI_OPERAND_OBJECT **source_desc_ptr, + OBJECT_TYPE_INTERNAL target_type, ACPI_WALK_STATE *walk_state) { + ACPI_OPERAND_OBJECT *source_desc = *source_desc_ptr; ACPI_STATUS status = AE_OK; - u8 *buffer = NULL; - u32 length = 0; - u32 mask; - u32 new_value; - u8 locked = FALSE; - u8 *location=NULL; - ACPI_OPERAND_OBJECT *dest_desc; - OBJECT_TYPE_INTERNAL destination_type = ACPI_TYPE_ANY; /* - * Assuming the parameters are valid!!! + * Ensure we have a Source that can be stored in the target */ - ACPI_ASSERT((node) && (val_desc)); + switch (target_type) + { - destination_type = acpi_ns_get_type (node); + /* This case handles the "interchangeable" types Integer, String, and Buffer. */ /* - * First ensure we have a value that can be stored in the target + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) */ - switch (destination_type) - { - /* Type of Name's existing value */ - - case INTERNAL_TYPE_ALIAS: - - /* - * Aliases are resolved by Acpi_aml_prep_operands - */ - - status = AE_AML_INTERNAL; - break; - - + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_FIELD_UNIT: case INTERNAL_TYPE_BANK_FIELD: case INTERNAL_TYPE_INDEX_FIELD: - case ACPI_TYPE_FIELD_UNIT: - case ACPI_TYPE_INTEGER: - - /* - * These cases all require only number values or values that - * can be converted to numbers. - * - * If value is not a Number, try to resolve it to one. - */ - - if (val_desc->common.type != ACPI_TYPE_INTEGER) { - /* - * Initially not a number, convert - */ - status = acpi_aml_resolve_to_value (&val_desc, walk_state); - if (ACPI_SUCCESS (status) && - (val_desc->common.type != ACPI_TYPE_INTEGER)) - { - /* - * Conversion successful but still not a number - */ - status = AE_AML_OPERAND_TYPE; - } - } - - break; + /* + * Stores into a Field/Region or into a Buffer/String + * are all essentially the same. + */ case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case INTERNAL_TYPE_DEF_FIELD: /* - * Storing into a Field in a region or into a buffer or into - * a string all is essentially the same. - * - * If value is not a valid type, try to resolve it to one. + * If Source_desc is not a valid type, try to resolve it to one. */ - - if ((val_desc->common.type != ACPI_TYPE_INTEGER) && - (val_desc->common.type != ACPI_TYPE_BUFFER) && - (val_desc->common.type != ACPI_TYPE_STRING)) + if ((source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { /* - * Initially not a valid type, convert + * Initially not a valid type, convert */ - status = acpi_aml_resolve_to_value (&val_desc, walk_state); + status = acpi_aml_resolve_to_value (source_desc_ptr, walk_state); if (ACPI_SUCCESS (status) && - (val_desc->common.type != ACPI_TYPE_INTEGER) && - (val_desc->common.type != ACPI_TYPE_BUFFER) && - (val_desc->common.type != ACPI_TYPE_STRING)) + (source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { /* - * Conversion successful but still not a valid type + * Conversion successful but still not a valid type */ status = AE_AML_OPERAND_TYPE; } @@ -169,347 +114,133 @@ acpi_aml_store_object_to_node ( break; - case ACPI_TYPE_PACKAGE: + case INTERNAL_TYPE_ALIAS: /* - * TBD: [Unhandled] Not real sure what to do here + * Aliases are resolved by Acpi_aml_prep_operands */ - status = AE_NOT_IMPLEMENTED; + status = AE_AML_INTERNAL; break; + case ACPI_TYPE_PACKAGE: default: /* - * All other types than Alias and the various Fields come here. - * Store Val_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * Val_desc reference count is incremented by Attach_object. + * All other types than Alias and the various Fields come here, + * including the untyped case - ACPI_TYPE_ANY. */ - - status = acpi_ns_attach_object (node, val_desc, val_desc->common.type); - - goto clean_up_and_bail_out; break; } - /* Exit now if failure above */ + return (status); +} + - if (ACPI_FAILURE (status)) { - goto clean_up_and_bail_out; - } +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object + * + * PARAMETERS: Source_desc - Object to store + * Target_type - Current type of the target + * Target_desc_ptr - Pointer to the target + * Walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object to another object. This may include + * converting the source type to the target type (implicit + * conversion), and a copy of the value of the source to + * the target. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object ( + ACPI_OPERAND_OBJECT *source_desc, + OBJECT_TYPE_INTERNAL target_type, + ACPI_OPERAND_OBJECT **target_desc_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *target_desc = *target_desc_ptr; + ACPI_STATUS status; - /* - * Get descriptor for object attached to Node - */ - dest_desc = acpi_ns_get_attached_object (node); - if (!dest_desc) { - /* - * There is no existing object attached to this Node - */ - status = AE_AML_INTERNAL; - goto clean_up_and_bail_out; - } /* - * Make sure the destination Object is the same as the Node + * Perform the "implicit conversion" of the source to the current type + * of the target - As per the ACPI specification. + * + * If no conversion performed, Source_desc is left alone, otherwise it + * is updated with a new object. */ - if (dest_desc->common.type != (u8) destination_type) { - status = AE_AML_INTERNAL; - goto clean_up_and_bail_out; + status = acpi_aml_convert_to_target_type (target_type, &source_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); } + /* - * Acpi_everything is ready to execute now, We have - * a value we can handle, just perform the update + * We now have two objects of identical types, and we can perform a + * copy of the *value* of the source object. */ - - switch (destination_type) + switch (target_type) { - /* Type of Name's existing value */ - - case INTERNAL_TYPE_BANK_FIELD: - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (dest_desc->bank_field.lock_rule); + case ACPI_TYPE_ANY: + case INTERNAL_TYPE_DEF_ANY: /* - * Set Bank value to select proper Bank - * Perform the update (Set Bank Select) + * The target namespace node is uninitialized (has no target object), + * and will take on the type of the source object */ - status = acpi_aml_access_named_field (ACPI_WRITE, - dest_desc->bank_field.bank_select, - &dest_desc->bank_field.value, - sizeof (dest_desc->bank_field.value)); - if (ACPI_SUCCESS (status)) { - /* Set bank select successful, set data value */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - dest_desc->bank_field.bank_select, - &val_desc->bank_field.value, - sizeof (val_desc->bank_field.value)); - } - + *target_desc_ptr = source_desc; break; - case INTERNAL_TYPE_DEF_FIELD: - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (val_desc->field.lock_rule); - - /* - * Perform the update - */ - - switch (val_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &val_desc->integer.value; - length = sizeof (val_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) val_desc->buffer.pointer; - length = val_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) val_desc->string.pointer; - length = val_desc->string.length; - break; - } - - status = acpi_aml_access_named_field (ACPI_WRITE, - node, buffer, length); - - break; /* Global Lock released below */ - - - case ACPI_TYPE_STRING: - - /* - * Perform the update - */ - - switch (val_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &val_desc->integer.value; - length = sizeof (val_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) val_desc->buffer.pointer; - length = val_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) val_desc->string.pointer; - length = val_desc->string.length; - break; - } + case ACPI_TYPE_INTEGER: - /* - * Setting a string value replaces the old string - */ + target_desc->integer.value = source_desc->integer.value; - if (length < dest_desc->string.length) { - /* - * Zero fill, not willing to do pointer arithmetic for - * archetecture independance. Just clear the whole thing - */ - MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length); - MEMCPY(dest_desc->string.pointer, buffer, length); - } - else { - /* - * Free the current buffer, then allocate a buffer - * large enough to hold the value - */ - if ( dest_desc->string.pointer && - !acpi_tb_system_table_pointer (dest_desc->string.pointer)) - { - /* - * Only free if not a pointer into the DSDT - */ + /* Truncate value if we are executing from a 32-bit ACPI table */ - acpi_cm_free(dest_desc->string.pointer); - } + acpi_aml_truncate_for32bit_table (target_desc, walk_state); + break; - dest_desc->string.pointer = acpi_cm_allocate (length + 1); - dest_desc->string.length = length; - if (!dest_desc->string.pointer) { - status = AE_NO_MEMORY; - goto clean_up_and_bail_out; - } + case ACPI_TYPE_FIELD_UNIT: - MEMCPY(dest_desc->string.pointer, buffer, length); - } + status = acpi_aml_copy_integer_to_field_unit (source_desc, target_desc); break; - case ACPI_TYPE_BUFFER: - - /* - * Perform the update to the buffer - */ - - switch (val_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &val_desc->integer.value; - length = sizeof (val_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) val_desc->buffer.pointer; - length = val_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) val_desc->string.pointer; - length = val_desc->string.length; - break; - } + case INTERNAL_TYPE_BANK_FIELD: - /* - * Buffer is a static allocation, - * only place what will fit in the buffer. - */ - if (length <= dest_desc->buffer.length) { - /* - * Zero fill first, not willing to do pointer arithmetic for - * archetecture independence. Just clear the whole thing - */ - MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length); - MEMCPY(dest_desc->buffer.pointer, buffer, length); - } - else { - /* - * truncate, copy only what will fit - */ - MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length); - } + status = acpi_aml_copy_integer_to_bank_field (source_desc, target_desc); break; case INTERNAL_TYPE_INDEX_FIELD: - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (dest_desc->index_field.lock_rule); - - /* - * Set Index value to select proper Data register - * perform the update (Set index) - */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - dest_desc->index_field.index, - &dest_desc->index_field.value, - sizeof (dest_desc->index_field.value)); - - if (ACPI_SUCCESS (status)) { - /* set index successful, next set Data value */ - - status = acpi_aml_access_named_field (ACPI_WRITE, - dest_desc->index_field.data, - &val_desc->integer.value, - sizeof (val_desc->integer.value)); - } + status = acpi_aml_copy_integer_to_index_field (source_desc, target_desc); break; - case ACPI_TYPE_FIELD_UNIT: - - - /* - * If the Field Buffer and Index have not been previously evaluated, - * evaluate them and save the results. - */ - if (!(dest_desc->common.flags & AOPOBJ_DATA_VALID)) { - status = acpi_ds_get_field_unit_arguments (dest_desc); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - if ((!dest_desc->field_unit.container || - ACPI_TYPE_BUFFER != dest_desc->field_unit.container->common.type)) - { - status = AE_AML_INTERNAL; - goto clean_up_and_bail_out; - } - - /* - * Get the global lock if needed - */ - locked = acpi_aml_acquire_global_lock (dest_desc->field_unit.lock_rule); - - /* - * TBD: [Unhandled] REMOVE this limitation - * Make sure the operation is within the limits of our implementation - * this is not a Spec limitation!! - */ - if (dest_desc->field_unit.length + dest_desc->field_unit.bit_offset > 32) { - status = AE_NOT_IMPLEMENTED; - goto clean_up_and_bail_out; - } - - /* Field location is (base of buffer) + (byte offset) */ - - location = dest_desc->field_unit.container->buffer.pointer - + dest_desc->field_unit.offset; - - /* - * Construct Mask with 1 bits where the field is, - * 0 bits elsewhere - */ - mask = ((u32) 1 << dest_desc->field_unit.length) - ((u32)1 - << dest_desc->field_unit.bit_offset); - - /* Zero out the field in the buffer */ - - MOVE_UNALIGNED32_TO_32 (&new_value, location); - new_value &= ~mask; - - /* - * Shift and mask the new value into position, - * and or it into the buffer. - */ - new_value |= (val_desc->integer.value << dest_desc->field_unit.bit_offset) & - mask; - - /* Store back the value */ - - MOVE_UNALIGNED32_TO_32 (location, &new_value); + case ACPI_TYPE_STRING: + status = acpi_aml_copy_string_to_string (source_desc, target_desc); break; - case ACPI_TYPE_INTEGER: - - - dest_desc->integer.value = val_desc->integer.value; - - /* Truncate value if we are executing from a 32-bit ACPI table */ + case ACPI_TYPE_BUFFER: - acpi_aml_truncate_for32bit_table (dest_desc, walk_state); + status = acpi_aml_copy_buffer_to_buffer (source_desc, target_desc); break; case ACPI_TYPE_PACKAGE: /* - * TBD: [Unhandled] Not real sure what to do here + * TBD: [Unhandled] Not real sure what to do here */ status = AE_NOT_IMPLEMENTED; break; @@ -518,24 +249,13 @@ acpi_aml_store_object_to_node ( default: /* - * All other types than Alias and the various Fields come here. - * Store Val_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * Val_desc reference count is incremented by Attach_object. + * All other types come here. */ - status = AE_NOT_IMPLEMENTED; break; } -clean_up_and_bail_out: - - /* - * Release global lock if we acquired it earlier - */ - acpi_aml_release_global_lock (locked); - return (status); } diff --git a/drivers/acpi/interpreter/amstorob.c b/drivers/acpi/interpreter/amstorob.c index f4f26d07f10e..8118f08bd5e7 100644 --- a/drivers/acpi/interpreter/amstorob.c +++ b/drivers/acpi/interpreter/amstorob.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: amstorob - AML Interpreter object store support, store to object - * $Revision: 20 $ + * $Revision: 22 $ * *****************************************************************************/ @@ -40,281 +40,383 @@ /******************************************************************************* * - * FUNCTION: Acpi_aml_store_object_to_object + * FUNCTION: Acpi_aml_copy_buffer_to_buffer * - * PARAMETERS: *Val_desc - Value to be stored - * *Dest_desc - Object to receive the value + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy * * RETURN: Status * - * DESCRIPTION: Store an object to another object. + * DESCRIPTION: Copy a buffer object to another buffer object. * - * The Assignment of an object to another (not named) object - * is handled here. - * The val passed in will replace the current value (if any) - * with the input value. + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_buffer_to_buffer ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + u32 length; + u8 *buffer; + + /* + * We know that Source_desc is a buffer by now + */ + buffer = (u8 *) source_desc->buffer.pointer; + length = source_desc->buffer.length; + + /* + * Buffer is a static allocation, + * only place what will fit in the buffer. + */ + if (length <= target_desc->buffer.length) { + /* Clear existing buffer and copy in the new one */ + + MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length); + MEMCPY(target_desc->buffer.pointer, buffer, length); + } + + else { + /* + * Truncate the source, copy only what will fit + */ + MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length); + + } + + return (AE_OK); +} + + +/******************************************************************************* * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. + * FUNCTION: Acpi_aml_copy_string_to_string + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status * - * This module allows destination types of Number, String, - * and Buffer. + * DESCRIPTION: Copy a String object to another String object * ******************************************************************************/ ACPI_STATUS -acpi_aml_store_object_to_object ( - ACPI_OPERAND_OBJECT *val_desc, - ACPI_OPERAND_OBJECT *dest_desc, - ACPI_WALK_STATE *walk_state) +acpi_aml_copy_string_to_string ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) { - ACPI_STATUS status = AE_OK; - u8 *buffer = NULL; - u32 length = 0; - OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type; + u32 length; + u8 *buffer; /* - * Assuming the parameters are valid!!! + * We know that Source_desc is a string by now. */ - ACPI_ASSERT((dest_desc) && (val_desc)); + buffer = (u8 *) source_desc->string.pointer; + length = source_desc->string.length; /* - * First ensure we have a value that can be stored in the target + * Setting a string value replaces the old string */ - switch (destination_type) - { - /* Type of Name's existing value */ + if (length < target_desc->string.length) { + /* Clear old string and copy in the new one */ - case ACPI_TYPE_INTEGER: + MEMSET(target_desc->string.pointer, 0, target_desc->string.length); + MEMCPY(target_desc->string.pointer, buffer, length); + } + else { /* - * These cases all require only number values or values that - * can be converted to numbers. - * - * If value is not a Number, try to resolve it to one. + * Free the current buffer, then allocate a buffer + * large enough to hold the value */ - - if (val_desc->common.type != ACPI_TYPE_INTEGER) { + if (target_desc->string.pointer && + !acpi_tb_system_table_pointer (target_desc->string.pointer)) + { /* - * Initially not a number, convert + * Only free if not a pointer into the DSDT */ - status = acpi_aml_resolve_to_value (&val_desc, walk_state); - if (ACPI_SUCCESS (status) && - (val_desc->common.type != ACPI_TYPE_INTEGER)) - { - /* - * Conversion successful but still not a number - */ - status = AE_AML_OPERAND_TYPE; - } + acpi_cm_free(target_desc->string.pointer); } - break; + target_desc->string.pointer = acpi_cm_allocate (length + 1); + target_desc->string.length = length; - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: + if (!target_desc->string.pointer) { + return (AE_NO_MEMORY); + } - /* - * Storing into a Field in a region or into a buffer or into - * a string all is essentially the same. - * - * If value is not a valid type, try to resolve it to one. - */ + MEMCPY(target_desc->string.pointer, buffer, length); + } - if ((val_desc->common.type != ACPI_TYPE_INTEGER) && - (val_desc->common.type != ACPI_TYPE_BUFFER) && - (val_desc->common.type != ACPI_TYPE_STRING)) - { - /* - * Initially not a valid type, convert - */ - status = acpi_aml_resolve_to_value (&val_desc, walk_state); - if (ACPI_SUCCESS (status) && - (val_desc->common.type != ACPI_TYPE_INTEGER) && - (val_desc->common.type != ACPI_TYPE_BUFFER) && - (val_desc->common.type != ACPI_TYPE_STRING)) - { - /* - * Conversion successful but still not a valid type - */ - status = AE_AML_OPERAND_TYPE; - } - } - break; + return (AE_OK); +} - default: +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_index_field + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to an Index Field + * + ******************************************************************************/ - /* - * TBD: [Unhandled] What other combinations must be implemented? - */ - status = AE_NOT_IMPLEMENTED; - break; - } +ACPI_STATUS +acpi_aml_copy_integer_to_index_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); - /* Exit now if failure above */ + /* + * Set Index value to select proper Data register + * perform the update (Set index) + */ + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->index_field.index, + &target_desc->index_field.value, + sizeof (target_desc->index_field.value)); + if (ACPI_SUCCESS (status)) { + /* Set_index was successful, next set Data value */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->index_field.data, + &source_desc->integer.value, + sizeof (source_desc->integer.value)); - if (ACPI_FAILURE (status)) { - goto clean_up_and_bail_out; } + + /* - * Acpi_everything is ready to execute now, We have - * a value we can handle, just perform the update + * Release global lock if we acquired it earlier */ + acpi_aml_release_global_lock (locked); - switch (destination_type) - { + return (status); +} - case ACPI_TYPE_STRING: - /* - * Perform the update - */ +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_bank_field + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to a Bank Field + * + ******************************************************************************/ - switch (val_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &val_desc->integer.value; - length = sizeof (val_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) val_desc->buffer.pointer; - length = val_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) val_desc->string.pointer; - length = val_desc->string.length; - break; - } +ACPI_STATUS +acpi_aml_copy_integer_to_bank_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status; + u8 locked; - /* - * Setting a string value replaces the old string - */ - if (length < dest_desc->string.length) { - /* - * Zero fill, not willing to do pointer arithmetic for - * architecture independence. Just clear the whole thing - */ - MEMSET(dest_desc->string.pointer, 0, dest_desc->string.length); - MEMCPY(dest_desc->string.pointer, buffer, length); - } - else { - /* - * Free the current buffer, then allocate a buffer - * large enough to hold the value - */ - if ( dest_desc->string.pointer && - !acpi_tb_system_table_pointer (dest_desc->string.pointer)) - { - /* - * Only free if not a pointer into the DSDT - */ + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); - acpi_cm_free(dest_desc->string.pointer); - } - dest_desc->string.pointer = acpi_cm_allocate (length + 1); - dest_desc->string.length = length; + /* + * Set Bank value to select proper Bank + * Perform the update (Set Bank Select) + */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->bank_field.bank_select, + &target_desc->bank_field.value, + sizeof (target_desc->bank_field.value)); + if (ACPI_SUCCESS (status)) { + /* Set bank select successful, set data value */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->bank_field.bank_select, + &source_desc->bank_field.value, + sizeof (source_desc->bank_field.value)); + } - if (!dest_desc->string.pointer) { - status = AE_NO_MEMORY; - goto clean_up_and_bail_out; - } - MEMCPY(dest_desc->string.pointer, buffer, length); - } - break; + /* + * Release global lock if we acquired it earlier + */ + acpi_aml_release_global_lock (locked); - case ACPI_TYPE_BUFFER: + return (status); +} - /* - * Perform the update to the buffer - */ - switch (val_desc->common.type) - { - case ACPI_TYPE_INTEGER: - buffer = (u8 *) &val_desc->integer.value; - length = sizeof (val_desc->integer.value); - break; - - case ACPI_TYPE_BUFFER: - buffer = (u8 *) val_desc->buffer.pointer; - length = val_desc->buffer.length; - break; - - case ACPI_TYPE_STRING: - buffer = (u8 *) val_desc->string.pointer; - length = val_desc->string.length; - break; - } +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_data_to_named_field + * + * PARAMETERS: Source_desc - Source object to copy + * Node - Destination Namespace node + * + * RETURN: Status + * + * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion + * is performed on the source object + * + ******************************************************************************/ - /* - * If the buffer is uninitialized, - * memory needs to be allocated for the copy. - */ - if(0 == dest_desc->buffer.length) { - dest_desc->buffer.pointer = acpi_cm_callocate(length); - dest_desc->buffer.length = length; - - if (!dest_desc->buffer.pointer) { - status = AE_NO_MEMORY; - goto clean_up_and_bail_out; - } - } +ACPI_STATUS +acpi_aml_copy_data_to_named_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node) +{ + ACPI_STATUS status; + u8 locked; + u32 length; + u8 *buffer; - /* - * Buffer is a static allocation, - * only place what will fit in the buffer. - */ - if (length <= dest_desc->buffer.length) { - /* - * Zero fill first, not willing to do pointer arithmetic for - * architecture independence. Just clear the whole thing - */ - MEMSET(dest_desc->buffer.pointer, 0, dest_desc->buffer.length); - MEMCPY(dest_desc->buffer.pointer, buffer, length); - } - else { - /* - * truncate, copy only what will fit - */ - MEMCPY(dest_desc->buffer.pointer, buffer, dest_desc->buffer.length); - } - break; + /* + * Named fields (Create_xxx_field) - We don't perform any conversions on the + * source operand, just use the raw data + */ + switch (source_desc->common.type) + { case ACPI_TYPE_INTEGER: + buffer = (u8 *) &source_desc->integer.value; + length = sizeof (source_desc->integer.value); + break; - dest_desc->integer.value = val_desc->integer.value; - - /* Truncate value if we are executing from a 32-bit ACPI table */ + case ACPI_TYPE_BUFFER: + buffer = (u8 *) source_desc->buffer.pointer; + length = source_desc->buffer.length; + break; - acpi_aml_truncate_for32bit_table (dest_desc, walk_state); + case ACPI_TYPE_STRING: + buffer = (u8 *) source_desc->string.pointer; + length = source_desc->string.length; break; default: + return (AE_TYPE); + } - /* - * All other types than Alias and the various Fields come here. - * Store Val_desc as the new value of the Name, and set - * the Name's type to that of the value being stored in it. - * Val_desc reference count is incremented by Attach_object. - */ + /* + * Get the global lock if needed before the update + * TBD: not needed! + */ + locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule); - status = AE_NOT_IMPLEMENTED; - break; - } + status = acpi_aml_access_named_field (ACPI_WRITE, + node, buffer, length); -clean_up_and_bail_out: + acpi_aml_release_global_lock (locked); return (status); } + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_field_unit + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to a Field Unit. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_integer_to_field_unit ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status = AE_OK; + u8 *location = NULL; + u32 mask; + u32 new_value; + u8 locked = FALSE; + + + /* + * If the Field Buffer and Index have not been previously evaluated, + * evaluate them and save the results. + */ + if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_field_unit_arguments (target_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + if ((!target_desc->field_unit.container || + ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type)) + { + return (AE_AML_INTERNAL); + } + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule); + + /* + * TBD: [Unhandled] REMOVE this limitation + * Make sure the operation is within the limits of our implementation + * this is not a Spec limitation!! + */ + if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) { + return (AE_NOT_IMPLEMENTED); + } + + /* Field location is (base of buffer) + (byte offset) */ + + location = target_desc->field_unit.container->buffer.pointer + + target_desc->field_unit.offset; + + /* + * Construct Mask with 1 bits where the field is, + * 0 bits elsewhere + */ + mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1 + << target_desc->field_unit.bit_offset); + + /* Zero out the field in the buffer */ + + MOVE_UNALIGNED32_TO_32 (&new_value, location); + new_value &= ~mask; + + /* + * Shift and mask the new value into position, + * and or it into the buffer. + */ + new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) & + mask; + + /* Store back the value */ + + MOVE_UNALIGNED32_TO_32 (location, &new_value); + + return (AE_OK); +} + + diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 6a9336c7141b..7a29e75426a6 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: nssearch - Namespace search - * $Revision: 63 $ + * $Revision: 64 $ * ******************************************************************************/ @@ -70,8 +70,6 @@ acpi_ns_search_node ( ACPI_NAMESPACE_NODE *next_node; - - /* * Search for name in this table, which is to say that we must search * for the name among the children of this object diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index f795fbba65ab..11457b33f369 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -2,7 +2,7 @@ * * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing * parents and siblings and Scope manipulation - * $Revision: 76 $ + * $Revision: 77 $ * *****************************************************************************/ diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index dc6fcaee8964..7373013da9ea 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 73 $ + * $Revision: 74 $ * *****************************************************************************/ @@ -537,7 +537,9 @@ acpi_ps_parse_loop ( */ status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE); - if (ACPI_FAILURE (status)) { + if (ACPI_FAILURE (status) && + ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) + { return (status); } diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 296ddb1047a1..328c755d9867 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psxface - Parser external interfaces - * $Revision: 39 $ + * $Revision: 40 $ * *****************************************************************************/ @@ -121,6 +121,12 @@ acpi_psx_execute ( return (AE_NO_MEMORY); } + + /* Init new op with the method name and pointer back to the NS node */ + + acpi_ps_set_name (op, method_node->name); + op->node = method_node; + /* * The walk of the parse tree is where we actually execute the method */ diff --git a/drivers/acpi/sys.c b/drivers/acpi/sys.c index 09781f97732d..2011174a1ec6 100644 --- a/drivers/acpi/sys.c +++ b/drivers/acpi/sys.c @@ -27,18 +27,13 @@ #define _COMPONENT OS_DEPENDENT MODULE_NAME ("sys") -#define ACPI_SLP_TYP(typa, typb) (((int)(typa) << 8) | (int)(typb)) -#define ACPI_SLP_TYPA(value) ((value) >> 8) -#define ACPI_SLP_TYPB(value) ((value) & 0xff) - struct acpi_enter_sx_ctx { wait_queue_head_t wait; unsigned int state; }; -volatile acpi_sstate_t acpi_sleep_state = ACPI_S0; -static unsigned long acpi_slptyp[ACPI_S5 + 1] = {ACPI_INVALID,}; +volatile acpi_sstate_t acpi_sleep_state = ACPI_STATE_S0; /* * Enter system sleep state @@ -50,44 +45,20 @@ acpi_enter_sx_async(void *context) ACPI_OBJECT_LIST arg_list; ACPI_OBJECT arg; - /* - * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. - */ - - // run the _PTS method - memset(&arg_list, 0, sizeof(arg_list)); - arg_list.count = 1; - arg_list.pointer = &arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = ctx->state; + acpi_enter_sleep_state(ctx->state); - acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); - - // clear wake status by writing a 1 - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); - - acpi_sleep_state = ctx->state; - - // set ACPI_SLP_TYPA/b and ACPI_SLP_EN - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_A, - ACPI_SLP_TYPA(acpi_slptyp[ctx->state])); - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_TYPE_B, - ACPI_SLP_TYPB(acpi_slptyp[ctx->state])); - acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, SLP_EN, 1); - - if (ctx->state != ACPI_S1) { - /* we should have just shut off - what are we doing here? */ - printk(KERN_ERR "ACPI: S%d failed\n", ctx->state); + /* either we are in S1, or the transition failed, as the other states resume + from the waking vector */ + if (ctx->state != ACPI_STATE_S1) { + printk(KERN_ERR "Could not enter S%d\n", ctx->state); goto out; } - // wait until S1 is entered + /* wait until S1 is entered */ while (!(acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) safe_halt(); - // run the _WAK method + /* run the _WAK method */ memset(&arg_list, 0, sizeof(arg_list)); arg_list.count = 1; arg_list.pointer = &arg; @@ -99,7 +70,7 @@ acpi_enter_sx_async(void *context) acpi_evaluate_object(NULL, "\\_WAK", &arg_list, NULL); out: - acpi_sleep_state = ACPI_S0; + acpi_sleep_state = ACPI_STATE_S0; if (waitqueue_active(&ctx->wait)) wake_up_interruptible(&ctx->wait); @@ -112,13 +83,9 @@ static void acpi_power_off(void) { struct acpi_enter_sx_ctx ctx; - - if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0) - || acpi_slptyp[ACPI_S5] == ACPI_INVALID) - return; init_waitqueue_head(&ctx.wait); - ctx.state = ACPI_S5; + ctx.state = ACPI_STATE_S5; acpi_enter_sx_async(&ctx); } @@ -132,10 +99,6 @@ acpi_enter_sx(acpi_sstate_t state) DECLARE_WAITQUEUE(wait, current); int ret = 0; - if ((STRNCMP(acpi_fadt.header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0) - || acpi_slptyp[state] == ACPI_INVALID) - return -EINVAL; - init_waitqueue_head(&ctx.wait); ctx.state = state; @@ -166,19 +129,14 @@ acpi_sys_init(void) printk(KERN_INFO "ACPI: System firmware supports:"); - for (sx = ACPI_S0; sx <= ACPI_S5; sx++) { - int ca_sx = (sx <= ACPI_S4) ? sx : (sx + 1); + for (sx = ACPI_STATE_S0; sx <= ACPI_STATE_S5; sx++) { if (ACPI_SUCCESS( - acpi_hw_obtain_sleep_type_register_data(ca_sx, + acpi_hw_obtain_sleep_type_register_data(sx, &type_a, &type_b))) { - acpi_slptyp[sx] = ACPI_SLP_TYP(type_a, type_b); printk(" S%d", sx); } - else { - acpi_slptyp[sx] = ACPI_INVALID; - } } printk("\n"); diff --git a/drivers/acpi/table.c b/drivers/acpi/table.c index 8379b4204d44..de0f99a275a9 100644 --- a/drivers/acpi/table.c +++ b/drivers/acpi/table.c @@ -47,21 +47,6 @@ acpi_fetch_fadt(void) return -ENODEV; } - if (acpi_fadt.plvl2_lat - && acpi_fadt.plvl2_lat <= ACPI_MAX_P_LVL2_LAT) { - acpi_c2_exit_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat); - acpi_c2_enter_latency - = ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000); - } - if (acpi_fadt.plvl3_lat - && acpi_fadt.plvl3_lat <= ACPI_MAX_P_LVL3_LAT) { - acpi_c3_exit_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat); - acpi_c3_enter_latency - = ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5); - } - return 0; } @@ -71,11 +56,7 @@ acpi_fetch_fadt(void) int acpi_find_and_load_tables(u64 rsdp) { - if (ACPI_SUCCESS(acpi_load_tables(rsdp))) - { - printk(KERN_INFO "ACPI: System description tables loaded\n"); - } - else { + if (!ACPI_SUCCESS(acpi_load_tables(rsdp))) { printk(KERN_INFO "ACPI: System description table load failed\n"); acpi_terminate(); return -1; diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 9984bcadb754..76d7fff15c47 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -312,11 +312,11 @@ acpi_tb_convert_table_fadt (void) /* No 0.71 equivalence. Leave pre-zeroed. */ /* FADT2->Flush_stride = 0; */ - /* Processor’s duty cycle index in processor's P_CNT reg*/ + /* Processor's duty cycle index in processor's P_CNT reg*/ /* No 0.71 equivalence. Leave pre-zeroed. */ /* FADT2->Duty_offset = 0; */ - /* Processor’s duty cycle value bit width in P_CNT register.*/ + /* Processor's duty cycle value bit width in P_CNT register.*/ /* No 0.71 equivalence. Leave pre-zeroed. */ /* FADT2->Duty_width = 0; */ diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 7b7a6f2066b6..836a89f1e3ed 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -39,8 +39,6 @@ extern int mac_floppy_init(void); #endif -extern int lvm_init(void); - /* * For the allocated request tables */ @@ -1120,12 +1118,25 @@ sorry: extern int stram_device_init (void); #endif -/* - * First step of what used to be end_request + +/** + * end_that_request_first - end I/O on one buffer. + * @req: the request being processed + * @uptodate: 0 for I/O error + * @name: the name printed for an I/O error * - * 0 means continue with end_that_request_last, - * 1 means we are done - */ + * Description: + * Ends I/O on the first buffer attached to @req, and sets it up + * for the next buffer_head (if any) in the cluster. + * + * Return: + * 0 - we are done with this request, call end_that_request_last() + * 1 - still buffers pending for this request + * + * Caveat: + * Drivers implementing their own end_request handling must call + * blk_finished_io() appropriately. + **/ int end_that_request_first (struct request *req, int uptodate, char *name) { @@ -1198,17 +1209,10 @@ int __init blk_dev_init(void) * use half of RAM */ high_queued_sectors = (total_ram * 2) / 3; - low_queued_sectors = high_queued_sectors - MB(128); - if (low_queued_sectors < 0) - low_queued_sectors = total_ram / 2; - - /* - * for big RAM machines (>= 384MB), use more for I/O - */ - if (total_ram >= MB(384)) { - high_queued_sectors = (total_ram * 4) / 5; + low_queued_sectors = high_queued_sectors / 3; + if (high_queued_sectors - low_queued_sectors > MB(128)) low_queued_sectors = high_queued_sectors - MB(128); - } + /* * make it sectors (512b) @@ -1336,9 +1340,6 @@ int __init blk_dev_init(void) #endif #ifdef CONFIG_SUN_JSFLASH jsfd_init(); -#endif -#ifdef CONFIG_BLK_DEV_LVM - lvm_init(); #endif return 0; }; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 1e555da55a80..cafe72afd32c 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -295,11 +295,11 @@ MODULE_PARM(check_media_type, "i"); /* These are used to simplify getting data in from and back to user land */ #define IOCTL_IN(arg, type, in) \ - if (copy_from_user(&in, (type *) arg, sizeof in)) \ + if (copy_from_user(&(in), (type *) (arg), sizeof (in))) \ return -EFAULT; #define IOCTL_OUT(arg, type, out) \ - if (copy_to_user((type *) arg, &out, sizeof out)) \ + if (copy_to_user((type *) (arg), &(out), sizeof (out))) \ return -EFAULT; /* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c index 942142832282..ccd53dacce7b 100644 --- a/drivers/char/agp/agpgart_be.c +++ b/drivers/char/agp/agpgart_be.c @@ -1384,9 +1384,11 @@ static void via_cleanup(void) aper_size_info_8 *previous_size; previous_size = A_SIZE_8(agp_bridge.previous_size); - pci_write_config_dword(agp_bridge.dev, VIA_ATTBASE, 0); pci_write_config_byte(agp_bridge.dev, VIA_APSIZE, previous_size->size_value); + /* Do not disable by writing 0 to VIA_ATTBASE, it screws things up + * during reinitialization. + */ } static void via_tlbflush(agp_memory * mem) @@ -2373,9 +2375,10 @@ static int __init agp_find_supported_device(void) if (i810_dev == NULL) { printk(KERN_ERR PFX "agpgart: Detected an " "Intel i815, but could not find the" - " secondary device.\n"); - agp_bridge.type = NOT_SUPPORTED; - return -ENODEV; + " secondary device.\n" + "Assuming user has added an external AGP" + " card\n"); + break; } printk(KERN_INFO PFX "agpgart: Detected an Intel i815 " "Chipset.\n"); diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c index c79d113a79e4..857b32a7efd9 100644 --- a/drivers/i2o/i2o_block.c +++ b/drivers/i2o/i2o_block.c @@ -420,17 +420,12 @@ static int i2ob_merge_requests(request_queue_t *q, { int max_segments = i2ob_dev[MINOR(req->rq_dev)].max_segments; int total_segments = req->nr_segments + next->nr_segments; - int same_segment; if (__max_segments < max_segments) max_segments = __max_segments; - same_segment = 0; if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) - { total_segments--; - same_segment = 1; - } if (total_segments > max_segments) return 0; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 3a6a9e8d94f9..433951e955a7 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -288,6 +288,9 @@ * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't * correctly sensing a disc change. * - Rearranged some code + * - Use extended sense on drives that support it for + * correctly reporting tray status -- from + * Michael D Johnson * *************************************************************************/ @@ -759,16 +762,13 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, * changed 5 parameters to 3 for dvd-ram * struct packet_command *pc; now packet_command_t *pc; */ -#undef CLASSIC_PACKET_STRUCT static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct packet_command *pc, ide_handler_t *handler) { -#ifdef CLASSIC_PACKET_STRUCT unsigned char *cmd_buf = pc->c; int cmd_len = sizeof(pc->c); unsigned int timeout = pc->timeout; -#endif ide_startstop_t startstop; if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { @@ -786,22 +786,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, } /* Arm the interrupt handler. */ -#ifdef CLASSIC_PACKET_STRUCT - /* Arm the interrupt handler. */ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len); -#else /* !CLASSIC_PACKET_STRUCT */ - /* Arm the interrupt handler. */ -// ide_set_handler (drive, handler, (unsigned int) pc->timeout, cdrom_timer_expiry); - ide_set_handler (drive, handler, pc->timeout, cdrom_timer_expiry); - - /* Send the command to the device. */ -// atapi_output_bytes (drive, (void *)pc->c, (unsigned int) sizeof(pc->c)); - atapi_output_bytes (drive, pc->c, sizeof(pc->c)); -#endif /* CLASSIC_PACKET_STRUCT */ - return ide_started; } @@ -1884,9 +1872,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) If it is, just return. */ (void) cdrom_check_status(drive, sense); - if (CDROM_STATE_FLAGS(drive)->toc_valid) - return 0; - /* First read just the header, so we know how long the TOC is. */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, sizeof(struct atapi_toc_header), sense); @@ -2324,11 +2309,17 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) sense.ascq == 0x04) return CDS_DISC_OK; + + /* + * If not using Mt Fuji extended media tray reports, + * just return TRAY_OPEN since ATAPI doesn't provide + * any other way to detect this... + */ if (sense.sense_key == NOT_READY) { - /* ATAPI doesn't have anything that can help - us decide whether the drive is really - emtpy or the tray is just open. irk. */ - return CDS_TRAY_OPEN; + if (sense.asc == 0x3a && (!sense.ascq||sense.ascq == 1)) + return CDS_NO_DISC; + else + return CDS_TRAY_OPEN; } return CDS_DRIVE_NOT_READY; @@ -2597,7 +2588,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram) printk (" DVD%s%s", (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", - (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : ""); + (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "-RAM" : ""); if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) printk (" CD%s%s", diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 0b60e89b3d90..6d0366cf268d 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1708,8 +1708,8 @@ int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard * } static struct pci_device_id hisax_pci_tbl[] __initdata = { -#ifdef CONFIG_HISAX_FRTIZPCI - {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_FRITZ, PCI_ANY_ID, PCI_ANY_ID}, +#ifdef CONFIG_HISAX_FRITZPCI + {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, #endif #ifdef CONFIG_HISAX_DIEHLDIVA {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, diff --git a/drivers/md/Config.in b/drivers/md/Config.in index 565055a68faa..30438c77fd3c 100644 --- a/drivers/md/Config.in +++ b/drivers/md/Config.in @@ -11,12 +11,7 @@ dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD -if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then - bool ' Boot support' CONFIG_MD_BOOT - bool ' Auto Detect support' CONFIG_AUTODETECT_RAID -fi dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD -dep_mbool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS $CONFIG_BLK_DEV_LVM endmenu diff --git a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c index 980694ee32df..e28ffdbe9449 100644 --- a/drivers/md/lvm-snap.c +++ b/drivers/md/lvm-snap.c @@ -21,6 +21,14 @@ * */ +/* + * Changelog + * + * 05/07/2000 - implemented persistent snapshot support + * 23/11/2000 - used cpu_to_le64 rather than my own macro + * + */ + #include #include #include @@ -30,7 +38,9 @@ #include -static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9 snapshot code (13/11/2000)\n"; +#include "lvm-snap.h" + +static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.9.1_beta2 snapshot code (18/01/2001)\n"; extern const char *const lvm_name; extern int lvm_blocksizes[]; @@ -214,10 +224,10 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) memset(lv_COW_table, 0, blksize_snap); for ( ; is < lv_snap->lv_remap_ptr; is++, id++) { /* store new COW_table entry */ - lv_COW_table[id].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org)); - lv_COW_table[id].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_org); - lv_COW_table[id].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new)); - lv_COW_table[id].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[is].rsector_new); + lv_COW_table[id].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_org)); + lv_COW_table[id].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_org); + lv_COW_table[id].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[is].rdev_new)); + lv_COW_table[id].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[is].rsector_new); } } @@ -227,8 +237,7 @@ void lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) * */ -int lvm_write_COW_table_block(vg_t * vg, - lv_t * lv_snap) +int lvm_write_COW_table_block(vg_t * vg, lv_t * lv_snap) { int blksize_snap; int end_of_table; @@ -268,10 +277,10 @@ int lvm_write_COW_table_block(vg_t * vg, blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10); /* store new COW_table entry */ - lv_COW_table[idx_COW_table].pv_org_number = LVM_TO_DISK64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org)); - lv_COW_table[idx_COW_table].pv_org_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_org); - lv_COW_table[idx_COW_table].pv_snap_number = LVM_TO_DISK64(lvm_pv_get_number(vg, snap_phys_dev)); - lv_COW_table[idx_COW_table].pv_snap_rsector = LVM_TO_DISK64(lv_snap->lv_block_exception[idx].rsector_new); + lv_COW_table[idx_COW_table].pv_org_number = cpu_to_le64(lvm_pv_get_number(vg, lv_snap->lv_block_exception[idx].rdev_org)); + lv_COW_table[idx_COW_table].pv_org_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_org); + lv_COW_table[idx_COW_table].pv_snap_number = cpu_to_le64(lvm_pv_get_number(vg, snap_phys_dev)); + lv_COW_table[idx_COW_table].pv_snap_rsector = cpu_to_le64(lv_snap->lv_block_exception[idx].rsector_new); length_tmp = iobuf->length; iobuf->length = blksize_snap; @@ -568,6 +577,7 @@ void lvm_snapshot_release(lv_t * lv) } if (lv->lv_iobuf) { + kiobuf_wait_for_io(lv->lv_iobuf); unmap_kiobuf(lv->lv_iobuf); free_kiovec(1, &lv->lv_iobuf); lv->lv_iobuf = NULL; diff --git a/drivers/md/lvm-snap.h b/drivers/md/lvm-snap.h new file mode 100644 index 000000000000..23538a1b7467 --- /dev/null +++ b/drivers/md/lvm-snap.h @@ -0,0 +1,47 @@ +/* + * kernel/lvm-snap.h + * + * Copyright (C) 2001 Sistina Software + * + * + * LVM driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LVM driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* + * Changelog + * + * 05/01/2001:Joe Thornber - Factored this file out of lvm.c + * + */ + +#ifndef LVM_SNAP_H +#define LVM_SNAP_H + +/* external snapshot calls */ +extern inline int lvm_get_blksize(kdev_t); +extern int lvm_snapshot_alloc(lv_t *); +extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *); +extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *); +extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *); +extern void lvm_snapshot_release(lv_t *); +extern int lvm_write_COW_table_block(vg_t *, lv_t *); +extern inline void lvm_hash_link(lv_block_exception_t *, + kdev_t, ulong, lv_t *); +extern int lvm_snapshot_alloc_hash_table(lv_t *); +extern void lvm_drop_snapshot(lv_t *, const char *); + +#endif diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c index ea276c57c95e..a4ca05e9086d 100644 --- a/drivers/md/lvm.c +++ b/drivers/md/lvm.c @@ -7,22 +7,23 @@ * April-May,July-August,November 1998 * January-March,May,July,September,October 1999 * January,February,July,September-November 2000 + * January 2001 * * * LVM driver is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * + * * LVM driver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING. If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Boston, MA 02111-1307, USA. * */ @@ -138,13 +139,21 @@ * 01/11/2000 - added memory information on hash tables to * lvm_proc_get_global_info() * 02/11/2000 - implemented /proc/lvm/ hierarchy - * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown + * 22/11/2000 - changed lvm_do_create_proc_entry_of_pv () to work + * with devfs + * 26/11/2000 - corrected #ifdef locations for PROC_FS + * 28/11/2000 - fixed lvm_do_vg_extend() NULL pointer BUG + * - fixed lvm_do_create_proc_entry_of_pv() buffer tampering BUG + * 08/01/2001 - Removed conditional compiles related to PROC_FS, + * procfs is always supported now. (JT) + * 12/01/2001 - avoided flushing logical volume in case of shrinking + * because of unecessary overhead in case of heavy updates * */ -static char *lvm_version = "LVM version 0.9 by Heinz Mauelshagen (13/11/2000)\n"; -static char *lvm_short_version = "version 0.9 (13/11/2000)"; +static char *lvm_version = "LVM version 0.9.1_beta2 by Heinz Mauelshagen (18/01/2001)\n"; +static char *lvm_short_version = "version 0.9.1_beta2 (18/01/2001)"; #define MAJOR_NR LVM_BLK_MAJOR #define DEVICE_OFF(device) @@ -190,6 +199,8 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)"; #include #include +#include "lvm-snap.h" + #define LVM_CORRECT_READ_AHEAD( a) \ if ( a < LVM_MIN_READ_AHEAD || \ a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD; @@ -198,19 +209,28 @@ static char *lvm_short_version = "version 0.9 (13/11/2000)"; # define WRITEA WRITE #endif -/* - * External function prototypes - */ -#ifdef MODULE -int init_module(void); -void cleanup_module(void); +/* debug macros */ +#ifdef DEBUG_IOCTL +#define P_IOCTL(fmt, args...) printk(KERN_DEBUG "lvm ioctl: " fmt, ## args) #else -extern int lvm_init(void); +#define P_IOCTL(fmt, args...) #endif -static void lvm_dummy_device_request(request_queue_t *); -#define DEVICE_REQUEST lvm_dummy_device_request +#ifdef DEBUG_MAP +#define P_MAP(fmt, args...) printk(KERN_DEBUG "lvm map: " fmt, ## args) +#else +#define P_MAP(fmt, args...) +#endif + +#ifdef DEBUG_KFREE +#define P_KFREE(fmt, args...) printk(KERN_DEBUG "lvm kfree: " fmt, ## args) +#else +#define P_KFREE(fmt, args...) +#endif +/* + * External function prototypes + */ static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*); static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong); @@ -224,42 +244,29 @@ static int lvm_user_bmap(struct inode *, struct lv_bmap *); static int lvm_chr_ioctl(struct inode *, struct file *, uint, ulong); -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS int lvm_proc_read_vg_info(char *, char **, off_t, int, int *, void *); int lvm_proc_read_lv_info(char *, char **, off_t, int, int *, void *); int lvm_proc_read_pv_info(char *, char **, off_t, int, int *, void *); static int lvm_proc_get_global_info(char *, char **, off_t, int, int *, void *); + +void lvm_do_create_devfs_entry_of_vg ( vg_t *); + void lvm_do_create_proc_entry_of_vg ( vg_t *); -inline void lvm_do_remove_proc_entry_of_vg ( vg_t *); -inline void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *); -inline void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *); -inline void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *); -inline void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *); -#endif +void lvm_do_remove_proc_entry_of_vg ( vg_t *); +void lvm_do_create_proc_entry_of_lv ( vg_t *, lv_t *); +void lvm_do_remove_proc_entry_of_lv ( vg_t *, lv_t *); +void lvm_do_create_proc_entry_of_pv ( vg_t *, pv_t *); +void lvm_do_remove_proc_entry_of_pv ( vg_t *, pv_t *); -#ifdef LVM_HD_NAME -void lvm_hd_name(char *, int); -#endif /* End external function prototypes */ /* * Internal function prototypes */ +static void lvm_cleanup(void); static void lvm_init_vars(void); -/* external snapshot calls */ -extern inline int lvm_get_blksize(kdev_t); -extern int lvm_snapshot_alloc(lv_t *); -extern void lvm_snapshot_fill_COW_page(vg_t *, lv_t *); -extern int lvm_snapshot_COW(kdev_t, ulong, ulong, ulong, lv_t *); -extern int lvm_snapshot_remap_block(kdev_t *, ulong *, ulong, lv_t *); -extern void lvm_snapshot_release(lv_t *); -extern int lvm_write_COW_table_block(vg_t *, lv_t *); -extern inline void lvm_hash_link(lv_block_exception_t *, kdev_t, ulong, lv_t *); -extern int lvm_snapshot_alloc_hash_table(lv_t *); -extern void lvm_drop_snapshot(lv_t *, char *); - #ifdef LVM_HD_NAME extern void (*lvm_hd_name_ptr) (char *, int); #endif @@ -288,9 +295,9 @@ static int lvm_do_vg_reduce(vg_t *, void *); static int lvm_do_vg_rename(vg_t *, void *); static int lvm_do_vg_remove(int); static void lvm_geninit(struct gendisk *); -#ifdef LVM_GET_INODE -static struct inode *lvm_get_inode(int); -void lvm_clear_inode(struct inode *); +static char *lvm_show_uuid ( char *); +#ifdef LVM_HD_NAME +void lvm_hd_name(char *, int); #endif /* END Internal function prototypes */ @@ -298,12 +305,10 @@ void lvm_clear_inode(struct inode *); /* volume group descriptor area pointers */ static vg_t *vg[ABS_MAX_VG]; -#ifdef CONFIG_DEVFS_FS static devfs_handle_t lvm_devfs_handle; static devfs_handle_t vg_devfs_handle[MAX_VG]; static devfs_handle_t ch_devfs_handle[MAX_VG]; static devfs_handle_t lv_devfs_handle[MAX_LV]; -#endif static pv_t *pvp = NULL; static lv_t *lvp = NULL; @@ -340,18 +345,15 @@ static int loadtime = 0; static uint vg_count = 0; static long lvm_chr_open_count = 0; static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION; -static DECLARE_WAIT_QUEUE_HEAD(lvm_snapshot_wait); static DECLARE_WAIT_QUEUE_HEAD(lvm_wait); static DECLARE_WAIT_QUEUE_HEAD(lvm_map_wait); static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED; static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS static struct proc_dir_entry *lvm_proc_dir = NULL; static struct proc_dir_entry *lvm_proc_vg_subdir = NULL; struct proc_dir_entry *pde = NULL; -#endif static struct file_operations lvm_chr_fops = { @@ -360,7 +362,7 @@ static struct file_operations lvm_chr_fops = ioctl: lvm_chr_ioctl, }; -#define BLOCK_DEVICE_OPERATIONS + /* block device operations structure needed for 2.3.38? and above */ static struct block_device_operations lvm_blk_dops = { @@ -391,22 +393,10 @@ static struct gendisk lvm_gendisk = NULL, /* pointer to next gendisk struct (internal) */ }; - -#ifdef MODULE -/* - * Module initialization... - */ -int init_module(void) -#else /* * Driver initialization... */ -#ifdef __initfunc -__initfunc(int lvm_init(void)) -#else -int __init lvm_init(void) -#endif -#endif /* #ifdef MODULE */ +int lvm_init(void) { struct gendisk *gendisk_ptr = NULL; @@ -414,11 +404,7 @@ int __init lvm_init(void) printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name); return -EIO; } -#ifdef BLOCK_DEVICE_OPERATIONS if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0) -#else - if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_fops) < 0) -#endif { printk("%s -- register_blkdev failed\n", lvm_name); if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) @@ -426,21 +412,17 @@ int __init lvm_init(void) return -EIO; } -#ifdef CONFIG_DEVFS_FS lvm_devfs_handle = devfs_register( 0 , "lvm", 0, 0, LVM_CHAR_MAJOR, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &lvm_chr_fops, NULL); -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_proc_dir = create_proc_entry (LVM_DIR, S_IFDIR, &proc_root); if (lvm_proc_dir != NULL) { lvm_proc_vg_subdir = create_proc_entry (LVM_VG_SUBDIR, S_IFDIR, lvm_proc_dir); pde = create_proc_entry(LVM_GLOBAL, S_IFREG, lvm_proc_dir); if ( pde != NULL) pde->read_proc = &lvm_proc_get_global_info; } -#endif lvm_init_vars(); lvm_geninit(&lvm_gendisk); @@ -464,9 +446,9 @@ int __init lvm_init(void) lvm_hd_name_ptr = lvm_hd_name; #endif - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn); + /* optional read root VGDA */ /* if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg); @@ -483,20 +465,17 @@ int __init lvm_init(void) lvm_version, lvm_name); return 0; -} /* init_module() / lvm_init() */ +} /* lvm_init() */ -#ifdef MODULE /* - * Module cleanup... + * cleanup... */ -void cleanup_module(void) +static void lvm_cleanup(void) { struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL; -#ifdef CONFIG_DEVFS_FS devfs_unregister (lvm_devfs_handle); -#endif if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) { printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); @@ -504,7 +483,7 @@ void cleanup_module(void) if (unregister_blkdev(MAJOR_NR, lvm_name) < 0) { printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name); } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + gendisk_ptr = gendisk_ptr_prev = gendisk_head; while (gendisk_ptr != NULL) { @@ -521,11 +500,9 @@ void cleanup_module(void) blksize_size[MAJOR_NR] = NULL; hardsect_size[MAJOR_NR] = NULL; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS remove_proc_entry(LVM_GLOBAL, lvm_proc_dir); remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir); remove_proc_entry(LVM_DIR, &proc_root); -#endif #ifdef LVM_HD_NAME /* reference from linux/drivers/block/genhd.c */ @@ -535,18 +512,13 @@ void cleanup_module(void) printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name); return; -} /* void cleanup_module() */ -#endif /* #ifdef MODULE */ +} /* lvm_cleanup() */ /* * support function to initialize lvm variables */ -#ifdef __initfunc -__initfunc(void lvm_init_vars(void)) -#else void __init lvm_init_vars(void) -#endif { int v; @@ -626,13 +598,9 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file, /* otherwise cc will complain about unused variables */ (void) lvm_lock; - -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d " - "VG#: %d mode: 0x%X\n", - lvm_name, command, minor, VG_CHR(minor), file->f_mode); -#endif + P_IOCTL("%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d " + "VG#: %d mode: 0x%X\n", + lvm_name, command, minor, VG_CHR(minor), file->f_mode); #ifdef LVM_TOTAL_RESET if (lvm_reset_spindown > 0) return -EACCES; @@ -890,14 +858,12 @@ static int lvm_blk_open(struct inode *inode, struct file *file) if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM; /* Check inactive LV and open for read/write */ - if (file->f_mode & O_RDWR) { - if (!(lv_ptr->lv_status & LV_ACTIVE)) return -EPERM; - if (!(lv_ptr->lv_access & LV_WRITE)) return -EACCES; - } + if (!(lv_ptr->lv_status & LV_ACTIVE)) + return -EPERM; + if (!(lv_ptr->lv_access & LV_WRITE) && + (file->f_mode & FMODE_WRITE)) + return -EACCES; -#ifndef BLOCK_DEVICE_OPERATIONS - file->f_op = &lvm_blk_fops; -#endif /* be sure to increment VG counter */ if (lv_ptr->lv_open == 0) vg_ptr->lv_open++; @@ -930,24 +896,18 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, void *arg = (void *) a; struct hd_geometry *hd = (struct hd_geometry *) a; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X " - "VG#: %dl LV#: %d\n", - lvm_name, minor, command, (ulong) arg, - VG_BLK(minor), LV_BLK(minor)); -#endif + P_IOCTL("%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X " + "VG#: %dl LV#: %d\n", + lvm_name, minor, command, (ulong) arg, + VG_BLK(minor), LV_BLK(minor)); switch (command) { case BLKGETSIZE: /* return device size */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n", - lvm_name, lv_ptr->lv_size); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKGETSIZE: %u\n", + lvm_name, lv_ptr->lv_size); if (put_user(lv_ptr->lv_size, (long *)arg)) - return -EFAULT; + return -EFAULT; break; @@ -955,10 +915,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, /* flush buffer cache */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKFLSBUF\n", lvm_name); + fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); break; @@ -968,11 +926,9 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, /* set read ahead for block device */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n", - lvm_name, (long) arg, MAJOR(inode->i_rdev), minor); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKRASET: %d sectors for %02X:%02X\n", + lvm_name, (long) arg, MAJOR(inode->i_rdev), minor); + if ((long) arg < LVM_MIN_READ_AHEAD || (long) arg > LVM_MAX_READ_AHEAD) return -EINVAL; @@ -982,10 +938,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, case BLKRAGET: /* get current read ahead setting */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- BLKRAGET\n", lvm_name); if (put_user(lv_ptr->lv_read_ahead, (long *)arg)) return -EFAULT; break; @@ -993,10 +946,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, case HDIO_GETGEO: /* get disk geometry */ -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name); if (hd == NULL) return -EINVAL; { @@ -1016,11 +966,8 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, return -EFAULT; } -#ifdef DEBUG_IOCTL - printk(KERN_DEBUG - "%s -- lvm_blk_ioctl -- cylinders: %d\n", - lvm_name, lv_ptr->lv_size / heads / sectors); -#endif + P_IOCTL("%s -- lvm_blk_ioctl -- cylinders: %d\n", + lvm_name, lv_ptr->lv_size / heads / sectors); break; @@ -1127,22 +1074,22 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result) struct buffer_head bh; unsigned long block; int err; - + if (get_user(block, &user_result->lv_block)) - return -EFAULT; - + return -EFAULT; + memset(&bh,0,sizeof bh); bh.b_rsector = block; bh.b_dev = bh.b_rdev = inode->i_dev; bh.b_size = lvm_get_blksize(bh.b_dev); if ((err=lvm_map(&bh, READ)) < 0) { - printk("lvm map failed: %d\n", err); - return -EINVAL; + printk("lvm map failed: %d\n", err); + return -EINVAL; } - - return put_user( kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) || + + return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) || put_user(bh.b_rsector, &user_result->lv_block) ? -EFAULT : 0; -} +} /* @@ -1168,7 +1115,7 @@ int lvm_vg_info(vg_t *vg_ptr, char *buf) { vg_ptr->pe_total, vg_ptr->pe_allocated * vg_ptr->pe_size >> 1, vg_ptr->pe_allocated, - (vg_ptr->pe_total - vg_ptr->pe_allocated) * + (vg_ptr->pe_total - vg_ptr->pe_allocated) * vg_ptr->pe_size >> 1, vg_ptr->pe_total - vg_ptr->pe_allocated); return sz; @@ -1263,7 +1210,6 @@ int lvm_pv_info(pv_t *pv_ptr, char *buf) { } -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS /* * Support functions /proc-Filesystem */ @@ -1325,10 +1271,7 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou lv_block_exception_t_bytes *= sizeof(lv_block_exception_t); if (buf != NULL) { -#ifdef DEBUG_KFREE - printk(KERN_DEBUG - "%s -- vfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- vfree %d\n", lvm_name, __LINE__); lock_kernel(); vfree(buf); unlock_kernel(); @@ -1452,7 +1395,6 @@ static int lvm_proc_get_global_info(char *page, char **start, off_t pos, int cou else return count; } /* lvm_proc_get_global_info() */ -#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */ /* @@ -1478,7 +1420,7 @@ int lvm_proc_read_vg_info(char *page, char **start, off_t off, sz += sprintf ( page+sz, "PE size: %u\n", vg->pe_size / 2); sz += sprintf ( page+sz, "PE total: %u\n", vg->pe_total); sz += sprintf ( page+sz, "PE allocated: %u\n", vg->pe_allocated); - sz += sprintf ( page+sz, "uuid: %s\n", vg->vg_uuid); + sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(vg->vg_uuid)); return sz; } @@ -1525,7 +1467,7 @@ int lvm_proc_read_pv_info(char *page, char **start, off_t off, sz += sprintf ( page+sz, "PE allocated: %u\n", pv->pe_allocated); sz += sprintf ( page+sz, "device: %02u:%02u\n", MAJOR(pv->pv_dev), MINOR(pv->pv_dev)); - sz += sprintf ( page+sz, "uuid: %s\n", pv->pv_uuid); + sz += sprintf ( page+sz, "uuid: %s\n", lvm_show_uuid(pv->pv_uuid)); return sz; @@ -1565,15 +1507,13 @@ static int lvm_map(struct buffer_head *bh, int rw) lvm_name, lv->lv_name); return -1; } -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu " - "size:%lu\n", - lvm_name, minor, - MAJOR(rdev_tmp), - MINOR(rdev_tmp), - rsector_tmp, size); -#endif + + P_MAP("%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu " + "size:%lu\n", + lvm_name, minor, + MAJOR(rdev_tmp), + MINOR(rdev_tmp), + rsector_tmp, size); if (rsector_tmp + size > lv->lv_size) { printk(KERN_ALERT @@ -1595,15 +1535,13 @@ lvm_second_remap: (rsector_tmp % vg_this->pe_size); rdev_tmp = lv->lv_current_pe[index].dev; -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n", + P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d " + "rsector:%ld\n", index, lv->lv_current_pe[index].pe, MAJOR(rdev_tmp), MINOR(rdev_tmp), rsector_tmp); -#endif /* striped mapping */ } else { @@ -1624,9 +1562,7 @@ lvm_second_remap: rdev_tmp = lv->lv_current_pe[index].dev; } -#ifdef DEBUG_MAP - printk(KERN_DEBUG - "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n" + P_MAP("lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n" "stripe_length: %ld stripe_index: %ld\n", index, lv->lv_current_pe[index].pe, @@ -1635,7 +1571,6 @@ lvm_second_remap: rsector_tmp, stripe_length, stripe_index); -#endif /* handle physical extents on the move */ if (pe_lock_req.lock == LOCK_PE) { @@ -1659,6 +1594,8 @@ lvm_second_remap: if (lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)) { /* original logical volume */ if (lv->lv_access & LV_SNAPSHOT_ORG) { + /* Serializes the access to the lv_snapshot_next list */ + down(&lv->lv_snapshot_sem); if (rw == WRITE || rw == WRITEA) { lv_t *lv_ptr; @@ -1669,7 +1606,8 @@ lvm_second_remap: lv_ptr = lv_ptr->lv_snapshot_next) { /* Check for inactive snapshot */ if (!(lv_ptr->lv_status & LV_ACTIVE)) continue; - down(&lv->lv_snapshot_org->lv_snapshot_sem); + /* Serializes the COW with the accesses to the snapshot device */ + down(&lv_ptr->lv_snapshot_sem); /* do we still have exception storage for this snapshot free? */ if (lv_ptr->lv_block_exception != NULL) { rdev_sav = rdev_tmp; @@ -1690,9 +1628,10 @@ lvm_second_remap: rdev_tmp = rdev_sav; rsector_tmp = rsector_sav; } - up(&lv->lv_snapshot_org->lv_snapshot_sem); + up(&lv_ptr->lv_snapshot_sem); } } + up(&lv->lv_snapshot_sem); } else { /* remap snapshot logical volume */ down(&lv->lv_snapshot_sem); @@ -1732,32 +1671,13 @@ void lvm_hd_name(char *buf, int minor) #endif -/* - * this one never should be called... - */ -static void lvm_dummy_device_request(request_queue_t * t) -{ - printk(KERN_EMERG - "%s -- oops, got lvm request for %02d:%02d [sector: %lu]\n", - lvm_name, - MAJOR(CURRENT->rq_dev), - MINOR(CURRENT->rq_dev), - CURRENT->sector); - return; -} - - /* * make request function */ static int lvm_make_request_fn(request_queue_t *q, int rw, - struct buffer_head *bh) -{ - if (lvm_map(bh, rw)<0) - return 0; /* failure, buffer_IO_error has been called, don't recurse */ - else - return 1; /* all ok, mapping done, call lower level driver */ + struct buffer_head *bh) { + return (lvm_map(bh, rw) < 0) ? 0 : 1; } @@ -1774,10 +1694,8 @@ static int lvm_do_lock_lvm(void) lock_try_again: spin_lock(&lvm_lock); if (lock != 0 && lock != current->pid) { -#ifdef DEBUG_IOCTL - printk(KERN_INFO "lvm_do_lock_lvm: %s is locked by pid %d ...\n", - lvm_name, lock); -#endif + P_IOCTL("lvm_do_lock_lvm: %s is locked by pid %d ...\n", + lvm_name, lock); spin_unlock(&lvm_lock); interruptible_sleep_on(&lvm_wait); if (current->sigpending != 0) @@ -1966,6 +1884,8 @@ int lvm_do_vg_create(int minor, void *arg) } } + lvm_do_create_devfs_entry_of_vg ( vg_ptr); + /* Second path to correct snapshot logical volumes which are not in place during first path above */ for (l = 0; l < ls; l++) { @@ -1980,18 +1900,7 @@ int lvm_do_vg_create(int minor, void *arg) } } -#ifdef CONFIG_DEVFS_FS - vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL); - ch_devfs_handle[vg_ptr->vg_number] = devfs_register( - vg_devfs_handle[vg_ptr->vg_number] , "group", - DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &lvm_chr_fops, NULL); -#endif - -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr); -#endif vfree(snap_lv_ptr); @@ -2021,25 +1930,15 @@ static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg) for (p = 0; p < vg_ptr->pv_max; p++) { if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) { ret = lvm_do_pv_create(arg, vg_ptr, p); - lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); if ( ret != 0) return ret; - - /* We don't need the PE list - in kernel space like LVs pe_t list */ - pv_ptr->pe = NULL; - vg_ptr->pv_cur++; - vg_ptr->pv_act++; - vg_ptr->pe_total += - pv_ptr->pe_total; -#ifdef LVM_GET_INODE - /* insert a dummy inode for fs_may_mount */ - pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev); -#endif + pv_ptr = vg_ptr->pv[p]; + vg_ptr->pe_total += pv_ptr->pe_total; + lvm_do_create_proc_entry_of_pv(vg_ptr, pv_ptr); return 0; } } } -return -EPERM; + return -EPERM; } /* lvm_do_vg_extend() */ @@ -2060,10 +1959,6 @@ static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) { strcmp(pv_ptr->pv_name, pv_name) == 0) { if (pv_ptr->lv_cur > 0) return -EPERM; - vg_ptr->pe_total -= - pv_ptr->pe_total; - vg_ptr->pv_cur--; - vg_ptr->pv_act--; lvm_do_pv_remove(vg_ptr, p); /* Make PV pointer array contiguous */ for (; p < vg_ptr->pv_max - 1; p++) @@ -2091,9 +1986,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg) if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0) return -EFAULT; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr); -#endif strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1); for ( l = 0; l < vg_ptr->lv_max; l++) @@ -2115,9 +2008,7 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg) strncpy(pv_ptr->vg_name, vg_name, NAME_LEN); } -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr); -#endif return 0; } /* lvm_do_vg_rename */ @@ -2166,27 +2057,17 @@ static int lvm_do_vg_remove(int minor) /* free PVs */ for (i = 0; i < vg_ptr->pv_max; i++) { if ((pv_ptr = vg_ptr->pv[i]) != NULL) { -#ifdef DEBUG_KFREE - printk(KERN_DEBUG - "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); lvm_do_pv_remove(vg_ptr, i); } } -#ifdef CONFIG_DEVFS_FS devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]); devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]); -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr); -#endif - -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(vg_ptr); vg[VG_CHR(minor)] = NULL; @@ -2222,11 +2103,6 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) { vg_ptr->pv_act++; vg_ptr->pv_cur++; -#ifdef LVM_GET_INODE - /* insert a dummy inode for fs_may_mount */ - pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev); -#endif - return 0; } /* lvm_do_pv_create() */ @@ -2237,11 +2113,8 @@ static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) { static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) { pv_t *pv_ptr = vg_ptr->pv[p]; -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr); -#endif - vg_ptr->pe_total -= - pv_ptr->pe_total; + vg_ptr->pe_total -= pv_ptr->pe_total; vg_ptr->pv_cur--; vg_ptr->pv_act--; #ifdef LVM_GET_INODE @@ -2320,11 +2193,9 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte " "at line %d\n", lvm_name, size, __LINE__); -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return -ENOMEM; } if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) { @@ -2354,9 +2225,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION " "of %d byte at line %d\n", lvm_name, size, __LINE__); -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, + __LINE__); kfree(lv_ptr); vg_ptr->lv[l] = NULL; return -ENOMEM; @@ -2364,7 +2234,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) { vfree(lv_ptr->lv_block_exception); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return -EFAULT; } /* point to the original logical volume */ @@ -2372,33 +2242,32 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) lv_ptr->lv_snapshot_minor = 0; lv_ptr->lv_snapshot_org = lv_ptr; - lv_ptr->lv_snapshot_prev = NULL; - /* walk thrugh the snapshot list */ - while (lv_ptr->lv_snapshot_next != NULL) - lv_ptr = lv_ptr->lv_snapshot_next; - /* now lv_ptr points to the last existing snapshot in the chain */ - vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr; /* our new one now back points to the previous last in the chain which can be the original logical volume */ lv_ptr = vg_ptr->lv[l]; /* now lv_ptr points to our new last snapshot logical volume */ - lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org; - lv_ptr->lv_snapshot_next = NULL; lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe; + lv_ptr->lv_allocated_snapshot_le = lv_ptr->lv_allocated_le; lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le; lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le; lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size; lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes; lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize; + + /* Update the VG PE(s) used by snapshot reserve space. */ + vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le; + if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0) { vfree(lv_ptr->lv_block_exception); kfree(lv_ptr); - vg[VG_CHR(minor)]->lv[l] = NULL; + vg_ptr->lv[l] = NULL; return ret; } for ( e = 0; e < lv_ptr->lv_remap_ptr; e++) - lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); + lvm_hash_link (lv_ptr->lv_block_exception + e, + lv_ptr->lv_block_exception[e].rdev_org, + lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); /* need to fill the COW exception table data into the page for disk i/o */ lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr); @@ -2426,9 +2295,8 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) vg_ptr->lv_cur++; lv_ptr->lv_status = lv_status_save; -#ifdef CONFIG_DEVFS_FS { - char *lv_tmp, *lv_buf = NULL; + char *lv_tmp, *lv_buf = lv->lv_name; strtok(lv->lv_name, "/"); /* /dev */ while((lv_tmp = strtok(NULL, "/")) != NULL) @@ -2440,24 +2308,29 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, &lvm_blk_dops, NULL); } -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif /* optionally add our new snapshot LV */ if (lv_ptr->lv_access & LV_SNAPSHOT) { + lv_t *org = lv_ptr->lv_snapshot_org, *last; + /* sync the original logical volume */ - fsync_dev(lv_ptr->lv_snapshot_org->lv_dev); + fsync_dev(org->lv_dev); #ifdef LVM_VFS_ENHANCEMENT /* VFS function call to sync and lock the filesystem */ - fsync_dev_lockfs(lv_ptr->lv_snapshot_org->lv_dev); + fsync_dev_lockfs(org->lv_dev); #endif - lv_ptr->lv_snapshot_org->lv_access |= LV_SNAPSHOT_ORG; - lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; - /* put ourselve into the chain */ - lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr; + + down(&org->lv_snapshot_sem); + org->lv_access |= LV_SNAPSHOT_ORG; + lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */ + + /* Link in the list of snapshot volumes */ + for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next); + lv_ptr->lv_snapshot_prev = last; + last->lv_snapshot_next = lv_ptr; + up(&org->lv_snapshot_sem); } /* activate the logical volume */ @@ -2513,6 +2386,31 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) lv_ptr->lv_snapshot_next != NULL) return -EPERM; + if (lv_ptr->lv_access & LV_SNAPSHOT) { + /* + * Atomically make the the snapshot invisible + * to the original lv before playing with it. + */ + lv_t * org = lv_ptr->lv_snapshot_org; + down(&org->lv_snapshot_sem); + + /* remove this snapshot logical volume from the chain */ + lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; + if (lv_ptr->lv_snapshot_next != NULL) { + lv_ptr->lv_snapshot_next->lv_snapshot_prev = + lv_ptr->lv_snapshot_prev; + } + up(&org->lv_snapshot_sem); + + /* no more snapshots? */ + if (!org->lv_snapshot_next) + org->lv_access &= ~LV_SNAPSHOT_ORG; + lvm_snapshot_release(lv_ptr); + + /* Update the VG PE(s) used by snapshot reserve space. */ + vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le; + } + lv_ptr->lv_status |= LV_SPINDOWN; /* sync the buffers */ @@ -2532,7 +2430,8 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) vg_lv_map[MINOR(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG; vg_lv_map[MINOR(lv_ptr->lv_dev)].lv_number = -1; - /* correct the PE count in PVs if this is no snapshot logical volume */ + /* correct the PE count in PVs if this is not a snapshot + logical volume */ if (!(lv_ptr->lv_access & LV_SNAPSHOT)) { /* only if this is no snapshot logical volume because we share the lv_current_pe[] structs with the @@ -2546,31 +2445,13 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) } } vfree(lv_ptr->lv_current_pe); - /* LV_SNAPSHOT */ - } else { - /* remove this snapshot logical volume from the chain */ - lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; - if (lv_ptr->lv_snapshot_next != NULL) { - lv_ptr->lv_snapshot_next->lv_snapshot_prev = - lv_ptr->lv_snapshot_prev; - } - /* no more snapshots? */ - if (lv_ptr->lv_snapshot_org->lv_snapshot_next == NULL) - lv_ptr->lv_snapshot_org->lv_access &= ~LV_SNAPSHOT_ORG; - lvm_snapshot_release(lv_ptr); } -#ifdef CONFIG_DEVFS_FS devfs_unregister(lv_devfs_handle[lv_ptr->lv_number]); -#endif -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif -#ifdef DEBUG_KFREE - printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__); -#endif + P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(lv_ptr); vg_ptr->lv[l] = NULL; vg_ptr->lv_cur--; @@ -2638,21 +2519,24 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) } memcpy(lvbe, lv_ptr->lv_block_exception, - (lv->lv_remap_end > lv_ptr->lv_remap_end ? lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t)); + (lv->lv_remap_end > lv_ptr->lv_remap_end ? + lv_ptr->lv_remap_ptr : lv->lv_remap_end) * sizeof(lv_block_exception_t)); lv_ptr->lv_block_exception = lvbe; lv_ptr->lv_remap_end = lv->lv_remap_end; if (lvm_snapshot_alloc_hash_table(lv_ptr) != 0) { - lvm_drop_snapshot(lv_ptr, "hash_alloc"); + lvm_drop_snapshot(lv_ptr, "no memory for hash table"); up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem); vfree(lvbe_old); vfree(lvs_hash_table_old); - return 1; + return -ENOMEM; } for (e = 0; e < lv_ptr->lv_remap_ptr; e++) - lvm_hash_link (lv_ptr->lv_block_exception + e, lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); + lvm_hash_link (lv_ptr->lv_block_exception + e, + lv_ptr->lv_block_exception[e].rdev_org, + lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); up(&lv_ptr->lv_snapshot_org->lv_snapshot_sem); @@ -2677,15 +2561,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) return -EFAULT; } -#ifdef DEBUG - printk(KERN_DEBUG - "%s -- fsync_dev and " - "invalidate_buffers for %s [%s] in %s\n", - lvm_name, lv_ptr->lv_name, - kdevname(lv_ptr->lv_dev), - vg_ptr->vg_name); -#endif - /* reduce allocation counters on PV(s) */ for (le = 0; le < lv_ptr->lv_allocated_le; le++) { vg_ptr->pe_allocated--; @@ -2714,9 +2589,6 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *lv) /* save # of old allocated logical extents */ old_allocated_le = lv_ptr->lv_allocated_le; - /* in case of shrinking -> let's flush */ - if ( end > lv->lv_current_le) fsync_dev(lv_ptr->lv_dev); - /* copy preloaded LV */ memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t)); @@ -2914,15 +2786,11 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv) if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue; if (lv_ptr->lv_dev == lv->lv_dev) { -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif strncpy(lv_ptr->lv_name, lv_req->lv_name, NAME_LEN); -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); -#endif break; } } @@ -3003,10 +2871,23 @@ static int lvm_do_pv_status(vg_t *vg_ptr, void *arg) +/* + * create a devfs entry for a volume group + */ +void lvm_do_create_devfs_entry_of_vg ( vg_t *vg_ptr) { + vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL); + ch_devfs_handle[vg_ptr->vg_number] = devfs_register( + vg_devfs_handle[vg_ptr->vg_number] , "group", + DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &lvm_chr_fops, NULL); +} + + /* * create a /proc entry for a logical volume */ -inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { +void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { char *basename; if ( vg_ptr->lv_subdir_pde != NULL) { @@ -3026,7 +2907,7 @@ inline void lvm_do_create_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { /* * remove a /proc entry for a logical volume */ -inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { +void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { char *basename; if ( vg_ptr->lv_subdir_pde != NULL) { @@ -3041,13 +2922,17 @@ inline void lvm_do_remove_proc_entry_of_lv ( vg_t *vg_ptr, lv_t *lv_ptr) { /* * create a /proc entry for a physical volume */ -inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { +void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { + int offset = 0; char *basename; - - basename = strrchr(pv_ptr->pv_name, '/'); - if (basename == NULL) basename = pv_ptr->pv_name; - else basename++; - pde = create_proc_entry(basename, S_IFREG, vg_ptr->pv_subdir_pde); + char buffer[NAME_LEN]; + + basename = pv_ptr->pv_name; + if (strncmp(basename, "/dev/", 5) == 0) offset = 5; + strncpy(buffer, basename + offset, sizeof(buffer)); + basename = buffer; + while ( ( basename = strchr ( basename, '/')) != NULL) *basename = '_'; + pde = create_proc_entry(buffer, S_IFREG, vg_ptr->pv_subdir_pde); if ( pde != NULL) { pde->read_proc = lvm_proc_read_pv_info; pde->data = pv_ptr; @@ -3058,7 +2943,7 @@ inline void lvm_do_create_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { /* * remove a /proc entry for a physical volume */ -inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { +void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { char *basename; basename = strrchr(pv_ptr->pv_name, '/'); @@ -3074,7 +2959,6 @@ inline void lvm_do_remove_proc_entry_of_pv ( vg_t *vg_ptr, pv_t *pv_ptr) { /* * create a /proc entry for a volume group */ -#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) { int l, p; pv_t *pv_ptr; @@ -3090,24 +2974,25 @@ void lvm_do_create_proc_entry_of_vg ( vg_t *vg_ptr) { pde->read_proc = lvm_proc_read_vg_info; pde->data = vg_ptr; } - vg_ptr->lv_subdir_pde = - create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, - vg_ptr->vg_dir_pde); - vg_ptr->pv_subdir_pde = - create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, - vg_ptr->vg_dir_pde); - } - - if ( vg_ptr->pv_subdir_pde != NULL) { - for ( l = 0; l < vg_ptr->lv_max; l++) { - if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue; - lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); - } - for ( p = 0; p < vg_ptr->pv_max; p++) { - if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue; - lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); - } - } + pde = create_proc_entry(LVM_LV_SUBDIR, S_IFDIR, + vg_ptr->vg_dir_pde); + if ( pde != NULL) { + vg_ptr->lv_subdir_pde = pde; + for ( l = 0; l < vg_ptr->lv_max; l++) { + if ( ( lv_ptr = vg_ptr->lv[l]) == NULL) continue; + lvm_do_create_proc_entry_of_lv ( vg_ptr, lv_ptr); + } + } + pde = create_proc_entry(LVM_PV_SUBDIR, S_IFDIR, + vg_ptr->vg_dir_pde); + if ( pde != NULL) { + vg_ptr->pv_subdir_pde = pde; + for ( p = 0; p < vg_ptr->pv_max; p++) { + if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) continue; + lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); + } + } + } } /* @@ -3133,18 +3018,12 @@ void lvm_do_remove_proc_entry_of_vg ( vg_t *vg_ptr) { remove_proc_entry(vg_ptr->vg_name, lvm_proc_vg_subdir); } } -#endif /* * support function initialize gendisk variables */ -#ifdef __initfunc -__initfunc(void lvm_geninit(struct gendisk *lvm_gdisk)) -#else -void __init - lvm_geninit(struct gendisk *lvm_gdisk) -#endif +void __init lvm_geninit(struct gendisk *lvm_gdisk) { int i = 0; @@ -3166,39 +3045,30 @@ void __init } /* lvm_gen_init() */ -#ifdef LVM_GET_INODE /* - * support function to get an empty inode - * - * Gets an empty inode to be inserted into the inode hash, - * so that a physical volume can't be mounted. - * This is analog to drivers/block/md.c - * - * Is this the real thing? - * + * return a pointer to a '-' padded uuid */ -struct inode *lvm_get_inode(int dev) -{ - struct inode *inode_this = NULL; +static char *lvm_show_uuid ( char *uuidstr) { + int i, j; + static char uuid[NAME_LEN] = { 0, }; - /* Lock the device by inserting a dummy inode. */ - inode_this = get_empty_inode(); - inode_this->i_dev = dev; - insert_inode_hash(inode_this); - return inode_this; -} + memset ( uuid, 0, NAME_LEN); + i = 6; + memcpy ( uuid, uuidstr, i); + uuidstr += i; -/* - * support function to clear an inode - * - */ -void lvm_clear_inode(struct inode *inode) -{ -#ifdef I_FREEING - inode->i_state |= I_FREEING; -#endif - clear_inode(inode); - return; + for ( j = 0; j < 6; j++) { + uuid[i++] = '-'; + memcpy ( &uuid[i], uuidstr, 4); + uuidstr += 4; + i += 4; + } + + memcpy ( &uuid[i], uuidstr, 2 ); + + return uuid; } -#endif /* #ifdef LVM_GET_INODE */ + +module_init(lvm_init); +module_exit(lvm_cleanup); diff --git a/drivers/md/md.c b/drivers/md/md.c index 8542bc2b067f..5d4bab6c9d8b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2033,68 +2033,65 @@ abort: struct { int set; int noautodetect; +} raid_setup_args md__initdata; -} raid_setup_args md__initdata = { 0, 0 }; - -void md_setup_drive(void) md__init; +void md_setup_drive (void) md__init; /* * Searches all registered partitions for autorun RAID arrays * at boot time. */ -#ifdef CONFIG_AUTODETECT_RAID -static int detected_devices[128] md__initdata = { 0, }; -static int dev_cnt=0; +static int detected_devices[128] md__initdata; +static int dev_cnt; + void md_autodetect_dev(kdev_t dev) { if (dev_cnt >= 0 && dev_cnt < 127) detected_devices[dev_cnt++] = dev; } -#endif -int md__init md_run_setup(void) + +static void autostart_arrays (void) { -#ifdef CONFIG_AUTODETECT_RAID mdk_rdev_t *rdev; int i; - if (raid_setup_args.noautodetect) - printk(KERN_INFO "skipping autodetection of RAID arrays\n"); - else { - - printk(KERN_INFO "autodetecting RAID arrays\n"); + printk(KERN_INFO "autodetecting RAID arrays\n"); - for (i=0; ifaulty) { - MD_BUG(); - continue; - } - md_list_add(&rdev->pending, &pending_raid_disks); + if (md_import_device(dev,1)) { + printk(KERN_ALERT "could not import %s!\n", + partition_name(dev)); + continue; } - - autorun_devices(-1); + /* + * Sanity checks: + */ + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + continue; + } + if (rdev->faulty) { + MD_BUG(); + continue; + } + md_list_add(&rdev->pending, &pending_raid_disks); } + autorun_devices(-1); +} + +int md__init md_run_setup(void) +{ + if (raid_setup_args.noautodetect) + printk(KERN_INFO "skipping autodetection of RAID arrays\n"); + else + autostart_arrays(); dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */ -#endif -#ifdef CONFIG_MD_BOOT md_setup_drive(); -#endif return 0; } @@ -2558,6 +2555,11 @@ static int md_ioctl (struct inode *inode, struct file *file, md_print_devices(); goto done_unlock; + case RAID_AUTORUN: + err = 0; + autostart_arrays(); + goto done; + case BLKGETSIZE: /* Return device size */ if (!arg) { err = -EINVAL; @@ -3639,14 +3641,12 @@ int md__init md_init (void) return (0); } -#ifdef CONFIG_MD_BOOT -#define MAX_MD_BOOT_DEVS 8 -struct { - unsigned long set; - int pers[MAX_MD_BOOT_DEVS]; - int chunk[MAX_MD_BOOT_DEVS]; - kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS]; -} md_setup_args md__initdata = { 0, }; +static struct { + char device_set [MAX_MD_DEVS]; + int pers[MAX_MD_DEVS]; + int chunk[MAX_MD_DEVS]; + kdev_t devices[MAX_MD_DEVS][MD_SB_DISKS]; +} md_setup_args md__initdata; /* * Parse the command-line parameters given our kernel, but do not @@ -3676,10 +3676,10 @@ static int md__init md_setup(char *str) printk("md: Too few arguments supplied to md=.\n"); return 0; } - if (minor >= MAX_MD_BOOT_DEVS) { + if (minor >= MAX_MD_DEVS) { printk ("md: Minor device number too high.\n"); return 0; - } else if (md_setup_args.set & (1 << minor)) { + } else if (md_setup_args.device_set[minor]) { printk ("md: Warning - md=%d,... has been specified twice;\n" " will discard the first definition.\n", minor); } @@ -3737,7 +3737,7 @@ static int md__init md_setup(char *str) printk ("md: Will configure md%d (%s) from %s, below.\n", minor, pername, devnames); md_setup_args.devices[minor][i] = (kdev_t) 0; - md_setup_args.set |= (1 << minor); + md_setup_args.device_set[minor] = 1; return 1; } @@ -3747,10 +3747,11 @@ void md__init md_setup_drive(void) kdev_t dev; mddev_t*mddev; - for (minor = 0; minor < MAX_MD_BOOT_DEVS; minor++) { + for (minor = 0; minor < MAX_MD_DEVS; minor++) { mdu_disk_info_t dinfo; - int err=0; - if (!(md_setup_args.set & (1 << minor))) + + int err = 0; + if (!md_setup_args.device_set[minor]) continue; printk("md: Loading md%d.\n", minor); if (mddev_map[minor].mddev) { @@ -3776,7 +3777,7 @@ void md__init md_setup_drive(void) ainfo.layout = 0; ainfo.chunk_size = md_setup_args.chunk[minor]; err = set_array_info(mddev, &ainfo); - for (i=0; !err && (dev = md_setup_args.devices[minor][i]); i++) { + for (i = 0; !err && (dev = md_setup_args.devices[minor][i]); i++) { dinfo.number = i; dinfo.raid_disk = i; dinfo.state = (1<pci_dev, sizeof(*lp), lp, lp->dma_addr); return -ENODEV; } lp->a = *a; @@ -731,6 +732,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car printk(", probed IRQ %d.\n", dev->irq); else { printk(", failed to detect IRQ line.\n"); + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); return -ENODEV; } } diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 1cdec0a45faf..7fffdf4f73a3 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -413,13 +413,12 @@ static int pppoe_disc_rcv(struct sk_buff *skb, po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); if (!po) - goto abort_put; + goto abort; sk = po->sk; pppox_unbind_sock(sk); - abort_put: sock_put(sk); abort: kfree_skb(skb); diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 942a6c59bbca..032776c7037f 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.91 2000/11/08 05:04:06 davem Exp $ +/* $Id: sbus.c,v 1.92 2001/01/25 17:15:59 davem Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -238,10 +238,14 @@ static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, break; } if (rngnum == num_ranges) { - prom_printf("sbus_apply_ranges: Cannot find matching " - "range nregs[%d] nranges[%d].\n", - num_regs, num_ranges); - prom_halt(); + /* We used to flag this as an error. Actually + * some devices do not report the regs as we expect. + * For example, see SUNW,pln device. In that case + * the reg property is in a format internal to that + * node, ie. it is not in the SBUS register space + * per se. -DaveM + */ + return; } regs[regnum].which_io = ranges[rngnum].ot_parent_space; regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index f966bf5a78ff..0e5ee69354f4 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -16,6 +16,7 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) #error "This driver works only with kernel 2.4.0 or higher!" #endif +#include #include #include #include @@ -38,7 +39,7 @@ #include /* current version of this driver-source: */ -#define IBMMCA_SCSI_DRIVER_VERSION "4.0a" +#define IBMMCA_SCSI_DRIVER_VERSION "4.0b" #define IBMLOCK spin_lock_irqsave(&io_request_lock, flags); #define IBMUNLOCK spin_unlock_irqrestore(&io_request_lock, flags); @@ -443,7 +444,6 @@ static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 }; (that is kernel version 2.1.x) */ #if defined(MODULE) static char *boot_options = NULL; -#include MODULE_PARM(boot_options, "s"); MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); @@ -2563,9 +2563,6 @@ static int option_setup(char *str) __setup("ibmmcascsi=", option_setup); -#ifdef MODULE -/* Eventually this will go into an include file, but this will be later */ -Scsi_Host_Template driver_template = IBMMCA; +static Scsi_Host_Template driver_template = IBMMCA; #include "scsi_module.c" -#endif diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 365ea61a5f46..7a2cde23b87a 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -678,7 +678,7 @@ void get_capabilities(int i) CDC_DVD | CDC_DVD_RAM | CDC_SELECT_DISC | CDC_SELECT_SPEED); scsi_free(buffer, 512); - printk("sr%i: scsi-1 drive\n"); + printk("sr%i: scsi-1 drive\n", i); return; } n = buffer[3] + 4; diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c index 73c9dcf54c65..03b4b1999cf3 100644 --- a/drivers/sound/trix.c +++ b/drivers/sound/trix.c @@ -17,7 +17,6 @@ * Arnaldo C. de Melo Got rid of attach_uart401 */ -#include #include #include diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index f9fa0d213c7d..4d5b66386d13 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -678,7 +678,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, int end, count, index; struct fbcmap *cmap; - if (!fb->loadcmap) + if (!fb->loadcmap || !fb->color_map) return -EINVAL; i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); if (i) return i; @@ -1110,6 +1110,8 @@ sizechange: } if (!p) { + if (fb->color_map) + kfree(fb->color_map); kfree(fb); return; } @@ -1147,6 +1149,8 @@ sizechange: sbusfb_set_var(var, -1, &fb->info); if (register_framebuffer(&fb->info) < 0) { + if (fb->color_map) + kfree(fb->color_map); kfree(fb); return; } diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index c8dc3dd8fccb..12de14e7b0c5 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -14,17 +14,21 @@ extern int coda_debug; extern int coda_print_entry; +static ViceFid NullFID = { 0, 0, 0 }; + inline int coda_fideq(ViceFid *fid1, ViceFid *fid2) { - if (fid1->Vnode != fid2->Vnode) - return 0; - if (fid1->Volume != fid2->Volume) - return 0; - if (fid1->Unique != fid2->Unique) - return 0; + if (fid1->Vnode != fid2->Vnode) return 0; + if (fid1->Volume != fid2->Volume) return 0; + if (fid1->Unique != fid2->Unique) return 0; return 1; } +static int coda_inocmp(struct inode *inode, unsigned long ino, void *opaque) +{ + return (coda_fideq((ViceFid *)opaque, &(ITOC(inode)->c_fid))); +} + static struct inode_operations coda_symlink_inode_operations = { readlink: page_readlink, follow_link: page_follow_link, @@ -62,7 +66,8 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, struct coda_inode_info *cii; ino_t ino = attr->va_fileid; - inode = iget(sb, ino); + inode = iget4(sb, ino, coda_inocmp, fid); + if ( !inode ) { CDEBUG(D_CNODE, "coda_iget: no inode\n"); return ERR_PTR(-ENOMEM); @@ -70,25 +75,16 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, /* check if the inode is already initialized */ cii = ITOC(inode); - if (cii->c_fid.Volume != 0 || cii->c_fid.Vnode != 0 || cii->c_fid.Unique != 0) { - /* see if it is the right one (might have an inode collision) */ - if ( !coda_fideq(fid, &cii->c_fid) ) { - printk("coda_iget: initialized inode old %s new %s!\n", - coda_f2s(&cii->c_fid), coda_f2s2(fid)); - iput(inode); - return ERR_PTR(-ENOENT); - } - /* we will still replace the attributes, type might have changed */ - goto out; + if (coda_fideq(&cii->c_fid, &NullFID)) { + /* new, empty inode found... initializing */ + cii->c_fid = *fid; + cii->c_vnode = inode; } - /* new, empty inode found... initializing */ - - /* Initialize the Coda inode info structure */ - cii->c_fid = *fid; - cii->c_vnode = inode; + /* we shouldnt see inode collisions anymore */ + if ( !coda_fideq(fid, &cii->c_fid) ) BUG(); -out: + /* always replace the attributes, type might have changed */ coda_fill_inode(inode, attr); return inode; } @@ -107,7 +103,6 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) ENTRY; /* We get inode numbers from Venus -- see venus source */ - error = venus_getattr(sb, fid, &attr); if ( error ) { CDEBUG(D_CNODE, @@ -183,7 +178,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) if ( coda_fideq(&cii->c_fid, fid) ) { inode = cii->c_vnode; CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino); - iget(sb, inode->i_ino); + iget4(sb, inode->i_ino, coda_inocmp, fid); return inode; } } @@ -192,7 +187,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) /* fid is not weird: ino should be computable */ nr = coda_f2i(fid); - inode = iget(sb, nr); + inode = iget4(sb, nr, coda_inocmp, fid); if ( !inode ) { printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n", sb, (long)nr); @@ -202,18 +197,11 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) /* check if this inode is linked to a cnode */ cii = ITOC(inode); - /* make sure this is the one we want */ - if ( coda_fideq(fid, &cii->c_fid) ) { - CDEBUG(D_INODE, "found %ld\n", inode->i_ino); - return inode; - } - -#if 0 - printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr, coda_f2s(fid)); -#endif - iput(inode); - return NULL; + /* we shouldn't have inode collisions anymore */ + if ( !coda_fideq(fid, &cii->c_fid) ) BUG(); + CDEBUG(D_INODE, "found %ld\n", inode->i_ino); + return inode; } /* the CONTROL inode is made without asking attributes from Venus */ diff --git a/fs/exec.c b/fs/exec.c index 667e5dad9058..28cb7db4c06d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -388,10 +388,8 @@ static int exec_mmap(void) old_mm = current->mm; if (old_mm && atomic_read(&old_mm->mm_users) == 1) { - flush_cache_mm(old_mm); mm_release(); exit_mmap(old_mm); - flush_tlb_mm(old_mm); return 0; } diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 69f6f0ce9234..0d72631c89b6 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -36,7 +36,7 @@ #include "check.h" #include "msdos.h" -#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID +#if CONFIG_BLK_DEV_MD extern void md_autodetect_dev(kdev_t dev); #endif @@ -136,7 +136,7 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) add_gd_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); -#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID +#if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { md_autodetect_dev(MKDEV(hd->major,current_minor)); } @@ -448,7 +448,7 @@ check_table: continue; add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); -#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID +#if CONFIG_BLK_DEV_MD if (SYS_IND(p) == LINUX_RAID_PARTITION) { md_autodetect_dev(MKDEV(hd->major,minor)); } diff --git a/fs/udf/file.c b/fs/udf/file.c index 9ab57d370ec8..02aa4f025047 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -86,6 +86,7 @@ static int udf_adinicb_writepage(struct page *page) brelse(bh); SetPageUptodate(page); kunmap(page); + UnlockPage(page); return 0; } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 3783b43fdd85..8c818666ca84 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -203,7 +203,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) udf_release_data(bh); inode->i_data.a_ops->writepage(page); - UnlockPage(page); page_cache_release(page); mark_inode_dirty(inode); diff --git a/include/asm-sh/current.h b/include/asm-sh/current.h index 355a2cd14588..c690c233b356 100644 --- a/include/asm-sh/current.h +++ b/include/asm-sh/current.h @@ -12,7 +12,7 @@ static __inline__ struct task_struct * get_current(void) { struct task_struct *current; - __asm__("stc $r7_bank, %0" + __asm__("stc r7_bank, %0" :"=r" (current)); return current; diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index b1a6f9461771..a448c6f00f38 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -39,6 +39,7 @@ extern void paging_init(void); #define flush_dcache_page(page) do { } while (0) #define flush_icache_range(start, end) do { } while (0) #define flush_icache_page(vma,pg) do { } while (0) +#define flush_cache_sigtramp(vaddr) do { } while (0) #elif defined(__SH4__) /* * Caches are broken on SH-4, so we need them. @@ -52,6 +53,7 @@ extern void flush_page_to_ram(struct page *page); extern void flush_dcache_page(struct page *pg); extern void flush_icache_range(unsigned long start, unsigned long end); extern void flush_icache_page(struct vm_area_struct *vma, struct page *pg); +extern void flush_cache_sigtramp(unsigned long addr); #endif /* @@ -125,11 +127,7 @@ extern unsigned long empty_zero_page[1024]; /* Hardware flags: SZ=1 (4k-byte) */ #define _PAGE_FLAGS_HARD 0x00000010 -#if defined(__sh3__) -#define _PAGE_SHARED _PAGE_HW_SHARED -#elif defined(__SH4__) #define _PAGE_SHARED _PAGE_U0_SHARED -#endif #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) diff --git a/include/asm-sh/sh_bios.h b/include/asm-sh/sh_bios.h index cdb73bdea28c..0ca261956e3d 100644 --- a/include/asm-sh/sh_bios.h +++ b/include/asm-sh/sh_bios.h @@ -13,5 +13,7 @@ extern void sh_bios_char_out(char ch); extern int sh_bios_in_gdb_mode(void); extern void sh_bios_gdb_detach(void); +extern void sh_bios_get_node_addr(unsigned char *node_addr); +extern void sh_bios_shutdown(unsigned int how); #endif /* __ASM_SH_BIOS_H */ diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 86786c730665..a8f720582de4 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -6,6 +6,7 @@ */ #include +#include /* * switch_to() should switch tasks to task nr n, first @@ -28,37 +29,37 @@ typedef struct { register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp; \ register unsigned long __ts7 __asm__ ("r7") = next->thread.pc; \ __asm__ __volatile__ (".balign 4\n\t" \ - "stc.l $gbr, @-$r15\n\t" \ - "sts.l $pr, @-$r15\n\t" \ - "mov.l $r8, @-$r15\n\t" \ - "mov.l $r9, @-$r15\n\t" \ - "mov.l $r10, @-$r15\n\t" \ - "mov.l $r11, @-$r15\n\t" \ - "mov.l $r12, @-$r15\n\t" \ - "mov.l $r13, @-$r15\n\t" \ - "mov.l $r14, @-$r15\n\t" \ - "mov.l $r15, @$r1 ! save SP\n\t" \ - "mov.l @$r6, $r15 ! change to new stack\n\t" \ - "mov.l %0, @-$r15 ! push R0 onto new stack\n\t" \ + "stc.l gbr, @-r15\n\t" \ + "sts.l pr, @-r15\n\t" \ + "mov.l r8, @-r15\n\t" \ + "mov.l r9, @-r15\n\t" \ + "mov.l r10, @-r15\n\t" \ + "mov.l r11, @-r15\n\t" \ + "mov.l r12, @-r15\n\t" \ + "mov.l r13, @-r15\n\t" \ + "mov.l r14, @-r15\n\t" \ + "mov.l r15, @r1 ! save SP\n\t" \ + "mov.l @r6, r15 ! change to new stack\n\t" \ + "mov.l %0, @-r15 ! push R0 onto new stack\n\t" \ "mova 1f, %0\n\t" \ - "mov.l %0, @$r2 ! save PC\n\t" \ + "mov.l %0, @r2 ! save PC\n\t" \ "mov.l 2f, %0\n\t" \ "jmp @%0 ! call __switch_to\n\t" \ - " lds $r7, $pr ! with return to new PC\n\t" \ + " lds r7, pr ! with return to new PC\n\t" \ ".balign 4\n" \ "2:\n\t" \ ".long " "__switch_to\n" \ "1:\n\t" \ - "mov.l @$r15+, %0 ! pop R0 from new stack\n\t" \ - "mov.l @$r15+, $r14\n\t" \ - "mov.l @$r15+, $r13\n\t" \ - "mov.l @$r15+, $r12\n\t" \ - "mov.l @$r15+, $r11\n\t" \ - "mov.l @$r15+, $r10\n\t" \ - "mov.l @$r15+, $r9\n\t" \ - "mov.l @$r15+, $r8\n\t" \ - "lds.l @$r15+, $pr\n\t" \ - "ldc.l @$r15+, $gbr\n\t" \ + "mov.l @r15+, %0 ! pop R0 from new stack\n\t" \ + "mov.l @r15+, r14\n\t" \ + "mov.l @r15+, r13\n\t" \ + "mov.l @r15+, r12\n\t" \ + "mov.l @r15+, r11\n\t" \ + "mov.l @r15+, r10\n\t" \ + "mov.l @r15+, r9\n\t" \ + "mov.l @r15+, r8\n\t" \ + "lds.l @r15+, pr\n\t" \ + "ldc.l @r15+, gbr\n\t" \ :"=&z" (__last) \ :"0" (prev), \ "r" (__ts1), "r" (__ts2), \ @@ -107,11 +108,11 @@ static __inline__ void __sti(void) { unsigned long __dummy0, __dummy1; - __asm__ __volatile__("stc $sr, %0\n\t" + __asm__ __volatile__("stc sr, %0\n\t" "and %1, %0\n\t" - "stc $r6_bank, %1\n\t" + "stc r6_bank, %1\n\t" "or %1, %0\n\t" - "ldc %0, $sr" + "ldc %0, sr" : "=&r" (__dummy0), "=r" (__dummy1) : "1" (~0x000000f0) : "memory"); @@ -120,9 +121,9 @@ static __inline__ void __sti(void) static __inline__ void __cli(void) { unsigned long __dummy; - __asm__ __volatile__("stc $sr, %0\n\t" + __asm__ __volatile__("stc sr, %0\n\t" "or #0xf0, %0\n\t" - "ldc %0, $sr" + "ldc %0, sr" : "=&z" (__dummy) : /* no inputs */ : "memory"); @@ -131,7 +132,7 @@ static __inline__ void __cli(void) #define __save_flags(x) \ x = (__extension__ ({ unsigned long __sr; \ __asm__ __volatile__( \ - "stc $sr, %0" \ + "stc sr, %0" \ : "=&r" (__sr) \ : /* no inputs */ \ : "memory"); \ @@ -140,10 +141,10 @@ x = (__extension__ ({ unsigned long __sr; \ #define __save_and_cli(x) \ x = (__extension__ ({ unsigned long __dummy,__sr; \ __asm__ __volatile__( \ - "stc $sr, %1\n\t" \ + "stc sr, %1\n\t" \ "mov %1, %0\n\t" \ "or #0xf0, %0\n\t" \ - "ldc %0, $sr" \ + "ldc %0, sr" \ : "=&z" (__dummy), "=&r" (__sr) \ : /* no inputs */ \ : "memory"); (__sr & 0x000000f0); })) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 38b7a6a982a5..4fce3f847249 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -28,19 +28,6 @@ #include #endif /* __KERNEL__ */ -/* - * System sleep states - */ -enum -{ - ACPI_S0, /* working */ - ACPI_S1, /* sleep */ - ACPI_S2, /* sleep */ - ACPI_S3, /* sleep */ - ACPI_S4, /* non-volatile sleep */ - ACPI_S5, /* soft-off */ -}; - typedef int acpi_sstate_t; /* diff --git a/include/linux/dn.h b/include/linux/dn.h index d98b0c3c7903..782cae49e64c 100644 --- a/include/linux/dn.h +++ b/include/linux/dn.h @@ -143,6 +143,5 @@ struct dn_addr { #define SIOCGNETADDR _IOR(DECNET_IOCTL_BASE, 0xe1, struct dn_naddr) #define OSIOCSNETADDR _IOW(DECNET_IOCTL_BASE, 0xe0, int) #define OSIOCGNETADDR _IOR(DECNET_IOCTL_BASE, 0xe1, int) -/* #define SIOCATEOR _IOR(DECNET_IOCTL_BASE, 0x01, int) */ #endif /* _LINUX_DN_H */ diff --git a/include/linux/lvm.h b/include/linux/lvm.h index 7b4ff94f9e53..07dac6c3677b 100644 --- a/include/linux/lvm.h +++ b/include/linux/lvm.h @@ -9,6 +9,7 @@ * May-July 1998 * January-March,July,September,October,Dezember 1999 * January,February,July,November 2000 + * January 2001 * * lvm is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +58,8 @@ * 26/06/2000 - implemented snapshot persistency and resizing support * 02/11/2000 - added hash table size member to lv structure * 12/11/2000 - removed unneeded timestamp definitions + * 24/12/2000 - removed LVM_TO_{CORE,DISK}*, use cpu_{from, to}_le* + * instead - Christoph Hellwig * */ @@ -64,11 +67,9 @@ #ifndef _LVM_H_INCLUDE #define _LVM_H_INCLUDE -#define _LVM_KERNEL_H_VERSION "LVM 0.9 (13/11/2000)" +#define _LVM_KERNEL_H_VERSION "LVM 0.9.1_beta2 (18/01/2001)" -#include #include -#include /* * preprocessor definitions @@ -77,8 +78,7 @@ #define LVM_TOTAL_RESET #ifdef __KERNEL__ -#define LVM_GET_INODE -#undef LVM_HD_NAME /* display nice names in /proc/partitions */ +#undef LVM_HD_NAME /* display nice names in /proc/partitions */ /* lots of debugging output (see driver source) #define DEBUG_LVM_GET_INFO @@ -109,6 +109,7 @@ #ifdef __KERNEL__ #include + #include #endif /* #ifdef __KERNEL__ */ @@ -216,15 +217,13 @@ * * 1K volume group structure ~200 byte * - * 5K time stamp structure ~ - * * 6K namelist of physical volumes 128 byte each * - * 6k + n * 128byte n logical volume structures ~300 byte each + * 6k + n * ~300byte n logical volume structures ~300 byte each * - * + m * 328byte m physical extent alloc. structs 4 byte each + * + m * 4byte m physical extent alloc. structs 4 byte each * - * End of disk - first physical extent typical 4 megabyte + * End of disk - first physical extent typically 4 megabyte * PE total * * PE size * @@ -292,7 +291,7 @@ #define LVM_MAX_PE_SIZE ( 16L * 1024L * 1024L / SECTOR_SIZE * 1024) /* 16GB in sectors */ #define LVM_DEFAULT_PE_SIZE ( 4096L * 1024 / SECTOR_SIZE) /* 4 MB in sectors */ #define LVM_DEFAULT_STRIPE_SIZE 16L /* 16 KB */ -#define LVM_MIN_STRIPE_SIZE ( PAGE_SIZE>>9) /* PAGESIZE in sectors */ +#define LVM_MIN_STRIPE_SIZE ( PAGE_SIZE/SECTOR_SIZE) /* PAGESIZE in sectors */ #define LVM_MAX_STRIPE_SIZE ( 512L * 1024 / SECTOR_SIZE) /* 512 KB in sectors */ #define LVM_MAX_STRIPES 128 /* max # of stripes */ #define LVM_MAX_SIZE ( 1024LU * 1024 / SECTOR_SIZE * 1024 * 1024) /* 1TB[sectors] */ @@ -326,51 +325,6 @@ COW_table_entries_per_PE - COW_table_chunks_per_PE;}) -/* to disk and to core data conversion macros */ -#if __BYTE_ORDER == __BIG_ENDIAN - -#define LVM_TO_CORE16(x) ( \ - ((uint16_t)((((uint16_t)(x) & 0x00FFU) << 8) | \ - (((uint16_t)(x) & 0xFF00U) >> 8)))) - -#define LVM_TO_DISK16(x) LVM_TO_CORE16(x) - -#define LVM_TO_CORE32(x) ( \ - ((uint32_t)((((uint32_t)(x) & 0x000000FFU) << 24) | \ - (((uint32_t)(x) & 0x0000FF00U) << 8))) \ - (((uint32_t)(x) & 0x00FF0000U) >> 8))) \ - (((uint32_t)(x) & 0xFF000000U) >> 24)))) - -#define LVM_TO_DISK32(x) LVM_TO_CORE32(x) - -#define LVM_TO_CORE64(x) \ - ((uint64_t)((((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \ - (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \ - (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \ - (((uint64_t)(x) & 0x00000000FF000000ULL) << 8) | \ - (((uint64_t)(x) & 0x000000FF00000000ULL) >> 8) | \ - (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \ - (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \ - (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56))) - -#define LVM_TO_DISK64(x) LVM_TO_CORE64(x) - -#elif __BYTE_ORDER == __LITTLE_ENDIAN - -#define LVM_TO_CORE16(x) x -#define LVM_TO_DISK16(x) x -#define LVM_TO_CORE32(x) x -#define LVM_TO_DISK32(x) x -#define LVM_TO_CORE64(x) x -#define LVM_TO_DISK64(x) x - -#else - -#error "__BYTE_ORDER must be defined as __LITTLE_ENDIAN or __BIG_ENDIAN" - -#endif /* #if __BYTE_ORDER == __BIG_ENDIAN */ - - /* * ioctls */ @@ -687,6 +641,8 @@ typedef struct lv_v4 { wait_queue_head_t lv_snapshot_wait; int lv_snapshot_use_rate; void *vg; + + uint lv_allocated_snapshot_le; #else char dummy[200]; #endif diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 1ee4dd6167e1..4c77c2081721 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -74,7 +74,7 @@ struct nfs_readargs { struct nfs_readres { struct nfs_fattr * fattr; - unsigned int count; + __u32 count; int eof; }; @@ -84,7 +84,7 @@ struct nfs_readres { #define NFS_WRITE_MAXIOV 8 struct nfs_writeargs { struct nfs_fh * fh; - __u32 offset; + __u64 offset; __u32 count; enum nfs3_stable_how stable; unsigned int nriov; diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h index c96b0e404386..22a1543808c9 100644 --- a/include/linux/raid/md_u.h +++ b/include/linux/raid/md_u.h @@ -22,6 +22,7 @@ #define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) #define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) #define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) /* configuration */ #define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) diff --git a/include/linux/rtc.h b/include/linux/rtc.h index fba9111dacef..df958b66ada6 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -8,7 +8,7 @@ * Copyright (C) 1999 Hewlett-Packard Co. * Copyright (C) 1999 Stephane Eranian */ -#ifndef _LINUX_RTC_H +#ifndef _LINUX_RTC_H_ #define _LINUX_RTC_H_ /* diff --git a/include/net/dn.h b/include/net/dn.h index c4c598f2f15c..88a0bab3e072 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -58,7 +58,6 @@ struct dn_scp /* Session Control Port */ unsigned short segsize_rem; unsigned short segsize_loc; - unsigned char at_eor; unsigned char nonagle; unsigned char multi_ireq; unsigned char accept_mode; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 3efa00b11469..f362615000f5 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -395,6 +395,7 @@ EXPORT_SYMBOL(unmap_kiobuf); EXPORT_SYMBOL(lock_kiovec); EXPORT_SYMBOL(unlock_kiovec); EXPORT_SYMBOL(brw_kiovec); +EXPORT_SYMBOL(kiobuf_wait_for_io); /* dma handling */ EXPORT_SYMBOL(request_dma); diff --git a/mm/mmap.c b/mm/mmap.c index e5b3a989ed20..e1faba3c7ea4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -883,6 +883,8 @@ void exit_mmap(struct mm_struct * mm) mm->rss = 0; mm->total_vm = 0; mm->locked_vm = 0; + + flush_cache_mm(mm); while (mpnt) { struct vm_area_struct * next = mpnt->vm_next; unsigned long start = mpnt->vm_start; @@ -895,13 +897,13 @@ void exit_mmap(struct mm_struct * mm) } mm->map_count--; remove_shared_vm_struct(mpnt); - flush_cache_range(mm, start, end); zap_page_range(mm, start, size); if (mpnt->vm_file) fput(mpnt->vm_file); kmem_cache_free(vm_area_cachep, mpnt); mpnt = next; } + flush_tlb_mm(mm); /* This is just debugging */ if (mm->map_count) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index da59ab6ef3d9..b930878c2eef 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -439,7 +439,6 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp) scp->info_loc = 0x03; /* NSP version 4.1 */ scp->segsize_rem = 230; /* Default: Updated by remote segsize */ scp->segsize_loc = 1450; /* Best guess for ethernet */ - scp->at_eor = 1; scp->nonagle = 0; scp->multi_ireq = 1; scp->accept_mode = ACC_IMMED; @@ -1121,18 +1120,6 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) release_sock(sk); return val; -#ifdef SIOCATEOR - case SIOCATEOR: - lock_sock(sk); - val = scp->at_eor; - if (scp->state != DN_RUN) - val = -ENOTCONN; - if (sock->type != SOCK_SEQPACKET) - val = -EINVAL; - release_sock(sk); - return val; -#endif /* SIOCATEOR */ - #ifdef CONFIG_DECNET_ROUTER case SIOCADDRT: case SIOCDELRT: @@ -1768,14 +1755,10 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size, rv = copied; - if (!(flags & (MSG_PEEK|MSG_OOB))) - scp->at_eor = 0; - if (eor && (sk->type == SOCK_SEQPACKET)) { + if (eor && (sk->type == SOCK_SEQPACKET)) msg->msg_flags |= MSG_EOR; - if (!(flags & (MSG_PEEK|MSG_OOB))) - scp->at_eor = 1; - } + out: if (rv == 0) rv = (flags & MSG_PEEK) ? -sk->err : sock_error(sk); @@ -2042,12 +2025,12 @@ static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf) { int i; - switch (dn->sdn_objnamel) { + switch (dn_ntohs(dn->sdn_objnamel)) { case 0: sprintf(buf, "%d", dn->sdn_objnum); break; default: - for (i = 0; i < dn->sdn_objnamel; i++) { + for (i = 0; i < dn_ntohs(dn->sdn_objnamel); i++) { buf[i] = dn->sdn_objname[i]; if (IS_NOT_PRINTABLE(buf[i])) buf[i] = '.'; diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 9ba62dc8480a..cc19e1f0b5ee 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -438,8 +438,27 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, conntrack)); ret = 1; goto clear_fulls; + } else if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { + /* Try implicit source NAT; protocol + may be able to play with ports to + make it unique. */ + struct ip_nat_range r + = { IP_NAT_RANGE_MAP_IPS, + tuple->src.ip, tuple->src.ip, + { 0 }, { 0 } }; + DEBUGP("Trying implicit mapping\n"); + if (proto->unique_tuple(tuple, &r, + IP_NAT_MANIP_SRC, + conntrack)) { + /* Must be unique. */ + IP_NF_ASSERT(!ip_nat_used_tuple + (tuple, conntrack)); + ret = 1; + goto clear_fulls; + } } - DEBUGP("Protocol can't get unique tuple.\n"); + DEBUGP("Protocol can't get unique tuple %u.\n", + hooknum); } /* Eliminate that from range, and try again. */ diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 99164a7a0201..3d7afadb0996 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -68,6 +68,7 @@ masquerade_target(struct sk_buff **pskb, struct ip_nat_multi_range newrange; u_int32_t newsrc; struct rtable *rt; + struct rt_key key; IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); @@ -82,10 +83,14 @@ masquerade_target(struct sk_buff **pskb, mr = targinfo; - if (ip_route_output(&rt, (*pskb)->nh.iph->daddr, - 0, - RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN, - out->ifindex) != 0) { + key.dst = (*pskb)->nh.iph->daddr; + key.src = 0; /* Unknown: that's what we're trying to establish */ + key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN; + key.oif = out->ifindex; +#ifdef CONFIG_IP_ROUTE_FWMARK + key.fwmark = (*pskb)->nfmark; +#endif + if (ip_route_output_key(&rt, &key) != 0) { /* Shouldn't happen */ printk("MASQUERADE: No route: Rusty's brain broke!\n"); return NF_DROP; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index c52ada64e606..60d4698fb74e 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -53,7 +53,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_standard), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_standard_target), "" } }, { } }, + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } }, /* LOCAL_OUT */ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, @@ -61,7 +61,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_standard), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_standard_target), "" } }, { } }, + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } } }, /* ERROR */ @@ -70,7 +70,7 @@ static struct sizeof(struct ipt_entry), sizeof(struct ipt_error), 0, { 0, 0 }, { } }, - { { { { sizeof(struct ipt_error_target), IPT_ERROR_TARGET } }, + { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } }, { } }, "ERROR" } diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index e5504ee96e9d..250b22ae9a96 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2409,6 +2409,7 @@ int __init irda_proto_init(void) #endif return 0; } +module_init(irda_proto_init); /* * Function irda_proto_cleanup (void) @@ -2429,11 +2430,9 @@ void irda_proto_cleanup(void) return; } -module_init(irda_proto_init); module_exit(irda_proto_cleanup); MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l"); #endif /* MODULE */ - -- cgit v1.2.3