diff --git a/[refs] b/[refs] index 028faa4beb13..0c7b96a9bc9a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 21d37bbc65e39a26856de6b14be371ff24e0d03f +refs/heads/master: 9990fa3cbd35046cce1eb4667bb2e33057c5ca1a diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index b3d1ce7e3ba0..0ba6af02cdaf 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -274,7 +274,6 @@ Who: Venkatesh Pallipadi --------------------------- -<<<<<<< test:Documentation/feature-removal-schedule.txt What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY) When: 2.6.21 Why: hotkey.c was an attempt to consolidate multiple drivers that use @@ -307,15 +306,8 @@ Why: The ACPI namespace is effectively the symbol list for the BIOS can be extracted and disassembled with acpidump and iasl as documented in the pmtools package here: http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils -Who: Len Brown - ---------------------------- -What: ACPI procfs interface -When: July 2007 -Why: After ACPI sysfs conversion, ACPI attributes will be duplicated - in sysfs and the ACPI procfs interface should be removed. -Who: Zhang Rui +Who: Len Brown --------------------------- diff --git a/trunk/Documentation/s390/Debugging390.txt b/trunk/Documentation/s390/Debugging390.txt index 0993969609cf..3f9ddbc23b27 100644 --- a/trunk/Documentation/s390/Debugging390.txt +++ b/trunk/Documentation/s390/Debugging390.txt @@ -480,7 +480,7 @@ r2 argument 0 / return value 0 call-clobbered r3 argument 1 / return value 1 (if long long) call-clobbered r4 argument 2 call-clobbered r5 argument 3 call-clobbered -r6 argument 4 saved +r6 argument 5 saved r7 pointer-to arguments 5 to ... saved r8 this & that saved r9 this & that saved diff --git a/trunk/Documentation/video-output.txt b/trunk/Documentation/video-output.txt deleted file mode 100644 index e517011be4f9..000000000000 --- a/trunk/Documentation/video-output.txt +++ /dev/null @@ -1,34 +0,0 @@ - - Video Output Switcher Control - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 2006 luming.yu@intel.com - -The output sysfs class driver provides an abstract video output layer that -can be used to hook platform specific methods to enable/disable video output -device through common sysfs interface. For example, on my IBM ThinkPad T42 -laptop, The ACPI video driver registered its output devices and read/write -method for 'state' with output sysfs class. The user interface under sysfs is: - -linux:/sys/class/video_output # tree . -. -|-- CRT0 -| |-- device -> ../../../devices/pci0000:00/0000:00:01.0 -| |-- state -| |-- subsystem -> ../../../class/video_output -| `-- uevent -|-- DVI0 -| |-- device -> ../../../devices/pci0000:00/0000:00:01.0 -| |-- state -| |-- subsystem -> ../../../class/video_output -| `-- uevent -|-- LCD0 -| |-- device -> ../../../devices/pci0000:00/0000:00:01.0 -| |-- state -| |-- subsystem -> ../../../class/video_output -| `-- uevent -`-- TV0 - |-- device -> ../../../devices/pci0000:00/0000:00:01.0 - |-- state - |-- subsystem -> ../../../class/video_output - `-- uevent - diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 96135d285eb0..0ad8803a0c75 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -584,14 +584,6 @@ W: http://sourceforge.net/projects/acpi4asus W: http://xf.iksaif.net/acpi4asus S: Maintained -ASUS LAPTOP EXTRAS DRIVER -P: Corentin Chary -M: corentincj@iksaif.net -L: acpi4asus-user@lists.sourceforge.net -W: http://sourceforge.net/projects/acpi4asus -W: http://xf.iksaif.net/acpi4asus -S: Maintained - ATA OVER ETHERNET DRIVER P: Ed L. Cashin M: ecashin@coraid.com @@ -2799,7 +2791,7 @@ M: schwidefsky@de.ibm.com P: Heiko Carstens M: heiko.carstens@de.ibm.com M: linux390@de.ibm.com -L: linux-s390@vger.kernel.org +L: linux-390@vm.marist.edu W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported @@ -2807,7 +2799,7 @@ S390 NETWORK DRIVERS P: Frank Pavlic M: fpavlic@de.ibm.com M: linux390@de.ibm.com -L: linux-s390@vger.kernel.org +L: linux-390@vm.marist.edu W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported @@ -2815,7 +2807,7 @@ S390 ZFCP DRIVER P: Swen Schillig M: swen@vnet.ibm.com M: linux390@de.ibm.com -L: linux-s390@vger.kernel.org +L: linux-390@vm.marist.edu W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported @@ -3655,7 +3647,7 @@ S: Maintained W83L51xD SD/MMC CARD INTERFACE DRIVER P: Pierre Ossman M: drzeus-wbsd@drzeus.cx -L: linux-kernel@vger.kernel.org +L: wbsd-devel@list.drzeus.cx W: http://projects.drzeus.cx/wbsd S: Maintained diff --git a/trunk/Makefile b/trunk/Makefile index cdeda68cf2aa..7e2750f4ca70 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -776,7 +776,7 @@ $(vmlinux-dirs): prepare scripts # $(EXTRAVERSION) eg, -rc6 # $(localver-full) # $(localver) -# localversion* (files without backups, containing '~') +# localversion* (all localversion* files) # $(CONFIG_LOCALVERSION) (from kernel config setting) # $(localver-auto) (only if CONFIG_LOCALVERSION_AUTO is set) # ./scripts/setlocalversion (SCM tag, if one exists) @@ -787,12 +787,17 @@ $(vmlinux-dirs): prepare scripts # moment, only git is supported but other SCMs can edit the script # scripts/setlocalversion and add the appropriate checks as needed. -pattern = ".*/localversion[^~]*" -string = $(shell cat /dev/null \ - `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`) +nullstring := +space := $(nullstring) # end of line -localver = $(subst $(space),, $(string) \ - $(patsubst "%",%,$(CONFIG_LOCALVERSION))) +___localver = $(objtree)/localversion* $(srctree)/localversion* +__localver = $(sort $(wildcard $(___localver))) +# skip backup files (containing '~') +_localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f))) + +localver = $(subst $(space),, \ + $(shell cat /dev/null $(_localver)) \ + $(patsubst "%",%,$(CONFIG_LOCALVERSION))) # If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called # and if the SCM is know a tag from the SCM is appended. diff --git a/trunk/arch/i386/defconfig b/trunk/arch/i386/defconfig index bb0c376b62b3..5d80edfc61b7 100644 --- a/trunk/arch/i386/defconfig +++ b/trunk/arch/i386/defconfig @@ -466,8 +466,7 @@ CONFIG_FW_LOADER=y # # Plug and Play support # -CONFIG_PNP=y -CONFIG_PNPACPI=y +# CONFIG_PNP is not set # # Block devices diff --git a/trunk/arch/i386/kernel/acpi/boot.c b/trunk/arch/i386/kernel/acpi/boot.c index e94aff6888ca..cbcb2c27f48b 100644 --- a/trunk/arch/i386/kernel/acpi/boot.c +++ b/trunk/arch/i386/kernel/acpi/boot.c @@ -66,7 +66,7 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ - ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) + ((acpi_table_entry_header *)entry)->length < sizeof(*entry)) #define PREFIX "ACPI: " @@ -79,7 +79,7 @@ int acpi_ioapic; int acpi_strict; EXPORT_SYMBOL(acpi_strict); -u8 acpi_sci_flags __initdata; +acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; int acpi_use_timer_override __initdata; @@ -92,6 +92,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #warning ACPI uses CMPXCHG, i486 and later hardware #endif +#define MAX_MADT_ENTRIES 256 +u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = + {[0 ... MAX_MADT_ENTRIES - 1] = 0xff }; +EXPORT_SYMBOL(x86_acpiid_to_apicid); + /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -161,26 +166,30 @@ char *__acpi_map_table(unsigned long phys, unsigned long size) #ifdef CONFIG_PCI_MMCONFIG /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ -struct acpi_mcfg_allocation *pci_mmcfg_config; +struct acpi_table_mcfg_config *pci_mmcfg_config; int pci_mmcfg_config_num; -int __init acpi_parse_mcfg(struct acpi_table_header *header) +int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) { struct acpi_table_mcfg *mcfg; unsigned long i; int config_size; - if (!header) + if (!phys_addr || !size) return -EINVAL; - mcfg = (struct acpi_table_mcfg *)header; + mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size); + if (!mcfg) { + printk(KERN_WARNING PREFIX "Unable to map MCFG\n"); + return -ENODEV; + } /* how many config structures do we have */ pci_mmcfg_config_num = 0; - i = header->length - sizeof(struct acpi_table_mcfg); - while (i >= sizeof(struct acpi_mcfg_allocation)) { + i = size - sizeof(struct acpi_table_mcfg); + while (i >= sizeof(struct acpi_table_mcfg_config)) { ++pci_mmcfg_config_num; - i -= sizeof(struct acpi_mcfg_allocation); + i -= sizeof(struct acpi_table_mcfg_config); }; if (pci_mmcfg_config_num == 0) { printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); @@ -195,9 +204,9 @@ int __init acpi_parse_mcfg(struct acpi_table_header *header) return -ENOMEM; } - memcpy(pci_mmcfg_config, &mcfg[1], config_size); + memcpy(pci_mmcfg_config, &mcfg->config, config_size); for (i = 0; i < pci_mmcfg_config_num; ++i) { - if (pci_mmcfg_config[i].address > 0xFFFFFFFF) { + if (mcfg->config[i].base_reserved) { printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); kfree(pci_mmcfg_config); @@ -211,24 +220,24 @@ int __init acpi_parse_mcfg(struct acpi_table_header *header) #endif /* CONFIG_PCI_MMCONFIG */ #ifdef CONFIG_X86_LOCAL_APIC -static int __init acpi_parse_madt(struct acpi_table_header *table) +static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size) { struct acpi_table_madt *madt = NULL; - if (!cpu_has_apic) + if (!phys_addr || !size || !cpu_has_apic) return -EINVAL; - madt = (struct acpi_table_madt *)table; + madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size); if (!madt) { printk(KERN_WARNING PREFIX "Unable to map MADT\n"); return -ENODEV; } - if (madt->address) { - acpi_lapic_addr = (u64) madt->address; + if (madt->lapic_address) { + acpi_lapic_addr = (u64) madt->lapic_address; printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n", - madt->address); + madt->lapic_address); } acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); @@ -237,17 +246,21 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) } static int __init -acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lapic(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_apic *processor = NULL; + struct acpi_table_lapic *processor = NULL; - processor = (struct acpi_madt_local_apic *)header; + processor = (struct acpi_table_lapic *)header; if (BAD_MADT_ENTRY(processor, end)) return -EINVAL; acpi_table_print_madt_entry(header); + /* Record local apic id only when enabled */ + if (processor->flags.enabled) + x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + /* * We need to register disabled CPU as well to permit * counting disabled CPUs. This allows us to size @@ -256,18 +269,18 @@ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) * when we use CPU hotplug. */ mp_register_lapic(processor->id, /* APIC ID */ - processor->lapic_flags & ACPI_MADT_ENABLED); /* Enabled? */ + processor->flags.enabled); /* Enabled? */ return 0; } static int __init -acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, +acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL; + struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; - lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header; + lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr *)header; if (BAD_MADT_ENTRY(lapic_addr_ovr, end)) return -EINVAL; @@ -278,11 +291,11 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, } static int __init -acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_apic_nmi *lapic_nmi = NULL; + struct acpi_table_lapic_nmi *lapic_nmi = NULL; - lapic_nmi = (struct acpi_madt_local_apic_nmi *)header; + lapic_nmi = (struct acpi_table_lapic_nmi *)header; if (BAD_MADT_ENTRY(lapic_nmi, end)) return -EINVAL; @@ -300,11 +313,11 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e #ifdef CONFIG_X86_IO_APIC static int __init -acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_io_apic *ioapic = NULL; + struct acpi_table_ioapic *ioapic = NULL; - ioapic = (struct acpi_madt_io_apic *)header; + ioapic = (struct acpi_table_ioapic *)header; if (BAD_MADT_ENTRY(ioapic, end)) return -EINVAL; @@ -329,11 +342,11 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) polarity = 3; /* Command-line over-ride via acpi_sci= */ - if (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) - trigger = (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2; + if (acpi_sci_flags.trigger) + trigger = acpi_sci_flags.trigger; - if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK) - polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK; + if (acpi_sci_flags.polarity) + polarity = acpi_sci_flags.polarity; /* * mp_config_acpi_legacy_irqs() already setup IRQs < 16 @@ -344,52 +357,51 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) /* * stash over-ride to indicate we've been here - * and for later update of acpi_gbl_FADT + * and for later update of acpi_fadt */ acpi_sci_override_gsi = gsi; return; } static int __init -acpi_parse_int_src_ovr(struct acpi_subtable_header * header, +acpi_parse_int_src_ovr(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_interrupt_override *intsrc = NULL; + struct acpi_table_int_src_ovr *intsrc = NULL; - intsrc = (struct acpi_madt_interrupt_override *)header; + intsrc = (struct acpi_table_int_src_ovr *)header; if (BAD_MADT_ENTRY(intsrc, end)) return -EINVAL; acpi_table_print_madt_entry(header); - if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { + if (intsrc->bus_irq == acpi_fadt.sci_int) { acpi_sci_ioapic_setup(intsrc->global_irq, - intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, - (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2); + intsrc->flags.polarity, + intsrc->flags.trigger); return 0; } if (acpi_skip_timer_override && - intsrc->source_irq == 0 && intsrc->global_irq == 2) { + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); return 0; } - mp_override_legacy_irq(intsrc->source_irq, - intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, - (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2, - intsrc->global_irq); + mp_override_legacy_irq(intsrc->bus_irq, + intsrc->flags.polarity, + intsrc->flags.trigger, intsrc->global_irq); return 0; } static int __init -acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_nmi_source *nmi_src = NULL; + struct acpi_table_nmi_src *nmi_src = NULL; - nmi_src = (struct acpi_madt_nmi_source *)header; + nmi_src = (struct acpi_table_nmi_src *)header; if (BAD_MADT_ENTRY(nmi_src, end)) return -EINVAL; @@ -405,7 +417,7 @@ acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end /* * acpi_pic_sci_set_trigger() - * + * * use ELCR to set PIC-mode trigger type for SCI * * If a PIC-mode SCI is not recognized or gives spurious IRQ7's @@ -499,7 +511,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; - struct acpi_madt_local_apic *lapic; + struct acpi_table_lapic *lapic; cpumask_t tmp_map, new_map; u8 physid; int cpu; @@ -517,10 +529,10 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) return -EINVAL; } - lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer; + lapic = (struct acpi_table_lapic *)obj->buffer.pointer; - if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC || - !(lapic->lapic_flags & ACPI_MADT_ENABLED)) { + if ((lapic->header.type != ACPI_MADT_LAPIC) || + (!lapic->flags.enabled)) { kfree(buffer.pointer); return -EINVAL; } @@ -532,7 +544,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) buffer.pointer = NULL; tmp_map = cpu_present_map; - mp_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED); + mp_register_lapic(physid, lapic->flags.enabled); /* * If mp_register_lapic successfully generates a new logical cpu @@ -554,6 +566,14 @@ EXPORT_SYMBOL(acpi_map_lsapic); int acpi_unmap_lsapic(int cpu) { + int i; + + for_each_possible_cpu(i) { + if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) { + x86_acpiid_to_apicid[i] = -1; + break; + } + } x86_cpu_to_apicid[cpu] = -1; cpu_clear(cpu, cpu_present_map); num_processors--; @@ -599,36 +619,42 @@ acpi_scan_rsdp(unsigned long start, unsigned long length) return 0; } -static int __init acpi_parse_sbf(struct acpi_table_header *table) +static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size) { - struct acpi_table_boot *sb; + struct acpi_table_sbf *sb; + + if (!phys_addr || !size) + return -EINVAL; - sb = (struct acpi_table_boot *)table; + sb = (struct acpi_table_sbf *)__acpi_map_table(phys_addr, size); if (!sb) { printk(KERN_WARNING PREFIX "Unable to map SBF\n"); return -ENODEV; } - sbf_port = sb->cmos_index; /* Save CMOS port */ + sbf_port = sb->sbf_cmos; /* Save CMOS port */ return 0; } #ifdef CONFIG_HPET_TIMER -static int __init acpi_parse_hpet(struct acpi_table_header *table) +static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) { struct acpi_table_hpet *hpet_tbl; struct resource *hpet_res; resource_size_t res_start; - hpet_tbl = (struct acpi_table_hpet *)table; + if (!phys || !size) + return -EINVAL; + + hpet_tbl = (struct acpi_table_hpet *)__acpi_map_table(phys, size); if (!hpet_tbl) { printk(KERN_WARNING PREFIX "Unable to map HPET\n"); return -ENODEV; } - if (hpet_tbl->address.space_id != ACPI_SPACE_MEM) { + if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) { printk(KERN_WARNING PREFIX "HPET timers must be located in " "memory.\n"); return -1; @@ -641,28 +667,29 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table) hpet_res->name = (void *)&hpet_res[1]; hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, - "HPET %u", hpet_tbl->sequence); + "HPET %u", hpet_tbl->number); hpet_res->end = (1 * 1024) - 1; } -#ifdef CONFIG_X86_64 - vxtime.hpet_address = hpet_tbl->address.address; +#ifdef CONFIG_X86_64 + vxtime.hpet_address = hpet_tbl->addr.addrl | + ((long)hpet_tbl->addr.addrh << 32); printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", - hpet_tbl->id, vxtime.hpet_address); + hpet_tbl->id, vxtime.hpet_address); res_start = vxtime.hpet_address; -#else /* X86 */ +#else /* X86 */ { extern unsigned long hpet_address; - hpet_address = hpet_tbl->address.address; + hpet_address = hpet_tbl->addr.addrl; printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", - hpet_tbl->id, hpet_address); + hpet_tbl->id, hpet_address); res_start = hpet_address; } -#endif /* X86 */ +#endif /* X86 */ if (hpet_res) { hpet_res->start = res_start; @@ -680,28 +707,42 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table) extern u32 pmtmr_ioport; #endif -static int __init acpi_parse_fadt(struct acpi_table_header *table) +static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) { + struct fadt_descriptor *fadt = NULL; + + fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size); + if (!fadt) { + printk(KERN_WARNING PREFIX "Unable to map FADT\n"); + return 0; + } + /* initialize sci_int early for INT_SRC_OVR MADT parsing */ + acpi_fadt.sci_int = fadt->sci_int; + + /* initialize rev and apic_phys_dest_mode for x86_64 genapic */ + acpi_fadt.revision = fadt->revision; + acpi_fadt.force_apic_physical_destination_mode = + fadt->force_apic_physical_destination_mode; #ifdef CONFIG_X86_PM_TIMER /* detect the location of the ACPI PM Timer */ - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) { + if (fadt->revision >= FADT2_REVISION_ID) { /* FADT rev. 2 */ - if (acpi_gbl_FADT.xpm_timer_block.space_id != + if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) return 0; - pmtmr_ioport = acpi_gbl_FADT.xpm_timer_block.address; + pmtmr_ioport = fadt->xpm_tmr_blk.address; /* * "X" fields are optional extensions to the original V1.0 * fields, so we must selectively expand V1.0 fields if the * corresponding X field is zero. */ if (!pmtmr_ioport) - pmtmr_ioport = acpi_gbl_FADT.pm_timer_block; + pmtmr_ioport = fadt->V1_pm_tmr_blk; } else { /* FADT rev. 1 */ - pmtmr_ioport = acpi_gbl_FADT.pm_timer_block; + pmtmr_ioport = fadt->V1_pm_tmr_blk; } if (pmtmr_ioport) printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", @@ -743,13 +784,13 @@ static int __init acpi_parse_madt_lapic_entries(void) if (!cpu_has_apic) return -ENODEV; - /* + /* * Note that the LAPIC address is obtained from the MADT (32-bit value) * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). */ count = - acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, + acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0); if (count < 0) { printk(KERN_ERR PREFIX @@ -759,7 +800,7 @@ static int __init acpi_parse_madt_lapic_entries(void) mp_register_lapic_address(acpi_lapic_addr); - count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic, + count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, MAX_APICS); if (!count) { printk(KERN_ERR PREFIX "No LAPIC entries present\n"); @@ -772,7 +813,7 @@ static int __init acpi_parse_madt_lapic_entries(void) } count = - acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0); + acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ @@ -801,7 +842,7 @@ static int __init acpi_parse_madt_ioapic_entries(void) return -ENODEV; } - if (!cpu_has_apic) + if (!cpu_has_apic) return -ENODEV; /* @@ -814,7 +855,7 @@ static int __init acpi_parse_madt_ioapic_entries(void) } count = - acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic, + acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS); if (!count) { printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); @@ -825,7 +866,7 @@ static int __init acpi_parse_madt_ioapic_entries(void) } count = - acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr, + acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); if (count < 0) { printk(KERN_ERR PREFIX @@ -839,13 +880,13 @@ static int __init acpi_parse_madt_ioapic_entries(void) * pretend we got one so we can set the SCI flags. */ if (!acpi_sci_override_gsi) - acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0); + acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0); /* Fill in identity legacy mapings where no override */ mp_config_acpi_legacy_irqs(); count = - acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src, + acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); if (count < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); @@ -867,7 +908,7 @@ static void __init acpi_process_madt(void) #ifdef CONFIG_X86_LOCAL_APIC int count, error; - count = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt); + count = acpi_table_parse(ACPI_APIC, acpi_parse_madt); if (count >= 1) { /* @@ -1154,7 +1195,7 @@ int __init acpi_boot_table_init(void) if (acpi_disabled && !acpi_ht) return 1; - /* + /* * Initialize the ACPI boot-time table parser. */ error = acpi_table_init(); @@ -1163,7 +1204,7 @@ int __init acpi_boot_table_init(void) return error; } - acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); + acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); /* * blacklist may disable ACPI entirely @@ -1191,19 +1232,19 @@ int __init acpi_boot_init(void) if (acpi_disabled && !acpi_ht) return 1; - acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); + acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); /* * set sci_int and PM timer address */ - acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt); + acpi_table_parse(ACPI_FADT, acpi_parse_fadt); /* * Process the Multiple APIC Description Table (MADT), if present */ acpi_process_madt(); - acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); + acpi_table_parse(ACPI_HPET, acpi_parse_hpet); return 0; } @@ -1274,17 +1315,13 @@ static int __init setup_acpi_sci(char *s) if (!s) return -EINVAL; if (!strcmp(s, "edge")) - acpi_sci_flags = ACPI_MADT_TRIGGER_EDGE | - (acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK); + acpi_sci_flags.trigger = 1; else if (!strcmp(s, "level")) - acpi_sci_flags = ACPI_MADT_TRIGGER_LEVEL | - (acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK); + acpi_sci_flags.trigger = 3; else if (!strcmp(s, "high")) - acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_HIGH | - (acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK); + acpi_sci_flags.polarity = 1; else if (!strcmp(s, "low")) - acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_LOW | - (acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK); + acpi_sci_flags.polarity = 3; else return -EINVAL; return 0; diff --git a/trunk/arch/i386/kernel/acpi/earlyquirk.c b/trunk/arch/i386/kernel/acpi/earlyquirk.c index bf86f7662d8b..4b60af7f91dd 100644 --- a/trunk/arch/i386/kernel/acpi/earlyquirk.c +++ b/trunk/arch/i386/kernel/acpi/earlyquirk.c @@ -16,7 +16,7 @@ static int nvidia_hpet_detected __initdata; -static int __init nvidia_hpet_check(struct acpi_table_header *header) +static int __init nvidia_hpet_check(unsigned long phys, unsigned long size) { nvidia_hpet_detected = 1; return 0; @@ -30,7 +30,7 @@ static int __init check_bridge(int vendor, int device) is enabled. */ if (!acpi_use_timer_override && vendor == PCI_VENDOR_ID_NVIDIA) { nvidia_hpet_detected = 0; - acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check); + acpi_table_parse(ACPI_HPET, nvidia_hpet_check); if (nvidia_hpet_detected == 0) { acpi_skip_timer_override = 1; printk(KERN_INFO "Nvidia board " diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c index a3db9332d652..e940e00b96c9 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -190,7 +190,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) /* Invoke C3 */ inb(cx_address); /* Dummy op - must do something useless after P_LVL3 read */ - t = inl(acpi_gbl_FADT.xpm_timer_block.address); + t = inl(acpi_fadt.xpm_tmr_blk.address); } /* Disable bus ratio bit */ local_irq_disable(); @@ -250,7 +250,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index) outb(3, 0x22); } else if ((pr != NULL) && pr->flags.bm_control) { /* Disable bus master arbitration */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, + ACPI_MTX_DO_NOT_LOCK); } switch (longhaul_version) { @@ -280,7 +281,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index) case TYPE_POWERSAVER: if (longhaul_flags & USE_ACPI_C3) { /* Don't allow wakeup */ - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, + ACPI_MTX_DO_NOT_LOCK); do_powersaver(cx->address, clock_ratio_index); } else { do_powersaver(0, clock_ratio_index); @@ -293,7 +295,8 @@ static void longhaul_setstate(unsigned int clock_ratio_index) outb(0, 0x22); } else if ((pr != NULL) && pr->flags.bm_control) { /* Enable bus master arbitration */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, + ACPI_MTX_DO_NOT_LOCK); } outb(pic2_mask,0xA1); /* restore mask */ outb(pic1_mask,0x21); @@ -411,7 +414,7 @@ static int __init longhaul_get_ranges(void) highest_speed = calc_speed(maxmult); lowest_speed = calc_speed(minmult); dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb, - print_speed(lowest_speed/1000), + print_speed(lowest_speed/1000), print_speed(highest_speed/1000)); if (lowest_speed == highest_speed) { @@ -495,7 +498,7 @@ static void __init longhaul_setup_voltagescaling(void) maxvid.mV/1000, maxvid.mV%1000, minvid.mV/1000, minvid.mV%1000, numvscales); - + j = 0; while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { speed = longhaul_table[j].frequency; diff --git a/trunk/arch/i386/kernel/mpparse.c b/trunk/arch/i386/kernel/mpparse.c index 4f5983c98669..49bff3596bff 100644 --- a/trunk/arch/i386/kernel/mpparse.c +++ b/trunk/arch/i386/kernel/mpparse.c @@ -1057,7 +1057,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) static int gsi_to_irq[MAX_GSI_NUM]; /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_gbl_FADT.sci_interrupt == gsi) + if (acpi_fadt.sci_int == gsi) return gsi; ioapic = mp_find_ioapic(gsi); @@ -1114,7 +1114,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) /* * Don't assign IRQ used by ACPI SCI */ - if (gsi == acpi_gbl_FADT.sci_interrupt) + if (gsi == acpi_fadt.sci_int) gsi = pci_irq++; gsi_to_irq[irq] = gsi; } else { diff --git a/trunk/arch/i386/kernel/srat.c b/trunk/arch/i386/kernel/srat.c index 2a8713ec0f9a..f7e735c077c3 100644 --- a/trunk/arch/i386/kernel/srat.c +++ b/trunk/arch/i386/kernel/srat.c @@ -62,19 +62,19 @@ extern void * boot_ioremap(unsigned long, unsigned long); /* Identify CPU proximity domains */ static void __init parse_cpu_affinity_structure(char *p) { - struct acpi_srat_cpu_affinity *cpu_affinity = - (struct acpi_srat_cpu_affinity *) p; + struct acpi_table_processor_affinity *cpu_affinity = + (struct acpi_table_processor_affinity *) p; - if ((cpu_affinity->flags & ACPI_SRAT_CPU_ENABLED) == 0) + if (!cpu_affinity->flags.enabled) return; /* empty entry */ /* mark this node as "seen" in node bitmap */ - BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo); + BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain); - apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo; + apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain; printk("CPU 0x%02X in proximity domain 0x%02X\n", - cpu_affinity->apic_id, cpu_affinity->proximity_domain_lo); + cpu_affinity->apic_id, cpu_affinity->proximity_domain); } /* @@ -84,27 +84,28 @@ static void __init parse_cpu_affinity_structure(char *p) static void __init parse_memory_affinity_structure (char *sratp) { unsigned long long paddr, size; - unsigned long start_pfn, end_pfn; + unsigned long start_pfn, end_pfn; u8 pxm; struct node_memory_chunk_s *p, *q, *pend; - struct acpi_srat_mem_affinity *memory_affinity = - (struct acpi_srat_mem_affinity *) sratp; + struct acpi_table_memory_affinity *memory_affinity = + (struct acpi_table_memory_affinity *) sratp; - if ((memory_affinity->flags & ACPI_SRAT_MEM_ENABLED) == 0) + if (!memory_affinity->flags.enabled) return; /* empty entry */ - pxm = memory_affinity->proximity_domain & 0xff; - /* mark this node as "seen" in node bitmap */ - BMAP_SET(pxm_bitmap, pxm); + BMAP_SET(pxm_bitmap, memory_affinity->proximity_domain); /* calculate info for memory chunk structure */ - paddr = memory_affinity->base_address; - size = memory_affinity->length; - + paddr = memory_affinity->base_addr_hi; + paddr = (paddr << 32) | memory_affinity->base_addr_lo; + size = memory_affinity->length_hi; + size = (size << 32) | memory_affinity->length_lo; + start_pfn = paddr >> PAGE_SHIFT; end_pfn = (paddr + size) >> PAGE_SHIFT; - + + pxm = memory_affinity->proximity_domain; if (num_memory_chunks >= MAXCHUNKS) { printk("Too many mem chunks in SRAT. Ignoring %lld MBytes at %llx\n", @@ -131,8 +132,8 @@ static void __init parse_memory_affinity_structure (char *sratp) printk("Memory range 0x%lX to 0x%lX (type 0x%X) in proximity domain 0x%02X %s\n", start_pfn, end_pfn, memory_affinity->memory_type, - pxm, - ((memory_affinity->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? + memory_affinity->proximity_domain, + (memory_affinity->flags.hot_pluggable ? "enabled and removable" : "enabled" ) ); } @@ -184,10 +185,10 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) num_memory_chunks = 0; while (p < end) { switch (*p) { - case ACPI_SRAT_TYPE_CPU_AFFINITY: + case ACPI_SRAT_PROCESSOR_AFFINITY: parse_cpu_affinity_structure(p); break; - case ACPI_SRAT_TYPE_MEMORY_AFFINITY: + case ACPI_SRAT_MEMORY_AFFINITY: parse_memory_affinity_structure(p); break; default: @@ -261,30 +262,31 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) return 0; } -struct acpi_static_rsdt { - struct acpi_table_rsdt table; - u32 padding[7]; /* Allow for 7 more table entries */ -}; - int __init get_memcfg_from_srat(void) { struct acpi_table_header *header = NULL; struct acpi_table_rsdp *rsdp = NULL; struct acpi_table_rsdt *rsdt = NULL; - acpi_native_uint rsdp_address = 0; - struct acpi_static_rsdt saved_rsdt; + struct acpi_pointer *rsdp_address = NULL; + struct acpi_table_rsdt saved_rsdt; int tables = 0; int i = 0; - rsdp_address = acpi_find_rsdp(); - if (!rsdp_address) { + if (ACPI_FAILURE(acpi_find_root_pointer(ACPI_PHYSICAL_ADDRESSING, + rsdp_address))) { printk("%s: System description tables not found\n", __FUNCTION__); goto out_err; } - printk("%s: assigning address to rsdp\n", __FUNCTION__); - rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address; + if (rsdp_address->pointer_type == ACPI_PHYSICAL_POINTER) { + printk("%s: assigning address to rsdp\n", __FUNCTION__); + rsdp = (struct acpi_table_rsdp *) + (u32)rsdp_address->pointer.physical; + } else { + printk("%s: rsdp_address is not a physical pointer\n", __FUNCTION__); + goto out_err; + } if (!rsdp) { printk("%s: Didn't find ACPI root!\n", __FUNCTION__); goto out_err; @@ -293,13 +295,13 @@ int __init get_memcfg_from_srat(void) printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision, rsdp->oem_id); - if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) { + if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) { printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__); goto out_err; } rsdt = (struct acpi_table_rsdt *) - boot_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt)); + boot_ioremap(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt)); if (!rsdt) { printk(KERN_WARNING @@ -308,9 +310,9 @@ int __init get_memcfg_from_srat(void) goto out_err; } - header = &rsdt->header; + header = & rsdt->header; - if (strncmp(header->signature, ACPI_SIG_RSDT, strlen(ACPI_SIG_RSDT))) { + if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) { printk(KERN_WARNING "ACPI: RSDT signature incorrect\n"); goto out_err; } @@ -328,9 +330,9 @@ int __init get_memcfg_from_srat(void) memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt)); - if (saved_rsdt.table.header.length > sizeof(saved_rsdt)) { + if (saved_rsdt.header.length > sizeof(saved_rsdt)) { printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", - saved_rsdt.table.header.length); + saved_rsdt.header.length); goto out_err; } @@ -339,15 +341,15 @@ int __init get_memcfg_from_srat(void) for (i = 0; i < tables; i++) { /* Map in header, then map in full table length. */ header = (struct acpi_table_header *) - boot_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header)); + boot_ioremap(saved_rsdt.entry[i], sizeof(struct acpi_table_header)); if (!header) break; header = (struct acpi_table_header *) - boot_ioremap(saved_rsdt.table.table_offset_entry[i], header->length); + boot_ioremap(saved_rsdt.entry[i], header->length); if (!header) break; - if (strncmp((char *) &header->signature, ACPI_SIG_SRAT, 4)) + if (strncmp((char *) &header->signature, "SRAT", 4)) continue; /* we've found the srat table. don't need to look at any more tables */ diff --git a/trunk/arch/i386/mach-es7000/es7000.h b/trunk/arch/i386/mach-es7000/es7000.h index c8d5aa132fa0..80566ca4a80a 100644 --- a/trunk/arch/i386/mach-es7000/es7000.h +++ b/trunk/arch/i386/mach-es7000/es7000.h @@ -84,6 +84,15 @@ struct es7000_oem_table { }; #ifdef CONFIG_ACPI +struct acpi_table_sdt { + unsigned long pa; + unsigned long count; + struct { + unsigned long pa; + enum acpi_table_id id; + unsigned long size; + } entry[50]; +}; struct oem_table { struct acpi_table_header Header; diff --git a/trunk/arch/i386/mach-es7000/es7000plat.c b/trunk/arch/i386/mach-es7000/es7000plat.c index 9be6ceabf042..3d0fc853516d 100644 --- a/trunk/arch/i386/mach-es7000/es7000plat.c +++ b/trunk/arch/i386/mach-es7000/es7000plat.c @@ -160,14 +160,51 @@ parse_unisys_oem (char *oemptr) int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) { - struct acpi_table_header *header = NULL; - int i = 0; - while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { - if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { - struct oem_table *t = (struct oem_table *)header; - *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, - t->OEMTableSize); - return 0; + struct acpi_table_rsdp *rsdp = NULL; + unsigned long rsdp_phys = 0; + struct acpi_table_header *header = NULL; + int i; + struct acpi_table_sdt sdt; + + rsdp_phys = acpi_find_rsdp(); + rsdp = __va(rsdp_phys); + if (rsdp->rsdt_address) { + struct acpi_table_rsdt *mapped_rsdt = NULL; + sdt.pa = rsdp->rsdt_address; + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + if (!header) + return -ENODEV; + + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; + mapped_rsdt = (struct acpi_table_rsdt *) + __acpi_map_table(sdt.pa, header->length); + if (!mapped_rsdt) + return -ENODEV; + + header = &mapped_rsdt->header; + + for (i = 0; i < sdt.count; i++) + sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; + }; + for (i = 0; i < sdt.count; i++) { + + header = (struct acpi_table_header *) + __acpi_map_table(sdt.entry[i].pa, + sizeof(struct acpi_table_header)); + if (!header) + continue; + if (!strncmp((char *) &header->signature, "OEM1", 4)) { + if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) { + void *addr; + struct oem_table *t; + acpi_table_print(header, sdt.entry[i].pa); + t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length); + addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize); + *oem_addr = (unsigned long) addr; + return 0; + } } } return -1; diff --git a/trunk/arch/i386/pci/mmconfig.c b/trunk/arch/i386/pci/mmconfig.c index 5700220dcf5f..e2616a266e13 100644 --- a/trunk/arch/i386/pci/mmconfig.c +++ b/trunk/arch/i386/pci/mmconfig.c @@ -36,7 +36,7 @@ static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32); static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) { int cfg_num = -1; - struct acpi_mcfg_allocation *cfg; + struct acpi_table_mcfg_config *cfg; if (seg == 0 && bus < MAX_CHECK_BUS && test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots)) @@ -48,11 +48,11 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) break; } cfg = &pci_mmcfg_config[cfg_num]; - if (cfg->pci_segment != seg) + if (cfg->pci_segment_group_number != seg) continue; if ((cfg->start_bus_number <= bus) && (cfg->end_bus_number >= bus)) - return cfg->address; + return cfg->base_address; } /* Handle more broken MCFG tables on Asus etc. @@ -60,9 +60,9 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) this applies to all busses. */ cfg = &pci_mmcfg_config[0]; if (pci_mmcfg_config_num == 1 && - cfg->pci_segment == 0 && + cfg->pci_segment_group_number == 0 && (cfg->start_bus_number | cfg->end_bus_number) == 0) - return cfg->address; + return cfg->base_address; /* Fall back to type 0 */ return 0; @@ -125,7 +125,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned long flags; u32 base; - if ((bus > 255) || (devfn > 255) || (reg > 4095)) + if ((bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; base = get_base_addr(seg, bus, devfn); @@ -199,19 +199,19 @@ void __init pci_mmcfg_init(int type) if ((pci_probe & PCI_PROBE_MMCONF) == 0) return; - acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); + acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); if ((pci_mmcfg_config_num == 0) || (pci_mmcfg_config == NULL) || - (pci_mmcfg_config[0].address == 0)) + (pci_mmcfg_config[0].base_address == 0)) return; /* Only do this check when type 1 works. If it doesn't work assume we run on a Mac and always use MCFG */ - if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address, - pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, + if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n", - (unsigned long)pci_mmcfg_config[0].address); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index f1d2899e9a62..fcacfe291b9b 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -11,8 +11,6 @@ menu "Processor type and features" config IA64 bool - select PCI if (!IA64_HP_SIM) - select ACPI if (!IA64_HP_SIM) default y help The Itanium Processor Family is Intel's 64-bit successor to @@ -30,6 +28,7 @@ config MMU config SWIOTLB bool + default y config RWSEM_XCHGADD_ALGORITHM bool @@ -85,9 +84,10 @@ choice config IA64_GENERIC bool "generic" + select ACPI + select PCI select NUMA select ACPI_NUMA - select SWIOTLB help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure @@ -104,7 +104,6 @@ config IA64_GENERIC config IA64_DIG bool "DIG-compliant" - select SWIOTLB config IA64_HP_ZX1 bool "HP-zx1/sx1000" @@ -114,7 +113,6 @@ config IA64_HP_ZX1 config IA64_HP_ZX1_SWIOTLB bool "HP-zx1/sx1000 with software I/O TLB" - select SWIOTLB help Build a kernel that runs on HP zx1 and sx1000 systems even when they have broken PCI devices which cannot DMA to full 32 bits. Apart @@ -133,7 +131,6 @@ config IA64_SGI_SN2 config IA64_HP_SIM bool "Ski-simulator" - select SWIOTLB endchoice diff --git a/trunk/arch/ia64/hp/common/hwsw_iommu.c b/trunk/arch/ia64/hp/common/hwsw_iommu.c index 2153bcacbe6c..a5a5637507be 100644 --- a/trunk/arch/ia64/hp/common/hwsw_iommu.c +++ b/trunk/arch/ia64/hp/common/hwsw_iommu.c @@ -192,7 +192,3 @@ EXPORT_SYMBOL(hwsw_unmap_sg); EXPORT_SYMBOL(hwsw_dma_supported); EXPORT_SYMBOL(hwsw_alloc_coherent); EXPORT_SYMBOL(hwsw_free_coherent); -EXPORT_SYMBOL(hwsw_sync_single_for_cpu); -EXPORT_SYMBOL(hwsw_sync_single_for_device); -EXPORT_SYMBOL(hwsw_sync_sg_for_cpu); -EXPORT_SYMBOL(hwsw_sync_sg_for_device); diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index 9197d7b361b3..29f05d4b68cd 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -55,7 +55,7 @@ #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ - ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) + ((acpi_table_entry_header *)entry)->length < sizeof(*entry)) #define PREFIX "ACPI: " @@ -67,11 +67,16 @@ EXPORT_SYMBOL(pm_power_off); unsigned int acpi_cpei_override; unsigned int acpi_cpei_phys_cpuid; +#define MAX_SAPICS 256 +u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = {[0 ... MAX_SAPICS - 1] = -1 }; + +EXPORT_SYMBOL(ia64_acpiid_to_sapicid); + const char *acpi_get_sysname(void) { #ifdef CONFIG_IA64_GENERIC unsigned long rsdp_phys; - struct acpi_table_rsdp *rsdp; + struct acpi20_table_rsdp *rsdp; struct acpi_table_xsdt *xsdt; struct acpi_table_header *hdr; @@ -82,16 +87,16 @@ const char *acpi_get_sysname(void) return "dig"; } - rsdp = (struct acpi_table_rsdp *)__va(rsdp_phys); - if (strncmp(rsdp->signature, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)) { + rsdp = (struct acpi20_table_rsdp *)__va(rsdp_phys); + if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) { printk(KERN_ERR "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n"); return "dig"; } - xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_physical_address); + xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_address); hdr = &xsdt->header; - if (strncmp(hdr->signature, ACPI_SIG_XSDT, sizeof(ACPI_SIG_XSDT) - 1)) { + if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) { printk(KERN_ERR "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n"); return "dig"; @@ -164,12 +169,12 @@ struct acpi_table_madt *acpi_madt __initdata; static u8 has_8259; static int __init -acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, +acpi_parse_lapic_addr_ovr(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_apic_override *lapic; + struct acpi_table_lapic_addr_ovr *lapic; - lapic = (struct acpi_madt_local_apic_override *)header; + lapic = (struct acpi_table_lapic_addr_ovr *)header; if (BAD_MADT_ENTRY(lapic, end)) return -EINVAL; @@ -182,19 +187,22 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, } static int __init -acpi_parse_lsapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lsapic(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_sapic *lsapic; + struct acpi_table_lsapic *lsapic; - lsapic = (struct acpi_madt_local_sapic *)header; + lsapic = (struct acpi_table_lsapic *)header; - /*Skip BAD_MADT_ENTRY check, as lsapic size could vary */ + if (BAD_MADT_ENTRY(lsapic, end)) + return -EINVAL; - if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { + if (lsapic->flags.enabled) { #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid; #endif + ia64_acpiid_to_sapicid[lsapic->acpi_id] = + (lsapic->id << 8) | lsapic->eid; ++available_cpus; } @@ -203,11 +211,11 @@ acpi_parse_lsapic(struct acpi_subtable_header * header, const unsigned long end) } static int __init -acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lapic_nmi(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_local_apic_nmi *lacpi_nmi; + struct acpi_table_lapic_nmi *lacpi_nmi; - lacpi_nmi = (struct acpi_madt_local_apic_nmi *)header; + lacpi_nmi = (struct acpi_table_lapic_nmi *)header; if (BAD_MADT_ENTRY(lacpi_nmi, end)) return -EINVAL; @@ -217,11 +225,11 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e } static int __init -acpi_parse_iosapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_io_sapic *iosapic; + struct acpi_table_iosapic *iosapic; - iosapic = (struct acpi_madt_io_sapic *)header; + iosapic = (struct acpi_table_iosapic *)header; if (BAD_MADT_ENTRY(iosapic, end)) return -EINVAL; @@ -232,13 +240,13 @@ acpi_parse_iosapic(struct acpi_subtable_header * header, const unsigned long end static unsigned int __initdata acpi_madt_rev; static int __init -acpi_parse_plat_int_src(struct acpi_subtable_header * header, +acpi_parse_plat_int_src(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_interrupt_source *plintsrc; + struct acpi_table_plat_int_src *plintsrc; int vector; - plintsrc = (struct acpi_madt_interrupt_source *)header; + plintsrc = (struct acpi_table_plat_int_src *)header; if (BAD_MADT_ENTRY(plintsrc, end)) return -EINVAL; @@ -249,19 +257,19 @@ acpi_parse_plat_int_src(struct acpi_subtable_header * header, */ vector = iosapic_register_platform_intr(plintsrc->type, plintsrc->global_irq, - plintsrc->io_sapic_vector, + plintsrc->iosapic_vector, plintsrc->eid, plintsrc->id, - ((plintsrc->inti_flags & ACPI_MADT_POLARITY_MASK) == - ACPI_MADT_POLARITY_ACTIVE_HIGH) ? - IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - ((plintsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) == - ACPI_MADT_TRIGGER_EDGE) ? - IOSAPIC_EDGE : IOSAPIC_LEVEL); + (plintsrc->flags.polarity == + 1) ? IOSAPIC_POL_HIGH : + IOSAPIC_POL_LOW, + (plintsrc->flags.trigger == + 1) ? IOSAPIC_EDGE : + IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; if (acpi_madt_rev > 1) { - acpi_cpei_override = plintsrc->flags & ACPI_MADT_CPEI_OVERRIDE; + acpi_cpei_override = plintsrc->plint_flags.cpei_override_flag; } /* @@ -316,32 +324,30 @@ unsigned int get_cpei_target_cpu(void) } static int __init -acpi_parse_int_src_ovr(struct acpi_subtable_header * header, +acpi_parse_int_src_ovr(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_interrupt_override *p; + struct acpi_table_int_src_ovr *p; - p = (struct acpi_madt_interrupt_override *)header; + p = (struct acpi_table_int_src_ovr *)header; if (BAD_MADT_ENTRY(p, end)) return -EINVAL; - iosapic_override_isa_irq(p->source_irq, p->global_irq, - ((p->inti_flags & ACPI_MADT_POLARITY_MASK) == - ACPI_MADT_POLARITY_ACTIVE_HIGH) ? - IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - ((p->inti_flags & ACPI_MADT_TRIGGER_MASK) == - ACPI_MADT_TRIGGER_EDGE) ? - IOSAPIC_EDGE : IOSAPIC_LEVEL); + iosapic_override_isa_irq(p->bus_irq, p->global_irq, + (p->flags.polarity == + 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (p->flags.trigger == + 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return 0; } static int __init -acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_nmi_src(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_madt_nmi_source *nmi_src; + struct acpi_table_nmi_src *nmi_src; - nmi_src = (struct acpi_madt_nmi_source *)header; + nmi_src = (struct acpi_table_nmi_src *)header; if (BAD_MADT_ENTRY(nmi_src, end)) return -EINVAL; @@ -365,12 +371,12 @@ static void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) } } -static int __init acpi_parse_madt(struct acpi_table_header *table) +static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size) { - if (!table) + if (!phys_addr || !size) return -EINVAL; - acpi_madt = (struct acpi_table_madt *)table; + acpi_madt = (struct acpi_table_madt *)__va(phys_addr); acpi_madt_rev = acpi_madt->header.revision; @@ -378,14 +384,14 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) #ifdef CONFIG_ITANIUM has_8259 = 1; /* Firmware on old Itanium systems is broken */ #else - has_8259 = acpi_madt->flags & ACPI_MADT_PCAT_COMPAT; + has_8259 = acpi_madt->flags.pcat_compat; #endif iosapic_system_init(has_8259); /* Get base address of IPI Message Block */ - if (acpi_madt->address) - ipi_base_addr = ioremap(acpi_madt->address, 0); + if (acpi_madt->lapic_address) + ipi_base_addr = ioremap(acpi_madt->lapic_address, 0); printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr); @@ -407,24 +413,23 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN]; #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) static struct acpi_table_slit __initdata *slit_table; -static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa) +static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa) { int pxm; - pxm = pa->proximity_domain_lo; + pxm = pa->proximity_domain; if (ia64_platform_is("sn2")) - pxm += pa->proximity_domain_hi[0] << 8; + pxm += pa->reserved[0] << 8; return pxm; } -static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma) +static int get_memory_proximity_domain(struct acpi_table_memory_affinity *ma) { int pxm; pxm = ma->proximity_domain; - if (!ia64_platform_is("sn2")) - pxm &= 0xff; - + if (ia64_platform_is("sn2")) + pxm += ma->reserved1[0] << 8; return pxm; } @@ -437,7 +442,7 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) u32 len; len = sizeof(struct acpi_table_header) + 8 - + slit->locality_count * slit->locality_count; + + slit->localities * slit->localities; if (slit->header.length != len) { printk(KERN_ERR "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", @@ -449,11 +454,11 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) } void __init -acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) +acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) { int pxm; - if (!(pa->flags & ACPI_SRAT_CPU_ENABLED)) + if (!pa->flags.enabled) return; pxm = get_processor_proximity_domain(pa); @@ -462,14 +467,14 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) pxm_bit_set(pxm); node_cpuid[srat_num_cpus].phys_id = - (pa->apic_id << 8) | (pa->local_sapic_eid); + (pa->apic_id << 8) | (pa->lsapic_eid); /* nid should be overridden as logical node id later */ node_cpuid[srat_num_cpus].nid = pxm; srat_num_cpus++; } void __init -acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) { unsigned long paddr, size; int pxm; @@ -478,11 +483,13 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) pxm = get_memory_proximity_domain(ma); /* fill node memory chunk structure */ - paddr = ma->base_address; - size = ma->length; + paddr = ma->base_addr_hi; + paddr = (paddr << 32) | ma->base_addr_lo; + size = ma->length_hi; + size = (size << 32) | ma->length_lo; /* Ignore disabled entries */ - if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) + if (!ma->flags.enabled) return; /* record this node in proximity bitmap */ @@ -553,16 +560,16 @@ void __init acpi_numa_arch_fixup(void) if (!slit_table) return; memset(numa_slit, -1, sizeof(numa_slit)); - for (i = 0; i < slit_table->locality_count; i++) { + for (i = 0; i < slit_table->localities; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); - for (j = 0; j < slit_table->locality_count; j++) { + for (j = 0; j < slit_table->localities; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); node_distance(node_from, node_to) = - slit_table->entry[i * slit_table->locality_count + j]; + slit_table->entry[i * slit_table->localities + j]; } } @@ -610,21 +617,21 @@ void acpi_unregister_gsi(u32 gsi) EXPORT_SYMBOL(acpi_unregister_gsi); -static int __init acpi_parse_fadt(struct acpi_table_header *table) +static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size) { struct acpi_table_header *fadt_header; - struct acpi_table_fadt *fadt; + struct fadt_descriptor *fadt; - if (!table) + if (!phys_addr || !size) return -EINVAL; - fadt_header = (struct acpi_table_header *)table; + fadt_header = (struct acpi_table_header *)__va(phys_addr); if (fadt_header->revision != 3) return -ENODEV; /* Only deal with ACPI 2.0 FADT */ - fadt = (struct acpi_table_fadt *)fadt_header; + fadt = (struct fadt_descriptor *)fadt_header; - acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); + acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; } @@ -651,7 +658,7 @@ int __init acpi_boot_init(void) * information -- the successor to MPS tables. */ - if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) < 1) { + if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) { printk(KERN_ERR PREFIX "Can't find MADT\n"); goto skip_madt; } @@ -659,40 +666,40 @@ int __init acpi_boot_init(void) /* Local APIC */ if (acpi_table_parse_madt - (ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, acpi_parse_lapic_addr_ovr, 0) < 0) + (ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0) printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, acpi_parse_lsapic, NR_CPUS) + if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS) < 1) printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n"); - if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0) + if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0) < 0) printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* I/O APIC */ if (acpi_table_parse_madt - (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) + (ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n"); /* System-Level Interrupt Routing */ if (acpi_table_parse_madt - (ACPI_MADT_TYPE_INTERRUPT_SOURCE, acpi_parse_plat_int_src, + (ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src, ACPI_MAX_PLATFORM_INTERRUPTS) < 0) printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n"); if (acpi_table_parse_madt - (ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr, 0) < 0) + (ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0) printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); - if (acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src, 0) < 0) + if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, 0) < 0) printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); skip_madt: @@ -702,7 +709,7 @@ int __init acpi_boot_init(void) * gets interrupts such as power and sleep buttons. If it's not * on a Legacy interrupt, it needs to be setup. */ - if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt) < 1) + if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1) printk(KERN_ERR PREFIX "Can't find FADT\n"); #ifdef CONFIG_SMP @@ -835,7 +842,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; - struct acpi_madt_local_sapic *lsapic; + struct acpi_table_lsapic *lsapic; cpumask_t tmp_map; long physid; int cpu; @@ -847,16 +854,16 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) return -EINVAL; obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER) - { + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*lsapic)) { kfree(buffer.pointer); return -EINVAL; } - lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer; + lsapic = (struct acpi_table_lsapic *)obj->buffer.pointer; - if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) || - (!lsapic->lapic_flags & ACPI_MADT_ENABLED)) { + if ((lsapic->header.type != ACPI_MADT_LSAPIC) || + (!lsapic->flags.enabled)) { kfree(buffer.pointer); return -EINVAL; } @@ -876,6 +883,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) cpu_set(cpu, cpu_present_map); ia64_cpu_to_sapicid[cpu] = physid; + ia64_acpiid_to_sapicid[lsapic->acpi_id] = ia64_cpu_to_sapicid[cpu]; *pcpu = cpu; return (0); @@ -885,6 +893,14 @@ EXPORT_SYMBOL(acpi_map_lsapic); int acpi_unmap_lsapic(int cpu) { + int i; + + for (i = 0; i < MAX_SAPICS; i++) { + if (ia64_acpiid_to_sapicid[i] == ia64_cpu_to_sapicid[cpu]) { + ia64_acpiid_to_sapicid[i] = -1; + break; + } + } ia64_cpu_to_sapicid[cpu] = -1; cpu_clear(cpu, cpu_present_map); @@ -904,7 +920,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; - struct acpi_madt_io_sapic *iosapic; + struct acpi_table_iosapic *iosapic; unsigned int gsi_base; int pxm, node; @@ -922,9 +938,9 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret) return AE_OK; } - iosapic = (struct acpi_madt_io_sapic *)obj->buffer.pointer; + iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer; - if (iosapic->header.type != ACPI_MADT_TYPE_IO_SAPIC) { + if (iosapic->header.type != ACPI_MADT_IOSAPIC) { kfree(buffer.pointer); return AE_OK; } diff --git a/trunk/arch/ia64/kernel/crash.c b/trunk/arch/ia64/kernel/crash.c index 9d92097ce96d..bc2f64d72244 100644 --- a/trunk/arch/ia64/kernel/crash.c +++ b/trunk/arch/ia64/kernel/crash.c @@ -79,7 +79,6 @@ crash_save_this_cpu() final_note(buf); } -#ifdef CONFIG_SMP static int kdump_wait_cpu_freeze(void) { @@ -92,7 +91,6 @@ kdump_wait_cpu_freeze(void) } return 1; } -#endif void machine_crash_shutdown(struct pt_regs *pt) @@ -118,11 +116,6 @@ machine_crash_shutdown(struct pt_regs *pt) static void machine_kdump_on_init(void) { - if (!ia64_kimage) { - printk(KERN_NOTICE "machine_kdump_on_init(): " - "kdump not configured\n"); - return; - } local_irq_disable(); kexec_disable_iosapic(); machine_kexec(ia64_kimage); @@ -139,12 +132,11 @@ kdump_cpu_freeze(struct unw_frame_info *info, void *arg) atomic_inc(&kdump_cpu_freezed); kdump_status[cpuid] = 1; mb(); -#ifdef CONFIG_HOTPLUG_CPU - if (cpuid != 0) + if (cpuid == 0) { + for (;;) + cpu_relax(); + } else ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]); -#endif - for (;;) - cpu_relax(); } static int diff --git a/trunk/arch/ia64/kernel/crash_dump.c b/trunk/arch/ia64/kernel/crash_dump.c index da60e90eeeb1..83b8c91c1408 100644 --- a/trunk/arch/ia64/kernel/crash_dump.c +++ b/trunk/arch/ia64/kernel/crash_dump.c @@ -9,8 +9,7 @@ #include #include -#include -#include +#include /** * copy_oldmem_page - copy one page from "oldmem" diff --git a/trunk/arch/ia64/kernel/efi.c b/trunk/arch/ia64/kernel/efi.c index 6c03928544c2..0b25a7d4e1e4 100644 --- a/trunk/arch/ia64/kernel/efi.c +++ b/trunk/arch/ia64/kernel/efi.c @@ -380,7 +380,7 @@ efi_get_pal_addr (void) #endif return __va(md->phys_addr); } - printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n", + printk(KERN_WARNING "%s: no PAL-code memory-descriptor found", __FUNCTION__); return NULL; } diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index e7873eeae448..15234ed3a341 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1610,7 +1610,5 @@ sys_call_table: data8 sys_sync_file_range // 1300 data8 sys_tee data8 sys_vmsplice - data8 sys_ni_syscall // reserved for move_pages - data8 sys_getcpu .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/trunk/arch/ia64/kernel/iosapic.c b/trunk/arch/ia64/kernel/iosapic.c index d6aab40c6416..0fc5fb7865cf 100644 --- a/trunk/arch/ia64/kernel/iosapic.c +++ b/trunk/arch/ia64/kernel/iosapic.c @@ -925,11 +925,6 @@ iosapic_unregister_intr (unsigned int gsi) /* Clear the interrupt controller descriptor */ idesc->chip = &no_irq_type; -#ifdef CONFIG_SMP - /* Clear affinity */ - cpus_setall(idesc->affinity); -#endif - /* Clear the interrupt information */ memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info)); diff --git a/trunk/arch/ia64/kernel/machine_kexec.c b/trunk/arch/ia64/kernel/machine_kexec.c index 4f0f3b8c1ee2..e2ccc9f660c5 100644 --- a/trunk/arch/ia64/kernel/machine_kexec.c +++ b/trunk/arch/ia64/kernel/machine_kexec.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -69,10 +68,22 @@ void machine_kexec_cleanup(struct kimage *image) { } +void machine_shutdown(void) +{ + int cpu; + + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id()) + cpu_down(cpu); + } + kexec_disable_iosapic(); +} + /* * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. */ +extern void *efi_get_pal_addr(void); static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) { struct kimage *image = arg; @@ -82,7 +93,6 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) unsigned long vector; int ii; - BUG_ON(!image); if (image->type == KEXEC_TYPE_CRASH) { crash_save_this_cpu(); current->thread.ksp = (__u64)info->sw - 16; @@ -121,7 +131,6 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) void machine_kexec(struct kimage *image) { - BUG_ON(!image); unw_init_running(ia64_machine_kexec, image); for(;;); } diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index ae96d4176995..17685abaf496 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -804,21 +803,6 @@ cpu_halt (void) ia64_pal_halt(min_power_state); } -void machine_shutdown(void) -{ -#ifdef CONFIG_HOTPLUG_CPU - int cpu; - - for_each_online_cpu(cpu) { - if (cpu != smp_processor_id()) - cpu_down(cpu); - } -#endif -#ifdef CONFIG_KEXEC - kexec_disable_iosapic(); -#endif -} - void machine_restart (char *restart_cmd) { diff --git a/trunk/arch/ia64/kernel/ptrace.c b/trunk/arch/ia64/kernel/ptrace.c index 3f8918782e0c..aa705e46b974 100644 --- a/trunk/arch/ia64/kernel/ptrace.c +++ b/trunk/arch/ia64/kernel/ptrace.c @@ -607,7 +607,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr) */ list_for_each_safe(this, next, ¤t->children) { p = list_entry(this, struct task_struct, sibling); - if (p->tgid != child->tgid) + if (p->mm != mm) continue; if (thread_matches(p, addr)) { child = p; @@ -1405,7 +1405,6 @@ ptrace_disable (struct task_struct *child) struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child)); /* make sure the single step/taken-branch trap bits are not set: */ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); child_psr->ss = 0; child_psr->tb = 0; } @@ -1526,7 +1525,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) * Make sure the single step/taken-branch trap bits * are not set: */ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); ia64_psr(pt)->ss = 0; ia64_psr(pt)->tb = 0; @@ -1558,7 +1556,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) goto out_tsk; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - set_tsk_thread_flag(child, TIF_SINGLESTEP); if (request == PTRACE_SINGLESTEP) { ia64_psr(pt)->ss = 1; } else { @@ -1598,9 +1595,13 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) } -static void +void syscall_trace (void) { + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + if (!(current->ptrace & PT_PTRACED)) + return; /* * The 0x80 provides a way for the tracing parent to * distinguish between a syscall stop and SIGTRAP delivery. @@ -1663,8 +1664,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, audit_syscall_exit(success, result); } - if ((test_thread_flag(TIF_SYSCALL_TRACE) - || test_thread_flag(TIF_SINGLESTEP)) + if (test_thread_flag(TIF_SYSCALL_TRACE) && (current->ptrace & PT_PTRACED)) syscall_trace(); } diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index 83c2629e1c4c..ad567b8d432e 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -569,31 +569,34 @@ show_cpuinfo (struct seq_file *m, void *v) { 1UL << 1, "spontaneous deferral"}, { 1UL << 2, "16-byte atomic ops" } }; - char features[128], *cp, *sep; + char features[128], *cp, sep; struct cpuinfo_ia64 *c = v; unsigned long mask; unsigned long proc_freq; - int i, size; + int i; mask = c->features; /* build the feature string: */ - memcpy(features, "standard", 9); + memcpy(features, " standard", 10); cp = features; - size = sizeof(features); - sep = ""; - for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) { + sep = 0; + for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) { if (mask & feature_bits[i].mask) { - cp += snprintf(cp, size, "%s%s", sep, - feature_bits[i].feature_name), - sep = ", "; + if (sep) + *cp++ = sep; + sep = ','; + *cp++ = ' '; + strcpy(cp, feature_bits[i].feature_name); + cp += strlen(feature_bits[i].feature_name); mask &= ~feature_bits[i].mask; - size = sizeof(features) - (cp - features); } } - if (mask && size > 1) { - /* print unknown features as a hex value */ - snprintf(cp, size, "%s0x%lx", sep, mask); + if (mask) { + /* print unknown features as a hex value: */ + if (sep) + *cp++ = sep; + sprintf(cp, " 0x%lx", mask); } proc_freq = cpufreq_quick_get(cpunum); @@ -609,7 +612,7 @@ show_cpuinfo (struct seq_file *m, void *v) "model name : %s\n" "revision : %u\n" "archrev : %u\n" - "features : %s\n" + "features :%s\n" /* don't change this---it _is_ right! */ "cpu number : %lu\n" "cpu regs : %u\n" "cpu MHz : %lu.%06lu\n" diff --git a/trunk/arch/ia64/kernel/vmlinux.lds.S b/trunk/arch/ia64/kernel/vmlinux.lds.S index 8f3d0066f446..d6083a0936f4 100644 --- a/trunk/arch/ia64/kernel/vmlinux.lds.S +++ b/trunk/arch/ia64/kernel/vmlinux.lds.S @@ -157,7 +157,6 @@ SECTIONS } #endif - . = ALIGN(8); __con_initcall_start = .; .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { *(.con_initcall.init) } diff --git a/trunk/arch/ia64/mm/contig.c b/trunk/arch/ia64/mm/contig.c index 63e6d49c5813..1e79551231b9 100644 --- a/trunk/arch/ia64/mm/contig.c +++ b/trunk/arch/ia64/mm/contig.c @@ -30,69 +30,47 @@ static unsigned long max_gap; #endif /** - * show_mem - give short summary of memory stats + * show_mem - display a memory statistics summary * - * Shows a simple page count of reserved and used pages in the system. - * For discontig machines, it does this on a per-pgdat basis. + * Just walks the pages in the system and describes where they're allocated. */ -void show_mem(void) +void +show_mem (void) { - int i, total_reserved = 0; - int total_shared = 0, total_cached = 0; - unsigned long total_present = 0; - pg_data_t *pgdat; + int i, total = 0, reserved = 0; + int shared = 0, cached = 0; printk(KERN_INFO "Mem-info:\n"); show_free_areas(); + printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - printk(KERN_INFO "Node memory in pages:\n"); - for_each_online_pgdat(pgdat) { - unsigned long present; - unsigned long flags; - int shared = 0, cached = 0, reserved = 0; - - pgdat_resize_lock(pgdat, &flags); - present = pgdat->node_present_pages; - for(i = 0; i < pgdat->node_spanned_pages; i++) { - struct page *page; - if (pfn_valid(pgdat->node_start_pfn + i)) - page = pfn_to_page(pgdat->node_start_pfn + i); - else { + i = max_mapnr; + for (i = 0; i < max_mapnr; i++) { + if (!pfn_valid(i)) { #ifdef CONFIG_VIRTUAL_MEM_MAP - if (max_gap < LARGE_GAP) - continue; -#endif - i = vmemmap_find_next_valid_pfn(pgdat->node_id, - i) - 1; + if (max_gap < LARGE_GAP) continue; - } - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (page_count(page)) - shared += page_count(page)-1; + i = vmemmap_find_next_valid_pfn(0, i) - 1; +#endif + continue; } - pgdat_resize_unlock(pgdat, &flags); - total_present += present; - total_reserved += reserved; - total_cached += cached; - total_shared += shared; - printk(KERN_INFO "Node %4d: RAM: %11ld, rsvd: %8d, " - "shrd: %10d, swpd: %10d\n", pgdat->node_id, - present, reserved, shared, cached); + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (page_count(mem_map + i)) + shared += page_count(mem_map + i) - 1; } - printk(KERN_INFO "%ld pages of RAM\n", total_present); - printk(KERN_INFO "%d reserved pages\n", total_reserved); - printk(KERN_INFO "%d pages shared\n", total_shared); - printk(KERN_INFO "%d pages swap cached\n", total_cached); - printk(KERN_INFO "Total of %ld pages in page table cache\n", + printk(KERN_INFO "%d pages of RAM\n", total); + printk(KERN_INFO "%d reserved pages\n", reserved); + printk(KERN_INFO "%d pages shared\n", shared); + printk(KERN_INFO "%d pages swap cached\n", cached); + printk(KERN_INFO "%ld pages in page table cache\n", pgtable_quicklist_total_size()); - printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages()); } - /* physical address where the bootmem map is located */ unsigned long bootmap_start; @@ -199,7 +177,7 @@ find_memory (void) #ifdef CONFIG_CRASH_DUMP /* If we are doing a crash dump, we still need to know the real mem - * size before original memory map is reset. */ + * size before original memory map is * reset. */ saved_max_pfn = max_pfn; #endif } diff --git a/trunk/arch/ia64/mm/discontig.c b/trunk/arch/ia64/mm/discontig.c index 6eae596c509d..96722cb1b49d 100644 --- a/trunk/arch/ia64/mm/discontig.c +++ b/trunk/arch/ia64/mm/discontig.c @@ -412,6 +412,37 @@ static void __init memory_less_nodes(void) return; } +#ifdef CONFIG_SPARSEMEM +/** + * register_sparse_mem - notify SPARSEMEM that this memory range exists. + * @start: physical start of range + * @end: physical end of range + * @arg: unused + * + * Simply calls SPARSEMEM to register memory section(s). + */ +static int __init register_sparse_mem(unsigned long start, unsigned long end, + void *arg) +{ + int nid; + + start = __pa(start) >> PAGE_SHIFT; + end = __pa(end) >> PAGE_SHIFT; + nid = early_pfn_to_nid(start); + memory_present(nid, start, end); + + return 0; +} + +static void __init arch_sparse_init(void) +{ + efi_memmap_walk(register_sparse_mem, NULL); + sparse_init(); +} +#else +#define arch_sparse_init() do {} while (0) +#endif + /** * find_memory - walk the EFI memory map and setup the bootmem allocator * @@ -442,9 +473,6 @@ void __init find_memory(void) node_clear(node, memory_less_mask); mem_data[node].min_pfn = ~0UL; } - - efi_memmap_walk(register_active_ranges, NULL); - /* * Initialize the boot memory maps in reverse order since that's * what the bootmem allocator expects @@ -478,12 +506,6 @@ void __init find_memory(void) max_pfn = max_low_pfn; find_initrd(); - -#ifdef CONFIG_CRASH_DUMP - /* If we are doing a crash dump, we still need to know the real mem - * size before original memory map is reset. */ - saved_max_pfn = max_pfn; -#endif } #ifdef CONFIG_SMP @@ -632,6 +654,7 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n { unsigned long end = start + len; + add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT); mem_data[node].num_physpages += len >> PAGE_SHIFT; if (start <= __pa(MAX_DMA_ADDRESS)) mem_data[node].num_dma_physpages += @@ -663,10 +686,9 @@ void __init paging_init(void) max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; - efi_memmap_walk(filter_rsvd_memory, count_node_pages); + arch_sparse_init(); - sparse_memory_present_with_active_regions(MAX_NUMNODES); - sparse_init(); + efi_memmap_walk(filter_rsvd_memory, count_node_pages); #ifdef CONFIG_VIRTUAL_MEM_MAP vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * diff --git a/trunk/arch/ia64/mm/init.c b/trunk/arch/ia64/mm/init.c index faaca21a3718..1373fae7657f 100644 --- a/trunk/arch/ia64/mm/init.c +++ b/trunk/arch/ia64/mm/init.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -129,25 +128,6 @@ lazy_mmu_prot_update (pte_t pte) set_bit(PG_arch_1, &page->flags); /* mark page as clean */ } -/* - * Since DMA is i-cache coherent, any (complete) pages that were written via - * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to - * flush them when they get mapped into an executable vm-area. - */ -void -dma_mark_clean(void *addr, size_t size) -{ - unsigned long pg_addr, end; - - pg_addr = PAGE_ALIGN((unsigned long) addr); - end = (unsigned long) addr + size; - while (pg_addr + PAGE_SIZE <= end) { - struct page *page = virt_to_page(pg_addr); - set_bit(PG_arch_1, &page->flags); - pg_addr += PAGE_SIZE; - } -} - inline void ia64_set_rbs_bot (void) { @@ -615,27 +595,13 @@ find_largest_hole (u64 start, u64 end, void *arg) return 0; } -#endif /* CONFIG_VIRTUAL_MEM_MAP */ - int __init register_active_ranges(u64 start, u64 end, void *arg) { - int nid = paddr_to_nid(__pa(start)); - - if (nid < 0) - nid = 0; -#ifdef CONFIG_KEXEC - if (start > crashk_res.start && start < crashk_res.end) - start = crashk_res.end; - if (end > crashk_res.start && end < crashk_res.end) - end = crashk_res.start; -#endif - - if (start < end) - add_active_range(nid, __pa(start) >> PAGE_SHIFT, - __pa(end) >> PAGE_SHIFT); + add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT); return 0; } +#endif /* CONFIG_VIRTUAL_MEM_MAP */ static int __init count_reserved_pages (u64 start, u64 end, void *arg) diff --git a/trunk/arch/ia64/sn/kernel/huberror.c b/trunk/arch/ia64/sn/kernel/huberror.c index fcf7f93c4b61..abca6bd7962f 100644 --- a/trunk/arch/ia64/sn/kernel/huberror.c +++ b/trunk/arch/ia64/sn/kernel/huberror.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved. */ #include @@ -38,20 +38,12 @@ static irqreturn_t hub_eint_handler(int irq, void *arg) (u64) nasid, 0, 0, 0, 0, 0, 0); if ((int)ret_stuff.v0) - panic("%s: Fatal %s Error", __FUNCTION__, - ((nasid & 1) ? "TIO" : "HUBII")); + panic("hubii_eint_handler(): Fatal TIO Error"); if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ (void)hubiio_crb_error_handler(hubdev_info); - } else - if (nasid & 1) { /* TIO errors */ - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, - (u64) nasid, 0, 0, 0, 0, 0, 0); - - if ((int)ret_stuff.v0) - panic("%s: Fatal TIO Error", __FUNCTION__); - } else - bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid))); + } else + bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid))); return IRQ_HANDLED; } diff --git a/trunk/arch/ia64/sn/kernel/io_acpi_init.c b/trunk/arch/ia64/sn/kernel/io_acpi_init.c index 8c331ca6e5c9..cb96b4ea7df6 100644 --- a/trunk/arch/ia64/sn/kernel/io_acpi_init.c +++ b/trunk/arch/ia64/sn/kernel/io_acpi_init.c @@ -13,7 +13,6 @@ #include #include "xtalk/hubdev.h" #include -#include /* @@ -32,12 +31,6 @@ struct acpi_vendor_uuid sn_uuid = { 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 }, }; -struct sn_pcidev_match { - u8 bus; - unsigned int devfn; - acpi_handle handle; -}; - /* * Perform the early IO init in PROM. */ @@ -126,11 +119,9 @@ sn_get_bussoft_ptr(struct pci_bus *bus) status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, &sn_uuid, &buffer); if (ACPI_FAILURE(status)) { - printk(KERN_ERR "%s: " - "acpi_get_vendor_resource() failed (0x%x) for: ", - __FUNCTION__, status); - acpi_ns_print_node_pathname(handle, NULL); - printk("\n"); + printk(KERN_ERR "get_acpi_pcibus_ptr: " + "get_acpi_bussoft_info() failed: %d\n", + status); return NULL; } resource = buffer.pointer; @@ -139,8 +130,8 @@ sn_get_bussoft_ptr(struct pci_bus *bus) if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != sizeof(struct pcibus_bussoft *)) { printk(KERN_ERR - "%s: Invalid vendor data length %d\n", - __FUNCTION__, vendor->byte_length); + "get_acpi_bussoft_ptr: Invalid vendor data " + "length %d\n", vendor->byte_length); kfree(buffer.pointer); return NULL; } @@ -152,254 +143,34 @@ sn_get_bussoft_ptr(struct pci_bus *bus) } /* - * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info - * pointers from the vendor resource using the - * provided acpi handle, and copy the structures - * into the argument buffers. - */ -static int -sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info, - struct sn_irq_info **sn_irq_info) -{ - u64 addr; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct sn_irq_info *irq_info, *irq_info_prom; - struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr; - struct acpi_resource *resource; - int ret = 0; - acpi_status status; - struct acpi_resource_vendor_typed *vendor; - - /* - * The pointer to this device's pcidev_info structure in - * the PROM, is in the vendor resource. - */ - status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS, - &sn_uuid, &buffer); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR - "%s: acpi_get_vendor_resource() failed (0x%x) for: ", - __FUNCTION__, status); - acpi_ns_print_node_pathname(handle, NULL); - printk("\n"); - return 1; - } - - resource = buffer.pointer; - vendor = &resource->data.vendor_typed; - if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) != - sizeof(struct pci_devdev_info *)) { - printk(KERN_ERR - "%s: Invalid vendor data length: %d for: ", - __FUNCTION__, vendor->byte_length); - acpi_ns_print_node_pathname(handle, NULL); - printk("\n"); - ret = 1; - goto exit; - } - - pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); - if (!pcidev_ptr) - panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__); - - memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *)); - pcidev_prom_ptr = __va(addr); - memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info)); - - /* Get the IRQ info */ - irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); - if (!irq_info) - panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__); - - if (pcidev_ptr->pdi_sn_irq_info) { - irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info); - memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info)); - } - - *pcidev_info = pcidev_ptr; - *sn_irq_info = irq_info; - -exit: - kfree(buffer.pointer); - return ret; -} - -static unsigned int -get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle) -{ - unsigned long adr; - acpi_handle child; - unsigned int devfn; - int function; - acpi_handle parent; - int slot; - acpi_status status; - - /* - * Do an upward search to find the root bus device, and - * obtain the host devfn from the previous child device. - */ - child = device_handle; - while (child) { - status = acpi_get_parent(child, &parent); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR "%s: acpi_get_parent() failed " - "(0x%x) for: ", __FUNCTION__, status); - acpi_ns_print_node_pathname(child, NULL); - printk("\n"); - panic("%s: Unable to find host devfn\n", __FUNCTION__); - } - if (parent == rootbus_handle) - break; - child = parent; - } - if (!child) { - printk(KERN_ERR "%s: Unable to find root bus for: ", - __FUNCTION__); - acpi_ns_print_node_pathname(device_handle, NULL); - printk("\n"); - BUG(); - } - - status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ", - __FUNCTION__, status); - acpi_ns_print_node_pathname(child, NULL); - printk("\n"); - panic("%s: Unable to find host devfn\n", __FUNCTION__); - } - - slot = (adr >> 16) & 0xffff; - function = adr & 0xffff; - devfn = PCI_DEVFN(slot, function); - return devfn; -} - -/* - * find_matching_device - Callback routine to find the ACPI device - * that matches up with our pci_dev device. - * Matching is done on bus number and devfn. - * To find the bus number for a particular - * ACPI device, we must look at the _BBN method - * of its parent. - */ -static acpi_status -find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - unsigned long bbn = -1; - unsigned long adr; - acpi_handle parent = NULL; - acpi_status status; - unsigned int devfn; - int function; - int slot; - struct sn_pcidev_match *info = context; - - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, - &adr); - if (ACPI_SUCCESS(status)) { - status = acpi_get_parent(handle, &parent); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR - "%s: acpi_get_parent() failed (0x%x) for: ", - __FUNCTION__, status); - acpi_ns_print_node_pathname(handle, NULL); - printk("\n"); - return AE_OK; - } - status = acpi_evaluate_integer(parent, METHOD_NAME__BBN, - NULL, &bbn); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR - "%s: Failed to find _BBN in parent of: ", - __FUNCTION__); - acpi_ns_print_node_pathname(handle, NULL); - printk("\n"); - return AE_OK; - } - - slot = (adr >> 16) & 0xffff; - function = adr & 0xffff; - devfn = PCI_DEVFN(slot, function); - if ((info->devfn == devfn) && (info->bus == bbn)) { - /* We have a match! */ - info->handle = handle; - return 1; - } - } - return AE_OK; -} - -/* - * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi - * device matching the specified pci_dev, - * and return the pcidev info and irq info. + * sn_acpi_bus_fixup */ -int -sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info, - struct sn_irq_info **sn_irq_info) +void +sn_acpi_bus_fixup(struct pci_bus *bus) { - unsigned int host_devfn; - struct sn_pcidev_match pcidev_match; - acpi_handle rootbus_handle; - unsigned long segment; - acpi_status status; + struct pci_dev *pci_dev = NULL; + struct pcibus_bussoft *prom_bussoft_ptr; + extern void sn_common_bus_fixup(struct pci_bus *, + struct pcibus_bussoft *); - rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle; - status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL, - &segment); - if (ACPI_SUCCESS(status)) { - if (segment != pci_domain_nr(dev)) { + if (!bus->parent) { /* If root bus */ + prom_bussoft_ptr = sn_get_bussoft_ptr(bus); + if (prom_bussoft_ptr == NULL) { printk(KERN_ERR - "%s: Segment number mismatch, 0x%lx vs 0x%x for: ", - __FUNCTION__, segment, pci_domain_nr(dev)); - acpi_ns_print_node_pathname(rootbus_handle, NULL); - printk("\n"); - return 1; + "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to " + "obtain prom_bussoft_ptr\n", + pci_domain_nr(bus), bus->number); + return; } - } else { - printk(KERN_ERR "%s: Unable to get __SEG from: ", - __FUNCTION__); - acpi_ns_print_node_pathname(rootbus_handle, NULL); - printk("\n"); - return 1; + sn_common_bus_fixup(bus, prom_bussoft_ptr); } - - /* - * We want to search all devices in this segment/domain - * of the ACPI namespace for the matching ACPI device, - * which holds the pcidev_info pointer in its vendor resource. - */ - pcidev_match.bus = dev->bus->number; - pcidev_match.devfn = dev->devfn; - pcidev_match.handle = NULL; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX, - find_matching_device, &pcidev_match, NULL); - - if (!pcidev_match.handle) { - printk(KERN_ERR - "%s: Could not find matching ACPI device for %s.\n", - __FUNCTION__, pci_name(dev)); - return 1; + list_for_each_entry(pci_dev, &bus->devices, bus_list) { + sn_pci_fixup_slot(pci_dev); } - - if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info)) - return 1; - - /* Build up the pcidev_info.pdi_slot_host_handle */ - host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle); - (*pcidev_info)->pdi_slot_host_handle = - ((unsigned long) pci_domain_nr(dev) << 40) | - /* bus == 0 */ - host_devfn; - return 0; } /* - * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info. - * Perform any SN specific slot fixup. + * sn_acpi_slot_fixup - Perform any SN specific slot fixup. * At present there does not appear to be * any generic way to handle a ROM image * that has been shadowed by the PROM, so @@ -408,18 +179,11 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info, */ void -sn_acpi_slot_fixup(struct pci_dev *dev) +sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info) { void __iomem *addr; - struct pcidev_info *pcidev_info = NULL; - struct sn_irq_info *sn_irq_info = NULL; size_t size; - if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { - panic("%s: Failure obtaining pcidev_info for %s\n", - __FUNCTION__, pci_name(dev)); - } - if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { /* * A valid ROM image exists and has been shadowed by the @@ -436,11 +200,8 @@ sn_acpi_slot_fixup(struct pci_dev *dev) (unsigned long) addr + size; dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; } - sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); } -EXPORT_SYMBOL(sn_acpi_slot_fixup); - static struct acpi_driver acpi_sn_hubdev_driver = { .name = "SGI HUBDEV Driver", .ids = "SGIHUB,SGITIO", @@ -450,33 +211,6 @@ static struct acpi_driver acpi_sn_hubdev_driver = { }; -/* - * sn_acpi_bus_fixup - Perform SN specific setup of software structs - * (pcibus_bussoft, pcidev_info) and hardware - * registers, for the specified bus and devices under it. - */ -void -sn_acpi_bus_fixup(struct pci_bus *bus) -{ - struct pci_dev *pci_dev = NULL; - struct pcibus_bussoft *prom_bussoft_ptr; - - if (!bus->parent) { /* If root bus */ - prom_bussoft_ptr = sn_get_bussoft_ptr(bus); - if (prom_bussoft_ptr == NULL) { - printk(KERN_ERR - "%s: 0x%04x:0x%02x Unable to " - "obtain prom_bussoft_ptr\n", - __FUNCTION__, pci_domain_nr(bus), bus->number); - return; - } - sn_common_bus_fixup(bus, prom_bussoft_ptr); - } - list_for_each_entry(pci_dev, &bus->devices, bus_list) { - sn_acpi_slot_fixup(pci_dev); - } -} - /* * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the * nodes and root buses in the DSDT. As a result, bus scanning diff --git a/trunk/arch/ia64/sn/kernel/io_common.c b/trunk/arch/ia64/sn/kernel/io_common.c index d48bcd83253c..d4dd8f4b6b8d 100644 --- a/trunk/arch/ia64/sn/kernel/io_common.c +++ b/trunk/arch/ia64/sn/kernel/io_common.c @@ -26,10 +26,14 @@ #include #include #include -#include "acpi/acglobal.h" extern void sn_init_cpei_timer(void); extern void register_sn_procfs(void); +extern void sn_acpi_bus_fixup(struct pci_bus *); +extern void sn_bus_fixup(struct pci_bus *); +extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *); +extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *); +extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64); extern void sn_io_acpi_init(void); extern void sn_io_init(void); @@ -44,9 +48,6 @@ struct sysdata_el { int sn_ioif_inited; /* SN I/O infrastructure initialized? */ -int sn_acpi_rev; /* SN ACPI revision */ -EXPORT_SYMBOL_GPL(sn_acpi_rev); - struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ /* @@ -97,6 +98,25 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, return ret_stuff.status; } +/* + * Retrieve the pci device information given the bus and device|function number. + */ +static inline u64 +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, + u64 sn_irq_info) +{ + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, + (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, + (u64) segment, (u64) bus_number, (u64) devfn, + (u64) pci_dev, + sn_irq_info, 0, 0); + return ret_stuff.v0; +} + /* * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified * device. @@ -229,25 +249,50 @@ void sn_pci_unfixup_slot(struct pci_dev *dev) } /* - * sn_pci_fixup_slot() + * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent + * with the Linux PCI abstraction layer. Resources + * acquired from our PCI provider include PIO maps + * to BAR space and interrupt objects. */ -void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info, - struct sn_irq_info *sn_irq_info) +void sn_pci_fixup_slot(struct pci_dev *dev) { int segment = pci_domain_nr(dev->bus); + int status = 0; struct pcibus_bussoft *bs; - struct pci_bus *host_pci_bus; - struct pci_dev *host_pci_dev; - unsigned int bus_no, devfn; + struct pci_bus *host_pci_bus; + struct pci_dev *host_pci_dev; + struct pcidev_info *pcidev_info; + struct sn_irq_info *sn_irq_info; + unsigned int bus_no, devfn; pci_dev_get(dev); /* for the sysdata pointer */ + pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); + if (!pcidev_info) + BUG(); /* Cannot afford to run out of memory */ + + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (!sn_irq_info) + BUG(); /* Cannot afford to run out of memory */ + + /* Call to retrieve pci device information needed by kernel. */ + status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, + dev->devfn, + (u64) __pa(pcidev_info), + (u64) __pa(sn_irq_info)); + if (status) + BUG(); /* Cannot get platform pci device information */ /* Add pcidev_info to list in pci_controller.platform_data */ list_add_tail(&pcidev_info->pdi_list, &(SN_PLATFORM_DATA(dev->bus)->pcidev_info)); + + if (SN_ACPI_BASE_SUPPORT()) + sn_acpi_slot_fixup(dev, pcidev_info); + else + sn_more_slot_fixup(dev, pcidev_info); /* * Using the PROMs values for the PCI host bus, get the Linux - * PCI host_pci_dev struct and set up host bus linkages + * PCI host_pci_dev struct and set up host bus linkages */ bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; @@ -444,6 +489,11 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address) sprintf(address, "%s^%d", address, geo_slot(geoid)); } +/* + * sn_pci_fixup_bus() - Perform SN specific setup of software structs + * (pcibus_bussoft, pcidev_info) and hardware + * registers, for the specified bus and devices under it. + */ void __devinit sn_pci_fixup_bus(struct pci_bus *bus) { @@ -469,15 +519,6 @@ sn_io_early_init(void) if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) return 0; - /* we set the acpi revision to that of the DSDT table OEM rev. */ - { - struct acpi_table_header *header = NULL; - - acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header); - BUG_ON(header == NULL); - sn_acpi_rev = header->oem_revision; - } - /* * prime sn_pci_provider[]. Individial provider init routines will * override their respective default entries. @@ -503,12 +544,8 @@ sn_io_early_init(void) register_sn_procfs(); #endif - { - struct acpi_table_header *header; - (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header); - printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n", - header->oem_revision); - } + printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n", + acpi_gbl_DSDT->oem_revision); if (SN_ACPI_BASE_SUPPORT()) sn_io_acpi_init(); else @@ -568,6 +605,7 @@ sn_io_late_init(void) fs_initcall(sn_io_late_init); +EXPORT_SYMBOL(sn_pci_fixup_slot); EXPORT_SYMBOL(sn_pci_unfixup_slot); EXPORT_SYMBOL(sn_bus_store_sysdata); EXPORT_SYMBOL(sn_bus_free_sysdata); diff --git a/trunk/arch/ia64/sn/kernel/io_init.c b/trunk/arch/ia64/sn/kernel/io_init.c index 600be3ebae05..9ad843e0383b 100644 --- a/trunk/arch/ia64/sn/kernel/io_init.c +++ b/trunk/arch/ia64/sn/kernel/io_init.c @@ -56,25 +56,6 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) return ret_stuff.v0; } -/* - * Retrieve the pci device information given the bus and device|function number. - */ -static inline u64 -sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, - u64 sn_irq_info) -{ - struct ia64_sal_retval ret_stuff; - ret_stuff.status = 0; - ret_stuff.v0 = 0; - - SAL_CALL_NOLOCK(ret_stuff, - (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, - (u64) segment, (u64) bus_number, (u64) devfn, - (u64) pci_dev, - sn_irq_info, 0, 0); - return ret_stuff.v0; -} - /* * sn_fixup_ionodes() - This routine initializes the HUB data structure for @@ -191,40 +172,18 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, } /* - * sn_io_slot_fixup() - We are not running with an ACPI capable PROM, + * sn_more_slot_fixup() - We are not running with an ACPI capable PROM, * and need to convert the pci_dev->resource * 'start' and 'end' addresses to mapped addresses, * and setup the pci_controller->window array entries. */ void -sn_io_slot_fixup(struct pci_dev *dev) +sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info) { unsigned int count = 0; int idx; s64 pci_addrs[PCI_ROM_RESOURCE + 1]; unsigned long addr, end, size, start; - struct pcidev_info *pcidev_info; - struct sn_irq_info *sn_irq_info; - int status; - - pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL); - if (!pcidev_info) - panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__); - - sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); - if (!sn_irq_info) - panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__); - - /* Call to retrieve pci device information needed by kernel. */ - status = sal_get_pcidev_info((u64) pci_domain_nr(dev), - (u64) dev->bus->number, - dev->devfn, - (u64) __pa(pcidev_info), - (u64) __pa(sn_irq_info)); - - if (status) - BUG(); /* Cannot get platform pci device information */ - /* Copy over PIO Mapped Addresses */ for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { @@ -260,12 +219,8 @@ sn_io_slot_fixup(struct pci_dev *dev) */ if (count > 0) sn_pci_window_fixup(dev, count, pci_addrs); - - sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); } -EXPORT_SYMBOL(sn_io_slot_fixup); - /* * sn_pci_controller_fixup() - This routine sets up a bus's resources * consistent with the Linux PCI abstraction layer. @@ -317,6 +272,9 @@ sn_bus_fixup(struct pci_bus *bus) { struct pci_dev *pci_dev = NULL; struct pcibus_bussoft *prom_bussoft_ptr; + extern void sn_common_bus_fixup(struct pci_bus *, + struct pcibus_bussoft *); + if (!bus->parent) { /* If root bus */ prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data; @@ -333,7 +291,7 @@ sn_bus_fixup(struct pci_bus *bus) prom_bussoft_ptr->bs_legacy_mem); } list_for_each_entry(pci_dev, &bus->devices, bus_list) { - sn_io_slot_fixup(pci_dev); + sn_pci_fixup_slot(pci_dev); } } diff --git a/trunk/arch/ia64/sn/kernel/iomv.c b/trunk/arch/ia64/sn/kernel/iomv.c index ab7e2fd40798..4aa4f301d56d 100644 --- a/trunk/arch/ia64/sn/kernel/iomv.c +++ b/trunk/arch/ia64/sn/kernel/iomv.c @@ -1,4 +1,4 @@ -/* +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -26,10 +26,9 @@ * @port: port to convert * * Legacy in/out instructions are converted to ld/st instructions - * on IA64. This routine will convert a port number into a valid + * on IA64. This routine will convert a port number into a valid * SN i/o address. Used by sn_in*() and sn_out*(). */ - void *sn_io_addr(unsigned long port) { if (!IS_RUNNING_ON_SIMULATOR()) { diff --git a/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 04a8256017eb..6846dc9b432d 100644 --- a/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/trunk/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -20,8 +20,7 @@ #include "xtalk/hubdev.h" int -sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp, - char **ssdt) +sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) { struct ia64_sal_retval ret_stuff; u64 busnum; @@ -33,8 +32,7 @@ sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp, segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment, - busnum, (u64) device, (u64) resp, (u64)ia64_tpa(ssdt), - 0, 0); + busnum, (u64) device, (u64) resp, 0, 0, 0); return (int)ret_stuff.v0; } diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 44a0224c32dd..bbd386f572d9 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -575,7 +575,6 @@ config SGI_IP27 select DMA_IP27 select EARLY_PRINTK select HW_HAS_PCI - select NR_CPUS_DEFAULT_64 select PCI_DOMAINS select SYS_HAS_CPU_R10000 select SYS_SUPPORTS_64BIT_KERNEL @@ -613,7 +612,6 @@ config SIBYTE_BIGSUR bool "Sibyte BCM91480B-BigSur" select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_4 select PCI_DOMAINS select SIBYTE_BCM1x80 select SWAP_IO_SPACE @@ -625,7 +623,6 @@ config SIBYTE_SWARM bool "Sibyte BCM91250A-SWARM" select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -638,7 +635,6 @@ config SIBYTE_SENTOSA depends on EXPERIMENTAL select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -672,7 +668,6 @@ config SIBYTE_PTSWARM depends on EXPERIMENTAL select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -685,7 +680,6 @@ config SIBYTE_LITTLESUR depends on EXPERIMENTAL select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -796,6 +790,23 @@ config TOSHIBA_RBTX4938 endchoice +config KEXEC + bool "Kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + source "arch/mips/ddb5xxx/Kconfig" source "arch/mips/gt64120/ev64120/Kconfig" source "arch/mips/jazz/Kconfig" @@ -1530,8 +1541,6 @@ config MIPS_MT_SMTC select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_SRS select MIPS_MT - select NR_CPUS_DEFAULT_2 - select NR_CPUS_DEFAULT_8 select SMP select SYS_SUPPORTS_SMP help @@ -1747,34 +1756,13 @@ config SMP config SYS_SUPPORTS_SMP bool -config NR_CPUS_DEFAULT_2 - bool - -config NR_CPUS_DEFAULT_4 - bool - -config NR_CPUS_DEFAULT_8 - bool - -config NR_CPUS_DEFAULT_16 - bool - -config NR_CPUS_DEFAULT_32 - bool - -config NR_CPUS_DEFAULT_64 - bool - config NR_CPUS int "Maximum number of CPUs (2-64)" range 2 64 depends on SMP - default "2" if NR_CPUS_DEFAULT_2 - default "4" if NR_CPUS_DEFAULT_4 - default "8" if NR_CPUS_DEFAULT_8 - default "16" if NR_CPUS_DEFAULT_16 - default "32" if NR_CPUS_DEFAULT_32 - default "64" if NR_CPUS_DEFAULT_64 + default "64" if SGI_IP27 + default "2" + default "8" if MIPS_MT_SMTC help This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 32 for 32-bit @@ -1871,40 +1859,6 @@ config MIPS_INSANE_LARGE This will result in additional memory usage, so it is not recommended for normal users. -config KEXEC - bool "Kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - kexec is a system call that implements the ability to shutdown your - current kernel, and to start another kernel. It is like a reboot - but it is indepedent of the system firmware. And like a reboot - you can start any kernel with it, not just Linux. - - The name comes from the similiarity to the exec system call. - - It is an ongoing process to be certain the hardware in a machine - is properly shutdown, so do not be surprised if this code does not - initially work for you. It may help to enable device hotplugging - support. As of this writing the exact hardware interface is - strongly in flux, so no good recommendation can be made. - -config SECCOMP - bool "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS && BROKEN - default y - help - This kernel feature is useful for number crunching applications - that may need to compute untrusted bytecode during their - execution. By using pipes or other transports made available to - the process as file descriptors supporting the read/write - syscalls, it's possible to isolate those applications in - their own address space using seccomp. Once seccomp is - enabled via /proc//seccomp, it cannot be disabled - and the task is only allowed to execute a few safe syscalls - defined by each seccomp mode. - - If unsure, say Y. Only embedded should say N here. - endmenu config RWSEM_GENERIC_SPINLOCK @@ -2071,6 +2025,23 @@ config BINFMT_ELF32 bool default y if MIPS32_O32 || MIPS32_N32 +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + depends on PROC_FS && BROKEN + default y + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via /proc//seccomp, it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + If unsure, say Y. Only embedded should say N here. + config PM bool "Power Management support (EXPERIMENTAL)" depends on EXPERIMENTAL && SOC_AU1X00 diff --git a/trunk/arch/mips/Kconfig.debug b/trunk/arch/mips/Kconfig.debug index 9351f1c04a9d..5d6afb52d904 100644 --- a/trunk/arch/mips/Kconfig.debug +++ b/trunk/arch/mips/Kconfig.debug @@ -22,10 +22,10 @@ config CMDLINE string "Default kernel command string" default "" help - On some platforms, there is currently no way for the boot loader to - pass arguments to the kernel. For these platforms, you can supply - some command-line options at build time by entering them here. In - other cases you can specify kernel args so that you don't have + On some platforms, there is currently no way for the boot loader to + pass arguments to the kernel. For these platforms, you can supply + some command-line options at build time by entering them here. In + other cases you can specify kernel args so that you don't have to set them up in board prom initialization routines. config DEBUG_STACK_USAGE diff --git a/trunk/arch/mips/arc/identify.c b/trunk/arch/mips/arc/identify.c index 4b907369b0f9..3ba7c47f9f23 100644 --- a/trunk/arch/mips/arc/identify.c +++ b/trunk/arch/mips/arc/identify.c @@ -77,7 +77,7 @@ static struct smatch * __init string_to_mach(const char *s) { int i; - for (i = 0; i < ARRAY_SIZE(mach_table); i++) { + for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) { if (!strcmp(s, mach_table[i].arcname)) return &mach_table[i]; } diff --git a/trunk/arch/mips/arc/memory.c b/trunk/arch/mips/arc/memory.c index 456cb81a32d9..8a9ef58cc399 100644 --- a/trunk/arch/mips/arc/memory.c +++ b/trunk/arch/mips/arc/memory.c @@ -141,20 +141,30 @@ void __init prom_meminit(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + unsigned long freed = 0; unsigned long addr; int i; if (prom_flags & PROM_FLAG_DONT_FREE_TEMP) - return; + return 0; for (i = 0; i < boot_mem_map.nr_map; i++) { if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; addr = boot_mem_map.map[i].addr; - free_init_pages("prom memory", - addr, addr + boot_mem_map.map[i].size); + while (addr < boot_mem_map.map[i].addr + + boot_mem_map.map[i].size) { + ClearPageReserved(virt_to_page(__va(addr))); + init_page_count(virt_to_page(__va(addr))); + free_page((unsigned long)__va(addr)); + addr += PAGE_SIZE; + freed += PAGE_SIZE; + } } + printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); + + return freed; } diff --git a/trunk/arch/mips/au1000/common/irq.c b/trunk/arch/mips/au1000/common/irq.c index ea6e99fbe2f7..9cf7b6715836 100644 --- a/trunk/arch/mips/au1000/common/irq.c +++ b/trunk/arch/mips/au1000/common/irq.c @@ -233,7 +233,7 @@ void restore_local_and_enable(int controller, unsigned long mask) static struct irq_chip rise_edge_irq_type = { - .name = "Au1000 Rise Edge", + .typename = "Au1000 Rise Edge", .ack = mask_and_ack_rise_edge_irq, .mask = local_disable_irq, .mask_ack = mask_and_ack_rise_edge_irq, @@ -242,7 +242,7 @@ static struct irq_chip rise_edge_irq_type = { }; static struct irq_chip fall_edge_irq_type = { - .name = "Au1000 Fall Edge", + .typename = "Au1000 Fall Edge", .ack = mask_and_ack_fall_edge_irq, .mask = local_disable_irq, .mask_ack = mask_and_ack_fall_edge_irq, @@ -251,7 +251,7 @@ static struct irq_chip fall_edge_irq_type = { }; static struct irq_chip either_edge_irq_type = { - .name = "Au1000 Rise or Fall Edge", + .typename = "Au1000 Rise or Fall Edge", .ack = mask_and_ack_either_edge_irq, .mask = local_disable_irq, .mask_ack = mask_and_ack_either_edge_irq, @@ -260,7 +260,7 @@ static struct irq_chip either_edge_irq_type = { }; static struct irq_chip level_irq_type = { - .name = "Au1000 Level", + .typename = "Au1000 Level", .ack = mask_and_ack_level_irq, .mask = local_disable_irq, .mask_ack = mask_and_ack_level_irq, diff --git a/trunk/arch/mips/au1000/common/pci.c b/trunk/arch/mips/au1000/common/pci.c index 6c25e6c09f78..9f8ce08e173b 100644 --- a/trunk/arch/mips/au1000/common/pci.c +++ b/trunk/arch/mips/au1000/common/pci.c @@ -76,17 +76,13 @@ static int __init au1x_pci_setup(void) } #ifdef CONFIG_DMA_NONCOHERENT - { - /* - * Set the NC bit in controller for Au1500 pre-AC silicon - */ - u32 prid = read_c0_prid(); - - if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { - au_writel((1 << 16) | au_readl(Au1500_PCI_CFG), - Au1500_PCI_CFG); - printk("Non-coherent PCI accesses enabled\n"); - } + /* + * Set the NC bit in controller for Au1500 pre-AC silicon + */ + u32 prid = read_c0_prid(); + if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { + au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG); + printk("Non-coherent PCI accesses enabled\n"); } #endif diff --git a/trunk/arch/mips/au1000/common/prom.c b/trunk/arch/mips/au1000/common/prom.c index a8637cdb5b4b..6fce60af005d 100644 --- a/trunk/arch/mips/au1000/common/prom.c +++ b/trunk/arch/mips/au1000/common/prom.c @@ -149,8 +149,9 @@ int get_ethernet_addr(char *ethernet_addr) return 0; } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } EXPORT_SYMBOL(prom_getcmdline); diff --git a/trunk/arch/mips/au1000/common/setup.c b/trunk/arch/mips/au1000/common/setup.c index 13fe187f35d6..919172db560c 100644 --- a/trunk/arch/mips/au1000/common/setup.c +++ b/trunk/arch/mips/au1000/common/setup.c @@ -141,20 +141,17 @@ void __init plat_mem_setup(void) /* This routine should be valid for all Au1x based boards */ phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) { + u32 start, end; + /* Don't fixup 36 bit addresses */ - if ((phys_addr >> 32) != 0) - return phys_addr; + if ((phys_addr >> 32) != 0) return phys_addr; #ifdef CONFIG_PCI - { - u32 start, end; - - start = (u32)Au1500_PCI_MEM_START; - end = (u32)Au1500_PCI_MEM_END; - /* check for pci memory window */ - if ((phys_addr >= start) && ((phys_addr + size) < end)) - return (phys_t) - ((phys_addr - start) + Au1500_PCI_MEM_START); + start = (u32)Au1500_PCI_MEM_START; + end = (u32)Au1500_PCI_MEM_END; + /* check for pci memory window */ + if ((phys_addr >= start) && ((phys_addr + size) < end)) { + return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START); } #endif diff --git a/trunk/arch/mips/au1000/pb1100/board_setup.c b/trunk/arch/mips/au1000/pb1100/board_setup.c index 6bc1f8e1b608..2d1533f116c0 100644 --- a/trunk/arch/mips/au1000/pb1100/board_setup.c +++ b/trunk/arch/mips/au1000/pb1100/board_setup.c @@ -47,7 +47,8 @@ void board_reset (void) void __init board_setup(void) { - volatile void __iomem * base = (volatile void __iomem *) 0xac000000UL; + u32 pin_func; + u32 sys_freqctrl, sys_clksrc; // set AUX clock to 12MHz * 8 = 96 MHz au_writel(8, SYS_AUXPLL); @@ -55,62 +56,58 @@ void __init board_setup(void) udelay(100); #ifdef CONFIG_USB_OHCI - { - u32 pin_func, sys_freqctrl, sys_clksrc; - - // configure pins GPIO[14:9] as GPIO - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); - - /* zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD/IrDA clock */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - - // FREQ2 = aux/2 = 48 MHz - sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48MHz FREQ2 into USBH/USBD/IrDA - */ - sys_clksrc |= ((4<<2) | (0<<1) | 0 ); - au_writel(sys_clksrc, SYS_CLKSRC); - - /* setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ - - // get USB Functionality pin state (device vs host drive pins) - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); - // 2nd USB port is USB host - pin_func |= 0x8000; - au_writel(pin_func, SYS_PINFUNC); - } + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD/IrDA clock */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USBH/USBD/IrDA + */ + sys_clksrc |= ((4<<2) | (0<<1) | 0 ); + au_writel(sys_clksrc, SYS_CLKSRC); + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + // get USB Functionality pin state (device vs host drive pins) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + // 2nd USB port is USB host + pin_func |= 0x8000; + au_writel(pin_func, SYS_PINFUNC); #endif // defined (CONFIG_USB_OHCI) /* Enable sys bus clock divider when IDLE state or no bus activity. */ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); // Enable the RTC if not already enabled - if (!(readb(base + 0x28) & 0x20)) { - writeb(readb(base + 0x28) | 0x20, base + 0x28); + if (!(readb(0xac000028) & 0x20)) { + writeb(readb(0xac000028) | 0x20, 0xac000028); au_sync(); } // Put the clock in BCD mode - if (readb(base + 0x2C) & 0x4) { /* reg B */ - writeb(readb(base + 0x2c) & ~0x4, base + 0x2c); + if (readb(0xac00002C) & 0x4) { /* reg B */ + writeb(readb(0xac00002c) & ~0x4, 0xac00002c); au_sync(); } } diff --git a/trunk/arch/mips/au1000/pb1200/irqmap.c b/trunk/arch/mips/au1000/pb1200/irqmap.c index b73b2d18bf56..91983ba407c4 100644 --- a/trunk/arch/mips/au1000/pb1200/irqmap.c +++ b/trunk/arch/mips/au1000/pb1200/irqmap.c @@ -137,20 +137,33 @@ static void pb1200_shutdown_irq( unsigned int irq_nr ) return; } +static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr) +{ + pb1200_disable_irq( irq_nr ); +} + +static void pb1200_end_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + pb1200_enable_irq(irq_nr); + } +} + static struct irq_chip external_irq_type = { #ifdef CONFIG_MIPS_PB1200 - .name = "Pb1200 Ext", + "Pb1200 Ext", #endif #ifdef CONFIG_MIPS_DB1200 - .name = "Db1200 Ext", + "Db1200 Ext", #endif - .startup = pb1200_startup_irq, - .shutdown = pb1200_shutdown_irq, - .ack = pb1200_disable_irq, - .mask = pb1200_disable_irq, - .mask_ack = pb1200_disable_irq, - .unmask = pb1200_enable_irq, + pb1200_startup_irq, + pb1200_shutdown_irq, + pb1200_enable_irq, + pb1200_disable_irq, + pb1200_mask_and_ack_irq, + pb1200_end_irq, + NULL }; void _board_init_irq(void) @@ -159,8 +172,7 @@ void _board_init_irq(void) for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++) { - set_irq_chip_and_handler(irq_nr, &external_irq_type, - handle_level_irq); + irq_desc[irq_nr].chip = &external_irq_type; pb1200_disable_irq(irq_nr); } diff --git a/trunk/arch/mips/basler/excite/excite_irq.c b/trunk/arch/mips/basler/excite/excite_irq.c index 1ecab6350421..2e2061a286c5 100644 --- a/trunk/arch/mips/basler/excite/excite_irq.c +++ b/trunk/arch/mips/basler/excite/excite_irq.c @@ -47,9 +47,9 @@ extern asmlinkage void excite_handle_int(void); */ void __init arch_init_irq(void) { - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); - rm9k_cpu_irq_init(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); + rm9k_cpu_irq_init(12); #ifdef CONFIG_KGDB excite_kgdb_init(); diff --git a/trunk/arch/mips/cobalt/irq.c b/trunk/arch/mips/cobalt/irq.c index fe93b846923b..4c46f0e73783 100644 --- a/trunk/arch/mips/cobalt/irq.c +++ b/trunk/arch/mips/cobalt/irq.c @@ -104,7 +104,7 @@ void __init arch_init_irq(void) GT_WRITE(GT_INTRMASK_OFS, 0); init_i8259_irqs(); /* 0 ... 15 */ - mips_cpu_irq_init(); /* 16 ... 23 */ + mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ /* * Mask all cpu interrupts diff --git a/trunk/arch/mips/cobalt/setup.c b/trunk/arch/mips/cobalt/setup.c index a4b69b543bd9..e8f0f20b852d 100644 --- a/trunk/arch/mips/cobalt/setup.c +++ b/trunk/arch/mips/cobalt/setup.c @@ -204,7 +204,8 @@ void __init prom_init(void) add_memory_region(0x0, memsz, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Nothing to do! */ + return 0; } diff --git a/trunk/arch/mips/ddb5xxx/common/prom.c b/trunk/arch/mips/ddb5xxx/common/prom.c index 54a857b5e3ba..efef0f57ce1e 100644 --- a/trunk/arch/mips/ddb5xxx/common/prom.c +++ b/trunk/arch/mips/ddb5xxx/common/prom.c @@ -59,8 +59,9 @@ void __init prom_init(void) #endif } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } #if defined(CONFIG_DDB5477) diff --git a/trunk/arch/mips/ddb5xxx/ddb5477/irq.c b/trunk/arch/mips/ddb5xxx/ddb5477/irq.c index 2b23234a5b95..a8bd2e66705c 100644 --- a/trunk/arch/mips/ddb5xxx/ddb5477/irq.c +++ b/trunk/arch/mips/ddb5xxx/ddb5477/irq.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -74,6 +73,7 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger) } extern void vrc5477_irq_init(u32 base); +extern void mips_cpu_irq_init(u32 base); static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; void __init arch_init_irq(void) @@ -125,7 +125,7 @@ void __init arch_init_irq(void) /* init all controllers */ init_i8259_irqs(); - mips_cpu_irq_init(); + mips_cpu_irq_init(CPU_IRQ_BASE); vrc5477_irq_init(VRC5477_IRQ_BASE); @@ -146,7 +146,8 @@ u8 i8259_interrupt_ack(void) irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); ddb_out32(DDB_PCIINIT10, reg); - return irq; + /* i8259.c set the base vector to be 0x0 */ + return irq + I8259_IRQ_BASE; } /* * the first level int-handler will jump here if it is a vrc5477 irq @@ -176,7 +177,7 @@ static void vrc5477_irq_dispatch(void) /* check for i8259 interrupts */ if (intStatus & (1 << VRC5477_I8259_CASCADE)) { int i8259_irq = i8259_interrupt_ack(); - do_IRQ(i8259_irq); + do_IRQ(I8259_IRQ_BASE + i8259_irq); return; } } diff --git a/trunk/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/trunk/arch/mips/ddb5xxx/ddb5477/irq_5477.c index 98c3b15eb369..96249aa5df5d 100644 --- a/trunk/arch/mips/ddb5xxx/ddb5477/irq_5477.c +++ b/trunk/arch/mips/ddb5xxx/ddb5477/irq_5477.c @@ -82,7 +82,7 @@ vrc5477_irq_end(unsigned int irq) } struct irq_chip vrc5477_irq_controller = { - .name = "vrc5477_irq", + .typename = "vrc5477_irq", .ack = vrc5477_irq_ack, .mask = vrc5477_irq_disable, .mask_ack = vrc5477_irq_ack, diff --git a/trunk/arch/mips/dec/ioasic-irq.c b/trunk/arch/mips/dec/ioasic-irq.c index 3acb133668dc..4c7cb4048d35 100644 --- a/trunk/arch/mips/dec/ioasic-irq.c +++ b/trunk/arch/mips/dec/ioasic-irq.c @@ -62,7 +62,7 @@ static inline void end_ioasic_irq(unsigned int irq) } static struct irq_chip ioasic_irq_type = { - .name = "IO-ASIC", + .typename = "IO-ASIC", .ack = ack_ioasic_irq, .mask = mask_ioasic_irq, .mask_ack = ack_ioasic_irq, @@ -84,7 +84,7 @@ static inline void end_ioasic_dma_irq(unsigned int irq) } static struct irq_chip ioasic_dma_irq_type = { - .name = "IO-ASIC-DMA", + .typename = "IO-ASIC-DMA", .ack = ack_ioasic_dma_irq, .mask = mask_ioasic_dma_irq, .mask_ack = ack_ioasic_dma_irq, diff --git a/trunk/arch/mips/dec/kn02-irq.c b/trunk/arch/mips/dec/kn02-irq.c index 02439dc0ba83..916e46b8ccd8 100644 --- a/trunk/arch/mips/dec/kn02-irq.c +++ b/trunk/arch/mips/dec/kn02-irq.c @@ -58,7 +58,7 @@ static void ack_kn02_irq(unsigned int irq) } static struct irq_chip kn02_irq_type = { - .name = "KN02-CSR", + .typename = "KN02-CSR", .ack = ack_kn02_irq, .mask = mask_kn02_irq, .mask_ack = ack_kn02_irq, diff --git a/trunk/arch/mips/dec/prom/memory.c b/trunk/arch/mips/dec/prom/memory.c index 5a557e268f78..3aa01d268f2d 100644 --- a/trunk/arch/mips/dec/prom/memory.c +++ b/trunk/arch/mips/dec/prom/memory.c @@ -92,9 +92,9 @@ void __init prom_meminit(u32 magic) rex_setup_memory_region(); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { - unsigned long end; + unsigned long addr, end; /* * Free everything below the kernel itself but leave @@ -114,5 +114,16 @@ void __init prom_free_prom_memory(void) #endif end = __pa(&_text); - free_init_pages("unused PROM memory", PAGE_SIZE, end); + addr = PAGE_SIZE; + while (addr < end) { + ClearPageReserved(virt_to_page(__va(addr))); + init_page_count(virt_to_page(__va(addr))); + free_page((unsigned long)__va(addr)); + addr += PAGE_SIZE; + } + + printk("Freeing unused PROM memory: %ldkb freed\n", + (end - PAGE_SIZE) >> 10); + + return end - PAGE_SIZE; } diff --git a/trunk/arch/mips/dec/setup.c b/trunk/arch/mips/dec/setup.c index 1058e2f409bb..d34032ac492a 100644 --- a/trunk/arch/mips/dec/setup.c +++ b/trunk/arch/mips/dec/setup.c @@ -234,7 +234,7 @@ static void __init dec_init_kn01(void) memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl, sizeof(kn01_cpu_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); } /* dec_init_kn01 */ @@ -309,7 +309,7 @@ static void __init dec_init_kn230(void) memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl, sizeof(kn230_cpu_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); } /* dec_init_kn230 */ @@ -403,7 +403,7 @@ static void __init dec_init_kn02(void) memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl, sizeof(kn02_asic_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); init_kn02_irqs(KN02_IRQ_BASE); } /* dec_init_kn02 */ @@ -504,7 +504,7 @@ static void __init dec_init_kn02ba(void) memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl, sizeof(kn02ba_asic_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); init_ioasic_irqs(IO_IRQ_BASE); } /* dec_init_kn02ba */ @@ -601,7 +601,7 @@ static void __init dec_init_kn02ca(void) memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl, sizeof(kn02ca_asic_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); init_ioasic_irqs(IO_IRQ_BASE); } /* dec_init_kn02ca */ @@ -702,7 +702,7 @@ static void __init dec_init_kn03(void) memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl, sizeof(kn03_asic_mask_nr_tbl)); - mips_cpu_irq_init(); + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); init_ioasic_irqs(IO_IRQ_BASE); } /* dec_init_kn03 */ diff --git a/trunk/arch/mips/emma2rh/common/irq_emma2rh.c b/trunk/arch/mips/emma2rh/common/irq_emma2rh.c index 96df37b77759..8d880f0b06ec 100644 --- a/trunk/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/trunk/arch/mips/emma2rh/common/irq_emma2rh.c @@ -57,7 +57,7 @@ static void emma2rh_irq_disable(unsigned int irq) } struct irq_chip emma2rh_irq_controller = { - .name = "emma2rh_irq", + .typename = "emma2rh_irq", .ack = emma2rh_irq_disable, .mask = emma2rh_irq_disable, .mask_ack = emma2rh_irq_disable, diff --git a/trunk/arch/mips/emma2rh/markeins/irq.c b/trunk/arch/mips/emma2rh/markeins/irq.c index 3299b6dfe764..c93369cb4115 100644 --- a/trunk/arch/mips/emma2rh/markeins/irq.c +++ b/trunk/arch/mips/emma2rh/markeins/irq.c @@ -106,7 +106,7 @@ void __init arch_init_irq(void) emma2rh_irq_init(EMMA2RH_IRQ_BASE); emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE); emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE); - mips_cpu_irq_init(); + mips_cpu_irq_init(CPU_IRQ_BASE); /* setup cascade interrupts */ setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); diff --git a/trunk/arch/mips/emma2rh/markeins/irq_markeins.c b/trunk/arch/mips/emma2rh/markeins/irq_markeins.c index fba5c156f472..2116d9be5fa9 100644 --- a/trunk/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/trunk/arch/mips/emma2rh/markeins/irq_markeins.c @@ -49,7 +49,7 @@ static void emma2rh_sw_irq_disable(unsigned int irq) } struct irq_chip emma2rh_sw_irq_controller = { - .name = "emma2rh_sw_irq", + .typename = "emma2rh_sw_irq", .ack = emma2rh_sw_irq_disable, .mask = emma2rh_sw_irq_disable, .mask_ack = emma2rh_sw_irq_disable, @@ -115,7 +115,7 @@ static void emma2rh_gpio_irq_end(unsigned int irq) } struct irq_chip emma2rh_gpio_irq_controller = { - .name = "emma2rh_gpio_irq", + .typename = "emma2rh_gpio_irq", .ack = emma2rh_gpio_irq_ack, .mask = emma2rh_gpio_irq_disable, .mask_ack = emma2rh_gpio_irq_ack, diff --git a/trunk/arch/mips/gt64120/ev64120/irq.c b/trunk/arch/mips/gt64120/ev64120/irq.c index 04572b9c9642..b3e5796c81d7 100644 --- a/trunk/arch/mips/gt64120/ev64120/irq.c +++ b/trunk/arch/mips/gt64120/ev64120/irq.c @@ -88,7 +88,7 @@ static void end_ev64120_irq(unsigned int irq) } static struct irq_chip ev64120_irq_type = { - .name = "EV64120", + .typename = "EV64120", .ack = disable_ev64120_irq, .mask = disable_ev64120_irq, .mask_ack = disable_ev64120_irq, diff --git a/trunk/arch/mips/gt64120/ev64120/setup.c b/trunk/arch/mips/gt64120/ev64120/setup.c index 477848c22a2c..99c8d42212e2 100644 --- a/trunk/arch/mips/gt64120/ev64120/setup.c +++ b/trunk/arch/mips/gt64120/ev64120/setup.c @@ -59,8 +59,9 @@ extern void galileo_machine_power_off(void); */ extern struct pci_ops galileo_pci_ops; -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } /* diff --git a/trunk/arch/mips/gt64120/momenco_ocelot/dbg_io.c b/trunk/arch/mips/gt64120/momenco_ocelot/dbg_io.c index 32d6fb4ee679..2128684584f5 100644 --- a/trunk/arch/mips/gt64120/momenco_ocelot/dbg_io.c +++ b/trunk/arch/mips/gt64120/momenco_ocelot/dbg_io.c @@ -1,4 +1,6 @@ +#ifdef CONFIG_KGDB + #include /* For the serial port location and base baud */ /* --- CONFIG --- */ @@ -119,3 +121,5 @@ int putDebugChar(uint8 byte) UART16550_WRITE(OFS_SEND_BUFFER, byte); return 1; } + +#endif diff --git a/trunk/arch/mips/gt64120/momenco_ocelot/irq.c b/trunk/arch/mips/gt64120/momenco_ocelot/irq.c index 2585d9dbda33..d9294401ccb0 100644 --- a/trunk/arch/mips/gt64120/momenco_ocelot/irq.c +++ b/trunk/arch/mips/gt64120/momenco_ocelot/irq.c @@ -90,6 +90,6 @@ void __init arch_init_irq(void) clear_c0_status(ST0_IM); local_irq_disable(); - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); } diff --git a/trunk/arch/mips/gt64120/momenco_ocelot/prom.c b/trunk/arch/mips/gt64120/momenco_ocelot/prom.c index 78f393b2afd9..8677b6d3ada7 100644 --- a/trunk/arch/mips/gt64120/momenco_ocelot/prom.c +++ b/trunk/arch/mips/gt64120/momenco_ocelot/prom.c @@ -67,6 +67,7 @@ void __init prom_init(void) add_memory_region(0, 64 << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff --git a/trunk/arch/mips/gt64120/wrppmc/irq.c b/trunk/arch/mips/gt64120/wrppmc/irq.c index d3d96591780e..eedfc24e1eae 100644 --- a/trunk/arch/mips/gt64120/wrppmc/irq.c +++ b/trunk/arch/mips/gt64120/wrppmc/irq.c @@ -63,7 +63,7 @@ void gt64120_init_pic(void) void __init arch_init_irq(void) { /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ - mips_cpu_irq_init(); + mips_cpu_irq_init(0); gt64120_init_pic(); } diff --git a/trunk/arch/mips/gt64120/wrppmc/setup.c b/trunk/arch/mips/gt64120/wrppmc/setup.c index 121188d5ec4a..429afc400cb4 100644 --- a/trunk/arch/mips/gt64120/wrppmc/setup.c +++ b/trunk/arch/mips/gt64120/wrppmc/setup.c @@ -93,8 +93,9 @@ void __init wrppmc_early_printk(const char *fmt, ...) } #endif /* WRPPMC_EARLY_DEBUG */ -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } #ifdef CONFIG_SERIAL_8250 diff --git a/trunk/arch/mips/jazz/irq.c b/trunk/arch/mips/jazz/irq.c index 295892e4ce53..f8d417b5c2bb 100644 --- a/trunk/arch/mips/jazz/irq.c +++ b/trunk/arch/mips/jazz/irq.c @@ -40,7 +40,7 @@ void disable_r4030_irq(unsigned int irq) } static struct irq_chip r4030_irq_type = { - .name = "R4030", + .typename = "R4030", .ack = disable_r4030_irq, .mask = disable_r4030_irq, .mask_ack = disable_r4030_irq, diff --git a/trunk/arch/mips/jmr3927/common/prom.c b/trunk/arch/mips/jmr3927/common/prom.c index aa481b774c42..5d5838f41d23 100644 --- a/trunk/arch/mips/jmr3927/common/prom.c +++ b/trunk/arch/mips/jmr3927/common/prom.c @@ -75,6 +75,7 @@ void __init prom_init_cmdline(void) *cp = '\0'; } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff --git a/trunk/arch/mips/jmr3927/rbhma3100/irq.c b/trunk/arch/mips/jmr3927/rbhma3100/irq.c index 7d2c203cb406..3da49c5aaf49 100644 --- a/trunk/arch/mips/jmr3927/rbhma3100/irq.c +++ b/trunk/arch/mips/jmr3927/rbhma3100/irq.c @@ -439,7 +439,7 @@ void __init arch_init_irq(void) } static struct irq_chip jmr3927_irq_controller = { - .name = "jmr3927_irq", + .typename = "jmr3927_irq", .ack = jmr3927_irq_ack, .mask = jmr3927_irq_disable, .mask_ack = jmr3927_irq_ack, diff --git a/trunk/arch/mips/jmr3927/rbhma3100/setup.c b/trunk/arch/mips/jmr3927/rbhma3100/setup.c index 7ca3d6d07b34..138f25efe38a 100644 --- a/trunk/arch/mips/jmr3927/rbhma3100/setup.c +++ b/trunk/arch/mips/jmr3927/rbhma3100/setup.c @@ -434,7 +434,7 @@ void __init tx3927_setup(void) /* DMA */ tx3927_dmaptr->mcr = 0; - for (i = 0; i < ARRAY_SIZE(tx3927_dmaptr->ch); i++) { + for (i = 0; i < sizeof(tx3927_dmaptr->ch) / sizeof(tx3927_dmaptr->ch[0]); i++) { /* reset channel */ tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST; tx3927_dmaptr->ch[i].ccr = 0; diff --git a/trunk/arch/mips/kernel/asm-offsets.c b/trunk/arch/mips/kernel/asm-offsets.c index ea7df4b8da33..ff88b06f89df 100644 --- a/trunk/arch/mips/kernel/asm-offsets.c +++ b/trunk/arch/mips/kernel/asm-offsets.c @@ -234,6 +234,10 @@ void output_mm_defines(void) constant("#define _PMD_SHIFT ", PMD_SHIFT); constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); linefeed; + constant("#define _PGD_ORDER ", PGD_ORDER); + constant("#define _PMD_ORDER ", PMD_ORDER); + constant("#define _PTE_ORDER ", PTE_ORDER); + linefeed; constant("#define _PTRS_PER_PGD ", PTRS_PER_PGD); constant("#define _PTRS_PER_PMD ", PTRS_PER_PMD); constant("#define _PTRS_PER_PTE ", PTRS_PER_PTE); diff --git a/trunk/arch/mips/kernel/cpu-probe.c b/trunk/arch/mips/kernel/cpu-probe.c index f59ef271d247..442839e9578c 100644 --- a/trunk/arch/mips/kernel/cpu-probe.c +++ b/trunk/arch/mips/kernel/cpu-probe.c @@ -565,7 +565,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) if (config3 & MIPS_CONF3_VEIC) c->options |= MIPS_CPU_VEIC; if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; + c->ases |= MIPS_ASE_MIPSMT; return config3 & MIPS_CONF_M; } diff --git a/trunk/arch/mips/kernel/gdb-stub.c b/trunk/arch/mips/kernel/gdb-stub.c index 7bc882049269..719d26968cb2 100644 --- a/trunk/arch/mips/kernel/gdb-stub.c +++ b/trunk/arch/mips/kernel/gdb-stub.c @@ -505,13 +505,13 @@ void show_gdbregs(struct gdb_regs * regs) */ printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", regs->reg0, regs->reg1, regs->reg2, regs->reg3, - regs->reg4, regs->reg5, regs->reg6, regs->reg7); + regs->reg4, regs->reg5, regs->reg6, regs->reg7); printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", regs->reg8, regs->reg9, regs->reg10, regs->reg11, - regs->reg12, regs->reg13, regs->reg14, regs->reg15); + regs->reg12, regs->reg13, regs->reg14, regs->reg15); printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", regs->reg16, regs->reg17, regs->reg18, regs->reg19, - regs->reg20, regs->reg21, regs->reg22, regs->reg23); + regs->reg20, regs->reg21, regs->reg22, regs->reg23); printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", regs->reg24, regs->reg25, regs->reg26, regs->reg27, regs->reg28, regs->reg29, regs->reg30, regs->reg31); diff --git a/trunk/arch/mips/kernel/head.S b/trunk/arch/mips/kernel/head.S index 6f57ca44291f..9a7811d13db2 100644 --- a/trunk/arch/mips/kernel/head.S +++ b/trunk/arch/mips/kernel/head.S @@ -231,3 +231,28 @@ NESTED(smp_bootstrap, 16, sp) #endif /* CONFIG_SMP */ __FINIT + + .comm kernelsp, NR_CPUS * 8, 8 + .comm pgd_current, NR_CPUS * 8, 8 + + .comm fw_arg0, SZREG, SZREG # firmware arguments + .comm fw_arg1, SZREG, SZREG + .comm fw_arg2, SZREG, SZREG + .comm fw_arg3, SZREG, SZREG + + .macro page name, order + .comm \name, (_PAGE_SIZE << \order), (_PAGE_SIZE << \order) + .endm + + /* + * On 64-bit we've got three-level pagetables with a slightly + * different layout ... + */ + page swapper_pg_dir, _PGD_ORDER +#ifdef CONFIG_64BIT +#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64) + page module_pg_dir, _PGD_ORDER +#endif + page invalid_pmd_table, _PMD_ORDER +#endif + page invalid_pte_table, _PTE_ORDER diff --git a/trunk/arch/mips/kernel/i8259.c b/trunk/arch/mips/kernel/i8259.c index b33ba6cd7f5b..b59a676c6d0e 100644 --- a/trunk/arch/mips/kernel/i8259.c +++ b/trunk/arch/mips/kernel/i8259.c @@ -54,11 +54,9 @@ static unsigned int cached_irq_mask = 0xffff; void disable_8259A_irq(unsigned int irq) { - unsigned int mask; + unsigned int mask = 1 << irq; unsigned long flags; - irq -= I8259A_IRQ_BASE; - mask = 1 << irq; spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; if (irq & 8) @@ -70,11 +68,9 @@ void disable_8259A_irq(unsigned int irq) void enable_8259A_irq(unsigned int irq) { - unsigned int mask; + unsigned int mask = ~(1 << irq); unsigned long flags; - irq -= I8259A_IRQ_BASE; - mask = ~(1 << irq); spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; if (irq & 8) @@ -86,12 +82,10 @@ void enable_8259A_irq(unsigned int irq) int i8259A_irq_pending(unsigned int irq) { - unsigned int mask; + unsigned int mask = 1 << irq; unsigned long flags; int ret; - irq -= I8259A_IRQ_BASE; - mask = 1 << irq; spin_lock_irqsave(&i8259A_lock, flags); if (irq < 8) ret = inb(PIC_MASTER_CMD) & mask; @@ -140,11 +134,9 @@ static inline int i8259A_irq_real(unsigned int irq) */ void mask_and_ack_8259A(unsigned int irq) { - unsigned int irqmask; + unsigned int irqmask = 1 << irq; unsigned long flags; - irq -= I8259A_IRQ_BASE; - irqmask = 1 << irq; spin_lock_irqsave(&i8259A_lock, flags); /* * Lightweight spurious IRQ detection. We do not want @@ -177,8 +169,8 @@ void mask_and_ack_8259A(unsigned int irq) outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */ } #ifdef CONFIG_MIPS_MT_SMTC - if (irq_hwmask[irq] & ST0_IM) - set_c0_status(irq_hwmask[irq] & ST0_IM); + if (irq_hwmask[irq] & ST0_IM) + set_c0_status(irq_hwmask[irq] & ST0_IM); #endif /* CONFIG_MIPS_MT_SMTC */ spin_unlock_irqrestore(&i8259A_lock, flags); return; @@ -330,8 +322,8 @@ void __init init_i8259_irqs (void) init_8259A(0); - for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) + for (i = 0; i < 16; i++) set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq); - setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2); + setup_irq(PIC_CASCADE_IR, &irq2); } diff --git a/trunk/arch/mips/kernel/irixelf.c b/trunk/arch/mips/kernel/irixelf.c index 3cc25c05d367..37cad5de515c 100644 --- a/trunk/arch/mips/kernel/irixelf.c +++ b/trunk/arch/mips/kernel/irixelf.c @@ -10,8 +10,6 @@ * Copyright (C) 1996 - 2004 David S. Miller * Copyright (C) 2004 - 2005 Steven J. Hill */ -#undef DEBUG - #include #include #include @@ -42,6 +40,8 @@ #include +#undef DEBUG + static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs); static int load_irix_library(struct file *); static int irix_core_dump(long signr, struct pt_regs * regs, @@ -52,102 +52,72 @@ static struct linux_binfmt irix_format = { irix_core_dump, PAGE_SIZE }; +#ifdef DEBUG /* Debugging routines. */ static char *get_elf_p_type(Elf32_Word p_type) { -#ifdef DEBUG - switch (p_type) { - case PT_NULL: - return "PT_NULL"; - break; - - case PT_LOAD: - return "PT_LOAD"; - break; - - case PT_DYNAMIC: - return "PT_DYNAMIC"; - break; - - case PT_INTERP: - return "PT_INTERP"; - break; - - case PT_NOTE: - return "PT_NOTE"; - break; - - case PT_SHLIB: - return "PT_SHLIB"; - break; - - case PT_PHDR: - return "PT_PHDR"; - break; - - case PT_LOPROC: - return "PT_LOPROC/REGINFO"; - break; - - case PT_HIPROC: - return "PT_HIPROC"; - break; - - default: - return "PT_BOGUS"; - break; + int i = (int) p_type; + + switch(i) { + case PT_NULL: return("PT_NULL"); break; + case PT_LOAD: return("PT_LOAD"); break; + case PT_DYNAMIC: return("PT_DYNAMIC"); break; + case PT_INTERP: return("PT_INTERP"); break; + case PT_NOTE: return("PT_NOTE"); break; + case PT_SHLIB: return("PT_SHLIB"); break; + case PT_PHDR: return("PT_PHDR"); break; + case PT_LOPROC: return("PT_LOPROC/REGINFO"); break; + case PT_HIPROC: return("PT_HIPROC"); break; + default: return("PT_BOGUS"); break; } -#endif } static void print_elfhdr(struct elfhdr *ehp) { int i; - pr_debug("ELFHDR: e_ident<"); - for (i = 0; i < (EI_NIDENT - 1); i++) - pr_debug("%x ", ehp->e_ident[i]); - pr_debug("%x>\n", ehp->e_ident[i]); - pr_debug(" e_type[%04x] e_machine[%04x] e_version[%08lx]\n", - (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine, - (unsigned long) ehp->e_version); - pr_debug(" e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] " - "e_flags[%08lx]\n", - (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff, - (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags); - pr_debug(" e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n", - (unsigned short) ehp->e_ehsize, - (unsigned short) ehp->e_phentsize, - (unsigned short) ehp->e_phnum); - pr_debug(" e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n", - (unsigned short) ehp->e_shentsize, - (unsigned short) ehp->e_shnum, - (unsigned short) ehp->e_shstrndx); + printk("ELFHDR: e_ident<"); + for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]); + printk("%x>\n", ehp->e_ident[i]); + printk(" e_type[%04x] e_machine[%04x] e_version[%08lx]\n", + (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine, + (unsigned long) ehp->e_version); + printk(" e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] " + "e_flags[%08lx]\n", + (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff, + (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags); + printk(" e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n", + (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize, + (unsigned short) ehp->e_phnum); + printk(" e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n", + (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum, + (unsigned short) ehp->e_shstrndx); } static void print_phdr(int i, struct elf_phdr *ep) { - pr_debug("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] " - "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type), - (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr, - (unsigned long) ep->p_paddr); - pr_debug(" p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] " - "p_align[%08lx]\n", (unsigned long) ep->p_filesz, - (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags, - (unsigned long) ep->p_align); + printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] " + "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type), + (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr, + (unsigned long) ep->p_paddr); + printk(" p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] " + "p_align[%08lx]\n", (unsigned long) ep->p_filesz, + (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags, + (unsigned long) ep->p_align); } static void dump_phdrs(struct elf_phdr *ep, int pnum) { int i; - for (i = 0; i < pnum; i++, ep++) { - if ((ep->p_type == PT_LOAD) || - (ep->p_type == PT_INTERP) || - (ep->p_type == PT_PHDR)) + for(i = 0; i < pnum; i++, ep++) { + if((ep->p_type == PT_LOAD) || + (ep->p_type == PT_INTERP) || + (ep->p_type == PT_PHDR)) print_phdr(i, ep); } } +#endif /* DEBUG */ static void set_brk(unsigned long start, unsigned long end) { @@ -186,10 +156,11 @@ static unsigned long * create_irix_tables(char * p, int argc, int envc, elf_addr_t *envp; elf_addr_t *sp, *csp; - pr_debug("create_irix_tables: p[%p] argc[%d] envc[%d] " - "load_addr[%08x] interp_load_addr[%08x]\n", - p, argc, envc, load_addr, interp_load_addr); - +#ifdef DEBUG + printk("create_irix_tables: p[%p] argc[%d] envc[%d] " + "load_addr[%08x] interp_load_addr[%08x]\n", + p, argc, envc, load_addr, interp_load_addr); +#endif sp = (elf_addr_t *) (~15UL & (unsigned long) p); csp = sp; csp -= exec ? DLINFO_ITEMS*2 : 2; @@ -210,7 +181,7 @@ static unsigned long * create_irix_tables(char * p, int argc, int envc, sp -= 2; NEW_AUX_ENT(0, AT_NULL, 0); - if (exec) { + if(exec) { sp -= 11*2; NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff); @@ -274,7 +245,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, last_bss = 0; error = load_addr = 0; +#ifdef DEBUG print_elfhdr(interp_elf_ex); +#endif /* First of all, some simple consistency checks */ if ((interp_elf_ex->e_type != ET_EXEC && @@ -285,7 +258,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, } /* Now read in all of the header information */ - if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) { + if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) { printk("IRIX interp header bigger than a page (%d)\n", (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum)); return 0xffffffff; @@ -294,15 +267,15 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); - if (!elf_phdata) { - printk("Cannot kmalloc phdata for IRIX interp.\n"); - return 0xffffffff; + if(!elf_phdata) { + printk("Cannot kmalloc phdata for IRIX interp.\n"); + return 0xffffffff; } /* If the size of this structure has changed, then punt, since * we will be doing the wrong thing. */ - if (interp_elf_ex->e_phentsize != 32) { + if(interp_elf_ex->e_phentsize != 32) { printk("IRIX interp e_phentsize == %d != 32 ", interp_elf_ex->e_phentsize); kfree(elf_phdata); @@ -313,71 +286,61 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, (char *) elf_phdata, sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); +#ifdef DEBUG dump_phdrs(elf_phdata, interp_elf_ex->e_phnum); +#endif eppnt = elf_phdata; - for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { - if (eppnt->p_type == PT_LOAD) { - int elf_type = MAP_PRIVATE | MAP_DENYWRITE; - int elf_prot = 0; - unsigned long vaddr = 0; - if (eppnt->p_flags & PF_R) - elf_prot = PROT_READ; - if (eppnt->p_flags & PF_W) - elf_prot |= PROT_WRITE; - if (eppnt->p_flags & PF_X) - elf_prot |= PROT_EXEC; - elf_type |= MAP_FIXED; - vaddr = eppnt->p_vaddr; - - pr_debug("INTERP do_mmap" - "(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", - interpreter, vaddr, - (unsigned long) - (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), - (unsigned long) - elf_prot, (unsigned long) elf_type, - (unsigned long) - (eppnt->p_offset & 0xfffff000)); - - down_write(¤t->mm->mmap_sem); - error = do_mmap(interpreter, vaddr, - eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), - elf_prot, elf_type, - eppnt->p_offset & 0xfffff000); - up_write(¤t->mm->mmap_sem); - - if (error < 0 && error > -1024) { - printk("Aieee IRIX interp mmap error=%d\n", - error); - break; /* Real error */ - } - pr_debug("error=%08lx ", (unsigned long) error); - if (!load_addr && interp_elf_ex->e_type == ET_DYN) { - load_addr = error; - pr_debug("load_addr = error "); - } - - /* - * Find the end of the file mapping for this phdr, and - * keep track of the largest address we see for this. - */ - k = eppnt->p_vaddr + eppnt->p_filesz; - if (k > elf_bss) - elf_bss = k; - - /* Do the same thing for the memory mapping - between - * elf_bss and last_bss is the bss section. - */ - k = eppnt->p_memsz + eppnt->p_vaddr; - if (k > last_bss) - last_bss = k; - pr_debug("\n"); - } + for(i=0; ie_phnum; i++, eppnt++) { + if(eppnt->p_type == PT_LOAD) { + int elf_type = MAP_PRIVATE | MAP_DENYWRITE; + int elf_prot = 0; + unsigned long vaddr = 0; + if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; + if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; + if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + elf_type |= MAP_FIXED; + vaddr = eppnt->p_vaddr; + + pr_debug("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", + interpreter, vaddr, + (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), + (unsigned long) elf_prot, (unsigned long) elf_type, + (unsigned long) (eppnt->p_offset & 0xfffff000)); + down_write(¤t->mm->mmap_sem); + error = do_mmap(interpreter, vaddr, + eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), + elf_prot, elf_type, + eppnt->p_offset & 0xfffff000); + up_write(¤t->mm->mmap_sem); + + if(error < 0 && error > -1024) { + printk("Aieee IRIX interp mmap error=%d\n", error); + break; /* Real error */ + } + pr_debug("error=%08lx ", (unsigned long) error); + if(!load_addr && interp_elf_ex->e_type == ET_DYN) { + load_addr = error; + pr_debug("load_addr = error "); + } + + /* Find the end of the file mapping for this phdr, and keep + * track of the largest address we see for this. + */ + k = eppnt->p_vaddr + eppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + + /* Do the same thing for the memory mapping - between + * elf_bss and last_bss is the bss section. + */ + k = eppnt->p_memsz + eppnt->p_vaddr; + if(k > last_bss) last_bss = k; + pr_debug("\n"); + } } /* Now use mmap to map the library into memory. */ - if (error < 0 && error > -1024) { + if(error < 0 && error > -1024) { pr_debug("got error %d\n", error); kfree(elf_phdata); return 0xffffffff; @@ -414,7 +377,7 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm) return -ENOEXEC; /* First of all, some simple consistency checks */ - if ((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || + if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || !bprm->file->f_op->mmap) { return -ENOEXEC; } @@ -425,7 +388,7 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm) * XXX all registers as 64bits on cpu's capable of this at * XXX exception time plus frob the XTLB exception vector. */ - if ((ehp->e_flags & EF_MIPS_ABI2)) + if((ehp->e_flags & EF_MIPS_ABI2)) return -ENOEXEC; return 0; @@ -447,7 +410,7 @@ static inline int look_for_irix_interpreter(char **name, struct file *file = NULL; *name = NULL; - for (i = 0; i < pnum; i++, epp++) { + for(i = 0; i < pnum; i++, epp++) { if (epp->p_type != PT_INTERP) continue; @@ -504,8 +467,8 @@ static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnu unsigned int tmp; int i, prot; - for (i = 0; i < pnum; i++, epp++) { - if (epp->p_type != PT_LOAD) + for(i = 0; i < pnum; i++, epp++) { + if(epp->p_type != PT_LOAD) continue; /* Map it. */ @@ -520,23 +483,23 @@ static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnu up_write(¤t->mm->mmap_sem); /* Fixup location tracking vars. */ - if ((epp->p_vaddr & 0xfffff000) < *estack) + if((epp->p_vaddr & 0xfffff000) < *estack) *estack = (epp->p_vaddr & 0xfffff000); - if (!*laddr) + if(!*laddr) *laddr = epp->p_vaddr - epp->p_offset; - if (epp->p_vaddr < *scode) + if(epp->p_vaddr < *scode) *scode = epp->p_vaddr; tmp = epp->p_vaddr + epp->p_filesz; - if (tmp > *ebss) + if(tmp > *ebss) *ebss = tmp; - if ((epp->p_flags & PF_X) && *ecode < tmp) + if((epp->p_flags & PF_X) && *ecode < tmp) *ecode = tmp; - if (*edata < tmp) + if(*edata < tmp) *edata = tmp; tmp = epp->p_vaddr + epp->p_memsz; - if (tmp > *ebrk) + if(tmp > *ebrk) *ebrk = tmp; } @@ -550,12 +513,12 @@ static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, int i; *eentry = 0xffffffff; - for (i = 0; i < pnum; i++, epp++) { - if (epp->p_type != PT_INTERP) + for(i = 0; i < pnum; i++, epp++) { + if(epp->p_type != PT_INTERP) continue; /* We should have fielded this error elsewhere... */ - if (*eentry != 0xffffffff) + if(*eentry != 0xffffffff) return -1; set_fs(old_fs); @@ -641,7 +604,9 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (elf_ex.e_shnum > 20) goto out; +#ifdef DEBUG print_elfhdr(&elf_ex); +#endif /* Now read in all of the header information */ size = elf_ex.e_phentsize * elf_ex.e_phnum; @@ -657,11 +622,13 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (retval < 0) goto out_free_ph; +#ifdef DEBUG dump_phdrs(elf_phdata, elf_ex.e_phnum); +#endif /* Set some things for later. */ - for (i = 0; i < elf_ex.e_phnum; i++) { - switch (elf_phdata[i].p_type) { + for(i = 0; i < elf_ex.e_phnum; i++) { + switch(elf_phdata[i].p_type) { case PT_INTERP: has_interp = 1; elf_ihdr = &elf_phdata[i]; @@ -700,7 +667,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); - if (retval) + if(retval) goto out_free_interp; } @@ -739,12 +706,12 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) &load_addr, &start_code, &elf_bss, &end_code, &end_data, &elf_brk); - if (elf_interpreter) { + if(elf_interpreter) { retval = map_interpreter(elf_phdata, &interp_elf_ex, interpreter, &interp_load_addr, elf_ex.e_phnum, old_fs, &elf_entry); kfree(elf_interpreter); - if (retval) { + if(retval) { set_fs(old_fs); printk("Unable to load IRIX ELF interpreter\n"); send_sig(SIGSEGV, current, 0); @@ -842,12 +809,12 @@ static int load_irix_library(struct file *file) return -ENOEXEC; /* First of all, some simple consistency checks. */ - if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || + if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || !file->f_op->mmap) return -ENOEXEC; /* Now read in all of the header information. */ - if (sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) + if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) return -ENOEXEC; elf_phdata = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); @@ -858,15 +825,15 @@ static int load_irix_library(struct file *file) sizeof(struct elf_phdr) * elf_ex.e_phnum); j = 0; - for (i=0; ip_type == PT_LOAD) j++; + for(i=0; ip_type == PT_LOAD) j++; - if (j != 1) { + if(j != 1) { kfree(elf_phdata); return -ENOEXEC; } - while (elf_phdata->p_type != PT_LOAD) elf_phdata++; + while(elf_phdata->p_type != PT_LOAD) elf_phdata++; /* Now use mmap to map the library into memory. */ down_write(¤t->mm->mmap_sem); @@ -922,7 +889,9 @@ unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt) return -EFAULT; } +#ifdef DEBUG dump_phdrs(user_phdrp, cnt); +#endif for (i = 0; i < cnt; i++, hp++) { if (__get_user(type, &hp->p_type)) @@ -936,14 +905,14 @@ unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt) filp = fget(fd); if (!filp) return -EACCES; - if (!filp->f_op) { + if(!filp->f_op) { printk("irix_mapelf: Bogon filp!\n"); fput(filp); return -EACCES; } hp = user_phdrp; - for (i = 0; i < cnt; i++, hp++) { + for(i = 0; i < cnt; i++, hp++) { int prot; retval = __get_user(vaddr, &hp->p_vaddr); @@ -1046,6 +1015,8 @@ static int notesize(struct memelfnote *en) return sz; } +/* #define DEBUG */ + #define DUMP_WRITE(addr, nr) \ if (!dump_write(file, (addr), (nr))) \ goto end_coredump; @@ -1122,7 +1093,9 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) segs++; } - pr_debug("irix_core_dump: %d segs taking %d bytes\n", segs, size); +#ifdef DEBUG + printk("irix_core_dump: %d segs taking %d bytes\n", segs, size); +#endif /* Set up header. */ memcpy(elf.e_ident, ELFMAG, SELFMAG); @@ -1248,7 +1221,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) struct elf_phdr phdr; int sz = 0; - for (i = 0; i < numnote; i++) + for(i = 0; i < numnote; i++) sz += notesize(¬es[i]); phdr.p_type = PT_NOTE; @@ -1268,7 +1241,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) dataoff = offset = roundup(offset, PAGE_SIZE); /* Write program headers for segments dump. */ - for (vma = current->mm->mmap, i = 0; + for(vma = current->mm->mmap, i = 0; i < segs && vma != NULL; vma = vma->vm_next) { struct elf_phdr phdr; size_t sz; @@ -1294,7 +1267,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) DUMP_WRITE(&phdr, sizeof(phdr)); } - for (i = 0; i < numnote; i++) + for(i = 0; i < numnote; i++) if (!writenote(¬es[i], file)) goto end_coredump; @@ -1302,7 +1275,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) DUMP_SEEK(dataoff); - for (i = 0, vma = current->mm->mmap; + for(i = 0, vma = current->mm->mmap; i < segs && vma != NULL; vma = vma->vm_next) { unsigned long addr = vma->vm_start; @@ -1311,7 +1284,9 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) if (!maydump(vma)) continue; i++; - pr_debug("elf_core_dump: writing %08lx %lx\n", addr, len); +#ifdef DEBUG + printk("elf_core_dump: writing %08lx %lx\n", addr, len); +#endif DUMP_WRITE((void __user *)addr, len); } diff --git a/trunk/arch/mips/kernel/irq-msc01.c b/trunk/arch/mips/kernel/irq-msc01.c index 2967537221e2..bcaad6696082 100644 --- a/trunk/arch/mips/kernel/irq-msc01.c +++ b/trunk/arch/mips/kernel/irq-msc01.c @@ -112,7 +112,7 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set) } struct irq_chip msc_levelirq_type = { - .name = "SOC-it-Level", + .typename = "SOC-it-Level", .ack = level_mask_and_ack_msc_irq, .mask = mask_msc_irq, .mask_ack = level_mask_and_ack_msc_irq, @@ -122,7 +122,7 @@ struct irq_chip msc_levelirq_type = { }; struct irq_chip msc_edgeirq_type = { - .name = "SOC-it-Edge", + .typename = "SOC-it-Edge", .ack = edge_mask_and_ack_msc_irq, .mask = mask_msc_irq, .mask_ack = edge_mask_and_ack_msc_irq, diff --git a/trunk/arch/mips/kernel/irq-mv6434x.c b/trunk/arch/mips/kernel/irq-mv6434x.c index 3dd561832e4c..efbd219845b5 100644 --- a/trunk/arch/mips/kernel/irq-mv6434x.c +++ b/trunk/arch/mips/kernel/irq-mv6434x.c @@ -23,13 +23,13 @@ static unsigned int irq_base; static inline int ls1bit32(unsigned int x) { - int b = 31, s; + int b = 31, s; - s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; - s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; - s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; - s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; - s = 1; if (x << 1 == 0) s = 0; b -= s; + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; return b; } @@ -92,7 +92,7 @@ void ll_mv64340_irq(void) } struct irq_chip mv64340_irq_type = { - .name = "MV-64340", + .typename = "MV-64340", .ack = mask_mv64340_irq, .mask = mask_mv64340_irq, .mask_ack = mask_mv64340_irq, diff --git a/trunk/arch/mips/kernel/irq-rm7000.c b/trunk/arch/mips/kernel/irq-rm7000.c index 250732883488..123324ba8c14 100644 --- a/trunk/arch/mips/kernel/irq-rm7000.c +++ b/trunk/arch/mips/kernel/irq-rm7000.c @@ -17,27 +17,28 @@ #include #include +static int irq_base; + static inline void unmask_rm7k_irq(unsigned int irq) { - set_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE)); + set_c0_intcontrol(0x100 << (irq - irq_base)); } static inline void mask_rm7k_irq(unsigned int irq) { - clear_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE)); + clear_c0_intcontrol(0x100 << (irq - irq_base)); } static struct irq_chip rm7k_irq_controller = { - .name = "RM7000", + .typename = "RM7000", .ack = mask_rm7k_irq, .mask = mask_rm7k_irq, .mask_ack = mask_rm7k_irq, .unmask = unmask_rm7k_irq, }; -void __init rm7k_cpu_irq_init(void) +void __init rm7k_cpu_irq_init(int base) { - int base = RM7K_CPU_IRQ_BASE; int i; clear_c0_intcontrol(0x00000f00); /* Mask all */ @@ -45,4 +46,6 @@ void __init rm7k_cpu_irq_init(void) for (i = base; i < base + 4; i++) set_irq_chip_and_handler(i, &rm7k_irq_controller, handle_level_irq); + + irq_base = base; } diff --git a/trunk/arch/mips/kernel/irq-rm9000.c b/trunk/arch/mips/kernel/irq-rm9000.c index ae83d2df6f31..0e6f4c5349d2 100644 --- a/trunk/arch/mips/kernel/irq-rm9000.c +++ b/trunk/arch/mips/kernel/irq-rm9000.c @@ -18,14 +18,16 @@ #include #include +static int irq_base; + static inline void unmask_rm9k_irq(unsigned int irq) { - set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE)); + set_c0_intcontrol(0x1000 << (irq - irq_base)); } static inline void mask_rm9k_irq(unsigned int irq) { - clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE)); + clear_c0_intcontrol(0x1000 << (irq - irq_base)); } static inline void rm9k_cpu_irq_enable(unsigned int irq) @@ -37,6 +39,15 @@ static inline void rm9k_cpu_irq_enable(unsigned int irq) local_irq_restore(flags); } +static void rm9k_cpu_irq_disable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + mask_rm9k_irq(irq); + local_irq_restore(flags); +} + /* * Performance counter interrupts are global on all processors. */ @@ -70,7 +81,7 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq) } static struct irq_chip rm9k_irq_controller = { - .name = "RM9000", + .typename = "RM9000", .ack = mask_rm9k_irq, .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, @@ -78,7 +89,7 @@ static struct irq_chip rm9k_irq_controller = { }; static struct irq_chip rm9k_perfcounter_irq = { - .name = "RM9000", + .typename = "RM9000", .startup = rm9k_perfcounter_irq_startup, .shutdown = rm9k_perfcounter_irq_shutdown, .ack = mask_rm9k_irq, @@ -91,9 +102,8 @@ unsigned int rm9000_perfcount_irq; EXPORT_SYMBOL(rm9000_perfcount_irq); -void __init rm9k_cpu_irq_init(void) +void __init rm9k_cpu_irq_init(int base) { - int base = RM9K_CPU_IRQ_BASE; int i; clear_c0_intcontrol(0x0000f000); /* Mask all */ @@ -105,4 +115,6 @@ void __init rm9k_cpu_irq_init(void) rm9000_perfcount_irq = base + 1; set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq, handle_level_irq); + + irq_base = base; } diff --git a/trunk/arch/mips/kernel/irq_cpu.c b/trunk/arch/mips/kernel/irq_cpu.c index 7b66e03b5899..fcc86b96ccf6 100644 --- a/trunk/arch/mips/kernel/irq_cpu.c +++ b/trunk/arch/mips/kernel/irq_cpu.c @@ -25,7 +25,7 @@ * Don't even think about using this on SMP. You have been warned. * * This file exports one global function: - * void mips_cpu_irq_init(void); + * void mips_cpu_irq_init(int irq_base); */ #include #include @@ -36,20 +36,22 @@ #include #include +static int mips_cpu_irq_base; + static inline void unmask_mips_irq(unsigned int irq) { - set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + set_c0_status(0x100 << (irq - mips_cpu_irq_base)); irq_enable_hazard(); } static inline void mask_mips_irq(unsigned int irq) { - clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); irq_disable_hazard(); } static struct irq_chip mips_cpu_irq_controller = { - .name = "MIPS", + .typename = "MIPS", .ack = mask_mips_irq, .mask = mask_mips_irq, .mask_ack = mask_mips_irq, @@ -68,7 +70,7 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) { unsigned int vpflags = dvpe(); - clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); evpe(vpflags); unmask_mips_mt_irq(irq); @@ -82,13 +84,13 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq) static void mips_mt_cpu_irq_ack(unsigned int irq) { unsigned int vpflags = dvpe(); - clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE)); + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); evpe(vpflags); mask_mips_mt_irq(irq); } static struct irq_chip mips_mt_cpu_irq_controller = { - .name = "MIPS", + .typename = "MIPS", .startup = mips_mt_cpu_irq_startup, .ack = mips_mt_cpu_irq_ack, .mask = mask_mips_mt_irq, @@ -97,9 +99,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = { .eoi = unmask_mips_mt_irq, }; -void __init mips_cpu_irq_init(void) +void __init mips_cpu_irq_init(int irq_base) { - int irq_base = MIPS_CPU_IRQ_BASE; int i; /* Mask interrupts. */ @@ -117,4 +118,6 @@ void __init mips_cpu_irq_init(void) for (i = irq_base + 2; i < irq_base + 8; i++) set_irq_chip_and_handler(i, &mips_cpu_irq_controller, handle_level_irq); + + mips_cpu_irq_base = irq_base; } diff --git a/trunk/arch/mips/kernel/linux32.c b/trunk/arch/mips/kernel/linux32.c index 0b8ce59429a8..de3fae260ff8 100644 --- a/trunk/arch/mips/kernel/linux32.c +++ b/trunk/arch/mips/kernel/linux32.c @@ -194,15 +194,15 @@ sysn32_waitid(int which, compat_pid_t pid, } struct sysinfo32 { - s32 uptime; - u32 loads[3]; - u32 totalram; - u32 freeram; - u32 sharedram; - u32 bufferram; - u32 totalswap; - u32 freeswap; - u16 procs; + s32 uptime; + u32 loads[3]; + u32 totalram; + u32 freeram; + u32 sharedram; + u32 bufferram; + u32 totalswap; + u32 freeswap; + u16 procs; u32 totalhigh; u32 freehigh; u32 mem_unit; @@ -558,7 +558,7 @@ extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf); asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) { int err; - struct ustat tmp; + struct ustat tmp; struct ustat32 tmp32; mm_segment_t old_fs = get_fs(); @@ -569,11 +569,11 @@ asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32) if (err) goto out; - memset(&tmp32,0,sizeof(struct ustat32)); - tmp32.f_tfree = tmp.f_tfree; - tmp32.f_tinode = tmp.f_tinode; + memset(&tmp32,0,sizeof(struct ustat32)); + tmp32.f_tfree = tmp.f_tfree; + tmp32.f_tinode = tmp.f_tinode; - err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0; + err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0; out: return err; diff --git a/trunk/arch/mips/kernel/mips-mt.c b/trunk/arch/mips/kernel/mips-mt.c index a32f6797353a..c1373a6e668b 100644 --- a/trunk/arch/mips/kernel/mips-mt.c +++ b/trunk/arch/mips/kernel/mips-mt.c @@ -96,10 +96,6 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, goto out_unlock; } - retval = security_task_setscheduler(p, 0, NULL); - if (retval) - goto out_unlock; - /* Record new user-specified CPU set for future reference */ p->thread.user_cpus_allowed = new_mask; @@ -145,9 +141,8 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, p = find_process_by_pid(pid); if (!p) goto out_unlock; - retval = security_task_getscheduler(p); - if (retval) - goto out_unlock; + + retval = 0; cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map); diff --git a/trunk/arch/mips/kernel/proc.c b/trunk/arch/mips/kernel/proc.c index 5ddc2e9deecf..4ed37ba19731 100644 --- a/trunk/arch/mips/kernel/proc.c +++ b/trunk/arch/mips/kernel/proc.c @@ -31,13 +31,13 @@ static const char *cpu_name[] = { [CPU_R4000PC] = "R4000PC", [CPU_R4000SC] = "R4000SC", [CPU_R4000MC] = "R4000MC", - [CPU_R4200] = "R4200", + [CPU_R4200] = "R4200", [CPU_R4400PC] = "R4400PC", [CPU_R4400SC] = "R4400SC", [CPU_R4400MC] = "R4400MC", [CPU_R4600] = "R4600", [CPU_R6000] = "R6000", - [CPU_R6000A] = "R6000A", + [CPU_R6000A] = "R6000A", [CPU_R8000] = "R8000", [CPU_R10000] = "R10000", [CPU_R12000] = "R12000", @@ -46,14 +46,14 @@ static const char *cpu_name[] = { [CPU_R4650] = "R4650", [CPU_R4700] = "R4700", [CPU_R5000] = "R5000", - [CPU_R5000A] = "R5000A", + [CPU_R5000A] = "R5000A", [CPU_R4640] = "R4640", [CPU_NEVADA] = "Nevada", [CPU_RM7000] = "RM7000", [CPU_RM9000] = "RM9000", [CPU_R5432] = "R5432", [CPU_4KC] = "MIPS 4Kc", - [CPU_5KC] = "MIPS 5Kc", + [CPU_5KC] = "MIPS 5Kc", [CPU_R4310] = "R4310", [CPU_SB1] = "SiByte SB1", [CPU_SB1A] = "SiByte SB1A", diff --git a/trunk/arch/mips/kernel/process.c b/trunk/arch/mips/kernel/process.c index 04e5b38d327d..ec8209f3a0c6 100644 --- a/trunk/arch/mips/kernel/process.c +++ b/trunk/arch/mips/kernel/process.c @@ -41,6 +41,10 @@ #include #include #include +#ifdef CONFIG_MIPS_MT_SMTC +#include +extern void smtc_idle_loop_hook(void); +#endif /* CONFIG_MIPS_MT_SMTC */ /* * The idle thread. There's no useful work to be done, so just try to conserve @@ -53,8 +57,6 @@ ATTRIB_NORET void cpu_idle(void) while (1) { while (!need_resched()) { #ifdef CONFIG_MIPS_MT_SMTC - extern void smtc_idle_loop_hook(void); - smtc_idle_loop_hook(); #endif /* CONFIG_MIPS_MT_SMTC */ if (cpu_wait) diff --git a/trunk/arch/mips/kernel/r4k_fpu.S b/trunk/arch/mips/kernel/r4k_fpu.S index 59c1577ecbb3..880fa6e841ee 100644 --- a/trunk/arch/mips/kernel/r4k_fpu.S +++ b/trunk/arch/mips/kernel/r4k_fpu.S @@ -114,14 +114,6 @@ LEAF(_save_fp_context32) */ LEAF(_restore_fp_context) EX lw t0, SC_FPC_CSR(a0) - - /* Fail if the CSR has exceptions pending */ - srl t1, t0, 5 - and t1, t0 - andi t1, 0x1f << 7 - bnez t1, fault - nop - #ifdef CONFIG_64BIT EX ldc1 $f1, SC_FPREGS+8(a0) EX ldc1 $f3, SC_FPREGS+24(a0) @@ -165,14 +157,6 @@ LEAF(_restore_fp_context) LEAF(_restore_fp_context32) /* Restore an o32 sigcontext. */ EX lw t0, SC32_FPC_CSR(a0) - - /* Fail if the CSR has exceptions pending */ - srl t1, t0, 5 - and t1, t0 - andi t1, 0x1f << 7 - bnez t1, fault - nop - EX ldc1 $f0, SC32_FPREGS+0(a0) EX ldc1 $f2, SC32_FPREGS+16(a0) EX ldc1 $f4, SC32_FPREGS+32(a0) @@ -193,9 +177,8 @@ LEAF(_restore_fp_context32) jr ra li v0, 0 # success END(_restore_fp_context32) -#endif - .set reorder +#endif .type fault@function .ent fault diff --git a/trunk/arch/mips/kernel/rtlx.c b/trunk/arch/mips/kernel/rtlx.c index 8610f4a925e9..5a99e3e0c96d 100644 --- a/trunk/arch/mips/kernel/rtlx.c +++ b/trunk/arch/mips/kernel/rtlx.c @@ -63,7 +63,7 @@ extern void *vpe_get_shared(int index); static void rtlx_dispatch(void) { - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ); + do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ); } @@ -491,7 +491,7 @@ static struct irqaction rtlx_irq = { .name = "RTLX", }; -static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ; +static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ; static char register_chrdev_failed[] __initdata = KERN_ERR "rtlx_module_init: unable to register device\n"; diff --git a/trunk/arch/mips/kernel/scall64-n32.S b/trunk/arch/mips/kernel/scall64-n32.S index 39add2341aa2..a7bff2a54723 100644 --- a/trunk/arch/mips/kernel/scall64-n32.S +++ b/trunk/arch/mips/kernel/scall64-n32.S @@ -384,7 +384,7 @@ EXPORT(sysn32_call_table) PTR sys_readlinkat PTR sys_fchmodat PTR sys_faccessat - PTR compat_sys_pselect6 + PTR sys_pselect6 PTR sys_ppoll /* 6265 */ PTR sys_unshare PTR sys_splice diff --git a/trunk/arch/mips/kernel/scall64-o32.S b/trunk/arch/mips/kernel/scall64-o32.S index c58b8e0105ea..e91379c1be1d 100644 --- a/trunk/arch/mips/kernel/scall64-o32.S +++ b/trunk/arch/mips/kernel/scall64-o32.S @@ -506,7 +506,7 @@ sys_call_table: PTR sys_readlinkat PTR sys_fchmodat PTR sys_faccessat /* 4300 */ - PTR compat_sys_pselect6 + PTR sys_pselect6 PTR sys_ppoll PTR sys_unshare PTR sys_splice diff --git a/trunk/arch/mips/kernel/setup.c b/trunk/arch/mips/kernel/setup.c index d2e01e7167b8..89440a0d8528 100644 --- a/trunk/arch/mips/kernel/setup.c +++ b/trunk/arch/mips/kernel/setup.c @@ -271,7 +271,8 @@ static void __init bootmem_init(void) static void __init bootmem_init(void) { unsigned long reserved_end; - unsigned long mapstart = ~0UL; + unsigned long highest = 0; + unsigned long mapstart = -1UL; unsigned long bootmap_size; int i; @@ -282,13 +283,6 @@ static void __init bootmem_init(void) */ reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end))); - /* - * max_low_pfn is not a number of pages. The number of pages - * of the system is given by 'max_low_pfn - min_low_pfn'. - */ - min_low_pfn = ~0UL; - max_low_pfn = 0; - /* * Find the highest page frame number we have available. */ @@ -302,10 +296,8 @@ static void __init bootmem_init(void) end = PFN_DOWN(boot_mem_map.map[i].addr + boot_mem_map.map[i].size); - if (end > max_low_pfn) - max_low_pfn = end; - if (start < min_low_pfn) - min_low_pfn = start; + if (end > highest) + highest = end; if (end <= reserved_end) continue; if (start >= mapstart) @@ -313,36 +305,22 @@ static void __init bootmem_init(void) mapstart = max(reserved_end, start); } - if (min_low_pfn >= max_low_pfn) - panic("Incorrect memory mapping !!!"); - if (min_low_pfn > ARCH_PFN_OFFSET) { - printk(KERN_INFO - "Wasting %lu bytes for tracking %lu unused pages\n", - (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), - min_low_pfn - ARCH_PFN_OFFSET); - } else if (min_low_pfn < ARCH_PFN_OFFSET) { - printk(KERN_INFO - "%lu free pages won't be used\n", - ARCH_PFN_OFFSET - min_low_pfn); - } - min_low_pfn = ARCH_PFN_OFFSET; - /* * Determine low and high memory ranges */ - if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) { + if (highest > PFN_DOWN(HIGHMEM_START)) { #ifdef CONFIG_HIGHMEM highstart_pfn = PFN_DOWN(HIGHMEM_START); - highend_pfn = max_low_pfn; + highend_pfn = highest; #endif - max_low_pfn = PFN_DOWN(HIGHMEM_START); + highest = PFN_DOWN(HIGHMEM_START); } /* * Initialize the boot-time allocator with low memory only. */ - bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, - min_low_pfn, max_low_pfn); + bootmap_size = init_bootmem(mapstart, highest); + /* * Register fully available low RAM pages with the bootmem allocator. */ @@ -529,9 +507,9 @@ void __init setup_arch(char **cmdline_p) #if defined(CONFIG_VT) #if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; + conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; + conswitchp = &dummy_con; #endif #endif @@ -563,6 +541,3 @@ int __init dsp_disable(char *s) } __setup("nodsp", dsp_disable); - -unsigned long kernelsp[NR_CPUS]; -unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; diff --git a/trunk/arch/mips/kernel/signal.c b/trunk/arch/mips/kernel/signal.c index 9a44053cd9f1..b9d358e05214 100644 --- a/trunk/arch/mips/kernel/signal.c +++ b/trunk/arch/mips/kernel/signal.c @@ -89,7 +89,7 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) spin_lock_irq(¤t->sighand->siglock); current->saved_sigmask = current->blocked; current->blocked = newset; - recalc_sigpending(); + recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); current->state = TASK_INTERRUPTIBLE; @@ -124,7 +124,7 @@ asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) - return -EFAULT; + return -EFAULT; err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); @@ -304,7 +304,7 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, frame->regs[31]); #endif - return 0; + return 0; give_sigsegv: force_sigsegv(signr, current); diff --git a/trunk/arch/mips/kernel/signal_n32.c b/trunk/arch/mips/kernel/signal_n32.c index b28646b3ceae..a67c18555ed3 100644 --- a/trunk/arch/mips/kernel/signal_n32.c +++ b/trunk/arch/mips/kernel/signal_n32.c @@ -105,7 +105,7 @@ _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) spin_lock_irq(¤t->sighand->siglock); current->saved_sigmask = current->blocked; current->blocked = newset; - recalc_sigpending(); + recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); current->state = TASK_INTERRUPTIBLE; @@ -184,7 +184,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka, /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_link); - sp = (int) (long) current->sas_ss_sp; + sp = (int) (long) current->sas_ss_sp; err |= __put_user(sp, &frame->rs_uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[29]), diff --git a/trunk/arch/mips/kernel/smp-mt.c b/trunk/arch/mips/kernel/smp-mt.c index 64b62bdfb4f6..1ee689c0e0c9 100644 --- a/trunk/arch/mips/kernel/smp-mt.c +++ b/trunk/arch/mips/kernel/smp-mt.c @@ -35,6 +35,7 @@ #include #include #include +#include /* This is f*cking wrong */ #define MIPS_CPU_IPI_RESCHED_IRQ 0 #define MIPS_CPU_IPI_CALL_IRQ 1 @@ -107,12 +108,12 @@ void __init sanitize_tlb_entries(void) static void ipi_resched_dispatch(void) { - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); + do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ); } static void ipi_call_dispatch(void) { - do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); + do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ); } static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) @@ -269,8 +270,8 @@ void __init plat_prepare_cpus(unsigned int max_cpus) set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); } - cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; - cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; + cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; + cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; setup_irq(cpu_ipi_resched_irq, &irq_resched); setup_irq(cpu_ipi_call_irq, &irq_call); diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index 9251ea824937..6a857bf030b0 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/arch/mips/kernel/smtc.c @@ -26,6 +26,16 @@ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */ +/* + * MIPSCPU_INT_BASE is identically defined in both + * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h, + * but as yet there's no properly organized include structure that + * will ensure that the right *int.h file will be included for a + * given platform build. + */ + +#define MIPSCPU_INT_BASE 16 + #define MIPS_CPU_IPI_IRQ 1 #define LOCK_MT_PRA() \ @@ -67,15 +77,15 @@ unsigned int ipi_timer_latch[NR_CPUS]; #define IPIBUF_PER_CPU 4 -static struct smtc_ipi_q IPIQ[NR_CPUS]; -static struct smtc_ipi_q freeIPIq; +struct smtc_ipi_q IPIQ[NR_CPUS]; +struct smtc_ipi_q freeIPIq; /* Forward declarations */ void ipi_decode(struct smtc_ipi *); -static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); -static void setup_cross_vpe_interrupts(void); +void post_direct_ipi(int cpu, struct smtc_ipi *pipi); +void setup_cross_vpe_interrupts(void); void init_smtc_stats(void); /* Global SMTC Status */ @@ -190,7 +200,7 @@ void __init sanitize_tlb_entries(void) * Configure shared TLB - VPC configuration bit must be set by caller */ -static void smtc_configure_tlb(void) +void smtc_configure_tlb(void) { int i,tlbsiz,vpes; unsigned long mvpconf0; @@ -638,7 +648,7 @@ int setup_irq_smtc(unsigned int irq, struct irqaction * new, * the VPE. */ -static void smtc_ipi_qdump(void) +void smtc_ipi_qdump(void) { int i; @@ -676,6 +686,28 @@ static __inline__ int atomic_postincrement(unsigned int *pv) return result; } +/* No longer used in IPI dispatch, but retained for future recycling */ + +static __inline__ int atomic_postclear(unsigned int *pv) +{ + unsigned long result; + + unsigned long temp; + + __asm__ __volatile__( + "1: ll %0, %2 \n" + " or %1, $0, $0 \n" + " sc %1, %2 \n" + " beqz %1, 1b \n" + " sync \n" + : "=&r" (result), "=&r" (temp), "=m" (*pv) + : "m" (*pv) + : "memory"); + + return result; +} + + void smtc_send_ipi(int cpu, int type, unsigned int action) { int tcstatus; @@ -749,7 +781,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) /* * Send IPI message to Halted TC, TargTC/TargVPE already having been set */ -static void post_direct_ipi(int cpu, struct smtc_ipi *pipi) +void post_direct_ipi(int cpu, struct smtc_ipi *pipi) { struct pt_regs *kstack; unsigned long tcstatus; @@ -889,7 +921,7 @@ void smtc_timer_broadcast(int vpe) * interrupts. */ -static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ; +static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ; static irqreturn_t ipi_interrupt(int irq, void *dev_idm) { @@ -968,7 +1000,7 @@ static void ipi_irq_dispatch(void) static struct irqaction irq_ipi; -static void setup_cross_vpe_interrupts(void) +void setup_cross_vpe_interrupts(void) { if (!cpu_has_vint) panic("SMTC Kernel requires Vectored Interupt support"); @@ -1159,7 +1191,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) * It would be nice to be able to use a spinlock here, * but this is invoked from within TLB flush routines * that protect themselves with DVPE, so if a lock is - * held by another TC, it'll never be freed. + * held by another TC, it'll never be freed. * * DVPE/DMT must not be done with interrupts enabled, * so even so most callers will already have disabled @@ -1264,7 +1296,7 @@ void smtc_flush_tlb_asid(unsigned long asid) * Support for single-threading cache flush operations. */ -static int halt_state_save[NR_CPUS]; +int halt_state_save[NR_CPUS]; /* * To really, really be sure that nothing is being done diff --git a/trunk/arch/mips/kernel/sysirix.c b/trunk/arch/mips/kernel/sysirix.c index 93a148486f88..6c2406a93f2b 100644 --- a/trunk/arch/mips/kernel/sysirix.c +++ b/trunk/arch/mips/kernel/sysirix.c @@ -669,7 +669,7 @@ asmlinkage int irix_mount(char __user *dev_name, char __user *dir_name, struct irix_statfs { short f_type; - long f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree; + long f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree; char f_fname[6], f_fpack[6]; }; @@ -959,7 +959,7 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin) fn = default_llseek; if (file->f_op && file->f_op->llseek) - fn = file->f_op->llseek; + fn = file->f_op->llseek; lock_kernel(); retval = fn(file, offset, origin); unlock_kernel(); diff --git a/trunk/arch/mips/kernel/vpe.c b/trunk/arch/mips/kernel/vpe.c index 459624969c99..458fccf87c54 100644 --- a/trunk/arch/mips/kernel/vpe.c +++ b/trunk/arch/mips/kernel/vpe.c @@ -522,7 +522,7 @@ static int (*reloc_handlers[]) (struct module *me, uint32_t *location, }; static char *rstrs[] = { - [R_MIPS_NONE] = "MIPS_NONE", + [R_MIPS_NONE] = "MIPS_NONE", [R_MIPS_32] = "MIPS_32", [R_MIPS_26] = "MIPS_26", [R_MIPS_HI16] = "MIPS_HI16", @@ -695,7 +695,7 @@ static void dump_tclist(void) } /* We are prepared so configure and start the VPE... */ -static int vpe_run(struct vpe * v) +int vpe_run(struct vpe * v) { struct vpe_notifications *n; unsigned long val, dmt_flag; @@ -713,16 +713,16 @@ static int vpe_run(struct vpe * v) dvpe(); if (!list_empty(&v->tc)) { - if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) { - printk(KERN_WARNING "VPE loader: TC %d is already in use.\n", - t->index); - return -ENOEXEC; - } - } else { - printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n", - v->minor); - return -ENOEXEC; - } + if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) { + printk(KERN_WARNING "VPE loader: TC %d is already in use.\n", + t->index); + return -ENOEXEC; + } + } else { + printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n", + v->minor); + return -ENOEXEC; + } /* Put MVPE's into 'configuration state' */ set_c0_mvpcontrol(MVPCONTROL_VPC); @@ -775,14 +775,14 @@ static int vpe_run(struct vpe * v) back_to_back_c0_hazard(); - /* Set up the XTC bit in vpeconf0 to point at our tc */ - write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) - | (t->index << VPECONF0_XTC_SHIFT)); + /* Set up the XTC bit in vpeconf0 to point at our tc */ + write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) + | (t->index << VPECONF0_XTC_SHIFT)); back_to_back_c0_hazard(); - /* enable this VPE */ - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); + /* enable this VPE */ + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); /* clear out any left overs from a previous program */ write_vpe_c0_status(0); @@ -832,7 +832,7 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, * contents of the program (p)buffer performing relocatations/etc, free's it * when finished. */ -static int vpe_elfload(struct vpe * v) +int vpe_elfload(struct vpe * v) { Elf_Ehdr *hdr; Elf_Shdr *sechdrs; diff --git a/trunk/arch/mips/lasat/interrupt.c b/trunk/arch/mips/lasat/interrupt.c index 9a622b9a1051..2affa5ff171c 100644 --- a/trunk/arch/mips/lasat/interrupt.c +++ b/trunk/arch/mips/lasat/interrupt.c @@ -45,7 +45,7 @@ void enable_lasat_irq(unsigned int irq_nr) } static struct irq_chip lasat_irq_type = { - .name = "Lasat", + .typename = "Lasat", .ack = disable_lasat_irq, .mask = disable_lasat_irq, .mask_ack = disable_lasat_irq, diff --git a/trunk/arch/mips/lasat/prom.c b/trunk/arch/mips/lasat/prom.c index d47692f73a26..88c7ab871ec4 100644 --- a/trunk/arch/mips/lasat/prom.c +++ b/trunk/arch/mips/lasat/prom.c @@ -132,8 +132,9 @@ void __init prom_init(void) add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } const char *get_system_type(void) diff --git a/trunk/arch/mips/lib-32/Makefile b/trunk/arch/mips/lib-32/Makefile index 2036cf5e6857..dcd4d2ed2ac4 100644 --- a/trunk/arch/mips/lib-32/Makefile +++ b/trunk/arch/mips/lib-32/Makefile @@ -2,7 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += watch.o +lib-y += memset.o watch.o obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o diff --git a/trunk/arch/mips/lib/memset.S b/trunk/arch/mips/lib-32/memset.S similarity index 85% rename from trunk/arch/mips/lib/memset.S rename to trunk/arch/mips/lib-32/memset.S index 3f8b8b3d0b23..1981485bd48b 100644 --- a/trunk/arch/mips/lib/memset.S +++ b/trunk/arch/mips/lib-32/memset.S @@ -10,14 +10,6 @@ #include #include -#if LONGSIZE == 4 -#define LONG_S_L swl -#define LONG_S_R swr -#else -#define LONG_S_L sdl -#define LONG_S_R sdr -#endif - #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ .section __ex_table,"a"; \ @@ -33,7 +25,6 @@ EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup) -#if LONGSIZE == 4 EX(LONG_S, \val, (\offset + 8 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 9 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup) @@ -42,7 +33,6 @@ EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup) EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup) -#endif .endm /* @@ -59,13 +49,9 @@ LEAF(memset) move v0, a0 /* result */ andi a1, 0xff /* spread fillword */ - LONG_SLL t1, a1, 8 + sll t1, a1, 8 or a1, t1 - LONG_SLL t1, a1, 16 -#if LONGSIZE == 8 - or a1, t1 - LONG_SLL t1, a1, 32 -#endif + sll t1, a1, 16 or a1, t1 1: @@ -78,10 +64,10 @@ FEXPORT(__bzero) PTR_SUBU t0, LONGSIZE /* alignment in bytes */ #ifdef __MIPSEB__ - EX(LONG_S_L, a1, (a0), first_fixup) /* make word/dword aligned */ + EX(swl, a1, (a0), first_fixup) /* make word aligned */ #endif #ifdef __MIPSEL__ - EX(LONG_S_R, a1, (a0), first_fixup) /* make word/dword aligned */ + EX(swr, a1, (a0), first_fixup) /* make word aligned */ #endif PTR_SUBU a0, t0 /* long align ptr */ PTR_ADDU a2, t0 /* correct size */ @@ -89,7 +75,7 @@ FEXPORT(__bzero) 1: ori t1, a2, 0x3f /* # of full blocks */ xori t1, 0x3f beqz t1, memset_partial /* no block to fill */ - andi t0, a2, 0x40-LONGSIZE + andi t0, a2, 0x3c PTR_ADDU t1, a0 /* end address */ .set reorder @@ -100,14 +86,7 @@ FEXPORT(__bzero) memset_partial: PTR_LA t1, 2f /* where to start */ -#if LONGSIZE == 4 PTR_SUBU t1, t0 -#else - .set noat - LONG_SRL AT, t0, 1 - PTR_SUBU t1, AT - .set noat -#endif jr t1 PTR_ADDU a0, t0 /* dest ptr */ @@ -121,10 +100,10 @@ memset_partial: beqz a2, 1f PTR_ADDU a0, a2 /* What's left */ #ifdef __MIPSEB__ - EX(LONG_S_R, a1, -1(a0), last_fixup) + EX(swr, a1, -1(a0), last_fixup) #endif #ifdef __MIPSEL__ - EX(LONG_S_L, a1, -1(a0), last_fixup) + EX(swl, a1, -1(a0), last_fixup) #endif 1: jr ra move a2, zero diff --git a/trunk/arch/mips/lib-64/Makefile b/trunk/arch/mips/lib-64/Makefile index 2036cf5e6857..dcd4d2ed2ac4 100644 --- a/trunk/arch/mips/lib-64/Makefile +++ b/trunk/arch/mips/lib-64/Makefile @@ -2,7 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += watch.o +lib-y += memset.o watch.o obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o diff --git a/trunk/arch/mips/lib-64/memset.S b/trunk/arch/mips/lib-64/memset.S new file mode 100644 index 000000000000..e2c42c85113b --- /dev/null +++ b/trunk/arch/mips/lib-64/memset.S @@ -0,0 +1,142 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + + .macro f_fill64 dst, offset, val, fixup + EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup) + .endm + +/* + * memset(void *s, int c, size_t n) + * + * a0: start of area to clear + * a1: char to fill with + * a2: size of area to clear + */ + .set noreorder + .align 5 +LEAF(memset) + beqz a1, 1f + move v0, a0 /* result */ + + andi a1, 0xff /* spread fillword */ + dsll t1, a1, 8 + or a1, t1 + dsll t1, a1, 16 + or a1, t1 + dsll t1, a1, 32 + or a1, t1 +1: + +FEXPORT(__bzero) + sltiu t0, a2, LONGSIZE /* very small region? */ + bnez t0, small_memset + andi t0, a0, LONGMASK /* aligned? */ + + beqz t0, 1f + PTR_SUBU t0, LONGSIZE /* alignment in bytes */ + +#ifdef __MIPSEB__ + EX(sdl, a1, (a0), first_fixup) /* make dword aligned */ +#endif +#ifdef __MIPSEL__ + EX(sdr, a1, (a0), first_fixup) /* make dword aligned */ +#endif + PTR_SUBU a0, t0 /* long align ptr */ + PTR_ADDU a2, t0 /* correct size */ + +1: ori t1, a2, 0x3f /* # of full blocks */ + xori t1, 0x3f + beqz t1, memset_partial /* no block to fill */ + andi t0, a2, 0x38 + + PTR_ADDU t1, a0 /* end address */ + .set reorder +1: PTR_ADDIU a0, 64 + f_fill64 a0, -64, a1, fwd_fixup + bne t1, a0, 1b + .set noreorder + +memset_partial: + PTR_LA t1, 2f /* where to start */ + .set noat + dsrl AT, t0, 1 + PTR_SUBU t1, AT + .set noat + jr t1 + PTR_ADDU a0, t0 /* dest ptr */ + + .set push + .set noreorder + .set nomacro + f_fill64 a0, -64, a1, partial_fixup /* ... but first do longs ... */ +2: .set pop + andi a2, LONGMASK /* At most one long to go */ + + beqz a2, 1f + PTR_ADDU a0, a2 /* What's left */ +#ifdef __MIPSEB__ + EX(sdr, a1, -1(a0), last_fixup) +#endif +#ifdef __MIPSEL__ + EX(sdl, a1, -1(a0), last_fixup) +#endif +1: jr ra + move a2, zero + +small_memset: + beqz a2, 2f + PTR_ADDU t1, a0, a2 + +1: PTR_ADDIU a0, 1 /* fill bytewise */ + bne t1, a0, 1b + sb a1, -1(a0) + +2: jr ra /* done */ + move a2, zero + END(memset) + +first_fixup: + jr ra + nop + +fwd_fixup: + PTR_L t0, TI_TASK($28) + LONG_L t0, THREAD_BUADDR(t0) + andi a2, 0x3f + LONG_ADDU a2, t1 + jr ra + LONG_SUBU a2, t0 + +partial_fixup: + PTR_L t0, TI_TASK($28) + LONG_L t0, THREAD_BUADDR(t0) + andi a2, LONGMASK + LONG_ADDU a2, t1 + jr ra + LONG_SUBU a2, t0 + +last_fixup: + jr ra + andi v1, a2, LONGMASK diff --git a/trunk/arch/mips/lib/Makefile b/trunk/arch/mips/lib/Makefile index 5ad501b30b43..989c900b8b14 100644 --- a/trunk/arch/mips/lib/Makefile +++ b/trunk/arch/mips/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial.o memcpy.o memset.o promlib.o \ +lib-y += csum_partial.o memcpy.o promlib.o \ strlen_user.o strncpy_user.o strnlen_user.o uncached.o obj-y += iomap.o diff --git a/trunk/arch/mips/lib/uncached.c b/trunk/arch/mips/lib/uncached.c index 2388f7f3ffde..98ce89f8068b 100644 --- a/trunk/arch/mips/lib/uncached.c +++ b/trunk/arch/mips/lib/uncached.c @@ -44,24 +44,20 @@ unsigned long __init run_uncached(void *func) if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) usp = CKSEG1ADDR(sp); -#ifdef CONFIG_64BIT else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0)) usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)sp)); -#endif else { BUG(); usp = sp; } if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) ufunc = CKSEG1ADDR(lfunc); -#ifdef CONFIG_64BIT else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) && (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0)) ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, XKPHYS_TO_PHYS((long long)lfunc)); -#endif else { BUG(); ufunc = lfunc; diff --git a/trunk/arch/mips/mips-boards/atlas/atlas_int.c b/trunk/arch/mips/mips-boards/atlas/atlas_int.c index dfa0acbd7fc2..43dba6ce6603 100644 --- a/trunk/arch/mips/mips-boards/atlas/atlas_int.c +++ b/trunk/arch/mips/mips-boards/atlas/atlas_int.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -70,7 +69,7 @@ static void end_atlas_irq(unsigned int irq) } static struct irq_chip atlas_irq_type = { - .name = "Atlas", + .typename = "Atlas", .ack = disable_atlas_irq, .mask = disable_atlas_irq, .mask_ack = disable_atlas_irq, @@ -221,7 +220,7 @@ msc_irqmap_t __initdata msc_irqmap[] = { {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, }; -int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); +int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap); msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, @@ -232,14 +231,14 @@ msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} }; -int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); +int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap); void __init arch_init_irq(void) { init_atlas_irqs(ATLAS_INT_BASE); if (!cpu_has_veic) - mips_cpu_irq_init(); + mips_cpu_irq_init(MIPSCPU_INT_BASE); switch(mips_revision_corid) { case MIPS_REVISION_CORID_CORE_MSC: diff --git a/trunk/arch/mips/mips-boards/generic/memory.c b/trunk/arch/mips/mips-boards/generic/memory.c index ebf0e16c5a0d..eeed944e0f83 100644 --- a/trunk/arch/mips/mips-boards/generic/memory.c +++ b/trunk/arch/mips/mips-boards/generic/memory.c @@ -166,8 +166,9 @@ void __init prom_meminit(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + unsigned long freed = 0; unsigned long addr; int i; @@ -175,8 +176,17 @@ void __init prom_free_prom_memory(void) if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; - addr = boot_mem_map.map[i].addr; - free_init_pages("prom memory", - addr, addr + boot_mem_map.map[i].size); + addr = PAGE_ALIGN(boot_mem_map.map[i].addr); + while (addr < boot_mem_map.map[i].addr + + boot_mem_map.map[i].size) { + ClearPageReserved(virt_to_page(__va(addr))); + init_page_count(virt_to_page(__va(addr))); + free_page((unsigned long)__va(addr)); + addr += PAGE_SIZE; + freed += PAGE_SIZE; + } } + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); + + return freed; } diff --git a/trunk/arch/mips/mips-boards/malta/malta_int.c b/trunk/arch/mips/mips-boards/malta/malta_int.c index 3c206bb17160..90ad5bf3e2f1 100644 --- a/trunk/arch/mips/mips-boards/malta/malta_int.c +++ b/trunk/arch/mips/mips-boards/malta/malta_int.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -290,7 +289,7 @@ msc_irqmap_t __initdata msc_irqmap[] = { {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, }; -int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); +int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t); msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, @@ -304,14 +303,14 @@ msc_irqmap_t __initdata msc_eicirqmap[] = { {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} }; -int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); +int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t); void __init arch_init_irq(void) { init_i8259_irqs(); if (!cpu_has_veic) - mips_cpu_irq_init(); + mips_cpu_irq_init (MIPSCPU_INT_BASE); switch(mips_revision_corid) { case MIPS_REVISION_CORID_CORE_MSC: diff --git a/trunk/arch/mips/mips-boards/sead/sead_int.c b/trunk/arch/mips/mips-boards/sead/sead_int.c index c4b9de3a7f27..874ccb0066b8 100644 --- a/trunk/arch/mips/mips-boards/sead/sead_int.c +++ b/trunk/arch/mips/mips-boards/sead/sead_int.c @@ -113,5 +113,5 @@ asmlinkage void plat_irq_dispatch(void) void __init arch_init_irq(void) { - mips_cpu_irq_init(); + mips_cpu_irq_init(MIPSCPU_INT_BASE); } diff --git a/trunk/arch/mips/mips-boards/sim/sim_int.c b/trunk/arch/mips/mips-boards/sim/sim_int.c index 15ac0655c1ff..2ce449dce6f2 100644 --- a/trunk/arch/mips/mips-boards/sim/sim_int.c +++ b/trunk/arch/mips/mips-boards/sim/sim_int.c @@ -21,7 +21,9 @@ #include #include #include -#include + + +extern void mips_cpu_irq_init(int); static inline int clz(unsigned long x) { @@ -84,5 +86,5 @@ asmlinkage void plat_irq_dispatch(void) void __init arch_init_irq(void) { - mips_cpu_irq_init(); + mips_cpu_irq_init(MIPSCPU_INT_BASE); } diff --git a/trunk/arch/mips/mips-boards/sim/sim_mem.c b/trunk/arch/mips/mips-boards/sim/sim_mem.c index 46bc16f8b15d..f7ce76983328 100644 --- a/trunk/arch/mips/mips-boards/sim/sim_mem.c +++ b/trunk/arch/mips/mips-boards/sim/sim_mem.c @@ -99,9 +99,10 @@ void __init prom_meminit(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { int i; + unsigned long freed = 0; unsigned long addr; for (i = 0; i < boot_mem_map.nr_map; i++) { @@ -109,7 +110,16 @@ void __init prom_free_prom_memory(void) continue; addr = boot_mem_map.map[i].addr; - free_init_pages("prom memory", - addr, addr + boot_mem_map.map[i].size); + while (addr < boot_mem_map.map[i].addr + + boot_mem_map.map[i].size) { + ClearPageReserved(virt_to_page(__va(addr))); + init_page_count(virt_to_page(__va(addr))); + free_page((unsigned long)__va(addr)); + addr += PAGE_SIZE; + freed += PAGE_SIZE; + } } + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); + + return freed; } diff --git a/trunk/arch/mips/mm/init.c b/trunk/arch/mips/mm/init.c index 125a4a85ec05..49065c133ebf 100644 --- a/trunk/arch/mips/mm/init.c +++ b/trunk/arch/mips/mm/init.c @@ -341,6 +341,7 @@ static int __init page_is_ram(unsigned long pagenr) void __init paging_init(void) { unsigned long zones_size[MAX_NR_ZONES] = { 0, }; + unsigned long max_dma, low; #ifndef CONFIG_FLATMEM unsigned long zholes_size[MAX_NR_ZONES] = { 0, }; unsigned long i, j, pfn; @@ -353,19 +354,19 @@ void __init paging_init(void) #endif kmap_coherent_init(); + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + low = max_low_pfn; + #ifdef CONFIG_ISA - if (max_low_pfn >= MAX_DMA_PFN) - if (min_low_pfn >= MAX_DMA_PFN) { - zones_size[ZONE_DMA] = 0; - zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; - } else { - zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn; - zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN; - } - else + if (low < max_dma) + zones_size[ZONE_DMA] = low; + else { + zones_size[ZONE_DMA] = max_dma; + zones_size[ZONE_NORMAL] = low - max_dma; + } +#else + zones_size[ZONE_DMA] = low; #endif - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; - #ifdef CONFIG_HIGHMEM zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn; @@ -466,7 +467,7 @@ void __init mem_init(void) } #endif /* !CONFIG_NEED_MULTIPLE_NODES */ -void free_init_pages(const char *what, unsigned long begin, unsigned long end) +static void free_init_pages(char *what, unsigned long begin, unsigned long end) { unsigned long pfn; @@ -492,25 +493,18 @@ void free_initrd_mem(unsigned long start, unsigned long end) } #endif +extern unsigned long prom_free_prom_memory(void); + void free_initmem(void) { - prom_free_prom_memory(); + unsigned long freed; + + freed = prom_free_prom_memory(); + if (freed) + printk(KERN_INFO "Freeing firmware memory: %ldkb freed\n", + freed >> 10); + free_init_pages("unused kernel memory", __pa_symbol(&__init_begin), __pa_symbol(&__init_end)); } - -unsigned long pgd_current[NR_CPUS]; -/* - * On 64-bit we've got three-level pagetables with a slightly - * different layout ... - */ -#define __page_aligned(order) __attribute__((__aligned__(PAGE_SIZE< -#include -#include -#include -#include - -#include "jaguar_atx_fpga.h" - -#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) - -static struct resource mv643xx_eth_shared_resources[] = { - [0] = { - .name = "ethernet shared base", - .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, - .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + - MV643XX_ETH_SHARED_REGS_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device mv643xx_eth_shared_device = { - .name = MV643XX_ETH_SHARED_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), - .resource = mv643xx_eth_shared_resources, -}; - -#define MV_SRAM_BASE 0xfe000000UL -#define MV_SRAM_SIZE (256 * 1024) - -#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) -#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) - -#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE -#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) - -#define MV64x60_IRQ_ETH_0 48 -#define MV64x60_IRQ_ETH_1 49 -#define MV64x60_IRQ_ETH_2 50 - -#ifdef CONFIG_MV643XX_ETH_0 - -static struct resource mv64x60_eth0_resources[] = { - [0] = { - .name = "eth0 irq", - .start = MV64x60_IRQ_ETH_0, - .end = MV64x60_IRQ_ETH_0, - .flags = IORESOURCE_IRQ, - }, -}; - -static char eth0_mac_addr[ETH_ALEN]; - -static struct mv643xx_eth_platform_data eth0_pd = { - .mac_addr = eth0_mac_addr, - - .tx_sram_addr = MV_SRAM_BASE_ETH0, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth0_device = { - .name = MV643XX_ETH_NAME, - .id = 0, - .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), - .resource = mv64x60_eth0_resources, - .dev = { - .platform_data = ð0_pd, - }, -}; -#endif /* CONFIG_MV643XX_ETH_0 */ - -#ifdef CONFIG_MV643XX_ETH_1 - -static struct resource mv64x60_eth1_resources[] = { - [0] = { - .name = "eth1 irq", - .start = MV64x60_IRQ_ETH_1, - .end = MV64x60_IRQ_ETH_1, - .flags = IORESOURCE_IRQ, - }, -}; - -static char eth1_mac_addr[ETH_ALEN]; - -static struct mv643xx_eth_platform_data eth1_pd = { - .mac_addr = eth1_mac_addr, - - .tx_sram_addr = MV_SRAM_BASE_ETH1, - .tx_sram_size = MV_SRAM_TXRING_SIZE, - .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, - - .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, - .rx_sram_size = MV_SRAM_RXRING_SIZE, - .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, -}; - -static struct platform_device eth1_device = { - .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), - .resource = mv64x60_eth1_resources, - .dev = { - .platform_data = ð1_pd, - }, -}; -#endif /* CONFIG_MV643XX_ETH_1 */ - -#ifdef CONFIG_MV643XX_ETH_2 - -static struct resource mv64x60_eth2_resources[] = { - [0] = { - .name = "eth2 irq", - .start = MV64x60_IRQ_ETH_2, - .end = MV64x60_IRQ_ETH_2, - .flags = IORESOURCE_IRQ, - }, -}; - -static char eth2_mac_addr[ETH_ALEN]; - -static struct mv643xx_eth_platform_data eth2_pd = { - .mac_addr = eth2_mac_addr, -}; - -static struct platform_device eth2_device = { - .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), - .resource = mv64x60_eth2_resources, - .dev = { - .platform_data = ð2_pd, - }, -}; -#endif /* CONFIG_MV643XX_ETH_2 */ - -static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { - &mv643xx_eth_shared_device, -#ifdef CONFIG_MV643XX_ETH_0 - ð0_device, -#endif -#ifdef CONFIG_MV643XX_ETH_1 - ð1_device, -#endif -#ifdef CONFIG_MV643XX_ETH_2 - ð2_device, -#endif -}; - -static u8 __init exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - udelay(1); - - /* turn the clock on */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - udelay(1); - - /* turn the clock off and read-strobe */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; -} - -static void __init get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} - -/* - * Copy and increment ethernet MAC address by a small value. - * - * This is useful for systems where the only one MAC address is stored in - * non-volatile memory for multiple ports. - */ -static inline void eth_mac_add(unsigned char *dst, unsigned char *src, - unsigned int add) -{ - int i; - - BUG_ON(add >= 256); - - for (i = ETH_ALEN; i >= 0; i--) { - dst[i] = src[i] + add; - add = dst[i] < src[i]; /* compute carry */ - } - - WARN_ON(add); -} - -static int __init mv643xx_eth_add_pds(void) -{ - unsigned char mac[ETH_ALEN]; - int ret; - - get_mac(mac); -#ifdef CONFIG_MV643XX_ETH_0 - eth_mac_add(eth1_mac_addr, mac, 0); -#endif -#ifdef CONFIG_MV643XX_ETH_1 - eth_mac_add(eth1_mac_addr, mac, 1); -#endif -#ifdef CONFIG_MV643XX_ETH_2 - eth_mac_add(eth2_mac_addr, mac, 2); -#endif - ret = platform_add_devices(mv643xx_eth_pd_devs, - ARRAY_SIZE(mv643xx_eth_pd_devs)); - - return ret; -} - -device_initcall(mv643xx_eth_add_pds); - -#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/trunk/arch/mips/momentum/jaguar_atx/prom.c b/trunk/arch/mips/momentum/jaguar_atx/prom.c index 5dd154ee58f6..3d2712929293 100644 --- a/trunk/arch/mips/momentum/jaguar_atx/prom.c +++ b/trunk/arch/mips/momentum/jaguar_atx/prom.c @@ -39,6 +39,56 @@ const char *get_system_type(void) return "Momentum Jaguar-ATX"; } +#ifdef CONFIG_MV643XX_ETH +extern unsigned char prom_mac_addr_base[6]; + +static void burn_clocks(void) +{ + int i; + + /* this loop should burn at least 1us -- this should be plenty */ + for (i = 0; i < 0x10000; i++) + ; +} + +static u8 exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + burn_clocks(); + + /* turn the clock on */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + burn_clocks(); + + /* turn the clock off and read-strobe */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); +} + +void get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} +#endif + #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -178,10 +228,16 @@ void __init prom_init(void) #endif /* CONFIG_64BIT */ mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_JAGUAR_ATX; + +#ifdef CONFIG_MV643XX_ETH + /* get the base MAC address for on-board ethernet ports */ + get_mac(prom_mac_addr_base); +#endif } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } void __init prom_fixup_mem_map(unsigned long start, unsigned long end) diff --git a/trunk/arch/mips/momentum/ocelot_3/irq.c b/trunk/arch/mips/momentum/ocelot_3/irq.c index 3862d1d1add4..cea0e5deb80e 100644 --- a/trunk/arch/mips/momentum/ocelot_3/irq.c +++ b/trunk/arch/mips/momentum/ocelot_3/irq.c @@ -65,7 +65,7 @@ void __init arch_init_irq(void) */ clear_c0_status(ST0_IM | ST0_BEV); - rm7k_cpu_irq_init(); + rm7k_cpu_irq_init(8); /* set up the cascading interrupts */ setup_irq(8, &cascade_mv64340); /* unmask intControl IM8, IRQ 9 */ diff --git a/trunk/arch/mips/momentum/ocelot_3/prom.c b/trunk/arch/mips/momentum/ocelot_3/prom.c index 8e02df63578a..6ce9b7fdb824 100644 --- a/trunk/arch/mips/momentum/ocelot_3/prom.c +++ b/trunk/arch/mips/momentum/ocelot_3/prom.c @@ -180,8 +180,9 @@ void __init prom_init(void) #endif } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } void __init prom_fixup_mem_map(unsigned long start, unsigned long end) diff --git a/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c index 186a140fd2a9..bb11fef08472 100644 --- a/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c +++ b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -84,7 +84,7 @@ void ll_cpci_irq(void) } struct irq_chip cpci_irq_type = { - .name = "CPCI/FPGA", + .typename = "CPCI/FPGA", .ack = mask_cpci_irq, .mask = mask_cpci_irq, .mask_ack = mask_cpci_irq, diff --git a/trunk/arch/mips/momentum/ocelot_c/dbg_io.c b/trunk/arch/mips/momentum/ocelot_c/dbg_io.c index 32d6fb4ee679..2128684584f5 100644 --- a/trunk/arch/mips/momentum/ocelot_c/dbg_io.c +++ b/trunk/arch/mips/momentum/ocelot_c/dbg_io.c @@ -1,4 +1,6 @@ +#ifdef CONFIG_KGDB + #include /* For the serial port location and base baud */ /* --- CONFIG --- */ @@ -119,3 +121,5 @@ int putDebugChar(uint8 byte) UART16550_WRITE(OFS_SEND_BUFFER, byte); return 1; } + +#endif diff --git a/trunk/arch/mips/momentum/ocelot_c/irq.c b/trunk/arch/mips/momentum/ocelot_c/irq.c index 40472f7944d7..ea65223a6d2c 100644 --- a/trunk/arch/mips/momentum/ocelot_c/irq.c +++ b/trunk/arch/mips/momentum/ocelot_c/irq.c @@ -94,7 +94,7 @@ void __init arch_init_irq(void) */ clear_c0_status(ST0_IM); - mips_cpu_irq_init(); + mips_cpu_irq_init(0); /* set up the cascading interrupts */ setup_irq(3, &cascade_fpga); diff --git a/trunk/arch/mips/momentum/ocelot_c/prom.c b/trunk/arch/mips/momentum/ocelot_c/prom.c index b689ceea8cfb..d0b77e101d74 100644 --- a/trunk/arch/mips/momentum/ocelot_c/prom.c +++ b/trunk/arch/mips/momentum/ocelot_c/prom.c @@ -178,6 +178,7 @@ void __init prom_init(void) #endif } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff --git a/trunk/arch/mips/momentum/ocelot_c/uart-irq.c b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c index de1a31ee52f3..a7a80c0da569 100644 --- a/trunk/arch/mips/momentum/ocelot_c/uart-irq.c +++ b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c @@ -77,7 +77,7 @@ void ll_uart_irq(void) } struct irq_chip uart_irq_type = { - .name = "UART/FPGA", + .typename = "UART/FPGA", .ack = mask_uart_irq, .mask = mask_uart_irq, .mask_ack = mask_uart_irq, diff --git a/trunk/arch/mips/momentum/ocelot_g/dbg_io.c b/trunk/arch/mips/momentum/ocelot_g/dbg_io.c index 32d6fb4ee679..2128684584f5 100644 --- a/trunk/arch/mips/momentum/ocelot_g/dbg_io.c +++ b/trunk/arch/mips/momentum/ocelot_g/dbg_io.c @@ -1,4 +1,6 @@ +#ifdef CONFIG_KGDB + #include /* For the serial port location and base baud */ /* --- CONFIG --- */ @@ -119,3 +121,5 @@ int putDebugChar(uint8 byte) UART16550_WRITE(OFS_SEND_BUFFER, byte); return 1; } + +#endif diff --git a/trunk/arch/mips/momentum/ocelot_g/irq.c b/trunk/arch/mips/momentum/ocelot_g/irq.c index 273541fe7087..da46524e87cb 100644 --- a/trunk/arch/mips/momentum/ocelot_g/irq.c +++ b/trunk/arch/mips/momentum/ocelot_g/irq.c @@ -94,8 +94,8 @@ void __init arch_init_irq(void) clear_c0_status(ST0_IM); local_irq_disable(); - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); gt64240_irq_init(); } diff --git a/trunk/arch/mips/momentum/ocelot_g/prom.c b/trunk/arch/mips/momentum/ocelot_g/prom.c index 836d0830720d..2f75c6b91ec5 100644 --- a/trunk/arch/mips/momentum/ocelot_g/prom.c +++ b/trunk/arch/mips/momentum/ocelot_g/prom.c @@ -79,6 +79,7 @@ void __init prom_init(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff --git a/trunk/arch/mips/oprofile/Kconfig b/trunk/arch/mips/oprofile/Kconfig index ca395ef06d4e..55feaf798596 100644 --- a/trunk/arch/mips/oprofile/Kconfig +++ b/trunk/arch/mips/oprofile/Kconfig @@ -11,7 +11,7 @@ config PROFILING config OPROFILE tristate "OProfile system profiling (EXPERIMENTAL)" - depends on PROFILING && !!MIPS_MT_SMTC && EXPERIMENTAL + depends on PROFILING && EXPERIMENTAL help OProfile is a profiling system capable of profiling the whole system, include the kernel, kernel modules, libraries, diff --git a/trunk/arch/mips/pci/fixup-vr4133.c b/trunk/arch/mips/pci/fixup-vr4133.c index a8d9d22b13df..597b89764ba1 100644 --- a/trunk/arch/mips/pci/fixup-vr4133.c +++ b/trunk/arch/mips/pci/fixup-vr4133.c @@ -17,10 +17,8 @@ */ #include #include -#include #include -#include #include extern int vr4133_rockhopper; @@ -144,7 +142,7 @@ int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot) if (bus == NULL) return -1; - for (i = 0; i < ARRAY_SIZE(int_map); i++) { + for (i = 0; i < sizeof (int_map) / sizeof (int_map[0]); i++) { if (int_map[i].bus == bus->number && int_map[i].slot == slot) { int line; for (line = 0; line < 4; line++) @@ -162,7 +160,17 @@ int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot) #ifdef CONFIG_ROCKHOPPER void i8259_init(void) { - init_i8259_irqs(); + outb(0x11, 0x20); /* Master ICW1 */ + outb(I8259_IRQ_BASE, 0x21); /* Master ICW2 */ + outb(0x04, 0x21); /* Master ICW3 */ + outb(0x01, 0x21); /* Master ICW4 */ + outb(0xff, 0x21); /* Master IMW */ + + outb(0x11, 0xa0); /* Slave ICW1 */ + outb(I8259_IRQ_BASE + 8, 0xa1); /* Slave ICW2 */ + outb(0x02, 0xa1); /* Slave ICW3 */ + outb(0x01, 0xa1); /* Slave ICW4 */ + outb(0xff, 0xa1); /* Slave IMW */ outb(0x00, 0x4d0); outb(0x02, 0x4d1); /* USB IRQ9 is level */ diff --git a/trunk/arch/mips/philips/pnx8550/common/int.c b/trunk/arch/mips/philips/pnx8550/common/int.c index d48665ebd33c..2c36c108c4d6 100644 --- a/trunk/arch/mips/philips/pnx8550/common/int.c +++ b/trunk/arch/mips/philips/pnx8550/common/int.c @@ -159,7 +159,7 @@ int pnx8550_set_gic_priority(int irq, int priority) } static struct irq_chip level_irq_type = { - .name = "PNX Level IRQ", + .typename = "PNX Level IRQ", .ack = mask_irq, .mask = mask_irq, .mask_ack = mask_irq, diff --git a/trunk/arch/mips/philips/pnx8550/common/prom.c b/trunk/arch/mips/philips/pnx8550/common/prom.c index 8aeed6c2b8c3..eb6ec11fef07 100644 --- a/trunk/arch/mips/philips/pnx8550/common/prom.c +++ b/trunk/arch/mips/philips/pnx8550/common/prom.c @@ -106,8 +106,9 @@ int get_ethernet_addr(char *ethernet_addr) return 0; } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } extern int pnx8550_console_port; diff --git a/trunk/arch/mips/pmc-sierra/yosemite/dbg_io.c b/trunk/arch/mips/pmc-sierra/yosemite/dbg_io.c index 6362c702e389..0f659c9106ac 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/dbg_io.c +++ b/trunk/arch/mips/pmc-sierra/yosemite/dbg_io.c @@ -93,7 +93,7 @@ * Functions to READ and WRITE to serial port 1 */ #define SERIAL_READ_1(ofs) (*((volatile unsigned char*) \ - (TITAN_SERIAL_BASE_1 + ofs))) + (TITAN_SERIAL_BASE_1 + ofs) #define SERIAL_WRITE_1(ofs, val) ((*((volatile unsigned char*) \ (TITAN_SERIAL_BASE_1 + ofs))) = val) diff --git a/trunk/arch/mips/pmc-sierra/yosemite/irq.c b/trunk/arch/mips/pmc-sierra/yosemite/irq.c index 428d1f45a287..adb048527e76 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/irq.c +++ b/trunk/arch/mips/pmc-sierra/yosemite/irq.c @@ -148,9 +148,9 @@ void __init arch_init_irq(void) { clear_c0_status(ST0_IM); - mips_cpu_irq_init(); - rm7k_cpu_irq_init(); - rm9k_cpu_irq_init(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); + rm9k_cpu_irq_init(12); #ifdef CONFIG_KGDB /* At this point, initialize the second serial port */ diff --git a/trunk/arch/mips/pmc-sierra/yosemite/prom.c b/trunk/arch/mips/pmc-sierra/yosemite/prom.c index 1e1685e415a4..9fe4973377c3 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/prom.c +++ b/trunk/arch/mips/pmc-sierra/yosemite/prom.c @@ -132,8 +132,9 @@ void __init prom_init(void) prom_grab_secondary(); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } void __init prom_fixup_mem_map(unsigned long start, unsigned long end) diff --git a/trunk/arch/mips/pmc-sierra/yosemite/setup.c b/trunk/arch/mips/pmc-sierra/yosemite/setup.c index 6a6e15e40009..1b9b0d396d3e 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/setup.c +++ b/trunk/arch/mips/pmc-sierra/yosemite/setup.c @@ -171,7 +171,6 @@ static void __init py_map_ocd(void) static void __init py_uart_setup(void) { -#ifdef CONFIG_SERIAL_8250 struct uart_port up; /* @@ -189,7 +188,6 @@ static void __init py_uart_setup(void) if (early_serial_setup(&up)) printk(KERN_ERR "Early serial init of port 0 failed\n"); -#endif /* CONFIG_SERIAL_8250 */ } static void __init py_rtc_setup(void) diff --git a/trunk/arch/mips/qemu/q-mem.c b/trunk/arch/mips/qemu/q-mem.c index dae39b59de15..d174fac43031 100644 --- a/trunk/arch/mips/qemu/q-mem.c +++ b/trunk/arch/mips/qemu/q-mem.c @@ -1,5 +1,6 @@ #include -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0UL; } diff --git a/trunk/arch/mips/sgi-ip22/ip22-eisa.c b/trunk/arch/mips/sgi-ip22/ip22-eisa.c index 6b6e97b90c6e..a1a9af6da7bf 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-eisa.c +++ b/trunk/arch/mips/sgi-ip22/ip22-eisa.c @@ -139,7 +139,7 @@ static void end_eisa1_irq(unsigned int irq) } static struct irq_chip ip22_eisa1_irq_type = { - .name = "IP22 EISA", + .typename = "IP22 EISA", .startup = startup_eisa1_irq, .ack = mask_and_ack_eisa1_irq, .mask = disable_eisa1_irq, @@ -194,7 +194,7 @@ static void end_eisa2_irq(unsigned int irq) } static struct irq_chip ip22_eisa2_irq_type = { - .name = "IP22 EISA", + .typename = "IP22 EISA", .startup = startup_eisa2_irq, .ack = mask_and_ack_eisa2_irq, .mask = disable_eisa2_irq, diff --git a/trunk/arch/mips/sgi-ip22/ip22-int.c b/trunk/arch/mips/sgi-ip22/ip22-int.c index b454924aeb56..c44f8be0644f 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-int.c +++ b/trunk/arch/mips/sgi-ip22/ip22-int.c @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -53,7 +52,7 @@ static void disable_local0_irq(unsigned int irq) } static struct irq_chip ip22_local0_irq_type = { - .name = "IP22 local 0", + .typename = "IP22 local 0", .ack = disable_local0_irq, .mask = disable_local0_irq, .mask_ack = disable_local0_irq, @@ -74,7 +73,7 @@ void disable_local1_irq(unsigned int irq) } static struct irq_chip ip22_local1_irq_type = { - .name = "IP22 local 1", + .typename = "IP22 local 1", .ack = disable_local1_irq, .mask = disable_local1_irq, .mask_ack = disable_local1_irq, @@ -95,7 +94,7 @@ void disable_local2_irq(unsigned int irq) } static struct irq_chip ip22_local2_irq_type = { - .name = "IP22 local 2", + .typename = "IP22 local 2", .ack = disable_local2_irq, .mask = disable_local2_irq, .mask_ack = disable_local2_irq, @@ -116,7 +115,7 @@ void disable_local3_irq(unsigned int irq) } static struct irq_chip ip22_local3_irq_type = { - .name = "IP22 local 3", + .typename = "IP22 local 3", .ack = disable_local3_irq, .mask = disable_local3_irq, .mask_ack = disable_local3_irq, @@ -254,6 +253,8 @@ asmlinkage void plat_irq_dispatch(void) indy_8254timer_irq(); } +extern void mips_cpu_irq_init(unsigned int irq_base); + void __init arch_init_irq(void) { int i; @@ -315,7 +316,7 @@ void __init arch_init_irq(void) sgint->cmeimask1 = 0; /* init CPU irqs */ - mips_cpu_irq_init(); + mips_cpu_irq_init(SGINT_CPU); for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) { struct irq_chip *handler; diff --git a/trunk/arch/mips/sgi-ip22/ip22-mc.c b/trunk/arch/mips/sgi-ip22/ip22-mc.c index ddb6506d8341..b58bd522262b 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-mc.c +++ b/trunk/arch/mips/sgi-ip22/ip22-mc.c @@ -202,6 +202,7 @@ void __init sgimc_init(void) } void __init prom_meminit(void) {} -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff --git a/trunk/arch/mips/sgi-ip27/ip27-irq.c b/trunk/arch/mips/sgi-ip27/ip27-irq.c index 60ade7690e09..319f8803ef6f 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-irq.c +++ b/trunk/arch/mips/sgi-ip27/ip27-irq.c @@ -333,7 +333,7 @@ static inline void disable_bridge_irq(unsigned int irq) } static struct irq_chip bridge_irq_type = { - .name = "bridge", + .typename = "bridge", .startup = startup_bridge_irq, .shutdown = shutdown_bridge_irq, .ack = disable_bridge_irq, diff --git a/trunk/arch/mips/sgi-ip27/ip27-memory.c b/trunk/arch/mips/sgi-ip27/ip27-memory.c index 0e3d535e9f43..16e5682b01f1 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-memory.c +++ b/trunk/arch/mips/sgi-ip27/ip27-memory.c @@ -498,9 +498,10 @@ void __init prom_meminit(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* We got nothing to free here ... */ + return 0; } extern void pagetable_init(void); diff --git a/trunk/arch/mips/sgi-ip27/ip27-timer.c b/trunk/arch/mips/sgi-ip27/ip27-timer.c index 9ce513629b14..c20e9899b34b 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-timer.c +++ b/trunk/arch/mips/sgi-ip27/ip27-timer.c @@ -181,7 +181,7 @@ static void disable_rt_irq(unsigned int irq) } static struct irq_chip rt_irq_type = { - .name = "SN HUB RT timer", + .typename = "SN HUB RT timer", .ack = disable_rt_irq, .mask = disable_rt_irq, .mask_ack = disable_rt_irq, diff --git a/trunk/arch/mips/sgi-ip32/ip32-irq.c b/trunk/arch/mips/sgi-ip32/ip32-irq.c index 8c450d9e8696..ae063864c026 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-irq.c +++ b/trunk/arch/mips/sgi-ip32/ip32-irq.c @@ -144,7 +144,7 @@ static void end_cpu_irq(unsigned int irq) } static struct irq_chip ip32_cpu_interrupt = { - .name = "IP32 CPU", + .typename = "IP32 CPU", .ack = disable_cpu_irq, .mask = disable_cpu_irq, .mask_ack = disable_cpu_irq, @@ -193,7 +193,7 @@ static void end_crime_irq(unsigned int irq) } static struct irq_chip ip32_crime_interrupt = { - .name = "IP32 CRIME", + .typename = "IP32 CRIME", .ack = mask_and_ack_crime_irq, .mask = disable_crime_irq, .mask_ack = mask_and_ack_crime_irq, @@ -234,7 +234,7 @@ static void end_macepci_irq(unsigned int irq) } static struct irq_chip ip32_macepci_interrupt = { - .name = "IP32 MACE PCI", + .typename = "IP32 MACE PCI", .ack = disable_macepci_irq, .mask = disable_macepci_irq, .mask_ack = disable_macepci_irq, @@ -347,7 +347,7 @@ static void end_maceisa_irq(unsigned irq) } static struct irq_chip ip32_maceisa_interrupt = { - .name = "IP32 MACE ISA", + .typename = "IP32 MACE ISA", .ack = mask_and_ack_maceisa_irq, .mask = disable_maceisa_irq, .mask_ack = mask_and_ack_maceisa_irq, @@ -379,7 +379,7 @@ static void end_mace_irq(unsigned int irq) } static struct irq_chip ip32_mace_interrupt = { - .name = "IP32 MACE", + .typename = "IP32 MACE", .ack = disable_mace_irq, .mask = disable_mace_irq, .mask_ack = disable_mace_irq, diff --git a/trunk/arch/mips/sgi-ip32/ip32-memory.c b/trunk/arch/mips/sgi-ip32/ip32-memory.c index 849d392a0013..d37d40a3cdae 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-memory.c +++ b/trunk/arch/mips/sgi-ip32/ip32-memory.c @@ -43,6 +43,7 @@ void __init prom_meminit (void) } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory (void) { + return 0; } diff --git a/trunk/arch/mips/sibyte/bcm1480/irq.c b/trunk/arch/mips/sibyte/bcm1480/irq.c index 1dc5d05d8962..2e8f6b2e2420 100644 --- a/trunk/arch/mips/sibyte/bcm1480/irq.c +++ b/trunk/arch/mips/sibyte/bcm1480/irq.c @@ -82,7 +82,7 @@ extern char sb1250_duart_present[]; #endif static struct irq_chip bcm1480_irq_type = { - .name = "BCM1480-IMR", + .typename = "BCM1480-IMR", .ack = ack_bcm1480_irq, .mask = disable_bcm1480_irq, .mask_ack = ack_bcm1480_irq, diff --git a/trunk/arch/mips/sibyte/cfe/setup.c b/trunk/arch/mips/sibyte/cfe/setup.c index 9e6099e69622..6e8952da6e2a 100644 --- a/trunk/arch/mips/sibyte/cfe/setup.c +++ b/trunk/arch/mips/sibyte/cfe/setup.c @@ -343,9 +343,10 @@ void __init prom_init(void) prom_meminit(); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Not sure what I'm supposed to do here. Nothing, I think */ + return 0; } void prom_putchar(char c) diff --git a/trunk/arch/mips/sibyte/sb1250/irq.c b/trunk/arch/mips/sibyte/sb1250/irq.c index 148239446e6e..82ce7533053f 100644 --- a/trunk/arch/mips/sibyte/sb1250/irq.c +++ b/trunk/arch/mips/sibyte/sb1250/irq.c @@ -67,7 +67,7 @@ extern char sb1250_duart_present[]; #endif static struct irq_chip sb1250_irq_type = { - .name = "SB1250-IMR", + .typename = "SB1250-IMR", .ack = ack_sb1250_irq, .mask = disable_sb1250_irq, .mask_ack = ack_sb1250_irq, diff --git a/trunk/arch/mips/sibyte/sb1250/prom.c b/trunk/arch/mips/sibyte/sb1250/prom.c index 257c4e674353..3c33a4517bc3 100644 --- a/trunk/arch/mips/sibyte/sb1250/prom.c +++ b/trunk/arch/mips/sibyte/sb1250/prom.c @@ -87,9 +87,10 @@ void __init prom_init(void) prom_meminit(); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Not sure what I'm supposed to do here. Nothing, I think */ + return 0; } void prom_putchar(char c) diff --git a/trunk/arch/mips/sni/irq.c b/trunk/arch/mips/sni/irq.c index 039e8e540508..8511bcc6d99d 100644 --- a/trunk/arch/mips/sni/irq.c +++ b/trunk/arch/mips/sni/irq.c @@ -37,7 +37,7 @@ static void end_pciasic_irq(unsigned int irq) } static struct irq_chip pciasic_irq_type = { - .name = "ASIC-PCI", + .typename = "ASIC-PCI", .ack = disable_pciasic_irq, .mask = disable_pciasic_irq, .mask_ack = disable_pciasic_irq, diff --git a/trunk/arch/mips/sni/sniprom.c b/trunk/arch/mips/sni/sniprom.c index 1213d166f22e..d1d0f1f493b4 100644 --- a/trunk/arch/mips/sni/sniprom.c +++ b/trunk/arch/mips/sni/sniprom.c @@ -67,8 +67,9 @@ void prom_printf(char *fmt, ...) va_end(args); } -void __init prom_free_prom_memory(void) +unsigned long prom_free_prom_memory(void) { + return 0; } /* diff --git a/trunk/arch/mips/tx4927/common/tx4927_irq.c b/trunk/arch/mips/tx4927/common/tx4927_irq.c index e7f3e5b84dcf..ed4a19adf361 100644 --- a/trunk/arch/mips/tx4927/common/tx4927_irq.c +++ b/trunk/arch/mips/tx4927/common/tx4927_irq.c @@ -120,7 +120,7 @@ static void tx4927_irq_pic_disable(unsigned int irq); #define TX4927_CP0_NAME "TX4927-CP0" static struct irq_chip tx4927_irq_cp0_type = { - .name = TX4927_CP0_NAME, + .typename = TX4927_CP0_NAME, .ack = tx4927_irq_cp0_disable, .mask = tx4927_irq_cp0_disable, .mask_ack = tx4927_irq_cp0_disable, @@ -129,7 +129,7 @@ static struct irq_chip tx4927_irq_cp0_type = { #define TX4927_PIC_NAME "TX4927-PIC" static struct irq_chip tx4927_irq_pic_type = { - .name = TX4927_PIC_NAME, + .typename = TX4927_PIC_NAME, .ack = tx4927_irq_pic_disable, .mask = tx4927_irq_pic_disable, .mask_ack = tx4927_irq_pic_disable, diff --git a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index dcce88f403c9..b54b529a29f9 100644 --- a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -228,7 +228,7 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq); #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { - .name = TOSHIBA_RBTX4927_IOC_NAME, + .typename = TOSHIBA_RBTX4927_IOC_NAME, .ack = toshiba_rbtx4927_irq_ioc_disable, .mask = toshiba_rbtx4927_irq_ioc_disable, .mask_ack = toshiba_rbtx4927_irq_ioc_disable, @@ -241,7 +241,7 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { #ifdef CONFIG_TOSHIBA_FPCIB0 #define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA" static struct irq_chip toshiba_rbtx4927_irq_isa_type = { - .name = TOSHIBA_RBTX4927_ISA_NAME, + .typename = TOSHIBA_RBTX4927_ISA_NAME, .ack = toshiba_rbtx4927_irq_isa_mask_and_ack, .mask = toshiba_rbtx4927_irq_isa_disable, .mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack, @@ -490,13 +490,13 @@ void toshiba_rbtx4927_irq_dump(char *key) { u32 i, j = 0; for (i = 0; i < NR_IRQS; i++) { - if (strcmp(irq_desc[i].chip->name, "none") + if (strcmp(irq_desc[i].chip->typename, "none") == 0) continue; if ((i >= 1) - && (irq_desc[i - 1].chip->name == - irq_desc[i].chip->name)) { + && (irq_desc[i - 1].chip->typename == + irq_desc[i].chip->typename)) { j++; } else { j = 0; @@ -510,7 +510,7 @@ void toshiba_rbtx4927_irq_dump(char *key) (u32) (irq_desc[i].action ? irq_desc[i]. action->handler : 0), irq_desc[i].depth, - irq_desc[i].chip->name, j); + irq_desc[i].chip->typename, j); } } #endif diff --git a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c index 9a3a5babd1fb..efe50562f0ce 100644 --- a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c +++ b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c @@ -80,8 +80,9 @@ void __init prom_init(void) add_memory_region(0, msize << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } const char *get_system_type(void) diff --git a/trunk/arch/mips/tx4938/common/irq.c b/trunk/arch/mips/tx4938/common/irq.c index 3a2dbfc25014..a347b424d91c 100644 --- a/trunk/arch/mips/tx4938/common/irq.c +++ b/trunk/arch/mips/tx4938/common/irq.c @@ -49,7 +49,7 @@ static void tx4938_irq_pic_disable(unsigned int irq); #define TX4938_CP0_NAME "TX4938-CP0" static struct irq_chip tx4938_irq_cp0_type = { - .name = TX4938_CP0_NAME, + .typename = TX4938_CP0_NAME, .ack = tx4938_irq_cp0_disable, .mask = tx4938_irq_cp0_disable, .mask_ack = tx4938_irq_cp0_disable, @@ -58,7 +58,7 @@ static struct irq_chip tx4938_irq_cp0_type = { #define TX4938_PIC_NAME "TX4938-PIC" static struct irq_chip tx4938_irq_pic_type = { - .name = TX4938_PIC_NAME, + .typename = TX4938_PIC_NAME, .ack = tx4938_irq_pic_disable, .mask = tx4938_irq_pic_disable, .mask_ack = tx4938_irq_pic_disable, diff --git a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 2e96dbb248b1..b6f363d08011 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -92,7 +92,7 @@ static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { - .name = TOSHIBA_RBTX4938_IOC_NAME, + .typename = TOSHIBA_RBTX4938_IOC_NAME, .ack = toshiba_rbtx4938_irq_ioc_disable, .mask = toshiba_rbtx4938_irq_ioc_disable, .mask_ack = toshiba_rbtx4938_irq_ioc_disable, diff --git a/trunk/arch/mips/tx4938/toshiba_rbtx4938/prom.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/prom.c index 7dc6a0aae21c..e44daf30a7c1 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/prom.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/prom.c @@ -56,8 +56,9 @@ void __init prom_init(void) return; } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } void __init prom_fixup_mem_map(unsigned long start, unsigned long end) diff --git a/trunk/arch/mips/vr41xx/common/icu.c b/trunk/arch/mips/vr41xx/common/icu.c index adabc6bad440..c075261976c5 100644 --- a/trunk/arch/mips/vr41xx/common/icu.c +++ b/trunk/arch/mips/vr41xx/common/icu.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2002 MontaVista Software Inc. * Author: Yoichi Yuasa - * Copyright (C) 2003-2006 Yoichi Yuasa + * Copyright (C) 2003-2005 Yoichi Yuasa * * 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 @@ -68,7 +68,6 @@ static unsigned char sysint2_assign[16] = { #define MPIUINTREG 0x0e #define MAIUINTREG 0x10 #define MKIUINTREG 0x12 -#define MMACINTREG 0x12 #define MGIUINTLREG 0x14 #define MDSIUINTREG 0x16 #define NMIREG 0x18 @@ -242,30 +241,6 @@ void vr41xx_disable_kiuint(uint16_t mask) EXPORT_SYMBOL(vr41xx_disable_kiuint); -void vr41xx_enable_macint(uint16_t mask) -{ - struct irq_desc *desc = irq_desc + ETHERNET_IRQ; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - icu1_set(MMACINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vr41xx_enable_macint); - -void vr41xx_disable_macint(uint16_t mask) -{ - struct irq_desc *desc = irq_desc + ETHERNET_IRQ; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - icu1_clear(MMACINTREG, mask); - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(vr41xx_disable_macint); - void vr41xx_enable_dsiuint(uint16_t mask) { struct irq_desc *desc = irq_desc + DSIU_IRQ; @@ -453,7 +428,7 @@ static void enable_sysint1_irq(unsigned int irq) } static struct irq_chip sysint1_irq_type = { - .name = "SYSINT1", + .typename = "SYSINT1", .ack = disable_sysint1_irq, .mask = disable_sysint1_irq, .mask_ack = disable_sysint1_irq, @@ -471,7 +446,7 @@ static void enable_sysint2_irq(unsigned int irq) } static struct irq_chip sysint2_irq_type = { - .name = "SYSINT2", + .typename = "SYSINT2", .ack = disable_sysint2_irq, .mask = disable_sysint2_irq, .mask_ack = disable_sysint2_irq, diff --git a/trunk/arch/mips/vr41xx/common/init.c b/trunk/arch/mips/vr41xx/common/init.c index 4f97e0ba9e24..a2e285c1d4d5 100644 --- a/trunk/arch/mips/vr41xx/common/init.c +++ b/trunk/arch/mips/vr41xx/common/init.c @@ -81,6 +81,7 @@ void __init prom_init(void) } } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory (void) { + return 0UL; } diff --git a/trunk/arch/mips/vr41xx/common/irq.c b/trunk/arch/mips/vr41xx/common/irq.c index cba36a247e32..16decf4ac2f4 100644 --- a/trunk/arch/mips/vr41xx/common/irq.c +++ b/trunk/arch/mips/vr41xx/common/irq.c @@ -95,27 +95,27 @@ asmlinkage void plat_irq_dispatch(void) unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; if (pending & CAUSEF_IP7) - do_IRQ(TIMER_IRQ); + do_IRQ(7); else if (pending & 0x7800) { if (pending & CAUSEF_IP3) - irq_dispatch(INT1_IRQ); + irq_dispatch(3); else if (pending & CAUSEF_IP4) - irq_dispatch(INT2_IRQ); + irq_dispatch(4); else if (pending & CAUSEF_IP5) - irq_dispatch(INT3_IRQ); + irq_dispatch(5); else if (pending & CAUSEF_IP6) - irq_dispatch(INT4_IRQ); + irq_dispatch(6); } else if (pending & CAUSEF_IP2) - irq_dispatch(INT0_IRQ); + irq_dispatch(2); else if (pending & CAUSEF_IP0) - do_IRQ(MIPS_SOFTINT0_IRQ); + do_IRQ(0); else if (pending & CAUSEF_IP1) - do_IRQ(MIPS_SOFTINT1_IRQ); + do_IRQ(1); else spurious_interrupt(); } void __init arch_init_irq(void) { - mips_cpu_irq_init(); + mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); } diff --git a/trunk/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/trunk/arch/mips/vr41xx/nec-cmbvr4133/irq.c index 7d2d076b0f54..128ed8d6f111 100644 --- a/trunk/arch/mips/vr41xx/nec-cmbvr4133/irq.c +++ b/trunk/arch/mips/vr41xx/nec-cmbvr4133/irq.c @@ -21,16 +21,60 @@ #include #include -#include #include +extern void enable_8259A_irq(unsigned int irq); +extern void disable_8259A_irq(unsigned int irq); +extern void mask_and_ack_8259A(unsigned int irq); +extern void init_8259A(int hoge); + extern int vr4133_rockhopper; +static void enable_i8259_irq(unsigned int irq) +{ + enable_8259A_irq(irq - I8259_IRQ_BASE); +} + +static void disable_i8259_irq(unsigned int irq) +{ + disable_8259A_irq(irq - I8259_IRQ_BASE); +} + +static void ack_i8259_irq(unsigned int irq) +{ + mask_and_ack_8259A(irq - I8259_IRQ_BASE); +} + +static struct irq_chip i8259_irq_type = { + .typename = "XT-PIC", + .ack = ack_i8259_irq, + .mask = disable_i8259_irq, + .mask_ack = ack_i8259_irq, + .unmask = enable_i8259_irq, +}; + static int i8259_get_irq_number(int irq) { - return i8259_irq(); + unsigned long isr; + + isr = inb(0x20); + irq = ffz(~isr); + if (irq == 2) { + isr = inb(0xa0); + irq = 8 + ffz(~isr); + } + + if (irq < 0 || irq > 15) + return -EINVAL; + + return I8259_IRQ_BASE + irq; } +static struct irqaction i8259_slave_cascade = { + .handler = &no_action, + .name = "cascade", +}; + void __init rockhopper_init_irq(void) { int i; @@ -40,6 +84,11 @@ void __init rockhopper_init_irq(void) return; } + for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++) + set_irq_chip_and_handler(i, &i8259_irq_type, handle_level_irq); + + setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade); + vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH); vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH); vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number); diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index eaed402ad346..12272361c018 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -34,6 +34,10 @@ config GENERIC_HWEIGHT bool default y +config GENERIC_CALIBRATE_DELAY + bool + default y + config GENERIC_TIME def_bool y @@ -130,31 +134,6 @@ config AUDIT_ARCH bool default y -config S390_SWITCH_AMODE - bool "Switch kernel/user addressing modes" - help - This option allows to switch the addressing modes of kernel and user - space. The kernel parameter switch_amode=on will enable this feature, - default is disabled. Enabling this (via kernel parameter) on machines - earlier than IBM System z9-109 EC/BC will reduce system performance. - - Note that this option will also be selected by selecting the execute - protection option below. Enabling the execute protection via the - noexec kernel parameter will also switch the addressing modes, - independent of the switch_amode kernel parameter. - - -config S390_EXEC_PROTECT - bool "Data execute protection" - select S390_SWITCH_AMODE - help - This option allows to enable a buffer overflow protection for user - space programs and it also selects the addressing mode option above. - The kernel parameter noexec=on will enable this feature and also - switch the addressing modes, default is disabled. Enabling this (via - kernel parameter) on machines earlier than IBM System z9-109 EC/BC - will reduce system performance. - comment "Code generation options" choice diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index c9da7d16145e..b8c237290263 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -81,7 +81,7 @@ static struct ctl_table appldata_dir_table[] = { /* * Timer */ -static DEFINE_PER_CPU(struct vtimer_list, appldata_timer); +DEFINE_PER_CPU(struct vtimer_list, appldata_timer); static atomic_t appldata_expire_count = ATOMIC_INIT(0); static DEFINE_SPINLOCK(appldata_timer_lock); diff --git a/trunk/arch/s390/appldata/appldata_mem.c b/trunk/arch/s390/appldata/appldata_mem.c index 4ca615788702..8aea3698a77b 100644 --- a/trunk/arch/s390/appldata/appldata_mem.c +++ b/trunk/arch/s390/appldata/appldata_mem.c @@ -36,7 +36,7 @@ * book: * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml */ -static struct appldata_mem_data { +struct appldata_mem_data { u64 timestamp; u32 sync_count_1; /* after VM collected the record data, */ u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the diff --git a/trunk/arch/s390/appldata/appldata_net_sum.c b/trunk/arch/s390/appldata/appldata_net_sum.c index f64b8c867ae2..075e619bf37d 100644 --- a/trunk/arch/s390/appldata/appldata_net_sum.c +++ b/trunk/arch/s390/appldata/appldata_net_sum.c @@ -34,7 +34,7 @@ * book: * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml */ -static struct appldata_net_sum_data { +struct appldata_net_sum_data { u64 timestamp; u32 sync_count_1; /* after VM collected the record data, */ u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the diff --git a/trunk/arch/s390/crypto/Kconfig b/trunk/arch/s390/crypto/Kconfig deleted file mode 100644 index 99ff9f08e4d7..000000000000 --- a/trunk/arch/s390/crypto/Kconfig +++ /dev/null @@ -1,60 +0,0 @@ -config CRYPTO_SHA1_S390 - tristate "SHA1 digest algorithm" - depends on S390 - select CRYPTO_ALGAPI - help - This is the s390 hardware accelerated implementation of the - SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). - -config CRYPTO_SHA256_S390 - tristate "SHA256 digest algorithm" - depends on S390 - select CRYPTO_ALGAPI - help - This is the s390 hardware accelerated implementation of the - SHA256 secure hash standard (DFIPS 180-2). - - This version of SHA implements a 256 bit hash with 128 bits of - security against collision attacks. - -config CRYPTO_DES_S390 - tristate "DES and Triple DES cipher algorithms" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER - help - This us the s390 hardware accelerated implementation of the - DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). - -config CRYPTO_AES_S390 - tristate "AES cipher algorithms" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER - help - This is the s390 hardware accelerated implementation of the - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - On s390 the System z9-109 currently only supports the key size - of 128 bit. - -config S390_PRNG - tristate "Pseudo random number generator device driver" - depends on S390 - default "m" - help - Select this option if you want to use the s390 pseudo random number - generator. The PRNG is part of the cryptograhic processor functions - and uses triple-DES to generate secure random numbers like the - ANSI X9.17 standard. The PRNG is usable via the char device - /dev/prandom. diff --git a/trunk/arch/s390/crypto/Makefile b/trunk/arch/s390/crypto/Makefile index 14e552c5cc43..bfe2541dc5cf 100644 --- a/trunk/arch/s390/crypto/Makefile +++ b/trunk/arch/s390/crypto/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o -obj-$(CONFIG_S390_PRNG) += prng.o + +obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o diff --git a/trunk/arch/s390/crypto/aes_s390.c b/trunk/arch/s390/crypto/aes_s390.c index 91636353f6f0..15c9eec02928 100644 --- a/trunk/arch/s390/crypto/aes_s390.c +++ b/trunk/arch/s390/crypto/aes_s390.c @@ -4,7 +4,7 @@ * s390 implementation of the AES Cipher Algorithm. * * s390 Version: - * Copyright IBM Corp. 2005,2007 + * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation * Author(s): Jan Glauber (jang@de.ibm.com) * * Derived from "crypto/aes.c" @@ -27,11 +27,9 @@ /* data block size for all key lengths */ #define AES_BLOCK_SIZE 16 -#define AES_KEYLEN_128 1 -#define AES_KEYLEN_192 2 -#define AES_KEYLEN_256 4 - -static char keylen_flag = 0; +int has_aes_128 = 0; +int has_aes_192 = 0; +int has_aes_256 = 0; struct s390_aes_ctx { u8 iv[AES_BLOCK_SIZE]; @@ -49,19 +47,20 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, switch (key_len) { case 16: - if (!(keylen_flag & AES_KEYLEN_128)) + if (!has_aes_128) goto fail; break; case 24: - if (!(keylen_flag & AES_KEYLEN_192)) + if (!has_aes_192) goto fail; break; case 32: - if (!(keylen_flag & AES_KEYLEN_256)) + if (!has_aes_256) goto fail; break; default: + /* invalid key length */ goto fail; break; } @@ -323,32 +322,34 @@ static int __init aes_init(void) int ret; if (crypt_s390_func_available(KM_AES_128_ENCRYPT)) - keylen_flag |= AES_KEYLEN_128; + has_aes_128 = 1; if (crypt_s390_func_available(KM_AES_192_ENCRYPT)) - keylen_flag |= AES_KEYLEN_192; + has_aes_192 = 1; if (crypt_s390_func_available(KM_AES_256_ENCRYPT)) - keylen_flag |= AES_KEYLEN_256; - - if (!keylen_flag) - return -EOPNOTSUPP; + has_aes_256 = 1; - /* z9 109 and z9 BC/EC only support 128 bit key length */ - if (keylen_flag == AES_KEYLEN_128) - printk(KERN_INFO - "aes_s390: hardware acceleration only available for" - "128 bit keys\n"); + if (!has_aes_128 && !has_aes_192 && !has_aes_256) + return -ENOSYS; ret = crypto_register_alg(&aes_alg); - if (ret) + if (ret != 0) { + printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n"); goto aes_err; + } ret = crypto_register_alg(&ecb_aes_alg); - if (ret) + if (ret != 0) { + printk(KERN_INFO + "crypt_s390: ecb-aes-s390 couldn't be loaded.\n"); goto ecb_aes_err; + } ret = crypto_register_alg(&cbc_aes_alg); - if (ret) + if (ret != 0) { + printk(KERN_INFO + "crypt_s390: cbc-aes-s390 couldn't be loaded.\n"); goto cbc_aes_err; + } out: return ret; diff --git a/trunk/arch/s390/crypto/crypt_s390.h b/trunk/arch/s390/crypto/crypt_s390.h index 2775d2618332..2b137089f625 100644 --- a/trunk/arch/s390/crypto/crypt_s390.h +++ b/trunk/arch/s390/crypto/crypt_s390.h @@ -3,9 +3,8 @@ * * Support for s390 cryptographic instructions. * - * Copyright IBM Corp. 2003,2007 - * Author(s): Thomas Spatzier - * Jan Glauber (jan.glauber@de.ibm.com) + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) * * 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 @@ -33,8 +32,7 @@ enum crypt_s390_operations { CRYPT_S390_KMAC = 0x0500 }; -/* - * function codes for KM (CIPHER MESSAGE) instruction +/* function codes for KM (CIPHER MESSAGE) instruction * 0x80 is the decipher modifier bit */ enum crypt_s390_km_func { @@ -53,8 +51,7 @@ enum crypt_s390_km_func { KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, }; -/* - * function codes for KMC (CIPHER MESSAGE WITH CHAINING) +/* function codes for KMC (CIPHER MESSAGE WITH CHAINING) * instruction */ enum crypt_s390_kmc_func { @@ -71,11 +68,9 @@ enum crypt_s390_kmc_func { KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80, KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14, KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80, - KMC_PRNG = CRYPT_S390_KMC | 0x43, }; -/* - * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) +/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) * instruction */ enum crypt_s390_kimd_func { @@ -84,8 +79,7 @@ enum crypt_s390_kimd_func { KIMD_SHA_256 = CRYPT_S390_KIMD | 2, }; -/* - * function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) +/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) * instruction */ enum crypt_s390_klmd_func { @@ -94,8 +88,7 @@ enum crypt_s390_klmd_func { KLMD_SHA_256 = CRYPT_S390_KLMD | 2, }; -/* - * function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) +/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) * instruction */ enum crypt_s390_kmac_func { @@ -105,219 +98,229 @@ enum crypt_s390_kmac_func { KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 }; -/** - * crypt_s390_km: - * @func: the function code passed to KM; see crypt_s390_km_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @src: address of source memory area - * @src_len: length of src operand in bytes - * +/* status word for s390 crypto instructions' QUERY functions */ +struct crypt_s390_query_status { + u64 high; + u64 low; +}; + +/* * Executes the KM (CIPHER MESSAGE) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for encryption/decryption funcs + * @param func: the function code passed to KM; see crypt_s390_km_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs */ -static inline int crypt_s390_km(long func, void *param, - u8 *dest, const u8 *src, long src_len) +static inline int +crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) { register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; - register u8 *__dest asm("4") = dest; + register u8* __dest asm("4") = dest; int ret; asm volatile( "0: .insn rre,0xb92e0000,%3,%1 \n" /* KM opcode */ "1: brc 1,0b \n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) EX_TABLE(1b,2b) + " ahi %0,%h7\n" + "2: ahi %0,%h8\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,2b) : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); + : "d" (__func), "a" (__param), "0" (-EFAULT), + "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory"); if (ret < 0) return ret; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; } -/** - * crypt_s390_kmc: - * @func: the function code passed to KM; see crypt_s390_kmc_func - * @param: address of parameter block; see POP for details on each func - * @dest: address of destination memory area - * @src: address of source memory area - * @src_len: length of src operand in bytes - * +/* * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for encryption/decryption funcs + * @param func: the function code passed to KM; see crypt_s390_kmc_func + * @param param: address of parameter block; see POP for details on each func + * @param dest: address of destination memory area + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for encryption/decryption funcs */ -static inline int crypt_s390_kmc(long func, void *param, - u8 *dest, const u8 *src, long src_len) +static inline int +crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) { register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; - register u8 *__dest asm("4") = dest; + register u8* __dest asm("4") = dest; int ret; asm volatile( "0: .insn rre,0xb92f0000,%3,%1 \n" /* KMC opcode */ "1: brc 1,0b \n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) EX_TABLE(1b,2b) + " ahi %0,%h7\n" + "2: ahi %0,%h8\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,2b) : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); + : "d" (__func), "a" (__param), "0" (-EFAULT), + "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory"); if (ret < 0) return ret; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; } -/** - * crypt_s390_kimd: - * @func: the function code passed to KM; see crypt_s390_kimd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * +/* * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation * of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs + * @param func: the function code passed to KM; see crypt_s390_kimd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs */ -static inline int crypt_s390_kimd(long func, void *param, - const u8 *src, long src_len) +static inline int +crypt_s390_kimd(long func, void* param, const u8* src, long src_len) { register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; int ret; asm volatile( "0: .insn rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */ "1: brc 1,0b \n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) EX_TABLE(1b,2b) + " ahi %0,%h6\n" + "2: ahi %0,%h7\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,2b) : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); + : "d" (__func), "a" (__param), "0" (-EFAULT), + "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory"); if (ret < 0) return ret; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; } -/** - * crypt_s390_klmd: - * @func: the function code passed to KM; see crypt_s390_klmd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * +/* * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs + * @param func: the function code passed to KM; see crypt_s390_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs */ -static inline int crypt_s390_klmd(long func, void *param, - const u8 *src, long src_len) +static inline int +crypt_s390_klmd(long func, void* param, const u8* src, long src_len) { register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; int ret; asm volatile( "0: .insn rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */ "1: brc 1,0b \n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) EX_TABLE(1b,2b) + " ahi %0,%h6\n" + "2: ahi %0,%h7\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,2b) : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); + : "d" (__func), "a" (__param), "0" (-EFAULT), + "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory"); if (ret < 0) return ret; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; } -/** - * crypt_s390_kmac: - * @func: the function code passed to KM; see crypt_s390_klmd_func - * @param: address of parameter block; see POP for details on each func - * @src: address of source memory area - * @src_len: length of src operand in bytes - * +/* * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation * of the CPU. - * - * Returns -1 for failure, 0 for the query func, number of processed - * bytes for digest funcs + * @param func: the function code passed to KM; see crypt_s390_klmd_func + * @param param: address of parameter block; see POP for details on each func + * @param src: address of source memory area + * @param src_len: length of src operand in bytes + * @returns < zero for failure, 0 for the query func, number of processed bytes + * for digest funcs */ -static inline int crypt_s390_kmac(long func, void *param, - const u8 *src, long src_len) +static inline int +crypt_s390_kmac(long func, void* param, const u8* src, long src_len) { register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; - register void *__param asm("1") = param; - register const u8 *__src asm("2") = src; + register void* __param asm("1") = param; + register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; int ret; asm volatile( "0: .insn rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */ "1: brc 1,0b \n" /* handle partial completion */ - " la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) EX_TABLE(1b,2b) + " ahi %0,%h6\n" + "2: ahi %0,%h7\n" + "3:\n" + EX_TABLE(0b,3b) EX_TABLE(1b,2b) : "=d" (ret), "+a" (__src), "+d" (__src_len) - : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory"); + : "d" (__func), "a" (__param), "0" (-EFAULT), + "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory"); if (ret < 0) return ret; return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len; } /** - * crypt_s390_func_available: - * @func: the function code of the specific function; 0 if op in general - * * Tests if a specific crypto function is implemented on the machine. - * - * Returns 1 if func available; 0 if func or op in general not available + * @param func: the function code of the specific function; 0 if op in general + * @return 1 if func available; 0 if func or op in general not available */ -static inline int crypt_s390_func_available(int func) +static inline int +crypt_s390_func_available(int func) { - unsigned char status[16]; int ret; - switch (func & CRYPT_S390_OP_MASK) { - case CRYPT_S390_KM: - ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_S390_KMC: - ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); - break; - case CRYPT_S390_KIMD: - ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); - break; - case CRYPT_S390_KLMD: - ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); - break; - case CRYPT_S390_KMAC: - ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); - break; - default: - return 0; + struct crypt_s390_query_status status = { + .high = 0, + .low = 0 + }; + switch (func & CRYPT_S390_OP_MASK){ + case CRYPT_S390_KM: + ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_S390_KMC: + ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); + break; + case CRYPT_S390_KIMD: + ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); + break; + case CRYPT_S390_KLMD: + ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); + break; + case CRYPT_S390_KMAC: + ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); + break; + default: + ret = 0; + return ret; } - if (ret < 0) - return 0; - func &= CRYPT_S390_FUNC_MASK; - func &= 0x7f; /* mask modifier bit */ - return (status[func >> 3] & (0x80 >> (func & 7))) != 0; + if (ret >= 0){ + func &= CRYPT_S390_FUNC_MASK; + func &= 0x7f; //mask modifier bit + if (func < 64){ + ret = (status.high >> (64 - func - 1)) & 0x1; + } else { + ret = (status.low >> (128 - func - 1)) & 0x1; + } + } else { + ret = 0; + } + return ret; } -#endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */ +#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H diff --git a/trunk/arch/s390/crypto/crypt_s390_query.c b/trunk/arch/s390/crypto/crypt_s390_query.c new file mode 100644 index 000000000000..54fb11d7fadd --- /dev/null +++ b/trunk/arch/s390/crypto/crypt_s390_query.c @@ -0,0 +1,129 @@ +/* + * Cryptographic API. + * + * Support for s390 cryptographic instructions. + * Testing module for querying processor crypto capabilities. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * 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. + * + */ +#include +#include +#include +#include +#include "crypt_s390.h" + +static void query_available_functions(void) +{ + printk(KERN_INFO "#####################\n"); + + /* query available KM functions */ + printk(KERN_INFO "KM_QUERY: %d\n", + crypt_s390_func_available(KM_QUERY)); + printk(KERN_INFO "KM_DEA: %d\n", + crypt_s390_func_available(KM_DEA_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_128: %d\n", + crypt_s390_func_available(KM_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_192: %d\n", + crypt_s390_func_available(KM_TDEA_192_ENCRYPT)); + printk(KERN_INFO "KM_AES_128: %d\n", + crypt_s390_func_available(KM_AES_128_ENCRYPT)); + printk(KERN_INFO "KM_AES_192: %d\n", + crypt_s390_func_available(KM_AES_192_ENCRYPT)); + printk(KERN_INFO "KM_AES_256: %d\n", + crypt_s390_func_available(KM_AES_256_ENCRYPT)); + + /* query available KMC functions */ + printk(KERN_INFO "KMC_QUERY: %d\n", + crypt_s390_func_available(KMC_QUERY)); + printk(KERN_INFO "KMC_DEA: %d\n", + crypt_s390_func_available(KMC_DEA_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_128: %d\n", + crypt_s390_func_available(KMC_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_192: %d\n", + crypt_s390_func_available(KMC_TDEA_192_ENCRYPT)); + printk(KERN_INFO "KMC_AES_128: %d\n", + crypt_s390_func_available(KMC_AES_128_ENCRYPT)); + printk(KERN_INFO "KMC_AES_192: %d\n", + crypt_s390_func_available(KMC_AES_192_ENCRYPT)); + printk(KERN_INFO "KMC_AES_256: %d\n", + crypt_s390_func_available(KMC_AES_256_ENCRYPT)); + + /* query available KIMD functions */ + printk(KERN_INFO "KIMD_QUERY: %d\n", + crypt_s390_func_available(KIMD_QUERY)); + printk(KERN_INFO "KIMD_SHA_1: %d\n", + crypt_s390_func_available(KIMD_SHA_1)); + printk(KERN_INFO "KIMD_SHA_256: %d\n", + crypt_s390_func_available(KIMD_SHA_256)); + + /* query available KLMD functions */ + printk(KERN_INFO "KLMD_QUERY: %d\n", + crypt_s390_func_available(KLMD_QUERY)); + printk(KERN_INFO "KLMD_SHA_1: %d\n", + crypt_s390_func_available(KLMD_SHA_1)); + printk(KERN_INFO "KLMD_SHA_256: %d\n", + crypt_s390_func_available(KLMD_SHA_256)); + + /* query available KMAC functions */ + printk(KERN_INFO "KMAC_QUERY: %d\n", + crypt_s390_func_available(KMAC_QUERY)); + printk(KERN_INFO "KMAC_DEA: %d\n", + crypt_s390_func_available(KMAC_DEA)); + printk(KERN_INFO "KMAC_TDEA_128: %d\n", + crypt_s390_func_available(KMAC_TDEA_128)); + printk(KERN_INFO "KMAC_TDEA_192: %d\n", + crypt_s390_func_available(KMAC_TDEA_192)); +} + +static int init(void) +{ + struct crypt_s390_query_status status = { + .high = 0, + .low = 0 + }; + + printk(KERN_INFO "crypt_s390: querying available crypto functions\n"); + crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KM:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KMC:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KIMD:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KLMD:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); + printk(KERN_INFO "KMAC:\t%016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + + query_available_functions(); + return -ECANCELED; +} + +static void __exit cleanup(void) +{ +} + +module_init(init); +module_exit(cleanup); + +MODULE_LICENSE("GPL"); diff --git a/trunk/arch/s390/crypto/des_check_key.c b/trunk/arch/s390/crypto/des_check_key.c index 5706af266442..e3f5c5f238fe 100644 --- a/trunk/arch/s390/crypto/des_check_key.c +++ b/trunk/arch/s390/crypto/des_check_key.c @@ -10,9 +10,8 @@ * scatterlist interface. Changed LGPL to GPL per section 3 of the LGPL. * * s390 Version: - * Copyright IBM Corp. 2003 - * Author(s): Thomas Spatzier - * Jan Glauber (jan.glauber@de.ibm.com) + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) * * Derived from "crypto/des.c" * Copyright (c) 1992 Dana L. How. @@ -31,7 +30,6 @@ #include #include #include -#include "crypto_des.h" #define ROR(d,c,o) ((d) = (d) >> (c) | (d) << (o)) diff --git a/trunk/arch/s390/crypto/des_s390.c b/trunk/arch/s390/crypto/des_s390.c index ea22707f435f..2aba04852fe3 100644 --- a/trunk/arch/s390/crypto/des_s390.c +++ b/trunk/arch/s390/crypto/des_s390.c @@ -3,9 +3,9 @@ * * s390 implementation of the DES Cipher Algorithm. * - * Copyright IBM Corp. 2003,2007 - * Author(s): Thomas Spatzier - * Jan Glauber (jan.glauber@de.ibm.com) + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * * * 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 @@ -557,7 +557,7 @@ static int init(void) if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)) - return -EOPNOTSUPP; + return -ENOSYS; ret = crypto_register_alg(&des_alg); if (ret) diff --git a/trunk/arch/s390/crypto/prng.c b/trunk/arch/s390/crypto/prng.c deleted file mode 100644 index 8eb3a1aedc22..000000000000 --- a/trunk/arch/s390/crypto/prng.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright IBM Corp. 2006,2007 - * Author(s): Jan Glauber - * Driver for the s390 pseudo random number generator - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "crypt_s390.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jan Glauber "); -MODULE_DESCRIPTION("s390 PRNG interface"); - -static int prng_chunk_size = 256; -module_param(prng_chunk_size, int, S_IRUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes"); - -static int prng_entropy_limit = 4096; -module_param(prng_entropy_limit, int, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); -MODULE_PARM_DESC(prng_entropy_limit, - "PRNG add entropy after that much bytes were produced"); - -/* - * Any one who considers arithmetical methods of producing random digits is, - * of course, in a state of sin. -- John von Neumann - */ - -struct s390_prng_data { - unsigned long count; /* how many bytes were produced */ - char *buf; -}; - -static struct s390_prng_data *p; - -/* copied from libica, use a non-zero initial parameter block */ -static unsigned char parm_block[32] = { -0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4, -0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0, -}; - -static int prng_open(struct inode *inode, struct file *file) -{ - return nonseekable_open(inode, file); -} - -static void prng_add_entropy(void) -{ - __u64 entropy[4]; - unsigned int i; - int ret; - - for (i = 0; i < 16; i++) { - ret = crypt_s390_kmc(KMC_PRNG, parm_block, (char *)entropy, - (char *)entropy, sizeof(entropy)); - BUG_ON(ret < 0 || ret != sizeof(entropy)); - memcpy(parm_block, entropy, sizeof(entropy)); - } -} - -static void prng_seed(int nbytes) -{ - char buf[16]; - int i = 0; - - BUG_ON(nbytes > 16); - get_random_bytes(buf, nbytes); - - /* Add the entropy */ - while (nbytes >= 8) { - *((__u64 *)parm_block) ^= *((__u64 *)buf+i*8); - prng_add_entropy(); - i += 8; - nbytes -= 8; - } - prng_add_entropy(); -} - -static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes, - loff_t *ppos) -{ - int chunk, n; - int ret = 0; - int tmp; - - /* nbytes can be arbitrary long, we spilt it into chunks */ - while (nbytes) { - /* same as in extract_entropy_user in random.c */ - if (need_resched()) { - if (signal_pending(current)) { - if (ret == 0) - ret = -ERESTARTSYS; - break; - } - schedule(); - } - - /* - * we lose some random bytes if an attacker issues - * reads < 8 bytes, but we don't care - */ - chunk = min_t(int, nbytes, prng_chunk_size); - - /* PRNG only likes multiples of 8 bytes */ - n = (chunk + 7) & -8; - - if (p->count > prng_entropy_limit) - prng_seed(8); - - /* if the CPU supports PRNG stckf is present too */ - asm volatile(".insn s,0xb27c0000,%0" - : "=m" (*((unsigned long long *)p->buf)) : : "cc"); - - /* - * Beside the STCKF the input for the TDES-EDE is the output - * of the last operation. We differ here from X9.17 since we - * only store one timestamp into the buffer. Padding the whole - * buffer with timestamps does not improve security, since - * successive stckf have nearly constant offsets. - * If an attacker knows the first timestamp it would be - * trivial to guess the additional values. One timestamp - * is therefore enough and still guarantees unique input values. - * - * Note: you can still get strict X9.17 conformity by setting - * prng_chunk_size to 8 bytes. - */ - tmp = crypt_s390_kmc(KMC_PRNG, parm_block, p->buf, p->buf, n); - BUG_ON((tmp < 0) || (tmp != n)); - - p->count += n; - - if (copy_to_user(ubuf, p->buf, chunk)) - return -EFAULT; - - nbytes -= chunk; - ret += chunk; - ubuf += chunk; - } - return ret; -} - -static struct file_operations prng_fops = { - .owner = THIS_MODULE, - .open = &prng_open, - .release = NULL, - .read = &prng_read, -}; - -static struct miscdevice prng_dev = { - .name = "prandom", - .minor = MISC_DYNAMIC_MINOR, - .fops = &prng_fops, -}; - -static int __init prng_init(void) -{ - int ret; - - /* check if the CPU has a PRNG */ - if (!crypt_s390_func_available(KMC_PRNG)) - return -EOPNOTSUPP; - - if (prng_chunk_size < 8) - return -EINVAL; - - p = kmalloc(sizeof(struct s390_prng_data), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->count = 0; - - p->buf = kmalloc(prng_chunk_size, GFP_KERNEL); - if (!p->buf) { - ret = -ENOMEM; - goto out_free; - } - - /* initialize the PRNG, add 128 bits of entropy */ - prng_seed(16); - - ret = misc_register(&prng_dev); - if (ret) { - printk(KERN_WARNING - "Could not register misc device for PRNG.\n"); - goto out_buf; - } - return 0; - -out_buf: - kfree(p->buf); -out_free: - kfree(p); - return ret; -} - -static void __exit prng_exit(void) -{ - /* wipe me */ - memset(p->buf, 0, prng_chunk_size); - kfree(p->buf); - kfree(p); - - misc_deregister(&prng_dev); -} - -module_init(prng_init); -module_exit(prng_exit); diff --git a/trunk/arch/s390/crypto/sha1_s390.c b/trunk/arch/s390/crypto/sha1_s390.c index 969639f31977..49ca8690ee39 100644 --- a/trunk/arch/s390/crypto/sha1_s390.c +++ b/trunk/arch/s390/crypto/sha1_s390.c @@ -8,9 +8,8 @@ * implementation written by Steve Reid. * * s390 Version: - * Copyright IBM Corp. 2003,2007 - * Author(s): Thomas Spatzier - * Jan Glauber (jan.glauber@de.ibm.com) + * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) * * Derived from "crypto/sha1.c" * Copyright (c) Alan Smithee. @@ -44,14 +43,16 @@ struct crypt_s390_sha1_ctx { static void sha1_init(struct crypto_tfm *tfm) { struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm); - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; + static const u32 initstate[5] = { + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0 + }; ctx->count = 0; + memcpy(ctx->state, &initstate, sizeof(initstate)); ctx->buf_len = 0; } @@ -62,13 +63,13 @@ static void sha1_update(struct crypto_tfm *tfm, const u8 *data, long imd_len; sctx = crypto_tfm_ctx(tfm); - sctx->count += len * 8; /* message bit length */ + sctx->count += len * 8; //message bit length - /* anything in buffer yet? -> must be completed */ + //anything in buffer yet? -> must be completed if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) { - /* complete full block and hash */ + //complete full block and hash memcpy(sctx->buffer + sctx->buf_len, data, - SHA1_BLOCK_SIZE - sctx->buf_len); + SHA1_BLOCK_SIZE - sctx->buf_len); crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, SHA1_BLOCK_SIZE); data += SHA1_BLOCK_SIZE - sctx->buf_len; @@ -76,36 +77,37 @@ static void sha1_update(struct crypto_tfm *tfm, const u8 *data, sctx->buf_len = 0; } - /* rest of data contains full blocks? */ + //rest of data contains full blocks? imd_len = len & ~0x3ful; - if (imd_len) { + if (imd_len){ crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); data += imd_len; len -= imd_len; } - /* anything left? store in buffer */ - if (len) { + //anything left? store in buffer + if (len){ memcpy(sctx->buffer + sctx->buf_len , data, len); sctx->buf_len += len; } } -static void pad_message(struct crypt_s390_sha1_ctx* sctx) +static void +pad_message(struct crypt_s390_sha1_ctx* sctx) { int index; index = sctx->buf_len; - sctx->buf_len = (sctx->buf_len < 56) ? - SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; - /* start pad with 1 */ + sctx->buf_len = (sctx->buf_len < 56)? + SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE; + //start pad with 1 sctx->buffer[index] = 0x80; - /* pad with zeros */ + //pad with zeros index++; memset(sctx->buffer + index, 0x00, sctx->buf_len - index); - /* append length */ + //append length memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count, - sizeof sctx->count); + sizeof sctx->count); } /* Add padding and return the message digest. */ @@ -113,40 +115,47 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out) { struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); - /* must perform manual padding */ + //must perform manual padding pad_message(sctx); crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); - /* copy digest to out */ + //copy digest to out memcpy(out, sctx->state, SHA1_DIGEST_SIZE); - /* wipe context */ + /* Wipe context */ memset(sctx, 0, sizeof *sctx); } static struct crypto_alg alg = { .cra_name = "sha1", - .cra_driver_name= "sha1-s390", + .cra_driver_name = "sha1-s390", .cra_priority = CRYPT_S390_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA1_DIGEST_SIZE, - .dia_init = sha1_init, - .dia_update = sha1_update, - .dia_final = sha1_final } } + .dia_init = sha1_init, + .dia_update = sha1_update, + .dia_final = sha1_final } } }; -static int __init init(void) +static int +init(void) { - if (!crypt_s390_func_available(KIMD_SHA_1)) - return -EOPNOTSUPP; + int ret = -ENOSYS; - return crypto_register_alg(&alg); + if (crypt_s390_func_available(KIMD_SHA_1)){ + ret = crypto_register_alg(&alg); + if (ret == 0){ + printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n"); + } + } + return ret; } -static void __exit fini(void) +static void __exit +fini(void) { crypto_unregister_alg(&alg); } diff --git a/trunk/arch/s390/crypto/sha256_s390.c b/trunk/arch/s390/crypto/sha256_s390.c index 78436c696d37..8e4e67503fe7 100644 --- a/trunk/arch/s390/crypto/sha256_s390.c +++ b/trunk/arch/s390/crypto/sha256_s390.c @@ -4,7 +4,7 @@ * s390 implementation of the SHA256 Secure Hash Algorithm. * * s390 Version: - * Copyright IBM Corp. 2005,2007 + * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation * Author(s): Jan Glauber (jang@de.ibm.com) * * Derived from "crypto/sha256.c" @@ -143,10 +143,15 @@ static struct crypto_alg alg = { static int init(void) { + int ret; + if (!crypt_s390_func_available(KIMD_SHA_256)) - return -EOPNOTSUPP; + return -ENOSYS; - return crypto_register_alg(&alg); + ret = crypto_register_alg(&alg); + if (ret != 0) + printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded."); + return ret; } static void __exit fini(void) diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 7c621b8ef683..5368cf4a350e 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -108,8 +108,6 @@ CONFIG_DEFAULT_MIGRATION_COST=1000000 CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_AUDIT_ARCH=y -CONFIG_S390_SWITCH_AMODE=y -CONFIG_S390_EXEC_PROTECT=y # # Code generation options @@ -433,6 +431,7 @@ CONFIG_TN3270_CONSOLE=y CONFIG_TN3215=y CONFIG_TN3215_CONSOLE=y CONFIG_CCW_CONSOLE=y +CONFIG_SCLP=y CONFIG_SCLP_TTY=y CONFIG_SCLP_CONSOLE=y CONFIG_SCLP_VT220_TTY=y @@ -725,7 +724,9 @@ CONFIG_CRYPTO_MANAGER=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_S390 is not set # CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_S390 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -734,10 +735,12 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_LRW is not set # CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DES_S390 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_S390 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set @@ -752,11 +755,6 @@ CONFIG_CRYPTO_CBC=y # # Hardware crypto devices # -# CONFIG_CRYPTO_SHA1_S390 is not set -# CONFIG_CRYPTO_SHA256_S390 is not set -# CONFIG_CRYPTO_DES_S390 is not set -# CONFIG_CRYPTO_AES_S390 is not set -CONFIG_S390_PRNG=m # # Library routines diff --git a/trunk/arch/s390/hypfs/Makefile b/trunk/arch/s390/hypfs/Makefile index b08d2abf6178..f4b00cd81f7c 100644 --- a/trunk/arch/s390/hypfs/Makefile +++ b/trunk/arch/s390/hypfs/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o -s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o +s390_hypfs-objs := inode.o hypfs_diag.o diff --git a/trunk/arch/s390/hypfs/hypfs.h b/trunk/arch/s390/hypfs/hypfs.h index aea572009d60..f3dbd91965c6 100644 --- a/trunk/arch/s390/hypfs/hypfs.h +++ b/trunk/arch/s390/hypfs/hypfs.h @@ -27,13 +27,4 @@ extern struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir, const char *name, char *string); -/* LPAR Hypervisor */ -extern int hypfs_diag_init(void); -extern void hypfs_diag_exit(void); -extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root); - -/* VM Hypervisor */ -extern int hypfs_vm_init(void); -extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); - #endif /* _HYPFS_H_ */ diff --git a/trunk/arch/s390/hypfs/hypfs_diag.h b/trunk/arch/s390/hypfs/hypfs_diag.h new file mode 100644 index 000000000000..256b384aebe1 --- /dev/null +++ b/trunk/arch/s390/hypfs/hypfs_diag.h @@ -0,0 +1,16 @@ +/* + * arch/s390/hypfs_diag.h + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu + */ + +#ifndef _HYPFS_DIAG_H_ +#define _HYPFS_DIAG_H_ + +extern int hypfs_diag_init(void); +extern void hypfs_diag_exit(void); +extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root); + +#endif /* _HYPFS_DIAG_H_ */ diff --git a/trunk/arch/s390/hypfs/hypfs_vm.c b/trunk/arch/s390/hypfs/hypfs_vm.c deleted file mode 100644 index d01fc8f799f0..000000000000 --- a/trunk/arch/s390/hypfs/hypfs_vm.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Hypervisor filesystem for Linux on s390. z/VM implementation. - * - * Copyright (C) IBM Corp. 2006 - * Author(s): Michael Holzheu - */ - -#include -#include -#include -#include -#include -#include "hypfs.h" - -#define NAME_LEN 8 - -static char local_guest[] = " "; -static char all_guests[] = "* "; -static char *guest_query; - -struct diag2fc_data { - __u32 version; - __u32 flags; - __u64 used_cpu; - __u64 el_time; - __u64 mem_min_kb; - __u64 mem_max_kb; - __u64 mem_share_kb; - __u64 mem_used_kb; - __u32 pcpus; - __u32 lcpus; - __u32 vcpus; - __u32 cpu_min; - __u32 cpu_max; - __u32 cpu_shares; - __u32 cpu_use_samp; - __u32 cpu_delay_samp; - __u32 page_wait_samp; - __u32 idle_samp; - __u32 other_samp; - __u32 total_samp; - char guest_name[NAME_LEN]; -}; - -struct diag2fc_parm_list { - char userid[NAME_LEN]; - char aci_grp[NAME_LEN]; - __u64 addr; - __u32 size; - __u32 fmt; -}; - -static int diag2fc(int size, char* query, void *addr) -{ - unsigned long residual_cnt; - unsigned long rc; - struct diag2fc_parm_list parm_list; - - memcpy(parm_list.userid, query, NAME_LEN); - ASCEBC(parm_list.userid, NAME_LEN); - parm_list.addr = (unsigned long) addr ; - parm_list.size = size; - parm_list.fmt = 0x02; - memset(parm_list.aci_grp, 0x40, NAME_LEN); - rc = -1; - - asm volatile( - " diag %0,%1,0x2fc\n" - "0:\n" - EX_TABLE(0b,0b) - : "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory"); - - if ((rc != 0 ) && (rc != -2)) - return rc; - else - return -residual_cnt; -} - -static struct diag2fc_data *diag2fc_store(char *query, int *count) -{ - int size; - struct diag2fc_data *data; - - do { - size = diag2fc(0, query, NULL); - if (size < 0) - return ERR_PTR(-EACCES); - data = vmalloc(size); - if (!data) - return ERR_PTR(-ENOMEM); - if (diag2fc(size, query, data) == 0) - break; - vfree(data); - } while (1); - *count = (size / sizeof(*data)); - - return data; -} - -static void diag2fc_free(void *data) -{ - vfree(data); -} - -#define ATTRIBUTE(sb, dir, name, member) \ -do { \ - void *rc; \ - rc = hypfs_create_u64(sb, dir, name, member); \ - if (IS_ERR(rc)) \ - return PTR_ERR(rc); \ -} while(0) - -static int hpyfs_vm_create_guest(struct super_block *sb, - struct dentry *systems_dir, - struct diag2fc_data *data) -{ - char guest_name[NAME_LEN + 1] = {}; - struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir; - int dedicated_flag, capped_value; - - capped_value = (data->flags & 0x00000006) >> 1; - dedicated_flag = (data->flags & 0x00000008) >> 3; - - /* guest dir */ - memcpy(guest_name, data->guest_name, NAME_LEN); - EBCASC(guest_name, NAME_LEN); - strstrip(guest_name); - guest_dir = hypfs_mkdir(sb, systems_dir, guest_name); - if (IS_ERR(guest_dir)) - return PTR_ERR(guest_dir); - ATTRIBUTE(sb, guest_dir, "onlinetime_us", data->el_time); - - /* logical cpu information */ - cpus_dir = hypfs_mkdir(sb, guest_dir, "cpus"); - if (IS_ERR(cpus_dir)) - return PTR_ERR(cpus_dir); - ATTRIBUTE(sb, cpus_dir, "cputime_us", data->used_cpu); - ATTRIBUTE(sb, cpus_dir, "capped", capped_value); - ATTRIBUTE(sb, cpus_dir, "dedicated", dedicated_flag); - ATTRIBUTE(sb, cpus_dir, "count", data->vcpus); - ATTRIBUTE(sb, cpus_dir, "weight_min", data->cpu_min); - ATTRIBUTE(sb, cpus_dir, "weight_max", data->cpu_max); - ATTRIBUTE(sb, cpus_dir, "weight_cur", data->cpu_shares); - - /* memory information */ - mem_dir = hypfs_mkdir(sb, guest_dir, "mem"); - if (IS_ERR(mem_dir)) - return PTR_ERR(mem_dir); - ATTRIBUTE(sb, mem_dir, "min_KiB", data->mem_min_kb); - ATTRIBUTE(sb, mem_dir, "max_KiB", data->mem_max_kb); - ATTRIBUTE(sb, mem_dir, "used_KiB", data->mem_used_kb); - ATTRIBUTE(sb, mem_dir, "share_KiB", data->mem_share_kb); - - /* samples */ - samples_dir = hypfs_mkdir(sb, guest_dir, "samples"); - if (IS_ERR(samples_dir)) - return PTR_ERR(samples_dir); - ATTRIBUTE(sb, samples_dir, "cpu_using", data->cpu_use_samp); - ATTRIBUTE(sb, samples_dir, "cpu_delay", data->cpu_delay_samp); - ATTRIBUTE(sb, samples_dir, "mem_delay", data->page_wait_samp); - ATTRIBUTE(sb, samples_dir, "idle", data->idle_samp); - ATTRIBUTE(sb, samples_dir, "other", data->other_samp); - ATTRIBUTE(sb, samples_dir, "total", data->total_samp); - return 0; -} - -int hypfs_vm_create_files(struct super_block *sb, struct dentry *root) -{ - struct dentry *dir, *file; - struct diag2fc_data *data; - int rc, i, count = 0; - - data = diag2fc_store(guest_query, &count); - if (IS_ERR(data)) - return PTR_ERR(data); - - /* Hpervisor Info */ - dir = hypfs_mkdir(sb, root, "hyp"); - if (IS_ERR(dir)) { - rc = PTR_ERR(dir); - goto failed; - } - file = hypfs_create_str(sb, dir, "type", "z/VM Hypervisor"); - if (IS_ERR(file)) { - rc = PTR_ERR(file); - goto failed; - } - - /* physical cpus */ - dir = hypfs_mkdir(sb, root, "cpus"); - if (IS_ERR(dir)) { - rc = PTR_ERR(dir); - goto failed; - } - file = hypfs_create_u64(sb, dir, "count", data->lcpus); - if (IS_ERR(file)) { - rc = PTR_ERR(file); - goto failed; - } - - /* guests */ - dir = hypfs_mkdir(sb, root, "systems"); - if (IS_ERR(dir)) { - rc = PTR_ERR(dir); - goto failed; - } - - for (i = 0; i < count; i++) { - rc = hpyfs_vm_create_guest(sb, dir, &(data[i])); - if (rc) - goto failed; - } - diag2fc_free(data); - return 0; - -failed: - diag2fc_free(data); - return rc; -} - -int hypfs_vm_init(void) -{ - if (diag2fc(0, all_guests, NULL) > 0) - guest_query = all_guests; - else if (diag2fc(0, local_guest, NULL) > 0) - guest_query = local_guest; - else - return -EACCES; - - return 0; -} diff --git a/trunk/arch/s390/hypfs/inode.c b/trunk/arch/s390/hypfs/inode.c index a4fda7b53640..b6716c4b9934 100644 --- a/trunk/arch/s390/hypfs/inode.c +++ b/trunk/arch/s390/hypfs/inode.c @@ -19,6 +19,7 @@ #include #include #include "hypfs.h" +#include "hypfs_diag.h" #define HYPFS_MAGIC 0x687970 /* ASCII 'hyp' */ #define TMP_SIZE 64 /* size of temporary buffers */ @@ -191,10 +192,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov, goto out; } hypfs_delete_tree(sb->s_root); - if (MACHINE_IS_VM) - rc = hypfs_vm_create_files(sb, sb->s_root); - else - rc = hypfs_diag_create_files(sb, sb->s_root); + rc = hypfs_diag_create_files(sb, sb->s_root); if (rc) { printk(KERN_ERR "hypfs: Update failed\n"); hypfs_delete_tree(sb->s_root); @@ -291,10 +289,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent) rc = -ENOMEM; goto err_alloc; } - if (MACHINE_IS_VM) - rc = hypfs_vm_create_files(sb, root_dentry); - else - rc = hypfs_diag_create_files(sb, root_dentry); + rc = hypfs_diag_create_files(sb, root_dentry); if (rc) goto err_tree; sbi->update_file = hypfs_create_update_file(sb, root_dentry); @@ -467,15 +462,11 @@ static int __init hypfs_init(void) { int rc; - if (MACHINE_IS_VM) { - if (hypfs_vm_init()) - /* no diag 2fc, just exit */ - return -ENODATA; - } else { - if (hypfs_diag_init()) { - rc = -ENODATA; - goto fail_diag; - } + if (MACHINE_IS_VM) + return -ENODATA; + if (hypfs_diag_init()) { + rc = -ENODATA; + goto fail_diag; } kset_set_kset_s(&s390_subsys, hypervisor_subsys); rc = subsystem_register(&s390_subsys); @@ -489,8 +480,7 @@ static int __init hypfs_init(void) fail_filesystem: subsystem_unregister(&s390_subsys); fail_sysfs: - if (!MACHINE_IS_VM) - hypfs_diag_exit(); + hypfs_diag_exit(); fail_diag: printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc); return rc; @@ -498,8 +488,7 @@ static int __init hypfs_init(void) static void __exit hypfs_exit(void) { - if (!MACHINE_IS_VM) - hypfs_diag_exit(); + hypfs_diag_exit(); unregister_filesystem(&hypfs_type); subsystem_unregister(&s390_subsys); } diff --git a/trunk/arch/s390/kernel/Makefile b/trunk/arch/s390/kernel/Makefile index 5492d25d7d69..a81881c9b297 100644 --- a/trunk/arch/s390/kernel/Makefile +++ b/trunk/arch/s390/kernel/Makefile @@ -4,9 +4,9 @@ EXTRA_AFLAGS := -traditional -obj-y := bitmap.o traps.o time.o process.o base.o early.o \ +obj-y := bitmap.o traps.o time.o process.o reset.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o irq.o ipl.o + semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/trunk/arch/s390/kernel/base.S b/trunk/arch/s390/kernel/base.S deleted file mode 100644 index dc7e5259770f..000000000000 --- a/trunk/arch/s390/kernel/base.S +++ /dev/null @@ -1,150 +0,0 @@ -/* - * arch/s390/kernel/base.S - * - * Copyright IBM Corp. 2006,2007 - * Author(s): Heiko Carstens - * Michael Holzheu - */ - -#include -#include - -#ifdef CONFIG_64BIT - - .globl s390_base_mcck_handler -s390_base_mcck_handler: - basr %r13,0 -0: lg %r15,__LC_PANIC_STACK # load panic stack - aghi %r15,-STACK_FRAME_OVERHEAD - larl %r1,s390_base_mcck_handler_fn - lg %r1,0(%r1) - ltgr %r1,%r1 - jz 1f - basr %r14,%r1 -1: la %r1,4095 - lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) - lpswe __LC_MCK_OLD_PSW - - .section .bss - .globl s390_base_mcck_handler_fn -s390_base_mcck_handler_fn: - .quad 0 - .previous - - .globl s390_base_ext_handler -s390_base_ext_handler: - stmg %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: aghi %r15,-STACK_FRAME_OVERHEAD - larl %r1,s390_base_ext_handler_fn - lg %r1,0(%r1) - ltgr %r1,%r1 - jz 1f - basr %r14,%r1 -1: lmg %r0,%r15,__LC_SAVE_AREA - ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit - lpswe __LC_EXT_OLD_PSW - - .section .bss - .globl s390_base_ext_handler_fn -s390_base_ext_handler_fn: - .quad 0 - .previous - - .globl s390_base_pgm_handler -s390_base_pgm_handler: - stmg %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: aghi %r15,-STACK_FRAME_OVERHEAD - larl %r1,s390_base_pgm_handler_fn - lg %r1,0(%r1) - ltgr %r1,%r1 - jz 1f - basr %r14,%r1 - lmg %r0,%r15,__LC_SAVE_AREA - lpswe __LC_PGM_OLD_PSW -1: lpswe disabled_wait_psw-0b(%r13) - - .align 8 -disabled_wait_psw: - .quad 0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler - - .section .bss - .globl s390_base_pgm_handler_fn -s390_base_pgm_handler_fn: - .quad 0 - .previous - -#else /* CONFIG_64BIT */ - - .globl s390_base_mcck_handler -s390_base_mcck_handler: - basr %r13,0 -0: l %r15,__LC_PANIC_STACK # load panic stack - ahi %r15,-STACK_FRAME_OVERHEAD - l %r1,2f-0b(%r13) - l %r1,0(%r1) - ltr %r1,%r1 - jz 1f - basr %r14,%r1 -1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA - lpsw __LC_MCK_OLD_PSW - -2: .long s390_base_mcck_handler_fn - - .section .bss - .globl s390_base_mcck_handler_fn -s390_base_mcck_handler_fn: - .long 0 - .previous - - .globl s390_base_ext_handler -s390_base_ext_handler: - stm %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: ahi %r15,-STACK_FRAME_OVERHEAD - l %r1,2f-0b(%r13) - l %r1,0(%r1) - ltr %r1,%r1 - jz 1f - basr %r14,%r1 -1: lm %r0,%r15,__LC_SAVE_AREA - ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit - lpsw __LC_EXT_OLD_PSW - -2: .long s390_base_ext_handler_fn - - .section .bss - .globl s390_base_ext_handler_fn -s390_base_ext_handler_fn: - .long 0 - .previous - - .globl s390_base_pgm_handler -s390_base_pgm_handler: - stm %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: ahi %r15,-STACK_FRAME_OVERHEAD - l %r1,2f-0b(%r13) - l %r1,0(%r1) - ltr %r1,%r1 - jz 1f - basr %r14,%r1 - lm %r0,%r15,__LC_SAVE_AREA - lpsw __LC_PGM_OLD_PSW - -1: lpsw disabled_wait_psw-0b(%r13) - -2: .long s390_base_pgm_handler_fn - -disabled_wait_psw: - .align 8 - .long 0x000a0000,0x00000000 + s390_base_pgm_handler - - .section .bss - .globl s390_base_pgm_handler_fn -s390_base_pgm_handler_fn: - .long 0 - .previous - -#endif /* CONFIG_64BIT */ diff --git a/trunk/arch/s390/kernel/binfmt_elf32.c b/trunk/arch/s390/kernel/binfmt_elf32.c index f1e40ca00d8d..5c46054195cb 100644 --- a/trunk/arch/s390/kernel/binfmt_elf32.c +++ b/trunk/arch/s390/kernel/binfmt_elf32.c @@ -192,7 +192,7 @@ MODULE_AUTHOR("Gerhard Tonn "); #undef cputime_to_timeval #define cputime_to_timeval cputime_to_compat_timeval -static inline void +static __inline__ void cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { value->tv_usec = cputime % 1000000; diff --git a/trunk/arch/s390/kernel/compat_exec_domain.c b/trunk/arch/s390/kernel/compat_exec_domain.c index 914d49444f92..71d27c493568 100644 --- a/trunk/arch/s390/kernel/compat_exec_domain.c +++ b/trunk/arch/s390/kernel/compat_exec_domain.c @@ -12,9 +12,10 @@ #include #include -static struct exec_domain s390_exec_domain; +struct exec_domain s390_exec_domain; -static int __init s390_init (void) +static int __init +s390_init (void) { s390_exec_domain.name = "Linux/s390"; s390_exec_domain.handler = NULL; diff --git a/trunk/arch/s390/kernel/compat_linux.c b/trunk/arch/s390/kernel/compat_linux.c index 666bb6daa148..5b33f823863a 100644 --- a/trunk/arch/s390/kernel/compat_linux.c +++ b/trunk/arch/s390/kernel/compat_linux.c @@ -69,12 +69,6 @@ #include "compat_linux.h" -long psw_user32_bits = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | - PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | - PSW_MASK_PSTATE | PSW_DEFAULT_KEY); -long psw32_user_bits = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | - PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | - PSW32_MASK_PSTATE); /* For this source file, we want overflow handling. */ @@ -422,7 +416,7 @@ asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sysinfo((struct sysinfo __force __user *) &s); + ret = sys_sysinfo((struct sysinfo __user *) &s); set_fs (old_fs); err = put_user (s.uptime, &info->uptime); err |= __put_user (s.loads[0], &info->loads[0]); @@ -451,8 +445,7 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, - (struct timespec __force __user *) &t); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); set_fs (old_fs); if (put_compat_timespec(&t, interval)) return -EFAULT; @@ -479,8 +472,8 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, } set_fs (KERNEL_DS); ret = sys_rt_sigprocmask(how, - set ? (sigset_t __force __user *) &s : NULL, - oset ? (sigset_t __force __user *) &s : NULL, + set ? (sigset_t __user *) &s : NULL, + oset ? (sigset_t __user *) &s : NULL, sigsetsize); set_fs (old_fs); if (ret) return ret; @@ -506,7 +499,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize); + ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); set_fs (old_fs); if (!ret) { switch (_NSIG_WORDS) { @@ -531,7 +524,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info); + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs (old_fs); return ret; } @@ -689,7 +682,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offse set_fs(KERNEL_DS); ret = sys_sendfile(out_fd, in_fd, - offset ? (off_t __force __user *) &of : NULL, count); + offset ? (off_t __user *) &of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) @@ -710,8 +703,7 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd, set_fs(KERNEL_DS); ret = sys_sendfile64(out_fd, in_fd, - offset ? (loff_t __force __user *) &lof : NULL, - count); + offset ? (loff_t __user *) &lof : NULL, count); set_fs(old_fs); if (offset && put_user(lof, offset)) diff --git a/trunk/arch/s390/kernel/compat_linux.h b/trunk/arch/s390/kernel/compat_linux.h index e89f8c0c42a0..1a18e29668ef 100644 --- a/trunk/arch/s390/kernel/compat_linux.h +++ b/trunk/arch/s390/kernel/compat_linux.h @@ -115,6 +115,37 @@ typedef struct __u32 addr; } _psw_t32 __attribute__ ((aligned(8))); +#define PSW32_MASK_PER 0x40000000UL +#define PSW32_MASK_DAT 0x04000000UL +#define PSW32_MASK_IO 0x02000000UL +#define PSW32_MASK_EXT 0x01000000UL +#define PSW32_MASK_KEY 0x00F00000UL +#define PSW32_MASK_MCHECK 0x00040000UL +#define PSW32_MASK_WAIT 0x00020000UL +#define PSW32_MASK_PSTATE 0x00010000UL +#define PSW32_MASK_ASC 0x0000C000UL +#define PSW32_MASK_CC 0x00003000UL +#define PSW32_MASK_PM 0x00000f00UL + +#define PSW32_ADDR_AMODE31 0x80000000UL +#define PSW32_ADDR_INSN 0x7FFFFFFFUL + +#define PSW32_BASE_BITS 0x00080000UL + +#define PSW32_ASC_PRIMARY 0x00000000UL +#define PSW32_ASC_ACCREG 0x00004000UL +#define PSW32_ASC_SECONDARY 0x00008000UL +#define PSW32_ASC_HOME 0x0000C000UL + +#define PSW32_USER_BITS (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | \ + PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | \ + PSW32_MASK_PSTATE) + +#define PSW32_MASK_MERGE(CURRENT,NEW) \ + (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \ + ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM))) + + typedef struct { _psw_t32 psw; diff --git a/trunk/arch/s390/kernel/compat_signal.c b/trunk/arch/s390/kernel/compat_signal.c index 887a9881d0d0..861888ab8c13 100644 --- a/trunk/arch/s390/kernel/compat_signal.c +++ b/trunk/arch/s390/kernel/compat_signal.c @@ -275,8 +275,8 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, } set_fs (KERNEL_DS); - ret = do_sigaltstack((stack_t __force __user *) (uss ? &kss : NULL), - (stack_t __force __user *) (uoss ? &koss : NULL), + ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL), + (stack_t __user *) (uoss ? &koss : NULL), regs->gprs[15]); set_fs (old_fs); @@ -298,7 +298,7 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) _s390_regs_common32 regs32; int err, i; - regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits, + regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS, (__u32)(regs->psw.mask >> 32)); regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr; for (i = 0; i < NUM_GPRS; i++) @@ -401,7 +401,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) goto badframe; set_fs (KERNEL_DS); - do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]); + do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]); set_fs (old_fs); return regs->gprs[2]; diff --git a/trunk/arch/s390/kernel/cpcmd.c b/trunk/arch/s390/kernel/cpcmd.c index 6c89f30c8e31..a5972f1541fe 100644 --- a/trunk/arch/s390/kernel/cpcmd.c +++ b/trunk/arch/s390/kernel/cpcmd.c @@ -16,7 +16,6 @@ #include #include #include -#include static DEFINE_SPINLOCK(cpcmd_lock); static char cpcmd_buf[241]; @@ -89,8 +88,13 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) int len; unsigned long flags; - if ((virt_to_phys(response) != (unsigned long) response) || - (((unsigned long)response + rlen) >> 31)) { + if ((rlen == 0) || (response == NULL) + || !((unsigned long)response >> 31)) { + spin_lock_irqsave(&cpcmd_lock, flags); + len = __cpcmd(cmd, response, rlen, response_code); + spin_unlock_irqrestore(&cpcmd_lock, flags); + } + else { lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); if (!lowbuf) { printk(KERN_WARNING @@ -102,10 +106,6 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) spin_unlock_irqrestore(&cpcmd_lock, flags); memcpy(response, lowbuf, rlen); kfree(lowbuf); - } else { - spin_lock_irqsave(&cpcmd_lock, flags); - len = __cpcmd(cmd, response, rlen, response_code); - spin_unlock_irqrestore(&cpcmd_lock, flags); } return len; } diff --git a/trunk/arch/s390/kernel/crash.c b/trunk/arch/s390/kernel/crash.c index 8cc7c9fa64f5..926cceeae0fa 100644 --- a/trunk/arch/s390/kernel/crash.c +++ b/trunk/arch/s390/kernel/crash.c @@ -9,7 +9,6 @@ #include #include -#include void machine_crash_shutdown(struct pt_regs *regs) { diff --git a/trunk/arch/s390/kernel/debug.c b/trunk/arch/s390/kernel/debug.c index f4b62df02aa2..bb57bc0e3fc8 100644 --- a/trunk/arch/s390/kernel/debug.c +++ b/trunk/arch/s390/kernel/debug.c @@ -120,7 +120,7 @@ struct debug_view debug_hex_ascii_view = { NULL }; -static struct debug_view debug_level_view = { +struct debug_view debug_level_view = { "level", &debug_prolog_level_fn, NULL, @@ -129,7 +129,7 @@ static struct debug_view debug_level_view = { NULL }; -static struct debug_view debug_pages_view = { +struct debug_view debug_pages_view = { "pages", &debug_prolog_pages_fn, NULL, @@ -138,7 +138,7 @@ static struct debug_view debug_pages_view = { NULL }; -static struct debug_view debug_flush_view = { +struct debug_view debug_flush_view = { "flush", NULL, NULL, @@ -156,14 +156,14 @@ struct debug_view debug_sprintf_view = { NULL }; -/* used by dump analysis tools to determine version of debug feature */ + unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION; /* static globals */ static debug_info_t *debug_area_first = NULL; static debug_info_t *debug_area_last = NULL; -static DECLARE_MUTEX(debug_lock); +DECLARE_MUTEX(debug_lock); static int initialized; @@ -905,7 +905,7 @@ static struct ctl_table s390dbf_dir_table[] = { { .ctl_name = 0 } }; -static struct ctl_table_header *s390dbf_sysctl_header; +struct ctl_table_header *s390dbf_sysctl_header; void debug_stop_all(void) @@ -1300,7 +1300,8 @@ debug_input_level_fn(debug_info_t * id, struct debug_view *view, * flushes debug areas */ -static void debug_flush(debug_info_t* id, int area) +void +debug_flush(debug_info_t* id, int area) { unsigned long flags; int i,j; @@ -1510,7 +1511,8 @@ debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view, /* * clean up module */ -static void __exit debug_exit(void) +void +__exit debug_exit(void) { debugfs_remove(debug_debugfs_root_entry); unregister_sysctl_table(s390dbf_sysctl_header); diff --git a/trunk/arch/s390/kernel/early.c b/trunk/arch/s390/kernel/early.c deleted file mode 100644 index e518dd53eff5..000000000000 --- a/trunk/arch/s390/kernel/early.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * arch/s390/kernel/early.c - * - * Copyright IBM Corp. 2007 - * Author(s): Hongjie Yang , - * Heiko Carstens - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Create a Kernel NSS if the SAVESYS= parameter is defined - */ -#define DEFSYS_CMD_SIZE 96 -#define SAVESYS_CMD_SIZE 32 - -char kernel_nss_name[NSS_NAME_SIZE + 1]; - -#ifdef CONFIG_SHARED_KERNEL -static noinline __init void create_kernel_nss(void) -{ - unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; -#ifdef CONFIG_BLK_DEV_INITRD - unsigned int sinitrd_pfn, einitrd_pfn; -#endif - int response; - char *savesys_ptr; - char upper_command_line[COMMAND_LINE_SIZE]; - char defsys_cmd[DEFSYS_CMD_SIZE]; - char savesys_cmd[SAVESYS_CMD_SIZE]; - - /* Do nothing if we are not running under VM */ - if (!MACHINE_IS_VM) - return; - - /* Convert COMMAND_LINE to upper case */ - for (i = 0; i < strlen(COMMAND_LINE); i++) - upper_command_line[i] = toupper(COMMAND_LINE[i]); - - savesys_ptr = strstr(upper_command_line, "SAVESYS="); - - if (!savesys_ptr) - return; - - savesys_ptr += 8; /* Point to the beginning of the NSS name */ - for (i = 0; i < NSS_NAME_SIZE; i++) { - if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0') - break; - kernel_nss_name[i] = savesys_ptr[i]; - } - - stext_pfn = PFN_DOWN(__pa(&_stext)); - eshared_pfn = PFN_DOWN(__pa(&_eshared)); - end_pfn = PFN_UP(__pa(&_end)); - min_size = end_pfn << 2; - - sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", - kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, - eshared_pfn, end_pfn); - -#ifdef CONFIG_BLK_DEV_INITRD - if (INITRD_START && INITRD_SIZE) { - sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); - einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); - min_size = einitrd_pfn << 2; - sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, - sinitrd_pfn, einitrd_pfn); - } -#endif - - sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); - sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", - kernel_nss_name, kernel_nss_name); - - __cpcmd(defsys_cmd, NULL, 0, &response); - - if (response != 0) - return; - - __cpcmd(savesys_cmd, NULL, 0, &response); - - if (response != strlen(savesys_cmd)) - return; - - ipl_flags = IPL_NSS_VALID; -} - -#else /* CONFIG_SHARED_KERNEL */ - -static inline void create_kernel_nss(void) { } - -#endif /* CONFIG_SHARED_KERNEL */ - -/* - * Clear bss memory - */ -static noinline __init void clear_bss_section(void) -{ - memset(__bss_start, 0, _end - __bss_start); -} - -/* - * Initialize storage key for kernel pages - */ -static noinline __init void init_kernel_storage_key(void) -{ - unsigned long end_pfn, init_pfn; - - end_pfn = PFN_UP(__pa(&_end)); - - for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) - page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); -} - -static noinline __init void detect_machine_type(void) -{ - struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; - - asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id)); - - /* Running under z/VM ? */ - if (cpuinfo->cpu_id.version == 0xff) - machine_flags |= 1; - - /* Running on a P/390 ? */ - if (cpuinfo->cpu_id.machine == 0x7490) - machine_flags |= 4; -} - -static noinline __init int memory_fast_detect(void) -{ - - unsigned long val0 = 0; - unsigned long val1 = 0xc; - int ret = -ENOSYS; - - if (ipl_flags & IPL_NSS_VALID) - return -ENOSYS; - - asm volatile( - " diag %1,%2,0x260\n" - "0: lhi %0,0\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc"); - - if (ret || val0 != val1) - return -ENOSYS; - - memory_chunk[0].size = val0; - return 0; -} - -#define ADDR2G (1UL << 31) - -static noinline __init unsigned long sclp_memory_detect(void) -{ - struct sclp_readinfo_sccb *sccb; - unsigned long long memsize; - - sccb = &s390_readinfo_sccb; - - if (sccb->header.response_code != 0x10) - return 0; - - if (sccb->rnsize) - memsize = sccb->rnsize << 20; - else - memsize = sccb->rnsize2 << 20; - if (sccb->rnmax) - memsize *= sccb->rnmax; - else - memsize *= sccb->rnmax2; -#ifndef CONFIG_64BIT - /* - * Can't deal with more than 2G in 31 bit addressing mode, so - * limit the value in order to avoid strange side effects. - */ - if (memsize > ADDR2G) - memsize = ADDR2G; -#endif - return (unsigned long) memsize; -} - -static inline __init unsigned long __tprot(unsigned long addr) -{ - int cc = -1; - - asm volatile( - " tprot 0(%1),0\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (cc) : "a" (addr) : "cc"); - return (unsigned long)cc; -} - -/* Checking memory in 128KB increments. */ -#define CHUNK_INCR (1UL << 17) - -static noinline __init void find_memory_chunks(unsigned long memsize) -{ - unsigned long addr = 0, old_addr = 0; - unsigned long old_cc = CHUNK_READ_WRITE; - unsigned long cc; - int chunk = 0; - - while (chunk < MEMORY_CHUNKS) { - cc = __tprot(addr); - while (cc == old_cc) { - addr += CHUNK_INCR; - cc = __tprot(addr); -#ifndef CONFIG_64BIT - if (addr == ADDR2G) - break; -#endif - } - - if (old_addr != addr && - (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) { - memory_chunk[chunk].addr = old_addr; - memory_chunk[chunk].size = addr - old_addr; - memory_chunk[chunk].type = old_cc; - chunk++; - } - - old_addr = addr; - old_cc = cc; - -#ifndef CONFIG_64BIT - if (addr == ADDR2G) - break; -#endif - /* - * Finish memory detection at the first hole, unless - * - we reached the hsa -> skip it. - * - we know there must be more. - */ - if (cc == -1UL && !memsize && old_addr != ADDR2G) - break; - if (memsize && addr >= memsize) - break; - } -} - -static __init void early_pgm_check_handler(void) -{ - unsigned long addr; - const struct exception_table_entry *fixup; - - addr = S390_lowcore.program_old_psw.addr; - fixup = search_exception_tables(addr & PSW_ADDR_INSN); - if (!fixup) - disabled_wait(0); - S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; -} - -static noinline __init void setup_lowcore_early(void) -{ - psw_t psw; - - psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; - psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler; - S390_lowcore.external_new_psw = psw; - psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; - S390_lowcore.program_new_psw = psw; - s390_base_pgm_handler_fn = early_pgm_check_handler; -} - -/* - * Save ipl parameters, clear bss memory, initialize storage keys - * and create a kernel NSS at startup if the SAVESYS= parm is defined - */ -void __init startup_init(void) -{ - unsigned long memsize; - - ipl_save_parameters(); - clear_bss_section(); - init_kernel_storage_key(); - lockdep_init(); - lockdep_off(); - detect_machine_type(); - create_kernel_nss(); - sort_main_extable(); - setup_lowcore_early(); - sclp_readinfo_early(); - memsize = sclp_memory_detect(); - if (memory_fast_detect() < 0) - find_memory_chunks(memsize); - lockdep_on(); -} diff --git a/trunk/arch/s390/kernel/ebcdic.c b/trunk/arch/s390/kernel/ebcdic.c index cc0dc609d738..bb0f973137f0 100644 --- a/trunk/arch/s390/kernel/ebcdic.c +++ b/trunk/arch/s390/kernel/ebcdic.c @@ -11,7 +11,6 @@ #include #include -#include /* * ASCII (IBM PC 437) -> EBCDIC 037 diff --git a/trunk/arch/s390/kernel/head31.S b/trunk/arch/s390/kernel/head31.S index 453fd3b4edea..eca507050e47 100644 --- a/trunk/arch/s390/kernel/head31.S +++ b/trunk/arch/s390/kernel/head31.S @@ -51,14 +51,175 @@ startup_continue: st %r15,__LC_KERNEL_STACK # set end of kernel stack ahi %r15,-96 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + + l %r14,.Lipl_save_parameters-.LPG1(%r13) + basr %r14,%r14 # -# Save ipl parameters, clear bss memory, initialize storage key for kernel pages, -# and create a kernel NSS if the SAVESYS= parm is defined +# clear bss memory # - l %r14,.Lstartup_init-.LPG1(%r13) - basr %r14,%r14 + l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss + l %r3,.Lbss_end-.LPG1(%r13) # end of bss + sr %r3,%r2 # length of bss + sr %r4,%r4 + sr %r5,%r5 # set src,length and pad to zero + sr %r0,%r0 + mvcle %r2,%r4,0 # clear mem + jo .-4 # branch back, if not finish + + l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word +.Lservicecall: + stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts + + stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 + la %r1,0x200 # set bit 22 + o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 + st %r1,.Lcr-.LPG1(%r13) + lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 + mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw + la %r1, .Lsclph-.LPG1(%r13) + a %r1,__LC_EXT_NEW_PSW+4 # set handler + st %r1,__LC_EXT_NEW_PSW+4 + + l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff + lr %r1,%r4 # our sccb + .insn rre,0xb2200000,%r2,%r1 # service call + ipm %r1 + srl %r1,28 # get cc code + xr %r3, %r3 + chi %r1,3 + be .Lfchunk-.LPG1(%r13) # leave + chi %r1,2 + be .Lservicecall-.LPG1(%r13) + lpsw .Lwaitsclp-.LPG1(%r13) +.Lsclph: + lh %r1,.Lsccbr-.Lsccb(%r4) + chi %r1,0x10 # 0x0010 is the sucess code + je .Lprocsccb # let's process the sccb + chi %r1,0x1f0 + bne .Lfchunk-.LPG1(%r13) # unhandled error code + c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced + bne .Lfchunk-.LPG1(%r13) # if no, give up + l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP + b .Lservicecall-.LPG1(%r13) +.Lprocsccb: + lhi %r1,0 + icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 + jnz .Lscnd + lhi %r1,0x800 # otherwise report 2GB +.Lscnd: + lhi %r3,0x800 # limit reported memory size to 2GB + cr %r1,%r3 + jl .Lno2gb + lr %r1,%r3 +.Lno2gb: + xr %r3,%r3 # same logic + ic %r3,.Lscpa1-.Lsccb(%r4) + chi %r3,0x00 + jne .Lcompmem + l %r3,.Lscpa2-.Lsccb(%r4) +.Lcompmem: + mr %r2,%r1 # mem in MB on 128-bit + l %r1,.Lonemb-.LPG1(%r13) + mr %r2,%r1 # mem size in bytes in %r3 + b .Lfchunk-.LPG1(%r13) + + .align 4 +.Lipl_save_parameters: + .long ipl_save_parameters +.Linittu: + .long init_thread_union +.Lpmask: + .byte 0 + .align 8 +.Lpcext:.long 0x00080000,0x80000000 +.Lcr: + .long 0x00 # place holder for cr0 + .align 8 +.Lwaitsclp: + .long 0x010a0000,0x80000000 + .Lsclph +.Lrcp: + .int 0x00120001 # Read SCP forced code +.Lrcp2: + .int 0x00020001 # Read SCP code +.Lonemb: + .int 0x100000 +.Lfchunk: + +# +# find memory chunks. +# + lr %r9,%r3 # end of mem + mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) + la %r1,1 # test in increments of 128KB + sll %r1,17 + l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array + slr %r4,%r4 # set start of chunk to zero + slr %r5,%r5 # set end of chunk to zero + slr %r6,%r6 # set access code to zero + la %r10,MEMORY_CHUNKS # number of chunks +.Lloop: + tprot 0(%r5),0 # test protection of first byte + ipm %r7 + srl %r7,28 + clr %r6,%r7 # compare cc with last access code + be .Lsame-.LPG1(%r13) + lhi %r8,0 # no program checks + b .Lsavchk-.LPG1(%r13) +.Lsame: + ar %r5,%r1 # add 128KB to end of chunk + bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop +.Lchkmem: # > 2GB or tprot got a program check + lhi %r8,1 # set program check flag +.Lsavchk: + clr %r4,%r5 # chunk size > 0? + be .Lchkloop-.LPG1(%r13) + st %r4,0(%r3) # store start address of chunk + lr %r0,%r5 + slr %r0,%r4 + st %r0,4(%r3) # store size of chunk + st %r6,8(%r3) # store type of chunk + la %r3,12(%r3) + ahi %r10,-1 # update chunk number +.Lchkloop: + lr %r6,%r7 # set access code to last cc + # we got an exception or we're starting a new + # chunk , we must check if we should + # still try to find valid memory (if we detected + # the amount of available storage), and if we + # have chunks left + xr %r0,%r0 + clr %r0,%r9 # did we detect memory? + je .Ldonemem # if not, leave + chi %r10,0 # do we have chunks left? + je .Ldonemem + chi %r8,1 # program check ? + je .Lpgmchk + lr %r4,%r5 # potential new chunk + alr %r5,%r1 # add 128KB to end of chunk + j .Llpcnt +.Lpgmchk: + alr %r5,%r1 # add 128KB to end of chunk + lr %r4,%r5 # potential new chunk +.Llpcnt: + clr %r5,%r9 # should we go on? + jl .Lloop +.Ldonemem: l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags +# +# find out if we are running under VM +# + stidp __LC_CPUID # store cpuid + tm __LC_CPUID,0xff # running under VM ? + bno .Lnovm-.LPG1(%r13) + oi 3(%r12),1 # set VM flag +.Lnovm: + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on a P/390 ? + bne .Lnop390-.LPG1(%r13) + oi 3(%r12),4 # set P/390 flag +.Lnop390: + # # find out if we have an IEEE fpu # @@ -134,6 +295,7 @@ startup_continue: .long 0 # cr15: linkage stack operations .Lduct: .long 0,0,0,0,0,0,0,0 .long 0,0,0,0,0,0,0,0 +.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg @@ -144,9 +306,7 @@ startup_continue: .Lbss_bgn: .long __bss_start .Lbss_end: .long _end .Lparmaddr: .long PARMAREA -.Linittu: .long init_thread_union -.Lstartup_init: - .long startup_init +.Lsccbaddr: .long .Lsccb .globl ipl_schib ipl_schib: @@ -162,6 +322,26 @@ ipl_devno: .word 0 .org 0x12000 +.globl s390_readinfo_sccb +s390_readinfo_sccb: +.Lsccb: + .hword 0x1000 # length, one page + .byte 0x00,0x00,0x00 + .byte 0x80 # variable response bit set +.Lsccbr: + .hword 0x00 # response code +.Lscpincr1: + .hword 0x00 +.Lscpa1: + .byte 0x00 + .fill 89,1,0 +.Lscpa2: + .int 0x00 +.Lscpincr2: + .quad 0x00 + .fill 3984,1,0 + .org 0x13000 + #ifdef CONFIG_SHARED_KERNEL .org 0x100000 #endif diff --git a/trunk/arch/s390/kernel/head64.S b/trunk/arch/s390/kernel/head64.S index b8fec4e5c5d4..6ba3f4512dd1 100644 --- a/trunk/arch/s390/kernel/head64.S +++ b/trunk/arch/s390/kernel/head64.S @@ -58,14 +58,182 @@ startup_continue: stg %r15,__LC_KERNEL_STACK # set end of kernel stack aghi %r15,-160 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + + brasl %r14,ipl_save_parameters # -# Save ipl parameters, clear bss memory, initialize storage key for kernel pages, -# and create a kernel NSS if the SAVESYS= parm is defined +# clear bss memory # - brasl %r14,startup_init + larl %r2,__bss_start # start of bss segment + larl %r3,_end # end of bss segment + sgr %r3,%r2 # length of bss + sgr %r4,%r4 # + sgr %r5,%r5 # set src,length and pad to zero + mvcle %r2,%r4,0 # clear mem + jo .-4 # branch back, if not finish # set program check new psw mask mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) + larl %r1,.Lslowmemdetect # set program check address + stg %r1,__LC_PGM_NEW_PSW+8 + lghi %r1,0xc + diag %r0,%r1,0x260 # get memory size of virtual machine + cgr %r0,%r1 # different? -> old detection routine + jne .Lslowmemdetect + aghi %r1,1 # size is one more than end + larl %r2,memory_chunk + stg %r1,8(%r2) # store size of chunk + j .Ldonemem + +.Lslowmemdetect: + l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word +.Lservicecall: + stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts + + stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0 + la %r1,0x200 # set bit 22 + og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 + stg %r1,.Lcr-.LPG1(%r13) + lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0 + + mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw + larl %r1,.Lsclph + stg %r1,__LC_EXT_NEW_PSW+8 # set handler + + larl %r4,.Lsccb # %r4 is our index for sccb stuff + lgr %r1,%r4 # our sccb + .insn rre,0xb2200000,%r2,%r1 # service call + ipm %r1 + srl %r1,28 # get cc code + xr %r3,%r3 + chi %r1,3 + be .Lfchunk-.LPG1(%r13) # leave + chi %r1,2 + be .Lservicecall-.LPG1(%r13) + lpswe .Lwaitsclp-.LPG1(%r13) +.Lsclph: + lh %r1,.Lsccbr-.Lsccb(%r4) + chi %r1,0x10 # 0x0010 is the sucess code + je .Lprocsccb # let's process the sccb + chi %r1,0x1f0 + bne .Lfchunk-.LPG1(%r13) # unhandled error code + c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced + bne .Lfchunk-.LPG1(%r13) # if no, give up + l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP + b .Lservicecall-.LPG1(%r13) +.Lprocsccb: + lghi %r1,0 + icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 + jnz .Lscnd + lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one +.Lscnd: + xr %r3,%r3 # same logic + ic %r3,.Lscpa1-.Lsccb(%r4) + chi %r3,0x00 + jne .Lcompmem + l %r3,.Lscpa2-.Lsccb(%r4) +.Lcompmem: + mlgr %r2,%r1 # mem in MB on 128-bit + l %r1,.Lonemb-.LPG1(%r13) + mlgr %r2,%r1 # mem size in bytes in %r3 + b .Lfchunk-.LPG1(%r13) + + .align 4 +.Lpmask: + .byte 0 + .align 8 +.Lcr: + .quad 0x00 # place holder for cr0 +.Lwaitsclp: + .quad 0x0102000180000000,.Lsclph +.Lrcp: + .int 0x00120001 # Read SCP forced code +.Lrcp2: + .int 0x00020001 # Read SCP code +.Lonemb: + .int 0x100000 + +.Lfchunk: + +# +# find memory chunks. +# + lgr %r9,%r3 # end of mem + larl %r1,.Lchkmem # set program check address + stg %r1,__LC_PGM_NEW_PSW+8 + la %r1,1 # test in increments of 128KB + sllg %r1,%r1,17 + larl %r3,memory_chunk + slgr %r4,%r4 # set start of chunk to zero + slgr %r5,%r5 # set end of chunk to zero + slr %r6,%r6 # set access code to zero + la %r10,MEMORY_CHUNKS # number of chunks +.Lloop: + tprot 0(%r5),0 # test protection of first byte + ipm %r7 + srl %r7,28 + clr %r6,%r7 # compare cc with last access code + je .Lsame + lghi %r8,0 # no program checks + j .Lsavchk +.Lsame: + algr %r5,%r1 # add 128KB to end of chunk + # no need to check here, + brc 12,.Lloop # this is the same chunk +.Lchkmem: # > 16EB or tprot got a program check + lghi %r8,1 # set program check flag +.Lsavchk: + clgr %r4,%r5 # chunk size > 0? + je .Lchkloop + stg %r4,0(%r3) # store start address of chunk + lgr %r0,%r5 + slgr %r0,%r4 + stg %r0,8(%r3) # store size of chunk + st %r6,20(%r3) # store type of chunk + la %r3,24(%r3) + ahi %r10,-1 # update chunk number +.Lchkloop: + lr %r6,%r7 # set access code to last cc + # we got an exception or we're starting a new + # chunk , we must check if we should + # still try to find valid memory (if we detected + # the amount of available storage), and if we + # have chunks left + lghi %r4,1 + sllg %r4,%r4,31 + clgr %r5,%r4 + je .Lhsaskip + xr %r0, %r0 + clgr %r0, %r9 # did we detect memory? + je .Ldonemem # if not, leave + chi %r10, 0 # do we have chunks left? + je .Ldonemem +.Lhsaskip: + chi %r8,1 # program check ? + je .Lpgmchk + lgr %r4,%r5 # potential new chunk + algr %r5,%r1 # add 128KB to end of chunk + j .Llpcnt +.Lpgmchk: + algr %r5,%r1 # add 128KB to end of chunk + lgr %r4,%r5 # potential new chunk +.Llpcnt: + clgr %r5,%r9 # should we go on? + jl .Lloop +.Ldonemem: + larl %r12,machine_flags +# +# find out if we are running under VM +# + stidp __LC_CPUID # store cpuid + tm __LC_CPUID,0xff # running under VM ? + bno 0f-.LPG1(%r13) + oi 7(%r12),1 # set VM flag +0: lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on a P/390 ? + bne 1f-.LPG1(%r13) + oi 7(%r12),4 # set P/390 flag +1: + # # find out if we have the MVPG instruction # @@ -168,6 +336,25 @@ ipl_devno: .word 0 .org 0x12000 +.globl s390_readinfo_sccb +s390_readinfo_sccb: +.Lsccb: + .hword 0x1000 # length, one page + .byte 0x00,0x00,0x00 + .byte 0x80 # variable response bit set +.Lsccbr: + .hword 0x00 # response code +.Lscpincr1: + .hword 0x00 +.Lscpa1: + .byte 0x00 + .fill 89,1,0 +.Lscpa2: + .int 0x00 +.Lscpincr2: + .quad 0x00 + .fill 3984,1,0 + .org 0x13000 #ifdef CONFIG_SHARED_KERNEL .org 0x100000 diff --git a/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 052259530651..9e9972e8a52b 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/arch/s390/kernel/ipl.c @@ -20,27 +20,26 @@ #include #include #include -#include #define IPL_PARM_BLOCK_VERSION 0 +#define LOADPARM_LEN 8 -#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10) -#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) -#define SCCB_FLAG (s390_readinfo_sccb.flags) +extern char s390_readinfo_sccb[]; +#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010) +#define SCCB_LOADPARM (&s390_readinfo_sccb[24]) +#define SCCB_FLAG (s390_readinfo_sccb[91]) enum ipl_type { IPL_TYPE_NONE = 1, IPL_TYPE_UNKNOWN = 2, IPL_TYPE_CCW = 4, IPL_TYPE_FCP = 8, - IPL_TYPE_NSS = 16, }; #define IPL_NONE_STR "none" #define IPL_UNKNOWN_STR "unknown" #define IPL_CCW_STR "ccw" #define IPL_FCP_STR "fcp" -#define IPL_NSS_STR "nss" static char *ipl_type_str(enum ipl_type type) { @@ -51,8 +50,6 @@ static char *ipl_type_str(enum ipl_type type) return IPL_CCW_STR; case IPL_TYPE_FCP: return IPL_FCP_STR; - case IPL_TYPE_NSS: - return IPL_NSS_STR; case IPL_TYPE_UNKNOWN: default: return IPL_UNKNOWN_STR; @@ -67,7 +64,6 @@ enum ipl_method { IPL_METHOD_FCP_RO_DIAG, IPL_METHOD_FCP_RW_DIAG, IPL_METHOD_FCP_RO_VM, - IPL_METHOD_NSS, }; enum shutdown_action { @@ -118,14 +114,11 @@ enum diag308_rc { static int diag308_set_works = 0; static int reipl_capabilities = IPL_TYPE_UNKNOWN; - static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; static enum ipl_method reipl_method = IPL_METHOD_NONE; static struct ipl_parameter_block *reipl_block_fcp; static struct ipl_parameter_block *reipl_block_ccw; -static char reipl_nss_name[NSS_NAME_SIZE + 1]; - static int dump_capabilities = IPL_TYPE_NONE; static enum ipl_type dump_type = IPL_TYPE_NONE; static enum ipl_method dump_method = IPL_METHOD_NONE; @@ -180,24 +173,6 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ sys_##_prefix##_##_name##_show, \ sys_##_prefix##_##_name##_store); -#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\ -static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \ - char *page) \ -{ \ - return sprintf(page, _fmt_out, _value); \ -} \ -static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\ - const char *buf, size_t len) \ -{ \ - if (sscanf(buf, _fmt_in, _value) != 1) \ - return -EINVAL; \ - return len; \ -} \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ - __ATTR(_name,(S_IRUGO | S_IWUSR), \ - sys_##_prefix##_##_name##_show, \ - sys_##_prefix##_##_name##_store); - static void make_attrs_ro(struct attribute **attrs) { while (*attrs) { @@ -214,8 +189,6 @@ static enum ipl_type ipl_get_type(void) { struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; - if (ipl_flags & IPL_NSS_VALID) - return IPL_TYPE_NSS; if (!(ipl_flags & IPL_DEVNO_VALID)) return IPL_TYPE_UNKNOWN; if (!(ipl_flags & IPL_PARMBLOCK_VALID)) @@ -351,20 +324,6 @@ static struct attribute_group ipl_ccw_attr_group = { .attrs = ipl_ccw_attrs, }; -/* NSS ipl device attributes */ - -DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name); - -static struct attribute *ipl_nss_attrs[] = { - &sys_ipl_type_attr.attr, - &sys_ipl_nss_name_attr.attr, - NULL, -}; - -static struct attribute_group ipl_nss_attr_group = { - .attrs = ipl_nss_attrs, -}; - /* UNKNOWN ipl device attributes */ static struct attribute *ipl_unknown_attrs[] = { @@ -473,21 +432,6 @@ static struct attribute_group reipl_ccw_attr_group = { .attrs = reipl_ccw_attrs, }; - -/* NSS reipl device attributes */ - -DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name); - -static struct attribute *reipl_nss_attrs[] = { - &sys_reipl_nss_name_attr.attr, - NULL, -}; - -static struct attribute_group reipl_nss_attr_group = { - .name = IPL_NSS_STR, - .attrs = reipl_nss_attrs, -}; - /* reipl type */ static int reipl_set_type(enum ipl_type type) @@ -510,9 +454,6 @@ static int reipl_set_type(enum ipl_type type) else reipl_method = IPL_METHOD_FCP_RO_DIAG; break; - case IPL_TYPE_NSS: - reipl_method = IPL_METHOD_NSS; - break; default: reipl_method = IPL_METHOD_NONE; } @@ -534,8 +475,6 @@ static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf, rc = reipl_set_type(IPL_TYPE_CCW); else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) rc = reipl_set_type(IPL_TYPE_FCP); - else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0) - rc = reipl_set_type(IPL_TYPE_NSS); return (rc != 0) ? rc : len; } @@ -708,10 +647,6 @@ void do_reipl(void) case IPL_METHOD_FCP_RO_VM: __cpcmd("IPL", NULL, 0, NULL); break; - case IPL_METHOD_NSS: - sprintf(buf, "IPL %s", reipl_nss_name); - __cpcmd(buf, NULL, 0, NULL); - break; case IPL_METHOD_NONE: default: if (MACHINE_IS_VM) @@ -798,10 +733,6 @@ static int __init ipl_init(void) case IPL_TYPE_FCP: rc = ipl_register_fcp_files(); break; - case IPL_TYPE_NSS: - rc = sysfs_create_group(&ipl_subsys.kset.kobj, - &ipl_nss_attr_group); - break; default: rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_unknown_attr_group); @@ -824,20 +755,6 @@ static void __init reipl_probe(void) free_page((unsigned long)buffer); } -static int __init reipl_nss_init(void) -{ - int rc; - - if (!MACHINE_IS_VM) - return 0; - rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group); - if (rc) - return rc; - strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); - reipl_capabilities |= IPL_TYPE_NSS; - return 0; -} - static int __init reipl_ccw_init(void) { int rc; @@ -918,9 +835,6 @@ static int __init reipl_init(void) if (rc) return rc; rc = reipl_fcp_init(); - if (rc) - return rc; - rc = reipl_nss_init(); if (rc) return rc; rc = reipl_set_type(ipl_get_type()); @@ -1079,6 +993,8 @@ static void do_reset_calls(void) reset->fn(); } +extern void reset_mcck_handler(void); +extern void reset_pgm_handler(void); extern __u32 dump_prefix_page; void s390_reset_system(void) @@ -1100,14 +1016,14 @@ void s390_reset_system(void) __ctl_clear_bit(0,28); /* Set new machine check handler */ - S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; + S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; S390_lowcore.mcck_new_psw.addr = - PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler; + PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; /* Set new program check handler */ - S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; + S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; S390_lowcore.program_new_psw.addr = - PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; + PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler; do_reset_calls(); } diff --git a/trunk/arch/s390/kernel/irq.c b/trunk/arch/s390/kernel/irq.c index 8f0cbca31203..1eef50918615 100644 --- a/trunk/arch/s390/kernel/irq.c +++ b/trunk/arch/s390/kernel/irq.c @@ -1,9 +1,9 @@ /* * arch/s390/kernel/irq.c * - * Copyright IBM Corp. 2004,2007 + * S390 version + * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * Thomas Spatzier (tspat@de.ibm.com) * * This file contains interrupt related functions. */ @@ -14,8 +14,6 @@ #include #include #include -#include -#include /* * show_interrupts is needed by /proc/interrupts. @@ -95,12 +93,5 @@ asmlinkage void do_softirq(void) local_irq_restore(flags); } -EXPORT_SYMBOL(do_softirq); - -void init_irq_proc(void) -{ - struct proc_dir_entry *root_irq_dir; - root_irq_dir = proc_mkdir("irq", NULL); - create_prof_cpu_mask(root_irq_dir); -} +EXPORT_SYMBOL(do_softirq); diff --git a/trunk/arch/s390/kernel/kprobes.c b/trunk/arch/s390/kernel/kprobes.c index a466bab6677e..576368c4f605 100644 --- a/trunk/arch/s390/kernel/kprobes.c +++ b/trunk/arch/s390/kernel/kprobes.c @@ -155,34 +155,15 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) static int __kprobes swap_instruction(void *aref) { struct ins_replace_args *args = aref; - u32 *addr; - u32 instr; int err = -EFAULT; - /* - * Text segment is read-only, hence we use stura to bypass dynamic - * address translation to exchange the instruction. Since stura - * always operates on four bytes, but we only want to exchange two - * bytes do some calculations to get things right. In addition we - * shall not cross any page boundaries (vmalloc area!) when writing - * the new instruction. - */ - addr = (u32 *)ALIGN((unsigned long)args->ptr, 4); - if ((unsigned long)args->ptr & 2) - instr = ((*addr) & 0xffff0000) | args->new; - else - instr = ((*addr) & 0x0000ffff) | args->new << 16; - asm volatile( - " lra %1,0(%1)\n" - "0: stura %2,%1\n" - "1: la %0,0\n" + "0: mvc 0(2,%2),0(%3)\n" + "1: la %0,0\n" "2:\n" EX_TABLE(0b,2b) - : "+d" (err) - : "a" (addr), "d" (instr) - : "memory", "cc"); - + : "+d" (err), "=m" (*args->ptr) + : "a" (args->ptr), "a" (&args->new), "m" (args->new)); return err; } @@ -375,7 +356,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * - When the probed function returns, this probe * causes the handlers to fire */ -void kretprobe_trampoline_holder(void) +void __kprobes kretprobe_trampoline_holder(void) { asm volatile(".global kretprobe_trampoline\n" "kretprobe_trampoline: bcr 0,0\n"); @@ -384,8 +365,7 @@ void kretprobe_trampoline_holder(void) /* * Called when the probe at kretprobe trampoline is hit */ -static int __kprobes trampoline_probe_handler(struct kprobe *p, - struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head, empty_rp; diff --git a/trunk/arch/s390/kernel/machine_kexec.c b/trunk/arch/s390/kernel/machine_kexec.c index 52f57af252b4..f6d9bcc0f75b 100644 --- a/trunk/arch/s390/kernel/machine_kexec.c +++ b/trunk/arch/s390/kernel/machine_kexec.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/s390/kernel/module.c b/trunk/arch/s390/kernel/module.c index 39d1dd752529..d989ed45a7aa 100644 --- a/trunk/arch/s390/kernel/module.c +++ b/trunk/arch/s390/kernel/module.c @@ -30,7 +30,6 @@ #include #include #include -#include #if 0 #define DEBUGP printk @@ -59,7 +58,7 @@ void module_free(struct module *mod, void *module_region) table entries. */ } -static void +static inline void check_rela(Elf_Rela *rela, struct module *me) { struct mod_arch_syminfo *info; @@ -182,7 +181,7 @@ apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, return -ENOEXEC; } -static int +static inline int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, struct module *me) { diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 5acfac654f9d..6603fbb41d07 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -144,7 +144,7 @@ static void default_idle(void) trace_hardirqs_on(); /* Wait for external, I/O or machine check interrupt. */ - __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | + __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT); } @@ -190,7 +190,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) struct pt_regs regs; memset(®s, 0, sizeof(regs)); - regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT; + regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE; regs.gprs[9] = (unsigned long) fn; regs.gprs[10] = (unsigned long) arg; diff --git a/trunk/arch/s390/kernel/profile.c b/trunk/arch/s390/kernel/profile.c new file mode 100644 index 000000000000..b81aa1f569ca --- /dev/null +++ b/trunk/arch/s390/kernel/profile.c @@ -0,0 +1,20 @@ +/* + * arch/s390/kernel/profile.c + * + * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + */ +#include +#include + +static struct proc_dir_entry * root_irq_dir; + +void init_irq_proc(void) +{ + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", NULL); + + /* create /proc/irq/prof_cpu_mask */ + create_prof_cpu_mask(root_irq_dir); +} diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index 2a8f0872ea8b..8f36504075ed 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -86,13 +86,15 @@ FixPerRegisters(struct task_struct *task) per_info->control_regs.bits.storage_alt_space_ctl = 0; } -static void set_single_step(struct task_struct *task) +void +set_single_step(struct task_struct *task) { task->thread.per_info.single_step = 1; FixPerRegisters(task); } -static void clear_single_step(struct task_struct *task) +void +clear_single_step(struct task_struct *task) { task->thread.per_info.single_step = 0; FixPerRegisters(task); @@ -230,9 +232,9 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) */ if (addr == (addr_t) &dummy->regs.psw.mask && #ifdef CONFIG_COMPAT - data != PSW_MASK_MERGE(psw_user32_bits, data) && + data != PSW_MASK_MERGE(PSW_USER32_BITS, data) && #endif - data != PSW_MASK_MERGE(psw_user_bits, data)) + data != PSW_MASK_MERGE(PSW_USER_BITS, data)) /* Invalid psw mask. */ return -EINVAL; #ifndef CONFIG_64BIT @@ -307,7 +309,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); if (copied != sizeof(tmp)) return -EIO; - return put_user(tmp, (unsigned long __force __user *) data); + return put_user(tmp, (unsigned long __user *) data); case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ @@ -329,7 +331,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: - if (copy_from_user(&parea, (void __force __user *) addr, + if (copy_from_user(&parea, (void __user *) addr, sizeof(parea))) return -EFAULT; addr = parea.kernel_addr; @@ -339,11 +341,10 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) if (request == PTRACE_PEEKUSR_AREA) ret = peek_user(child, addr, data); else { - addr_t utmp; - if (get_user(utmp, - (addr_t __force __user *) data)) + addr_t tmp; + if (get_user (tmp, (addr_t __user *) data)) return -EFAULT; - ret = poke_user(child, addr, utmp); + ret = poke_user(child, addr, tmp); } if (ret) return ret; @@ -393,7 +394,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) if (addr == (addr_t) &dummy32->regs.psw.mask) { /* Fake a 31 bit psw mask. */ tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32); - tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp); + tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Fake a 31 bit psw address. */ tmp = (__u32) task_pt_regs(child)->psw.addr | @@ -468,11 +469,11 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) */ if (addr == (addr_t) &dummy32->regs.psw.mask) { /* Build a 64 bit psw mask from 31 bit mask. */ - if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp)) + if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp)) /* Invalid psw mask. */ return -EINVAL; task_pt_regs(child)->psw.mask = - PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32); + PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Build a 64 bit psw address from 31 bit address. */ task_pt_regs(child)->psw.addr = @@ -549,7 +550,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); if (copied != sizeof(tmp)) return -EIO; - return put_user(tmp, (unsigned int __force __user *) data); + return put_user(tmp, (unsigned int __user *) data); case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ @@ -570,7 +571,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: - if (copy_from_user(&parea, (void __force __user *) addr, + if (copy_from_user(&parea, (void __user *) addr, sizeof(parea))) return -EFAULT; addr = parea.kernel_addr; @@ -580,11 +581,10 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) if (request == PTRACE_PEEKUSR_AREA) ret = peek_user_emu31(child, addr, data); else { - __u32 utmp; - if (get_user(utmp, - (__u32 __force __user *) data)) + __u32 tmp; + if (get_user (tmp, (__u32 __user *) data)) return -EFAULT; - ret = poke_user_emu31(child, addr, utmp); + ret = poke_user_emu31(child, addr, tmp); } if (ret) return ret; @@ -595,19 +595,17 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) return 0; case PTRACE_GETEVENTMSG: return put_user((__u32) child->ptrace_message, - (unsigned int __force __user *) data); + (unsigned int __user *) data); case PTRACE_GETSIGINFO: if (child->last_siginfo == NULL) return -EINVAL; - return copy_siginfo_to_user32((compat_siginfo_t - __force __user *) data, + return copy_siginfo_to_user32((compat_siginfo_t __user *) data, child->last_siginfo); case PTRACE_SETSIGINFO: if (child->last_siginfo == NULL) return -EINVAL; return copy_siginfo_from_user32(child->last_siginfo, - (compat_siginfo_t - __force __user *) data); + (compat_siginfo_t __user *) data); } return ptrace_request(child, request, addr, data); } diff --git a/trunk/arch/s390/kernel/reset.S b/trunk/arch/s390/kernel/reset.S new file mode 100644 index 000000000000..8a87355161fa --- /dev/null +++ b/trunk/arch/s390/kernel/reset.S @@ -0,0 +1,90 @@ +/* + * arch/s390/kernel/reset.S + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Heiko Carstens + * Michael Holzheu + */ + +#include +#include + +#ifdef CONFIG_64BIT + + .globl reset_mcck_handler +reset_mcck_handler: + basr %r13,0 +0: lg %r15,__LC_PANIC_STACK # load panic stack + aghi %r15,-STACK_FRAME_OVERHEAD + lg %r1,s390_reset_mcck_handler-0b(%r13) + ltgr %r1,%r1 + jz 1f + basr %r14,%r1 +1: la %r1,4095 + lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) + lpswe __LC_MCK_OLD_PSW + + .globl s390_reset_mcck_handler +s390_reset_mcck_handler: + .quad 0 + + .globl reset_pgm_handler +reset_pgm_handler: + stmg %r0,%r15,__LC_SAVE_AREA + basr %r13,0 +0: lg %r15,__LC_PANIC_STACK # load panic stack + aghi %r15,-STACK_FRAME_OVERHEAD + lg %r1,s390_reset_pgm_handler-0b(%r13) + ltgr %r1,%r1 + jz 1f + basr %r14,%r1 + lmg %r0,%r15,__LC_SAVE_AREA + lpswe __LC_PGM_OLD_PSW +1: lpswe disabled_wait_psw-0b(%r13) + .globl s390_reset_pgm_handler +s390_reset_pgm_handler: + .quad 0 + .align 8 +disabled_wait_psw: + .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler + +#else /* CONFIG_64BIT */ + + .globl reset_mcck_handler +reset_mcck_handler: + basr %r13,0 +0: l %r15,__LC_PANIC_STACK # load panic stack + ahi %r15,-STACK_FRAME_OVERHEAD + l %r1,s390_reset_mcck_handler-0b(%r13) + ltr %r1,%r1 + jz 1f + basr %r14,%r1 +1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA + lpsw __LC_MCK_OLD_PSW + + .globl s390_reset_mcck_handler +s390_reset_mcck_handler: + .long 0 + + .globl reset_pgm_handler +reset_pgm_handler: + stm %r0,%r15,__LC_SAVE_AREA + basr %r13,0 +0: l %r15,__LC_PANIC_STACK # load panic stack + ahi %r15,-STACK_FRAME_OVERHEAD + l %r1,s390_reset_pgm_handler-0b(%r13) + ltr %r1,%r1 + jz 1f + basr %r14,%r1 + lm %r0,%r15,__LC_SAVE_AREA + lpsw __LC_PGM_OLD_PSW + +1: lpsw disabled_wait_psw-0b(%r13) + .globl s390_reset_pgm_handler +s390_reset_pgm_handler: + .long 0 +disabled_wait_psw: + .align 8 + .long 0x000a0000,0x00000000 + reset_pgm_handler + +#endif /* CONFIG_64BIT */ diff --git a/trunk/arch/s390/kernel/s390_ext.c b/trunk/arch/s390/kernel/s390_ext.c index acf93dba7727..bc5beaa8f98e 100644 --- a/trunk/arch/s390/kernel/s390_ext.c +++ b/trunk/arch/s390/kernel/s390_ext.c @@ -125,12 +125,14 @@ void do_extint(struct pt_regs *regs, unsigned short code) * Make sure that the i/o interrupt did not "overtake" * the last HZ timer interrupt. */ - account_ticks(S390_lowcore.int_clock); + account_ticks(); kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; index = ext_hash(code); for (p = ext_int_hash[index]; p; p = p->next) { - if (likely(p->code == code)) - p->handler(code); + if (likely(p->code == code)) { + if (likely(p->handler)) + p->handler(code); + } } irq_exit(); set_irq_regs(old_regs); diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index 03739813d3bf..5d8ee3baac14 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -38,8 +38,6 @@ #include #include #include -#include -#include #include #include @@ -51,14 +49,6 @@ #include #include #include -#include -#include - -long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | - PSW_MASK_MCHECK | PSW_DEFAULT_KEY); -long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | - PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | - PSW_MASK_PSTATE | PSW_DEFAULT_KEY); /* * User copy operations. @@ -127,9 +117,9 @@ void __devinit cpu_init (void) */ char vmhalt_cmd[128] = ""; char vmpoff_cmd[128] = ""; -static char vmpanic_cmd[128] = ""; +char vmpanic_cmd[128] = ""; -static void strncpy_skip_quote(char *dst, char *src, int n) +static inline void strncpy_skip_quote(char *dst, char *src, int n) { int sx, dx; @@ -285,6 +275,10 @@ static void __init conmode_default(void) } #ifdef CONFIG_SMP +extern void machine_restart_smp(char *); +extern void machine_halt_smp(void); +extern void machine_power_off_smp(void); + void (*_machine_restart)(char *command) = machine_restart_smp; void (*_machine_halt)(void) = machine_halt_smp; void (*_machine_power_off)(void) = machine_power_off_smp; @@ -392,84 +386,6 @@ static int __init early_parse_ipldelay(char *p) } early_param("ipldelay", early_parse_ipldelay); -#ifdef CONFIG_S390_SWITCH_AMODE -unsigned int switch_amode = 0; -EXPORT_SYMBOL_GPL(switch_amode); - -static void set_amode_and_uaccess(unsigned long user_amode, - unsigned long user32_amode) -{ - psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode | - PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | - PSW_MASK_PSTATE | PSW_DEFAULT_KEY; -#ifdef CONFIG_COMPAT - psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode | - PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | - PSW_MASK_PSTATE | PSW_DEFAULT_KEY; - psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode | - PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | - PSW32_MASK_PSTATE; -#endif - psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | - PSW_MASK_MCHECK | PSW_DEFAULT_KEY; - - if (MACHINE_HAS_MVCOS) { - printk("mvcos available.\n"); - memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); - } else { - printk("mvcos not available.\n"); - memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); - } -} - -/* - * Switch kernel/user addressing modes? - */ -static int __init early_parse_switch_amode(char *p) -{ - switch_amode = 1; - return 0; -} -early_param("switch_amode", early_parse_switch_amode); - -#else /* CONFIG_S390_SWITCH_AMODE */ -static inline void set_amode_and_uaccess(unsigned long user_amode, - unsigned long user32_amode) -{ -} -#endif /* CONFIG_S390_SWITCH_AMODE */ - -#ifdef CONFIG_S390_EXEC_PROTECT -unsigned int s390_noexec = 0; -EXPORT_SYMBOL_GPL(s390_noexec); - -/* - * Enable execute protection? - */ -static int __init early_parse_noexec(char *p) -{ - if (!strncmp(p, "off", 3)) - return 0; - switch_amode = 1; - s390_noexec = 1; - return 0; -} -early_param("noexec", early_parse_noexec); -#endif /* CONFIG_S390_EXEC_PROTECT */ - -static void setup_addressing_mode(void) -{ - if (s390_noexec) { - printk("S390 execute protection active, "); - set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY); - return; - } - if (switch_amode) { - printk("S390 address spaces switched, "); - set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); - } -} - static void __init setup_lowcore(void) { @@ -486,21 +402,19 @@ setup_lowcore(void) lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) restart_int_handler; - if (switch_amode) - lc->restart_psw.mask |= PSW_ASC_HOME; - lc->external_new_psw.mask = psw_kernel_bits; + lc->external_new_psw.mask = PSW_KERNEL_BITS; lc->external_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) ext_int_handler; - lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT; + lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; - lc->program_new_psw.mask = psw_kernel_bits; + lc->program_new_psw.mask = PSW_KERNEL_BITS; lc->program_new_psw.addr = PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; lc->mcck_new_psw.mask = - psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT; + PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT; lc->mcck_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; - lc->io_new_psw.mask = psw_kernel_bits; + lc->io_new_psw.mask = PSW_KERNEL_BITS; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->ipl_device = S390_lowcore.ipl_device; lc->jiffy_timer = -1LL; @@ -525,7 +439,7 @@ setup_lowcore(void) static void __init setup_resources(void) { - struct resource *res, *sub_res; + struct resource *res; int i; code_resource.start = (unsigned long) &_text; @@ -550,38 +464,8 @@ setup_resources(void) res->start = memory_chunk[i].addr; res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; request_resource(&iomem_resource, res); - - if (code_resource.start >= res->start && - code_resource.start <= res->end && - code_resource.end > res->end) { - sub_res = alloc_bootmem_low(sizeof(struct resource)); - memcpy(sub_res, &code_resource, - sizeof(struct resource)); - sub_res->end = res->end; - code_resource.start = res->end + 1; - request_resource(res, sub_res); - } - - if (code_resource.start >= res->start && - code_resource.start <= res->end && - code_resource.end <= res->end) - request_resource(res, &code_resource); - - if (data_resource.start >= res->start && - data_resource.start <= res->end && - data_resource.end > res->end) { - sub_res = alloc_bootmem_low(sizeof(struct resource)); - memcpy(sub_res, &data_resource, - sizeof(struct resource)); - sub_res->end = res->end; - data_resource.start = res->end + 1; - request_resource(res, sub_res); - } - - if (data_resource.start >= res->start && - data_resource.start <= res->end && - data_resource.end <= res->end) - request_resource(res, &data_resource); + request_resource(res, &code_resource); + request_resource(res, &data_resource); } } @@ -611,13 +495,16 @@ static void __init setup_memory_end(void) } if (!memory_end) memory_end = memory_size; + if (real_size > memory_end) + printk("More memory detected than supported. Unused: %luk\n", + (real_size - memory_end) >> 10); } static void __init setup_memory(void) { unsigned long bootmap_size; - unsigned long start_pfn, end_pfn; + unsigned long start_pfn, end_pfn, init_pfn; int i; /* @@ -627,6 +514,10 @@ setup_memory(void) start_pfn = PFN_UP(__pa(&_end)); end_pfn = max_pfn = PFN_DOWN(memory_end); + /* Initialize storage key for kernel pages */ + for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++) + page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); + #ifdef CONFIG_BLK_DEV_INITRD /* * Move the initrd in case the bitmap of the bootmem allocater @@ -760,7 +651,6 @@ setup_arch(char **cmdline_p) parse_early_param(); setup_memory_end(); - setup_addressing_mode(); setup_memory(); setup_resources(); setup_lowcore(); @@ -804,7 +694,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; - s390_adjust_jiffies(); preempt_disable(); if (!n) { seq_printf(m, "vendor_id : IBM/S390\n" diff --git a/trunk/arch/s390/kernel/signal.c b/trunk/arch/s390/kernel/signal.c index 554f9cf7499c..4c8a7954ef48 100644 --- a/trunk/arch/s390/kernel/signal.c +++ b/trunk/arch/s390/kernel/signal.c @@ -119,7 +119,7 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) /* Copy a 'clean' PSW mask to the user to avoid leaking information about whether PER is currently on. */ - user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask); + user_sregs.regs.psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask); user_sregs.regs.psw.addr = regs->psw.addr; memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs)); memcpy(&user_sregs.regs.acrs, current->thread.acrs, diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 65b52320d145..c0cd255fddbd 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -22,23 +22,23 @@ #include #include + #include #include #include #include + #include #include #include #include -#include -#include + #include #include #include #include #include #include -#include extern volatile int __cpu_logical_map[]; @@ -53,6 +53,12 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE; static struct task_struct *current_set[NR_CPUS]; +/* + * Reboot, halt and power_off routines for SMP. + */ +extern char vmhalt_cmd[]; +extern char vmpoff_cmd[]; + static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); @@ -194,7 +200,7 @@ int smp_call_function_on(void (*func) (void *info), void *info, } EXPORT_SYMBOL(smp_call_function_on); -static void do_send_stop(void) +static inline void do_send_stop(void) { int cpu, rc; @@ -208,7 +214,7 @@ static void do_send_stop(void) } } -static void do_store_status(void) +static inline void do_store_status(void) { int cpu, rc; @@ -224,7 +230,7 @@ static void do_store_status(void) } } -static void do_wait_for_stop(void) +static inline void do_wait_for_stop(void) { int cpu; @@ -244,7 +250,7 @@ static void do_wait_for_stop(void) void smp_send_stop(void) { /* Disable all interrupts/machine checks */ - __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); + __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK); /* write magic number to zero page (absolute 0) */ lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; @@ -292,7 +298,7 @@ void machine_power_off_smp(void) * cpus are handled. */ -static void do_ext_call_interrupt(__u16 code) +void do_ext_call_interrupt(__u16 code) { unsigned long bits; @@ -379,7 +385,7 @@ struct ec_creg_mask_parms { /* * callback for setting/clearing control bits */ -static void smp_ctl_bit_callback(void *info) { +void smp_ctl_bit_callback(void *info) { struct ec_creg_mask_parms *pp = info; unsigned long cregs[16]; int i; @@ -452,15 +458,17 @@ __init smp_count_cpus(void) /* * Activate a secondary processor. */ +extern void init_cpu_timer(void); +extern void init_cpu_vtimer(void); + int __devinit start_secondary(void *cpuvoid) { /* Setup the cpu */ cpu_init(); preempt_disable(); - /* Enable TOD clock interrupts on the secondary cpu. */ + /* init per CPU timer */ init_cpu_timer(); #ifdef CONFIG_VIRT_TIMER - /* Enable cpu timer interrupts on the secondary cpu. */ init_cpu_vtimer(); #endif /* Enable pfault pseudo page faults on this cpu. */ @@ -534,7 +542,7 @@ smp_put_cpu(int cpu) spin_unlock_irqrestore(&smp_reserve_lock, flags); } -static int +static inline int cpu_stopped(int cpu) { __u32 status; diff --git a/trunk/arch/s390/kernel/stacktrace.c b/trunk/arch/s390/kernel/stacktrace.c index 2e5c65a1863e..0d14a4789bf2 100644 --- a/trunk/arch/s390/kernel/stacktrace.c +++ b/trunk/arch/s390/kernel/stacktrace.c @@ -11,11 +11,11 @@ #include #include -static unsigned long save_context_stack(struct stack_trace *trace, - unsigned int *skip, - unsigned long sp, - unsigned long low, - unsigned long high) +static inline unsigned long save_context_stack(struct stack_trace *trace, + unsigned int *skip, + unsigned long sp, + unsigned long low, + unsigned long high) { struct stack_frame *sf; struct pt_regs *regs; diff --git a/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index 3b91f27ab202..6cceed4df73e 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/arch/s390/kernel/time.c @@ -37,15 +37,11 @@ #include #include #include -#include /* change this if you have some constant time drift */ #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) -/* The value of the TOD clock for 1.1.1970. */ -#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL - /* * Create a small time difference between the timer interrupts * on the different cpus to avoid lock contention. @@ -55,7 +51,6 @@ #define TICK_SIZE tick static ext_int_info_t ext_int_info_cc; -static ext_int_info_t ext_int_etr_cc; static u64 init_timer_cc; static u64 jiffies_timer_cc; static u64 xtime_cc; @@ -94,21 +89,29 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime) #define s390_do_profile() do { ; } while(0) #endif /* CONFIG_PROFILING */ + /* - * Advance the per cpu tick counter up to the time given with the - * "time" argument. The per cpu update consists of accounting - * the virtual cpu time, calling update_process_times and calling - * the profiling hook. If xtime is before time it is advanced as well. + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick */ -void account_ticks(u64 time) +void account_ticks(void) { - __u32 ticks; __u64 tmp; + __u32 ticks; /* Calculate how many ticks have passed. */ - if (time < S390_lowcore.jiffy_timer) + if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) { + /* + * We have to program the clock comparator even if + * no tick has passed. That happens if e.g. an i/o + * interrupt wakes up an idle processor that has + * switched off its hz timer. + */ + tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (tmp)); return; - tmp = time - S390_lowcore.jiffy_timer; + } + tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */ ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1; S390_lowcore.jiffy_timer += @@ -121,6 +124,10 @@ void account_ticks(u64 time) S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; } + /* set clock comparator for next tick */ + tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (tmp)); + #ifdef CONFIG_SMP /* * Do not rely on the boot cpu to do the calls to do_timer. @@ -166,7 +173,7 @@ int sysctl_hz_timer = 1; * Stop the HZ tick on the current CPU. * Only cpu_idle may call this function. */ -static void stop_hz_timer(void) +static inline void stop_hz_timer(void) { unsigned long flags; unsigned long seq, next; @@ -203,21 +210,20 @@ static void stop_hz_timer(void) if (timer >= jiffies_timer_cc) todval = timer; } - set_clock_comparator(todval); + asm volatile ("SCKC %0" : : "m" (todval)); } /* * Start the HZ tick on the current CPU. * Only cpu_idle may call this function. */ -static void start_hz_timer(void) +static inline void start_hz_timer(void) { BUG_ON(!in_interrupt()); if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) return; - account_ticks(get_clock()); - set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); + account_ticks(); cpu_clear(smp_processor_id(), nohz_cpu_mask); } @@ -239,7 +245,7 @@ static struct notifier_block nohz_idle_nb = { .notifier_call = nohz_idle_notify, }; -static void __init nohz_init(void) +void __init nohz_init(void) { if (register_idle_notifier(&nohz_idle_nb)) panic("Couldn't register idle notifier"); @@ -248,57 +254,24 @@ static void __init nohz_init(void) #endif /* - * Set up per cpu jiffy timer and set the clock comparator. - */ -static void setup_jiffy_timer(void) -{ - /* Set up clock comparator to next jiffy. */ - S390_lowcore.jiffy_timer = - jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY; - set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); -} - -/* - * Set up lowcore and control register of the current cpu to - * enable TOD clock and clock comparator interrupts. + * Start the clock comparator on the current CPU. */ void init_cpu_timer(void) { - setup_jiffy_timer(); + unsigned long cr0; + __u64 timer; - /* Enable clock comparator timer interrupt. */ - __ctl_set_bit(0,11); - - /* Always allow ETR external interrupts, even without an ETR. */ - __ctl_set_bit(0, 4); + timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY; + S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY; + timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (timer)); + /* allow clock comparator timer interrupt */ + __ctl_store(cr0, 0, 0); + cr0 |= 0x800; + __ctl_load(cr0, 0, 0); } -static void clock_comparator_interrupt(__u16 code) -{ - /* set clock comparator for next tick */ - set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); -} - -static void etr_reset(void); -static void etr_init(void); -static void etr_ext_handler(__u16); - -/* - * Get the TOD clock running. - */ -static u64 __init reset_tod_clock(void) -{ - u64 time; - - etr_reset(); - if (store_clock(&time) == 0) - return time; - /* TOD clock not running. Set the clock to Unix Epoch. */ - if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0) - panic("TOD clock not operational."); - - return TOD_UNIX_EPOCH; -} +extern void vtime_init(void); static cycle_t read_tod_clock(void) { @@ -322,31 +295,48 @@ static struct clocksource clocksource_tod = { */ void __init time_init(void) { - init_timer_cc = reset_tod_clock(); - xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY; + __u64 set_time_cc; + int cc; + + /* kick the TOD clock */ + asm volatile( + " stck 0(%2)\n" + " ipm %0\n" + " srl %0,28" + : "=d" (cc), "=m" (init_timer_cc) + : "a" (&init_timer_cc) : "cc"); + switch (cc) { + case 0: /* clock in set state: all is fine */ + break; + case 1: /* clock in non-set state: FIXME */ + printk("time_init: TOD clock in non-set state\n"); + break; + case 2: /* clock in error state: FIXME */ + printk("time_init: TOD clock in error state\n"); + break; + case 3: /* clock in stopped or not-operational state: FIXME */ + printk("time_init: TOD clock stopped/non-operational\n"); + break; + } jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY; /* set xtime */ - tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime); + xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY; + set_time_cc = init_timer_cc - 0x8126d60e46000000LL + + (0x3c26700LL*1000000*4096); + tod_to_timeval(set_time_cc, &xtime); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); /* request the clock comparator external interrupt */ - if (register_early_external_interrupt(0x1004, - clock_comparator_interrupt, + if (register_early_external_interrupt(0x1004, NULL, &ext_int_info_cc) != 0) panic("Couldn't request external interrupt 0x1004"); if (clocksource_register(&clocksource_tod) != 0) panic("Could not register TOD clock source"); - /* request the etr external interrupt */ - if (register_early_external_interrupt(0x1406, etr_ext_handler, - &ext_int_etr_cc) != 0) - panic("Couldn't request external interrupt 0x1406"); - - /* Enable TOD clock interrupts on the boot cpu. */ - init_cpu_timer(); + init_cpu_timer(); #ifdef CONFIG_NO_IDLE_HZ nohz_init(); @@ -355,1048 +345,5 @@ void __init time_init(void) #ifdef CONFIG_VIRT_TIMER vtime_init(); #endif - etr_init(); -} - -/* - * External Time Reference (ETR) code. - */ -static int etr_port0_online; -static int etr_port1_online; - -static int __init early_parse_etr(char *p) -{ - if (strncmp(p, "off", 3) == 0) - etr_port0_online = etr_port1_online = 0; - else if (strncmp(p, "port0", 5) == 0) - etr_port0_online = 1; - else if (strncmp(p, "port1", 5) == 0) - etr_port1_online = 1; - else if (strncmp(p, "on", 2) == 0) - etr_port0_online = etr_port1_online = 1; - return 0; -} -early_param("etr", early_parse_etr); - -enum etr_event { - ETR_EVENT_PORT0_CHANGE, - ETR_EVENT_PORT1_CHANGE, - ETR_EVENT_PORT_ALERT, - ETR_EVENT_SYNC_CHECK, - ETR_EVENT_SWITCH_LOCAL, - ETR_EVENT_UPDATE, -}; - -enum etr_flags { - ETR_FLAG_ENOSYS, - ETR_FLAG_EACCES, - ETR_FLAG_STEAI, -}; - -/* - * Valid bit combinations of the eacr register are (x = don't care): - * e0 e1 dp p0 p1 ea es sl - * 0 0 x 0 0 0 0 0 initial, disabled state - * 0 0 x 0 1 1 0 0 port 1 online - * 0 0 x 1 0 1 0 0 port 0 online - * 0 0 x 1 1 1 0 0 both ports online - * 0 1 x 0 1 1 0 0 port 1 online and usable, ETR or PPS mode - * 0 1 x 0 1 1 0 1 port 1 online, usable and ETR mode - * 0 1 x 0 1 1 1 0 port 1 online, usable, PPS mode, in-sync - * 0 1 x 0 1 1 1 1 port 1 online, usable, ETR mode, in-sync - * 0 1 x 1 1 1 0 0 both ports online, port 1 usable - * 0 1 x 1 1 1 1 0 both ports online, port 1 usable, PPS mode, in-sync - * 0 1 x 1 1 1 1 1 both ports online, port 1 usable, ETR mode, in-sync - * 1 0 x 1 0 1 0 0 port 0 online and usable, ETR or PPS mode - * 1 0 x 1 0 1 0 1 port 0 online, usable and ETR mode - * 1 0 x 1 0 1 1 0 port 0 online, usable, PPS mode, in-sync - * 1 0 x 1 0 1 1 1 port 0 online, usable, ETR mode, in-sync - * 1 0 x 1 1 1 0 0 both ports online, port 0 usable - * 1 0 x 1 1 1 1 0 both ports online, port 0 usable, PPS mode, in-sync - * 1 0 x 1 1 1 1 1 both ports online, port 0 usable, ETR mode, in-sync - * 1 1 x 1 1 1 1 0 both ports online & usable, ETR, in-sync - * 1 1 x 1 1 1 1 1 both ports online & usable, ETR, in-sync - */ -static struct etr_eacr etr_eacr; -static u64 etr_tolec; /* time of last eacr update */ -static unsigned long etr_flags; -static struct etr_aib etr_port0; -static int etr_port0_uptodate; -static struct etr_aib etr_port1; -static int etr_port1_uptodate; -static unsigned long etr_events; -static struct timer_list etr_timer; -static struct tasklet_struct etr_tasklet; -static DEFINE_PER_CPU(atomic_t, etr_sync_word); - -static void etr_timeout(unsigned long dummy); -static void etr_tasklet_fn(unsigned long dummy); - -/* - * The etr get_clock function. It will write the current clock value - * to the clock pointer and return 0 if the clock is in sync with the - * external time source. If the clock mode is local it will return - * -ENOSYS and -EAGAIN if the clock is not in sync with the external - * reference. This function is what ETR is all about.. - */ -int get_sync_clock(unsigned long long *clock) -{ - atomic_t *sw_ptr; - unsigned int sw0, sw1; - - sw_ptr = &get_cpu_var(etr_sync_word); - sw0 = atomic_read(sw_ptr); - *clock = get_clock(); - sw1 = atomic_read(sw_ptr); - put_cpu_var(etr_sync_sync); - if (sw0 == sw1 && (sw0 & 0x80000000U)) - /* Success: time is in sync. */ - return 0; - if (test_bit(ETR_FLAG_ENOSYS, &etr_flags)) - return -ENOSYS; - if (test_bit(ETR_FLAG_EACCES, &etr_flags)) - return -EACCES; - return -EAGAIN; -} -EXPORT_SYMBOL(get_sync_clock); - -/* - * Make get_sync_clock return -EAGAIN. - */ -static void etr_disable_sync_clock(void *dummy) -{ - atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word); - /* - * Clear the in-sync bit 2^31. All get_sync_clock calls will - * fail until the sync bit is turned back on. In addition - * increase the "sequence" counter to avoid the race of an - * etr event and the complete recovery against get_sync_clock. - */ - atomic_clear_mask(0x80000000, sw_ptr); - atomic_inc(sw_ptr); -} - -/* - * Make get_sync_clock return 0 again. - * Needs to be called from a context disabled for preemption. - */ -static void etr_enable_sync_clock(void) -{ - atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word); - atomic_set_mask(0x80000000, sw_ptr); -} - -/* - * Reset ETR attachment. - */ -static void etr_reset(void) -{ - etr_eacr = (struct etr_eacr) { - .e0 = 0, .e1 = 0, ._pad0 = 4, .dp = 0, - .p0 = 0, .p1 = 0, ._pad1 = 0, .ea = 0, - .es = 0, .sl = 0 }; - if (etr_setr(&etr_eacr) == 0) - etr_tolec = get_clock(); - else { - set_bit(ETR_FLAG_ENOSYS, &etr_flags); - if (etr_port0_online || etr_port1_online) { - printk(KERN_WARNING "Running on non ETR capable " - "machine, only local mode available.\n"); - etr_port0_online = etr_port1_online = 0; - } - } -} - -static void etr_init(void) -{ - struct etr_aib aib; - - if (test_bit(ETR_FLAG_ENOSYS, &etr_flags)) - return; - /* Check if this machine has the steai instruction. */ - if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0) - set_bit(ETR_FLAG_STEAI, &etr_flags); - setup_timer(&etr_timer, etr_timeout, 0UL); - tasklet_init(&etr_tasklet, etr_tasklet_fn, 0); - if (!etr_port0_online && !etr_port1_online) - set_bit(ETR_FLAG_EACCES, &etr_flags); - if (etr_port0_online) { - set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); - } - if (etr_port1_online) { - set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); - } -} - -/* - * Two sorts of ETR machine checks. The architecture reads: - * "When a machine-check niterruption occurs and if a switch-to-local or - * ETR-sync-check interrupt request is pending but disabled, this pending - * disabled interruption request is indicated and is cleared". - * Which means that we can get etr_switch_to_local events from the machine - * check handler although the interruption condition is disabled. Lovely.. - */ - -/* - * Switch to local machine check. This is called when the last usable - * ETR port goes inactive. After switch to local the clock is not in sync. - */ -void etr_switch_to_local(void) -{ - if (!etr_eacr.sl) - return; - etr_disable_sync_clock(NULL); - set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); - tasklet_hi_schedule(&etr_tasklet); -} - -/* - * ETR sync check machine check. This is called when the ETR OTE and the - * local clock OTE are farther apart than the ETR sync check tolerance. - * After a ETR sync check the clock is not in sync. The machine check - * is broadcasted to all cpus at the same time. - */ -void etr_sync_check(void) -{ - if (!etr_eacr.es) - return; - etr_disable_sync_clock(NULL); - set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); - tasklet_hi_schedule(&etr_tasklet); -} - -/* - * ETR external interrupt. There are two causes: - * 1) port state change, check the usability of the port - * 2) port alert, one of the ETR-data-validity bits (v1-v2 bits of the - * sldr-status word) or ETR-data word 1 (edf1) or ETR-data word 3 (edf3) - * or ETR-data word 4 (edf4) has changed. - */ -static void etr_ext_handler(__u16 code) -{ - struct etr_interruption_parameter *intparm = - (struct etr_interruption_parameter *) &S390_lowcore.ext_params; - - if (intparm->pc0) - /* ETR port 0 state change. */ - set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); - if (intparm->pc1) - /* ETR port 1 state change. */ - set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); - if (intparm->eai) - /* - * ETR port alert on either port 0, 1 or both. - * Both ports are not up-to-date now. - */ - set_bit(ETR_EVENT_PORT_ALERT, &etr_events); - tasklet_hi_schedule(&etr_tasklet); -} - -static void etr_timeout(unsigned long dummy) -{ - set_bit(ETR_EVENT_UPDATE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); -} - -/* - * Check if the etr mode is pss. - */ -static inline int etr_mode_is_pps(struct etr_eacr eacr) -{ - return eacr.es && !eacr.sl; -} - -/* - * Check if the etr mode is etr. - */ -static inline int etr_mode_is_etr(struct etr_eacr eacr) -{ - return eacr.es && eacr.sl; -} - -/* - * Check if the port can be used for TOD synchronization. - * For PPS mode the port has to receive OTEs. For ETR mode - * the port has to receive OTEs, the ETR stepping bit has to - * be zero and the validity bits for data frame 1, 2, and 3 - * have to be 1. - */ -static int etr_port_valid(struct etr_aib *aib, int port) -{ - unsigned int psc; - - /* Check that this port is receiving OTEs. */ - if (aib->tsp == 0) - return 0; - - psc = port ? aib->esw.psc1 : aib->esw.psc0; - if (psc == etr_lpsc_pps_mode) - return 1; - if (psc == etr_lpsc_operational_step) - return !aib->esw.y && aib->slsw.v1 && - aib->slsw.v2 && aib->slsw.v3; - return 0; -} - -/* - * Check if two ports are on the same network. - */ -static int etr_compare_network(struct etr_aib *aib1, struct etr_aib *aib2) -{ - // FIXME: any other fields we have to compare? - return aib1->edf1.net_id == aib2->edf1.net_id; -} - -/* - * Wrapper for etr_stei that converts physical port states - * to logical port states to be consistent with the output - * of stetr (see etr_psc vs. etr_lpsc). - */ -static void etr_steai_cv(struct etr_aib *aib, unsigned int func) -{ - BUG_ON(etr_steai(aib, func) != 0); - /* Convert port state to logical port state. */ - if (aib->esw.psc0 == 1) - aib->esw.psc0 = 2; - else if (aib->esw.psc0 == 0 && aib->esw.p == 0) - aib->esw.psc0 = 1; - if (aib->esw.psc1 == 1) - aib->esw.psc1 = 2; - else if (aib->esw.psc1 == 0 && aib->esw.p == 1) - aib->esw.psc1 = 1; -} - -/* - * Check if the aib a2 is still connected to the same attachment as - * aib a1, the etv values differ by one and a2 is valid. - */ -static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p) -{ - int state_a1, state_a2; - - /* Paranoia check: e0/e1 should better be the same. */ - if (a1->esw.eacr.e0 != a2->esw.eacr.e0 || - a1->esw.eacr.e1 != a2->esw.eacr.e1) - return 0; - - /* Still connected to the same etr ? */ - state_a1 = p ? a1->esw.psc1 : a1->esw.psc0; - state_a2 = p ? a2->esw.psc1 : a2->esw.psc0; - if (state_a1 == etr_lpsc_operational_step) { - if (state_a2 != etr_lpsc_operational_step || - a1->edf1.net_id != a2->edf1.net_id || - a1->edf1.etr_id != a2->edf1.etr_id || - a1->edf1.etr_pn != a2->edf1.etr_pn) - return 0; - } else if (state_a2 != etr_lpsc_pps_mode) - return 0; - - /* The ETV value of a2 needs to be ETV of a1 + 1. */ - if (a1->edf2.etv + 1 != a2->edf2.etv) - return 0; - - if (!etr_port_valid(a2, p)) - return 0; - - return 1; -} - -/* - * The time is "clock". xtime is what we think the time is. - * Adjust the value by a multiple of jiffies and add the delta to ntp. - * "delay" is an approximation how long the synchronization took. If - * the time correction is positive, then "delay" is subtracted from - * the time difference and only the remaining part is passed to ntp. - */ -static void etr_adjust_time(unsigned long long clock, unsigned long long delay) -{ - unsigned long long delta, ticks; - struct timex adjust; - - /* - * We don't have to take the xtime lock because the cpu - * executing etr_adjust_time is running disabled in - * tasklet context and all other cpus are looping in - * etr_sync_cpu_start. - */ - if (clock > xtime_cc) { - /* It is later than we thought. */ - delta = ticks = clock - xtime_cc; - delta = ticks = (delta < delay) ? 0 : delta - delay; - delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); - init_timer_cc = init_timer_cc + delta; - jiffies_timer_cc = jiffies_timer_cc + delta; - xtime_cc = xtime_cc + delta; - adjust.offset = ticks * (1000000 / HZ); - } else { - /* It is earlier than we thought. */ - delta = ticks = xtime_cc - clock; - delta -= do_div(ticks, CLK_TICKS_PER_JIFFY); - init_timer_cc = init_timer_cc - delta; - jiffies_timer_cc = jiffies_timer_cc - delta; - xtime_cc = xtime_cc - delta; - adjust.offset = -ticks * (1000000 / HZ); - } - if (adjust.offset != 0) { - printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n", - adjust.offset); - adjust.modes = ADJ_OFFSET_SINGLESHOT; - do_adjtimex(&adjust); - } -} - -static void etr_sync_cpu_start(void *dummy) -{ - int *in_sync = dummy; - - etr_enable_sync_clock(); - /* - * This looks like a busy wait loop but it isn't. etr_sync_cpus - * is called on all other cpus while the TOD clocks is stopped. - * __udelay will stop the cpu on an enabled wait psw until the - * TOD is running again. - */ - while (*in_sync == 0) - __udelay(1); - if (*in_sync != 1) - /* Didn't work. Clear per-cpu in sync bit again. */ - etr_disable_sync_clock(NULL); - /* - * This round of TOD syncing is done. Set the clock comparator - * to the next tick and let the processor continue. - */ - setup_jiffy_timer(); -} - -static void etr_sync_cpu_end(void *dummy) -{ -} - -/* - * Sync the TOD clock using the port refered to by aibp. This port - * has to be enabled and the other port has to be disabled. The - * last eacr update has to be more than 1.6 seconds in the past. - */ -static int etr_sync_clock(struct etr_aib *aib, int port) -{ - struct etr_aib *sync_port; - unsigned long long clock, delay; - int in_sync, follows; - int rc; - - /* Check if the current aib is adjacent to the sync port aib. */ - sync_port = (port == 0) ? &etr_port0 : &etr_port1; - follows = etr_aib_follows(sync_port, aib, port); - memcpy(sync_port, aib, sizeof(*aib)); - if (!follows) - return -EAGAIN; - - /* - * Catch all other cpus and make them wait until we have - * successfully synced the clock. smp_call_function will - * return after all other cpus are in etr_sync_cpu_start. - */ - in_sync = 0; - preempt_disable(); - smp_call_function(etr_sync_cpu_start,&in_sync,0,0); - local_irq_disable(); - etr_enable_sync_clock(); - - /* Set clock to next OTE. */ - __ctl_set_bit(14, 21); - __ctl_set_bit(0, 29); - clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32; - if (set_clock(clock) == 0) { - __udelay(1); /* Wait for the clock to start. */ - __ctl_clear_bit(0, 29); - __ctl_clear_bit(14, 21); - etr_stetr(aib); - /* Adjust Linux timing variables. */ - delay = (unsigned long long) - (aib->edf2.etv - sync_port->edf2.etv) << 32; - etr_adjust_time(clock, delay); - setup_jiffy_timer(); - /* Verify that the clock is properly set. */ - if (!etr_aib_follows(sync_port, aib, port)) { - /* Didn't work. */ - etr_disable_sync_clock(NULL); - in_sync = -EAGAIN; - rc = -EAGAIN; - } else { - in_sync = 1; - rc = 0; - } - } else { - /* Could not set the clock ?!? */ - __ctl_clear_bit(0, 29); - __ctl_clear_bit(14, 21); - etr_disable_sync_clock(NULL); - in_sync = -EAGAIN; - rc = -EAGAIN; - } - local_irq_enable(); - smp_call_function(etr_sync_cpu_end,NULL,0,0); - preempt_enable(); - return rc; -} - -/* - * Handle the immediate effects of the different events. - * The port change event is used for online/offline changes. - */ -static struct etr_eacr etr_handle_events(struct etr_eacr eacr) -{ - if (test_and_clear_bit(ETR_EVENT_SYNC_CHECK, &etr_events)) - eacr.es = 0; - if (test_and_clear_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events)) - eacr.es = eacr.sl = 0; - if (test_and_clear_bit(ETR_EVENT_PORT_ALERT, &etr_events)) - etr_port0_uptodate = etr_port1_uptodate = 0; - - if (test_and_clear_bit(ETR_EVENT_PORT0_CHANGE, &etr_events)) { - if (eacr.e0) - /* - * Port change of an enabled port. We have to - * assume that this can have caused an stepping - * port switch. - */ - etr_tolec = get_clock(); - eacr.p0 = etr_port0_online; - if (!eacr.p0) - eacr.e0 = 0; - etr_port0_uptodate = 0; - } - if (test_and_clear_bit(ETR_EVENT_PORT1_CHANGE, &etr_events)) { - if (eacr.e1) - /* - * Port change of an enabled port. We have to - * assume that this can have caused an stepping - * port switch. - */ - etr_tolec = get_clock(); - eacr.p1 = etr_port1_online; - if (!eacr.p1) - eacr.e1 = 0; - etr_port1_uptodate = 0; - } - clear_bit(ETR_EVENT_UPDATE, &etr_events); - return eacr; -} - -/* - * Set up a timer that expires after the etr_tolec + 1.6 seconds if - * one of the ports needs an update. - */ -static void etr_set_tolec_timeout(unsigned long long now) -{ - unsigned long micros; - - if ((!etr_eacr.p0 || etr_port0_uptodate) && - (!etr_eacr.p1 || etr_port1_uptodate)) - return; - micros = (now > etr_tolec) ? ((now - etr_tolec) >> 12) : 0; - micros = (micros > 1600000) ? 0 : 1600000 - micros; - mod_timer(&etr_timer, jiffies + (micros * HZ) / 1000000 + 1); -} - -/* - * Set up a time that expires after 1/2 second. - */ -static void etr_set_sync_timeout(void) -{ - mod_timer(&etr_timer, jiffies + HZ/2); -} - -/* - * Update the aib information for one or both ports. - */ -static struct etr_eacr etr_handle_update(struct etr_aib *aib, - struct etr_eacr eacr) -{ - /* With both ports disabled the aib information is useless. */ - if (!eacr.e0 && !eacr.e1) - return eacr; - - /* Update port0 or port1 with aib stored in etr_tasklet_fn. */ - if (aib->esw.q == 0) { - /* Information for port 0 stored. */ - if (eacr.p0 && !etr_port0_uptodate) { - etr_port0 = *aib; - if (etr_port0_online) - etr_port0_uptodate = 1; - } - } else { - /* Information for port 1 stored. */ - if (eacr.p1 && !etr_port1_uptodate) { - etr_port1 = *aib; - if (etr_port0_online) - etr_port1_uptodate = 1; - } - } - - /* - * Do not try to get the alternate port aib if the clock - * is not in sync yet. - */ - if (!eacr.es) - return eacr; - - /* - * If steai is available we can get the information about - * the other port immediately. If only stetr is available the - * data-port bit toggle has to be used. - */ - if (test_bit(ETR_FLAG_STEAI, &etr_flags)) { - if (eacr.p0 && !etr_port0_uptodate) { - etr_steai_cv(&etr_port0, ETR_STEAI_PORT_0); - etr_port0_uptodate = 1; - } - if (eacr.p1 && !etr_port1_uptodate) { - etr_steai_cv(&etr_port1, ETR_STEAI_PORT_1); - etr_port1_uptodate = 1; - } - } else { - /* - * One port was updated above, if the other - * port is not uptodate toggle dp bit. - */ - if ((eacr.p0 && !etr_port0_uptodate) || - (eacr.p1 && !etr_port1_uptodate)) - eacr.dp ^= 1; - else - eacr.dp = 0; - } - return eacr; -} - -/* - * Write new etr control register if it differs from the current one. - * Return 1 if etr_tolec has been updated as well. - */ -static void etr_update_eacr(struct etr_eacr eacr) -{ - int dp_changed; - - if (memcmp(&etr_eacr, &eacr, sizeof(eacr)) == 0) - /* No change, return. */ - return; - /* - * The disable of an active port of the change of the data port - * bit can/will cause a change in the data port. - */ - dp_changed = etr_eacr.e0 > eacr.e0 || etr_eacr.e1 > eacr.e1 || - (etr_eacr.dp ^ eacr.dp) != 0; - etr_eacr = eacr; - etr_setr(&etr_eacr); - if (dp_changed) - etr_tolec = get_clock(); -} - -/* - * ETR tasklet. In this function you'll find the main logic. In - * particular this is the only function that calls etr_update_eacr(), - * it "controls" the etr control register. - */ -static void etr_tasklet_fn(unsigned long dummy) -{ - unsigned long long now; - struct etr_eacr eacr; - struct etr_aib aib; - int sync_port; - - /* Create working copy of etr_eacr. */ - eacr = etr_eacr; - - /* Check for the different events and their immediate effects. */ - eacr = etr_handle_events(eacr); - - /* Check if ETR is supposed to be active. */ - eacr.ea = eacr.p0 || eacr.p1; - if (!eacr.ea) { - /* Both ports offline. Reset everything. */ - eacr.dp = eacr.es = eacr.sl = 0; - on_each_cpu(etr_disable_sync_clock, NULL, 0, 1); - del_timer_sync(&etr_timer); - etr_update_eacr(eacr); - set_bit(ETR_FLAG_EACCES, &etr_flags); - return; - } - - /* Store aib to get the current ETR status word. */ - BUG_ON(etr_stetr(&aib) != 0); - etr_port0.esw = etr_port1.esw = aib.esw; /* Copy status word. */ - now = get_clock(); - - /* - * Update the port information if the last stepping port change - * or data port change is older than 1.6 seconds. - */ - if (now >= etr_tolec + (1600000 << 12)) - eacr = etr_handle_update(&aib, eacr); - - /* - * Select ports to enable. The prefered synchronization mode is PPS. - * If a port can be enabled depends on a number of things: - * 1) The port needs to be online and uptodate. A port is not - * disabled just because it is not uptodate, but it is only - * enabled if it is uptodate. - * 2) The port needs to have the same mode (pps / etr). - * 3) The port needs to be usable -> etr_port_valid() == 1 - * 4) To enable the second port the clock needs to be in sync. - * 5) If both ports are useable and are ETR ports, the network id - * has to be the same. - * The eacr.sl bit is used to indicate etr mode vs. pps mode. - */ - if (eacr.p0 && aib.esw.psc0 == etr_lpsc_pps_mode) { - eacr.sl = 0; - eacr.e0 = 1; - if (!etr_mode_is_pps(etr_eacr)) - eacr.es = 0; - if (!eacr.es || !eacr.p1 || aib.esw.psc1 != etr_lpsc_pps_mode) - eacr.e1 = 0; - // FIXME: uptodate checks ? - else if (etr_port0_uptodate && etr_port1_uptodate) - eacr.e1 = 1; - sync_port = (etr_port0_uptodate && - etr_port_valid(&etr_port0, 0)) ? 0 : -1; - clear_bit(ETR_FLAG_EACCES, &etr_flags); - } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_pps_mode) { - eacr.sl = 0; - eacr.e0 = 0; - eacr.e1 = 1; - if (!etr_mode_is_pps(etr_eacr)) - eacr.es = 0; - sync_port = (etr_port1_uptodate && - etr_port_valid(&etr_port1, 1)) ? 1 : -1; - clear_bit(ETR_FLAG_EACCES, &etr_flags); - } else if (eacr.p0 && aib.esw.psc0 == etr_lpsc_operational_step) { - eacr.sl = 1; - eacr.e0 = 1; - if (!etr_mode_is_etr(etr_eacr)) - eacr.es = 0; - if (!eacr.es || !eacr.p1 || - aib.esw.psc1 != etr_lpsc_operational_alt) - eacr.e1 = 0; - else if (etr_port0_uptodate && etr_port1_uptodate && - etr_compare_network(&etr_port0, &etr_port1)) - eacr.e1 = 1; - sync_port = (etr_port0_uptodate && - etr_port_valid(&etr_port0, 0)) ? 0 : -1; - clear_bit(ETR_FLAG_EACCES, &etr_flags); - } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_operational_step) { - eacr.sl = 1; - eacr.e0 = 0; - eacr.e1 = 1; - if (!etr_mode_is_etr(etr_eacr)) - eacr.es = 0; - sync_port = (etr_port1_uptodate && - etr_port_valid(&etr_port1, 1)) ? 1 : -1; - clear_bit(ETR_FLAG_EACCES, &etr_flags); - } else { - /* Both ports not usable. */ - eacr.es = eacr.sl = 0; - sync_port = -1; - set_bit(ETR_FLAG_EACCES, &etr_flags); - } - - /* - * If the clock is in sync just update the eacr and return. - * If there is no valid sync port wait for a port update. - */ - if (eacr.es || sync_port < 0) { - etr_update_eacr(eacr); - etr_set_tolec_timeout(now); - return; - } - - /* - * Prepare control register for clock syncing - * (reset data port bit, set sync check control. - */ - eacr.dp = 0; - eacr.es = 1; - - /* - * Update eacr and try to synchronize the clock. If the update - * of eacr caused a stepping port switch (or if we have to - * assume that a stepping port switch has occured) or the - * clock syncing failed, reset the sync check control bit - * and set up a timer to try again after 0.5 seconds - */ - etr_update_eacr(eacr); - if (now < etr_tolec + (1600000 << 12) || - etr_sync_clock(&aib, sync_port) != 0) { - /* Sync failed. Try again in 1/2 second. */ - eacr.es = 0; - etr_update_eacr(eacr); - etr_set_sync_timeout(); - } else - etr_set_tolec_timeout(now); -} - -/* - * Sysfs interface functions - */ -static struct sysdev_class etr_sysclass = { - set_kset_name("etr") -}; - -static struct sys_device etr_port0_dev = { - .id = 0, - .cls = &etr_sysclass, -}; - -static struct sys_device etr_port1_dev = { - .id = 1, - .cls = &etr_sysclass, -}; - -/* - * ETR class attributes - */ -static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf) -{ - return sprintf(buf, "%i\n", etr_port0.esw.p); -} - -static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL); - -static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf) -{ - char *mode_str; - - if (etr_mode_is_pps(etr_eacr)) - mode_str = "pps"; - else if (etr_mode_is_etr(etr_eacr)) - mode_str = "etr"; - else - mode_str = "local"; - return sprintf(buf, "%s\n", mode_str); -} - -static SYSDEV_CLASS_ATTR(stepping_mode, 0400, etr_stepping_mode_show, NULL); - -/* - * ETR port attributes - */ -static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev) -{ - if (dev == &etr_port0_dev) - return etr_port0_online ? &etr_port0 : NULL; - else - return etr_port1_online ? &etr_port1 : NULL; -} - -static ssize_t etr_online_show(struct sys_device *dev, char *buf) -{ - unsigned int online; - - online = (dev == &etr_port0_dev) ? etr_port0_online : etr_port1_online; - return sprintf(buf, "%i\n", online); -} - -static ssize_t etr_online_store(struct sys_device *dev, - const char *buf, size_t count) -{ - unsigned int value; - - value = simple_strtoul(buf, NULL, 0); - if (value != 0 && value != 1) - return -EINVAL; - if (test_bit(ETR_FLAG_ENOSYS, &etr_flags)) - return -ENOSYS; - if (dev == &etr_port0_dev) { - if (etr_port0_online == value) - return count; /* Nothing to do. */ - etr_port0_online = value; - set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); - } else { - if (etr_port1_online == value) - return count; /* Nothing to do. */ - etr_port1_online = value; - set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); - tasklet_hi_schedule(&etr_tasklet); - } - return count; -} - -static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store); - -static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf) -{ - return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ? - etr_eacr.e0 : etr_eacr.e1); -} - -static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL); - -static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf) -{ - if (!etr_port0_online && !etr_port1_online) - /* Status word is not uptodate if both ports are offline. */ - return -ENODATA; - return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ? - etr_port0.esw.psc0 : etr_port0.esw.psc1); -} - -static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL); - -static ssize_t etr_untuned_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v1) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf1.u); -} - -static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL); - -static ssize_t etr_network_id_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v1) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf1.net_id); -} - -static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL); - -static ssize_t etr_id_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v1) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf1.etr_id); -} - -static SYSDEV_ATTR(id, 0400, etr_id_show, NULL); - -static ssize_t etr_port_number_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v1) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf1.etr_pn); -} - -static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL); - -static ssize_t etr_coupled_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v3) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf3.c); -} - -static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL); - -static ssize_t etr_local_time_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v3) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf3.blto); -} - -static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL); - -static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf) -{ - struct etr_aib *aib = etr_aib_from_dev(dev); - - if (!aib || !aib->slsw.v3) - return -ENODATA; - return sprintf(buf, "%i\n", aib->edf3.buo); -} - -static SYSDEV_ATTR(utc_offset, 0400, etr_utc_offset_show, NULL); - -static struct sysdev_attribute *etr_port_attributes[] = { - &attr_online, - &attr_stepping_control, - &attr_state_code, - &attr_untuned, - &attr_network, - &attr_id, - &attr_port, - &attr_coupled, - &attr_local_time, - &attr_utc_offset, - NULL -}; - -static int __init etr_register_port(struct sys_device *dev) -{ - struct sysdev_attribute **attr; - int rc; - - rc = sysdev_register(dev); - if (rc) - goto out; - for (attr = etr_port_attributes; *attr; attr++) { - rc = sysdev_create_file(dev, *attr); - if (rc) - goto out_unreg; - } - return 0; -out_unreg: - for (; attr >= etr_port_attributes; attr--) - sysdev_remove_file(dev, *attr); - sysdev_unregister(dev); -out: - return rc; -} - -static void __init etr_unregister_port(struct sys_device *dev) -{ - struct sysdev_attribute **attr; - - for (attr = etr_port_attributes; *attr; attr++) - sysdev_remove_file(dev, *attr); - sysdev_unregister(dev); -} - -static int __init etr_init_sysfs(void) -{ - int rc; - - rc = sysdev_class_register(&etr_sysclass); - if (rc) - goto out; - rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_port); - if (rc) - goto out_unreg_class; - rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_mode); - if (rc) - goto out_remove_stepping_port; - rc = etr_register_port(&etr_port0_dev); - if (rc) - goto out_remove_stepping_mode; - rc = etr_register_port(&etr_port1_dev); - if (rc) - goto out_remove_port0; - return 0; - -out_remove_port0: - etr_unregister_port(&etr_port0_dev); -out_remove_stepping_mode: - sysdev_class_remove_file(&etr_sysclass, &attr_stepping_mode); -out_remove_stepping_port: - sysdev_class_remove_file(&etr_sysclass, &attr_stepping_port); -out_unreg_class: - sysdev_class_unregister(&etr_sysclass); -out: - return rc; } -device_initcall(etr_init_sysfs); diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index f0e5a320e2ec..3cbb0dcf1f1d 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -283,7 +283,7 @@ char *task_show_regs(struct task_struct *task, char *buffer) return buffer; } -static DEFINE_SPINLOCK(die_lock); +DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) { @@ -364,7 +364,8 @@ void __kprobes do_single_step(struct pt_regs *regs) force_sig(SIGTRAP, current); } -static void default_trap_handler(struct pt_regs * regs, long interruption_code) +asmlinkage void +default_trap_handler(struct pt_regs * regs, long interruption_code) { if (regs->psw.mask & PSW_MASK_PSTATE) { local_irq_enable(); @@ -375,7 +376,7 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code) } #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \ -static void name(struct pt_regs * regs, long interruption_code) \ +asmlinkage void name(struct pt_regs * regs, long interruption_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ @@ -441,7 +442,7 @@ do_fp_trap(struct pt_regs *regs, void __user *location, "floating point exception", regs, &si); } -static void illegal_op(struct pt_regs * regs, long interruption_code) +asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) { siginfo_t info; __u8 opcode[6]; @@ -490,15 +491,8 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) #endif } else signal = SIGILL; - } else { - /* - * If we get an illegal op in kernel mode, send it through the - * kprobes notifier. If kprobes doesn't pick it up, SIGILL - */ - if (notify_die(DIE_BPT, "bpt", regs, interruption_code, - 3, SIGTRAP) != NOTIFY_STOP) - signal = SIGILL; - } + } else + signal = SIGILL; #ifdef CONFIG_MATHEMU if (signal == SIGFPE) @@ -591,7 +585,7 @@ DO_ERROR_INFO(SIGILL, "specification exception", specification_exception, ILL_ILLOPN, get_check_address(regs)); #endif -static void data_exception(struct pt_regs * regs, long interruption_code) +asmlinkage void data_exception(struct pt_regs * regs, long interruption_code) { __u16 __user *location; int signal = 0; @@ -681,7 +675,7 @@ static void data_exception(struct pt_regs * regs, long interruption_code) } } -static void space_switch_exception(struct pt_regs * regs, long int_code) +asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code) { siginfo_t info; diff --git a/trunk/arch/s390/kernel/vmlinux.lds.S b/trunk/arch/s390/kernel/vmlinux.lds.S index a48907392522..fe0f2e97ba7b 100644 --- a/trunk/arch/s390/kernel/vmlinux.lds.S +++ b/trunk/arch/s390/kernel/vmlinux.lds.S @@ -31,19 +31,18 @@ SECTIONS _etext = .; /* End of text section */ + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + RODATA #ifdef CONFIG_SHARED_KERNEL . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ -#endif - . = ALIGN(4096); _eshared = .; /* End of shareable data */ - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; +#endif .data : { /* Data */ *(.data) diff --git a/trunk/arch/s390/kernel/vtime.c b/trunk/arch/s390/kernel/vtime.c index 9d5b02801b46..21baaf5496d6 100644 --- a/trunk/arch/s390/kernel/vtime.c +++ b/trunk/arch/s390/kernel/vtime.c @@ -25,7 +25,7 @@ #include static ext_int_info_t ext_int_info_timer; -static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); +DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); #ifdef CONFIG_VIRT_CPU_ACCOUNTING /* @@ -524,15 +524,16 @@ EXPORT_SYMBOL(del_virt_timer); void init_cpu_vtimer(void) { struct vtimer_queue *vt_list; + unsigned long cr0; /* kick the virtual timer */ S390_lowcore.exit_timer = VTIMER_MAX_SLICE; S390_lowcore.last_update_timer = VTIMER_MAX_SLICE; asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); - - /* enable cpu timer interrupts */ - __ctl_set_bit(0,10); + __ctl_store(cr0, 0, 0); + cr0 |= 0x400; + __ctl_load(cr0, 0, 0); vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); INIT_LIST_HEAD(&vt_list->list); @@ -571,7 +572,6 @@ void __init vtime_init(void) if (register_idle_notifier(&vtimer_idle_nb)) panic("Couldn't register idle notifier"); - /* Enable cpu timer interrupts on the boot cpu. */ init_cpu_vtimer(); } diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index 7a44fed21b35..b5f94cf3bde8 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,7 +4,7 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o +lib-y += delay.o string.o uaccess_std.o uaccess_pt.o lib-$(CONFIG_32BIT) += div64.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/trunk/arch/s390/lib/delay.c b/trunk/arch/s390/lib/delay.c index 02854449b74b..027c4742a001 100644 --- a/trunk/arch/s390/lib/delay.c +++ b/trunk/arch/s390/lib/delay.c @@ -1,5 +1,5 @@ /* - * arch/s390/lib/delay.c + * arch/s390/kernel/delay.c * Precise Delay Loops for S390 * * S390 version @@ -13,8 +13,10 @@ #include #include -#include -#include + +#ifdef CONFIG_SMP +#include +#endif void __delay(unsigned long loops) { @@ -29,39 +31,17 @@ void __delay(unsigned long loops) } /* - * Waits for 'usecs' microseconds using the TOD clock comparator. + * Waits for 'usecs' microseconds using the tod clock, giving up the time slice + * of the virtual PU inbetween to avoid congestion. */ void __udelay(unsigned long usecs) { - u64 end, time, jiffy_timer = 0; - unsigned long flags, cr0, mask, dummy; - - local_irq_save(flags); - if (raw_irqs_disabled_flags(flags)) { - jiffy_timer = S390_lowcore.jiffy_timer; - S390_lowcore.jiffy_timer = -1ULL - (4096 << 12); - __ctl_store(cr0, 0, 0); - dummy = (cr0 & 0xffff00e0) | 0x00000800; - __ctl_load(dummy , 0, 0); - mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; - } else - mask = psw_kernel_bits | PSW_MASK_WAIT | - PSW_MASK_EXT | PSW_MASK_IO; - - end = get_clock() + ((u64) usecs << 12); - do { - time = end < S390_lowcore.jiffy_timer ? - end : S390_lowcore.jiffy_timer; - set_clock_comparator(time); - trace_hardirqs_on(); - __load_psw_mask(mask); - local_irq_disable(); - } while (get_clock() < end); + uint64_t start_cc; - if (raw_irqs_disabled_flags(flags)) { - __ctl_load(cr0, 0, 0); - S390_lowcore.jiffy_timer = jiffy_timer; - } - set_clock_comparator(S390_lowcore.jiffy_timer); - local_irq_restore(flags); + if (usecs == 0) + return; + start_cc = get_clock(); + do { + cpu_relax(); + } while (((get_clock() - start_cc)/4096) < usecs); } diff --git a/trunk/arch/s390/lib/qrnnd.S b/trunk/arch/s390/lib/qrnnd.S deleted file mode 100644 index eb1df632e749..000000000000 --- a/trunk/arch/s390/lib/qrnnd.S +++ /dev/null @@ -1,77 +0,0 @@ -# S/390 __udiv_qrnnd - -# r2 : &__r -# r3 : upper half of 64 bit word n -# r4 : lower half of 64 bit word n -# r5 : divisor d -# the reminder r of the division is to be stored to &__r and -# the quotient q is to be returned - - .text - .globl __udiv_qrnnd -__udiv_qrnnd: - st %r2,24(%r15) # store pointer to reminder for later - lr %r0,%r3 # reload n - lr %r1,%r4 - ltr %r2,%r5 # reload and test divisor - jp 5f - # divisor >= 0x80000000 - srdl %r0,2 # n/4 - srl %r2,1 # d/2 - slr %r1,%r2 # special case if last bit of d is set - brc 3,0f # (n/4) div (n/2) can overflow by 1 - ahi %r0,-1 # trick: subtract n/2, then divide -0: dr %r0,%r2 # signed division - ahi %r1,1 # trick part 2: add 1 to the quotient - # now (n >> 2) = (d >> 1) * %r1 + %r0 - lhi %r3,1 - nr %r3,%r1 # test last bit of q - jz 1f - alr %r0,%r2 # add (d>>1) to r -1: srl %r1,1 # q >>= 1 - # now (n >> 2) = (d&-2) * %r1 + %r0 - lhi %r3,1 - nr %r3,%r5 # test last bit of d - jz 2f - slr %r0,%r1 # r -= q - brc 3,2f # borrow ? - alr %r0,%r5 # r += d - ahi %r1,-1 -2: # now (n >> 2) = d * %r1 + %r0 - alr %r1,%r1 # q <<= 1 - alr %r0,%r0 # r <<= 1 - brc 12,3f # overflow on r ? - slr %r0,%r5 # r -= d - ahi %r1,1 # q += 1 -3: lhi %r3,2 - nr %r3,%r4 # test next to last bit of n - jz 4f - ahi %r0,1 # r += 1 -4: clr %r0,%r5 # r >= d ? - jl 6f - slr %r0,%r5 # r -= d - ahi %r1,1 # q += 1 - # now (n >> 1) = d * %r1 + %r0 - j 6f -5: # divisor < 0x80000000 - srdl %r0,1 - dr %r0,%r2 # signed division - # now (n >> 1) = d * %r1 + %r0 -6: alr %r1,%r1 # q <<= 1 - alr %r0,%r0 # r <<= 1 - brc 12,7f # overflow on r ? - slr %r0,%r5 # r -= d - ahi %r1,1 # q += 1 -7: lhi %r3,1 - nr %r3,%r4 # isolate last bit of n - alr %r0,%r3 # r += (n & 1) - clr %r0,%r5 # r >= d ? - jl 8f - slr %r0,%r5 # r -= d - ahi %r1,1 # q += 1 -8: # now n = d * %r1 + %r0 - l %r2,24(%r15) - st %r0,0(%r2) - lr %r2,%r1 - br %r14 - .end __udiv_qrnnd diff --git a/trunk/arch/s390/lib/uaccess.h b/trunk/arch/s390/lib/uaccess.h deleted file mode 100644 index 126011df14f1..000000000000 --- a/trunk/arch/s390/lib/uaccess.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/s390/uaccess.h - * - * Copyright IBM Corp. 2007 - * - */ - -#ifndef __ARCH_S390_LIB_UACCESS_H -#define __ARCH_S390_LIB_UACCESS_H - -extern size_t copy_from_user_std(size_t, const void __user *, void *); -extern size_t copy_to_user_std(size_t, void __user *, const void *); -extern size_t strnlen_user_std(size_t, const char __user *); -extern size_t strncpy_from_user_std(size_t, const char __user *, char *); -extern int futex_atomic_cmpxchg_std(int __user *, int, int); -extern int futex_atomic_op_std(int, int __user *, int, int *); - -extern size_t copy_from_user_pt(size_t, const void __user *, void *); -extern size_t copy_to_user_pt(size_t, void __user *, const void *); -extern int futex_atomic_op_pt(int, int __user *, int, int *); -extern int futex_atomic_cmpxchg_pt(int __user *, int, int); - -#endif /* __ARCH_S390_LIB_UACCESS_H */ diff --git a/trunk/arch/s390/lib/uaccess_mvcos.c b/trunk/arch/s390/lib/uaccess_mvcos.c index 6d8772339d76..f9a23d57eb79 100644 --- a/trunk/arch/s390/lib/uaccess_mvcos.c +++ b/trunk/arch/s390/lib/uaccess_mvcos.c @@ -12,7 +12,6 @@ #include #include #include -#include "uaccess.h" #ifndef __s390x__ #define AHI "ahi" @@ -28,7 +27,10 @@ #define SLR "slgr" #endif -static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) +extern size_t copy_from_user_std(size_t, const void __user *, void *); +extern size_t copy_to_user_std(size_t, void __user *, const void *); + +size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) { register unsigned long reg0 asm("0") = 0x81UL; unsigned long tmp1, tmp2; @@ -67,14 +69,14 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) return size; } -static size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x) +size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x) { if (size <= 256) return copy_from_user_std(size, ptr, x); return copy_from_user_mvcos(size, ptr, x); } -static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) +size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) { register unsigned long reg0 asm("0") = 0x810000UL; unsigned long tmp1, tmp2; @@ -103,16 +105,14 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) return size; } -static size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, - const void *x) +size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x) { if (size <= 256) return copy_to_user_std(size, ptr, x); return copy_to_user_mvcos(size, ptr, x); } -static size_t copy_in_user_mvcos(size_t size, void __user *to, - const void __user *from) +size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from) { register unsigned long reg0 asm("0") = 0x810081UL; unsigned long tmp1, tmp2; @@ -134,7 +134,7 @@ static size_t copy_in_user_mvcos(size_t size, void __user *to, return size; } -static size_t clear_user_mvcos(size_t size, void __user *to) +size_t clear_user_mvcos(size_t size, void __user *to) { register unsigned long reg0 asm("0") = 0x810000UL; unsigned long tmp1, tmp2; @@ -162,43 +162,10 @@ static size_t clear_user_mvcos(size_t size, void __user *to) return size; } -static size_t strnlen_user_mvcos(size_t count, const char __user *src) -{ - char buf[256]; - int rc; - size_t done, len, len_str; - - done = 0; - do { - len = min(count - done, (size_t) 256); - rc = uaccess.copy_from_user(len, src + done, buf); - if (unlikely(rc == len)) - return 0; - len -= rc; - len_str = strnlen(buf, len); - done += len_str; - } while ((len_str == len) && (done < count)); - return done + 1; -} - -static size_t strncpy_from_user_mvcos(size_t count, const char __user *src, - char *dst) -{ - int rc; - size_t done, len, len_str; - - done = 0; - do { - len = min(count - done, (size_t) 4096); - rc = uaccess.copy_from_user(len, src + done, dst); - if (unlikely(rc == len)) - return -EFAULT; - len -= rc; - len_str = strnlen(dst, len); - done += len_str; - } while ((len_str == len) && (done < count)); - return done; -} +extern size_t strnlen_user_std(size_t, const char __user *); +extern size_t strncpy_from_user_std(size_t, const char __user *, char *); +extern int futex_atomic_op(int, int __user *, int, int *); +extern int futex_atomic_cmpxchg(int __user *, int, int); struct uaccess_ops uaccess_mvcos = { .copy_from_user = copy_from_user_mvcos_check, @@ -209,21 +176,6 @@ struct uaccess_ops uaccess_mvcos = { .clear_user = clear_user_mvcos, .strnlen_user = strnlen_user_std, .strncpy_from_user = strncpy_from_user_std, - .futex_atomic_op = futex_atomic_op_std, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std, -}; - -#ifdef CONFIG_S390_SWITCH_AMODE -struct uaccess_ops uaccess_mvcos_switch = { - .copy_from_user = copy_from_user_mvcos, - .copy_from_user_small = copy_from_user_mvcos, - .copy_to_user = copy_to_user_mvcos, - .copy_to_user_small = copy_to_user_mvcos, - .copy_in_user = copy_in_user_mvcos, - .clear_user = clear_user_mvcos, - .strnlen_user = strnlen_user_mvcos, - .strncpy_from_user = strncpy_from_user_mvcos, - .futex_atomic_op = futex_atomic_op_pt, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt, + .futex_atomic_op = futex_atomic_op, + .futex_atomic_cmpxchg = futex_atomic_cmpxchg, }; -#endif diff --git a/trunk/arch/s390/lib/uaccess_pt.c b/trunk/arch/s390/lib/uaccess_pt.c index 63181671e3e3..49c3e46b4065 100644 --- a/trunk/arch/s390/lib/uaccess_pt.c +++ b/trunk/arch/s390/lib/uaccess_pt.c @@ -1,8 +1,7 @@ /* * arch/s390/lib/uaccess_pt.c * - * User access functions based on page table walks for enhanced - * system layout without hardware support. + * User access functions based on page table walks. * * Copyright IBM Corp. 2006 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) @@ -13,10 +12,9 @@ #include #include #include -#include "uaccess.h" -static int __handle_fault(struct mm_struct *mm, unsigned long address, - int write_access) +static inline int __handle_fault(struct mm_struct *mm, unsigned long address, + int write_access) { struct vm_area_struct *vma; int ret = -EFAULT; @@ -81,8 +79,8 @@ static int __handle_fault(struct mm_struct *mm, unsigned long address, return ret; } -static size_t __user_copy_pt(unsigned long uaddr, void *kptr, - size_t n, int write_user) +static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, + size_t n, int write_user) { struct mm_struct *mm = current->mm; unsigned long offset, pfn, done, size; @@ -135,49 +133,6 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr, goto retry; } -/* - * Do DAT for user address by page table walk, return kernel address. - * This function needs to be called with current->mm->page_table_lock held. - */ -static unsigned long __dat_user_addr(unsigned long uaddr) -{ - struct mm_struct *mm = current->mm; - unsigned long pfn, ret; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - int rc; - - ret = 0; -retry: - pgd = pgd_offset(mm, uaddr); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - goto fault; - - pmd = pmd_offset(pgd, uaddr); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - goto fault; - - pte = pte_offset_map(pmd, uaddr); - if (!pte || !pte_present(*pte)) - goto fault; - - pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) - goto out; - - ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); -out: - return ret; -fault: - spin_unlock(&mm->page_table_lock); - rc = __handle_fault(mm, uaddr, 0); - spin_lock(&mm->page_table_lock); - if (rc) - goto out; - goto retry; -} - size_t copy_from_user_pt(size_t n, const void __user *from, void *to) { size_t rc; @@ -200,277 +155,3 @@ size_t copy_to_user_pt(size_t n, void __user *to, const void *from) } return __user_copy_pt((unsigned long) to, (void *) from, n, 1); } - -static size_t clear_user_pt(size_t n, void __user *to) -{ - long done, size, ret; - - if (segment_eq(get_fs(), KERNEL_DS)) { - memset((void __kernel __force *) to, 0, n); - return 0; - } - done = 0; - do { - if (n - done > PAGE_SIZE) - size = PAGE_SIZE; - else - size = n - done; - ret = __user_copy_pt((unsigned long) to + done, - &empty_zero_page, size, 1); - done += size; - if (ret) - return ret + n - done; - } while (done < n); - return 0; -} - -static size_t strnlen_user_pt(size_t count, const char __user *src) -{ - char *addr; - unsigned long uaddr = (unsigned long) src; - struct mm_struct *mm = current->mm; - unsigned long offset, pfn, done, len; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - size_t len_str; - - if (segment_eq(get_fs(), KERNEL_DS)) - return strnlen((const char __kernel __force *) src, count) + 1; - done = 0; -retry: - spin_lock(&mm->page_table_lock); - do { - pgd = pgd_offset(mm, uaddr); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - goto fault; - - pmd = pmd_offset(pgd, uaddr); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - goto fault; - - pte = pte_offset_map(pmd, uaddr); - if (!pte || !pte_present(*pte)) - goto fault; - - pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) { - done = -1; - goto out; - } - - offset = uaddr & (PAGE_SIZE-1); - addr = (char *)(pfn << PAGE_SHIFT) + offset; - len = min(count - done, PAGE_SIZE - offset); - len_str = strnlen(addr, len); - done += len_str; - uaddr += len_str; - } while ((len_str == len) && (done < count)); -out: - spin_unlock(&mm->page_table_lock); - return done + 1; -fault: - spin_unlock(&mm->page_table_lock); - if (__handle_fault(mm, uaddr, 0)) { - return 0; - } - goto retry; -} - -static size_t strncpy_from_user_pt(size_t count, const char __user *src, - char *dst) -{ - size_t n = strnlen_user_pt(count, src); - - if (!n) - return -EFAULT; - if (n > count) - n = count; - if (segment_eq(get_fs(), KERNEL_DS)) { - memcpy(dst, (const char __kernel __force *) src, n); - if (dst[n-1] == '\0') - return n-1; - else - return n; - } - if (__user_copy_pt((unsigned long) src, dst, n, 0)) - return -EFAULT; - if (dst[n-1] == '\0') - return n-1; - else - return n; -} - -static size_t copy_in_user_pt(size_t n, void __user *to, - const void __user *from) -{ - struct mm_struct *mm = current->mm; - unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to, - uaddr, done, size; - unsigned long uaddr_from = (unsigned long) from; - unsigned long uaddr_to = (unsigned long) to; - pgd_t *pgd_from, *pgd_to; - pmd_t *pmd_from, *pmd_to; - pte_t *pte_from, *pte_to; - int write_user; - - done = 0; -retry: - spin_lock(&mm->page_table_lock); - do { - pgd_from = pgd_offset(mm, uaddr_from); - if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) { - uaddr = uaddr_from; - write_user = 0; - goto fault; - } - pgd_to = pgd_offset(mm, uaddr_to); - if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) { - uaddr = uaddr_to; - write_user = 1; - goto fault; - } - - pmd_from = pmd_offset(pgd_from, uaddr_from); - if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) { - uaddr = uaddr_from; - write_user = 0; - goto fault; - } - pmd_to = pmd_offset(pgd_to, uaddr_to); - if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) { - uaddr = uaddr_to; - write_user = 1; - goto fault; - } - - pte_from = pte_offset_map(pmd_from, uaddr_from); - if (!pte_from || !pte_present(*pte_from)) { - uaddr = uaddr_from; - write_user = 0; - goto fault; - } - pte_to = pte_offset_map(pmd_to, uaddr_to); - if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) { - uaddr = uaddr_to; - write_user = 1; - goto fault; - } - - pfn_from = pte_pfn(*pte_from); - if (!pfn_valid(pfn_from)) - goto out; - pfn_to = pte_pfn(*pte_to); - if (!pfn_valid(pfn_to)) - goto out; - - offset_from = uaddr_from & (PAGE_SIZE-1); - offset_to = uaddr_from & (PAGE_SIZE-1); - offset_max = max(offset_from, offset_to); - size = min(n - done, PAGE_SIZE - offset_max); - - memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to, - (void *)(pfn_from << PAGE_SHIFT) + offset_from, size); - done += size; - uaddr_from += size; - uaddr_to += size; - } while (done < n); -out: - spin_unlock(&mm->page_table_lock); - return n - done; -fault: - spin_unlock(&mm->page_table_lock); - if (__handle_fault(mm, uaddr, write_user)) - return n - done; - goto retry; -} - -#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ - asm volatile("0: l %1,0(%6)\n" \ - "1: " insn \ - "2: cs %1,%2,0(%6)\n" \ - "3: jl 1b\n" \ - " lhi %0,0\n" \ - "4:\n" \ - EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b) \ - : "=d" (ret), "=&d" (oldval), "=&d" (newval), \ - "=m" (*uaddr) \ - : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ - "m" (*uaddr) : "cc" ); - -int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old) -{ - int oldval = 0, newval, ret; - - spin_lock(¤t->mm->page_table_lock); - uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr); - if (!uaddr) { - spin_unlock(¤t->mm->page_table_lock); - return -EFAULT; - } - get_page(virt_to_page(uaddr)); - spin_unlock(¤t->mm->page_table_lock); - switch (op) { - case FUTEX_OP_SET: - __futex_atomic_op("lr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_ADD: - __futex_atomic_op("lr %2,%1\nar %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_OR: - __futex_atomic_op("lr %2,%1\nor %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_ANDN: - __futex_atomic_op("lr %2,%1\nnr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_XOR: - __futex_atomic_op("lr %2,%1\nxr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - default: - ret = -ENOSYS; - } - put_page(virt_to_page(uaddr)); - *old = oldval; - return ret; -} - -int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval) -{ - int ret; - - spin_lock(¤t->mm->page_table_lock); - uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr); - if (!uaddr) { - spin_unlock(¤t->mm->page_table_lock); - return -EFAULT; - } - get_page(virt_to_page(uaddr)); - spin_unlock(¤t->mm->page_table_lock); - asm volatile(" cs %1,%4,0(%5)\n" - "0: lr %0,%1\n" - "1:\n" - EX_TABLE(0b,1b) - : "=d" (ret), "+d" (oldval), "=m" (*uaddr) - : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) - : "cc", "memory" ); - put_page(virt_to_page(uaddr)); - return ret; -} - -struct uaccess_ops uaccess_pt = { - .copy_from_user = copy_from_user_pt, - .copy_from_user_small = copy_from_user_pt, - .copy_to_user = copy_to_user_pt, - .copy_to_user_small = copy_to_user_pt, - .copy_in_user = copy_in_user_pt, - .clear_user = clear_user_pt, - .strnlen_user = strnlen_user_pt, - .strncpy_from_user = strncpy_from_user_pt, - .futex_atomic_op = futex_atomic_op_pt, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt, -}; diff --git a/trunk/arch/s390/lib/uaccess_std.c b/trunk/arch/s390/lib/uaccess_std.c index 28c4500a58d0..56a0214e9928 100644 --- a/trunk/arch/s390/lib/uaccess_std.c +++ b/trunk/arch/s390/lib/uaccess_std.c @@ -13,7 +13,6 @@ #include #include #include -#include "uaccess.h" #ifndef __s390x__ #define AHI "ahi" @@ -29,6 +28,9 @@ #define SLR "slgr" #endif +extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to); +extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from); + size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) { unsigned long tmp1, tmp2; @@ -70,8 +72,7 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) return size; } -static size_t copy_from_user_std_check(size_t size, const void __user *ptr, - void *x) +size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x) { if (size <= 1024) return copy_from_user_std(size, ptr, x); @@ -109,16 +110,14 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) return size; } -static size_t copy_to_user_std_check(size_t size, void __user *ptr, - const void *x) +size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x) { if (size <= 1024) return copy_to_user_std(size, ptr, x); return copy_to_user_pt(size, ptr, x); } -static size_t copy_in_user_std(size_t size, void __user *to, - const void __user *from) +size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) { unsigned long tmp1; @@ -149,7 +148,7 @@ static size_t copy_in_user_std(size_t size, void __user *to, return size; } -static size_t clear_user_std(size_t size, void __user *to) +size_t clear_user_std(size_t size, void __user *to) { unsigned long tmp1, tmp2; @@ -255,7 +254,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst) : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ "m" (*uaddr) : "cc"); -int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old) +int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) { int oldval = 0, newval, ret; @@ -287,7 +286,7 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old) return ret; } -int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval) +int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval) { int ret; @@ -312,6 +311,6 @@ struct uaccess_ops uaccess_std = { .clear_user = clear_user_std, .strnlen_user = strnlen_user_std, .strncpy_from_user = strncpy_from_user_std, - .futex_atomic_op = futex_atomic_op_std, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std, + .futex_atomic_op = futex_atomic_op, + .futex_atomic_cmpxchg = futex_atomic_cmpxchg, }; diff --git a/trunk/arch/s390/math-emu/Makefile b/trunk/arch/s390/math-emu/Makefile index 73b3e72efc46..c10df144f2ab 100644 --- a/trunk/arch/s390/math-emu/Makefile +++ b/trunk/arch/s390/math-emu/Makefile @@ -2,7 +2,7 @@ # Makefile for the FPU instruction emulation. # -obj-$(CONFIG_MATHEMU) := math.o +obj-$(CONFIG_MATHEMU) := math.o qrnnd.o EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w EXTRA_AFLAGS := -traditional diff --git a/trunk/arch/s390/math-emu/math.c b/trunk/arch/s390/math-emu/math.c index 3ee78ccb617d..6b9aec5a2c18 100644 --- a/trunk/arch/s390/math-emu/math.c +++ b/trunk/arch/s390/math-emu/math.c @@ -15,7 +15,7 @@ #include #include -#include +#include "sfp-util.h" #include #include #include diff --git a/trunk/arch/s390/math-emu/qrnnd.S b/trunk/arch/s390/math-emu/qrnnd.S new file mode 100644 index 000000000000..b01c2b648e22 --- /dev/null +++ b/trunk/arch/s390/math-emu/qrnnd.S @@ -0,0 +1,77 @@ +# S/390 __udiv_qrnnd + +# r2 : &__r +# r3 : upper half of 64 bit word n +# r4 : lower half of 64 bit word n +# r5 : divisor d +# the reminder r of the division is to be stored to &__r and +# the quotient q is to be returned + + .text + .globl __udiv_qrnnd +__udiv_qrnnd: + st %r2,24(%r15) # store pointer to reminder for later + lr %r0,%r3 # reload n + lr %r1,%r4 + ltr %r2,%r5 # reload and test divisor + jp 5f + # divisor >= 0x80000000 + srdl %r0,2 # n/4 + srl %r2,1 # d/2 + slr %r1,%r2 # special case if last bit of d is set + brc 3,0f # (n/4) div (n/2) can overflow by 1 + ahi %r0,-1 # trick: subtract n/2, then divide +0: dr %r0,%r2 # signed division + ahi %r1,1 # trick part 2: add 1 to the quotient + # now (n >> 2) = (d >> 1) * %r1 + %r0 + lhi %r3,1 + nr %r3,%r1 # test last bit of q + jz 1f + alr %r0,%r2 # add (d>>1) to r +1: srl %r1,1 # q >>= 1 + # now (n >> 2) = (d&-2) * %r1 + %r0 + lhi %r3,1 + nr %r3,%r5 # test last bit of d + jz 2f + slr %r0,%r1 # r -= q + brc 3,2f # borrow ? + alr %r0,%r5 # r += d + ahi %r1,-1 +2: # now (n >> 2) = d * %r1 + %r0 + alr %r1,%r1 # q <<= 1 + alr %r0,%r0 # r <<= 1 + brc 12,3f # overflow on r ? + slr %r0,%r5 # r -= d + ahi %r1,1 # q += 1 +3: lhi %r3,2 + nr %r3,%r4 # test next to last bit of n + jz 4f + ahi %r0,1 # r += 1 +4: clr %r0,%r5 # r >= d ? + jl 6f + slr %r0,%r5 # r -= d + ahi %r1,1 # q += 1 + # now (n >> 1) = d * %r1 + %r0 + j 6f +5: # divisor < 0x80000000 + srdl %r0,1 + dr %r0,%r2 # signed division + # now (n >> 1) = d * %r1 + %r0 +6: alr %r1,%r1 # q <<= 1 + alr %r0,%r0 # r <<= 1 + brc 12,7f # overflow on r ? + slr %r0,%r5 # r -= d + ahi %r1,1 # q += 1 +7: lhi %r3,1 + nr %r3,%r4 # isolate last bit of n + alr %r0,%r3 # r += (n & 1) + clr %r0,%r5 # r >= d ? + jl 8f + slr %r0,%r5 # r -= d + ahi %r1,1 # q += 1 +8: # now n = d * %r1 + %r0 + l %r2,24(%r15) + st %r0,0(%r2) + lr %r2,%r1 + br %r14 + .end __udiv_qrnnd diff --git a/trunk/include/asm-s390/sfp-util.h b/trunk/arch/s390/math-emu/sfp-util.h similarity index 91% rename from trunk/include/asm-s390/sfp-util.h rename to trunk/arch/s390/math-emu/sfp-util.h index 8cabcd23d976..5b6ca4570ea4 100644 --- a/trunk/include/asm-s390/sfp-util.h +++ b/trunk/arch/s390/math-emu/sfp-util.h @@ -52,12 +52,12 @@ }) #define udiv_qrnnd(q, r, n1, n0, d) \ - do { unsigned int __r; \ + do { unsigned long __r; \ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ (r) = __r; \ } while (0) -extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, - unsigned int , unsigned int); +extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long, + unsigned long , unsigned long); #define UDIV_NEEDS_NORMALIZATION 0 diff --git a/trunk/arch/s390/mm/cmm.c b/trunk/arch/s390/mm/cmm.c index f93a056869bc..607f50ead1fd 100644 --- a/trunk/arch/s390/mm/cmm.c +++ b/trunk/arch/s390/mm/cmm.c @@ -245,7 +245,7 @@ cmm_set_timeout(long nr, long seconds) cmm_set_timer(); } -static int +static inline int cmm_skip_blanks(char *cp, char **endp) { char *str; @@ -414,7 +414,7 @@ cmm_smsg_target(char *from, char *msg) } #endif -static struct ctl_table_header *cmm_sysctl_header; +struct ctl_table_header *cmm_sysctl_header; static int cmm_init (void) diff --git a/trunk/arch/s390/mm/extmem.c b/trunk/arch/s390/mm/extmem.c index 394980b05e6f..775bf19e742b 100644 --- a/trunk/arch/s390/mm/extmem.c +++ b/trunk/arch/s390/mm/extmem.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +70,6 @@ struct qin64 { struct dcss_segment { struct list_head list; char dcss_name[8]; - char res_name[15]; unsigned long start_addr; unsigned long end; atomic_t ref_count; @@ -79,7 +77,6 @@ struct dcss_segment { unsigned int vm_segtype; struct qrange range[6]; int segcnt; - struct resource *res; }; static DEFINE_MUTEX(dcss_lock); @@ -91,7 +88,7 @@ static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", * Create the 8 bytes, ebcdic VM segment name from * an ascii name. */ -static void +static void inline dcss_mkname(char *name, char *dcss_name) { int i; @@ -306,29 +303,6 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long goto out_free; } - seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL); - if (seg->res == NULL) { - rc = -ENOMEM; - goto out_shared; - } - seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; - seg->res->start = seg->start_addr; - seg->res->end = seg->end; - memcpy(&seg->res_name, seg->dcss_name, 8); - EBCASC(seg->res_name, 8); - seg->res_name[8] = '\0'; - strncat(seg->res_name, " (DCSS)", 7); - seg->res->name = seg->res_name; - rc = seg->vm_segtype; - if (rc == SEG_TYPE_SC || - ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) - seg->res->flags |= IORESOURCE_READONLY; - if (request_resource(&iomem_resource, seg->res)) { - rc = -EBUSY; - kfree(seg->res); - goto out_shared; - } - if (do_nonshared) dcss_command = DCSS_LOADNSR; else @@ -342,11 +316,12 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long rc = dcss_diag_translate_rc (seg->end); dcss_diag(DCSS_PURGESEG, seg->dcss_name, &seg->start_addr, &seg->end); - goto out_resource; + goto out_shared; } seg->do_nonshared = do_nonshared; atomic_set(&seg->ref_count, 1); list_add(&seg->list, &dcss_list); + rc = seg->vm_segtype; *addr = seg->start_addr; *end = seg->end; if (do_nonshared) @@ -354,16 +329,12 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long "type %s in non-shared mode\n", name, (void*)seg->start_addr, (void*)seg->end, segtype_string[seg->vm_segtype]); - else { + else PRINT_INFO ("segment_load: loaded segment %s range %p .. %p " "type %s in shared mode\n", name, (void*)seg->start_addr, (void*)seg->end, segtype_string[seg->vm_segtype]); - } goto out; - out_resource: - release_resource(seg->res); - kfree(seg->res); out_shared: remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); out_free: @@ -430,7 +401,6 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, * -ENOENT : no such segment (segment gone!) * -EAGAIN : segment is in use by other exploiters, try later * -EINVAL : no segment with the given name is currently loaded - name invalid - * -EBUSY : segment can temporarily not be used (overlaps with dcss) * 0 : operation succeeded */ int @@ -458,24 +428,12 @@ segment_modify_shared (char *name, int do_nonshared) rc = -EAGAIN; goto out_unlock; } - release_resource(seg->res); - if (do_nonshared) { + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); + if (do_nonshared) dcss_command = DCSS_LOADNSR; - seg->res->flags &= ~IORESOURCE_READONLY; - } else { - dcss_command = DCSS_LOADNOLY; - if (seg->vm_segtype == SEG_TYPE_SR || - seg->vm_segtype == SEG_TYPE_ER) - seg->res->flags |= IORESOURCE_READONLY; - } - if (request_resource(&iomem_resource, seg->res)) { - PRINT_WARN("segment_modify_shared: could not reload segment %s" - " - overlapping resources\n", name); - rc = -EBUSY; - kfree(seg->res); - goto out_del; - } - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + else + dcss_command = DCSS_LOADNOLY; diag_cc = dcss_diag(dcss_command, seg->dcss_name, &seg->start_addr, &seg->end); if (diag_cc > 1) { @@ -488,9 +446,9 @@ segment_modify_shared (char *name, int do_nonshared) rc = 0; goto out_unlock; out_del: - remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); kfree(seg); out_unlock: mutex_unlock(&dcss_lock); @@ -520,8 +478,6 @@ segment_unload(char *name) } if (atomic_dec_return(&seg->ref_count) != 0) goto out_unlock; - release_resource(seg->res); - kfree(seg->res); remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); list_del(&seg->list); dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index 9ff143e87746..cd85e34d8703 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -52,7 +52,7 @@ extern int sysctl_userprocess_debug; extern void die(const char *,struct pt_regs *,long); #ifdef CONFIG_KPROBES -static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); int register_page_fault_notifier(struct notifier_block *nb) { return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); @@ -137,9 +137,7 @@ static int __check_access_register(struct pt_regs *regs, int error_code) /* * Check which address space the address belongs to. - * May return 1 or 2 for user space and 0 for kernel space. - * Returns 2 for user space in primary addressing mode with - * CONFIG_S390_EXEC_PROTECT on and kernel parameter noexec=on. + * Returns 1 for user space and 0 for kernel space. */ static inline int check_user_space(struct pt_regs *regs, int error_code) { @@ -156,7 +154,7 @@ static inline int check_user_space(struct pt_regs *regs, int error_code) return __check_access_register(regs, error_code); if (descriptor == 2) return current->thread.mm_segment.ar4; - return ((descriptor != 0) ^ (switch_amode)) << s390_noexec; + return descriptor != 0; } /* @@ -185,77 +183,6 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, force_sig_info(SIGSEGV, &si, current); } -#ifdef CONFIG_S390_EXEC_PROTECT -extern long sys_sigreturn(struct pt_regs *regs); -extern long sys_rt_sigreturn(struct pt_regs *regs); -extern long sys32_sigreturn(struct pt_regs *regs); -extern long sys32_rt_sigreturn(struct pt_regs *regs); - -static inline void do_sigreturn(struct mm_struct *mm, struct pt_regs *regs, - int rt) -{ - up_read(&mm->mmap_sem); - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); -#ifdef CONFIG_COMPAT - if (test_tsk_thread_flag(current, TIF_31BIT)) { - if (rt) - sys32_rt_sigreturn(regs); - else - sys32_sigreturn(regs); - return; - } -#endif /* CONFIG_COMPAT */ - if (rt) - sys_rt_sigreturn(regs); - else - sys_sigreturn(regs); - return; -} - -static int signal_return(struct mm_struct *mm, struct pt_regs *regs, - unsigned long address, unsigned long error_code) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - u16 *instruction; - unsigned long pfn, uaddr = regs->psw.addr; - - spin_lock(&mm->page_table_lock); - pgd = pgd_offset(mm, uaddr); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) - goto out_fault; - pmd = pmd_offset(pgd, uaddr); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) - goto out_fault; - pte = pte_offset_map(pmd_offset(pgd_offset(mm, uaddr), uaddr), uaddr); - if (!pte || !pte_present(*pte)) - goto out_fault; - pfn = pte_pfn(*pte); - if (!pfn_valid(pfn)) - goto out_fault; - spin_unlock(&mm->page_table_lock); - - instruction = (u16 *) ((pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE-1))); - if (*instruction == 0x0a77) - do_sigreturn(mm, regs, 0); - else if (*instruction == 0x0aad) - do_sigreturn(mm, regs, 1); - else { - printk("- XXX - do_exception: task = %s, primary, NO EXEC " - "-> SIGSEGV\n", current->comm); - up_read(&mm->mmap_sem); - current->thread.prot_addr = address; - current->thread.trap_no = error_code; - do_sigsegv(regs, error_code, SEGV_MAPERR, address); - } - return 0; -out_fault: - spin_unlock(&mm->page_table_lock); - return -EFAULT; -} -#endif /* CONFIG_S390_EXEC_PROTECT */ - /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -333,17 +260,6 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) vma = find_vma(mm, address); if (!vma) goto bad_area; - -#ifdef CONFIG_S390_EXEC_PROTECT - if (unlikely((user_address == 2) && !(vma->vm_flags & VM_EXEC))) - if (!signal_return(mm, regs, address, error_code)) - /* - * signal_return() has done an up_read(&mm->mmap_sem) - * if it returns 0. - */ - return; -#endif - if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) @@ -536,7 +452,8 @@ void pfault_fini(void) : : "a" (&refbk), "m" (refbk) : "cc"); } -static void pfault_interrupt(__u16 error_code) +asmlinkage void +pfault_interrupt(__u16 error_code) { struct task_struct *tsk; __u16 subcode; diff --git a/trunk/arch/s390/mm/init.c b/trunk/arch/s390/mm/init.c index b3e7c45efb63..4bb21be3b007 100644 --- a/trunk/arch/s390/mm/init.c +++ b/trunk/arch/s390/mm/init.c @@ -25,7 +25,7 @@ #include #include #include -#include + #include #include #include @@ -95,18 +95,20 @@ static void __init setup_ro_region(void) pte_t new_pte; unsigned long address, end; - address = ((unsigned long)&_stext) & PAGE_MASK; - end = PFN_ALIGN((unsigned long)&_eshared); + address = ((unsigned long)&__start_rodata) & PAGE_MASK; + end = PFN_ALIGN((unsigned long)&__end_rodata); for (; address < end; address += PAGE_SIZE) { pgd = pgd_offset_k(address); pmd = pmd_offset(pgd, address); pte = pte_offset_kernel(pmd, address); new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO)); - *pte = new_pte; + set_pte(pte, new_pte); } } +extern void vmem_map_init(void); + /* * paging_init() sets up the page tables */ @@ -123,11 +125,11 @@ void __init paging_init(void) #ifdef CONFIG_64BIT pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE; for (i = 0; i < PTRS_PER_PGD; i++) - pgd_clear_kernel(pg_dir + i); + pgd_clear(pg_dir + i); #else pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; for (i = 0; i < PTRS_PER_PGD; i++) - pmd_clear_kernel((pmd_t *)(pg_dir + i)); + pmd_clear((pmd_t *)(pg_dir + i)); #endif vmem_map_init(); setup_ro_region(); @@ -172,8 +174,10 @@ void __init mem_init(void) datasize >>10, initsize >> 10); printk("Write protected kernel read-only data: %#lx - %#lx\n", - (unsigned long)&_stext, - PFN_ALIGN((unsigned long)&_eshared) - 1); + (unsigned long)&__start_rodata, + PFN_ALIGN((unsigned long)&__end_rodata) - 1); + printk("Virtual memmap size: %ldk\n", + (max_pfn * sizeof(struct page)) >> 10); } void free_initmem(void) diff --git a/trunk/arch/s390/mm/vmem.c b/trunk/arch/s390/mm/vmem.c index 92a565190028..cd3d93e8c211 100644 --- a/trunk/arch/s390/mm/vmem.c +++ b/trunk/arch/s390/mm/vmem.c @@ -82,7 +82,7 @@ static inline pmd_t *vmem_pmd_alloc(void) if (!pmd) return NULL; for (i = 0; i < PTRS_PER_PMD; i++) - pmd_clear_kernel(pmd + i); + pmd_clear(pmd + i); return pmd; } @@ -97,7 +97,7 @@ static inline pte_t *vmem_pte_alloc(void) return NULL; pte_val(empty_pte) = _PAGE_TYPE_EMPTY; for (i = 0; i < PTRS_PER_PTE; i++) - pte[i] = empty_pte; + set_pte(pte + i, empty_pte); return pte; } @@ -119,7 +119,7 @@ static int vmem_add_range(unsigned long start, unsigned long size) pm_dir = vmem_pmd_alloc(); if (!pm_dir) goto out; - pgd_populate_kernel(&init_mm, pg_dir, pm_dir); + pgd_populate(&init_mm, pg_dir, pm_dir); } pm_dir = pmd_offset(pg_dir, address); @@ -132,7 +132,7 @@ static int vmem_add_range(unsigned long start, unsigned long size) pt_dir = pte_offset_kernel(pm_dir, address); pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL); - *pt_dir = pte; + set_pte(pt_dir, pte); } ret = 0; out: @@ -161,7 +161,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size) if (pmd_none(*pm_dir)) continue; pt_dir = pte_offset_kernel(pm_dir, address); - *pt_dir = pte; + set_pte(pt_dir, pte); } flush_tlb_kernel_range(start, start + size); } @@ -191,7 +191,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) pm_dir = vmem_pmd_alloc(); if (!pm_dir) goto out; - pgd_populate_kernel(&init_mm, pg_dir, pm_dir); + pgd_populate(&init_mm, pg_dir, pm_dir); } pm_dir = pmd_offset(pg_dir, address); @@ -210,7 +210,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) if (!new_page) goto out; pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL); - *pt_dir = pte; + set_pte(pt_dir, pte); } } ret = 0; diff --git a/trunk/arch/x86_64/kernel/early-quirks.c b/trunk/arch/x86_64/kernel/early-quirks.c index bd30d138113f..49802f1bee94 100644 --- a/trunk/arch/x86_64/kernel/early-quirks.c +++ b/trunk/arch/x86_64/kernel/early-quirks.c @@ -32,7 +32,7 @@ static void via_bugs(void) static int nvidia_hpet_detected __initdata; -static int __init nvidia_hpet_check(struct acpi_table_header *header) +static int __init nvidia_hpet_check(unsigned long phys, unsigned long size) { nvidia_hpet_detected = 1; return 0; @@ -53,7 +53,7 @@ static void nvidia_bugs(void) return; nvidia_hpet_detected = 0; - acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check); + acpi_table_parse(ACPI_HPET, nvidia_hpet_check); if (nvidia_hpet_detected == 0) { acpi_skip_timer_override = 1; printk(KERN_INFO "Nvidia board " diff --git a/trunk/arch/x86_64/kernel/genapic.c b/trunk/arch/x86_64/kernel/genapic.c index 0b3603adf56d..b007433f96bb 100644 --- a/trunk/arch/x86_64/kernel/genapic.c +++ b/trunk/arch/x86_64/kernel/genapic.c @@ -58,8 +58,8 @@ void __init clustered_apic_check(void) * Some x86_64 machines use physical APIC mode regardless of how many * procs/clusters are present (x86_64 ES7000 is an example). */ - if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID) - if (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) { + if (acpi_fadt.revision > FADT2_REVISION_ID) + if (acpi_fadt.force_apic_physical_destination_mode) { genapic = &apic_cluster; goto print; } diff --git a/trunk/arch/x86_64/kernel/mpparse.c b/trunk/arch/x86_64/kernel/mpparse.c index 50dd8bef850e..08072568847d 100644 --- a/trunk/arch/x86_64/kernel/mpparse.c +++ b/trunk/arch/x86_64/kernel/mpparse.c @@ -798,7 +798,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) return gsi; /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_gbl_FADT.sci_interrupt == gsi) + if (acpi_fadt.sci_int == gsi) return gsi; ioapic = mp_find_ioapic(gsi); diff --git a/trunk/arch/x86_64/kernel/pci-swiotlb.c b/trunk/arch/x86_64/kernel/pci-swiotlb.c index eb18be5a6569..697f0aa794b9 100644 --- a/trunk/arch/x86_64/kernel/pci-swiotlb.c +++ b/trunk/arch/x86_64/kernel/pci-swiotlb.c @@ -29,7 +29,7 @@ struct dma_mapping_ops swiotlb_dma_ops = { .dma_supported = NULL, }; -void __init pci_swiotlb_init(void) +void pci_swiotlb_init(void) { /* don't initialize swiotlb if iommu=off (no_iommu=1) */ if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN) diff --git a/trunk/arch/x86_64/kernel/time.c b/trunk/arch/x86_64/kernel/time.c index 335cc91c49b7..5cc76d0d331f 100644 --- a/trunk/arch/x86_64/kernel/time.c +++ b/trunk/arch/x86_64/kernel/time.c @@ -498,7 +498,7 @@ static unsigned long get_cmos_time(void) { unsigned int year, mon, day, hour, min, sec; unsigned long flags; - unsigned century = 0; + unsigned extyear = 0; spin_lock_irqsave(&rtc_lock, flags); @@ -510,9 +510,9 @@ static unsigned long get_cmos_time(void) mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); #ifdef CONFIG_ACPI - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - acpi_gbl_FADT.century) - century = CMOS_READ(acpi_gbl_FADT.century); + if (acpi_fadt.revision >= FADT2_REVISION_ID && + acpi_fadt.century) + extyear = CMOS_READ(acpi_fadt.century); #endif } while (sec != CMOS_READ(RTC_SECONDS)); @@ -530,10 +530,10 @@ static unsigned long get_cmos_time(void) BCD_TO_BIN(mon); BCD_TO_BIN(year); - if (century) { - BCD_TO_BIN(century); - year += century * 100; - printk(KERN_INFO "Extended CMOS year: %d\n", century * 100); + if (extyear) { + BCD_TO_BIN(extyear); + year += extyear; + printk(KERN_INFO "Extended CMOS year: %d\n", extyear); } else { /* * x86-64 systems only exists since 2002. @@ -954,7 +954,7 @@ __cpuinit int unsynchronized_tsc(void) if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { #ifdef CONFIG_ACPI /* But TSC doesn't tick in C3 so don't use it there */ - if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000) + if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 1000) return 1; #endif return 0; diff --git a/trunk/arch/x86_64/mm/srat.c b/trunk/arch/x86_64/mm/srat.c index 2efe215fc76a..1087e150a218 100644 --- a/trunk/arch/x86_64/mm/srat.c +++ b/trunk/arch/x86_64/mm/srat.c @@ -101,7 +101,7 @@ static __init inline int srat_disabled(void) static __init int slit_valid(struct acpi_table_slit *slit) { int i, j; - int d = slit->locality_count; + int d = slit->localities; for (i = 0; i < d; i++) { for (j = 0; j < d; j++) { u8 val = slit->entry[d*i + j]; @@ -127,18 +127,18 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) /* Callback for Proximity Domain -> LAPIC mapping */ void __init -acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) +acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) { int pxm, node; if (srat_disabled()) return; - if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) { + if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { bad_srat(); return; } - if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) + if (pa->flags.enabled == 0) return; - pxm = pa->proximity_domain_lo; + pxm = pa->proximity_domain; node = setup_node(pxm); if (node < 0) { printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); @@ -254,21 +254,21 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end) /* Looks good */ if (nd->start == nd->end) { - nd->start = start; - nd->end = end; + nd->start = start; + nd->end = end; changed = 1; - } else { - if (nd->start == end) { - nd->start = start; + } else { + if (nd->start == end) { + nd->start = start; changed = 1; } - if (nd->end == start) { - nd->end = end; + if (nd->end == start) { + nd->end = end; changed = 1; } if (!changed) printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n"); - } + } ret = update_end_of_memory(nd->end); @@ -279,7 +279,7 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end) /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ void __init -acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) { struct bootnode *nd, oldnode; unsigned long start, end; @@ -288,17 +288,16 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) if (srat_disabled()) return; - if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) { + if (ma->header.length != sizeof(struct acpi_table_memory_affinity)) { bad_srat(); return; } - if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) + if (ma->flags.enabled == 0) return; - - if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info()) + if (ma->flags.hot_pluggable && !save_add_info()) return; - start = ma->base_address; - end = start + ma->length; + start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); + end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); pxm = ma->proximity_domain; node = setup_node(pxm); if (node < 0) { @@ -338,8 +337,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) push_node_boundaries(node, nd->start >> PAGE_SHIFT, nd->end >> PAGE_SHIFT); - if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && - (reserve_hotadd(node, start, end) < 0)) { + if (ma->flags.hot_pluggable && (reserve_hotadd(node, start, end) < 0)) { /* Ignore hotadd region. Undo damage */ printk(KERN_NOTICE "SRAT: Hotplug region ignored\n"); *nd = oldnode; @@ -396,7 +394,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) /* First clean up the node list */ for (i = 0; i < MAX_NUMNODES; i++) { - cutoff_node(i, start, end); + cutoff_node(i, start, end); if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) { unparse_node(i); node_set_offline(i); @@ -428,7 +426,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) if (!node_online(i)) setup_node_bootmem(i, nodes[i].start, nodes[i].end); - for (i = 0; i < NR_CPUS; i++) { + for (i = 0; i < NR_CPUS; i++) { if (cpu_to_node[i] == NUMA_NO_NODE) continue; if (!node_isset(cpu_to_node[i], nodes_parsed)) @@ -463,7 +461,7 @@ int __node_distance(int a, int b) if (!acpi_slit) return a == b ? 10 : 20; - index = acpi_slit->locality_count * node_to_pxm(a); + index = acpi_slit->localities * node_to_pxm(a); return acpi_slit->entry[index + node_to_pxm(b)]; } diff --git a/trunk/arch/x86_64/pci/mmconfig.c b/trunk/arch/x86_64/pci/mmconfig.c index faabb6e87f12..f8b6b2800a62 100644 --- a/trunk/arch/x86_64/pci/mmconfig.c +++ b/trunk/arch/x86_64/pci/mmconfig.c @@ -1,6 +1,6 @@ /* * mmconfig.c - Low-level direct PCI config space access via MMCONFIG - * + * * This is an 64bit optimized version that always keeps the full mmconfig * space mapped. This allows lockless config space operation. */ @@ -25,7 +25,7 @@ static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS); /* Static virtual mapping of the MMCONFIG aperture */ struct mmcfg_virt { - struct acpi_mcfg_allocation *cfg; + struct acpi_table_mcfg_config *cfg; char __iomem *virt; }; static struct mmcfg_virt *pci_mmcfg_virt; @@ -33,14 +33,14 @@ static struct mmcfg_virt *pci_mmcfg_virt; static char __iomem *get_virt(unsigned int seg, unsigned bus) { int cfg_num = -1; - struct acpi_mcfg_allocation *cfg; + struct acpi_table_mcfg_config *cfg; while (1) { ++cfg_num; if (cfg_num >= pci_mmcfg_config_num) break; cfg = pci_mmcfg_virt[cfg_num].cfg; - if (cfg->pci_segment != seg) + if (cfg->pci_segment_group_number != seg) continue; if ((cfg->start_bus_number <= bus) && (cfg->end_bus_number >= bus)) @@ -52,7 +52,7 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) this applies to all busses. */ cfg = &pci_mmcfg_config[0]; if (pci_mmcfg_config_num == 1 && - cfg->pci_segment == 0 && + cfg->pci_segment_group_number == 0 && (cfg->start_bus_number | cfg->end_bus_number) == 0) return pci_mmcfg_virt[0].virt; @@ -170,19 +170,19 @@ void __init pci_mmcfg_init(int type) if ((pci_probe & PCI_PROBE_MMCONF) == 0) return; - acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); + acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); if ((pci_mmcfg_config_num == 0) || (pci_mmcfg_config == NULL) || - (pci_mmcfg_config[0].address == 0)) + (pci_mmcfg_config[0].base_address == 0)) return; /* Only do this check when type 1 works. If it doesn't work assume we run on a Mac and always use MCFG */ - if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address, - pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, + if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n", - (unsigned long)pci_mmcfg_config[0].address); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } @@ -194,16 +194,15 @@ void __init pci_mmcfg_init(int type) } for (i = 0; i < pci_mmcfg_config_num; ++i) { pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address, + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_MAX); if (!pci_mmcfg_virt[i].virt) { printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " "segment %d\n", - pci_mmcfg_config[i].pci_segment); + pci_mmcfg_config[i].pci_segment_group_number); return; } - printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n", - (unsigned long)pci_mmcfg_config[i].address); + printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address); } unreachable_devices(); diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index 918b4d845f93..92ba249f3a5b 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -74,6 +74,14 @@ config CRYPTO_SHA1 help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). +config CRYPTO_SHA1_S390 + tristate "SHA1 digest algorithm (s390)" + depends on S390 + select CRYPTO_ALGAPI + help + This is the s390 hardware accelerated implementation of the + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). + config CRYPTO_SHA256 tristate "SHA256 digest algorithm" select CRYPTO_ALGAPI @@ -83,6 +91,17 @@ config CRYPTO_SHA256 This version of SHA implements a 256 bit hash with 128 bits of security against collision attacks. +config CRYPTO_SHA256_S390 + tristate "SHA256 digest algorithm (s390)" + depends on S390 + select CRYPTO_ALGAPI + help + This is the s390 hardware accelerated implementation of the + SHA256 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 256 bit hash with 128 bits of + security against collision attacks. + config CRYPTO_SHA512 tristate "SHA384 and SHA512 digest algorithms" select CRYPTO_ALGAPI @@ -168,6 +187,14 @@ config CRYPTO_DES help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). +config CRYPTO_DES_S390 + tristate "DES and Triple DES cipher algorithms (s390)" + depends on S390 + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + help + DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). + config CRYPTO_BLOWFISH tristate "Blowfish cipher algorithm" select CRYPTO_ALGAPI @@ -309,6 +336,28 @@ config CRYPTO_AES_X86_64 See for more information. +config CRYPTO_AES_S390 + tristate "AES cipher algorithms (s390)" + depends on S390 + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + help + This is the s390 hardware accelerated implementation of the + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + On s390 the System z9-109 currently only supports the key size + of 128 bit. + config CRYPTO_CAST5 tristate "CAST5 (CAST-128) cipher algorithm" select CRYPTO_ALGAPI diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 20eacc2c9e0e..f4f000abc4e9 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -3,7 +3,6 @@ # menu "ACPI (Advanced Configuration and Power Interface) Support" - depends on !X86_NUMAQ depends on !X86_VISWS depends on !IA64_HP_SIM depends on IA64 || X86 @@ -78,20 +77,6 @@ config ACPI_SLEEP_PROC_SLEEP Create /proc/acpi/sleep Deprecated by /sys/power/state -config ACPI_PROCFS - bool "Procfs interface (deprecated)" - depends on ACPI - default y - ---help--- - Procfs interface for ACPI is made optional for back-compatible. - As the same functions are duplicated in sysfs interface - and this proc interface will be removed some time later, - it's marked as deprecated. - ( /proc/acpi/debug_layer && debug_level are deprecated by - /sys/module/acpi/parameters/debug_layer && debug_level. - /proc/acpi/info is deprecated by - /sys/module/acpi/parameters/acpica_version ) - config ACPI_AC tristate "AC Adapter" depends on X86 @@ -122,7 +107,7 @@ config ACPI_BUTTON config ACPI_VIDEO tristate "Video" - depends on X86 && BACKLIGHT_CLASS_DEVICE + depends on X86 help This driver implement the ACPI Extensions For Display Adapters for integrated graphics devices on motherboard, as specified in @@ -154,13 +139,6 @@ config ACPI_DOCK help This driver adds support for ACPI controlled docking stations -config ACPI_BAY - tristate "Removable Drive Bay (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This driver adds support for ACPI controlled removable drive - bays such as the IBM ultrabay or the Dell Module Bay. - config ACPI_PROCESSOR tristate "Processor" default y @@ -208,22 +186,19 @@ config ACPI_ASUS Note: display switching code is currently considered EXPERIMENTAL, toying with these values may even lock your machine. - + All settings are changed via /proc/acpi/asus directory entries. Owner and group for these entries can be set with asus_uid and asus_gid parameters. - + More information and a userspace daemon for handling the extra buttons at . - + If you have an ACPI-compatible ASUS laptop, say Y or M here. This driver is still under development, so if your laptop is unsupported or something works not quite as expected, please use the mailing list - available on the above page (acpi4asus-user@lists.sourceforge.net). - - NOTE: This driver is deprecated and will probably be removed soon, - use asus-laptop instead. - + available on the above page (acpi4asus-user@lists.sourceforge.net) + config ACPI_IBM tristate "IBM ThinkPad Laptop Extras" depends on X86 diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index 856c32bccacb..bce7ca27b429 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -37,15 +37,13 @@ endif obj-y += sleep/ obj-y += bus.o glue.o -obj-y += scan.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o -obj-$(CONFIG_ACPI_BAY) += bay.o -obj-$(CONFIG_ACPI_VIDEO) += video.o +obj-$(CONFIG_ACPI_VIDEO) += video.o obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o @@ -58,6 +56,7 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o +obj-y += scan.o motherboard.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-y += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += i2c_ec.o sbs.o diff --git a/trunk/drivers/acpi/asus_acpi.c b/trunk/drivers/acpi/asus_acpi.c index 31ad70a6e22e..396140bbbe57 100644 --- a/trunk/drivers/acpi/asus_acpi.c +++ b/trunk/drivers/acpi/asus_acpi.c @@ -26,7 +26,7 @@ * Pontus Fuchs - Helper functions, cleanup * Johann Wiesner - Small compile fixes * John Belmonte - ACPI code for Toshiba laptop was a good starting point. - * �ic Burghard - LED display support for W1N + * Éric Burghard - LED display support for W1N * */ @@ -1128,6 +1128,7 @@ static int asus_model_match(char *model) static int asus_hotk_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; int bsts_result; char *string = NULL; @@ -1141,9 +1142,11 @@ static int asus_hotk_get_info(void) * HID), this bit will be moved. A global variable asus_info contains * the DSDT header. */ - status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) printk(KERN_WARNING " Couldn't get the DSDT table header\n"); + else + asus_info = dsdt.pointer; /* We have to write 0 on init this far for all ASUS models */ if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { @@ -1355,6 +1358,8 @@ static void __exit asus_acpi_exit(void) acpi_bus_unregister_driver(&asus_hotk_driver); remove_proc_entry(PROC_ASUS, acpi_root_dir); + kfree(asus_info); + return; } diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 2f4521a48fe7..5f43e0d14899 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -64,7 +64,7 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); static int acpi_battery_add(struct acpi_device *device); static int acpi_battery_remove(struct acpi_device *device, int type); -static int acpi_battery_resume(struct acpi_device *device); +static int acpi_battery_resume(struct acpi_device *device, int status); static struct acpi_driver acpi_battery_driver = { .name = ACPI_BATTERY_DRIVER_NAME, @@ -753,7 +753,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) } /* this is needed to learn about changes made in suspended state */ -static int acpi_battery_resume(struct acpi_device *device) +static int acpi_battery_resume(struct acpi_device *device, int state) { struct acpi_battery *battery; diff --git a/trunk/drivers/acpi/bay.c b/trunk/drivers/acpi/bay.c deleted file mode 100644 index 667fa1dfa1a3..000000000000 --- a/trunk/drivers/acpi/bay.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * bay.c - ACPI removable drive bay driver - * - * Copyright (C) 2006 Kristen Carlson Accardi - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver" - -ACPI_MODULE_NAME("bay") -MODULE_AUTHOR("Kristen Carlson Accardi"); -MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME); -MODULE_LICENSE("GPL"); -#define ACPI_BAY_CLASS "bay" -#define ACPI_BAY_COMPONENT 0x10000000 -#define _COMPONENT ACPI_BAY_COMPONENT -#define bay_dprintk(h,s) {\ - char prefix[80] = {'\0'};\ - struct acpi_buffer buffer = {sizeof(prefix), prefix};\ - acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ - printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } -static void bay_notify(acpi_handle handle, u32 event, void *data); -static int acpi_bay_add(struct acpi_device *device); -static int acpi_bay_remove(struct acpi_device *device, int type); - -static struct acpi_driver acpi_bay_driver = { - .name = ACPI_BAY_DRIVER_NAME, - .class = ACPI_BAY_CLASS, - .ids = ACPI_BAY_HID, - .ops = { - .add = acpi_bay_add, - .remove = acpi_bay_remove, - }, -}; - -struct bay { - acpi_handle handle; - char *name; - struct list_head list; - struct platform_device *pdev; -}; - -static LIST_HEAD(drive_bays); - - -/***************************************************************************** - * Drive Bay functions * - *****************************************************************************/ -/** - * is_ejectable - see if a device is ejectable - * @handle: acpi handle of the device - * - * If an acpi object has a _EJ0 method, then it is ejectable - */ -static int is_ejectable(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -/** - * bay_present - see if the bay device is present - * @bay: the drive bay - * - * execute the _STA method. - */ -static int bay_present(struct bay *bay) -{ - unsigned long sta; - acpi_status status; - - if (bay) { - status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && sta) - return 1; - } - return 0; -} - -/** - * eject_device - respond to an eject request - * @handle - the device to eject - * - * Call this devices _EJ0 method. - */ -static void eject_device(acpi_handle handle) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - - bay_dprintk(handle, "Ejecting device"); - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0", - &arg_list, NULL))) - pr_debug("Failed to evaluate _EJ0!\n"); -} - -/* - * show_present - read method for "present" file in sysfs - */ -static ssize_t show_present(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct bay *bay = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay)); - -} -DEVICE_ATTR(present, S_IRUGO, show_present, NULL); - -/* - * write_eject - write method for "eject" file in sysfs - */ -static ssize_t write_eject(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bay *bay = dev_get_drvdata(dev); - - if (!count) - return -EINVAL; - - eject_device(bay->handle); - return count; -} -DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject); - -/** - * is_ata - see if a device is an ata device - * @handle: acpi handle of the device - * - * If an acpi object has one of 4 ATA ACPI methods defined, - * then it is an ATA device - */ -static int is_ata(acpi_handle handle) -{ - acpi_handle tmp; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 1; - - return 0; -} - -/** - * parent_is_ata(acpi_handle handle) - * - */ -static int parent_is_ata(acpi_handle handle) -{ - acpi_handle phandle; - - if (acpi_get_parent(handle, &phandle)) - return 0; - - return is_ata(phandle); -} - -/** - * is_ejectable_bay - see if a device is an ejectable drive bay - * @handle: acpi handle of the device - * - * If an acpi object is ejectable and has one of the ACPI ATA - * methods defined, then we can safely call it an ejectable - * drive bay - */ -static int is_ejectable_bay(acpi_handle handle) -{ - if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle)) - return 1; - return 0; -} - -/** - * eject_removable_drive - try to eject this drive - * @dev : the device structure of the drive - * - * If a device is a removable drive that requires an _EJ0 method - * to be executed in order to safely remove from the system, do - * it. ATM - always returns success - */ -int eject_removable_drive(struct device *dev) -{ - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); - - if (handle) { - bay_dprintk(handle, "Got device handle"); - if (is_ejectable_bay(handle)) - eject_device(handle); - } else { - printk("No acpi handle for device\n"); - } - - /* should I return an error code? */ - return 0; -} -EXPORT_SYMBOL_GPL(eject_removable_drive); - -static int acpi_bay_add(struct acpi_device *device) -{ - bay_dprintk(device->handle, "adding bay device"); - strcpy(acpi_device_name(device), "Dockable Bay"); - strcpy(acpi_device_class(device), "bay"); - return 0; -} - -static int acpi_bay_add_fs(struct bay *bay) -{ - int ret; - struct device *dev = &bay->pdev->dev; - - ret = device_create_file(dev, &dev_attr_present); - if (ret) - goto add_fs_err; - ret = device_create_file(dev, &dev_attr_eject); - if (ret) { - device_remove_file(dev, &dev_attr_present); - goto add_fs_err; - } - return 0; - - add_fs_err: - bay_dprintk(bay->handle, "Error adding sysfs files\n"); - return ret; -} - -static void acpi_bay_remove_fs(struct bay *bay) -{ - struct device *dev = &bay->pdev->dev; - - /* cleanup sysfs */ - device_remove_file(dev, &dev_attr_present); - device_remove_file(dev, &dev_attr_eject); -} - -static int bay_is_dock_device(acpi_handle handle) -{ - acpi_handle parent; - - acpi_get_parent(handle, &parent); - - /* if the device or it's parent is dependent on the - * dock, then we are a dock device - */ - return (is_dock_device(handle) || is_dock_device(parent)); -} - -static int bay_add(acpi_handle handle, int id) -{ - acpi_status status; - struct bay *new_bay; - struct platform_device *pdev; - struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); - - bay_dprintk(handle, "Adding notify handler"); - - /* - * Initialize bay device structure - */ - new_bay = kzalloc(GFP_ATOMIC, sizeof(*new_bay)); - INIT_LIST_HEAD(&new_bay->list); - new_bay->handle = handle; - new_bay->name = (char *)nbuffer.pointer; - - /* initialize platform device stuff */ - pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0); - if (pdev == NULL) { - printk(KERN_ERR PREFIX "Error registering bay device\n"); - goto bay_add_err; - } - new_bay->pdev = pdev; - platform_set_drvdata(pdev, new_bay); - - if (acpi_bay_add_fs(new_bay)) { - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - - /* register for events on this device */ - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - bay_notify, new_bay); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing bay notify handler\n"); - } - - /* if we are on a dock station, we should register for dock - * notifications. - */ - if (bay_is_dock_device(handle)) { - bay_dprintk(handle, "Is dependent on dock\n"); - register_hotplug_dock_device(handle, bay_notify, new_bay); - } - list_add(&new_bay->list, &drive_bays); - printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); - return 0; - -bay_add_err: - kfree(new_bay->name); - kfree(new_bay); - return -ENODEV; -} - -static int acpi_bay_remove(struct acpi_device *device, int type) -{ - /*** FIXME: do something here */ - return 0; -} - -/** - * bay_create_acpi_device - add new devices to acpi - * @handle - handle of the device to add - * - * This function will create a new acpi_device for the given - * handle if one does not exist already. This should cause - * acpi to scan for drivers for the given devices, and call - * matching driver's add routine. - * - * Returns a pointer to the acpi_device corresponding to the handle. - */ -static struct acpi_device * bay_create_acpi_device(acpi_handle handle) -{ - struct acpi_device *device = NULL; - struct acpi_device *parent_device; - acpi_handle parent; - int ret; - - bay_dprintk(handle, "Trying to get device"); - if (acpi_bus_get_device(handle, &device)) { - /* - * no device created for this object, - * so we should create one. - */ - bay_dprintk(handle, "No device for handle"); - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { - pr_debug("error adding bus, %x\n", - -ret); - return NULL; - } - } - return device; -} - -/** - * bay_notify - act upon an acpi bay notification - * @handle: the bay handle - * @event: the acpi event - * @data: our driver data struct - * - */ -static void bay_notify(acpi_handle handle, u32 event, void *data) -{ - struct acpi_device *dev; - - bay_dprintk(handle, "Bay event"); - - switch(event) { - case ACPI_NOTIFY_BUS_CHECK: - printk("Bus Check\n"); - case ACPI_NOTIFY_DEVICE_CHECK: - printk("Device Check\n"); - dev = bay_create_acpi_device(handle); - if (dev) - acpi_bus_generate_event(dev, event, 0); - else - printk("No device for generating event\n"); - /* wouldn't it be a good idea to just rescan SATA - * right here? - */ - break; - case ACPI_NOTIFY_EJECT_REQUEST: - printk("Eject request\n"); - dev = bay_create_acpi_device(handle); - if (dev) - acpi_bus_generate_event(dev, event, 0); - else - printk("No device for generating eventn"); - - /* wouldn't it be a good idea to just call the - * eject_device here if we were a SATA device? - */ - break; - default: - printk("unknown event %d\n", event); - } -} - -static acpi_status -find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int *count = (int *)context; - - /* - * there could be more than one ejectable bay. - * so, just return AE_OK always so that every object - * will be checked. - */ - if (is_ejectable_bay(handle)) { - bay_dprintk(handle, "found ejectable bay"); - if (!bay_add(handle, *count)) - (*count)++; - } - return AE_OK; -} - -static int __init bay_init(void) -{ - int bays = 0; - - INIT_LIST_HEAD(&drive_bays); - - /* look for dockable drive bays */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_bay, &bays, NULL); - - if (bays) - if ((acpi_bus_register_driver(&acpi_bay_driver) < 0)) - printk(KERN_ERR "Unable to register bay driver\n"); - - if (!bays) - return -ENODEV; - - return 0; -} - -static void __exit bay_exit(void) -{ - struct bay *bay, *tmp; - - list_for_each_entry_safe(bay, tmp, &drive_bays, list) { - if (is_dock_device(bay->handle)) - unregister_hotplug_dock_device(bay->handle); - acpi_bay_remove_fs(bay); - acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, - bay_notify); - platform_device_unregister(bay->pdev); - kfree(bay->name); - kfree(bay); - } - - acpi_bus_unregister_driver(&acpi_bay_driver); -} - -postcore_initcall(bay_init); -module_exit(bay_exit); - diff --git a/trunk/drivers/acpi/blacklist.c b/trunk/drivers/acpi/blacklist.c index f289fd41e77d..f9c972b26f4f 100644 --- a/trunk/drivers/acpi/blacklist.c +++ b/trunk/drivers/acpi/blacklist.c @@ -44,7 +44,7 @@ struct acpi_blacklist_item { char oem_id[7]; char oem_table_id[9]; u32 oem_revision; - char *table; + acpi_table_type table; enum acpi_blacklist_predicates oem_revision_predicate; char *reason; u32 is_critical_error; @@ -56,18 +56,18 @@ struct acpi_blacklist_item { */ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { /* Compaq Presario 1700 */ - {"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal, + {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1}, /* Sony FX120, FX140, FX150? */ - {"SONY ", "U0 ", 0x20010313, ACPI_SIG_DSDT, less_than_or_equal, + {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1}, /* Compaq Presario 800, Insyde BIOS */ - {"INT440", "SYSFexxx", 0x00001001, ACPI_SIG_DSDT, less_than_or_equal, + {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1}, /* IBM 600E - _ADR should return 7, but it returns 1 */ - {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, + {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, - {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions, + {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1}, {""} @@ -79,7 +79,7 @@ static int __init blacklist_by_year(void) { int year = dmi_get_year(DMI_BIOS_DATE); /* Doesn't exist? Likely an old system */ - if (year == -1) + if (year == -1) return 1; /* 0? Likely a buggy new BIOS */ if (year == 0) @@ -103,21 +103,22 @@ int __init acpi_blacklisted(void) { int i = 0; int blacklisted = 0; - struct acpi_table_header table_header; + struct acpi_table_header *table_header; while (acpi_blacklist[i].oem_id[0] != '\0') { - if (acpi_get_table_header(acpi_blacklist[i].table, 0, &table_header)) { + if (acpi_get_table_header_early + (acpi_blacklist[i].table, &table_header)) { i++; continue; } - if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) { + if (strncmp(acpi_blacklist[i].oem_id, table_header->oem_id, 6)) { i++; continue; } if (strncmp - (acpi_blacklist[i].oem_table_id, table_header.oem_table_id, + (acpi_blacklist[i].oem_table_id, table_header->oem_table_id, 8)) { i++; continue; @@ -126,14 +127,14 @@ int __init acpi_blacklisted(void) if ((acpi_blacklist[i].oem_revision_predicate == all_versions) || (acpi_blacklist[i].oem_revision_predicate == less_than_or_equal - && table_header.oem_revision <= + && table_header->oem_revision <= acpi_blacklist[i].oem_revision) || (acpi_blacklist[i].oem_revision_predicate == greater_than_or_equal - && table_header.oem_revision >= + && table_header->oem_revision >= acpi_blacklist[i].oem_revision) || (acpi_blacklist[i].oem_revision_predicate == equal - && table_header.oem_revision == + && table_header->oem_revision == acpi_blacklist[i].oem_revision)) { printk(KERN_ERR PREFIX diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index c26468da4295..766332e45592 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -44,6 +44,9 @@ ACPI_MODULE_NAME("acpi_bus") extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); #endif +struct fadt_descriptor acpi_fadt; +EXPORT_SYMBOL(acpi_fadt); + struct acpi_device *acpi_root; struct proc_dir_entry *acpi_root_dir; EXPORT_SYMBOL(acpi_root_dir); @@ -192,7 +195,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) if (!device->flags.power_manageable) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", - device->dev.kobj.name)); + device->kobj.name)); return -ENODEV; } /* @@ -579,12 +582,11 @@ static int __init acpi_bus_init_irq(void) return 0; } -acpi_native_uint acpi_gbl_permanent_mmap; - - void __init acpi_early_init(void) { acpi_status status = AE_OK; + struct acpi_buffer buffer = { sizeof(acpi_fadt), &acpi_fadt }; + if (acpi_disabled) return; @@ -595,15 +597,6 @@ void __init acpi_early_init(void) if (!acpi_strict) acpi_gbl_enable_interpreter_slack = TRUE; - acpi_gbl_permanent_mmap = 1; - - status = acpi_reallocate_root_table(); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to reallocate ACPI tables\n"); - goto error0; - } - status = acpi_initialize_subsystem(); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX @@ -618,25 +611,32 @@ void __init acpi_early_init(void) goto error0; } + /* + * Get a separate copy of the FADT for use by other drivers. + */ + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to get the FADT\n"); + goto error0; + } #ifdef CONFIG_X86 if (!acpi_ioapic) { - extern u8 acpi_sci_flags; + extern acpi_interrupt_flags acpi_sci_flags; /* compatible (0) means level (3) */ - if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) { - acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK; - acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL; - } + if (acpi_sci_flags.trigger == 0) + acpi_sci_flags.trigger = 3; + /* Set PIC-mode SCI trigger type */ - acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt, - (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2); + acpi_pic_sci_set_trigger(acpi_fadt.sci_int, + acpi_sci_flags.trigger); } else { extern int acpi_sci_override_gsi; /* - * now that acpi_gbl_FADT is initialized, + * now that acpi_fadt is initialized, * update it with result from INT_SRC_OVR parsing */ - acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; + acpi_fadt.sci_int = acpi_sci_override_gsi; } #endif diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index c726612fafb6..ac860583c203 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -75,7 +75,7 @@ static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, .class = ACPI_BUTTON_CLASS, - .ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E", + .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", .ops = { .add = acpi_button_add, .remove = acpi_button_remove, diff --git a/trunk/drivers/acpi/container.c b/trunk/drivers/acpi/container.c index 69a68fd394cf..0a1863ec91f3 100644 --- a/trunk/drivers/acpi/container.c +++ b/trunk/drivers/acpi/container.c @@ -167,7 +167,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (ACPI_FAILURE(status) || !device) { result = container_device_add(&device, handle); if (!result) - kobject_uevent(&device->dev.kobj, + kobject_uevent(&device->kobj, KOBJ_ONLINE); else printk("Failed to add container\n"); @@ -175,13 +175,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) } else { if (ACPI_SUCCESS(status)) { /* device exist and this is a remove request */ - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + kobject_uevent(&device->kobj, KOBJ_OFFLINE); } } break; case ACPI_NOTIFY_EJECT_REQUEST: if (!acpi_bus_get_device(handle, &device) && device) { - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + kobject_uevent(&device->kobj, KOBJ_OFFLINE); } break; default: diff --git a/trunk/drivers/acpi/debug.c b/trunk/drivers/acpi/debug.c index d48f65a8f658..35c6af8a83cd 100644 --- a/trunk/drivers/acpi/debug.c +++ b/trunk/drivers/acpi/debug.c @@ -13,11 +13,14 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("debug") - +#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" +#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" #ifdef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX #endif -#define MODULE_PARAM_PREFIX "acpi." +#define MODULE_PARAM_PREFIX + module_param(acpi_dbg_layer, uint, 0400); +module_param(acpi_dbg_level, uint, 0400); struct acpi_dlayer { const char *name; @@ -83,60 +86,6 @@ static const struct acpi_dlevel acpi_debug_levels[] = { ACPI_DEBUG_INIT(ACPI_LV_EVENTS), }; -/* -------------------------------------------------------------------------- - FS Interface (/sys) - -------------------------------------------------------------------------- */ -static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { - int result = 0; - int i; - - result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); - - for(i = 0; i common.next; - - /* Currently, only the following constants are supported */ - - switch (arg->common.aml_opcode) { - case AML_ZERO_OP: - info.bank_value = 0; - break; - - case AML_ONE_OP: - info.bank_value = 1; - break; - - case AML_BYTE_OP: - case AML_WORD_OP: - case AML_DWORD_OP: - case AML_QWORD_OP: - info.bank_value = (u32) arg->common.value.integer; - break; - - default: - info.bank_value = 0; - ACPI_ERROR((AE_INFO, - "Non-constant BankValue for BankField is not implemented")); - } + info.bank_value = (u32) arg->common.value.integer; /* Fourth arg is the field flags */ diff --git a/trunk/drivers/acpi/dispatcher/dsinit.c b/trunk/drivers/acpi/dispatcher/dsinit.c index af923c388520..1888c055d10f 100644 --- a/trunk/drivers/acpi/dispatcher/dsinit.c +++ b/trunk/drivers/acpi/dispatcher/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include #include #include -#include #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsinit") @@ -91,7 +90,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, * We are only interested in NS nodes owned by the table that * was just loaded */ - if (node->owner_id != info->owner_id) { + if (node->owner_id != info->table_desc->owner_id) { return (AE_OK); } @@ -151,21 +150,14 @@ acpi_ds_init_one_object(acpi_handle obj_handle, ******************************************************************************/ acpi_status -acpi_ds_initialize_objects(acpi_native_uint table_index, +acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, struct acpi_namespace_node * start_node) { acpi_status status; struct acpi_init_walk_info info; - struct acpi_table_header *table; - acpi_owner_id owner_id; ACPI_FUNCTION_TRACE(ds_initialize_objects); - status = acpi_tb_get_owner_id(table_index, &owner_id); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); @@ -174,8 +166,7 @@ acpi_ds_initialize_objects(acpi_native_uint table_index, info.op_region_count = 0; info.object_count = 0; info.device_count = 0; - info.table_index = table_index; - info.owner_id = owner_id; + info.table_desc = table_desc; /* Walk entire namespace from the supplied root */ @@ -185,14 +176,10 @@ acpi_ds_initialize_objects(acpi_native_uint table_index, ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", - table->signature, owner_id, info.object_count, + table_desc->pointer->signature, + table_desc->owner_id, info.object_count, info.device_count, info.method_count, info.op_region_count)); diff --git a/trunk/drivers/acpi/dispatcher/dsmethod.c b/trunk/drivers/acpi/dispatcher/dsmethod.c index 1cbe61905824..cf888add3191 100644 --- a/trunk/drivers/acpi/dispatcher/dsmethod.c +++ b/trunk/drivers/acpi/dispatcher/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -327,7 +327,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Calling method %p, currentstate=%p\n", + "Execute method %p, currentstate=%p\n", this_walk_state->prev_op, this_walk_state)); /* @@ -351,7 +351,49 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, return_ACPI_STATUS(status); } - /* Begin method parse/execution. Create a new walk state */ + /* + * 1) Parse the method. All "normal" methods are parsed for each execution. + * Internal methods (_OSI, etc.) do not require parsing. + */ + if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { + + /* Create a new walk state for the parse */ + + next_walk_state = + acpi_ds_create_walk_state(obj_desc->method.owner_id, op, + obj_desc, NULL); + if (!next_walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create and init a parse tree root */ + + op = acpi_ps_create_scope_op(); + if (!op) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk(next_walk_state, op, method_node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, + NULL, 1); + if (ACPI_FAILURE(status)) { + acpi_ps_delete_parse_tree(op); + goto cleanup; + } + + /* Begin AML parse (deletes next_walk_state) */ + + status = acpi_ps_parse_aml(next_walk_state); + acpi_ps_delete_parse_tree(op); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + /* 2) Begin method execution. Create a new walk state */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc, thread); @@ -382,8 +424,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, obj_desc->method.aml_start, - obj_desc->method.aml_length, info, - ACPI_IMODE_EXECUTE); + obj_desc->method.aml_length, info, 3); ACPI_FREE(info); if (ACPI_FAILURE(status)) { @@ -404,8 +445,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, this_walk_state->num_operands = 0; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", - method_node->name.ascii, next_walk_state)); + "Starting nested execution, newstate=%p\n", + next_walk_state)); /* Invoke an internal method if necessary */ diff --git a/trunk/drivers/acpi/dispatcher/dsmthdat.c b/trunk/drivers/acpi/dispatcher/dsmthdat.c index ba4626e06a5e..459160ff9058 100644 --- a/trunk/drivers/acpi/dispatcher/dsmthdat.c +++ b/trunk/drivers/acpi/dispatcher/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/dispatcher/dsobject.c b/trunk/drivers/acpi/dispatcher/dsobject.c index a474ca2334d5..72190abb1d59 100644 --- a/trunk/drivers/acpi/dispatcher/dsobject.c +++ b/trunk/drivers/acpi/dispatcher/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -260,7 +260,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, } obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; - op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); + op->common.node = (struct acpi_namespace_node *)obj_desc; return_ACPI_STATUS(AE_OK); } @@ -270,8 +270,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, * * PARAMETERS: walk_state - Current walk state * Op - Parser object to be translated - * element_count - Number of elements in the package - this is - * the num_elements argument to Package() + * package_length - Number of elements in the package * obj_desc_ptr - Where the ACPI internal object is returned * * RETURN: Status @@ -279,29 +278,18 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, * DESCRIPTION: Translate a parser Op package object to the equivalent * namespace object * - * NOTE: The number of elements in the package will be always be the num_elements - * count, regardless of the number of elements in the package list. If - * num_elements is smaller, only that many package list elements are used. - * if num_elements is larger, the Package object is padded out with - * objects of type Uninitialized (as per ACPI spec.) - * - * Even though the ASL compilers do not allow num_elements to be smaller - * than the Package list length (for the fixed length package opcode), some - * BIOS code modifies the AML on the fly to adjust the num_elements, and - * this code compensates for that. This also provides compatibility with - * other AML interpreters. - * ******************************************************************************/ acpi_status acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *op, - u32 element_count, + u32 package_length, union acpi_operand_object **obj_desc_ptr) { union acpi_parse_object *arg; union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; + u32 package_list_length; acpi_status status = AE_OK; acpi_native_uint i; @@ -330,13 +318,32 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, obj_desc->package.node = parent->common.node; } + obj_desc->package.count = package_length; + + /* Count the number of items in the package list */ + + arg = op->common.value.arg; + arg = arg->common.next; + for (package_list_length = 0; arg; package_list_length++) { + arg = arg->common.next; + } + + /* + * The package length (number of elements) will be the greater + * of the specified length and the length of the initializer list + */ + if (package_list_length > package_length) { + obj_desc->package.count = package_list_length; + } + /* - * Allocate the element array (array of pointers to the individual - * objects) based on the num_elements parameter. Add an extra pointer slot - * so that the list is always null terminated. + * Allocate the pointer array (array of pointers to the + * individual objects). Add an extra pointer slot so + * that the list is always null terminated. */ obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) - element_count + + obj_desc->package. + count + 1) * sizeof(void *)); if (!obj_desc->package.elements) { @@ -344,20 +351,15 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_NO_MEMORY); } - obj_desc->package.count = element_count; - /* - * Initialize the elements of the package, up to the num_elements count. - * Package is automatically padded with uninitialized (NULL) elements - * if num_elements is greater than the package list length. Likewise, - * Package is truncated if num_elements is less than the list length. + * Initialize all elements of the package */ arg = op->common.value.arg; arg = arg->common.next; - for (i = 0; arg && (i < element_count); i++) { + for (i = 0; arg; i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { - /* This package element is already built, just get it */ + /* Object (package or buffer) is already built */ obj_desc->package.elements[i] = ACPI_CAST_PTR(union acpi_operand_object, @@ -371,14 +373,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; } - if (!arg) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Package List length larger than NumElements count (%X), truncated\n", - element_count)); - } - obj_desc->package.flags |= AOPOBJ_DATA_VALID; - op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); + op->common.node = (struct acpi_namespace_node *)obj_desc; return_ACPI_STATUS(status); } @@ -492,9 +488,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* * Defer evaluation of Buffer term_arg operand */ - obj_desc->buffer.node = - ACPI_CAST_PTR(struct acpi_namespace_node, - walk_state->operands[0]); + obj_desc->buffer.node = (struct acpi_namespace_node *) + walk_state->operands[0]; obj_desc->buffer.aml_start = op->named.data; obj_desc->buffer.aml_length = op->named.length; break; @@ -504,9 +499,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* * Defer evaluation of Package term_arg operand */ - obj_desc->package.node = - ACPI_CAST_PTR(struct acpi_namespace_node, - walk_state->operands[0]); + obj_desc->package.node = (struct acpi_namespace_node *) + walk_state->operands[0]; obj_desc->package.aml_start = op->named.data; obj_desc->package.aml_length = op->named.length; break; diff --git a/trunk/drivers/acpi/dispatcher/dsopcode.c b/trunk/drivers/acpi/dispatcher/dsopcode.c index 6c6104a7a247..5b974a8fe614 100644 --- a/trunk/drivers/acpi/dispatcher/dsopcode.c +++ b/trunk/drivers/acpi/dispatcher/dsopcode.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -114,7 +114,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, } status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_LOAD_PASS1); + aml_length, NULL, 1); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup; @@ -157,7 +157,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, /* Execute the opcode and arguments */ status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_EXECUTE); + aml_length, NULL, 3); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup; diff --git a/trunk/drivers/acpi/dispatcher/dsutils.c b/trunk/drivers/acpi/dispatcher/dsutils.c index e4073e05a75c..05230baf5de8 100644 --- a/trunk/drivers/acpi/dispatcher/dsutils.c +++ b/trunk/drivers/acpi/dispatcher/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/dispatcher/dswexec.c b/trunk/drivers/acpi/dispatcher/dswexec.c index 69693fa07224..d7a616c3104e 100644 --- a/trunk/drivers/acpi/dispatcher/dswexec.c +++ b/trunk/drivers/acpi/dispatcher/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -219,7 +219,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, if (!op) { status = acpi_ds_load2_begin_op(walk_state, out_op); if (ACPI_FAILURE(status)) { - goto error_exit; + return_ACPI_STATUS(status); } op = *out_op; @@ -238,7 +238,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, status = acpi_ds_scope_stack_pop(walk_state); if (ACPI_FAILURE(status)) { - goto error_exit; + return_ACPI_STATUS(status); } } } @@ -287,7 +287,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, status = acpi_ds_result_stack_push(walk_state); if (ACPI_FAILURE(status)) { - goto error_exit; + return_ACPI_STATUS(status); } status = acpi_ds_exec_begin_control_op(walk_state, op); @@ -328,10 +328,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, /* Nothing to do here during method execution */ return_ACPI_STATUS(status); - - error_exit: - status = acpi_ds_method_error(status, walk_state); - return_ACPI_STATUS(status); } /***************************************************************************** diff --git a/trunk/drivers/acpi/dispatcher/dswload.c b/trunk/drivers/acpi/dispatcher/dswload.c index 8ab9d1b29a4c..e3ca7f6539c1 100644 --- a/trunk/drivers/acpi/dispatcher/dswload.c +++ b/trunk/drivers/acpi/dispatcher/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -196,7 +196,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * one of the opcodes that actually opens a scope */ switch (node->type) { - case ACPI_TYPE_ANY: case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: @@ -547,7 +546,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_status status; acpi_object_type object_type; char *buffer_ptr; - u32 flags; ACPI_FUNCTION_TRACE(ds_load2_begin_op); @@ -671,7 +669,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, * one of the opcodes that actually opens a scope */ switch (node->type) { - case ACPI_TYPE_ANY: case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: @@ -753,20 +750,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, break; } - flags = ACPI_NS_NO_UPSEARCH; - if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { - - /* Execution mode, node cannot already exist, node is temporary */ - - flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); - } - - /* Add new entry or lookup existing entry */ + /* Add new entry into namespace */ status = acpi_ns_lookup(walk_state->scope_info, buffer_ptr, - object_type, ACPI_IMODE_LOAD_PASS2, flags, - walk_state, &node); + object_type, ACPI_IMODE_LOAD_PASS2, + ACPI_NS_NO_UPSEARCH, walk_state, &(node)); break; } diff --git a/trunk/drivers/acpi/dispatcher/dswscope.c b/trunk/drivers/acpi/dispatcher/dswscope.c index 3927c495e4bf..c9228972f5f6 100644 --- a/trunk/drivers/acpi/dispatcher/dswscope.c +++ b/trunk/drivers/acpi/dispatcher/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/dispatcher/dswstate.c b/trunk/drivers/acpi/dispatcher/dswstate.c index 16c8e38b51ef..7817e5522679 100644 --- a/trunk/drivers/acpi/dispatcher/dswstate.c +++ b/trunk/drivers/acpi/dispatcher/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 688e83a16906..90990a4b6526 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -615,28 +615,20 @@ static acpi_status find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; - acpi_handle tmp, parent; + acpi_handle tmp; struct dock_station *ds = context; struct dock_dependent_device *dd; status = acpi_bus_get_ejd(handle, &tmp); - if (ACPI_FAILURE(status)) { - /* try the parent device as well */ - status = acpi_get_parent(handle, &parent); - if (ACPI_FAILURE(status)) - goto fdd_out; - /* see if parent is dependent on dock */ - status = acpi_bus_get_ejd(parent, &tmp); - if (ACPI_FAILURE(status)) - goto fdd_out; - } + if (ACPI_FAILURE(status)) + return AE_OK; if (tmp == ds->handle) { dd = alloc_dock_dependent_device(handle); if (dd) add_dock_dependent_device(ds, dd); } -fdd_out: + return AE_OK; } diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 743ce27fa0bb..cbdf031f3c09 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -872,8 +872,9 @@ static int __init acpi_ec_get_real_ecdt(void) acpi_status status; struct acpi_table_ecdt *ecdt_ptr; - status = acpi_get_table(ACPI_SIG_ECDT, 1, - (struct acpi_table_header **)&ecdt_ptr); + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) + &ecdt_ptr); if (ACPI_FAILURE(status)) return -ENODEV; @@ -890,14 +891,14 @@ static int __init acpi_ec_get_real_ecdt(void) if (acpi_ec_mode == EC_INTR) { init_waitqueue_head(&ec_ecdt->wait); } - ec_ecdt->command_addr = ecdt_ptr->control.address; - ec_ecdt->data_addr = ecdt_ptr->data.address; - ec_ecdt->gpe = ecdt_ptr->gpe; + ec_ecdt->command_addr = ecdt_ptr->ec_control.address; + ec_ecdt->data_addr = ecdt_ptr->ec_data.address; + ec_ecdt->gpe = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ ec_ecdt->global_lock = TRUE; ec_ecdt->uid = ecdt_ptr->uid; - status = acpi_get_handle(NULL, ecdt_ptr->id, &ec_ecdt->handle); + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); if (ACPI_FAILURE(status)) { goto error; } diff --git a/trunk/drivers/acpi/events/evevent.c b/trunk/drivers/acpi/events/evevent.c index a1f87b5def2a..919037d6acff 100644 --- a/trunk/drivers/acpi/events/evevent.c +++ b/trunk/drivers/acpi/events/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,6 +70,13 @@ acpi_status acpi_ev_initialize_events(void) ACPI_FUNCTION_TRACE(ev_initialize_events); + /* Make sure we have ACPI tables */ + + if (!acpi_gbl_DSDT) { + ACPI_WARNING((AE_INFO, "No ACPI tables present!")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + /* * Initialize the Fixed and General Purpose Events. This is done prior to * enabling SCIs to prevent interrupts from occurring before the handlers are @@ -204,7 +211,8 @@ static acpi_status acpi_ev_fixed_event_initialize(void) if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { status = acpi_set_register(acpi_gbl_fixed_event_info[i]. - enable_register_id, 0); + enable_register_id, 0, + ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return (status); } @@ -290,7 +298,7 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) /* Clear the status bit */ (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + status_register_id, 1, ACPI_MTX_DO_NOT_LOCK); /* * Make sure we've got a handler. If not, report an error. @@ -298,7 +306,8 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + enable_register_id, 0, + ACPI_MTX_DO_NOT_LOCK); ACPI_ERROR((AE_INFO, "No installed handler for fixed event [%08X]", diff --git a/trunk/drivers/acpi/events/evgpe.c b/trunk/drivers/acpi/events/evgpe.c index dfac3ecc596e..c76c0583ca6a 100644 --- a/trunk/drivers/acpi/events/evgpe.c +++ b/trunk/drivers/acpi/events/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,9 +121,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, if (!gpe_register_info) { return_ACPI_STATUS(AE_NOT_EXIST); } - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); + register_bit = gpe_event_info->register_bit; /* 1) Disable case. Simply clear all enable bits */ @@ -460,7 +458,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) /* Examine one GPE bit */ - if (enabled_status_byte & (1 << j)) { + if (enabled_status_byte & + acpi_gbl_decode_to8bit[j]) { /* * Found an active GPE. Dispatch the event to a handler * or method. @@ -571,7 +570,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "while evaluating GPE method [%4.4s]", + "While evaluating GPE method [%4.4s]", acpi_ut_get_node_name (local_gpe_event_info.dispatch. method_node))); @@ -619,8 +618,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) ACPI_FUNCTION_TRACE(ev_gpe_dispatch); - acpi_gpe_count++; - /* * If edge-triggered, clear the GPE status bit now. Note that * level-triggered events are cleared after the GPE is serviced. @@ -636,23 +633,20 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) } } - if (!acpi_gbl_system_awake_and_running) { - /* - * We just woke up because of a wake GPE. Disable any further GPEs - * until we are fully up and running (Only wake GPEs should be enabled - * at this time, but we just brute-force disable them all.) - * 1) We must disable this particular wake GPE so it won't fire again - * 2) We want to disable all wake GPEs, since we are now awake - */ - (void)acpi_hw_disable_all_gpes(); + /* Save current system state */ + + if (acpi_gbl_system_awake_and_running) { + ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING); + } else { + ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING); } /* - * Dispatch the GPE to either an installed handler, or the control method - * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke - * it and do not attempt to run the method. If there is neither a handler - * nor a method, we disable this GPE to prevent further such pointless - * events from firing. + * Dispatch the GPE to either an installed handler, or the control + * method associated with this GPE (_Lxx or _Exx). + * If a handler exists, we invoke it and do not attempt to run the method. + * If there is neither a handler nor a method, we disable the level to + * prevent further events from coming in here. */ switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_HANDLER: @@ -683,8 +677,8 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) case ACPI_GPE_DISPATCH_METHOD: /* - * Disable the GPE, so it doesn't keep firing before the method has a - * chance to run (it runs asynchronously with interrupts enabled). + * Disable GPE, so it doesn't keep firing before the method has a + * chance to run. */ status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { @@ -717,7 +711,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) gpe_number)); /* - * Disable the GPE. The GPE will remain disabled until the ACPI + * Disable the GPE. The GPE will remain disabled until the ACPI * Core Subsystem is restarted, or a handler is installed. */ status = acpi_ev_disable_gpe(gpe_event_info); @@ -732,3 +726,50 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) return_UINT32(ACPI_INTERRUPT_HANDLED); } + +#ifdef ACPI_GPE_NOTIFY_CHECK +/******************************************************************************* + * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED + * + * FUNCTION: acpi_ev_check_for_wake_only_gpe + * + * PARAMETERS: gpe_event_info - info for this GPE + * + * RETURN: Status + * + * DESCRIPTION: Determine if a a GPE is "wake-only". + * + * Called from Notify() code in interpreter when a "DeviceWake" + * Notify comes in. + * + ******************************************************************************/ + +acpi_status +acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_check_for_wake_only_gpe); + + if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */ + ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) { /* System state at GPE time */ + /* This must be a wake-only GPE, disable it */ + + status = acpi_ev_disable_gpe(gpe_event_info); + + /* Set GPE to wake-only. Do not change wake disabled/enabled status */ + + acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); + + ACPI_INFO((AE_INFO, + "GPE %p was updated from wake/run to wake-only", + gpe_event_info)); + + /* This was a wake-only GPE */ + + return_ACPI_STATUS(AE_WAKE_ONLY_GPE); + } + + return_ACPI_STATUS(AE_OK); +} +#endif diff --git a/trunk/drivers/acpi/events/evgpeblk.c b/trunk/drivers/acpi/events/evgpeblk.c index ad5bc76edf46..95ddeb48bc0f 100644 --- a/trunk/drivers/acpi/events/evgpeblk.c +++ b/trunk/drivers/acpi/events/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -529,7 +529,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 /* Install new interrupt handler if not SCI_INT */ - if (interrupt_number != acpi_gbl_FADT.sci_interrupt) { + if (interrupt_number != acpi_gbl_FADT->sci_int) { status = acpi_os_install_interrupt_handler(interrupt_number, acpi_ev_gpe_xrupt_handler, gpe_xrupt); @@ -567,7 +567,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) /* We never want to remove the SCI interrupt handler */ - if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) { + if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) { gpe_xrupt->gpe_block_list_head = NULL; return_ACPI_STATUS(AE_OK); } @@ -796,31 +796,30 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) (u8) (gpe_block->block_base_number + (i * ACPI_GPE_REGISTER_WIDTH)); - this_register->status_address.address = - gpe_block->block_address.address + i; + ACPI_STORE_ADDRESS(this_register->status_address.address, + (gpe_block->block_address.address + i)); - this_register->enable_address.address = - gpe_block->block_address.address + i + - gpe_block->register_count; + ACPI_STORE_ADDRESS(this_register->enable_address.address, + (gpe_block->block_address.address + + i + gpe_block->register_count)); - this_register->status_address.space_id = - gpe_block->block_address.space_id; - this_register->enable_address.space_id = - gpe_block->block_address.space_id; - this_register->status_address.bit_width = + this_register->status_address.address_space_id = + gpe_block->block_address.address_space_id; + this_register->enable_address.address_space_id = + gpe_block->block_address.address_space_id; + this_register->status_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; - this_register->enable_address.bit_width = + this_register->enable_address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; - this_register->status_address.bit_offset = + this_register->status_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; - this_register->enable_address.bit_offset = + this_register->enable_address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; /* Init the event_info for each GPE within this register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - this_event->gpe_number = - (u8) (this_register->base_gpe_number + j); + this_event->register_bit = acpi_gbl_decode_to8bit[j]; this_event->register_info = this_register; this_event++; } @@ -1110,12 +1109,11 @@ acpi_status acpi_ev_gpe_initialize(void) * If EITHER the register length OR the block address are zero, then that * particular block is not supported. */ - if (acpi_gbl_FADT.gpe0_block_length && - acpi_gbl_FADT.xgpe0_block.address) { + if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) { /* GPE block 0 exists (has both length and address > 0) */ - register_count0 = (u16) (acpi_gbl_FADT.gpe0_block_length / 2); + register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2); gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; @@ -1123,9 +1121,9 @@ acpi_status acpi_ev_gpe_initialize(void) /* Install GPE Block 0 */ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe0_block, + &acpi_gbl_FADT->xgpe0_blk, register_count0, 0, - acpi_gbl_FADT.sci_interrupt, + acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]); if (ACPI_FAILURE(status)) { @@ -1134,21 +1132,20 @@ acpi_status acpi_ev_gpe_initialize(void) } } - if (acpi_gbl_FADT.gpe1_block_length && - acpi_gbl_FADT.xgpe1_block.address) { + if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) { /* GPE block 1 exists (has both length and address > 0) */ - register_count1 = (u16) (acpi_gbl_FADT.gpe1_block_length / 2); + register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2); /* Check for GPE0/GPE1 overlap (if both banks exist) */ if ((register_count0) && - (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { + (gpe_number_max >= acpi_gbl_FADT->gpe1_base)) { ACPI_ERROR((AE_INFO, "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", - gpe_number_max, acpi_gbl_FADT.gpe1_base, - acpi_gbl_FADT.gpe1_base + + gpe_number_max, acpi_gbl_FADT->gpe1_base, + acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1))); @@ -1160,11 +1157,10 @@ acpi_status acpi_ev_gpe_initialize(void) status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe1_block, + &acpi_gbl_FADT->xgpe1_blk, register_count1, - acpi_gbl_FADT.gpe1_base, - acpi_gbl_FADT. - sci_interrupt, + acpi_gbl_FADT->gpe1_base, + acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks [1]); @@ -1177,7 +1173,7 @@ acpi_status acpi_ev_gpe_initialize(void) * GPE0 and GPE1 do not have to be contiguous in the GPE number * space. However, GPE0 always starts at GPE number zero. */ - gpe_number_max = acpi_gbl_FADT.gpe1_base + + gpe_number_max = acpi_gbl_FADT->gpe1_base + ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); } } diff --git a/trunk/drivers/acpi/events/evmisc.c b/trunk/drivers/acpi/events/evmisc.c index 1b784ffe54c3..bf63edc6608d 100644 --- a/trunk/drivers/acpi/events/evmisc.c +++ b/trunk/drivers/acpi/events/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,17 +63,13 @@ static const char *acpi_notify_value_names[] = { }; #endif -/* Pointer to FACS needed for the Global Lock */ - -static struct acpi_table_facs *facs = NULL; - /* Local prototypes */ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); -static u32 acpi_ev_global_lock_handler(void *context); +static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context); -static acpi_status acpi_ev_remove_global_lock_handler(void); +static u32 acpi_ev_global_lock_handler(void *context); /******************************************************************************* * @@ -284,21 +280,51 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) acpi_ut_delete_generic_state(notify_info); } +/******************************************************************************* + * + * FUNCTION: acpi_ev_global_lock_thread + * + * PARAMETERS: Context - From thread interface, not used + * + * RETURN: None + * + * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the + * Global Lock. Simply signal all threads that are waiting + * for the lock. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context) +{ + acpi_status status; + + /* Signal threads that are waiting for the lock */ + + if (acpi_gbl_global_lock_thread_count) { + + /* Send sufficient units to the semaphore */ + + status = + acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, + acpi_gbl_global_lock_thread_count); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not signal Global Lock semaphore")); + } + } +} + /******************************************************************************* * * FUNCTION: acpi_ev_global_lock_handler * * PARAMETERS: Context - From thread interface, not used * - * RETURN: ACPI_INTERRUPT_HANDLED + * RETURN: ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED * * DESCRIPTION: Invoked directly from the SCI handler when a global lock - * release interrupt occurs. Attempt to acquire the global lock, - * if successful, signal the thread waiting for the lock. - * - * NOTE: Assumes that the semaphore can be signaled from interrupt level. If - * this is not possible for some reason, a separate thread will have to be - * scheduled to do this. + * release interrupt occurs. Grab the global lock and queue + * the global lock thread for execution * ******************************************************************************/ @@ -307,24 +333,16 @@ static u32 acpi_ev_global_lock_handler(void *context) u8 acquired = FALSE; /* - * Attempt to get the lock. - * + * Attempt to get the lock * If we don't get it now, it will be marked pending and we will * take another interrupt when it becomes free. */ - ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired); + ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { /* Got the lock, now wake all threads waiting for it */ - acpi_gbl_global_lock_acquired = TRUE; - /* Send a unit to the semaphore */ - - if (ACPI_FAILURE(acpi_os_signal_semaphore( - acpi_gbl_global_lock_semaphore, 1))) { - ACPI_ERROR((AE_INFO, - "Could not signal Global Lock semaphore")); - } + acpi_ev_global_lock_thread(context); } return (ACPI_INTERRUPT_HANDLED); @@ -348,13 +366,6 @@ acpi_status acpi_ev_init_global_lock_handler(void) ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - acpi_gbl_global_lock_present = TRUE; status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, acpi_ev_global_lock_handler, @@ -378,31 +389,6 @@ acpi_status acpi_ev_init_global_lock_handler(void) return_ACPI_STATUS(status); } -/******************************************************************************* - * - * FUNCTION: acpi_ev_remove_global_lock_handler - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Remove the handler for the Global Lock - * - ******************************************************************************/ - -static acpi_status acpi_ev_remove_global_lock_handler(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler); - - acpi_gbl_global_lock_present = FALSE; - status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, - acpi_ev_global_lock_handler); - - return_ACPI_STATUS(status); -} - /****************************************************************************** * * FUNCTION: acpi_ev_acquire_global_lock @@ -413,16 +399,6 @@ static acpi_status acpi_ev_remove_global_lock_handler(void) * * DESCRIPTION: Attempt to gain ownership of the Global Lock. * - * MUTEX: Interpreter must be locked - * - * Note: The original implementation allowed multiple threads to "acquire" the - * Global Lock, and the OS would hold the lock until the last thread had - * released it. However, this could potentially starve the BIOS out of the - * lock, especially in the case where there is a tight handshake between the - * Embedded Controller driver and the BIOS. Therefore, this implementation - * allows only one thread to acquire the HW Global Lock at a time, and makes - * the global lock appear as a standard mutex on the OS side. - * *****************************************************************************/ acpi_status acpi_ev_acquire_global_lock(u16 timeout) @@ -432,51 +408,53 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) ACPI_FUNCTION_TRACE(ev_acquire_global_lock); - /* - * Only one thread can acquire the GL at a time, the global_lock_mutex - * enforces this. This interface releases the interpreter if we must wait. - */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); +#ifndef ACPI_APPLICATION + /* Make sure that we actually have a global lock */ + + if (!acpi_gbl_global_lock_present) { + return_ACPI_STATUS(AE_NO_GLOBAL_LOCK); } +#endif + + /* One more thread wants the global lock */ + + acpi_gbl_global_lock_thread_count++; /* - * Make sure that a global lock actually exists. If not, just treat - * the lock as a standard mutex. + * If we (OS side vs. BIOS side) have the hardware lock already, + * we are done */ - if (!acpi_gbl_global_lock_present) { - acpi_gbl_global_lock_acquired = TRUE; + if (acpi_gbl_global_lock_acquired) { return_ACPI_STATUS(AE_OK); } - /* Attempt to acquire the actual hardware lock */ + /* We must acquire the actual hardware lock */ - ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired); + ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { /* We got the lock */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Acquired hardware Global Lock\n")); + "Acquired the HW Global Lock\n")); acpi_gbl_global_lock_acquired = TRUE; return_ACPI_STATUS(AE_OK); } /* - * Did not get the lock. The pending bit was set above, and we must now + * Did not get the lock. The pending bit was set above, and we must now * wait until we get the global lock released interrupt. */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n")); /* - * Wait for handshake with the global lock interrupt handler. - * This interface releases the interpreter if we must wait. + * Acquire the global lock semaphore first. + * Since this wait will block, we must release the interpreter */ - status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, - ACPI_WAIT_FOREVER); - + status = + acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, + timeout); return_ACPI_STATUS(status); } @@ -499,39 +477,38 @@ acpi_status acpi_ev_release_global_lock(void) ACPI_FUNCTION_TRACE(ev_release_global_lock); - /* Lock must be already acquired */ - - if (!acpi_gbl_global_lock_acquired) { + if (!acpi_gbl_global_lock_thread_count) { ACPI_WARNING((AE_INFO, - "Cannot release the ACPI Global Lock, it has not been acquired")); + "Cannot release HW Global Lock, it has not been acquired")); return_ACPI_STATUS(AE_NOT_ACQUIRED); } - if (acpi_gbl_global_lock_present) { + /* One fewer thread has the global lock */ - /* Allow any thread to release the lock */ + acpi_gbl_global_lock_thread_count--; + if (acpi_gbl_global_lock_thread_count) { - ACPI_RELEASE_GLOBAL_LOCK(facs, pending); + /* There are still some threads holding the lock, cannot release */ - /* - * If the pending bit was set, we must write GBL_RLS to the control - * register - */ - if (pending) { - status = - acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, - 1); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Released hardware Global Lock\n")); + return_ACPI_STATUS(AE_OK); } + /* + * No more threads holding lock, we can do the actual hardware + * release + */ + ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending); acpi_gbl_global_lock_acquired = FALSE; - /* Release the local GL mutex */ + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (pending) { + status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, + 1, ACPI_MTX_LOCK); + } - acpi_os_release_mutex(acpi_gbl_global_lock_mutex); return_ACPI_STATUS(status); } @@ -581,12 +558,6 @@ void acpi_ev_terminate(void) if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); } - - status = acpi_ev_remove_global_lock_handler(); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not remove Global Lock handler")); - } } /* Deallocate all handler objects installed within GPE info structs */ diff --git a/trunk/drivers/acpi/events/evregion.c b/trunk/drivers/acpi/events/evregion.c index e99f0c435a47..21caae04fe85 100644 --- a/trunk/drivers/acpi/events/evregion.c +++ b/trunk/drivers/acpi/events/evregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 bit_width, acpi_integer * value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; @@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } /* Check for failure of the Region Setup */ @@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/events/evrgnini.c b/trunk/drivers/acpi/events/evrgnini.c index a4fa7e6822a3..203d1359190a 100644 --- a/trunk/drivers/acpi/events/evrgnini.c +++ b/trunk/drivers/acpi/events/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,11 +48,6 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evrgnini") -/* Local prototypes */ -static u8 acpi_ev_match_pci_root_bridge(char *id); - -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); - /******************************************************************************* * * FUNCTION: acpi_ev_system_memory_region_setup @@ -67,7 +62,6 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); * DESCRIPTION: Setup a system_memory operation region * ******************************************************************************/ - acpi_status acpi_ev_system_memory_region_setup(acpi_handle handle, u32 function, @@ -174,9 +168,9 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, union acpi_operand_object *handler_obj; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *pci_root_node; - struct acpi_namespace_node *pci_device_node; union acpi_operand_object *region_obj = (union acpi_operand_object *)handle; + struct acpi_device_id object_hID; ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); @@ -221,30 +215,45 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, pci_root_node = parent_node; while (pci_root_node != acpi_gbl_root_node) { + status = + acpi_ut_execute_HID(pci_root_node, &object_hID); + if (ACPI_SUCCESS(status)) { + /* + * Got a valid _HID string, check if this is a PCI root. + * New for ACPI 3.0: check for a PCI Express root also. + */ + if (! + (ACPI_STRNCMP + (object_hID.value, PCI_ROOT_HID_STRING, + sizeof(PCI_ROOT_HID_STRING))) + || + !(ACPI_STRNCMP + (object_hID.value, + PCI_EXPRESS_ROOT_HID_STRING, + sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { + + /* Install a handler for this PCI root bridge */ - /* Get the _HID/_CID in order to detect a root_bridge */ - - if (acpi_ev_is_pci_root_bridge(pci_root_node)) { - - /* Install a handler for this PCI root bridge */ - - status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE(status)) { - if (status == AE_SAME_HANDLER) { - /* - * It is OK if the handler is already installed on the root - * bridge. Still need to return a context object for the - * new PCI_Config operation region, however. - */ - status = AE_OK; - } else { - ACPI_EXCEPTION((AE_INFO, status, - "Could not install PciConfig handler for Root Bridge %4.4s", - acpi_ut_get_node_name - (pci_root_node))); + status = + acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + if (ACPI_FAILURE(status)) { + if (status == AE_SAME_HANDLER) { + /* + * It is OK if the handler is already installed on the root + * bridge. Still need to return a context object for the + * new PCI_Config operation region, however. + */ + status = AE_OK; + } else { + ACPI_EXCEPTION((AE_INFO, + status, + "Could not install PciConfig handler for Root Bridge %4.4s", + acpi_ut_get_node_name + (pci_root_node))); + } } + break; } - break; } pci_root_node = acpi_ns_get_parent_node(pci_root_node); @@ -273,25 +282,14 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* * For PCI_Config space access, we need the segment, bus, * device and function numbers. Acquire them here. - * - * Find the parent device object. (This allows the operation region to be - * within a subscope under the device, such as a control method.) */ - pci_device_node = region_obj->region.node; - while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { - pci_device_node = acpi_ns_get_parent_node(pci_device_node); - } - - if (!pci_device_node) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } /* * Get the PCI device and function numbers from the _ADR object * contained in the parent's scope. */ status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, + acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node, &pci_value); /* @@ -329,91 +327,6 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, return_ACPI_STATUS(AE_OK); } -/******************************************************************************* - * - * FUNCTION: acpi_ev_match_pci_root_bridge - * - * PARAMETERS: Id - The HID/CID in string format - * - * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge - * - * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. - * - ******************************************************************************/ - -static u8 acpi_ev_match_pci_root_bridge(char *id) -{ - - /* - * Check if this is a PCI root. - * ACPI 3.0+: check for a PCI Express root also. - */ - if (!(ACPI_STRNCMP(id, - PCI_ROOT_HID_STRING, - sizeof(PCI_ROOT_HID_STRING))) || - !(ACPI_STRNCMP(id, - PCI_EXPRESS_ROOT_HID_STRING, - sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { - return (TRUE); - } - - return (FALSE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_is_pci_root_bridge - * - * PARAMETERS: Node - Device node being examined - * - * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge - * - * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by - * examining the _HID and _CID for the device. - * - ******************************************************************************/ - -static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) -{ - acpi_status status; - struct acpi_device_id hid; - struct acpi_compatible_id_list *cid; - acpi_native_uint i; - - /* - * Get the _HID and check for a PCI Root Bridge - */ - status = acpi_ut_execute_HID(node, &hid); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - - if (acpi_ev_match_pci_root_bridge(hid.value)) { - return (TRUE); - } - - /* - * The _HID did not match. - * Get the _CID and check for a PCI Root Bridge - */ - status = acpi_ut_execute_CID(node, &cid); - if (ACPI_FAILURE(status)) { - return (FALSE); - } - - /* Check all _CIDs in the returned list */ - - for (i = 0; i < cid->count; i++) { - if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { - ACPI_FREE(cid); - return (TRUE); - } - } - - ACPI_FREE(cid); - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_ev_pci_bar_region_setup @@ -519,9 +432,6 @@ acpi_ev_default_region_setup(acpi_handle handle, * a PCI address in the scope of the definition. This address is * required to perform an access to PCI config space. * - * MUTEX: Interpreter should be unlocked, because we may run the _REG - * method for this region. - * ******************************************************************************/ acpi_status diff --git a/trunk/drivers/acpi/events/evsci.c b/trunk/drivers/acpi/events/evsci.c index 7e5d15ce2395..8106215ad554 100644 --- a/trunk/drivers/acpi/events/evsci.c +++ b/trunk/drivers/acpi/events/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -142,10 +142,9 @@ u32 acpi_ev_install_sci_handler(void) ACPI_FUNCTION_TRACE(ev_install_sci_handler); - status = - acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, - acpi_ev_sci_xrupt_handler, - acpi_gbl_gpe_xrupt_list_head); + status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int, + acpi_ev_sci_xrupt_handler, + acpi_gbl_gpe_xrupt_list_head); return_ACPI_STATUS(status); } @@ -176,9 +175,8 @@ acpi_status acpi_ev_remove_sci_handler(void) /* Just let the OS remove the handler and disable the level */ - status = - acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, - acpi_ev_sci_xrupt_handler); + status = acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT->sci_int, + acpi_ev_sci_xrupt_handler); return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/events/evxface.c b/trunk/drivers/acpi/events/evxface.c index 685a103a3587..923fd2b46955 100644 --- a/trunk/drivers/acpi/events/evxface.c +++ b/trunk/drivers/acpi/events/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -768,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_ex_enter_interpreter(); status = acpi_ev_acquire_global_lock(timeout); acpi_ex_exit_interpreter(); diff --git a/trunk/drivers/acpi/events/evxfevnt.c b/trunk/drivers/acpi/events/evxfevnt.c index 17065e98807c..7ebc2efac936 100644 --- a/trunk/drivers/acpi/events/evxfevnt.c +++ b/trunk/drivers/acpi/events/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include #include #include -#include #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evxfevnt") @@ -66,14 +65,13 @@ acpi_status acpi_enable(void) ACPI_FUNCTION_TRACE(acpi_enable); - /* ACPI tables must be present */ + /* Make sure we have the FADT */ - if (!acpi_tb_tables_loaded()) { + if (!acpi_gbl_FADT) { + ACPI_WARNING((AE_INFO, "No FADT information present!")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } - /* Check current mode */ - if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "System is already in ACPI mode\n")); @@ -113,6 +111,11 @@ acpi_status acpi_disable(void) ACPI_FUNCTION_TRACE(acpi_disable); + if (!acpi_gbl_FADT) { + ACPI_WARNING((AE_INFO, "No FADT information present!")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { ACPI_DEBUG_PRINT((ACPI_DB_INIT, "System is already in legacy (non-ACPI) mode\n")); @@ -166,7 +169,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 1); + enable_register_id, 1, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -175,7 +178,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags) status = acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + enable_register_id, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -365,14 +368,14 @@ acpi_status acpi_disable_event(u32 event, u32 flags) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + enable_register_id, 0, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + enable_register_id, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -418,7 +421,7 @@ acpi_status acpi_clear_event(u32 event) */ status = acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + status_register_id, 1, ACPI_MTX_LOCK); return_ACPI_STATUS(status); } @@ -507,7 +510,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) status = acpi_get_register(acpi_gbl_fixed_event_info[event]. - status_register_id, event_status); + status_register_id, event_status, ACPI_MTX_LOCK); return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/events/evxfregn.c b/trunk/drivers/acpi/events/evxfregn.c index 7bf09c5fb242..83b12a9afa32 100644 --- a/trunk/drivers/acpi/events/evxfregn.c +++ b/trunk/drivers/acpi/events/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exconfig.c b/trunk/drivers/acpi/executer/exconfig.c index 25802f302ffe..c8341fa5fe01 100644 --- a/trunk/drivers/acpi/executer/exconfig.c +++ b/trunk/drivers/acpi/executer/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ ACPI_MODULE_NAME("exconfig") /* Local prototypes */ static acpi_status -acpi_ex_add_table(acpi_native_uint table_index, +acpi_ex_add_table(struct acpi_table_header *table, struct acpi_namespace_node *parent_node, union acpi_operand_object **ddb_handle); @@ -74,11 +74,12 @@ acpi_ex_add_table(acpi_native_uint table_index, ******************************************************************************/ static acpi_status -acpi_ex_add_table(acpi_native_uint table_index, +acpi_ex_add_table(struct acpi_table_header *table, struct acpi_namespace_node *parent_node, union acpi_operand_object **ddb_handle) { acpi_status status; + struct acpi_table_desc table_info; union acpi_operand_object *obj_desc; ACPI_FUNCTION_TRACE(ex_add_table); @@ -97,16 +98,42 @@ acpi_ex_add_table(acpi_native_uint table_index, /* Install the new table into the local data structures */ - obj_desc->reference.object = ACPI_CAST_PTR(void, table_index); + ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); + + table_info.type = ACPI_TABLE_ID_SSDT; + table_info.pointer = table; + table_info.length = (acpi_size) table->length; + table_info.allocation = ACPI_MEM_ALLOCATED; + + status = acpi_tb_install_table(&table_info); + obj_desc->reference.object = table_info.installed_desc; + + if (ACPI_FAILURE(status)) { + if (status == AE_ALREADY_EXISTS) { + + /* Table already exists, just return the handle */ + + return_ACPI_STATUS(AE_OK); + } + goto cleanup; + } /* Add the table to the namespace */ - status = acpi_ns_load_table(table_index, parent_node); + status = acpi_ns_load_table(table_info.installed_desc, parent_node); if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(obj_desc); - *ddb_handle = NULL; + + /* Uninstall table on error */ + + (void)acpi_tb_uninstall_table(table_info.installed_desc); + goto cleanup; } + return_ACPI_STATUS(AE_OK); + + cleanup: + acpi_ut_remove_reference(obj_desc); + *ddb_handle = NULL; return_ACPI_STATUS(status); } @@ -119,7 +146,7 @@ acpi_ex_add_table(acpi_native_uint table_index, * * RETURN: Status * - * DESCRIPTION: Load an ACPI table from the RSDT/XSDT + * DESCRIPTION: Load an ACPI table * ******************************************************************************/ @@ -129,20 +156,33 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, { acpi_status status; union acpi_operand_object **operand = &walk_state->operands[0]; - acpi_native_uint table_index; + struct acpi_table_header *table; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *start_node; struct acpi_namespace_node *parameter_node = NULL; union acpi_operand_object *ddb_handle; - struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Find the ACPI table in the RSDT/XSDT */ +#if 0 + /* + * Make sure that the signature does not match one of the tables that + * is already loaded. + */ + status = acpi_tb_match_signature(operand[0]->string.pointer, NULL); + if (status == AE_OK) { + + /* Signature matched -- don't allow override */ + + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } +#endif + + /* Find the ACPI table */ status = acpi_tb_find_table(operand[0]->string.pointer, operand[1]->string.pointer, - operand[2]->string.pointer, &table_index); + operand[2]->string.pointer, &table); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) { return_ACPI_STATUS(status); @@ -205,7 +245,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* Load the table into the namespace */ - status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); + status = acpi_ex_add_table(table, parent_node, &ddb_handle); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -226,13 +266,9 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, } } - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_SUCCESS(status)) { - ACPI_INFO((AE_INFO, - "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", - table->signature, table->oem_id, - table->oem_table_id)); - } + ACPI_INFO((AE_INFO, + "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", + table->signature, table->oem_id, table->oem_table_id)); *return_desc = ddb_handle; return_ACPI_STATUS(status); @@ -242,7 +278,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, * * FUNCTION: acpi_ex_load_op * - * PARAMETERS: obj_desc - Region or Buffer/Field where the table will be + * PARAMETERS: obj_desc - Region or Field where the table will be * obtained * Target - Where a handle to the table will be stored * walk_state - Current state @@ -251,12 +287,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, * * DESCRIPTION: Load an ACPI table from a field or operation region * - * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer - * objects before this code is reached. - * - * If source is an operation region, it must refer to system_memory, as - * per the ACPI specification. - * ******************************************************************************/ acpi_status @@ -264,26 +294,22 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, union acpi_operand_object *target, struct acpi_walk_state *walk_state) { - union acpi_operand_object *ddb_handle; - struct acpi_table_desc table_desc; - acpi_native_uint table_index; acpi_status status; + union acpi_operand_object *ddb_handle; + union acpi_operand_object *buffer_desc = NULL; + struct acpi_table_header *table_ptr = NULL; + acpi_physical_address address; + struct acpi_table_header table_header; + acpi_integer temp; + u32 i; ACPI_FUNCTION_TRACE(ex_load_op); - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - - /* Source Object can be either an op_region or a Buffer/Field */ + /* Object can be either an op_region or a Field */ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: - /* Region must be system_memory (from ACPI spec) */ - - if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); @@ -299,41 +325,113 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } } - table_desc.address = obj_desc->region.address; - table_desc.length = obj_desc->region.length; - table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; - break; + /* Get the base physical address of the region */ - case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ + address = obj_desc->region.address; - /* Simply extract the buffer from the buffer object */ + /* Get part of the table header to get the table length */ - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Load from Buffer or Field %p %s\n", obj_desc, + table_header.length = 0; + for (i = 0; i < 8; i++) { + status = + acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, + (acpi_physical_address) + (i + address), 8, + &temp); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; + } + + /* Sanity check the table length */ + + if (table_header.length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_BAD_HEADER); + } + + /* Allocate a buffer for the entire table */ + + table_ptr = ACPI_ALLOCATE(table_header.length); + if (!table_ptr) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Get the entire table from the op region */ + + for (i = 0; i < table_header.length; i++) { + status = + acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, + (acpi_physical_address) + (i + address), 8, + &temp); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; + } + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n", + obj_desc, acpi_ut_get_object_type_name(obj_desc))); - table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, - obj_desc->buffer.pointer); - table_desc.length = table_desc.pointer->length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + /* + * The length of the field must be at least as large as the table. + * Read the entire field and thus the entire table. Buffer is + * allocated during the read. + */ + status = + acpi_ex_read_data_from_field(walk_state, obj_desc, + &buffer_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + table_ptr = ACPI_CAST_PTR(struct acpi_table_header, + buffer_desc->buffer.pointer); + + /* All done with the buffer_desc, delete it */ + + buffer_desc->buffer.pointer = NULL; + acpi_ut_remove_reference(buffer_desc); + + /* Sanity check the table length */ - obj_desc->buffer.pointer = NULL; + if (table_ptr->length < sizeof(struct acpi_table_header)) { + status = AE_BAD_HEADER; + goto cleanup; + } break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* - * Install the new table into the local data structures - */ - status = acpi_tb_add_table(&table_desc, &table_index); - if (ACPI_FAILURE(status)) { + /* The table must be either an SSDT or a PSDT */ + + if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && + (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) { + ACPI_ERROR((AE_INFO, + "Table has invalid signature [%4.4s], must be SSDT or PSDT", + table_ptr->signature)); + status = AE_BAD_SIGNATURE; goto cleanup; } - status = - acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); + /* Install the new table into the local data structures */ + + status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ @@ -352,9 +450,13 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(status); } + ACPI_INFO((AE_INFO, + "Dynamic SSDT Load - OemId [%6.6s] OemTableId [%8.8s]", + table_ptr->oem_id, table_ptr->oem_table_id)); + cleanup: if (ACPI_FAILURE(status)) { - acpi_tb_delete_table(&table_desc); + ACPI_FREE(table_ptr); } return_ACPI_STATUS(status); } @@ -375,7 +477,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) { acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; - acpi_native_uint table_index; + struct acpi_table_desc *table_info; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -391,18 +493,19 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the table index from the ddb_handle */ + /* Get the actual table descriptor from the ddb_handle */ - table_index = (acpi_native_uint) table_desc->reference.object; + table_info = (struct acpi_table_desc *)table_desc->reference.object; /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ - acpi_tb_delete_namespace_by_owner(table_index); - acpi_tb_release_owner_id(table_index); + acpi_ns_delete_namespace_by_owner(table_info->owner_id); + + /* Delete the table itself */ - acpi_tb_set_table_loaded_flag(table_index, FALSE); + (void)acpi_tb_uninstall_table(table_info->installed_desc); /* Delete the table descriptor (ddb_handle) */ diff --git a/trunk/drivers/acpi/executer/exconvrt.c b/trunk/drivers/acpi/executer/exconvrt.c index d470e8b1f4ea..544e81a6a438 100644 --- a/trunk/drivers/acpi/executer/exconvrt.c +++ b/trunk/drivers/acpi/executer/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/excreate.c b/trunk/drivers/acpi/executer/excreate.c index 7c38528a7e83..34eec82c1b1e 100644 --- a/trunk/drivers/acpi/executer/excreate.c +++ b/trunk/drivers/acpi/executer/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -359,9 +359,8 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) union acpi_operand_object **operand = &walk_state->operands[0]; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; - union acpi_operand_object *region_obj2; - acpi_native_uint table_index; struct acpi_table_header *table; + union acpi_operand_object *region_obj2; ACPI_FUNCTION_TRACE(ex_create_table_region); @@ -381,7 +380,7 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) status = acpi_tb_find_table(operand[1]->string.pointer, operand[2]->string.pointer, - operand[3]->string.pointer, &table_index); + operand[3]->string.pointer, &table); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -396,11 +395,6 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) region_obj2 = obj_desc->common.next_object; region_obj2->extra.region_context = NULL; - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - /* Init the region from the operands */ obj_desc->region.space_id = REGION_DATA_TABLE; @@ -559,8 +553,7 @@ acpi_ex_create_method(u8 * aml_start, obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); if (!obj_desc) { - status = AE_NO_MEMORY; - goto exit; + return_ACPI_STATUS(AE_NO_MEMORY); } /* Save the method's AML pointer and length */ @@ -583,7 +576,10 @@ acpi_ex_create_method(u8 * aml_start, * Get the sync_level. If method is serialized, a mutex will be * created for this method when it is parsed. */ - if (method_flags & AML_METHOD_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.sync_level = 0; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: sync_level = 0 * ACPI 2.0: sync_level = sync_level in method declaration @@ -601,7 +597,6 @@ acpi_ex_create_method(u8 * aml_start, acpi_ut_remove_reference(obj_desc); - exit: /* Remove a reference to the operand */ acpi_ut_remove_reference(operand[1]); diff --git a/trunk/drivers/acpi/executer/exdump.c b/trunk/drivers/acpi/executer/exdump.c index 68d283fd60e7..2450943add33 100644 --- a/trunk/drivers/acpi/executer/exdump.c +++ b/trunk/drivers/acpi/executer/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,6 +59,8 @@ static void acpi_ex_out_string(char *title, char *value); static void acpi_ex_out_pointer(char *title, void *value); +static void acpi_ex_out_address(char *title, acpi_physical_address value); + static void acpi_ex_dump_object(union acpi_operand_object *obj_desc, struct acpi_exdump_info *info); @@ -90,11 +92,10 @@ static struct acpi_exdump_info acpi_ex_dump_string[4] = { {ACPI_EXD_STRING, 0, NULL} }; -static struct acpi_exdump_info acpi_ex_dump_buffer[5] = { +static struct acpi_exdump_info acpi_ex_dump_buffer[4] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_buffer), NULL}, {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(buffer.length), "Length"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.pointer), "Pointer"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(buffer.node), "Parent Node"}, {ACPI_EXD_BUFFER, 0, NULL} }; @@ -164,8 +165,8 @@ static struct acpi_exdump_info acpi_ex_dump_power[5] = { static struct acpi_exdump_info acpi_ex_dump_processor[7] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_processor), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(processor.length), "Length"}, {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), "System Notify"}, @@ -378,12 +379,18 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, break; case ACPI_EXD_POINTER: - case ACPI_EXD_ADDRESS: acpi_ex_out_pointer(name, *ACPI_CAST_PTR(void *, target)); break; + case ACPI_EXD_ADDRESS: + + acpi_ex_out_address(name, + *ACPI_CAST_PTR + (acpi_physical_address, target)); + break; + case ACPI_EXD_STRING: acpi_ut_print_string(obj_desc->string.pointer, @@ -827,6 +834,16 @@ static void acpi_ex_out_pointer(char *title, void *value) acpi_os_printf("%20s : %p\n", title, value); } +static void acpi_ex_out_address(char *title, acpi_physical_address value) +{ + +#if ACPI_MACHINE_WIDTH == 16 + acpi_os_printf("%20s : %p\n", title, value); +#else + acpi_os_printf("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value)); +#endif +} + /******************************************************************************* * * FUNCTION: acpi_ex_dump_namespace_node diff --git a/trunk/drivers/acpi/executer/exfield.c b/trunk/drivers/acpi/executer/exfield.c index 2d88a3d8d1ad..9ea9c3a67ca9 100644 --- a/trunk/drivers/acpi/executer/exfield.c +++ b/trunk/drivers/acpi/executer/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exfldio.c b/trunk/drivers/acpi/executer/exfldio.c index 65a48b6170ee..40f0bee6faa5 100644 --- a/trunk/drivers/acpi/executer/exfldio.c +++ b/trunk/drivers/acpi/executer/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -257,13 +257,14 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, } ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, - " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", + " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", acpi_ut_get_region_name(rgn_desc->region. space_id), rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, (void *)address)); + field_datum_byte_offset, + ACPI_FORMAT_UINT64(address))); /* Invoke the appropriate address_space/op_region handler */ diff --git a/trunk/drivers/acpi/executer/exmisc.c b/trunk/drivers/acpi/executer/exmisc.c index f13d1cec2d6d..bd98aab017cf 100644 --- a/trunk/drivers/acpi/executer/exmisc.c +++ b/trunk/drivers/acpi/executer/exmisc.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exmutex.c b/trunk/drivers/acpi/executer/exmutex.c index 5101bad5baf8..bf90f04f2c60 100644 --- a/trunk/drivers/acpi/executer/exmutex.c +++ b/trunk/drivers/acpi/executer/exmutex.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include #include -#include #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exmutex") @@ -151,7 +150,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Sanity check: we must have a valid thread ID */ + /* Sanity check -- we must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -175,28 +174,24 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { + + /* Special case for Global Lock, allow all threads */ + + if ((obj_desc->mutex.owner_thread->thread_id == + walk_state->thread->thread_id) || + (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK)) { /* - * The mutex is already owned by this thread, just increment the - * acquisition depth + * The mutex is already owned by this thread, + * just increment the acquisition depth */ obj_desc->mutex.acquisition_depth++; return_ACPI_STATUS(AE_OK); } } - /* Acquire the mutex, wait if necessary. Special case for Global Lock */ - - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = - acpi_ev_acquire_global_lock((u16) time_desc->integer.value); - } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - (u16) time_desc->integer. - value); - } + /* Acquire the mutex, wait if necessary */ + status = acpi_ex_system_acquire_mutex(time_desc, obj_desc); if (ACPI_FAILURE(status)) { /* Includes failure from a timeout on time_desc */ @@ -216,6 +211,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Link the mutex to the current thread for force-unlock at method exit */ acpi_ex_link_mutex(obj_desc, walk_state->thread); + return_ACPI_STATUS(AE_OK); } @@ -236,7 +232,7 @@ acpi_status acpi_ex_release_mutex(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { - acpi_status status = AE_OK; + acpi_status status; ACPI_FUNCTION_TRACE(ex_release_mutex); @@ -253,7 +249,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check: we must have a valid thread ID */ + /* Sanity check -- we must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -268,7 +264,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { + && (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, @@ -278,8 +274,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, } /* - * The sync level of the mutex must be less than or equal to the current - * sync level + * The sync level of the mutex must be less than or + * equal to the current sync level */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, @@ -302,15 +298,11 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, acpi_ex_unlink_mutex(obj_desc); - /* Release the mutex, special case for Global Lock */ + /* Release the mutex */ - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - status = acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); - } + status = acpi_ex_system_release_mutex(obj_desc); - /* Update the mutex and restore sync_level */ + /* Update the mutex and walk state, restore sync_level before acquire */ obj_desc->mutex.owner_thread = NULL; walk_state->thread->current_sync_level = @@ -329,49 +321,39 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * * DESCRIPTION: Release all mutexes held by this thread * - * NOTE: This function is called as the thread is exiting the interpreter. - * Mutexes are not released when an individual control method is exited, but - * only when the parent thread actually exits the interpreter. This allows one - * method to acquire a mutex, and a different method to release it, as long as - * this is performed underneath a single parent control method. - * ******************************************************************************/ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) { union acpi_operand_object *next = thread->acquired_mutex_list; - union acpi_operand_object *obj_desc; + union acpi_operand_object *this; + acpi_status status; ACPI_FUNCTION_ENTRY(); /* Traverse the list of owned mutexes, releasing each one */ while (next) { - obj_desc = next; - next = obj_desc->mutex.next; - - obj_desc->mutex.prev = NULL; - obj_desc->mutex.next = NULL; - obj_desc->mutex.acquisition_depth = 0; - - /* Release the mutex, special case for Global Lock */ + this = next; + next = this->mutex.next; - if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + this->mutex.acquisition_depth = 1; + this->mutex.prev = NULL; + this->mutex.next = NULL; - /* Ignore errors */ + /* Release the mutex */ - (void)acpi_ev_release_global_lock(); - } else { - acpi_os_release_mutex(obj_desc->mutex.os_mutex); + status = acpi_ex_system_release_mutex(this); + if (ACPI_FAILURE(status)) { + continue; } /* Mark mutex unowned */ - obj_desc->mutex.owner_thread = NULL; + this->mutex.owner_thread = NULL; /* Update Thread sync_level (Last mutex is the important one) */ - thread->current_sync_level = - obj_desc->mutex.original_sync_level; + thread->current_sync_level = this->mutex.original_sync_level; } } diff --git a/trunk/drivers/acpi/executer/exnames.c b/trunk/drivers/acpi/executer/exnames.c index 1ee4fb1175c6..d3d70364626c 100644 --- a/trunk/drivers/acpi/executer/exnames.c +++ b/trunk/drivers/acpi/executer/exnames.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exoparg1.c b/trunk/drivers/acpi/executer/exoparg1.c index 252f10acbbcc..6374d8be88e0 100644 --- a/trunk/drivers/acpi/executer/exoparg1.c +++ b/trunk/drivers/acpi/executer/exoparg1.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,7 +104,9 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) status = AE_NO_MEMORY; goto cleanup; } +#if ACPI_MACHINE_WIDTH != 16 return_desc->integer.value = acpi_os_get_timer(); +#endif break; default: /* Unknown opcode */ diff --git a/trunk/drivers/acpi/executer/exoparg2.c b/trunk/drivers/acpi/executer/exoparg2.c index 17e652e65379..7d2cbc113160 100644 --- a/trunk/drivers/acpi/executer/exoparg2.c +++ b/trunk/drivers/acpi/executer/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exoparg3.c b/trunk/drivers/acpi/executer/exoparg3.c index 7fe67cf82cee..e2d945dfd509 100644 --- a/trunk/drivers/acpi/executer/exoparg3.c +++ b/trunk/drivers/acpi/executer/exoparg3.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exoparg6.c b/trunk/drivers/acpi/executer/exoparg6.c index bd80a9cb3d65..f0c0ba6eb408 100644 --- a/trunk/drivers/acpi/executer/exoparg6.c +++ b/trunk/drivers/acpi/executer/exoparg6.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exprep.c b/trunk/drivers/acpi/executer/exprep.c index a6696621ff1b..44d064f427b9 100644 --- a/trunk/drivers/acpi/executer/exprep.c +++ b/trunk/drivers/acpi/executer/exprep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exregion.c b/trunk/drivers/acpi/executer/exregion.c index 2e9ce94798c7..3cc97ba48b36 100644 --- a/trunk/drivers/acpi/executer/exregion.c +++ b/trunk/drivers/acpi/executer/exregion.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -155,15 +155,16 @@ acpi_ex_system_memory_space_handler(u32 function, /* Create a new mapping starting at the address given */ - mem_info->mapped_logical_address = - acpi_os_map_memory((acpi_native_uint) address, window_size); - if (!mem_info->mapped_logical_address) { + status = acpi_os_map_memory(address, window_size, + (void **)&mem_info-> + mapped_logical_address); + if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", ACPI_FORMAT_UINT64(address), (u32) window_size)); mem_info->mapped_length = 0; - return_ACPI_STATUS(AE_NO_MEMORY); + return_ACPI_STATUS(status); } /* Save the physical address and mapping size */ @@ -209,10 +210,11 @@ acpi_ex_system_memory_space_handler(u32 function, *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); break; +#if ACPI_MACHINE_WIDTH != 16 case 64: *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); break; - +#endif default: /* bit_width was already validated */ break; @@ -234,9 +236,11 @@ acpi_ex_system_memory_space_handler(u32 function, ACPI_SET32(logical_addr_ptr) = (u32) * value; break; +#if ACPI_MACHINE_WIDTH != 16 case 64: ACPI_SET64(logical_addr_ptr) = (u64) * value; break; +#endif default: /* bit_width was already validated */ diff --git a/trunk/drivers/acpi/executer/exresnte.c b/trunk/drivers/acpi/executer/exresnte.c index 2b3a01cc4929..3089b05a1368 100644 --- a/trunk/drivers/acpi/executer/exresnte.c +++ b/trunk/drivers/acpi/executer/exresnte.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exresolv.c b/trunk/drivers/acpi/executer/exresolv.c index 6c64e55dab0e..6499de878017 100644 --- a/trunk/drivers/acpi/executer/exresolv.c +++ b/trunk/drivers/acpi/executer/exresolv.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -141,7 +141,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, acpi_status status = AE_OK; union acpi_operand_object *stack_desc; void *temp_node; - union acpi_operand_object *obj_desc = NULL; + union acpi_operand_object *obj_desc; u16 opcode; ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); @@ -299,6 +299,8 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, status = acpi_ds_get_package_arguments(stack_desc); break; + /* These cases may never happen here, but just in case.. */ + case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: @@ -312,10 +314,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, status = acpi_ex_read_data_from_field(walk_state, stack_desc, &obj_desc); - - /* Remove a reference to the original operand, then override */ - - acpi_ut_remove_reference(*stack_ptr); *stack_ptr = (void *)obj_desc; break; diff --git a/trunk/drivers/acpi/executer/exresop.c b/trunk/drivers/acpi/executer/exresop.c index ba761862a599..4c93d0972333 100644 --- a/trunk/drivers/acpi/executer/exresop.c +++ b/trunk/drivers/acpi/executer/exresop.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -611,20 +611,22 @@ acpi_ex_resolve_operands(u16 opcode, } goto next_operand; - case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ + case ARGI_REGION_OR_FIELD: - /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ + /* Need an operand of type REGION or a FIELD in a region */ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { - case ACPI_TYPE_BUFFER: case ACPI_TYPE_REGION: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Valid operand */ break; default: ACPI_ERROR((AE_INFO, - "Needed [Region/Buffer], found [%s] %p", + "Needed [Region/RegionField], found [%s] %p", acpi_ut_get_object_type_name (obj_desc), obj_desc)); diff --git a/trunk/drivers/acpi/executer/exstore.c b/trunk/drivers/acpi/executer/exstore.c index f4b69a637820..0456405ba019 100644 --- a/trunk/drivers/acpi/executer/exstore.c +++ b/trunk/drivers/acpi/executer/exstore.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exstoren.c b/trunk/drivers/acpi/executer/exstoren.c index 1d622c625c64..591aaf0e18b3 100644 --- a/trunk/drivers/acpi/executer/exstoren.c +++ b/trunk/drivers/acpi/executer/exstoren.c @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exstorob.c b/trunk/drivers/acpi/executer/exstorob.c index 8233d40178ee..99ebe5adfcda 100644 --- a/trunk/drivers/acpi/executer/exstorob.c +++ b/trunk/drivers/acpi/executer/exstorob.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/executer/exsystem.c b/trunk/drivers/acpi/executer/exsystem.c index 9460baff3032..28aef3e69ecc 100644 --- a/trunk/drivers/acpi/executer/exsystem.c +++ b/trunk/drivers/acpi/executer/exsystem.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem") acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); @@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_mutex); @@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -195,18 +209,96 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { + acpi_status status; + ACPI_FUNCTION_ENTRY(); /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_os_sleep(how_long); /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); - return (AE_OK); + status = acpi_ex_enter_interpreter(); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_acquire_mutex + * + * PARAMETERS: time_desc - Maximum time to wait for the mutex + * obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This function will cause a lock to be generated + * for the Mutex pointed to by obj_desc. + * + ******************************************************************************/ + +acpi_status +acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc, + union acpi_operand_object * obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Support for the _GL_ Mutex object -- go get the global lock */ + + if (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK) { + status = + acpi_ev_acquire_global_lock((u16) time_desc->integer.value); + return_ACPI_STATUS(status); + } + + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + (u16) time_desc->integer.value); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_system_release_mutex + * + * PARAMETERS: obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to release a + * previously acquired Mutex. If the Mutex variable is set then + * it will be decremented. + * + ******************************************************************************/ + +acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ex_system_release_mutex); + + if (!obj_desc) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Support for the _GL_ Mutex object -- release the global lock */ + + if (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK) { + status = acpi_ev_release_global_lock(); + return_ACPI_STATUS(status); + } + + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* @@ -222,7 +314,7 @@ acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) * ******************************************************************************/ -acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) +acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc) { acpi_status status = AE_OK; diff --git a/trunk/drivers/acpi/executer/exutils.c b/trunk/drivers/acpi/executer/exutils.c index 6b0aeccbb69b..982c8b65876f 100644 --- a/trunk/drivers/acpi/executer/exutils.c +++ b/trunk/drivers/acpi/executer/exutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ -void acpi_ex_enter_interpreter(void) +acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; @@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void) * * RETURN: None * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void) * * RETURN: none * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. * ******************************************************************************/ diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index af22fdf73413..f305a826ca2d 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -48,8 +48,8 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state); -static int acpi_fan_resume(struct acpi_device *device); +static int acpi_fan_suspend(struct acpi_device *device, int state); +static int acpi_fan_resume(struct acpi_device *device, int state); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -237,7 +237,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type) return 0; } -static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) +static int acpi_fan_suspend(struct acpi_device *device, int state) { if (!device) return -EINVAL; @@ -247,7 +247,7 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state) return AE_OK; } -static int acpi_fan_resume(struct acpi_device *device) +static int acpi_fan_resume(struct acpi_device *device, int state) { int result = 0; int power_state = 0; diff --git a/trunk/drivers/acpi/glue.c b/trunk/drivers/acpi/glue.c index 7b6c9ff9bebe..8a0324b43e53 100644 --- a/trunk/drivers/acpi/glue.c +++ b/trunk/drivers/acpi/glue.c @@ -86,6 +86,129 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) return ret; } +/* Get PCI root bridge's handle from its segment and bus number */ +struct acpi_find_pci_root { + unsigned int seg; + unsigned int bus; + acpi_handle handle; +}; + +static acpi_status +do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) +{ + unsigned long *busnr = data; + struct acpi_resource_address64 address; + + if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 && + resource->type != ACPI_RESOURCE_TYPE_ADDRESS64) + return AE_OK; + + acpi_resource_to_address64(resource, &address); + if ((address.address_length > 0) && + (address.resource_type == ACPI_BUS_NUMBER_RANGE)) + *busnr = address.minimum; + + return AE_OK; +} + +static int get_root_bridge_busnr(acpi_handle handle) +{ + acpi_status status; + unsigned long bus, bbn; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, + &bbn); + if (status == AE_NOT_FOUND) { + /* Assume bus = 0 */ + printk(KERN_INFO PREFIX + "Assume root bridge [%s] bus is 0\n", + (char *)buffer.pointer); + status = AE_OK; + bbn = 0; + } + if (ACPI_FAILURE(status)) { + bbn = -ENODEV; + goto exit; + } + if (bbn > 0) + goto exit; + + /* _BBN in some systems return 0 for all root bridges */ + bus = -1; + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + do_root_bridge_busnr_callback, &bus); + /* If _CRS failed, we just use _BBN */ + if (ACPI_FAILURE(status) || (bus == -1)) + goto exit; + /* We select _CRS */ + if (bbn != bus) { + printk(KERN_INFO PREFIX + "_BBN and _CRS returns different value for %s. Select _CRS\n", + (char *)buffer.pointer); + bbn = bus; + } + exit: + kfree(buffer.pointer); + return (int)bbn; +} + +static acpi_status +find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpi_find_pci_root *find = (struct acpi_find_pci_root *)context; + unsigned long seg, bus; + acpi_status status; + int tmp; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &seg); + if (status == AE_NOT_FOUND) { + /* Assume seg = 0 */ + status = AE_OK; + seg = 0; + } + if (ACPI_FAILURE(status)) { + status = AE_CTRL_DEPTH; + goto exit; + } + + tmp = get_root_bridge_busnr(handle); + if (tmp < 0) { + printk(KERN_ERR PREFIX + "Find root bridge failed for %s\n", + (char *)buffer.pointer); + status = AE_CTRL_DEPTH; + goto exit; + } + bus = tmp; + + if (seg == find->seg && bus == find->bus) + { + find->handle = handle; + status = AE_CTRL_TERMINATE; + } + else + status = AE_OK; + exit: + kfree(buffer.pointer); + return status; +} + +acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) +{ + struct acpi_find_pci_root find = { seg, bus, NULL }; + + acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL); + return find.handle; +} +EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); + /* Get device's handler per its address under its parent */ struct acpi_find_child { acpi_handle handle; diff --git a/trunk/drivers/acpi/hardware/hwacpi.c b/trunk/drivers/acpi/hardware/hwacpi.c index 6031ca13dd2f..de50fab2a910 100644 --- a/trunk/drivers/acpi/hardware/hwacpi.c +++ b/trunk/drivers/acpi/hardware/hwacpi.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,41 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwacpi") +/****************************************************************************** + * + * FUNCTION: acpi_hw_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and validate the various ACPI registers defined in + * the FADT. + * + ******************************************************************************/ +acpi_status acpi_hw_initialize(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_initialize); + + /* We must have the ACPI tables by the time we get here */ + + if (!acpi_gbl_FADT) { + ACPI_ERROR((AE_INFO, "No FADT is present")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* Sanity check the FADT for valid values */ + + status = acpi_ut_validate_fadt(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_hw_set_mode @@ -58,6 +93,7 @@ ACPI_MODULE_NAME("hwacpi") * DESCRIPTION: Transitions the system into the requested mode. * ******************************************************************************/ + acpi_status acpi_hw_set_mode(u32 mode) { @@ -70,7 +106,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. */ - if (!acpi_gbl_FADT.smi_command) { + if (!acpi_gbl_FADT->smi_cmd) { ACPI_ERROR((AE_INFO, "No SMI_CMD in FADT, mode transition failed")); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); @@ -83,7 +119,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * we make sure both the numbers are zero to determine these * transitions are not supported. */ - if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) { + if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) { ACPI_ERROR((AE_INFO, "No ACPI mode transition supported in this system (enable/disable both zero)")); return_ACPI_STATUS(AE_OK); @@ -94,8 +130,9 @@ acpi_status acpi_hw_set_mode(u32 mode) /* BIOS should have disabled ALL fixed and GP events */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_enable, 8); + status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, + (u32) acpi_gbl_FADT->acpi_enable, + 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); break; @@ -106,8 +143,8 @@ acpi_status acpi_hw_set_mode(u32 mode) * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_disable, + status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, + (u32) acpi_gbl_FADT->acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); @@ -167,11 +204,12 @@ u32 acpi_hw_get_mode(void) * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. */ - if (!acpi_gbl_FADT.smi_command) { + if (!acpi_gbl_FADT->smi_cmd) { return_UINT32(ACPI_SYS_MODE_ACPI); } - status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value); + status = + acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value, ACPI_MTX_LOCK); if (ACPI_FAILURE(status)) { return_UINT32(ACPI_SYS_MODE_LEGACY); } diff --git a/trunk/drivers/acpi/hardware/hwgpe.c b/trunk/drivers/acpi/hardware/hwgpe.c index 117a05cadaaa..608a3a60ee11 100644 --- a/trunk/drivers/acpi/hardware/hwgpe.c +++ b/trunk/drivers/acpi/hardware/hwgpe.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -105,20 +105,14 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info) acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) { acpi_status status; - u8 register_bit; ACPI_FUNCTION_ENTRY(); - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); - /* * Write a one to the appropriate bit in the status register to * clear this GPE. */ - status = acpi_hw_low_level_write(8, register_bit, + status = acpi_hw_low_level_write(8, gpe_event_info->register_bit, &gpe_event_info->register_info-> status_address); @@ -161,10 +155,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = gpe_event_info->register_bit; /* GPE currently enabled? (enabled for runtime?) */ diff --git a/trunk/drivers/acpi/hardware/hwregs.c b/trunk/drivers/acpi/hardware/hwregs.c index 1d371fa663f2..fa58c1edce1e 100644 --- a/trunk/drivers/acpi/hardware/hwregs.c +++ b/trunk/drivers/acpi/hardware/hwregs.c @@ -7,7 +7,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,15 +54,17 @@ ACPI_MODULE_NAME("hwregs") * * FUNCTION: acpi_hw_clear_acpi_status * - * PARAMETERS: None + * PARAMETERS: Flags - Lock the hardware or not * - * RETURN: None + * RETURN: none * * DESCRIPTION: Clears all fixed and general purpose status bits * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ -acpi_status acpi_hw_clear_acpi_status(void) +acpi_status acpi_hw_clear_acpi_status(u32 flags) { acpi_status status; acpi_cpu_flags lock_flags = 0; @@ -71,7 +73,7 @@ acpi_status acpi_hw_clear_acpi_status(void) ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", ACPI_BITMASK_ALL_FIXED_STATUS, - (u16) acpi_gbl_FADT.xpm1a_event_block.address)); + (u16) acpi_gbl_FADT->xpm1a_evt_blk.address)); lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); @@ -84,10 +86,10 @@ acpi_status acpi_hw_clear_acpi_status(void) /* Clear the fixed events */ - if (acpi_gbl_FADT.xpm1b_event_block.address) { + if (acpi_gbl_FADT->xpm1b_evt_blk.address) { status = acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT.xpm1b_event_block); + &acpi_gbl_FADT->xpm1b_evt_blk); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -251,15 +253,18 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) * * PARAMETERS: register_id - ID of ACPI bit_register to access * return_value - Value that was read from the register + * Flags - Lock the hardware or not * * RETURN: Status and the value read from specified Register. Value * returned is normalized to bit0 (is shifted all the way right) * * DESCRIPTION: ACPI bit_register read function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ -acpi_status acpi_get_register(u32 register_id, u32 * return_value) +acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; @@ -307,13 +312,16 @@ ACPI_EXPORT_SYMBOL(acpi_get_register) * PARAMETERS: register_id - ID of ACPI bit_register to access * Value - (only used on write) value to write to the * Register, NOT pre-normalized to the bit pos + * Flags - Lock the hardware or not * * RETURN: Status * * DESCRIPTION: ACPI Bit Register write function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ -acpi_status acpi_set_register(u32 register_id, u32 value) +acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; @@ -414,9 +422,8 @@ acpi_status acpi_set_register(u32 register_id, u32 value) ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); + ACPI_FORMAT_UINT64(acpi_gbl_FADT-> + xpm2_cnt_blk.address))); ACPI_REGISTER_INSERT_VALUE(register_value, bit_reg_info->bit_position, @@ -426,9 +433,8 @@ acpi_status acpi_set_register(u32 register_id, u32 value) ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); + ACPI_FORMAT_UINT64(acpi_gbl_FADT-> + xpm2_cnt_blk.address))); status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM2_CONTROL, @@ -489,7 +495,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) status = acpi_hw_low_level_read(16, &value1, - &acpi_gbl_FADT.xpm1a_event_block); + &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -498,7 +504,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) status = acpi_hw_low_level_read(16, &value2, - &acpi_gbl_FADT.xpm1b_event_block); + &acpi_gbl_FADT->xpm1b_evt_blk); value1 |= value2; break; @@ -521,14 +527,14 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) status = acpi_hw_low_level_read(16, &value1, - &acpi_gbl_FADT.xpm1a_control_block); + &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } status = acpi_hw_low_level_read(16, &value2, - &acpi_gbl_FADT.xpm1b_control_block); + &acpi_gbl_FADT->xpm1b_cnt_blk); value1 |= value2; break; @@ -536,20 +542,19 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) status = acpi_hw_low_level_read(8, &value1, - &acpi_gbl_FADT.xpm2_control_block); + &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ status = acpi_hw_low_level_read(32, &value1, - &acpi_gbl_FADT.xpm_timer_block); + &acpi_gbl_FADT->xpm_tmr_blk); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ - status = - acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); + status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8); break; default: @@ -630,7 +635,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1a_event_block); + &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -639,7 +644,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1b_event_block); + &acpi_gbl_FADT->xpm1b_evt_blk); break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ @@ -677,50 +682,49 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1a_control_block); + &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1b_control_block); + &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1a_control_block); + &acpi_gbl_FADT->xpm1a_cnt_blk); break; case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ status = acpi_hw_low_level_write(16, value, - &acpi_gbl_FADT.xpm1b_control_block); + &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ status = acpi_hw_low_level_write(8, value, - &acpi_gbl_FADT.xpm2_control_block); + &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ status = acpi_hw_low_level_write(32, value, - &acpi_gbl_FADT.xpm_timer_block); + &acpi_gbl_FADT->xpm_tmr_blk); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ /* SMI_CMD is currently always in IO space */ - status = - acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); + status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8); break; default: @@ -779,7 +783,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) * Two address spaces supported: Memory or IO. * PCI_Config is not supported here because the GAS struct is insufficient */ - switch (reg->space_id) { + switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: status = acpi_os_read_memory((acpi_physical_address) address, @@ -788,20 +792,22 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) case ACPI_ADR_SPACE_SYSTEM_IO: - status = - acpi_os_read_port((acpi_io_address) address, value, width); + status = acpi_os_read_port((acpi_io_address) address, + value, width); break; default: ACPI_ERROR((AE_INFO, - "Unsupported address space: %X", reg->space_id)); + "Unsupported address space: %X", + reg->address_space_id)); return (AE_BAD_PARAMETER); } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", - *value, width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); + *value, width, + ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(reg->address_space_id))); return (status); } @@ -848,7 +854,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) * Two address spaces supported: Memory or IO. * PCI_Config is not supported here because the GAS struct is insufficient */ - switch (reg->space_id) { + switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: status = acpi_os_write_memory((acpi_physical_address) address, @@ -857,20 +863,22 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_os_write_port((acpi_io_address) address, value, - width); + status = acpi_os_write_port((acpi_io_address) address, + value, width); break; default: ACPI_ERROR((AE_INFO, - "Unsupported address space: %X", reg->space_id)); + "Unsupported address space: %X", + reg->address_space_id)); return (AE_BAD_PARAMETER); } ACPI_DEBUG_PRINT((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", - value, width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); + value, width, + ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(reg->address_space_id))); return (status); } diff --git a/trunk/drivers/acpi/hardware/hwsleep.c b/trunk/drivers/acpi/hardware/hwsleep.c index 57901ca3ade9..8bb43cae60c2 100644 --- a/trunk/drivers/acpi/hardware/hwsleep.c +++ b/trunk/drivers/acpi/hardware/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,6 @@ */ #include -#include #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwsleep") @@ -63,32 +62,17 @@ ACPI_MODULE_NAME("hwsleep") acpi_status acpi_set_firmware_waking_vector(acpi_physical_address physical_address) { - struct acpi_table_facs *facs; - acpi_status status; ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); - /* Get the FACS */ - - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - /* Set the vector */ - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - facs->firmware_waking_vector = (u32) physical_address; + if (acpi_gbl_common_fACS.vector_width == 32) { + *(ACPI_CAST_PTR + (u32, acpi_gbl_common_fACS.firmware_waking_vector)) + = (u32) physical_address; } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ - facs->xfirmware_waking_vector = physical_address; + *acpi_gbl_common_fACS.firmware_waking_vector = physical_address; } return_ACPI_STATUS(AE_OK); @@ -113,8 +97,6 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) acpi_status acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) { - struct acpi_table_facs *facs; - acpi_status status; ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); @@ -122,29 +104,16 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the FACS */ - - status = - acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - (struct acpi_table_header **)&facs); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - /* Get the vector */ - if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { - /* - * ACPI 1.0 FACS or short table or optional X_ field is zero - */ - *physical_address = - (acpi_physical_address) facs->firmware_waking_vector; + if (acpi_gbl_common_fACS.vector_width == 32) { + *physical_address = (acpi_physical_address) + * + (ACPI_CAST_PTR + (u32, acpi_gbl_common_fACS.firmware_waking_vector)); } else { - /* - * ACPI 2.0 FACS with valid X_ field - */ *physical_address = - (acpi_physical_address) facs->xfirmware_waking_vector; + *acpi_gbl_common_fACS.firmware_waking_vector; } return_ACPI_STATUS(AE_OK); @@ -277,14 +246,15 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Clear wake status */ - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + status = + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Clear all fixed and general purpose status bits */ - status = acpi_hw_clear_acpi_status(); + status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -397,7 +367,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Wait until we enter sleep state */ do { - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, + ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -430,12 +401,13 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + status = + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_clear_acpi_status(); + status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -457,12 +429,13 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FLUSH_CPU_CACHE(); - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.S4bios_request, 8); + status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, + (u32) acpi_gbl_FADT->S4bios_req, 8); do { acpi_os_stall(1000); - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, + ACPI_MTX_DO_NOT_LOCK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -595,11 +568,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) (void) acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); + [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1, + ACPI_MTX_DO_NOT_LOCK); (void) acpi_set_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); + [ACPI_EVENT_POWER_BUTTON].status_register_id, 1, + ACPI_MTX_DO_NOT_LOCK); arg.integer.value = ACPI_SST_WORKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); diff --git a/trunk/drivers/acpi/hardware/hwtimer.c b/trunk/drivers/acpi/hardware/hwtimer.c index c32eab696acd..c4ec47c939fd 100644 --- a/trunk/drivers/acpi/hardware/hwtimer.c +++ b/trunk/drivers/acpi/hardware/hwtimer.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ acpi_status acpi_get_timer_resolution(u32 * resolution) return_ACPI_STATUS(AE_BAD_PARAMETER); } - if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { *resolution = 24; } else { *resolution = 32; @@ -98,8 +98,7 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = - acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT->xpm_tmr_blk); return_ACPI_STATUS(status); } @@ -154,7 +153,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) if (start_ticks < end_ticks) { delta_ticks = end_ticks - start_ticks; } else if (start_ticks > end_ticks) { - if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { /* 24-bit Timer */ diff --git a/trunk/drivers/acpi/motherboard.c b/trunk/drivers/acpi/motherboard.c new file mode 100644 index 000000000000..2e17ec75af03 --- /dev/null +++ b/trunk/drivers/acpi/motherboard.c @@ -0,0 +1,191 @@ +/* + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * 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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +/* Purpose: Prevent PCMCIA cards from using motherboard resources. */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define _COMPONENT ACPI_SYSTEM_COMPONENT +ACPI_MODULE_NAME("acpi_motherboard") + +/* Dell use PNP0C01 instead of PNP0C02 */ +#define ACPI_MB_HID1 "PNP0C01" +#define ACPI_MB_HID2 "PNP0C02" +/** + * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved + * Doesn't care about the failure of 'request_region', since other may reserve + * the io ports as well + */ +#define IS_RESERVED_ADDR(base, len) \ + (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ + && ((base) + (len) > PCIBIOS_MIN_IO)) +/* + * Clearing the flag (IORESOURCE_BUSY) allows drivers to use + * the io ports if they really know they can use it, while + * still preventing hotplug PCI devices from using it. + */ + +/* + * When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01 + * and PNP0C02, redundant with acpi_reserve_io_ranges(). + * But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP. + */ +static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) +{ + struct resource *requested_res = NULL; + + + if (res->type == ACPI_RESOURCE_TYPE_IO) { + struct acpi_resource_io *io_res = &res->data.io; + + if (io_res->minimum != io_res->maximum) + return AE_OK; + if (IS_RESERVED_ADDR + (io_res->minimum, io_res->address_length)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Motherboard resources 0x%08x - 0x%08x\n", + io_res->minimum, + io_res->minimum + + io_res->address_length)); + requested_res = + request_region(io_res->minimum, + io_res->address_length, "motherboard"); + } + } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) { + struct acpi_resource_fixed_io *fixed_io_res = + &res->data.fixed_io; + + if (IS_RESERVED_ADDR + (fixed_io_res->address, fixed_io_res->address_length)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Motherboard resources 0x%08x - 0x%08x\n", + fixed_io_res->address, + fixed_io_res->address + + fixed_io_res->address_length)); + requested_res = + request_region(fixed_io_res->address, + fixed_io_res->address_length, + "motherboard"); + } + } else { + /* Memory mapped IO? */ + } + + if (requested_res) + requested_res->flags &= ~IORESOURCE_BUSY; + return AE_OK; +} + +static int acpi_motherboard_add(struct acpi_device *device) +{ + if (!device) + return -EINVAL; + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + acpi_reserve_io_ranges, NULL); + + return 0; +} + +static struct acpi_driver acpi_motherboard_driver1 = { + .name = "motherboard", + .class = "", + .ids = ACPI_MB_HID1, + .ops = { + .add = acpi_motherboard_add, + }, +}; + +static struct acpi_driver acpi_motherboard_driver2 = { + .name = "motherboard", + .class = "", + .ids = ACPI_MB_HID2, + .ops = { + .add = acpi_motherboard_add, + }, +}; + +static void __init acpi_request_region (struct acpi_generic_address *addr, + unsigned int length, char *desc) +{ + if (!addr->address || !length) + return; + + if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr->address, length, desc); + else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr->address, length, desc); +} + +static void __init acpi_reserve_resources(void) +{ + acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk, + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK"); + + acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk, + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK"); + + acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk, + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK"); + + acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk, + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK"); + + if (acpi_gbl_FADT->pm_tm_len == 4) + acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR"); + + acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk, + acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK"); + + /* Length of GPE blocks must be a non-negative multiple of 2 */ + + if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe0_blk, + acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK"); + + if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe1_blk, + acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK"); +} + +static int __init acpi_motherboard_init(void) +{ + acpi_bus_register_driver(&acpi_motherboard_driver1); + acpi_bus_register_driver(&acpi_motherboard_driver2); + /* + * Guarantee motherboard IO reservation first + * This module must run after scan.c + */ + if (!acpi_disabled) + acpi_reserve_resources(); + return 0; +} + +/** + * Reserve motherboard resources after PCI claim BARs, + * but before PCI assign resources for uninitialized PCI devices + */ +fs_initcall(acpi_motherboard_init); diff --git a/trunk/drivers/acpi/namespace/nsaccess.c b/trunk/drivers/acpi/namespace/nsaccess.c index 57faf598bad8..c1c6c236df9a 100644 --- a/trunk/drivers/acpi/namespace/nsaccess.c +++ b/trunk/drivers/acpi/namespace/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -195,27 +195,31 @@ acpi_status acpi_ns_root_initialize(void) obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER(val) - 1); - /* Create a mutex */ + if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { - status = - acpi_os_create_mutex(&obj_desc->mutex. - os_mutex); - if (ACPI_FAILURE(status)) { - acpi_ut_remove_reference(obj_desc); - goto unlock_and_exit; - } + /* Create a counting semaphore for the global lock */ - /* Special case for ACPI Global Lock */ + status = + acpi_os_create_semaphore + (ACPI_NO_UNIT_LIMIT, 1, + &acpi_gbl_global_lock_semaphore); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference + (obj_desc); + goto unlock_and_exit; + } - if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { - acpi_gbl_global_lock_mutex = - obj_desc->mutex.os_mutex; + /* Mark this mutex as very special */ - /* Create additional counting semaphore for global lock */ + obj_desc->mutex.os_mutex = + ACPI_GLOBAL_LOCK; + } else { + /* Create a mutex */ status = - acpi_os_create_semaphore(1, 0, - &acpi_gbl_global_lock_semaphore); + acpi_os_create_mutex(&obj_desc-> + mutex. + os_mutex); if (ACPI_FAILURE(status)) { acpi_ut_remove_reference (obj_desc); diff --git a/trunk/drivers/acpi/namespace/nsalloc.c b/trunk/drivers/acpi/namespace/nsalloc.c index 1d693d8ad2d8..55b407aae266 100644 --- a/trunk/drivers/acpi/namespace/nsalloc.c +++ b/trunk/drivers/acpi/namespace/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,9 +61,6 @@ ACPI_MODULE_NAME("nsalloc") struct acpi_namespace_node *acpi_ns_create_node(u32 name) { struct acpi_namespace_node *node; -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - u32 temp; -#endif ACPI_FUNCTION_TRACE(ns_create_node); @@ -74,15 +71,6 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - temp = - acpi_gbl_ns_node_list->total_allocated - - acpi_gbl_ns_node_list->total_freed; - if (temp > acpi_gbl_ns_node_list->max_occupied) { - acpi_gbl_ns_node_list->max_occupied = temp; - } -#endif - node->name.integer = name; ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); return_PTR(node); diff --git a/trunk/drivers/acpi/namespace/nsdump.c b/trunk/drivers/acpi/namespace/nsdump.c index 1fc4f86676e1..d72df66aa965 100644 --- a/trunk/drivers/acpi/namespace/nsdump.c +++ b/trunk/drivers/acpi/namespace/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -205,7 +205,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { this_node->name.integer = - acpi_ut_repair_name(this_node->name.ascii); + acpi_ut_repair_name(this_node->name.integer); ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", this_node->name.integer)); @@ -226,12 +226,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, obj_desc = acpi_ns_get_attached_object(this_node); acpi_dbg_level = dbg_level; - /* Temp nodes are those nodes created by a control method */ - - if (this_node->flags & ANOBJ_TEMPORARY) { - acpi_os_printf("(T) "); - } - switch (info->display_type & ACPI_DISPLAY_MASK) { case ACPI_DISPLAY_SUMMARY: @@ -629,8 +623,7 @@ acpi_ns_dump_objects(acpi_object_type type, info.display_type = display_type; (void)acpi_ns_walk_namespace(type, start_handle, max_depth, - ACPI_NS_WALK_NO_UNLOCK | - ACPI_NS_WALK_TEMP_NODES, + ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object, (void *)&info, NULL); } diff --git a/trunk/drivers/acpi/namespace/nsdumpdv.c b/trunk/drivers/acpi/namespace/nsdumpdv.c index 5097e167939e..c6bf5d30fca3 100644 --- a/trunk/drivers/acpi/namespace/nsdumpdv.c +++ b/trunk/drivers/acpi/namespace/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/namespace/nseval.c b/trunk/drivers/acpi/namespace/nseval.c index aa6370c67ec1..4b0a4a8c9843 100644 --- a/trunk/drivers/acpi/namespace/nseval.c +++ b/trunk/drivers/acpi/namespace/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); } else { @@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Function has a strange interface */ diff --git a/trunk/drivers/acpi/namespace/nsinit.c b/trunk/drivers/acpi/namespace/nsinit.c index 326af8fc0ce7..aec8488c0019 100644 --- a/trunk/drivers/acpi/namespace/nsinit.c +++ b/trunk/drivers/acpi/namespace/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -213,7 +213,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; - acpi_status status = AE_OK; + acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = @@ -267,7 +267,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, /* * Must lock the interpreter before executing AML code */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } /* * Each of these types can contain executable AML code within the diff --git a/trunk/drivers/acpi/namespace/nsload.c b/trunk/drivers/acpi/namespace/nsload.c index d4f9654fd20f..fe75d888e183 100644 --- a/trunk/drivers/acpi/namespace/nsload.c +++ b/trunk/drivers/acpi/namespace/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,12 +44,13 @@ #include #include #include -#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsload") /* Local prototypes */ +static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type); + #ifdef ACPI_FUTURE_IMPLEMENTATION acpi_status acpi_ns_unload_namespace(acpi_handle handle); @@ -61,7 +62,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); * * FUNCTION: acpi_ns_load_table * - * PARAMETERS: table_index - Index for table to be loaded + * PARAMETERS: table_desc - Descriptor for table to be loaded * Node - Owning NS node * * RETURN: Status @@ -71,13 +72,42 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); ******************************************************************************/ acpi_status -acpi_ns_load_table(acpi_native_uint table_index, +acpi_ns_load_table(struct acpi_table_desc *table_desc, struct acpi_namespace_node *node) { acpi_status status; ACPI_FUNCTION_TRACE(ns_load_table); + /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ + + if (! + (acpi_gbl_table_data[table_desc->type]. + flags & ACPI_TABLE_EXECUTABLE)) { + + /* Just ignore this table */ + + return_ACPI_STATUS(AE_OK); + } + + /* Check validity of the AML start and length */ + + if (!table_desc->aml_start) { + ACPI_ERROR((AE_INFO, "Null AML pointer")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AML block at %p\n", + table_desc->aml_start)); + + /* Ignore table if there is no AML contained within */ + + if (!table_desc->aml_length) { + ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]", + table_desc->pointer->signature)); + return_ACPI_STATUS(AE_OK); + } + /* * Parse the table and load the namespace with all named * objects found within. Control methods are NOT parsed @@ -87,34 +117,15 @@ acpi_ns_load_table(acpi_native_uint table_index, * to another control method, we can't continue parsing * because we don't know how many arguments to parse next! */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* If table already loaded into namespace, just return */ - - if (acpi_tb_is_table_loaded(table_index)) { - status = AE_ALREADY_EXISTS; - goto unlock; - } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Loading table into namespace ****\n")); - status = acpi_tb_allocate_owner_id(table_index); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - goto unlock; - } - - status = acpi_ns_parse_table(table_index, node->child); - if (ACPI_SUCCESS(status)) { - acpi_tb_set_table_loaded_flag(table_index, TRUE); - } else { - acpi_tb_release_owner_id(table_index); + return_ACPI_STATUS(status); } - unlock: + status = acpi_ns_parse_table(table_desc, node->child); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -130,7 +141,7 @@ acpi_ns_load_table(acpi_native_uint table_index, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Begin Table Method Parsing and Object Initialization ****\n")); - status = acpi_ds_initialize_objects(table_index, node); + status = acpi_ds_initialize_objects(table_desc, node); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Completed Table Method Parsing and Object Initialization ****\n")); @@ -138,7 +149,99 @@ acpi_ns_load_table(acpi_native_uint table_index, return_ACPI_STATUS(status); } -#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_ns_load_table_by_type + * + * PARAMETERS: table_type - Id of the table type to load + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables + * of the given type are loaded. The mechanism allows this + * routine to be called repeatedly. + * + ******************************************************************************/ + +static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type) +{ + u32 i; + acpi_status status; + struct acpi_table_desc *table_desc; + + ACPI_FUNCTION_TRACE(ns_load_table_by_type); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Table types supported are: + * DSDT (one), SSDT/PSDT (multiple) + */ + switch (table_type) { + case ACPI_TABLE_ID_DSDT: + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n")); + + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next; + + /* If table already loaded into namespace, just return */ + + if (table_desc->loaded_into_namespace) { + goto unlock_and_exit; + } + + /* Now load the single DSDT */ + + status = acpi_ns_load_table(table_desc, acpi_gbl_root_node); + if (ACPI_SUCCESS(status)) { + table_desc->loaded_into_namespace = TRUE; + } + break; + + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Namespace load: %d SSDT or PSDTs\n", + acpi_gbl_table_lists[table_type].count)); + + /* + * Traverse list of SSDT or PSDT tables + */ + table_desc = acpi_gbl_table_lists[table_type].next; + for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) { + /* + * Only attempt to load table into namespace if it is not + * already loaded! + */ + if (!table_desc->loaded_into_namespace) { + status = + acpi_ns_load_table(table_desc, + acpi_gbl_root_node); + if (ACPI_FAILURE(status)) { + break; + } + + table_desc->loaded_into_namespace = TRUE; + } + + table_desc = table_desc->next; + } + break; + + default: + status = AE_SUPPORT; + break; + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + /******************************************************************************* * * FUNCTION: acpi_load_namespace @@ -185,7 +288,6 @@ acpi_status acpi_ns_load_namespace(void) return_ACPI_STATUS(status); } -#endif #ifdef ACPI_FUTURE_IMPLEMENTATION /******************************************************************************* diff --git a/trunk/drivers/acpi/namespace/nsnames.c b/trunk/drivers/acpi/namespace/nsnames.c index cbd94af08cc5..97b8332c9746 100644 --- a/trunk/drivers/acpi/namespace/nsnames.c +++ b/trunk/drivers/acpi/namespace/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/namespace/nsobject.c b/trunk/drivers/acpi/namespace/nsobject.c index d9d7377bc6e6..aabe8794b908 100644 --- a/trunk/drivers/acpi/namespace/nsobject.c +++ b/trunk/drivers/acpi/namespace/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/namespace/nsparse.c b/trunk/drivers/acpi/namespace/nsparse.c index e696aa847990..155505a4ef69 100644 --- a/trunk/drivers/acpi/namespace/nsparse.c +++ b/trunk/drivers/acpi/namespace/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ #include #include #include -#include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsparse") @@ -63,24 +62,14 @@ ACPI_MODULE_NAME("nsparse") * ******************************************************************************/ acpi_status -acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index) +acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) { union acpi_parse_object *parse_root; acpi_status status; - acpi_native_uint aml_length; - u8 *aml_start; struct acpi_walk_state *walk_state; - struct acpi_table_header *table; - acpi_owner_id owner_id; ACPI_FUNCTION_TRACE(ns_one_complete_parse); - status = acpi_tb_get_owner_id(table_index, &owner_id); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - /* Create and init a Root Node */ parse_root = acpi_ps_create_scope_op(); @@ -90,41 +79,26 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state(table_desc->owner_id, + NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op(parse_root); return_ACPI_STATUS(AE_NO_MEMORY); } - status = acpi_get_table_by_index(table_index, &table); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - acpi_ps_free_op(parse_root); - return_ACPI_STATUS(status); - } - - /* Table must consist of at least a complete header */ - - if (table->length < sizeof(struct acpi_table_header)) { - status = AE_BAD_HEADER; - } else { - aml_start = (u8 *) table + sizeof(struct acpi_table_header); - aml_length = table->length - sizeof(struct acpi_table_header); - status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); - } - + status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, + table_desc->aml_start, + table_desc->aml_length, NULL, + pass_number); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); - acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); } /* Parse the AML */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", - (unsigned)pass_number)); + pass_number)); status = acpi_ps_parse_aml(walk_state); acpi_ps_delete_parse_tree(parse_root); @@ -145,7 +119,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, ******************************************************************************/ acpi_status -acpi_ns_parse_table(acpi_native_uint table_index, +acpi_ns_parse_table(struct acpi_table_desc *table_desc, struct acpi_namespace_node *start_node) { acpi_status status; @@ -160,10 +134,10 @@ acpi_ns_parse_table(acpi_native_uint table_index, * each Parser Op subtree is deleted when it is finished. This saves * a great deal of memory, and allows a small cache of parse objects * to service the entire parse. The second pass of the parse then - * performs another complete parse of the AML. + * performs another complete parse of the AML.. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index); + status = acpi_ns_one_complete_parse(1, table_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -178,7 +152,7 @@ acpi_ns_parse_table(acpi_native_uint table_index, * parse objects are all cached. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index); + status = acpi_ns_one_complete_parse(2, table_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/namespace/nssearch.c b/trunk/drivers/acpi/namespace/nssearch.c index e863be665ce8..500e2bbcfaf7 100644 --- a/trunk/drivers/acpi/namespace/nssearch.c +++ b/trunk/drivers/acpi/namespace/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -321,8 +321,7 @@ acpi_ns_search_and_enter(u32 target_name, * even though there are a few bad names. */ if (!acpi_ut_valid_acpi_name(target_name)) { - target_name = - acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); + target_name = acpi_ut_repair_name(target_name); /* Report warning only if in strict mode or debug mode */ @@ -402,10 +401,6 @@ acpi_ns_search_and_enter(u32 target_name, } #endif - if (flags & ACPI_NS_TEMPORARY) { - new_node->flags |= ANOBJ_TEMPORARY; - } - /* Install the new object into the parent's list of children */ acpi_ns_install_node(walk_state, node, new_node, type); diff --git a/trunk/drivers/acpi/namespace/nsutils.c b/trunk/drivers/acpi/namespace/nsutils.c index 90fd059615ff..aa4e799d9a8c 100644 --- a/trunk/drivers/acpi/namespace/nsutils.c +++ b/trunk/drivers/acpi/namespace/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -770,6 +770,13 @@ void acpi_ns_terminate(void) } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); + + /* + * 2) Now we can delete the ACPI tables + */ + acpi_tb_delete_all_tables(); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); + return_VOID; } diff --git a/trunk/drivers/acpi/namespace/nswalk.c b/trunk/drivers/acpi/namespace/nswalk.c index 94eb8f332d94..c8f6bef16ed0 100644 --- a/trunk/drivers/acpi/namespace/nswalk.c +++ b/trunk/drivers/acpi/namespace/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,7 +126,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, * PARAMETERS: Type - acpi_object_type to search for * start_node - Handle in namespace where search begins * max_depth - Depth to which search is to reach - * Flags - Whether to unlock the NS before invoking + * unlock_before_callback- Whether to unlock the NS before invoking * the callback routine * user_function - Called when an object of "Type" is found * Context - Passed to user function @@ -153,7 +153,7 @@ acpi_status acpi_ns_walk_namespace(acpi_object_type type, acpi_handle start_node, u32 max_depth, - u32 flags, + u8 unlock_before_callback, acpi_walk_callback user_function, void *context, void **return_value) { @@ -193,34 +193,20 @@ acpi_ns_walk_namespace(acpi_object_type type, acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, child_node); if (child_node) { - - /* Found next child, get the type if we are not searching for ANY */ - - if (type != ACPI_TYPE_ANY) { - child_type = child_node->type; - } - /* - * Ignore all temporary namespace nodes (created during control - * method execution) unless told otherwise. These temporary nodes - * can cause a race condition because they can be deleted during the - * execution of the user function (if the namespace is unlocked before - * invocation of the user function.) Only the debugger namespace dump - * will examine the temporary nodes. + * Found node, Get the type if we are not + * searching for ANY */ - if ((child_node->flags & ANOBJ_TEMPORARY) && - !(flags & ACPI_NS_WALK_TEMP_NODES)) { - status = AE_CTRL_DEPTH; + if (type != ACPI_TYPE_ANY) { + child_type = child_node->type; } - /* Type must match requested type */ - - else if (child_type == type) { + if (child_type == type) { /* - * Found a matching node, invoke the user callback function. - * Unlock the namespace if flag is set. + * Found a matching node, invoke the user + * callback function */ - if (flags & ACPI_NS_WALK_UNLOCK) { + if (unlock_before_callback) { mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); @@ -230,11 +216,10 @@ acpi_ns_walk_namespace(acpi_object_type type, } } - status = - user_function(child_node, level, context, - return_value); + status = user_function(child_node, level, + context, return_value); - if (flags & ACPI_NS_WALK_UNLOCK) { + if (unlock_before_callback) { mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); @@ -266,17 +251,20 @@ acpi_ns_walk_namespace(acpi_object_type type, } /* - * Depth first search: Attempt to go down another level in the - * namespace if we are allowed to. Don't go any further if we have - * reached the caller specified maximum depth or if the user - * function has specified that the maximum depth has been reached. + * Depth first search: + * Attempt to go down another level in the namespace + * if we are allowed to. Don't go any further if we + * have reached the caller specified maximum depth + * or if the user function has specified that the + * maximum depth has been reached. */ if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) { - - /* There is at least one child of this node, visit it */ - + /* + * There is at least one child of this + * node, visit the onde + */ level++; parent_node = child_node; child_node = NULL; @@ -284,8 +272,9 @@ acpi_ns_walk_namespace(acpi_object_type type, } } else { /* - * No more children of this node (acpi_ns_get_next_node failed), go - * back upwards in the namespace tree to the node's parent. + * No more children of this node (acpi_ns_get_next_node + * failed), go back upwards in the namespace tree to + * the node's parent. */ level--; child_node = parent_node; diff --git a/trunk/drivers/acpi/namespace/nsxfeval.c b/trunk/drivers/acpi/namespace/nsxfeval.c index 7ac6ace50059..dca6799ac678 100644 --- a/trunk/drivers/acpi/namespace/nsxfeval.c +++ b/trunk/drivers/acpi/namespace/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -170,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle, struct acpi_buffer *return_buffer) { acpi_status status; + acpi_status status2; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; @@ -328,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle, * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ - acpi_ex_enter_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_SUCCESS(status2)) { - /* Remove one reference on the return object (should delete it) */ + /* Remove one reference on the return object (should delete it) */ - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } } cleanup: diff --git a/trunk/drivers/acpi/namespace/nsxfname.c b/trunk/drivers/acpi/namespace/nsxfname.c index b489781b22a8..978213a6c19f 100644 --- a/trunk/drivers/acpi/namespace/nsxfname.c +++ b/trunk/drivers/acpi/namespace/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,41 +84,38 @@ acpi_get_handle(acpi_handle parent, /* Convert a parent handle to a prefix node */ if (parent) { + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); + } + prefix_node = acpi_ns_map_handle_to_node(parent); if (!prefix_node) { + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } - } - - /* - * Valid cases are: - * 1) Fully qualified pathname - * 2) Parent + Relative pathname - * - * Error for - */ - if (acpi_ns_valid_root_prefix(pathname[0])) { - /* Pathname is fully qualified (starts with '\') */ - - /* Special case for root-only, since we can't search for it */ - - if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { - *ret_handle = - acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); - return (AE_OK); + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return (status); } - } else if (!prefix_node) { + } - /* Relative path with null prefix is disallowed */ + /* Special case for root, since we can't search for it */ - return (AE_BAD_PARAMETER); + if (ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH) == 0) { + *ret_handle = + acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); + return (AE_OK); } - /* Find the Node and convert to a handle */ + /* + * Find the Node and convert to a handle + */ + status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, + &node); - status = - acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); + *ret_handle = NULL; if (ACPI_SUCCESS(status)) { *ret_handle = acpi_ns_convert_entry_to_handle(node); } diff --git a/trunk/drivers/acpi/namespace/nsxfobj.c b/trunk/drivers/acpi/namespace/nsxfobj.c index faa375887201..a18b1c223129 100644 --- a/trunk/drivers/acpi/namespace/nsxfobj.c +++ b/trunk/drivers/acpi/namespace/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/numa.c b/trunk/drivers/acpi/numa.c index 4a9faff4c01d..bd96a7045925 100644 --- a/trunk/drivers/acpi/numa.c +++ b/trunk/drivers/acpi/numa.c @@ -45,7 +45,7 @@ int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; -extern int __init acpi_table_parse_madt_family(char *id, +extern int __init acpi_table_parse_madt_family(enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, @@ -89,7 +89,7 @@ void __cpuinit acpi_unmap_pxm_to_node(int node) node_clear(node, nodes_found_map); } -void __init acpi_table_print_srat_entry(struct acpi_subtable_header * header) +void __init acpi_table_print_srat_entry(acpi_table_entry_header * header) { ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); @@ -99,35 +99,36 @@ void __init acpi_table_print_srat_entry(struct acpi_subtable_header * header) switch (header->type) { - case ACPI_SRAT_TYPE_CPU_AFFINITY: + case ACPI_SRAT_PROCESSOR_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { - struct acpi_srat_cpu_affinity *p = - (struct acpi_srat_cpu_affinity *)header; + struct acpi_table_processor_affinity *p = + (struct acpi_table_processor_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", - p->apic_id, p->local_sapic_eid, - p->proximity_domain_lo, - (p->flags & ACPI_SRAT_CPU_ENABLED)? - "enabled" : "disabled")); + p->apic_id, p->lsapic_eid, + p->proximity_domain, + p->flags. + enabled ? "enabled" : "disabled")); } #endif /* ACPI_DEBUG_OUTPUT */ break; - case ACPI_SRAT_TYPE_MEMORY_AFFINITY: + case ACPI_SRAT_MEMORY_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { - struct acpi_srat_mem_affinity *p = - (struct acpi_srat_mem_affinity *)header; + struct acpi_table_memory_affinity *p = + (struct acpi_table_memory_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Memory (0x%lx length 0x%lx type 0x%x) in proximity domain %d %s%s\n", - (unsigned long)p->base_address, - (unsigned long)p->length, + "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n", + p->base_addr_hi, p->base_addr_lo, + p->length_hi, p->length_lo, p->memory_type, p->proximity_domain, - (p->flags & ACPI_SRAT_MEM_ENABLED)? - "enabled" : "disabled", - (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? - " hot-pluggable" : "")); + p->flags. + enabled ? "enabled" : "disabled", + p->flags. + hot_pluggable ? " hot-pluggable" : + "")); } #endif /* ACPI_DEBUG_OUTPUT */ break; @@ -140,18 +141,18 @@ void __init acpi_table_print_srat_entry(struct acpi_subtable_header * header) } } -static int __init acpi_parse_slit(struct acpi_table_header *table) +static int __init acpi_parse_slit(unsigned long phys_addr, unsigned long size) { struct acpi_table_slit *slit; u32 localities; - if (!table) + if (!phys_addr || !size) return -EINVAL; - slit = (struct acpi_table_slit *)table; + slit = (struct acpi_table_slit *)__va(phys_addr); /* downcast just for %llu vs %lu for i386/ia64 */ - localities = (u32) slit->locality_count; + localities = (u32) slit->localities; acpi_numa_slit_init(slit); @@ -159,12 +160,12 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) } static int __init -acpi_parse_processor_affinity(struct acpi_subtable_header * header, +acpi_parse_processor_affinity(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_srat_cpu_affinity *processor_affinity; + struct acpi_table_processor_affinity *processor_affinity; - processor_affinity = (struct acpi_srat_cpu_affinity *)header; + processor_affinity = (struct acpi_table_processor_affinity *)header; if (!processor_affinity) return -EINVAL; @@ -177,12 +178,12 @@ acpi_parse_processor_affinity(struct acpi_subtable_header * header, } static int __init -acpi_parse_memory_affinity(struct acpi_subtable_header * header, +acpi_parse_memory_affinity(acpi_table_entry_header * header, const unsigned long end) { - struct acpi_srat_mem_affinity *memory_affinity; + struct acpi_table_memory_affinity *memory_affinity; - memory_affinity = (struct acpi_srat_mem_affinity *)header; + memory_affinity = (struct acpi_table_memory_affinity *)header; if (!memory_affinity) return -EINVAL; @@ -194,23 +195,23 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header, return 0; } -static int __init acpi_parse_srat(struct acpi_table_header *table) +static int __init acpi_parse_srat(unsigned long phys_addr, unsigned long size) { struct acpi_table_srat *srat; - if (!table) + if (!phys_addr || !size) return -EINVAL; - srat = (struct acpi_table_srat *)table; + srat = (struct acpi_table_srat *)__va(phys_addr); return 0; } int __init -acpi_table_parse_srat(enum acpi_srat_type id, +acpi_table_parse_srat(enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_SRAT, + return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat), id, handler, max_entries); } @@ -220,17 +221,17 @@ int __init acpi_numa_init(void) int result; /* SRAT: Static Resource Affinity Table */ - result = acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat); + result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat); if (result > 0) { - result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, + result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY, acpi_parse_processor_affinity, NR_CPUS); - result = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific + result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific } /* SLIT: System Locality Information Table */ - result = acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); + result = acpi_table_parse(ACPI_SLIT, acpi_parse_slit); acpi_numa_arch_fixup(); return 0; diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 0f6f3bcbc8eb..57ae1e5cde0a 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -76,54 +75,6 @@ static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -static void __init acpi_request_region (struct acpi_generic_address *addr, - unsigned int length, char *desc) -{ - struct resource *res; - - if (!addr->address || !length) - return; - - if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) - res = request_region(addr->address, length, desc); - else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - res = request_mem_region(addr->address, length, desc); -} - -static int __init acpi_reserve_resources(void) -{ - acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, - "ACPI PM1a_EVT_BLK"); - - acpi_request_region(&acpi_gbl_FADT.xpm1b_event_block, acpi_gbl_FADT.pm1_event_length, - "ACPI PM1b_EVT_BLK"); - - acpi_request_region(&acpi_gbl_FADT.xpm1a_control_block, acpi_gbl_FADT.pm1_control_length, - "ACPI PM1a_CNT_BLK"); - - acpi_request_region(&acpi_gbl_FADT.xpm1b_control_block, acpi_gbl_FADT.pm1_control_length, - "ACPI PM1b_CNT_BLK"); - - if (acpi_gbl_FADT.pm_timer_length == 4) - acpi_request_region(&acpi_gbl_FADT.xpm_timer_block, 4, "ACPI PM_TMR"); - - acpi_request_region(&acpi_gbl_FADT.xpm2_control_block, acpi_gbl_FADT.pm2_control_length, - "ACPI PM2_CNT_BLK"); - - /* Length of GPE blocks must be a non-negative multiple of 2 */ - - if (!(acpi_gbl_FADT.gpe0_block_length & 0x1)) - acpi_request_region(&acpi_gbl_FADT.xgpe0_block, - acpi_gbl_FADT.gpe0_block_length, "ACPI GPE0_BLK"); - - if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) - acpi_request_region(&acpi_gbl_FADT.xgpe1_block, - acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); - - return 0; -} -device_initcall(acpi_reserve_resources); - acpi_status acpi_os_initialize(void) { return AE_OK; @@ -185,43 +136,53 @@ void acpi_os_vprintf(const char *fmt, va_list args) #endif } -acpi_physical_address __init acpi_os_get_root_pointer(void) +acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) { if (efi_enabled) { + addr->pointer_type = ACPI_PHYSICAL_POINTER; if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) - return efi.acpi20; + addr->pointer.physical = efi.acpi20; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) - return efi.acpi; + addr->pointer.physical = efi.acpi; else { printk(KERN_ERR PREFIX "System description tables not found\n"); - return 0; + return AE_NOT_FOUND; } - } else - return acpi_find_rsdp(); + } else { + if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) { + printk(KERN_ERR PREFIX + "System description tables not found\n"); + return AE_NOT_FOUND; + } + } + + return AE_OK; } -void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) +acpi_status +acpi_os_map_memory(acpi_physical_address phys, acpi_size size, + void __iomem ** virt) { if (phys > ULONG_MAX) { printk(KERN_ERR PREFIX "Cannot map memory that high\n"); - return 0; + return AE_BAD_PARAMETER; } - if (acpi_gbl_permanent_mmap) - /* - * ioremap checks to ensure this is in reserved space - */ - return ioremap((unsigned long)phys, size); - else - return __acpi_map_table((unsigned long)phys, size); + /* + * ioremap checks to ensure this is in reserved space + */ + *virt = ioremap((unsigned long)phys, size); + + if (!*virt) + return AE_NO_MEMORY; + + return AE_OK; } EXPORT_SYMBOL_GPL(acpi_os_map_memory); void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) { - if (acpi_gbl_permanent_mmap) { - iounmap(virt); - } + iounmap(virt); } EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); @@ -293,7 +254,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, * FADT. It may not be the same if an interrupt source override exists * for the SCI. */ - gsi = acpi_gbl_FADT.sci_interrupt; + gsi = acpi_fadt.sci_int; if (acpi_gsi_to_irq(gsi, &irq) < 0) { printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", gsi); diff --git a/trunk/drivers/acpi/parser/psargs.c b/trunk/drivers/acpi/parser/psargs.c index c2b9835c890b..bf88e076c3e9 100644 --- a/trunk/drivers/acpi/parser/psargs.c +++ b/trunk/drivers/acpi/parser/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/psloop.c b/trunk/drivers/acpi/parser/psloop.c index 773aee82fbb8..e1541db3753a 100644 --- a/trunk/drivers/acpi/parser/psloop.c +++ b/trunk/drivers/acpi/parser/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,11 +42,12 @@ */ /* - * Parse the AML and build an operation tree as most interpreters, (such as - * Perl) do. Parsing is done by hand rather than with a YACC generated parser - * to tightly constrain stack and dynamic memory usage. Parsing is kept - * flexible and the code fairly compact by parsing based on a list of AML - * opcode templates in aml_op_info[]. + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in aml_op_info[] */ #include @@ -59,761 +60,6 @@ ACPI_MODULE_NAME("psloop") static u32 acpi_gbl_depth = 0; -/* Local prototypes */ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op); - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op); - -static acpi_status -acpi_ps_get_arguments(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object *op); - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status); - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status); - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_aml_opcode - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Extract the next AML opcode from the input stream. - * - ******************************************************************************/ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); - walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Just skip unknown opcodes */ - - ACPI_ERROR((AE_INFO, - "Found unknown opcode %X at AML address %p offset %X, ignoring", - walk_state->opcode, walk_state->parser_state.aml, - walk_state->aml_offset)); - - ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); - - /* Assume one-byte bad opcode */ - - walk_state->parser_state.aml++; - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - - default: - - /* Found opcode info, this is a normal opcode */ - - walk_state->parser_state.aml += - acpi_ps_get_opcode_size(walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_build_named_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Begin of named Op in AML - * unnamed_op - Early Op (not a named Op) - * Op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Parse a named Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); - - unnamed_op->common.value.arg = NULL; - unnamed_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(unnamed_op, arg); - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of arguments - */ - if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST(walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback(walk_state, op); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); - return_ACPI_STATUS(status); - } - - if (!*op) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - status = acpi_ps_next_parse_state(walk_state, *op, status); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PENDING) { - return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); - } - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(*op, unnamed_op->common.value.arg); - acpi_gbl_depth++; - - if ((*op)->common.aml_opcode == AML_REGION_OP) { - /* - * Defer final parsing of an operation_region body, because we don't - * have enough info in the first pass to parse it correctly (i.e., - * there may be method calls within the term_arg elements of the body.) - * - * However, we must continue parsing because the opregion is not a - * standalone package -- we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - (*op)->named.data = aml_op_start; - (*op)->named.length = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * new_op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Get Op from AML - * - ******************************************************************************/ - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op; - union acpi_parse_object *named_op = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); - - status = acpi_ps_get_aml_opcode(walk_state); - if (status == AE_CTRL_PARSE_CONTINUE) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - /* Create Op structure and append to parent's argument list */ - - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (walk_state->op_info->flags & AML_NAMED) { - status = - acpi_ps_build_named_op(walk_state, aml_op_start, op, - &named_op); - acpi_ps_free_op(op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *new_op = named_op; - return_ACPI_STATUS(AE_OK); - } - - /* Not a named opcode, just allocate Op and append to parent */ - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_xXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - acpi_ps_append_arg(acpi_ps_get_parent_scope - (&(walk_state->parser_state)), op); - - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = *new_op = op; - - status = walk_state->descending_callback(walk_state, &op); - status = acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_CTRL_PARSE_PENDING; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_arguments - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * Op - Current Op - * - * RETURN: Status - * - * DESCRIPTION: Get arguments for passed Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_get_arguments(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object *op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); - - switch (op->common.aml_opcode) { - case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ - case AML_WORD_OP: /* AML_WORDDATA_ARG */ - case AML_DWORD_OP: /* AML_DWORDATA_ARG */ - case AML_QWORD_OP: /* AML_QWORDATA_ARG */ - case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ - - /* Fill in constant or string argument directly */ - - acpi_ps_get_next_simple_arg(&(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), - op); - break; - - case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ - - status = - acpi_ps_get_next_namepath(walk_state, - &(walk_state->parser_state), op, - 1); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - walk_state->arg_types = 0; - break; - - default: - /* - * Op is not a constant or string, append each argument to the Op - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) - && !walk_state->arg_count) { - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state. - aml_start); - - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE - (walk_state->arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (arg) { - arg->common.aml_offset = walk_state->aml_offset; - acpi_ps_append_arg(op, arg); - } - - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* Special processing for certain opcodes */ - - /* TBD (remove): Temporary mechanism to disable this code if needed */ - -#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE - - if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && - ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { - /* - * We want to skip If/Else/While constructs during Pass1 because we - * want to actually conditionally execute the code during Pass2. - * - * Except for disassembly, where we always want to walk the - * If/Else/While packages - */ - switch (op->common.aml_opcode) { - case AML_IF_OP: - case AML_ELSE_OP: - case AML_WHILE_OP: - - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Pass1: Skipping an If/Else/While body\n")); - - /* Skip body of if/else/while in pass 1 */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - break; - - default: - break; - } - } -#endif - - switch (op->common.aml_opcode) { - case AML_METHOD_OP: - /* - * Skip parsing of control method because we don't have enough - * info in the first pass to parse it correctly. - * - * Save the length and address of the body - */ - op->named.data = walk_state->parser_state.aml; - op->named.length = (u32) - (walk_state->parser_state.pkg_end - - walk_state->parser_state.aml); - - /* Skip body of method */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - break; - - case AML_BUFFER_OP: - case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: - - if ((op->common.parent) && - (op->common.parent->common.aml_opcode == - AML_NAME_OP) - && (walk_state->pass_number <= - ACPI_IMODE_LOAD_PASS2)) { - /* - * Skip parsing of Buffers and Packages because we don't have - * enough info in the first pass to parse them correctly. - */ - op->named.data = aml_op_start; - op->named.length = (u32) - (walk_state->parser_state.pkg_end - - aml_op_start); - - /* Skip body */ - - walk_state->parser_state.aml = - walk_state->parser_state.pkg_end; - walk_state->arg_count = 0; - } - break; - - case AML_WHILE_OP: - - if (walk_state->control_state) { - walk_state->control_state->control.package_end = - walk_state->parser_state.pkg_end; - } - break; - - default: - - /* No action for all other opcodes */ - break; - } - - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_op - * - * PARAMETERS: walk_state - Current state - * Op - Returned Op - * Status - Parse status before complete Op - * - * RETURN: Status - * - * DESCRIPTION: Complete Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); - - /* - * Finished one argument of the containing scope - */ - walk_state->parser_state.scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - *op = NULL; - - switch (status) { - case AE_OK: - break; - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method */ - - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - - case AE_CTRL_END: - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if (*op) { - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - status = AE_OK; - break; - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if ((*op)->common.aml_opcode != AML_WHILE_OP) { - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - } - - /* Close this iteration of the While loop */ - - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - status = AE_OK; - break; - - case AE_CTRL_TERMINATE: - - /* Clean up */ - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - status2 = acpi_ds_result_stack_pop(walk_state); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - acpi_ut_delete_generic_state - (acpi_ut_pop_generic_state - (&walk_state->control_state)); - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - - return_ACPI_STATUS(AE_OK); - - default: /* All other non-AE_OK status */ - - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - -#if 0 - /* - * TBD: Cleanup parse ops on error - */ - if (*op == NULL) { - acpi_ps_pop_scope(parser_state, op, - &walk_state->arg_types, - &walk_state->arg_count); - } -#endif - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); - } else { - *op = NULL; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_final_op - * - * PARAMETERS: walk_state - Current state - * Op - Current Op - * Status - Current parse status before complete last - * Op - * - * RETURN: Status - * - * DESCRIPTION: Complete last Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", - op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = - walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, - status); - if (status == AE_CTRL_PENDING) { - status = - acpi_ps_complete_op(walk_state, &op, - AE_OK); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - status2 = - acpi_ps_complete_this_op - (walk_state, op); - if (ACPI_FAILURE - (status2)) { - return_ACPI_STATUS - (status2); - } - } - - acpi_ps_pop_scope(& - (walk_state-> - parser_state), - &op, - &walk_state-> - arg_types, - &walk_state-> - arg_count); - - } while (op); - - return_ACPI_STATUS(status); - } - - else if (ACPI_FAILURE(status)) { - - /* First error is most important */ - - (void) - acpi_ps_complete_this_op(walk_state, - op); - return_ACPI_STATUS(status); - } - } - - status2 = acpi_ps_complete_this_op(walk_state, op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), &op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_ps_parse_loop @@ -830,7 +76,10 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; + acpi_status status2; union acpi_parse_object *op = NULL; /* current op */ + union acpi_parse_object *arg = NULL; + union acpi_parse_object *pre_op = NULL; struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; @@ -879,7 +128,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) "Invoked method did not return a value")); } - ACPI_EXCEPTION((AE_INFO, status, "GetPredicate Failed")); return_ACPI_STATUS(status); @@ -905,30 +153,222 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) } #endif - /* Iterative parsing loop, while there is more AML to process: */ + /* Iterative parsing loop, while there is more AML to process: */ + + while ((parser_state->aml < parser_state->aml_end) || (op)) { + aml_op_start = parser_state->aml; + if (!op) { + + /* Get the next opcode from the AML stream */ + + walk_state->aml_offset = + (u32) ACPI_PTR_DIFF(parser_state->aml, + parser_state->aml_start); + walk_state->opcode = acpi_ps_peek_opcode(parser_state); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = + acpi_ps_get_opcode_info(walk_state->opcode); + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Just skip unknown opcodes */ + + ACPI_ERROR((AE_INFO, + "Found unknown opcode %X at AML address %p offset %X, ignoring", + walk_state->opcode, + parser_state->aml, + walk_state->aml_offset)); + + ACPI_DUMP_BUFFER(parser_state->aml, 128); + + /* Assume one-byte bad opcode */ + + parser_state->aml++; + continue; + + default: + + /* Found opcode info, this is a normal opcode */ + + parser_state->aml += + acpi_ps_get_opcode_size(walk_state->opcode); + walk_state->arg_types = + walk_state->op_info->parse_args; + break; + } + + /* Create Op structure and append to parent's argument list */ + + if (walk_state->op_info->flags & AML_NAMED) { + + /* Allocate a new pre_op if necessary */ + + if (!pre_op) { + pre_op = + acpi_ps_alloc_op(walk_state-> + opcode); + if (!pre_op) { + status = AE_NO_MEMORY; + goto close_this_op; + } + } + + pre_op->common.value.arg = NULL; + pre_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE + (walk_state->arg_types) + && + (GET_CURRENT_ARG_TYPE + (walk_state->arg_types) != ARGP_NAME)) { + status = + acpi_ps_get_next_arg(walk_state, + parser_state, + GET_CURRENT_ARG_TYPE + (walk_state-> + arg_types), + &arg); + if (ACPI_FAILURE(status)) { + goto close_this_op; + } + + acpi_ps_append_arg(pre_op, arg); + INCREMENT_ARG_LIST(walk_state-> + arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of + * arguments + */ + if (!GET_CURRENT_ARG_TYPE + (walk_state->arg_types)) { + status = AE_AML_NO_OPERAND; + goto close_this_op; + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST(walk_state->arg_types); - while ((parser_state->aml < parser_state->aml_end) || (op)) { - aml_op_start = parser_state->aml; - if (!op) { - status = - acpi_ps_create_op(walk_state, aml_op_start, &op); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PARSE_CONTINUE) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = + walk_state->descending_callback(walk_state, + &op); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "During name lookup/catalog")); + goto close_this_op; + } + + if (!op) { continue; } - if (status == AE_CTRL_PARSE_PENDING) { + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { status = AE_OK; + goto close_this_op; } - status = - acpi_ps_complete_op(walk_state, &op, - status); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto close_this_op; } - continue; + acpi_ps_append_arg(op, + pre_op->common.value.arg); + acpi_gbl_depth++; + + if (op->common.aml_opcode == AML_REGION_OP) { + /* + * Defer final parsing of an operation_region body, + * because we don't have enough info in the first pass + * to parse it correctly (i.e., there may be method + * calls within the term_arg elements of the body.) + * + * However, we must continue parsing because + * the opregion is not a standalone package -- + * we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + } else { + /* Not a named opcode, just allocate Op and append to parent */ + + walk_state->op_info = + acpi_ps_get_opcode_info(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + status = AE_NO_MEMORY; + goto close_this_op; + } + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_xXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + acpi_ps_append_arg(acpi_ps_get_parent_scope + (parser_state), op); + + if ((walk_state->descending_callback != NULL)) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = op; + + status = + walk_state-> + descending_callback(walk_state, + &op); + status = + acpi_ps_next_parse_state(walk_state, + op, + status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (ACPI_FAILURE(status)) { + goto close_this_op; + } + } } op->common.aml_offset = walk_state->aml_offset; @@ -955,17 +395,172 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) /* Get arguments */ - status = - acpi_ps_get_arguments(walk_state, aml_op_start, op); - if (ACPI_FAILURE(status)) { + switch (op->common.aml_opcode) { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_QWORD_OP: /* AML_QWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* Fill in constant or string argument directly */ + + acpi_ps_get_next_simple_arg(parser_state, + GET_CURRENT_ARG_TYPE + (walk_state-> + arg_types), op); + break; + + case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + status = - acpi_ps_complete_op(walk_state, &op, - status); + acpi_ps_get_next_namepath(walk_state, + parser_state, op, + 1); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto close_this_op; } - continue; + walk_state->arg_types = 0; + break; + + default: + /* + * Op is not a constant or string, append each argument + * to the Op + */ + while (GET_CURRENT_ARG_TYPE + (walk_state->arg_types) + && !walk_state->arg_count) { + walk_state->aml_offset = (u32) + ACPI_PTR_DIFF(parser_state->aml, + parser_state-> + aml_start); + + status = + acpi_ps_get_next_arg(walk_state, + parser_state, + GET_CURRENT_ARG_TYPE + (walk_state-> + arg_types), + &arg); + if (ACPI_FAILURE(status)) { + goto close_this_op; + } + + if (arg) { + arg->common.aml_offset = + walk_state->aml_offset; + acpi_ps_append_arg(op, arg); + } + INCREMENT_ARG_LIST(walk_state-> + arg_types); + } + + /* Special processing for certain opcodes */ + + /* TBD (remove): Temporary mechanism to disable this code if needed */ + +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + + if ((walk_state->pass_number <= + ACPI_IMODE_LOAD_PASS1) + && + ((walk_state-> + parse_flags & ACPI_PARSE_DISASSEMBLE) == + 0)) { + /* + * We want to skip If/Else/While constructs during Pass1 + * because we want to actually conditionally execute the + * code during Pass2. + * + * Except for disassembly, where we always want to + * walk the If/Else/While packages + */ + switch (op->common.aml_opcode) { + case AML_IF_OP: + case AML_ELSE_OP: + case AML_WHILE_OP: + + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Pass1: Skipping an If/Else/While body\n")); + + /* Skip body of if/else/while in pass 1 */ + + parser_state->aml = + parser_state->pkg_end; + walk_state->arg_count = 0; + break; + + default: + break; + } + } +#endif + switch (op->common.aml_opcode) { + case AML_METHOD_OP: + + /* + * Skip parsing of control method + * because we don't have enough info in the first pass + * to parse it correctly. + * + * Save the length and address of the body + */ + op->named.data = parser_state->aml; + op->named.length = + (u32) (parser_state->pkg_end - + parser_state->aml); + + /* Skip body of method */ + + parser_state->aml = + parser_state->pkg_end; + walk_state->arg_count = 0; + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + + if ((op->common.parent) && + (op->common.parent->common. + aml_opcode == AML_NAME_OP) + && (walk_state->pass_number <= + ACPI_IMODE_LOAD_PASS2)) { + /* + * Skip parsing of Buffers and Packages + * because we don't have enough info in the first pass + * to parse them correctly. + */ + op->named.data = aml_op_start; + op->named.length = + (u32) (parser_state-> + pkg_end - + aml_op_start); + + /* Skip body */ + + parser_state->aml = + parser_state->pkg_end; + walk_state->arg_count = 0; + } + break; + + case AML_WHILE_OP: + + if (walk_state->control_state) { + walk_state->control_state-> + control.package_end = + parser_state->pkg_end; + } + break; + + default: + + /* No action for all other opcodes */ + break; + } + break; } } @@ -980,16 +575,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) walk_state->arg_types, walk_state->arg_count); if (ACPI_FAILURE(status)) { - status = - acpi_ps_complete_op(walk_state, &op, - status); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - continue; + goto close_this_op; } - op = NULL; continue; } @@ -1041,16 +628,269 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; + goto close_this_op; } } - status = acpi_ps_complete_op(walk_state, &op, status); - if (ACPI_FAILURE(status)) { + close_this_op: + /* + * Finished one argument of the containing scope + */ + parser_state->scope->parse_scope.arg_count--; + + /* Finished with pre_op */ + + if (pre_op) { + acpi_ps_free_op(pre_op); + pre_op = NULL; + } + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + op = NULL; + + switch (status) { + case AE_OK: + break; + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method. */ + + walk_state->prev_op = op; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + + case AE_CTRL_END: + + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (op) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + + status2 = + acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + op = NULL; + } + status = AE_OK; + break; + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (op->common.aml_opcode != AML_WHILE_OP) { + status2 = + acpi_ds_result_stack_pop + (walk_state); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + } + + /* Close this iteration of the While loop */ + + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common.aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, status); + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + op = NULL; + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op(walk_state, + op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + status2 = + acpi_ds_result_stack_pop + (walk_state); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); + } + + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS(status); + + default: /* All other non-AE_OK status */ + + do { + if (op) { + status2 = + acpi_ps_complete_this_op(walk_state, + op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + /* + * TBD: Cleanup parse ops on error + */ +#if 0 + if (op == NULL) { + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + } +#endif + walk_state->prev_op = op; + walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } + /* This scope complete? */ + + if (acpi_ps_has_completed_scope(parser_state)) { + acpi_ps_pop_scope(parser_state, &op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Popped scope, Op=%p\n", op)); + } else { + op = NULL; + } + } /* while parser_state->Aml */ - status = acpi_ps_complete_final_op(walk_state, op, status); + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", + op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op + (walk_state, op); + if (ACPI_FAILURE + (status2)) { + return_ACPI_STATUS + (status2); + } + } + + acpi_ps_pop_scope(parser_state, + &op, + &walk_state-> + arg_types, + &walk_state-> + arg_count); + + } while (op); + + return_ACPI_STATUS(status); + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + + (void) + acpi_ps_complete_this_op(walk_state, + op); + return_ACPI_STATUS(status); + } + } + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/parser/psopcode.c b/trunk/drivers/acpi/parser/psopcode.c index 16d8b6cc3c22..4bd25e32769f 100644 --- a/trunk/drivers/acpi/parser/psopcode.c +++ b/trunk/drivers/acpi/parser/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/psparse.c b/trunk/drivers/acpi/parser/psparse.c index 5d63f48e56b5..a02aa62fe1e5 100644 --- a/trunk/drivers/acpi/parser/psparse.c +++ b/trunk/drivers/acpi/parser/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -540,11 +540,6 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) if ((status == AE_ALREADY_EXISTS) && (!walk_state->method_desc->method.mutex)) { - ACPI_INFO((AE_INFO, - "Marking method %4.4s as Serialized", - walk_state->method_node->name. - ascii)); - /* * Method tried to create an object twice. The probable cause is * that the method cannot handle reentrancy. diff --git a/trunk/drivers/acpi/parser/psscope.c b/trunk/drivers/acpi/parser/psscope.c index 77cfa4ed0cfe..a3e0314de24d 100644 --- a/trunk/drivers/acpi/parser/psscope.c +++ b/trunk/drivers/acpi/parser/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/pstree.c b/trunk/drivers/acpi/parser/pstree.c index 966e7ea2a0c4..0015717ef096 100644 --- a/trunk/drivers/acpi/parser/pstree.c +++ b/trunk/drivers/acpi/parser/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/psutils.c b/trunk/drivers/acpi/parser/psutils.c index 8ca52002db55..d405387b7414 100644 --- a/trunk/drivers/acpi/parser/psutils.c +++ b/trunk/drivers/acpi/parser/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/pswalk.c b/trunk/drivers/acpi/parser/pswalk.c index 49f9757434e4..a84a547a0f1b 100644 --- a/trunk/drivers/acpi/parser/pswalk.c +++ b/trunk/drivers/acpi/parser/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/parser/psxface.c b/trunk/drivers/acpi/parser/psxface.c index 94103bced75e..5d996c1140af 100644 --- a/trunk/drivers/acpi/parser/psxface.c +++ b/trunk/drivers/acpi/parser/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,6 +54,8 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info); static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info); + static void acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); @@ -213,8 +215,6 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) { acpi_status status; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE(ps_execute_method); @@ -234,7 +234,8 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) } /* - * The caller "owns" the parameters, so give each one an extra reference + * The caller "owns" the parameters, so give each one an extra + * reference */ acpi_ps_update_parameter_list(info, REF_INCREMENT); @@ -243,50 +244,30 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) acpi_ps_start_trace(info); /* - * Execute the method. Performs parse simultaneously + * 1) Perform the first pass parse of the method to enter any + * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", - info->resolved_node->name.ascii, info->resolved_node, - info->obj_desc)); - - /* Create and init a Root Node */ - - op = acpi_ps_create_scope_op(); - if (!op) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Create and initialize a new walk state */ - - info->pass_number = ACPI_IMODE_EXECUTE; - walk_state = - acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, - NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } + "**** Begin Method Parse **** Entry=%p obj=%p\n", + info->resolved_node, info->obj_desc)); - status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, - info->obj_desc->method.aml_start, - info->obj_desc->method.aml_length, info, - info->pass_number); + info->pass_number = 1; + status = acpi_ps_execute_pass(info); if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); goto cleanup; } - /* Parse the AML */ - - status = acpi_ps_parse_aml(walk_state); + /* + * 2) Execute the method. Performs second pass parse simultaneously + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "**** Begin Method Execution **** Entry=%p obj=%p\n", + info->resolved_node, info->obj_desc)); - /* walk_state was deleted by parse_aml */ + info->pass_number = 3; + status = acpi_ps_execute_pass(info); cleanup: - acpi_ps_delete_parse_tree(op); - /* End optional tracing */ acpi_ps_stop_trace(info); @@ -349,3 +330,62 @@ acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) } } } + +/******************************************************************************* + * + * FUNCTION: acpi_ps_execute_pass + * + * PARAMETERS: Info - See struct acpi_evaluate_info + * (Used: pass_number, Node, and obj_desc) + * + * RETURN: Status + * + * DESCRIPTION: Single AML pass: Parse or Execute a control method + * + ******************************************************************************/ + +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_TRACE(ps_execute_pass); + + /* Create and init a Root Node */ + + op = acpi_ps_create_scope_op(); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Create and initialize a new walk state */ + + walk_state = + acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, + NULL, NULL); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, + info->obj_desc->method.aml_start, + info->obj_desc->method.aml_length, + info->pass_number == 1 ? NULL : info, + info->pass_number); + if (ACPI_FAILURE(status)) { + acpi_ds_delete_walk_state(walk_state); + goto cleanup; + } + + /* Parse the AML */ + + status = acpi_ps_parse_aml(walk_state); + + /* Walk state was deleted by parse_aml */ + + cleanup: + acpi_ps_delete_parse_tree(op); + return_ACPI_STATUS(status); +} diff --git a/trunk/drivers/acpi/pci_link.c b/trunk/drivers/acpi/pci_link.c index 0f683c8c6fbc..481e633bbf41 100644 --- a/trunk/drivers/acpi/pci_link.c +++ b/trunk/drivers/acpi/pci_link.c @@ -513,7 +513,7 @@ int __init acpi_irq_penalty_init(void) } } /* Add a penalty for the SCI */ - acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; + acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING; return 0; } @@ -785,7 +785,7 @@ static int irqrouter_resume(struct sys_device *dev) /* Make sure SCI is enabled again (Apple firmware bug?) */ - acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK); list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index 4ecf701687e8..a860efa2c562 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -117,19 +117,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) EXPORT_SYMBOL(acpi_pci_unregister_driver); -acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) -{ - struct acpi_pci_root *tmp; - - list_for_each_entry(tmp, &acpi_pci_roots, node) { - if ((tmp->id.segment == (u16) seg) && (tmp->id.bus == (u16) bus)) - return tmp->device->handle; - } - return NULL; -} - -EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); - static acpi_status get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) { @@ -165,21 +152,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) return AE_OK; } -static void acpi_pci_bridge_scan(struct acpi_device *device) -{ - int status; - struct acpi_device *child = NULL; - - if (device->flags.bus_address) - if (device->parent && device->parent->ops.bind) { - status = device->parent->ops.bind(device); - if (!status) { - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - } - } -} - static int acpi_pci_root_add(struct acpi_device *device) { int result = 0; @@ -188,7 +160,6 @@ static int acpi_pci_root_add(struct acpi_device *device) acpi_status status = AE_OK; unsigned long value = 0; acpi_handle handle = NULL; - struct acpi_device *child; if (!device) @@ -204,6 +175,9 @@ static int acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); acpi_driver_data(device) = root; + /* + * TBD: Doesn't the bus driver automatically set this? + */ device->ops.bind = acpi_pci_bind; /* @@ -325,12 +299,6 @@ static int acpi_pci_root_add(struct acpi_device *device) result = acpi_pci_irq_add_prt(device->handle, root->id.segment, root->id.bus); - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - end: if (result) { if (!list_empty(&root->node)) diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index 0079bc51082c..5f9496d59ed6 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -375,126 +375,30 @@ static int acpi_processor_remove_fs(struct acpi_device *device) } /* Use the acpiid in MADT to map cpus in case of SMP */ - #ifndef CONFIG_SMP -static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} +#define convert_acpiid_to_cpu(acpi_id) (-1) #else -static struct acpi_table_madt *madt; - -static int map_lapic_id(struct acpi_subtable_header *entry, - u32 acpi_id, int *apic_id) -{ - struct acpi_madt_local_apic *lapic = - (struct acpi_madt_local_apic *)entry; - if ((lapic->lapic_flags & ACPI_MADT_ENABLED) && - lapic->processor_id == acpi_id) { - *apic_id = lapic->id; - return 1; - } - return 0; -} - -static int map_lsapic_id(struct acpi_subtable_header *entry, - u32 acpi_id, int *apic_id) -{ - struct acpi_madt_local_sapic *lsapic = - (struct acpi_madt_local_sapic *)entry; - /* Only check enabled APICs*/ - if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { - /* First check against id */ - if (lsapic->processor_id == acpi_id) { - *apic_id = lsapic->id; - return 1; - /* Check against optional uid */ - } else if (entry->length >= 16 && - lsapic->uid == acpi_id) { - *apic_id = lsapic->uid; - return 1; - } - } - return 0; -} - #ifdef CONFIG_IA64 +#define arch_acpiid_to_apicid ia64_acpiid_to_sapicid #define arch_cpu_to_apicid ia64_cpu_to_sapicid +#define ARCH_BAD_APICID (0xffff) #else +#define arch_acpiid_to_apicid x86_acpiid_to_apicid #define arch_cpu_to_apicid x86_cpu_to_apicid +#define ARCH_BAD_APICID (0xff) #endif -static int map_madt_entry(u32 acpi_id) -{ - unsigned long madt_end, entry; - int apic_id = -1; - - if (!madt) - return apic_id; - - entry = (unsigned long)madt; - madt_end = entry + madt->header.length; - - /* Parse all entries looking for a match. */ - - entry += sizeof(struct acpi_table_madt); - while (entry + sizeof(struct acpi_subtable_header) < madt_end) { - struct acpi_subtable_header *header = - (struct acpi_subtable_header *)entry; - if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { - if (map_lapic_id(header, acpi_id, &apic_id)) - break; - } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - if (map_lsapic_id(header, acpi_id, &apic_id)) - break; - } - entry += header->length; - } - return apic_id; -} - -static int map_mat_entry(acpi_handle handle, u32 acpi_id) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - struct acpi_subtable_header *header; - int apic_id = -1; - - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) - goto exit; - - if (!buffer.length || !buffer.pointer) - goto exit; - - obj = buffer.pointer; - if (obj->type != ACPI_TYPE_BUFFER || - obj->buffer.length < sizeof(struct acpi_subtable_header)) { - goto exit; - } - - header = (struct acpi_subtable_header *)obj->buffer.pointer; - if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { - map_lapic_id(header, acpi_id, &apic_id); - } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - map_lsapic_id(header, acpi_id, &apic_id); - } - -exit: - if (buffer.pointer) - kfree(buffer.pointer); - return apic_id; -} - -static int get_cpu_id(acpi_handle handle, u32 acpi_id) +static int convert_acpiid_to_cpu(u8 acpi_id) { + u16 apic_id; int i; - int apic_id = -1; - apic_id = map_mat_entry(handle, acpi_id); - if (apic_id == -1) - apic_id = map_madt_entry(acpi_id); - if (apic_id == -1) - return apic_id; + apic_id = arch_acpiid_to_apicid[acpi_id]; + if (apic_id == ARCH_BAD_APICID) + return -1; - for (i = 0; i < NR_CPUS; ++i) { + for (i = 0; i < NR_CPUS; i++) { if (arch_cpu_to_apicid[i] == apic_id) return i; } @@ -506,7 +410,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) +static int acpi_processor_get_info(struct acpi_processor *pr) { acpi_status status = 0; union acpi_object object = { 0 }; @@ -527,7 +431,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) * Check to see if we have bus mastering arbitration control. This * is required for proper C3 usage (to maintain cache coherency). */ - if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { + if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) { pr->flags.bm_control = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Bus mastering arbitration control present\n")); @@ -535,35 +439,24 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No bus mastering arbitration control\n")); - /* Check if it is a Device with HID and UID */ - if (has_uid) { - unsigned long value; - status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, - NULL, &value); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); - return -ENODEV; - } - pr->acpi_id = value; - } else { - /* - * Evalute the processor object. Note that it is common on SMP to - * have the first (boot) processor with a valid PBLK address while - * all others have a NULL address. - */ - status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor object\n"); - return -ENODEV; - } - - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c - */ - pr->acpi_id = object.processor.proc_id; + /* + * Evalute the processor object. Note that it is common on SMP to + * have the first (boot) processor with a valid PBLK address while + * all others have a NULL address. + */ + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Evaluating processor object\n"); + return -ENODEV; } - cpu_index = get_cpu_id(pr->handle, pr->acpi_id); + + /* + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c + */ + pr->acpi_id = object.processor.proc_id; + + cpu_index = convert_acpiid_to_cpu(pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && @@ -580,7 +473,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) * less than the max # of CPUs. They should be ignored _iff * they are physically not present. */ - if (pr->id == -1) { + if (cpu_index == -1) { if (ACPI_FAILURE (acpi_processor_hotadd_init(pr->handle, &pr->id))) { return -ENODEV; @@ -597,8 +490,8 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) object.processor.pblk_length); else { pr->throttling.address = object.processor.pblk_address; - pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; - pr->throttling.duty_width = acpi_gbl_FADT.duty_width; + pr->throttling.duty_offset = acpi_fadt.duty_offset; + pr->throttling.duty_width = acpi_fadt.duty_width; pr->pblk = object.processor.pblk_address; @@ -632,7 +525,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) pr = acpi_driver_data(device); - result = acpi_processor_get_info(pr, device->flags.unique_id); + result = acpi_processor_get_info(pr); if (result) { /* Processor is physically not present */ return 0; @@ -814,7 +707,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) return -ENODEV; if ((pr->id >= 0) && (pr->id < NR_CPUS)) { - kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); + kobject_uevent(&(*device)->kobj, KOBJ_ONLINE); } return 0; } @@ -852,13 +745,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) } if (pr->id >= 0 && (pr->id < NR_CPUS)) { - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + kobject_uevent(&device->kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { - kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); + kobject_uevent(&device->kobj, KOBJ_ONLINE); } else { printk(KERN_ERR PREFIX "Device [%s] failed to start\n", acpi_device_bid(device)); @@ -881,7 +774,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) } if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) - kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + kobject_uevent(&device->kobj, KOBJ_OFFLINE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -1002,12 +895,6 @@ static int __init acpi_processor_init(void) memset(&processors, 0, sizeof(processors)); memset(&errata, 0, sizeof(errata)); -#ifdef CONFIG_SMP - if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, - (struct acpi_table_header **)&madt))) - madt = 0; -#endif - acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); if (!acpi_processor_dir) return -ENOMEM; diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 6c6751b1405b..3f30af21574e 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -160,7 +160,7 @@ static inline u32 ticks_elapsed(u32 t1, u32 t2) { if (t2 >= t1) return (t2 - t1); - else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) + else if (!acpi_fadt.tmr_val_ext) return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); else return ((0xFFFFFFFF - t1) + t2); @@ -187,7 +187,8 @@ acpi_processor_power_activate(struct acpi_processor *pr, case ACPI_STATE_C3: /* Disable bus master reload */ if (new->type != ACPI_STATE_C3 && pr->flags.bm_check) - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, + ACPI_MTX_DO_NOT_LOCK); break; } } @@ -197,7 +198,8 @@ acpi_processor_power_activate(struct acpi_processor *pr, case ACPI_STATE_C3: /* Enable bus master reload */ if (old->type != ACPI_STATE_C3 && pr->flags.bm_check) - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, + ACPI_MTX_DO_NOT_LOCK); break; } @@ -234,7 +236,7 @@ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) /* Dummy wait op - must do something useless after P_LVL2 read because chipsets cannot guarantee that STPCLK# signal gets asserted in time to freeze execution properly. */ - unused = inl(acpi_gbl_FADT.xpm_timer_block.address); + unused = inl(acpi_fadt.xpm_tmr_blk.address); } } @@ -289,10 +291,12 @@ static void acpi_processor_idle(void) pr->power.bm_activity <<= diff; - acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); + acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, + &bm_status, ACPI_MTX_DO_NOT_LOCK); if (bm_status) { pr->power.bm_activity |= 0x1; - acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); + acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, + 1, ACPI_MTX_DO_NOT_LOCK); } /* * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect @@ -334,7 +338,7 @@ static void acpi_processor_idle(void) * detection phase, to work cleanly with logical CPU hotplug. */ if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && - !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) + !pr->flags.has_cst && !acpi_fadt.plvl2_up) cx = &pr->power.states[ACPI_STATE_C1]; #endif @@ -380,11 +384,11 @@ static void acpi_processor_idle(void) case ACPI_STATE_C2: /* Get start time (ticks) */ - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C2 */ acpi_cstate_enter(cx); /* Get end time (ticks) */ - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t2 = inl(acpi_fadt.xpm_tmr_blk.address); #ifdef CONFIG_GENERIC_TIME /* TSC halts in C2, so notify users */ @@ -407,7 +411,8 @@ static void acpi_processor_idle(void) * All CPUs are trying to go to C3 * Disable bus master arbitration */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, + ACPI_MTX_DO_NOT_LOCK); } } else { /* SMP with no shared cache... Invalidate cache */ @@ -415,15 +420,16 @@ static void acpi_processor_idle(void) } /* Get start time (ticks) */ - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C3 */ acpi_cstate_enter(cx); /* Get end time (ticks) */ - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t2 = inl(acpi_fadt.xpm_tmr_blk.address); if (pr->flags.bm_check) { /* Enable bus master arbitration */ atomic_dec(&c3_cpu_count); - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, + ACPI_MTX_DO_NOT_LOCK); } #ifdef CONFIG_GENERIC_TIME @@ -451,7 +457,7 @@ static void acpi_processor_idle(void) #ifdef CONFIG_HOTPLUG_CPU /* Don't do promotion/demotion */ if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) && - !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) { + !pr->flags.has_cst && !acpi_fadt.plvl2_up) { next_state = cx; goto end; } @@ -621,8 +627,7 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) * Check for P_LVL2_UP flag before entering C2 and above on * an SMP system. */ - if ((num_online_cpus() > 1) && - !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) + if ((num_online_cpus() > 1) && !acpi_fadt.plvl2_up) return -ENODEV; #endif @@ -631,8 +636,8 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; /* determine latencies from FADT */ - pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; - pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; + pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat; + pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", @@ -878,13 +883,14 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. */ - if (!(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD)) { + if (acpi_fadt.wb_invd != 1) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cache invalidation should work properly" " for C3 to be enabled on SMP systems\n")); return; } - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, + 0, ACPI_MTX_DO_NOT_LOCK); } /* @@ -1090,7 +1096,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n", pr->power.states[i].latency, pr->power.states[i].usage, - (unsigned long long)pr->power.states[i].time); + pr->power.states[i].time); } end: @@ -1158,9 +1164,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, if (!pr) return -EINVAL; - if (acpi_gbl_FADT.cst_control && !nocst) { + if (acpi_fadt.cst_cnt && !nocst) { status = - acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); + acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Notifying BIOS of _CST ability failed")); diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index 058f13cf3b79..cbb6f0814ce2 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -352,24 +352,31 @@ int acpi_processor_notify_smm(struct module *calling_module) is_done = -EIO; - /* Can't write pstate_control to smi_command if either value is zero */ - if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n")); + /* Can't write pstate_cnt to smi_cmd if either value is zero */ + if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_cnt\n")); module_put(calling_module); return 0; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Writing pstate_control [0x%x] to smi_command [0x%x]\n", - acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command)); + "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", + acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.pstate_control, 8); + /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use + * it anyway, so we need to support it... */ + if (acpi_fadt_is_v1) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Using v1.0 FADT reserved value for pstate_cnt\n")); + } + + status = acpi_os_write_port(acpi_fadt.smi_cmd, + (u32) acpi_fadt.pstate_cnt, 8); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Failed to write pstate_control [0x%x] to " - "smi_command [0x%x]", acpi_gbl_FADT.pstate_control, - acpi_gbl_FADT.smi_command)); + "Failed to write pstate_cnt [0x%x] to " + "smi_cmd [0x%x]", acpi_fadt.pstate_cnt, + acpi_fadt.smi_cmd)); module_put(calling_module); return status; } diff --git a/trunk/drivers/acpi/processor_throttling.c b/trunk/drivers/acpi/processor_throttling.c index 89dff3639abe..0ec7dcde0063 100644 --- a/trunk/drivers/acpi/processor_throttling.c +++ b/trunk/drivers/acpi/processor_throttling.c @@ -125,7 +125,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) /* Used to clear all duty_value bits */ duty_mask = pr->throttling.state_count - 1; - duty_mask <<= acpi_gbl_FADT.duty_offset; + duty_mask <<= acpi_fadt.duty_offset; duty_mask = ~duty_mask; } @@ -208,7 +208,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) return 0; } - pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; + pr->throttling.state_count = 1 << acpi_fadt.duty_width; /* * Compute state values. Note that throttling displays a linear power/ diff --git a/trunk/drivers/acpi/resources/rsaddr.c b/trunk/drivers/acpi/resources/rsaddr.c index 271e61509eeb..8fa3213ce000 100644 --- a/trunk/drivers/acpi/resources/rsaddr.c +++ b/trunk/drivers/acpi/resources/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rscalc.c b/trunk/drivers/acpi/resources/rscalc.c index 8c6d3fdec38a..cf87b0230026 100644 --- a/trunk/drivers/acpi/resources/rscalc.c +++ b/trunk/drivers/acpi/resources/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rscreate.c b/trunk/drivers/acpi/resources/rscreate.c index 1358c06a969c..008058acdd39 100644 --- a/trunk/drivers/acpi/resources/rscreate.c +++ b/trunk/drivers/acpi/resources/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsdump.c b/trunk/drivers/acpi/resources/rsdump.c index de20a5d6decf..9c99a723a860 100644 --- a/trunk/drivers/acpi/resources/rsdump.c +++ b/trunk/drivers/acpi/resources/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsinfo.c b/trunk/drivers/acpi/resources/rsinfo.c index 7e3c335ab320..9e7ae2f8a1d3 100644 --- a/trunk/drivers/acpi/resources/rsinfo.c +++ b/trunk/drivers/acpi/resources/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsio.c b/trunk/drivers/acpi/resources/rsio.c index b297bc3e4419..ea567167c4f2 100644 --- a/trunk/drivers/acpi/resources/rsio.c +++ b/trunk/drivers/acpi/resources/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsirq.c b/trunk/drivers/acpi/resources/rsirq.c index 5657f7b95039..1fa63bc2e36f 100644 --- a/trunk/drivers/acpi/resources/rsirq.c +++ b/trunk/drivers/acpi/resources/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rslist.c b/trunk/drivers/acpi/resources/rslist.c index a92755c8877d..29423ce030ca 100644 --- a/trunk/drivers/acpi/resources/rslist.c +++ b/trunk/drivers/acpi/resources/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsmemory.c b/trunk/drivers/acpi/resources/rsmemory.c index 521eab7dd8df..a5131936d690 100644 --- a/trunk/drivers/acpi/resources/rsmemory.c +++ b/trunk/drivers/acpi/resources/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsmisc.c b/trunk/drivers/acpi/resources/rsmisc.c index 3b63b561b94e..faf6e106b785 100644 --- a/trunk/drivers/acpi/resources/rsmisc.c +++ b/trunk/drivers/acpi/resources/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsutils.c b/trunk/drivers/acpi/resources/rsutils.c index 2442a8f8df57..a9cbee8e8b44 100644 --- a/trunk/drivers/acpi/resources/rsutils.c +++ b/trunk/drivers/acpi/resources/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/resources/rsxface.c b/trunk/drivers/acpi/resources/rsxface.c index 991f8901498c..1999e2ab7daa 100644 --- a/trunk/drivers/acpi/resources/rsxface.c +++ b/trunk/drivers/acpi/resources/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index 64f26db10c8e..283d87522c5d 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -21,305 +21,101 @@ extern struct acpi_device *acpi_root; #define ACPI_BUS_DEVICE_NAME "System Bus" static LIST_HEAD(acpi_device_list); -static LIST_HEAD(acpi_bus_id_list); DEFINE_SPINLOCK(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); -struct acpi_device_bus_id{ - char bus_id[15]; - unsigned int instance_no; - struct list_head node; -}; -static int acpi_eject_operation(acpi_handle handle, int lockable) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status = AE_OK; - - /* - * TBD: evaluate _PS3? - */ - - if (lockable) { - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 0; - acpi_evaluate_object(handle, "_LCK", &arg_list, NULL); - } - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - /* - * TBD: _EJD support. - */ - - status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - return (-ENODEV); - } - - return (0); -} -static ssize_t -acpi_eject_store(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) +static void acpi_device_release(struct kobject *kobj) { - int result; - int ret = count; - int islockable; - acpi_status status; - acpi_handle handle; - acpi_object_type type = 0; - struct acpi_device *acpi_device = to_acpi_device(d); - - if ((!count) || (buf[0] != '1')) { - return -EINVAL; - } -#ifndef FORCE_EJECT - if (acpi_device->driver == NULL) { - ret = -ENODEV; - goto err; - } -#endif - status = acpi_get_type(acpi_device->handle, &type); - if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { - ret = -ENODEV; - goto err; - } - - islockable = acpi_device->flags.lockable; - handle = acpi_device->handle; - - result = acpi_bus_trim(acpi_device, 1); - - if (!result) - result = acpi_eject_operation(handle, islockable); - - if (result) { - ret = -EBUSY; - } - err: - return ret; -} - -static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); - -static ssize_t -acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - - return sprintf(buf, "%s\n", acpi_dev->pnp.hardware_id); + struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); + kfree(dev->pnp.cid_list); + kfree(dev); } -static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL); -static ssize_t -acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; - int result; - - result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); - if(result) - goto end; +struct acpi_device_attribute { + struct attribute attr; + ssize_t(*show) (struct acpi_device *, char *); + ssize_t(*store) (struct acpi_device *, const char *, size_t); +}; - result = sprintf(buf, "%s\n", (char*)path.pointer); - kfree(path.pointer); - end: - return result; -} -static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); +typedef void acpi_device_sysfs_files(struct kobject *, + const struct attribute *); -static int acpi_device_setup_files(struct acpi_device *dev) -{ - acpi_status status; - acpi_handle temp; - int result = 0; +static void setup_sys_fs_device_files(struct acpi_device *dev, + acpi_device_sysfs_files * func); - /* - * Devices gotten from FADT don't have a "path" attribute - */ - if(dev->handle) { - result = device_create_file(&dev->dev, &dev_attr_path); - if(result) - goto end; - } +#define create_sysfs_device_files(dev) \ + setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file) +#define remove_sysfs_device_files(dev) \ + setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file) - if(dev->flags.hardware_id) { - result = device_create_file(&dev->dev, &dev_attr_hid); - if(result) - goto end; - } +#define to_acpi_device(n) container_of(n, struct acpi_device, kobj) +#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr); - /* - * If device has _EJ0, 'eject' file is created that is used to trigger - * hot-removal function from userland. - */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - result = device_create_file(&dev->dev, &dev_attr_eject); - end: - return result; -} - -static void acpi_device_remove_files(struct acpi_device *dev) +static ssize_t acpi_device_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) { - acpi_status status; - acpi_handle temp; - - /* - * If device has _EJ0, 'eject' file is created that is used to trigger - * hot-removal function from userland. - */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - device_remove_file(&dev->dev, &dev_attr_eject); - - if(dev->flags.hardware_id) - device_remove_file(&dev->dev, &dev_attr_hid); - if(dev->handle) - device_remove_file(&dev->dev, &dev_attr_path); + struct acpi_device *device = to_acpi_device(kobj); + struct acpi_device_attribute *attribute = to_handle_attr(attr); + return attribute->show ? attribute->show(device, buf) : -EIO; } -/* -------------------------------------------------------------------------- - ACPI Bus operations - -------------------------------------------------------------------------- */ -static void acpi_device_release(struct device *dev) +static ssize_t acpi_device_attr_store(struct kobject *kobj, + struct attribute *attr, const char *buf, + size_t len) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - - kfree(acpi_dev->pnp.cid_list); - kfree(acpi_dev); + struct acpi_device *device = to_acpi_device(kobj); + struct acpi_device_attribute *attribute = to_handle_attr(attr); + return attribute->store ? attribute->store(device, buf, len) : -EIO; } -static int acpi_device_suspend(struct device *dev, pm_message_t state) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; - - if (acpi_drv && acpi_drv->ops.suspend) - return acpi_drv->ops.suspend(acpi_dev, state); - return 0; -} - -static int acpi_device_resume(struct device *dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; +static struct sysfs_ops acpi_device_sysfs_ops = { + .show = acpi_device_attr_show, + .store = acpi_device_attr_store, +}; - if (acpi_drv && acpi_drv->ops.resume) - return acpi_drv->ops.resume(acpi_dev); - return 0; -} +static struct kobj_type ktype_acpi_ns = { + .sysfs_ops = &acpi_device_sysfs_ops, + .release = acpi_device_release, +}; -static int acpi_bus_match(struct device *dev, struct device_driver *drv) +static int namespace_uevent(struct kset *kset, struct kobject *kobj, + char **envp, int num_envp, char *buffer, + int buffer_size) { - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = to_acpi_driver(drv); + struct acpi_device *dev = to_acpi_device(kobj); + int i = 0; + int len = 0; - return !acpi_match_ids(acpi_dev, acpi_drv->ids); -} + if (!dev->driver) + return 0; -static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - int i = 0, length = 0, ret = 0; - - if (acpi_dev->flags.hardware_id) - ret = add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "HWID=%s", acpi_dev->pnp.hardware_id); - if (ret) + if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, + "PHYSDEVDRIVER=%s", dev->driver->name)) return -ENOMEM; - if (acpi_dev->flags.compatible_ids) { - int j; - struct acpi_compatible_id_list *cid_list; - - cid_list = acpi_dev->pnp.cid_list; - - for (j = 0; j < cid_list->count; j++) { - ret = add_uevent_var(envp, num_envp, &i, buffer, - buffer_size, &length, "COMPTID=%s", - cid_list->id[j].value); - if (ret) - return -ENOMEM; - } - } envp[i] = NULL; - return 0; -} -static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_start_single_object(struct acpi_device *); -static int acpi_device_probe(struct device * dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); - int ret; - - ret = acpi_bus_driver_init(acpi_dev, acpi_drv); - if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) - acpi_start_single_object(acpi_dev); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found driver [%s] for device [%s]\n", - acpi_drv->name, acpi_dev->pnp.bus_id)); - get_device(dev); - } - return ret; -} - -static int acpi_device_remove(struct device * dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; - - if (acpi_drv) { - if (acpi_drv->ops.stop) - acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type); - if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); - } - acpi_dev->driver = NULL; - acpi_driver_data(dev) = NULL; - - put_device(dev); return 0; } -static void acpi_device_shutdown(struct device *dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; - - if (acpi_drv && acpi_drv->ops.shutdown) - acpi_drv->ops.shutdown(acpi_dev); - - return ; -} +static struct kset_uevent_ops namespace_uevent_ops = { + .uevent = &namespace_uevent, +}; -static struct bus_type acpi_bus_type = { - .name = "acpi", - .suspend = acpi_device_suspend, - .resume = acpi_device_resume, - .shutdown = acpi_device_shutdown, - .match = acpi_bus_match, - .probe = acpi_device_probe, - .remove = acpi_device_remove, - .uevent = acpi_device_uevent, +static struct kset acpi_namespace_kset = { + .kobj = { + .name = "namespace", + }, + .subsys = &acpi_subsys, + .ktype = &ktype_acpi_ns, + .uevent_ops = &namespace_uevent_ops, }; -static int acpi_device_register(struct acpi_device *device, +static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { - int result; - struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; - int found = 0; + int err; + /* * Linkage * ------- @@ -330,33 +126,7 @@ static int acpi_device_register(struct acpi_device *device, INIT_LIST_HEAD(&device->g_list); INIT_LIST_HEAD(&device->wakeup_list); - new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); - if (!new_bus_id) { - printk(KERN_ERR PREFIX "Memory allocation error\n"); - return -ENOMEM; - } - spin_lock(&acpi_device_lock); - /* - * Find suitable bus_id and instance number in acpi_bus_id_list - * If failed, create one and link it into acpi_bus_id_list - */ - list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) { - if(!strcmp(acpi_device_bus_id->bus_id, device->flags.hardware_id? device->pnp.hardware_id : "device")) { - acpi_device_bus_id->instance_no ++; - found = 1; - kfree(new_bus_id); - break; - } - } - if(!found) { - acpi_device_bus_id = new_bus_id; - strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "device"); - acpi_device_bus_id->instance_no = 0; - list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); - } - sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); - if (device->parent) { list_add_tail(&device->node, &device->parent->children); list_add_tail(&device->g_list, &device->parent->g_list); @@ -366,33 +136,16 @@ static int acpi_device_register(struct acpi_device *device, list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); spin_unlock(&acpi_device_lock); - if (device->parent) - device->dev.parent = &parent->dev; - device->dev.bus = &acpi_bus_type; - device_initialize(&device->dev); - device->dev.release = &acpi_device_release; - result = device_add(&device->dev); - if(result) { - printk("Error adding device %s", device->dev.bus_id); - goto end; - } - - result = acpi_device_setup_files(device); - if(result) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id)); - - device->removal_type = ACPI_BUS_REMOVAL_NORMAL; - return 0; - end: - spin_lock(&acpi_device_lock); - if (device->parent) { - list_del(&device->node); - list_del(&device->g_list); - } else - list_del(&device->g_list); - list_del(&device->wakeup_list); - spin_unlock(&acpi_device_lock); - return result; + strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN); + if (parent) + device->kobj.parent = &parent->kobj; + device->kobj.ktype = &ktype_acpi_ns; + device->kobj.kset = &acpi_namespace_kset; + err = kobject_register(&device->kobj); + if (err < 0) + printk(KERN_WARNING "%s: kobject_register error: %d\n", + __FUNCTION__, err); + create_sysfs_device_files(device); } static void acpi_device_unregister(struct acpi_device *device, int type) @@ -405,143 +158,81 @@ static void acpi_device_unregister(struct acpi_device *device, int type) list_del(&device->g_list); list_del(&device->wakeup_list); + spin_unlock(&acpi_device_lock); acpi_detach_data(device->handle, acpi_bus_data_handler); - - acpi_device_remove_files(device); - device_unregister(&device->dev); -} - -/* -------------------------------------------------------------------------- - Driver Management - -------------------------------------------------------------------------- */ -/** - * acpi_bus_driver_init - add a device to a driver - * @device: the device to add and initialize - * @driver: driver for the device - * - * Used to initialize a device via its device driver. Called whenever a - * driver is bound to a device. Invokes the driver's add() ops. - */ -static int -acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) -{ - int result = 0; - - - if (!device || !driver) - return -EINVAL; - - if (!driver->ops.add) - return -ENOSYS; - - result = driver->ops.add(device); - if (result) { - device->driver = NULL; - acpi_driver_data(device) = NULL; - return result; - } - - device->driver = driver; - - /* - * TBD - Configuration Management: Assign resources to device based - * upon possible configuration and currently allocated resources. - */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Driver successfully bound to device\n")); - return 0; + remove_sysfs_device_files(device); + kobject_unregister(&device->kobj); } -static int acpi_start_single_object(struct acpi_device *device) +void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) { - int result = 0; - struct acpi_driver *driver; - - - if (!(driver = device->driver)) - return 0; - if (driver->ops.start) { - result = driver->ops.start(device); - if (result && driver->ops.remove) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - } + /* TBD */ - return result; + return; } -/** - * acpi_bus_register_driver - register a driver with the ACPI bus - * @driver: driver being registered - * - * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. Returns zero for - * success or a negative error status for failure. - */ -int acpi_bus_register_driver(struct acpi_driver *driver) +static int acpi_bus_get_power_flags(struct acpi_device *device) { - int ret; - - if (acpi_disabled) - return -ENODEV; - driver->drv.name = driver->name; - driver->drv.bus = &acpi_bus_type; - driver->drv.owner = driver->owner; + acpi_status status = 0; + acpi_handle handle = NULL; + u32 i = 0; - ret = driver_register(&driver->drv); - return ret; -} -EXPORT_SYMBOL(acpi_bus_register_driver); + /* + * Power Management Flags + */ + status = acpi_get_handle(device->handle, "_PSC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.explicit_get = 1; + status = acpi_get_handle(device->handle, "_IRC", &handle); + if (ACPI_SUCCESS(status)) + device->power.flags.inrush_current = 1; -/** - * acpi_bus_unregister_driver - unregisters a driver with the APIC bus - * @driver: driver to unregister - * - * Unregisters a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and unbinds. - */ -void acpi_bus_unregister_driver(struct acpi_driver *driver) -{ - driver_unregister(&driver->drv); -} + /* + * Enumerate supported power management states + */ + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { + struct acpi_device_power_state *ps = &device->power.states[i]; + char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; -EXPORT_SYMBOL(acpi_bus_unregister_driver); + /* Evaluate "_PRx" to se if power resources are referenced */ + acpi_evaluate_reference(device->handle, object_name, NULL, + &ps->resources); + if (ps->resources.count) { + device->power.flags.power_resources = 1; + ps->flags.valid = 1; + } -/* -------------------------------------------------------------------------- - Device Enumeration - -------------------------------------------------------------------------- */ -acpi_status -acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) -{ - acpi_status status; - acpi_handle tmp; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; + /* Evaluate "_PSx" to see if we can do explicit sets */ + object_name[2] = 'S'; + status = acpi_get_handle(device->handle, object_name, &handle); + if (ACPI_SUCCESS(status)) { + ps->flags.explicit_set = 1; + ps->flags.valid = 1; + } - status = acpi_get_handle(handle, "_EJD", &tmp); - if (ACPI_FAILURE(status)) - return status; + /* State is valid if we have some power control */ + if (ps->resources.count || ps->flags.explicit_set) + ps->flags.valid = 1; - status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer); - if (ACPI_SUCCESS(status)) { - obj = buffer.pointer; - status = acpi_get_handle(NULL, obj->string.pointer, ejd); - kfree(buffer.pointer); + ps->power = -1; /* Unknown - driver assigned */ + ps->latency = -1; /* Unknown - driver assigned */ } - return status; -} -EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); -void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) -{ + /* Set defaults for D0 and D3 states (always valid) */ + device->power.states[ACPI_STATE_D0].flags.valid = 1; + device->power.states[ACPI_STATE_D0].power = 100; + device->power.states[ACPI_STATE_D3].flags.valid = 1; + device->power.states[ACPI_STATE_D3].power = 0; - /* TBD */ + /* TBD: System wake support and resource requirements. */ - return; + device->power.state = ACPI_STATE_UNKNOWN; + + return 0; } int acpi_match_ids(struct acpi_device *device, char *ids) @@ -563,12 +254,6 @@ int acpi_match_ids(struct acpi_device *device, char *ids) return -ENOENT; } -static int acpi_bus_get_perf_flags(struct acpi_device *device) -{ - device->performance.state = ACPI_STATE_UNKNOWN; - return 0; -} - static acpi_status acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, union acpi_object *package) @@ -647,72 +332,365 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E")) device->wakeup.flags.run_wake = 1; - end: - if (ACPI_FAILURE(status)) - device->flags.wake_capable = 0; + end: + if (ACPI_FAILURE(status)) + device->flags.wake_capable = 0; + return 0; +} + +/* -------------------------------------------------------------------------- + ACPI sysfs device file support + -------------------------------------------------------------------------- */ +static ssize_t acpi_eject_store(struct acpi_device *device, + const char *buf, size_t count); + +#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \ +static struct acpi_device_attribute acpi_device_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); + +/** + * setup_sys_fs_device_files - sets up the device files under device namespace + * @dev: acpi_device object + * @func: function pointer to create or destroy the device file + */ +static void +setup_sys_fs_device_files(struct acpi_device *dev, + acpi_device_sysfs_files * func) +{ + acpi_status status; + acpi_handle temp = NULL; + + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. + */ + status = acpi_get_handle(dev->handle, "_EJ0", &temp); + if (ACPI_SUCCESS(status)) + (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr); +} + +static int acpi_eject_operation(acpi_handle handle, int lockable) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status = AE_OK; + + /* + * TBD: evaluate _PS3? + */ + + if (lockable) { + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 0; + acpi_evaluate_object(handle, "_LCK", &arg_list, NULL); + } + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + /* + * TBD: _EJD support. + */ + + status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); + if (ACPI_FAILURE(status)) { + return (-ENODEV); + } + + return (0); +} + +static ssize_t +acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) +{ + int result; + int ret = count; + int islockable; + acpi_status status; + acpi_handle handle; + acpi_object_type type = 0; + + if ((!count) || (buf[0] != '1')) { + return -EINVAL; + } +#ifndef FORCE_EJECT + if (device->driver == NULL) { + ret = -ENODEV; + goto err; + } +#endif + status = acpi_get_type(device->handle, &type); + if (ACPI_FAILURE(status) || (!device->flags.ejectable)) { + ret = -ENODEV; + goto err; + } + + islockable = device->flags.lockable; + handle = device->handle; + + result = acpi_bus_trim(device, 1); + + if (!result) + result = acpi_eject_operation(handle, islockable); + + if (result) { + ret = -EBUSY; + } + err: + return ret; +} + +/* -------------------------------------------------------------------------- + Performance Management + -------------------------------------------------------------------------- */ + +static int acpi_bus_get_perf_flags(struct acpi_device *device) +{ + device->performance.state = ACPI_STATE_UNKNOWN; + return 0; +} + +/* -------------------------------------------------------------------------- + Driver Management + -------------------------------------------------------------------------- */ + +static LIST_HEAD(acpi_bus_drivers); + +/** + * acpi_bus_match - match device IDs to driver's supported IDs + * @device: the device that we are trying to match to a driver + * @driver: driver whose device id table is being checked + * + * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it + * matches the specified driver's criteria. + */ +static int +acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver) +{ + if (driver && driver->ops.match) + return driver->ops.match(device, driver); + return acpi_match_ids(device, driver->ids); +} + +/** + * acpi_bus_driver_init - add a device to a driver + * @device: the device to add and initialize + * @driver: driver for the device + * + * Used to initialize a device via its device driver. Called whenever a + * driver is bound to a device. Invokes the driver's add() and start() ops. + */ +static int +acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) +{ + int result = 0; + + + if (!device || !driver) + return -EINVAL; + + if (!driver->ops.add) + return -ENOSYS; + + result = driver->ops.add(device); + if (result) { + device->driver = NULL; + acpi_driver_data(device) = NULL; + return result; + } + + device->driver = driver; + + /* + * TBD - Configuration Management: Assign resources to device based + * upon possible configuration and currently allocated resources. + */ + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Driver successfully bound to device\n")); + return 0; +} + +static int acpi_start_single_object(struct acpi_device *device) +{ + int result = 0; + struct acpi_driver *driver; + + + if (!(driver = device->driver)) + return 0; + + if (driver->ops.start) { + result = driver->ops.start(device); + if (result && driver->ops.remove) + driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + } + + return result; +} + +static void acpi_driver_attach(struct acpi_driver *drv) +{ + struct list_head *node, *next; + + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, g_list); + + if (dev->driver || !dev->status.present) + continue; + spin_unlock(&acpi_device_lock); + + if (!acpi_bus_match(dev, drv)) { + if (!acpi_bus_driver_init(dev, drv)) { + acpi_start_single_object(dev); + atomic_inc(&drv->references); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found driver [%s] for device [%s]\n", + drv->name, dev->pnp.bus_id)); + } + } + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); +} + +static void acpi_driver_detach(struct acpi_driver *drv) +{ + struct list_head *node, *next; + + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_device_list) { + struct acpi_device *dev = + container_of(node, struct acpi_device, g_list); + + if (dev->driver == drv) { + spin_unlock(&acpi_device_lock); + if (drv->ops.remove) + drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL); + spin_lock(&acpi_device_lock); + dev->driver = NULL; + dev->driver_data = NULL; + atomic_dec(&drv->references); + } + } + spin_unlock(&acpi_device_lock); +} + +/** + * acpi_bus_register_driver - register a driver with the ACPI bus + * @driver: driver being registered + * + * Registers a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and binds. Returns zero for + * success or a negative error status for failure. + */ +int acpi_bus_register_driver(struct acpi_driver *driver) +{ + + if (acpi_disabled) + return -ENODEV; + + spin_lock(&acpi_device_lock); + list_add_tail(&driver->node, &acpi_bus_drivers); + spin_unlock(&acpi_device_lock); + acpi_driver_attach(driver); + return 0; } -static int acpi_bus_get_power_flags(struct acpi_device *device) +EXPORT_SYMBOL(acpi_bus_register_driver); + +/** + * acpi_bus_unregister_driver - unregisters a driver with the APIC bus + * @driver: driver to unregister + * + * Unregisters a driver with the ACPI bus. Searches the namespace for all + * devices that match the driver's criteria and unbinds. + */ +void acpi_bus_unregister_driver(struct acpi_driver *driver) { - acpi_status status = 0; - acpi_handle handle = NULL; - u32 i = 0; + acpi_driver_detach(driver); + if (!atomic_read(&driver->references)) { + spin_lock(&acpi_device_lock); + list_del_init(&driver->node); + spin_unlock(&acpi_device_lock); + } + return; +} - /* - * Power Management Flags - */ - status = acpi_get_handle(device->handle, "_PSC", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.explicit_get = 1; - status = acpi_get_handle(device->handle, "_IRC", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.inrush_current = 1; +EXPORT_SYMBOL(acpi_bus_unregister_driver); - /* - * Enumerate supported power management states - */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { - struct acpi_device_power_state *ps = &device->power.states[i]; - char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; +/** + * acpi_bus_find_driver - check if there is a driver installed for the device + * @device: device that we are trying to find a supporting driver for + * + * Parses the list of registered drivers looking for a driver applicable for + * the specified device. + */ +static int acpi_bus_find_driver(struct acpi_device *device) +{ + int result = 0; + struct list_head *node, *next; - /* Evaluate "_PRx" to se if power resources are referenced */ - acpi_evaluate_reference(device->handle, object_name, NULL, - &ps->resources); - if (ps->resources.count) { - device->power.flags.power_resources = 1; - ps->flags.valid = 1; - } - /* Evaluate "_PSx" to see if we can do explicit sets */ - object_name[2] = 'S'; - status = acpi_get_handle(device->handle, object_name, &handle); - if (ACPI_SUCCESS(status)) { - ps->flags.explicit_set = 1; - ps->flags.valid = 1; + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_bus_drivers) { + struct acpi_driver *driver = + container_of(node, struct acpi_driver, node); + + atomic_inc(&driver->references); + spin_unlock(&acpi_device_lock); + if (!acpi_bus_match(device, driver)) { + result = acpi_bus_driver_init(device, driver); + if (!result) + goto Done; } - - /* State is valid if we have some power control */ - if (ps->resources.count || ps->flags.explicit_set) - ps->flags.valid = 1; - - ps->power = -1; /* Unknown - driver assigned */ - ps->latency = -1; /* Unknown - driver assigned */ + atomic_dec(&driver->references); + spin_lock(&acpi_device_lock); } + spin_unlock(&acpi_device_lock); - /* Set defaults for D0 and D3 states (always valid) */ - device->power.states[ACPI_STATE_D0].flags.valid = 1; - device->power.states[ACPI_STATE_D0].power = 100; - device->power.states[ACPI_STATE_D3].flags.valid = 1; - device->power.states[ACPI_STATE_D3].power = 0; + Done: + return result; +} - /* TBD: System wake support and resource requirements. */ +/* -------------------------------------------------------------------------- + Device Enumeration + -------------------------------------------------------------------------- */ - device->power.state = ACPI_STATE_UNKNOWN; +acpi_status +acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) +{ + acpi_status status; + acpi_handle tmp; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; - return 0; + status = acpi_get_handle(handle, "_EJD", &tmp); + if (ACPI_FAILURE(status)) + return status; + + status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer); + if (ACPI_SUCCESS(status)) { + obj = buffer.pointer; + status = acpi_get_handle(NULL, obj->string.pointer, ejd); + kfree(buffer.pointer); + } + return status; } +EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); + static int acpi_bus_get_flags(struct acpi_device *device) { @@ -804,75 +782,6 @@ static void acpi_device_get_busid(struct acpi_device *device, } } -static int -acpi_video_bus_match(struct acpi_device *device) -{ - acpi_handle h_dummy1; - acpi_handle h_dummy2; - acpi_handle h_dummy3; - - - if (!device) - return -EINVAL; - - /* Since there is no HID, CID for ACPI Video drivers, we have - * to check well known required nodes for each feature we support. - */ - - /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) - return 0; - - /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) - return 0; - - /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) - return 0; - - return -ENODEV; -} - -/* - * acpi_bay_match - see if a device is an ejectable driver bay - * - * If an acpi object is ejectable and has one of the ACPI ATA methods defined, - * then we can safely call it an ejectable drive bay - */ -static int acpi_bay_match(struct acpi_device *device){ - acpi_status status; - acpi_handle handle; - acpi_handle tmp; - acpi_handle phandle; - - handle = device->handle; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return -ENODEV; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 0; - - if (acpi_get_parent(handle, &phandle)) - return -ENODEV; - - if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp)))) - return 0; - - return -ENODEV; -} - static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) @@ -903,16 +812,6 @@ static void acpi_device_set_id(struct acpi_device *device, device->pnp.bus_address = info->address; device->flags.bus_address = 1; } - - if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ - status = acpi_video_bus_match(device); - if(ACPI_SUCCESS(status)) - hid = ACPI_VIDEO_HID; - - status = acpi_bay_match(device); - if (ACPI_SUCCESS(status)) - hid = ACPI_BAY_HID; - } break; case ACPI_BUS_TYPE_POWER: hid = ACPI_POWER_HID; @@ -989,24 +888,86 @@ static int acpi_device_set_context(struct acpi_device *device, int type) return result; } +static void acpi_device_get_debug_info(struct acpi_device *device, + acpi_handle handle, int type) +{ +#ifdef CONFIG_ACPI_DEBUG_OUTPUT + char *type_string = NULL; + char name[80] = { '?', '\0' }; + struct acpi_buffer buffer = { sizeof(name), name }; + + switch (type) { + case ACPI_BUS_TYPE_DEVICE: + type_string = "Device"; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + break; + case ACPI_BUS_TYPE_POWER: + type_string = "Power Resource"; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + break; + case ACPI_BUS_TYPE_PROCESSOR: + type_string = "Processor"; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + break; + case ACPI_BUS_TYPE_SYSTEM: + type_string = "System"; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + break; + case ACPI_BUS_TYPE_THERMAL: + type_string = "Thermal Zone"; + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + break; + case ACPI_BUS_TYPE_POWER_BUTTON: + type_string = "Power Button"; + sprintf(name, "PWRB"); + break; + case ACPI_BUS_TYPE_SLEEP_BUTTON: + type_string = "Sleep Button"; + sprintf(name, "SLPB"); + break; + } + + printk(KERN_DEBUG "Found %s %s [%p]\n", type_string, name, handle); +#endif /*CONFIG_ACPI_DEBUG_OUTPUT */ +} + static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) { + int result = 0; + struct acpi_driver *driver; + + if (!dev) return -EINVAL; - dev->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&dev->dev); + driver = dev->driver; + + if ((driver) && (driver->ops.remove)) { + + if (driver->ops.stop) { + result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT); + if (result) + return result; + } + + result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT); + if (result) { + return result; + } + + atomic_dec(&dev->driver->references); + dev->driver = NULL; + acpi_driver_data(dev) = NULL; + } if (!rmdevice) return 0; - /* - * unbind _ADR-Based Devices when hot removal - */ if (dev->flags.bus_address) { if ((dev->parent) && (dev->parent->ops.unbind)) dev->parent->ops.unbind(dev); } + acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); return 0; @@ -1014,8 +975,7 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) static int acpi_add_single_object(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type, - struct acpi_bus_ops *ops) + struct acpi_device *parent, acpi_handle handle, int type) { int result = 0; struct acpi_device *device = NULL; @@ -1032,8 +992,6 @@ acpi_add_single_object(struct acpi_device **child, device->handle = handle; device->parent = parent; - device->bus_ops = *ops; /* workround for not call .start */ - acpi_device_get_busid(device, handle, type); @@ -1118,16 +1076,33 @@ acpi_add_single_object(struct acpi_device **child, if ((result = acpi_device_set_context(device, type))) goto end; - result = acpi_device_register(device, parent); + acpi_device_get_debug_info(device, handle, type); + + acpi_device_register(device, parent); /* - * Bind _ADR-Based Devices when hot add + * Bind _ADR-Based Devices + * ----------------------- + * If there's a a bus address (_ADR) then we utilize the parent's + * 'bind' function (if exists) to bind the ACPI- and natively- + * enumerated device representations. */ if (device->flags.bus_address) { if (device->parent && device->parent->ops.bind) device->parent->ops.bind(device); } + /* + * Locate & Attach Driver + * ---------------------- + * If there's a hardware id (_HID) or compatible ids (_CID) we check + * to see if there's a driver installed for this kind of device. Note + * that drivers can install before or after a device is enumerated. + * + * TBD: Assumes LDM provides driver hot-plug capability. + */ + acpi_bus_find_driver(device); + end: if (!result) *child = device; @@ -1213,14 +1188,14 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) if (ops->acpi_op_add) status = acpi_add_single_object(&child, parent, - chandle, type, ops); + chandle, type); else status = acpi_bus_get_device(chandle, &child); if (ACPI_FAILURE(status)) continue; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { + if (ops->acpi_op_start) { status = acpi_start_single_object(child); if (ACPI_FAILURE(status)) continue; @@ -1258,13 +1233,13 @@ acpi_bus_add(struct acpi_device **child, int result; struct acpi_bus_ops ops; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - result = acpi_add_single_object(child, parent, handle, type, &ops); - if (!result) + result = acpi_add_single_object(child, parent, handle, type); + if (!result) { + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; result = acpi_bus_scan(*child, &ops); - + } return result; } @@ -1350,35 +1325,127 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops; + if (!root) return -ENODEV; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; - /* * Enumerate all fixed-feature devices. */ - if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { + if (acpi_fadt.pwr_button == 0) { result = acpi_add_single_object(&device, acpi_root, NULL, - ACPI_BUS_TYPE_POWER_BUTTON, - &ops); + ACPI_BUS_TYPE_POWER_BUTTON); + if (!result) + result = acpi_start_single_object(device); } - if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { + if (acpi_fadt.sleep_button == 0) { result = acpi_add_single_object(&device, acpi_root, NULL, - ACPI_BUS_TYPE_SLEEP_BUTTON, - &ops); + ACPI_BUS_TYPE_SLEEP_BUTTON); + if (!result) + result = acpi_start_single_object(device); } return result; } + +static inline struct acpi_device * to_acpi_dev(struct device * dev) +{ + return container_of(dev, struct acpi_device, dev); +} + + +static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.suspend) { + spin_unlock(&acpi_device_lock); + result = dev->driver->ops.suspend(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_suspend(struct device * dev, pm_message_t state) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to suspend each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_suspend(acpi_dev, state); + return 0; +} + + + +static int root_resume(struct acpi_device * acpi_dev) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.resume) { + spin_unlock(&acpi_device_lock); + result = dev->driver->ops.resume(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_resume(struct device * dev) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to resume each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_resume(acpi_dev); + return 0; +} + + +static struct bus_type acpi_bus_type = { + .name = "acpi", + .suspend = acpi_device_suspend, + .resume = acpi_device_resume, +}; + + + static int __init acpi_scan_init(void) { int result; @@ -1388,9 +1455,9 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; + result = kset_register(&acpi_namespace_kset); + if (result < 0) + printk(KERN_ERR PREFIX "kset_register error: %d\n", result); result = bus_register(&acpi_bus_type); if (result) { @@ -1402,16 +1469,32 @@ static int __init acpi_scan_init(void) * Create the root device in the bus's device tree */ result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, - ACPI_BUS_TYPE_SYSTEM, &ops); + ACPI_BUS_TYPE_SYSTEM); if (result) goto Done; + result = acpi_start_single_object(acpi_root); + if (result) + goto Done; + + acpi_root->dev.bus = &acpi_bus_type; + snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); + result = device_register(&acpi_root->dev); + if (result) { + /* We don't want to quit even if we failed to add suspend/resume */ + printk(KERN_ERR PREFIX "Could not register device\n"); + } + /* * Enumerate devices in the ACPI namespace. */ result = acpi_bus_scan_fixed(acpi_root); - if (!result) + if (!result) { + memset(&ops, 0, sizeof(ops)); + ops.acpi_op_add = 1; + ops.acpi_op_start = 1; result = acpi_bus_scan(acpi_root, &ops); + } if (result) acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); diff --git a/trunk/drivers/acpi/sleep/proc.c b/trunk/drivers/acpi/sleep/proc.c index ccc11b33d89c..34962578039d 100644 --- a/trunk/drivers/acpi/sleep/proc.c +++ b/trunk/drivers/acpi/sleep/proc.c @@ -73,7 +73,7 @@ acpi_system_write_sleep(struct file *file, static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) { u32 sec, min, hr; - u32 day, mo, yr, cent = 0; + u32 day, mo, yr; unsigned char rtc_control = 0; unsigned long flags; @@ -87,19 +87,20 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) rtc_control = CMOS_READ(RTC_CONTROL); /* If we ever get an FACP with proper values... */ - if (acpi_gbl_FADT.day_alarm) + if (acpi_gbl_FADT->day_alrm) /* ACPI spec: only low 6 its should be cared */ - day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; + day = CMOS_READ(acpi_gbl_FADT->day_alrm) & 0x3F; else day = CMOS_READ(RTC_DAY_OF_MONTH); - if (acpi_gbl_FADT.month_alarm) - mo = CMOS_READ(acpi_gbl_FADT.month_alarm); + if (acpi_gbl_FADT->mon_alrm) + mo = CMOS_READ(acpi_gbl_FADT->mon_alrm); else mo = CMOS_READ(RTC_MONTH); - if (acpi_gbl_FADT.century) - cent = CMOS_READ(acpi_gbl_FADT.century); - - yr = CMOS_READ(RTC_YEAR); + if (acpi_gbl_FADT->century) + yr = CMOS_READ(acpi_gbl_FADT->century) * 100 + + CMOS_READ(RTC_YEAR); + else + yr = CMOS_READ(RTC_YEAR); spin_unlock_irqrestore(&rtc_lock, flags); @@ -110,11 +111,10 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) BCD_TO_BIN(day); BCD_TO_BIN(mo); BCD_TO_BIN(yr); - BCD_TO_BIN(cent); } /* we're trusting the FADT (see above) */ - if (!acpi_gbl_FADT.century) + if (!acpi_gbl_FADT->century) /* If we're not trusting the FADT, we should at least make it * right for _this_ century... ehm, what is _this_ century? * @@ -134,8 +134,6 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) * */ yr += 2000; - else - yr += cent * 100; seq_printf(seq, "%4.4u-", yr); (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); @@ -319,12 +317,12 @@ acpi_system_write_alarm(struct file *file, * offsets into the CMOS RAM here -- which for some reason are pointing * to the RTC area of memory. */ - if (acpi_gbl_FADT.day_alarm) - CMOS_WRITE(day, acpi_gbl_FADT.day_alarm); - if (acpi_gbl_FADT.month_alarm) - CMOS_WRITE(mo, acpi_gbl_FADT.month_alarm); - if (acpi_gbl_FADT.century) - CMOS_WRITE(yr / 100, acpi_gbl_FADT.century); + if (acpi_gbl_FADT->day_alrm) + CMOS_WRITE(day, acpi_gbl_FADT->day_alrm); + if (acpi_gbl_FADT->mon_alrm) + CMOS_WRITE(mo, acpi_gbl_FADT->mon_alrm); + if (acpi_gbl_FADT->century) + CMOS_WRITE(yr / 100, acpi_gbl_FADT->century); /* enable the rtc alarm interrupt */ rtc_control |= RTC_AIE; CMOS_WRITE(rtc_control, RTC_CONTROL); diff --git a/trunk/drivers/acpi/system.c b/trunk/drivers/acpi/system.c index 7147b0bdab0a..d86dcb3c2366 100644 --- a/trunk/drivers/acpi/system.c +++ b/trunk/drivers/acpi/system.c @@ -32,11 +32,6 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("acpi_system") -#ifdef MODULE_PARAM_PREFIX -#undef MODULE_PARAM_PREFIX -#endif -#define MODULE_PARAM_PREFIX "acpi." - #define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver" #define ACPI_SYSTEM_DEVICE_NAME "System" @@ -44,24 +39,11 @@ ACPI_MODULE_NAME("acpi_system") #define ACPI_SYSTEM_FILE_EVENT "event" #define ACPI_SYSTEM_FILE_DSDT "dsdt" #define ACPI_SYSTEM_FILE_FADT "fadt" - -/* - * Make ACPICA version work as module param - */ -static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { - int result; - - result = sprintf(buffer, "%x", ACPI_CA_VERSION); - - return result; -} - -module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); +extern struct fadt_descriptor acpi_fadt; /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS static int acpi_system_read_info(struct seq_file *seq, void *offset) { @@ -81,7 +63,6 @@ static const struct file_operations acpi_system_info_ops = { .llseek = seq_lseek, .release = single_release, }; -#endif static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, loff_t *); @@ -95,16 +76,17 @@ acpi_system_read_dsdt(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { acpi_status status = AE_OK; - struct acpi_table_header *dsdt = NULL; + struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; ssize_t res; - status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) return -ENODEV; res = simple_read_from_buffer(buffer, count, ppos, - dsdt, dsdt->length); + dsdt.pointer, dsdt.length); + kfree(dsdt.pointer); return res; } @@ -121,16 +103,17 @@ acpi_system_read_fadt(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { acpi_status status = AE_OK; - struct acpi_table_header *fadt = NULL; + struct acpi_buffer fadt = { ACPI_ALLOCATE_BUFFER, NULL }; ssize_t res; - status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &fadt); if (ACPI_FAILURE(status)) return -ENODEV; res = simple_read_from_buffer(buffer, count, ppos, - fadt, fadt->length); + fadt.pointer, fadt.length); + kfree(fadt.pointer); return res; } @@ -145,7 +128,6 @@ static int __init acpi_system_init(void) if (acpi_disabled) return 0; -#ifdef CONFIG_ACPI_PROCFS /* 'info' [R] */ name = ACPI_SYSTEM_FILE_INFO; entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); @@ -154,7 +136,6 @@ static int __init acpi_system_init(void) else { entry->proc_fops = &acpi_system_info_ops; } -#endif /* 'dsdt' [R] */ name = ACPI_SYSTEM_FILE_DSDT; @@ -178,9 +159,7 @@ static int __init acpi_system_init(void) Error: remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); -#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); -#endif error = -EFAULT; goto Done; diff --git a/trunk/drivers/acpi/tables.c b/trunk/drivers/acpi/tables.c index ba4cb200314a..ffa30c9fccbf 100644 --- a/trunk/drivers/acpi/tables.c +++ b/trunk/drivers/acpi/tables.c @@ -38,97 +38,154 @@ #define ACPI_MAX_TABLES 128 +static char *acpi_table_signatures[ACPI_TABLE_COUNT] = { + [ACPI_TABLE_UNKNOWN] = "????", + [ACPI_APIC] = "APIC", + [ACPI_BOOT] = "BOOT", + [ACPI_DBGP] = "DBGP", + [ACPI_DSDT] = "DSDT", + [ACPI_ECDT] = "ECDT", + [ACPI_ETDT] = "ETDT", + [ACPI_FADT] = "FACP", + [ACPI_FACS] = "FACS", + [ACPI_OEMX] = "OEM", + [ACPI_PSDT] = "PSDT", + [ACPI_SBST] = "SBST", + [ACPI_SLIT] = "SLIT", + [ACPI_SPCR] = "SPCR", + [ACPI_SRAT] = "SRAT", + [ACPI_SSDT] = "SSDT", + [ACPI_SPMI] = "SPMI", + [ACPI_HPET] = "HPET", + [ACPI_MCFG] = "MCFG", +}; + static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; -static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; +/* System Description Table (RSDT/XSDT) */ +struct acpi_table_sdt { + unsigned long pa; + enum acpi_table_id id; + unsigned long size; +} __attribute__ ((packed)); + +static unsigned long sdt_pa; /* Physical Address */ +static unsigned long sdt_count; /* Table count */ -void acpi_table_print_madt_entry(struct acpi_subtable_header * header) +static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata; + +void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr) +{ + char *name = NULL; + + if (!header) + return; + + /* Some table signatures aren't good table names */ + + if (!strncmp((char *)&header->signature, + acpi_table_signatures[ACPI_APIC], + sizeof(header->signature))) { + name = "MADT"; + } else if (!strncmp((char *)&header->signature, + acpi_table_signatures[ACPI_FADT], + sizeof(header->signature))) { + name = "FADT"; + } else + name = header->signature; + + printk(KERN_DEBUG PREFIX + "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name, + header->revision, header->oem_id, header->oem_table_id, + header->oem_revision, header->asl_compiler_id, + header->asl_compiler_revision, (void *)phys_addr); +} + +void acpi_table_print_madt_entry(acpi_table_entry_header * header) { if (!header) return; switch (header->type) { - case ACPI_MADT_TYPE_LOCAL_APIC: + case ACPI_MADT_LAPIC: { - struct acpi_madt_local_apic *p = - (struct acpi_madt_local_apic *)header; + struct acpi_table_lapic *p = + (struct acpi_table_lapic *)header; printk(KERN_INFO PREFIX "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", - p->processor_id, p->id, - (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + p->acpi_id, p->id, + p->flags.enabled ? "enabled" : "disabled"); } break; - case ACPI_MADT_TYPE_IO_APIC: + case ACPI_MADT_IOAPIC: { - struct acpi_madt_io_apic *p = - (struct acpi_madt_io_apic *)header; + struct acpi_table_ioapic *p = + (struct acpi_table_ioapic *)header; printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", p->id, p->address, p->global_irq_base); } break; - case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: + case ACPI_MADT_INT_SRC_OVR: { - struct acpi_madt_interrupt_override *p = - (struct acpi_madt_interrupt_override *)header; + struct acpi_table_int_src_ovr *p = + (struct acpi_table_int_src_ovr *)header; printk(KERN_INFO PREFIX "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", - p->bus, p->source_irq, p->global_irq, - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]); - if (p->inti_flags & - ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)) + p->bus, p->bus_irq, p->global_irq, + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger]); + if (p->flags.reserved) printk(KERN_INFO PREFIX "INT_SRC_OVR unexpected reserved flags: 0x%x\n", - p->inti_flags & - ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)); + p->flags.reserved); } break; - case ACPI_MADT_TYPE_NMI_SOURCE: + case ACPI_MADT_NMI_SRC: { - struct acpi_madt_nmi_source *p = - (struct acpi_madt_nmi_source *)header; + struct acpi_table_nmi_src *p = + (struct acpi_table_nmi_src *)header; printk(KERN_INFO PREFIX "NMI_SRC (%s %s global_irq %d)\n", - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], p->global_irq); } break; - case ACPI_MADT_TYPE_LOCAL_APIC_NMI: + case ACPI_MADT_LAPIC_NMI: { - struct acpi_madt_local_apic_nmi *p = - (struct acpi_madt_local_apic_nmi *)header; + struct acpi_table_lapic_nmi *p = + (struct acpi_table_lapic_nmi *)header; printk(KERN_INFO PREFIX "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", - p->processor_id, - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK ], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], + p->acpi_id, + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], p->lint); } break; - case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: + case ACPI_MADT_LAPIC_ADDR_OVR: { - struct acpi_madt_local_apic_override *p = - (struct acpi_madt_local_apic_override *)header; + struct acpi_table_lapic_addr_ovr *p = + (struct acpi_table_lapic_addr_ovr *)header; printk(KERN_INFO PREFIX "LAPIC_ADDR_OVR (address[%p])\n", (void *)(unsigned long)p->address); } break; - case ACPI_MADT_TYPE_IO_SAPIC: + case ACPI_MADT_IOSAPIC: { - struct acpi_madt_io_sapic *p = - (struct acpi_madt_io_sapic *)header; + struct acpi_table_iosapic *p = + (struct acpi_table_iosapic *)header; printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", p->id, (void *)(unsigned long)p->address, @@ -136,26 +193,26 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header) } break; - case ACPI_MADT_TYPE_LOCAL_SAPIC: + case ACPI_MADT_LSAPIC: { - struct acpi_madt_local_sapic *p = - (struct acpi_madt_local_sapic *)header; + struct acpi_table_lsapic *p = + (struct acpi_table_lsapic *)header; printk(KERN_INFO PREFIX "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", - p->processor_id, p->id, p->eid, - (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + p->acpi_id, p->id, p->eid, + p->flags.enabled ? "enabled" : "disabled"); } break; - case ACPI_MADT_TYPE_INTERRUPT_SOURCE: + case ACPI_MADT_PLAT_INT_SRC: { - struct acpi_madt_interrupt_source *p = - (struct acpi_madt_interrupt_source *)header; + struct acpi_table_plat_int_src *p = + (struct acpi_table_plat_int_src *)header; printk(KERN_INFO PREFIX "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", - mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], - mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], - p->type, p->id, p->eid, p->io_sapic_vector, + mps_inti_flags_polarity[p->flags.polarity], + mps_inti_flags_trigger[p->flags.trigger], + p->type, p->id, p->eid, p->iosapic_vector, p->global_irq); } break; @@ -168,76 +225,342 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header) } } +static int +acpi_table_compute_checksum(void *table_pointer, unsigned long length) +{ + u8 *p = table_pointer; + unsigned long remains = length; + unsigned long sum = 0; + + if (!p || !length) + return -EINVAL; + + while (remains--) + sum += *p++; + + return (sum & 0xFF); +} +/* + * acpi_get_table_header_early() + * for acpi_blacklisted(), acpi_table_get_sdt() + */ int __init -acpi_table_parse_madt_family(char *id, +acpi_get_table_header_early(enum acpi_table_id id, + struct acpi_table_header **header) +{ + unsigned int i; + enum acpi_table_id temp_id; + + /* DSDT is different from the rest */ + if (id == ACPI_DSDT) + temp_id = ACPI_FADT; + else + temp_id = id; + + /* Locate the table. */ + + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != temp_id) + continue; + *header = (void *) + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); + if (!*header) { + printk(KERN_WARNING PREFIX "Unable to map %s\n", + acpi_table_signatures[temp_id]); + return -ENODEV; + } + break; + } + + if (!*header) { + printk(KERN_WARNING PREFIX "%s not present\n", + acpi_table_signatures[id]); + return -ENODEV; + } + + /* Map the DSDT header via the pointer in the FADT */ + if (id == ACPI_DSDT) { + struct fadt_descriptor *fadt = + (struct fadt_descriptor *)*header; + + if (fadt->revision == 3 && fadt->Xdsdt) { + *header = (void *)__acpi_map_table(fadt->Xdsdt, + sizeof(struct + acpi_table_header)); + } else if (fadt->V1_dsdt) { + *header = (void *)__acpi_map_table(fadt->V1_dsdt, + sizeof(struct + acpi_table_header)); + } else + *header = NULL; + + if (!*header) { + printk(KERN_WARNING PREFIX "Unable to map DSDT\n"); + return -ENODEV; + } + } + + return 0; +} + +int __init +acpi_table_parse_madt_family(enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries) { - struct acpi_table_header *madt = NULL; - struct acpi_subtable_header *entry; + void *madt = NULL; + acpi_table_entry_header *entry; unsigned int count = 0; unsigned long madt_end; + unsigned int i; if (!handler) return -EINVAL; /* Locate the MADT (if exists). There should only be one. */ - acpi_get_table(id, 0, &madt); + + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != id) + continue; + madt = (void *) + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map %s\n", + acpi_table_signatures[id]); + return -ENODEV; + } + break; + } if (!madt) { - printk(KERN_WARNING PREFIX "%4.4s not present\n", id); + printk(KERN_WARNING PREFIX "%s not present\n", + acpi_table_signatures[id]); return -ENODEV; } - madt_end = (unsigned long)madt + madt->length; + madt_end = (unsigned long)madt + sdt_entry[i].size; /* Parse all entries looking for a match. */ - entry = (struct acpi_subtable_header *) + entry = (acpi_table_entry_header *) ((unsigned long)madt + madt_size); - while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < + while (((unsigned long)entry) + sizeof(acpi_table_entry_header) < madt_end) { if (entry->type == entry_id && (!max_entries || count++ < max_entries)) if (handler(entry, madt_end)) return -EINVAL; - entry = (struct acpi_subtable_header *) + entry = (acpi_table_entry_header *) ((unsigned long)entry + entry->length); } if (max_entries && count > max_entries) { - printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of " - "%i found\n", id, entry_id, count - max_entries, count); + printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of " + "%i found\n", acpi_table_signatures[id], entry_id, + count - max_entries, count); } return count; } int __init -acpi_table_parse_madt(enum acpi_madt_type id, +acpi_table_parse_madt(enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_MADT, + return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt), id, handler, max_entries); } -int __init acpi_table_parse(char *id, acpi_table_handler handler) +int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler) { - struct acpi_table_header *table = NULL; + int count = 0; + unsigned int i = 0; + if (!handler) return -EINVAL; - acpi_get_table(id, 0, &table); - if (table) { - handler(table); - return 1; - } else - return 0; + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != id) + continue; + count++; + if (count == 1) + handler(sdt_entry[i].pa, sdt_entry[i].size); + + else + printk(KERN_WARNING PREFIX + "%d duplicate %s table ignored.\n", count, + acpi_table_signatures[id]); + } + + return count; +} + +static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp) +{ + struct acpi_table_header *header = NULL; + unsigned int i, id = 0; + + if (!rsdp) + return -EINVAL; + + /* First check XSDT (but only on ACPI 2.0-compatible systems) */ + + if ((rsdp->revision >= 2) && + (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) { + + struct acpi_table_xsdt *mapped_xsdt = NULL; + + sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address; + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); + + if (!header) { + printk(KERN_WARNING PREFIX + "Unable to map XSDT header\n"); + return -ENODEV; + } + + /* remap in the entire table before processing */ + mapped_xsdt = (struct acpi_table_xsdt *) + __acpi_map_table(sdt_pa, header->length); + if (!mapped_xsdt) { + printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); + return -ENODEV; + } + header = &mapped_xsdt->header; + + if (strncmp(header->signature, "XSDT", 4)) { + printk(KERN_WARNING PREFIX + "XSDT signature incorrect\n"); + return -ENODEV; + } + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n"); + return -ENODEV; + } + + sdt_count = + (header->length - sizeof(struct acpi_table_header)) >> 3; + if (sdt_count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX + "Truncated %lu XSDT entries\n", + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i]; + } + + /* Then check RSDT */ + + else if (rsdp->rsdt_address) { + + struct acpi_table_rsdt *mapped_rsdt = NULL; + + sdt_pa = rsdp->rsdt_address; + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); + if (!header) { + printk(KERN_WARNING PREFIX + "Unable to map RSDT header\n"); + return -ENODEV; + } + + /* remap in the entire table before processing */ + mapped_rsdt = (struct acpi_table_rsdt *) + __acpi_map_table(sdt_pa, header->length); + if (!mapped_rsdt) { + printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); + return -ENODEV; + } + header = &mapped_rsdt->header; + + if (strncmp(header->signature, "RSDT", 4)) { + printk(KERN_WARNING PREFIX + "RSDT signature incorrect\n"); + return -ENODEV; + } + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n"); + return -ENODEV; + } + + sdt_count = + (header->length - sizeof(struct acpi_table_header)) >> 2; + if (sdt_count > ACPI_MAX_TABLES) { + printk(KERN_WARNING PREFIX + "Truncated %lu RSDT entries\n", + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i]; + } + + else { + printk(KERN_WARNING PREFIX + "No System Description Table (RSDT/XSDT) specified in RSDP\n"); + return -ENODEV; + } + + acpi_table_print(header, sdt_pa); + + for (i = 0; i < sdt_count; i++) { + + /* map in just the header */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_entry[i].pa, + sizeof(struct acpi_table_header)); + if (!header) + continue; + + /* remap in the entire table before processing */ + header = (struct acpi_table_header *) + __acpi_map_table(sdt_entry[i].pa, header->length); + if (!header) + continue; + + acpi_table_print(header, sdt_entry[i].pa); + + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + continue; + } + + sdt_entry[i].size = header->length; + + for (id = 0; id < ACPI_TABLE_COUNT; id++) { + if (!strncmp((char *)&header->signature, + acpi_table_signatures[id], + sizeof(header->signature))) { + sdt_entry[i].id = id; + } + } + } + + /* + * The DSDT is *not* in the RSDT (why not? no idea.) but we want + * to print its info, because this is what people usually blacklist + * against. Unfortunately, we don't know the phys_addr, so just + * print 0. Maybe no one will notice. + */ + if (!acpi_get_table_header_early(ACPI_DSDT, &header)) + acpi_table_print(header, 0); + + return 0; } /* @@ -245,13 +568,54 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) * * find RSDP, find and checksum SDT/XSDT. * checksum all tables, print SDT/XSDT - * + * * result: sdt_entry[] is initialized */ - int __init acpi_table_init(void) { - acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + struct acpi_table_rsdp *rsdp = NULL; + unsigned long rsdp_phys = 0; + int result = 0; + + /* Locate and map the Root System Description Table (RSDP) */ + + rsdp_phys = acpi_find_rsdp(); + if (!rsdp_phys) { + printk(KERN_ERR PREFIX "Unable to locate RSDP\n"); + return -ENODEV; + } + + rsdp = (struct acpi_table_rsdp *)__acpi_map_table(rsdp_phys, + sizeof(struct acpi_table_rsdp)); + if (!rsdp) { + printk(KERN_WARNING PREFIX "Unable to map RSDP\n"); + return -ENODEV; + } + + printk(KERN_DEBUG PREFIX + "RSDP (v%3.3d %6.6s ) @ 0x%p\n", + rsdp->revision, rsdp->oem_id, (void *)rsdp_phys); + + if (rsdp->revision < 2) + result = + acpi_table_compute_checksum(rsdp, + sizeof(struct acpi_table_rsdp)); + else + result = + acpi_table_compute_checksum(rsdp, + ((struct acpi20_table_rsdp *) + rsdp)->length); + + if (result) { + printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); + return -ENODEV; + } + + /* Locate and map the System Description table (RSDT/XSDT) */ + + if (acpi_table_get_sdt(rsdp)) + return -ENODEV; + return 0; } diff --git a/trunk/drivers/acpi/tables/Makefile b/trunk/drivers/acpi/tables/Makefile index 0a7d7afac255..aa4c69594d97 100644 --- a/trunk/drivers/acpi/tables/Makefile +++ b/trunk/drivers/acpi/tables/Makefile @@ -2,6 +2,7 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o +obj-y := tbconvrt.o tbget.o tbrsdt.o tbxface.o \ + tbgetall.o tbinstal.o tbutils.o tbxfroot.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/trunk/drivers/acpi/tables/tbconvrt.c b/trunk/drivers/acpi/tables/tbconvrt.c new file mode 100644 index 000000000000..d697fcb35d52 --- /dev/null +++ b/trunk/drivers/acpi/tables/tbconvrt.c @@ -0,0 +1,622 @@ +/****************************************************************************** + * + * Module Name: tbconvrt - ACPI Table conversion utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbconvrt") + +/* Local prototypes */ +static void +acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, + u8 register_bit_width, + acpi_physical_address address); + +static void +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, + struct fadt_descriptor_rev1 *original_fadt); + +static void +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt); + +u8 acpi_fadt_is_v1; +ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table_count + * + * PARAMETERS: RSDP - Pointer to the RSDP + * RSDT - Pointer to the RSDT/XSDT + * + * RETURN: The number of tables pointed to by the RSDT or XSDT. + * + * DESCRIPTION: Calculate the number of tables. Automatically handles either + * an RSDT or XSDT. + * + ******************************************************************************/ + +u32 +acpi_tb_get_table_count(struct rsdp_descriptor *RSDP, + struct acpi_table_header *RSDT) +{ + u32 pointer_size; + + ACPI_FUNCTION_ENTRY(); + + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + pointer_size = sizeof(u32); + } else { + pointer_size = sizeof(u64); + } + + /* + * Determine the number of tables pointed to by the RSDT/XSDT. + * This is defined by the ACPI Specification to be the number of + * pointers contained within the RSDT/XSDT. The size of the pointers + * is architecture-dependent. + */ + return ((RSDT->length - + sizeof(struct acpi_table_header)) / pointer_size); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_convert_to_xsdt + * + * PARAMETERS: table_info - Info about the RSDT + * + * RETURN: Status + * + * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) + * + ******************************************************************************/ + +acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) +{ + acpi_size table_size; + u32 i; + struct xsdt_descriptor *new_table; + + ACPI_FUNCTION_ENTRY(); + + /* Compute size of the converted XSDT */ + + table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) + + sizeof(struct acpi_table_header); + + /* Allocate an XSDT */ + + new_table = ACPI_ALLOCATE_ZEROED(table_size); + if (!new_table) { + return (AE_NO_MEMORY); + } + + /* Copy the header and set the length */ + + ACPI_MEMCPY(new_table, table_info->pointer, + sizeof(struct acpi_table_header)); + new_table->length = (u32) table_size; + + /* Copy the table pointers */ + + for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], + (ACPI_CAST_PTR + (struct rsdt_descriptor, + table_info->pointer))-> + table_offset_entry[i]); + } else { + new_table->table_offset_entry[i] = + (ACPI_CAST_PTR(struct xsdt_descriptor, + table_info->pointer))-> + table_offset_entry[i]; + } + } + + /* Delete the original table (either mapped or in a buffer) */ + + acpi_tb_delete_single_table(table_info); + + /* Point the table descriptor to the new table */ + + table_info->pointer = + ACPI_CAST_PTR(struct acpi_table_header, new_table); + table_info->length = table_size; + table_info->allocation = ACPI_MEM_ALLOCATED; + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_init_generic_address + * + * PARAMETERS: new_gas_struct - GAS struct to be initialized + * register_bit_width - Width of this register + * Address - Address of the register + * + * RETURN: None + * + * DESCRIPTION: Initialize a GAS structure. + * + ******************************************************************************/ + +static void +acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, + u8 register_bit_width, + acpi_physical_address address) +{ + + ACPI_STORE_ADDRESS(new_gas_struct->address, address); + + new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + new_gas_struct->register_bit_width = register_bit_width; + new_gas_struct->register_bit_offset = 0; + new_gas_struct->access_width = 0; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_convert_fadt1 + * + * PARAMETERS: local_fadt - Pointer to new FADT + * original_fadt - Pointer to old FADT + * + * RETURN: None, populates local_fadt + * + * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format + * + ******************************************************************************/ + +static void +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, + struct fadt_descriptor_rev1 *original_fadt) +{ + + /* ACPI 1.0 FACS */ + /* The BIOS stored FADT should agree with Revision 1.0 */ + acpi_fadt_is_v1 = 1; + + /* + * Copy the table header and the common part of the tables. + * + * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 + * table can be copied first, then expand some fields to 64 bits. + */ + ACPI_MEMCPY(local_fadt, original_fadt, + sizeof(struct fadt_descriptor_rev1)); + + /* Convert table pointers to 64-bit fields */ + + ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, + local_fadt->V1_firmware_ctrl); + ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); + + /* + * System Interrupt Model isn't used in ACPI 2.0 + * (local_fadt->Reserved1 = 0;) + */ + + /* + * This field is set by the OEM to convey the preferred power management + * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't + * know what kind of 32-bit system this is, we will use "unspecified". + */ + local_fadt->prefer_PM_profile = PM_UNSPECIFIED; + + /* + * Processor Performance State Control. This is the value OSPM writes to + * the SMI_CMD register to assume processor performance state control + * responsibility. There isn't any equivalence in 1.0, but as many 1.x + * ACPI tables contain _PCT and _PSS we also keep this value, unless + * acpi_strict is set. + */ + if (acpi_strict) + local_fadt->pstate_cnt = 0; + + /* + * Support for the _CST object and C States change notification. + * This data item hasn't any 1.0 equivalence so leave it zero. + */ + local_fadt->cst_cnt = 0; + + /* + * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. + * It primarily adds the FADT reset mechanism. + */ + if ((original_fadt->revision == 2) && + (original_fadt->length == + sizeof(struct fadt_descriptor_rev2_minus))) { + /* + * Grab the entire generic address struct, plus the 1-byte reset value + * that immediately follows. + */ + ACPI_MEMCPY(&local_fadt->reset_register, + &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus, + original_fadt))->reset_register, + sizeof(struct acpi_generic_address) + 1); + } else { + /* + * Since there isn't any equivalence in 1.0 and since it is highly + * likely that a 1.0 system has legacy support. + */ + local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; + } + + /* + * Convert the V1.0 block addresses to V2.0 GAS structures + */ + acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, + local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt-> + V1_pm1a_evt_blk); + acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, + local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt-> + V1_pm1b_evt_blk); + acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, + local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt-> + V1_pm1a_cnt_blk); + acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, + local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt-> + V1_pm1b_cnt_blk); + acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, + local_fadt->pm2_cnt_len, + (acpi_physical_address) local_fadt-> + V1_pm2_cnt_blk); + acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, + local_fadt->pm_tm_len, + (acpi_physical_address) local_fadt-> + V1_pm_tmr_blk); + acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0, + (acpi_physical_address) local_fadt-> + V1_gpe0_blk); + acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0, + (acpi_physical_address) local_fadt-> + V1_gpe1_blk); + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len), + (acpi_physical_address) + (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); + + /* PM1B is optional; leave null if not present */ + + if (local_fadt->xpm1b_evt_blk.address) { + acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len), + (acpi_physical_address) + (local_fadt->xpm1b_evt_blk. + address + + ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len))); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_convert_fadt2 + * + * PARAMETERS: local_fadt - Pointer to new FADT + * original_fadt - Pointer to old FADT + * + * RETURN: None, populates local_fadt + * + * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. + * Handles optional "X" fields. + * + ******************************************************************************/ + +static void +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt) +{ + + /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ + + ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor)); + + /* + * "X" fields are optional extensions to the original V1.0 fields, so + * we must selectively expand V1.0 fields if the corresponding X field + * is zero. + */ + if (!(local_fadt->xfirmware_ctrl)) { + ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, + local_fadt->V1_firmware_ctrl); + } + + if (!(local_fadt->Xdsdt)) { + ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); + } + + if (!(local_fadt->xpm1a_evt_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, + local_fadt->pm1_evt_len, + (acpi_physical_address) + local_fadt->V1_pm1a_evt_blk); + } + + if (!(local_fadt->xpm1b_evt_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, + local_fadt->pm1_evt_len, + (acpi_physical_address) + local_fadt->V1_pm1b_evt_blk); + } + + if (!(local_fadt->xpm1a_cnt_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, + local_fadt->pm1_cnt_len, + (acpi_physical_address) + local_fadt->V1_pm1a_cnt_blk); + } + + if (!(local_fadt->xpm1b_cnt_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, + local_fadt->pm1_cnt_len, + (acpi_physical_address) + local_fadt->V1_pm1b_cnt_blk); + } + + if (!(local_fadt->xpm2_cnt_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, + local_fadt->pm2_cnt_len, + (acpi_physical_address) + local_fadt->V1_pm2_cnt_blk); + } + + if (!(local_fadt->xpm_tmr_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, + local_fadt->pm_tm_len, + (acpi_physical_address) + local_fadt->V1_pm_tmr_blk); + } + + if (!(local_fadt->xgpe0_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, + 0, + (acpi_physical_address) + local_fadt->V1_gpe0_blk); + } + + if (!(local_fadt->xgpe1_blk.address)) { + acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, + 0, + (acpi_physical_address) + local_fadt->V1_gpe1_blk); + } + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len), + (acpi_physical_address) + (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); + + acpi_gbl_xpm1a_enable.address_space_id = + local_fadt->xpm1a_evt_blk.address_space_id; + + /* PM1B is optional; leave null if not present */ + + if (local_fadt->xpm1b_evt_blk.address) { + acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len), + (acpi_physical_address) + (local_fadt->xpm1b_evt_blk. + address + + ACPI_DIV_2(acpi_gbl_FADT-> + pm1_evt_len))); + + acpi_gbl_xpm1b_enable.address_space_id = + local_fadt->xpm1b_evt_blk.address_space_id; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_convert_table_fadt + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local + * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply + * copied to the local FADT. The ACPI CA software uses this + * local FADT. Thus a significant amount of special #ifdef + * type codeing is saved. + * + ******************************************************************************/ + +acpi_status acpi_tb_convert_table_fadt(void) +{ + struct fadt_descriptor *local_fadt; + struct acpi_table_desc *table_desc; + + ACPI_FUNCTION_TRACE(tb_convert_table_fadt); + + /* + * acpi_gbl_FADT is valid. Validate the FADT length. The table must be + * at least as long as the version 1.0 FADT + */ + if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) { + ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X", + acpi_gbl_FADT->length)); + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* Allocate buffer for the ACPI 2.0(+) FADT */ + + local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor)); + if (!local_fadt) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { + if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) { + + /* Length is too short to be a V2.0 table */ + + ACPI_WARNING((AE_INFO, + "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table", + acpi_gbl_FADT->length, + acpi_gbl_FADT->revision)); + + acpi_tb_convert_fadt1(local_fadt, + (void *)acpi_gbl_FADT); + } else { + /* Valid V2.0 table */ + + acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT); + } + } else { + /* Valid V1.0 table */ + + acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT); + } + + /* Global FADT pointer will point to the new common V2.0 FADT */ + + acpi_gbl_FADT = local_fadt; + acpi_gbl_FADT->length = sizeof(struct fadt_descriptor); + + /* Free the original table */ + + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next; + acpi_tb_delete_single_table(table_desc); + + /* Install the new table */ + + table_desc->pointer = + ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); + table_desc->allocation = ACPI_MEM_ALLOCATED; + table_desc->length = sizeof(struct fadt_descriptor); + + /* Dump the entire FADT */ + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "Hex dump of common internal FADT, size %d (%X)\n", + acpi_gbl_FADT->length, acpi_gbl_FADT->length)); + + ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT), + acpi_gbl_FADT->length); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_build_common_facs + * + * PARAMETERS: table_info - Info for currently installed FACS + * + * RETURN: Status + * + * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal + * table format. + * + ******************************************************************************/ + +acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) +{ + + ACPI_FUNCTION_TRACE(tb_build_common_facs); + + /* Absolute minimum length is 24, but the ACPI spec says 64 */ + + if (acpi_gbl_FACS->length < 24) { + ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X", + acpi_gbl_FACS->length)); + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + if (acpi_gbl_FACS->length < 64) { + ACPI_WARNING((AE_INFO, + "FACS is shorter than the ACPI specification allows: 0x%X, using anyway", + acpi_gbl_FACS->length)); + } + + /* Copy fields to the new FACS */ + + acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); + + if ((acpi_gbl_RSDP->revision < 2) || + (acpi_gbl_FACS->length < 32) || + (!(acpi_gbl_FACS->xfirmware_waking_vector))) { + + /* ACPI 1.0 FACS or short table or optional X_ field is zero */ + + acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, + & + (acpi_gbl_FACS-> + firmware_waking_vector)); + acpi_gbl_common_fACS.vector_width = 32; + } else { + /* ACPI 2.0 FACS with valid X_ field */ + + acpi_gbl_common_fACS.firmware_waking_vector = + &acpi_gbl_FACS->xfirmware_waking_vector; + acpi_gbl_common_fACS.vector_width = 64; + } + + return_ACPI_STATUS(AE_OK); +} diff --git a/trunk/drivers/acpi/tables/tbfadt.c b/trunk/drivers/acpi/tables/tbfadt.c deleted file mode 100644 index 807c7116e94b..000000000000 --- a/trunk/drivers/acpi/tables/tbfadt.c +++ /dev/null @@ -1,434 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbfadt - FADT table utilities - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2007, R. Byron Moore - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbfadt") - -/* Local prototypes */ -static void inline -acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address); - -static void acpi_tb_convert_fadt(void); - -static void acpi_tb_validate_fadt(void); - -/* Table for conversion of FADT to common internal format and FADT validation */ - -typedef struct acpi_fadt_info { - char *name; - u8 target; - u8 source; - u8 length; - u8 type; - -} acpi_fadt_info; - -#define ACPI_FADT_REQUIRED 1 -#define ACPI_FADT_SEPARATE_LENGTH 2 - -static struct acpi_fadt_info fadt_info_table[] = { - {"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block), - ACPI_FADT_OFFSET(pm1a_event_block), - ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED}, - - {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block), - ACPI_FADT_OFFSET(pm1b_event_block), - ACPI_FADT_OFFSET(pm1_event_length), 0}, - - {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block), - ACPI_FADT_OFFSET(pm1a_control_block), - ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED}, - - {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block), - ACPI_FADT_OFFSET(pm1b_control_block), - ACPI_FADT_OFFSET(pm1_control_length), 0}, - - {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block), - ACPI_FADT_OFFSET(pm2_control_block), - ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH}, - - {"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block), - ACPI_FADT_OFFSET(pm_timer_block), - ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED}, - - {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block), - ACPI_FADT_OFFSET(gpe0_block), - ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH}, - - {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), - ACPI_FADT_OFFSET(gpe1_block), - ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH} -}; - -#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) - -/******************************************************************************* - * - * FUNCTION: acpi_tb_init_generic_address - * - * PARAMETERS: generic_address - GAS struct to be initialized - * bit_width - Width of this register - * Address - Address of the register - * - * RETURN: None - * - * DESCRIPTION: Initialize a Generic Address Structure (GAS) - * See the ACPI specification for a full description and - * definition of this structure. - * - ******************************************************************************/ - -static void inline -acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, - u8 bit_width, u64 address) -{ - - /* - * The 64-bit Address field is non-aligned in the byte packed - * GAS struct. - */ - ACPI_MOVE_64_TO_64(&generic_address->address, &address); - - /* All other fields are byte-wide */ - - generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; - generic_address->bit_width = bit_width; - generic_address->bit_offset = 0; - generic_address->access_width = 0; -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_parse_fadt - * - * PARAMETERS: table_index - Index for the FADT - * Flags - Flags - * - * RETURN: None - * - * DESCRIPTION: Initialize the FADT, DSDT and FACS tables - * (FADT contains the addresses of the DSDT and FACS) - * - ******************************************************************************/ - -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) -{ - u32 length; - struct acpi_table_header *table; - - /* - * The FADT has multiple versions with different lengths, - * and it contains pointers to both the DSDT and FACS tables. - * - * Get a local copy of the FADT and convert it to a common format - * Map entire FADT, assumed to be smaller than one page. - */ - length = acpi_gbl_root_table_list.tables[table_index].length; - - table = - acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. - address, length); - if (!table) { - return; - } - - /* - * Validate the FADT checksum before we copy the table. Ignore - * checksum error as we want to try to get the DSDT and FACS. - */ - (void)acpi_tb_verify_checksum(table, length); - - /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ - - acpi_tb_create_local_fadt(table, length); - - /* All done with the real FADT, unmap it */ - - acpi_os_unmap_memory(table, length); - - /* Obtain the DSDT and FACS tables via their addresses within the FADT */ - - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); - - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, - flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_create_local_fadt - * - * PARAMETERS: Table - Pointer to BIOS FADT - * Length - Length of the table - * - * RETURN: None - * - * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. - * Performs validation on some important FADT fields. - * - ******************************************************************************/ - -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) -{ - - /* - * Check if the FADT is larger than what we know about (ACPI 2.0 version). - * Truncate the table, but make some noise. - */ - if (length > sizeof(struct acpi_table_fadt)) { - ACPI_WARNING((AE_INFO, - "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX", - table->revision, (unsigned)length, - sizeof(struct acpi_table_fadt))); - } - - /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ - - ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); - - ACPI_MEMCPY(&acpi_gbl_FADT, table, - ACPI_MIN(length, sizeof(struct acpi_table_fadt))); - - /* - * 1) Convert the local copy of the FADT to the common internal format - * 2) Validate some of the important values within the FADT - */ - acpi_tb_convert_fadt(); - acpi_tb_validate_fadt(); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_convert_fadt - * - * PARAMETERS: None, uses acpi_gbl_FADT - * - * RETURN: None - * - * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * -> Expand all 32-bit addresses to 64-bit. - * - * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), - * and must contain a copy of the actual FADT. - * - * ACPICA will use the "X" fields of the FADT for all addresses. - * - * "X" fields are optional extensions to the original V1.0 fields. Even if - * they are present in the structure, they can be optionally not used by - * setting them to zero. Therefore, we must selectively expand V1.0 fields - * if the corresponding X field is zero. - * - * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding - * "X" fields. - * - * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by - * expanding the corresponding ACPI 1.0 field. - * - ******************************************************************************/ - -static void acpi_tb_convert_fadt(void) -{ - u8 pm1_register_length; - struct acpi_generic_address *target; - acpi_native_uint i; - - /* Update the local FADT table header length */ - - acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); - - /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */ - - if (!acpi_gbl_FADT.Xfacs) { - acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; - } - - if (!acpi_gbl_FADT.Xdsdt) { - acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; - } - - /* - * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address - * structures as necessary. - */ - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target = - ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, - fadt_info_table[i].target); - - /* Expand only if the X target is null */ - - if (!target->address) { - acpi_tb_init_generic_address(target, - *ACPI_ADD_PTR(u8, - &acpi_gbl_FADT, - fadt_info_table - [i].length), - (u64) * ACPI_ADD_PTR(u32, - &acpi_gbl_FADT, - fadt_info_table - [i]. - source)); - } - } - - /* - * Calculate separate GAS structs for the PM1 Enable registers. - * These addresses do not appear (directly) in the FADT, so it is - * useful to calculate them once, here. - * - * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable Register - * block. Each is of length (pm1_event_length/2) - */ - pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); - - /* The PM1A register block is required */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - pm1_register_length, - (acpi_gbl_FADT.xpm1a_event_block.address + - pm1_register_length)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; - - /* The PM1B register block is optional, ignore if not present */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - pm1_register_length, - (acpi_gbl_FADT.xpm1b_event_block. - address + pm1_register_length)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; - - } -} - -/****************************************************************************** - * - * FUNCTION: acpi_tb_validate_fadt - * - * PARAMETERS: Table - Pointer to the FADT to be validated - * - * RETURN: None - * - * DESCRIPTION: Validate various important fields within the FADT. If a problem - * is found, issue a message, but no status is returned. - * Used by both the table manager and the disassembler. - * - * Possible additional checks: - * (acpi_gbl_FADT.pm1_event_length >= 4) - * (acpi_gbl_FADT.pm1_control_length >= 2) - * (acpi_gbl_FADT.pm_timer_length >= 4) - * Gpe block lengths must be multiple of 2 - * - ******************************************************************************/ - -static void acpi_tb_validate_fadt(void) -{ - u32 *address32; - struct acpi_generic_address *address64; - u8 length; - acpi_native_uint i; - - /* Examine all of the 64-bit extended address fields (X fields) */ - - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - - /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ - - address64 = - ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, - fadt_info_table[i].target); - address32 = - ACPI_ADD_PTR(u32, &acpi_gbl_FADT, - fadt_info_table[i].source); - length = - *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, - fadt_info_table[i].length); - - if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { - /* - * Field is required (Pm1a_event, Pm1a_control, pm_timer). - * Both the address and length must be non-zero. - */ - if (!address64->address || !length) { - ACPI_ERROR((AE_INFO, - "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", - fadt_info_table[i].name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); - } - } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { - /* - * Field is optional (PM2Control, GPE0, GPE1) AND has its own - * length field. If present, both the address and length must be valid. - */ - if ((address64->address && !length) - || (!address64->address && length)) { - ACPI_WARNING((AE_INFO, - "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", - fadt_info_table[i].name, - ACPI_FORMAT_UINT64(address64-> - address), - length)); - } - } - - /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ - - if (address64->address && *address32 && - (address64->address != (u64) * address32)) { - ACPI_ERROR((AE_INFO, - "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", - fadt_info_table[i].name, *address32, - ACPI_FORMAT_UINT64(address64->address))); - } - } -} diff --git a/trunk/drivers/acpi/tables/tbfind.c b/trunk/drivers/acpi/tables/tbfind.c deleted file mode 100644 index 058c064948e1..000000000000 --- a/trunk/drivers/acpi/tables/tbfind.c +++ /dev/null @@ -1,126 +0,0 @@ -/****************************************************************************** - * - * Module Name: tbfind - find table - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2007, R. Byron Moore - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include - -#define _COMPONENT ACPI_TABLES -ACPI_MODULE_NAME("tbfind") - -/******************************************************************************* - * - * FUNCTION: acpi_tb_find_table - * - * PARAMETERS: Signature - String with ACPI table signature - * oem_id - String with the table OEM ID - * oem_table_id - String with the OEM Table ID - * table_index - Where the table index is returned - * - * RETURN: Status and table index - * - * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the - * Signature, OEM ID and OEM Table ID. Returns an index that can - * be used to get the table header or entire table. - * - ******************************************************************************/ -acpi_status -acpi_tb_find_table(char *signature, - char *oem_id, - char *oem_table_id, acpi_native_uint * table_index) -{ - acpi_native_uint i; - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_find_table); - - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), - signature, ACPI_NAME_SIZE)) { - - /* Not the requested table */ - - continue; - } - - /* Table with matching signature has been found */ - - if (!acpi_gbl_root_table_list.tables[i].pointer) { - - /* Table is not currently mapped, map it */ - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - if (!acpi_gbl_root_table_list.tables[i].pointer) { - continue; - } - } - - /* Check for table match on all IDs */ - - if (!ACPI_MEMCMP - (acpi_gbl_root_table_list.tables[i].pointer->signature, - signature, ACPI_NAME_SIZE) && (!oem_id[0] - || - !ACPI_MEMCMP - (acpi_gbl_root_table_list. - tables[i].pointer->oem_id, - oem_id, ACPI_OEM_ID_SIZE)) - && (!oem_table_id[0] - || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. - pointer->oem_table_id, oem_table_id, - ACPI_OEM_TABLE_ID_SIZE))) { - *table_index = i; - - ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Found table [%4.4s]\n", signature)); - return_ACPI_STATUS(AE_OK); - } - } - - return_ACPI_STATUS(AE_NOT_FOUND); -} diff --git a/trunk/drivers/acpi/tables/tbget.c b/trunk/drivers/acpi/tables/tbget.c new file mode 100644 index 000000000000..11e2d4454e05 --- /dev/null +++ b/trunk/drivers/acpi/tables/tbget.c @@ -0,0 +1,471 @@ +/****************************************************************************** + * + * Module Name: tbget - ACPI Table get* routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbget") + +/* Local prototypes */ +static acpi_status +acpi_tb_get_this_table(struct acpi_pointer *address, + struct acpi_table_header *header, + struct acpi_table_desc *table_info); + +static acpi_status +acpi_tb_table_override(struct acpi_table_header *header, + struct acpi_table_desc *table_info); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table + * + * PARAMETERS: Address - Address of table to retrieve. Can be + * Logical or Physical + * table_info - Where table info is returned + * + * RETURN: None + * + * DESCRIPTION: Get entire table of unknown size. + * + ******************************************************************************/ + +acpi_status +acpi_tb_get_table(struct acpi_pointer *address, + struct acpi_table_desc *table_info) +{ + acpi_status status; + struct acpi_table_header header; + + ACPI_FUNCTION_TRACE(tb_get_table); + + /* Get the header in order to get signature and table size */ + + status = acpi_tb_get_table_header(address, &header); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the entire table */ + + status = acpi_tb_get_table_body(address, &header, table_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not get ACPI table (size %X)", + header.length)); + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table_header + * + * PARAMETERS: Address - Address of table to retrieve. Can be + * Logical or Physical + * return_header - Where the table header is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table header. Works in both physical or virtual + * addressing mode. Works with both physical or logical pointers. + * Table is either copied or mapped, depending on the pointer + * type and mode of the processor. + * + ******************************************************************************/ + +acpi_status +acpi_tb_get_table_header(struct acpi_pointer *address, + struct acpi_table_header *return_header) +{ + acpi_status status = AE_OK; + struct acpi_table_header *header = NULL; + + ACPI_FUNCTION_TRACE(tb_get_table_header); + + /* + * Flags contains the current processor mode (Virtual or Physical + * addressing) The pointer_type is either Logical or Physical + */ + switch (address->pointer_type) { + case ACPI_PHYSMODE_PHYSPTR: + case ACPI_LOGMODE_LOGPTR: + + /* Pointer matches processor mode, copy the header */ + + ACPI_MEMCPY(return_header, address->pointer.logical, + sizeof(struct acpi_table_header)); + break; + + case ACPI_LOGMODE_PHYSPTR: + + /* Create a logical address for the physical pointer */ + + status = acpi_os_map_memory(address->pointer.physical, + sizeof(struct acpi_table_header), + (void *)&header); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X%8.8X for table header", + ACPI_FORMAT_UINT64(address->pointer. + physical))); + return_ACPI_STATUS(status); + } + + /* Copy header and delete mapping */ + + ACPI_MEMCPY(return_header, header, + sizeof(struct acpi_table_header)); + acpi_os_unmap_memory(header, sizeof(struct acpi_table_header)); + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid address flags %X", + address->pointer_type)); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n", + return_header->signature)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table_body + * + * PARAMETERS: Address - Address of table to retrieve. Can be + * Logical or Physical + * Header - Header of the table to retrieve + * table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to + * replace the table with a newer version (table override.) + * Works in both physical or virtual + * addressing mode. Works with both physical or logical pointers. + * Table is either copied or mapped, depending on the pointer + * type and mode of the processor. + * + ******************************************************************************/ + +acpi_status +acpi_tb_get_table_body(struct acpi_pointer *address, + struct acpi_table_header *header, + struct acpi_table_desc *table_info) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_get_table_body); + + if (!table_info || !address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Attempt table override. */ + + status = acpi_tb_table_override(header, table_info); + if (ACPI_SUCCESS(status)) { + + /* Table was overridden by the host OS */ + + return_ACPI_STATUS(status); + } + + /* No override, get the original table */ + + status = acpi_tb_get_this_table(address, header, table_info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_table_override + * + * PARAMETERS: Header - Pointer to table header + * table_info - Return info if table is overridden + * + * RETURN: None + * + * DESCRIPTION: Attempts override of current table with a new one if provided + * by the host OS. + * + ******************************************************************************/ + +static acpi_status +acpi_tb_table_override(struct acpi_table_header *header, + struct acpi_table_desc *table_info) +{ + struct acpi_table_header *new_table; + acpi_status status; + struct acpi_pointer address; + + ACPI_FUNCTION_TRACE(tb_table_override); + + /* + * The OSL will examine the header and decide whether to override this + * table. If it decides to override, a table will be returned in new_table, + * which we will then copy. + */ + status = acpi_os_table_override(header, &new_table); + if (ACPI_FAILURE(status)) { + + /* Some severe error from the OSL, but we basically ignore it */ + + ACPI_EXCEPTION((AE_INFO, status, + "Could not override ACPI table")); + return_ACPI_STATUS(status); + } + + if (!new_table) { + + /* No table override */ + + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* + * We have a new table to override the old one. Get a copy of + * the new one. We know that the new table has a logical pointer. + */ + address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; + address.pointer.logical = new_table; + + status = acpi_tb_get_this_table(&address, new_table, table_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table")); + return_ACPI_STATUS(status); + } + + /* Copy the table info */ + + ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS", + table_info->pointer->signature)); + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_this_table + * + * PARAMETERS: Address - Address of table to retrieve. Can be + * Logical or Physical + * Header - Header of the table to retrieve + * table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual + * addressing mode. Works with both physical or logical pointers. + * Table is either copied or mapped, depending on the pointer + * type and mode of the processor. + * + ******************************************************************************/ + +static acpi_status +acpi_tb_get_this_table(struct acpi_pointer *address, + struct acpi_table_header *header, + struct acpi_table_desc *table_info) +{ + struct acpi_table_header *full_table = NULL; + u8 allocation; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_get_this_table); + + /* Validate minimum length */ + + if (header->length < sizeof(struct acpi_table_header)) { + ACPI_ERROR((AE_INFO, + "Table length (%X) is smaller than minimum (%zX)", + header->length, sizeof(struct acpi_table_header))); + + return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); + } + + /* + * Flags contains the current processor mode (Virtual or Physical + * addressing) The pointer_type is either Logical or Physical + */ + switch (address->pointer_type) { + case ACPI_PHYSMODE_PHYSPTR: + case ACPI_LOGMODE_LOGPTR: + + /* Pointer matches processor mode, copy the table to a new buffer */ + + full_table = ACPI_ALLOCATE(header->length); + if (!full_table) { + ACPI_ERROR((AE_INFO, + "Could not allocate table memory for [%4.4s] length %X", + header->signature, header->length)); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy the entire table (including header) to the local buffer */ + + ACPI_MEMCPY(full_table, address->pointer.logical, + header->length); + + /* Save allocation type */ + + allocation = ACPI_MEM_ALLOCATED; + break; + + case ACPI_LOGMODE_PHYSPTR: + + /* + * Just map the table's physical memory + * into our address space. + */ + status = acpi_os_map_memory(address->pointer.physical, + (acpi_size) header->length, + ACPI_CAST_PTR(void, &full_table)); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X", + header->signature, + ACPI_FORMAT_UINT64(address->pointer. + physical), + header->length)); + return (status); + } + + /* Save allocation type */ + + allocation = ACPI_MEM_MAPPED; + break; + + default: + + ACPI_ERROR((AE_INFO, "Invalid address flags %X", + address->pointer_type)); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Validate checksum for _most_ tables, + * even the ones whose signature we don't recognize + */ + if (table_info->type != ACPI_TABLE_ID_FACS) { + status = acpi_tb_verify_table_checksum(full_table); + +#if (!ACPI_CHECKSUM_ABORT) + if (ACPI_FAILURE(status)) { + + /* Ignore the error if configuration says so */ + + status = AE_OK; + } +#endif + } + + /* Return values */ + + table_info->pointer = full_table; + table_info->length = (acpi_size) header->length; + table_info->allocation = allocation; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", + full_table->signature, + ACPI_FORMAT_UINT64(address->pointer.physical), + full_table)); + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table_ptr + * + * PARAMETERS: table_type - one of the defined table types + * Instance - Which table of this type + * return_table - pointer to location to place the pointer for + * return + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the pointer to an ACPI table. + * + ******************************************************************************/ + +acpi_status +acpi_tb_get_table_ptr(acpi_table_type table_type, + u32 instance, struct acpi_table_header **return_table) +{ + struct acpi_table_desc *table_desc; + u32 i; + + ACPI_FUNCTION_TRACE(tb_get_table_ptr); + + if (table_type > ACPI_TABLE_ID_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Check for instance out of range of the current table count */ + + if (instance > acpi_gbl_table_lists[table_type].count) { + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * Walk the list to get the desired table + * Note: Instance is one-based + */ + table_desc = acpi_gbl_table_lists[table_type].next; + for (i = 1; i < instance; i++) { + table_desc = table_desc->next; + } + + /* We are now pointing to the requested table's descriptor */ + + *return_table = table_desc->pointer; + return_ACPI_STATUS(AE_OK); +} diff --git a/trunk/drivers/acpi/tables/tbgetall.c b/trunk/drivers/acpi/tables/tbgetall.c new file mode 100644 index 000000000000..ad982112e4c6 --- /dev/null +++ b/trunk/drivers/acpi/tables/tbgetall.c @@ -0,0 +1,311 @@ +/****************************************************************************** + * + * Module Name: tbgetall - Get all required ACPI tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbgetall") + +/* Local prototypes */ +static acpi_status +acpi_tb_get_primary_table(struct acpi_pointer *address, + struct acpi_table_desc *table_info); + +static acpi_status +acpi_tb_get_secondary_table(struct acpi_pointer *address, + acpi_string signature, + struct acpi_table_desc *table_info); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_primary_table + * + * PARAMETERS: Address - Physical address of table to retrieve + * *table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +static acpi_status +acpi_tb_get_primary_table(struct acpi_pointer *address, + struct acpi_table_desc *table_info) +{ + acpi_status status; + struct acpi_table_header header; + + ACPI_FUNCTION_TRACE(tb_get_primary_table); + + /* Ignore a NULL address in the RSDT */ + + if (!address->pointer.value) { + return_ACPI_STATUS(AE_OK); + } + + /* Get the header in order to get signature and table size */ + + status = acpi_tb_get_table_header(address, &header); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Clear the table_info */ + + ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc)); + + /* + * Check the table signature and make sure it is recognized. + * Also checks the header checksum + */ + table_info->pointer = &header; + status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the entire table */ + + status = acpi_tb_get_table_body(address, &header, table_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Install the table */ + + status = acpi_tb_install_table(table_info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_secondary_table + * + * PARAMETERS: Address - Physical address of table to retrieve + * *table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +static acpi_status +acpi_tb_get_secondary_table(struct acpi_pointer *address, + acpi_string signature, + struct acpi_table_desc *table_info) +{ + acpi_status status; + struct acpi_table_header header; + + ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature); + + /* Get the header in order to match the signature */ + + status = acpi_tb_get_table_header(address, &header); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Signature must match request */ + + if (!ACPI_COMPARE_NAME(header.signature, signature)) { + ACPI_ERROR((AE_INFO, + "Incorrect table signature - wanted [%s] found [%4.4s]", + signature, header.signature)); + return_ACPI_STATUS(AE_BAD_SIGNATURE); + } + + /* + * Check the table signature and make sure it is recognized. + * Also checks the header checksum + */ + table_info->pointer = &header; + status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the entire table */ + + status = acpi_tb_get_table_body(address, &header, table_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Install the table */ + + status = acpi_tb_install_table(table_info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_required_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must + * already be loaded and validated. + * + * Get the minimum set of ACPI tables, namely: + * + * 1) FADT (via RSDT in loop below) + * 2) FACS (via FADT) + * 3) DSDT (via FADT) + * + ******************************************************************************/ + +acpi_status acpi_tb_get_required_tables(void) +{ + acpi_status status = AE_OK; + u32 i; + struct acpi_table_desc table_info; + struct acpi_pointer address; + + ACPI_FUNCTION_TRACE(tb_get_required_tables); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", + acpi_gbl_rsdt_table_count)); + + address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; + + /* + * Loop through all table pointers found in RSDT. + * This will NOT include the FACS and DSDT - we must get + * them after the loop. + * + * The only tables we are interested in getting here is the FADT and + * any SSDTs. + */ + for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + + /* Get the table address from the common internal XSDT */ + + address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; + + /* + * Get the tables needed by this subsystem (FADT and any SSDTs). + * NOTE: All other tables are completely ignored at this time. + */ + status = acpi_tb_get_primary_table(&address, &table_info); + if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { + ACPI_WARNING((AE_INFO, + "%s, while getting table at %8.8X%8.8X", + acpi_format_exception(status), + ACPI_FORMAT_UINT64(address.pointer. + value))); + } + } + + /* We must have a FADT to continue */ + + if (!acpi_gbl_FADT) { + ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* + * Convert the FADT to a common format. This allows earlier revisions of + * the table to coexist with newer versions, using common access code. + */ + status = acpi_tb_convert_table_fadt(); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not convert FADT to internal common format")); + return_ACPI_STATUS(status); + } + + /* Get the FACS (Pointed to by the FADT) */ + + address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl; + + status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not get/install the FACS")); + return_ACPI_STATUS(status); + } + + /* + * Create the common FACS pointer table + * (Contains pointers to the original table) + */ + status = acpi_tb_build_common_facs(&table_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get/install the DSDT (Pointed to by the FADT) */ + + address.pointer.value = acpi_gbl_FADT->Xdsdt; + + status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not get/install the DSDT")); + return_ACPI_STATUS(status); + } + + /* Set Integer Width (32/64) based upon DSDT revision */ + + acpi_ut_set_integer_width(acpi_gbl_DSDT->revision); + + /* Dump the entire DSDT */ + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", + acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, + acpi_gbl_integer_bit_width)); + + ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT), + acpi_gbl_DSDT->length); + + /* Always delete the RSDP mapping, we are done with it */ + + acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP); + return_ACPI_STATUS(status); +} diff --git a/trunk/drivers/acpi/tables/tbinstal.c b/trunk/drivers/acpi/tables/tbinstal.c index 0e7b121a99ce..1668a232fb67 100644 --- a/trunk/drivers/acpi/tables/tbinstal.c +++ b/trunk/drivers/acpi/tables/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,498 +42,510 @@ */ #include -#include #include #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbinstal") -/****************************************************************************** +/* Local prototypes */ +static acpi_status +acpi_tb_match_signature(char *signature, + struct acpi_table_desc *table_info, u8 search_type); + +/******************************************************************************* * - * FUNCTION: acpi_tb_verify_table + * FUNCTION: acpi_tb_match_signature * - * PARAMETERS: table_desc - table + * PARAMETERS: Signature - Table signature to match + * table_info - Return data + * search_type - Table type to match (primary/secondary) * * RETURN: Status * - * DESCRIPTION: this function is called to verify and map table + * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" + * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. * - *****************************************************************************/ -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) + ******************************************************************************/ + +static acpi_status +acpi_tb_match_signature(char *signature, + struct acpi_table_desc *table_info, u8 search_type) { - acpi_status status = AE_OK; + acpi_native_uint i; - ACPI_FUNCTION_TRACE(tb_verify_table); + ACPI_FUNCTION_TRACE(tb_match_signature); - /* Map the table if necessary */ + /* Search for a signature match among the known table types */ - if (!table_desc->pointer) { - if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { - table_desc->pointer = - acpi_os_map_memory(table_desc->address, - table_desc->length); - } - if (!table_desc->pointer) { - return_ACPI_STATUS(AE_NO_MEMORY); + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { + if (!(acpi_gbl_table_data[i].flags & search_type)) { + continue; } - } - /* FACS is the odd table, has no standard ACPI header and no checksum */ + if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, + acpi_gbl_table_data[i].sig_length)) { + + /* Found a signature match, return index if requested */ - if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { + if (table_info) { + table_info->type = (u8) i; + } - /* Always calculate checksum, ignore bad checksum if requested */ + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", + (char *)acpi_gbl_table_data[i]. + signature)); - status = - acpi_tb_verify_checksum(table_desc->pointer, - table_desc->length); + return_ACPI_STATUS(AE_OK); + } } - return_ACPI_STATUS(status); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", + (char *)signature)); + + return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); } /******************************************************************************* * - * FUNCTION: acpi_tb_add_table + * FUNCTION: acpi_tb_install_table * - * PARAMETERS: table_desc - Table descriptor - * table_index - Where the table index is returned + * PARAMETERS: table_info - Return value from acpi_tb_get_table_body * * RETURN: Status * - * DESCRIPTION: This function is called to add the ACPI table + * DESCRIPTION: Install the table into the global data structures. * ******************************************************************************/ -acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, - acpi_native_uint * table_index) +acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) { - acpi_native_uint i; - acpi_native_uint length; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE(tb_add_table); + acpi_status status; - if (!table_desc->pointer) { - status = acpi_tb_verify_table(table_desc); - if (ACPI_FAILURE(status) || !table_desc->pointer) { - return_ACPI_STATUS(status); - } - } - - /* The table must be either an SSDT or a PSDT */ - - if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) - && - (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))) - { - ACPI_ERROR((AE_INFO, - "Table has invalid signature [%4.4s], must be SSDT or PSDT", - table_desc->pointer->signature)); - return_ACPI_STATUS(AE_BAD_SIGNATURE); - } + ACPI_FUNCTION_TRACE(tb_install_table); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + /* Lock tables while installing */ - /* Check if table is already registered */ - - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (!acpi_gbl_root_table_list.tables[i].pointer) { - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); - if (ACPI_FAILURE(status) - || !acpi_gbl_root_table_list.tables[i].pointer) { - continue; - } - } - - length = ACPI_MIN(table_desc->length, - acpi_gbl_root_table_list.tables[i].length); - if (ACPI_MEMCMP(table_desc->pointer, - acpi_gbl_root_table_list.tables[i].pointer, - length)) { - continue; - } - - /* Table is already registered */ - - acpi_tb_delete_table(table_desc); - *table_index = i; - goto release; + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not acquire table mutex")); + return_ACPI_STATUS(status); } /* - * Add the table to the global table list + * Ignore a table that is already installed. For example, some BIOS + * ASL code will repeatedly attempt to load the same SSDT. */ - status = acpi_tb_store_table(table_desc->address, table_desc->pointer, - table_desc->length, table_desc->flags, - table_index); + status = acpi_tb_is_table_installed(table_info); + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + + /* Install the table into the global data structure */ + + status = acpi_tb_init_table_descriptor(table_info->type, table_info); if (ACPI_FAILURE(status)) { - goto release; + ACPI_EXCEPTION((AE_INFO, status, + "Could not install table [%4.4s]", + table_info->pointer->signature)); } - acpi_tb_print_table_header(table_desc->address, table_desc->pointer); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", + acpi_gbl_table_data[table_info->type].name, + table_info->pointer)); - release: + unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_resize_root_table_list + * FUNCTION: acpi_tb_recognize_table * - * PARAMETERS: None + * PARAMETERS: table_info - Return value from acpi_tb_get_table_body + * search_type - Table type to match (primary/secondary) * * RETURN: Status * - * DESCRIPTION: Expand the size of global table array + * DESCRIPTION: Check a table signature for a match against known table types + * + * NOTE: All table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum for some odd reason) * ******************************************************************************/ -acpi_status acpi_tb_resize_root_table_list(void) +acpi_status +acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) { - struct acpi_table_desc *tables; + struct acpi_table_header *table_header; + acpi_status status; - ACPI_FUNCTION_TRACE(tb_resize_root_table_list); + ACPI_FUNCTION_TRACE(tb_recognize_table); - /* allow_resize flag is a parameter to acpi_initialize_tables */ + /* Ensure that we have a valid table pointer */ - if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { - ACPI_ERROR((AE_INFO, - "Resize of Root Table Array is not allowed")); - return_ACPI_STATUS(AE_SUPPORT); + table_header = (struct acpi_table_header *)table_info->pointer; + if (!table_header) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Increase the Table Array size */ - - tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size + - ACPI_ROOT_TABLE_SIZE_INCREMENT) - * sizeof(struct acpi_table_desc)); - if (!tables) { - ACPI_ERROR((AE_INFO, - "Could not allocate new root table array")); - return_ACPI_STATUS(AE_NO_MEMORY); + /* + * We only "recognize" a limited number of ACPI tables -- namely, the + * ones that are used by the subsystem (DSDT, FADT, etc.) + * + * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. + * This can be any one of many valid ACPI tables, it just isn't one of + * the tables that is consumed by the core subsystem + */ + status = acpi_tb_match_signature(table_header->signature, + table_info, search_type); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - /* Copy and free the previous table array */ - - if (acpi_gbl_root_table_list.tables) { - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, - acpi_gbl_root_table_list.size * - sizeof(struct acpi_table_desc)); - - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); - } + status = acpi_tb_validate_table_header(table_header); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; - acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; + /* Return the table type and length via the info struct */ - return_ACPI_STATUS(AE_OK); + table_info->length = (acpi_size) table_header->length; + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_store_table + * FUNCTION: acpi_tb_init_table_descriptor * - * PARAMETERS: Address - Table address - * Table - Table header - * Length - Table length - * Flags - flags + * PARAMETERS: table_type - The type of the table + * table_info - A table info struct * - * RETURN: Status and table index. + * RETURN: None. * - * DESCRIPTION: Add an ACPI table to the global table list + * DESCRIPTION: Install a table into the global data structs. * ******************************************************************************/ acpi_status -acpi_tb_store_table(acpi_physical_address address, - struct acpi_table_header *table, - u32 length, u8 flags, acpi_native_uint * table_index) +acpi_tb_init_table_descriptor(acpi_table_type table_type, + struct acpi_table_desc *table_info) { - acpi_status status = AE_OK; + struct acpi_table_list *list_head; + struct acpi_table_desc *table_desc; + acpi_status status; - /* Ensure that there is room for the table in the Root Table List */ + ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); - if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - return (status); - } + /* Allocate a descriptor for this table */ + + table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); + if (!table_desc) { + return_ACPI_STATUS(AE_NO_MEMORY); } - /* Initialize added table */ - - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - address = address; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - pointer = table; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = - length; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - owner_id = 0; - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = - flags; - - ACPI_MOVE_32_TO_32(& - (acpi_gbl_root_table_list. - tables[acpi_gbl_root_table_list.count].signature), - table->signature); - - *table_index = acpi_gbl_root_table_list.count; - acpi_gbl_root_table_list.count++; - return (status); -} + /* Get a new owner ID for the table */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_delete_table - * - * PARAMETERS: table_index - Table index - * - * RETURN: None - * - * DESCRIPTION: Delete one internal ACPI table - * - ******************************************************************************/ - -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) -{ - /* Table must be mapped or allocated */ - if (!table_desc->pointer) { - return; - } - switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { - case ACPI_TABLE_ORIGIN_MAPPED: - acpi_os_unmap_memory(table_desc->pointer, table_desc->length); - break; - case ACPI_TABLE_ORIGIN_ALLOCATED: - ACPI_FREE(table_desc->pointer); - break; - default:; + status = acpi_ut_allocate_owner_id(&table_desc->owner_id); + if (ACPI_FAILURE(status)) { + goto error_exit1; } - table_desc->pointer = NULL; -} + /* Install the table into the global data structure */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_terminate - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Delete all internal ACPI tables - * - ******************************************************************************/ + list_head = &acpi_gbl_table_lists[table_type]; -void acpi_tb_terminate(void) -{ - acpi_native_uint i; + /* + * Two major types of tables: 1) Only one instance is allowed. This + * includes most ACPI tables such as the DSDT. 2) Multiple instances of + * the table are allowed. This includes SSDT and PSDTs. + */ + if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { + /* + * Only one table allowed, and a table has alread been installed + * at this location, so return an error. + */ + if (list_head->next) { + status = AE_ALREADY_EXISTS; + goto error_exit2; + } - ACPI_FUNCTION_TRACE(tb_terminate); + table_desc->next = list_head->next; + list_head->next = table_desc; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_desc->next) { + table_desc->next->prev = table_desc; + } - /* Delete the individual tables */ + list_head->count++; + } else { + /* + * Link the new table in to the list of tables of this type. + * Insert at the end of the list, order IS IMPORTANT. + * + * table_desc->Prev & Next are already NULL from calloc() + */ + list_head->count++; + + if (!list_head->next) { + list_head->next = table_desc; + } else { + table_desc->next = list_head->next; + + while (table_desc->next->next) { + table_desc->next = table_desc->next->next; + } - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); + table_desc->next->next = table_desc; + table_desc->prev = table_desc->next; + table_desc->next = NULL; + } } + /* Finish initialization of the table descriptor */ + + table_desc->loaded_into_namespace = FALSE; + table_desc->type = (u8) table_type; + table_desc->pointer = table_info->pointer; + table_desc->length = table_info->length; + table_desc->allocation = table_info->allocation; + table_desc->aml_start = (u8 *) (table_desc->pointer + 1), + table_desc->aml_length = (u32) + (table_desc->length - (u32) sizeof(struct acpi_table_header)); + /* - * Delete the root table array if allocated locally. Array cannot be - * mapped, so we don't need to check for that flag. + * Set the appropriate global pointer (if there is one) to point to the + * newly installed table */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); + if (acpi_gbl_table_data[table_type].global_ptr) { + *(acpi_gbl_table_data[table_type].global_ptr) = + table_info->pointer; } - acpi_gbl_root_table_list.tables = NULL; - acpi_gbl_root_table_list.flags = 0; - acpi_gbl_root_table_list.count = 0; + /* Return Data */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + table_info->owner_id = table_desc->owner_id; + table_info->installed_desc = table_desc; + return_ACPI_STATUS(AE_OK); + + /* Error exit with cleanup */ + + error_exit2: + + acpi_ut_release_owner_id(&table_desc->owner_id); + + error_exit1: + + ACPI_FREE(table_desc); + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_delete_namespace_by_owner + * FUNCTION: acpi_tb_delete_all_tables * - * PARAMETERS: table_index - Table index + * PARAMETERS: None. * - * RETURN: None + * RETURN: None. * - * DESCRIPTION: Delete all namespace objects created when this table was loaded. + * DESCRIPTION: Delete all internal ACPI tables * ******************************************************************************/ -void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) +void acpi_tb_delete_all_tables(void) { - acpi_owner_id owner_id; + acpi_table_type type; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - } else { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return; + /* + * Free memory allocated for ACPI tables + * Memory can either be mapped or allocated + */ + for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { + acpi_tb_delete_tables_by_type(type); } - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - acpi_ns_delete_namespace_by_owner(owner_id); } /******************************************************************************* * - * FUNCTION: acpi_tb_allocate_owner_id + * FUNCTION: acpi_tb_delete_tables_by_type * - * PARAMETERS: table_index - Table index + * PARAMETERS: Type - The table type to be deleted * - * RETURN: Status + * RETURN: None. * - * DESCRIPTION: Allocates owner_id in table_desc + * DESCRIPTION: Delete an internal ACPI table + * Locks the ACPI table mutex * ******************************************************************************/ -acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) +void acpi_tb_delete_tables_by_type(acpi_table_type type) { - acpi_status status = AE_BAD_PARAMETER; + struct acpi_table_desc *table_desc; + u32 count; + u32 i; - ACPI_FUNCTION_TRACE(tb_allocate_owner_id); + ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - status = acpi_ut_allocate_owner_id - (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); + if (type > ACPI_TABLE_ID_MAX) { + return_VOID; } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} + if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { + return; + } -/******************************************************************************* - * - * FUNCTION: acpi_tb_release_owner_id - * - * PARAMETERS: table_index - Table index - * - * RETURN: Status - * - * DESCRIPTION: Releases owner_id in table_desc - * - ******************************************************************************/ + /* Clear the appropriate "typed" global table pointer */ -acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) -{ - acpi_status status = AE_BAD_PARAMETER; + switch (type) { + case ACPI_TABLE_ID_RSDP: + acpi_gbl_RSDP = NULL; + break; + + case ACPI_TABLE_ID_DSDT: + acpi_gbl_DSDT = NULL; + break; - ACPI_FUNCTION_TRACE(tb_release_owner_id); + case ACPI_TABLE_ID_FADT: + acpi_gbl_FADT = NULL; + break; + + case ACPI_TABLE_ID_FACS: + acpi_gbl_FACS = NULL; + break; + + case ACPI_TABLE_ID_XSDT: + acpi_gbl_XSDT = NULL; + break; + + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: + default: + break; + } + + /* + * Free the table + * 1) Get the head of the list + */ + table_desc = acpi_gbl_table_lists[type].next; + count = acpi_gbl_table_lists[type].count; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - acpi_ut_release_owner_id(& - (acpi_gbl_root_table_list. - tables[table_index].owner_id)); - status = AE_OK; + /* + * 2) Walk the entire list, deleting both the allocated tables + * and the table descriptors + */ + for (i = 0; i < count; i++) { + table_desc = acpi_tb_uninstall_table(table_desc); } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); + return_VOID; } /******************************************************************************* * - * FUNCTION: acpi_tb_get_owner_id + * FUNCTION: acpi_tb_delete_single_table * - * PARAMETERS: table_index - Table index - * owner_id - Where the table owner_id is returned + * PARAMETERS: table_info - A table info struct * - * RETURN: Status + * RETURN: None. * - * DESCRIPTION: returns owner_id for the ACPI table + * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where + * the table was allocated a buffer or was mapped. * ******************************************************************************/ -acpi_status -acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) +void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) { - acpi_status status = AE_BAD_PARAMETER; - ACPI_FUNCTION_TRACE(tb_get_owner_id); + /* Must have a valid table descriptor and pointer */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - *owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - status = AE_OK; + if ((!table_desc) || (!table_desc->pointer)) { + return; } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} + /* Valid table, determine type of memory allocation */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_is_table_loaded - * - * PARAMETERS: table_index - Table index - * - * RETURN: Table Loaded Flag - * - ******************************************************************************/ + switch (table_desc->allocation) { + case ACPI_MEM_NOT_ALLOCATED: + break; -u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) -{ - u8 is_loaded = FALSE; + case ACPI_MEM_ALLOCATED: - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - is_loaded = (u8) - (acpi_gbl_root_table_list.tables[table_index]. - flags & ACPI_TABLE_IS_LOADED); - } + ACPI_FREE(table_desc->pointer); + break; - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return (is_loaded); + case ACPI_MEM_MAPPED: + + acpi_os_unmap_memory(table_desc->pointer, table_desc->length); + break; + + default: + break; + } } /******************************************************************************* * - * FUNCTION: acpi_tb_set_table_loaded_flag + * FUNCTION: acpi_tb_uninstall_table * - * PARAMETERS: table_index - Table index - * is_loaded - TRUE if table is loaded, FALSE otherwise + * PARAMETERS: table_info - A table info struct * - * RETURN: None + * RETURN: Pointer to the next table in the list (of same type) * - * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * DESCRIPTION: Free the memory associated with an internal ACPI table that + * is either installed or has never been installed. + * Table mutex should be locked. * ******************************************************************************/ -void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) +struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc + *table_desc) { + struct acpi_table_desc *next_desc; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - if (is_loaded) { - acpi_gbl_root_table_list.tables[table_index].flags |= - ACPI_TABLE_IS_LOADED; - } else { - acpi_gbl_root_table_list.tables[table_index].flags &= - ~ACPI_TABLE_IS_LOADED; - } + ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); + + if (!table_desc) { + return_PTR(NULL); } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + /* Unlink the descriptor from the doubly linked list */ + + if (table_desc->prev) { + table_desc->prev->next = table_desc->next; + } else { + /* Is first on list, update list head */ + + acpi_gbl_table_lists[table_desc->type].next = table_desc->next; + } + + if (table_desc->next) { + table_desc->next->prev = table_desc->prev; + } + + /* Free the memory allocated for the table itself */ + + acpi_tb_delete_single_table(table_desc); + + /* Free the owner ID associated with this table */ + + acpi_ut_release_owner_id(&table_desc->owner_id); + + /* Free the table descriptor */ + + next_desc = table_desc->next; + ACPI_FREE(table_desc); + + /* Return pointer to the next descriptor */ + + return_PTR(next_desc); } diff --git a/trunk/drivers/acpi/tables/tbrsdt.c b/trunk/drivers/acpi/tables/tbrsdt.c new file mode 100644 index 000000000000..86a5fca9b739 --- /dev/null +++ b/trunk/drivers/acpi/tables/tbrsdt.c @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * Module Name: tbrsdt - ACPI RSDT table utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbrsdt") + +/******************************************************************************* + * + * FUNCTION: acpi_tb_verify_rsdp + * + * PARAMETERS: Address - RSDP (Pointer to RSDT) + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ +acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) +{ + struct acpi_table_desc table_info; + acpi_status status; + struct rsdp_descriptor *rsdp; + + ACPI_FUNCTION_TRACE(tb_verify_rsdp); + + switch (address->pointer_type) { + case ACPI_LOGICAL_POINTER: + + rsdp = address->pointer.logical; + break; + + case ACPI_PHYSICAL_POINTER: + /* + * Obtain access to the RSDP structure + */ + status = acpi_os_map_memory(address->pointer.physical, + sizeof(struct rsdp_descriptor), + ACPI_CAST_PTR(void, &rsdp)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + break; + + default: + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Verify RSDP signature and checksum */ + + status = acpi_tb_validate_rsdp(rsdp); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* RSDP is ok. Init the table info */ + + table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp); + table_info.length = sizeof(struct rsdp_descriptor); + + if (address->pointer_type == ACPI_PHYSICAL_POINTER) { + table_info.allocation = ACPI_MEM_MAPPED; + } else { + table_info.allocation = ACPI_MEM_NOT_ALLOCATED; + } + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + /* Save the RSDP in a global for easy access */ + + acpi_gbl_RSDP = + ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer); + return_ACPI_STATUS(status); + + /* Error exit */ + cleanup: + + if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) { + acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor)); + } + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_rsdt_address + * + * PARAMETERS: out_address - Where the address is returned + * + * RETURN: None, Address + * + * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the + * version of the RSDP and whether the XSDT pointer is valid + * + ******************************************************************************/ + +void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address) +{ + + ACPI_FUNCTION_ENTRY(); + + out_address->pointer_type = + acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; + + /* Use XSDT if it is present */ + + if ((acpi_gbl_RSDP->revision >= 2) && + acpi_gbl_RSDP->xsdt_physical_address) { + out_address->pointer.value = + acpi_gbl_RSDP->xsdt_physical_address; + acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT; + } else { + /* No XSDT, use the RSDT */ + + out_address->pointer.value = + acpi_gbl_RSDP->rsdt_physical_address; + acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_validate_rsdt + * + * PARAMETERS: table_ptr - Addressable pointer to the RSDT. + * + * RETURN: Status + * + * DESCRIPTION: Validate signature for the RSDT or XSDT + * + ******************************************************************************/ + +acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) +{ + char *signature; + + ACPI_FUNCTION_ENTRY(); + + /* Validate minimum length */ + + if (table_ptr->length < sizeof(struct acpi_table_header)) { + ACPI_ERROR((AE_INFO, + "RSDT/XSDT length (%X) is smaller than minimum (%zX)", + table_ptr->length, + sizeof(struct acpi_table_header))); + + return (AE_INVALID_TABLE_LENGTH); + } + + /* Search for appropriate signature, RSDT or XSDT */ + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + signature = RSDT_SIG; + } else { + signature = XSDT_SIG; + } + + if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) { + + /* Invalid RSDT or XSDT signature */ + + ACPI_ERROR((AE_INFO, + "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:")); + + ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); + + ACPI_ERROR((AE_INFO, + "RSDT/XSDT signature at %X is invalid", + acpi_gbl_RSDP->rsdt_physical_address)); + + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + ACPI_ERROR((AE_INFO, "Looking for RSDT")); + } else { + ACPI_ERROR((AE_INFO, "Looking for XSDT")); + } + + ACPI_DUMP_BUFFER(ACPI_CAST_PTR(char, table_ptr), 48); + return (AE_BAD_SIGNATURE); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_table_rsdt + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ + +acpi_status acpi_tb_get_table_rsdt(void) +{ + struct acpi_table_desc table_info; + acpi_status status; + struct acpi_pointer address; + + ACPI_FUNCTION_TRACE(tb_get_table_rsdt); + + /* Get the RSDT/XSDT via the RSDP */ + + acpi_tb_get_rsdt_address(&address); + + table_info.type = ACPI_TABLE_ID_XSDT; + status = acpi_tb_get_table(&address, &table_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not get the RSDT/XSDT")); + return_ACPI_STATUS(status); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n", + acpi_gbl_RSDP, + ACPI_FORMAT_UINT64(address.pointer.value))); + + /* Check the RSDT or XSDT signature */ + + status = acpi_tb_validate_rsdt(table_info.pointer); + if (ACPI_FAILURE(status)) { + goto error_cleanup; + } + + /* Get the number of tables defined in the RSDT or XSDT */ + + acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, + table_info.pointer); + + /* Convert and/or copy to an XSDT structure */ + + status = acpi_tb_convert_to_xsdt(&table_info); + if (ACPI_FAILURE(status)) { + goto error_cleanup; + } + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info); + if (ACPI_FAILURE(status)) { + goto error_cleanup; + } + + acpi_gbl_XSDT = + ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); + return_ACPI_STATUS(status); + + error_cleanup: + + /* Free table allocated by acpi_tb_get_table */ + + acpi_tb_delete_single_table(&table_info); + + return_ACPI_STATUS(status); +} diff --git a/trunk/drivers/acpi/tables/tbutils.c b/trunk/drivers/acpi/tables/tbutils.c index 1da64b4518c0..209a401801e3 100644 --- a/trunk/drivers/acpi/tables/tbutils.c +++ b/trunk/drivers/acpi/tables/tbutils.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: tbutils - table utilities + * Module Name: tbutils - Table manipulation utilities * *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,119 +48,137 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -static acpi_physical_address -acpi_tb_get_root_table_entry(u8 * table_entry, - acpi_native_uint table_entry_size); +#ifdef ACPI_OBSOLETE_FUNCTIONS +acpi_status +acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); +#endif /******************************************************************************* * - * FUNCTION: acpi_tb_tables_loaded + * FUNCTION: acpi_tb_is_table_installed + * + * PARAMETERS: new_table_desc - Descriptor for new table being installed * - * PARAMETERS: None + * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed * - * RETURN: TRUE if required ACPI tables are loaded + * DESCRIPTION: Determine if an ACPI table is already installed * - * DESCRIPTION: Determine if the minimum required ACPI tables are present - * (FADT, FACS, DSDT) + * MUTEX: Table data structures should be locked * ******************************************************************************/ -u8 acpi_tb_tables_loaded(void) +acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) { + struct acpi_table_desc *table_desc; - if (acpi_gbl_root_table_list.count >= 3) { - return (TRUE); - } + ACPI_FUNCTION_TRACE(tb_is_table_installed); - return (FALSE); -} + /* Get the list descriptor and first table descriptor */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_print_table_header - * - * PARAMETERS: Address - Table physical address - * Header - Table header - * - * RETURN: None - * - * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. - * - ******************************************************************************/ + table_desc = acpi_gbl_table_lists[new_table_desc->type].next; -void -acpi_tb_print_table_header(acpi_physical_address address, - struct acpi_table_header *header) -{ + /* Examine all installed tables of this type */ - if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - - /* FACS only has signature and length fields of common table header */ - - ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", - header->signature, (unsigned long)address, - header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { - - /* RSDP has no common fields */ - - ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", - (unsigned long)address, - (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> - revision > - 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->length : 20, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->revision, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id)); - } else { - /* Standard ACPI table with full common header */ - - ACPI_INFO((AE_INFO, - "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", - header->signature, (unsigned long)address, - header->length, header->revision, header->oem_id, - header->oem_table_id, header->oem_revision, - header->asl_compiler_id, - header->asl_compiler_revision)); + while (table_desc) { + /* + * If the table lengths match, perform a full bytewise compare. This + * means that we will allow tables with duplicate oem_table_id(s), as + * long as the tables are different in some way. + * + * Checking if the table has been loaded into the namespace means that + * we don't check for duplicate tables during the initial installation + * of tables within the RSDT/XSDT. + */ + if ((table_desc->loaded_into_namespace) && + (table_desc->pointer->length == + new_table_desc->pointer->length) + && + (!ACPI_MEMCMP + (table_desc->pointer, new_table_desc->pointer, + new_table_desc->pointer->length))) { + + /* Match: this table is already installed */ + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, + "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", + new_table_desc->pointer->signature, + new_table_desc->pointer->revision, + new_table_desc->pointer-> + oem_table_id)); + + new_table_desc->owner_id = table_desc->owner_id; + new_table_desc->installed_desc = table_desc; + + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + /* Get next table on the list */ + + table_desc = table_desc->next; } + + return_ACPI_STATUS(AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_tb_validate_checksum + * FUNCTION: acpi_tb_validate_table_header * - * PARAMETERS: Table - ACPI table to verify - * Length - Length of entire table + * PARAMETERS: table_header - Logical pointer to the table * * RETURN: Status * - * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns - * exception on bad checksum. + * DESCRIPTION: Check an ACPI table header for validity + * + * NOTE: Table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum because it contains variable fields) * ******************************************************************************/ -acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) +acpi_status +acpi_tb_validate_table_header(struct acpi_table_header *table_header) { - u8 checksum; + acpi_name signature; - /* Compute the checksum on the table */ + ACPI_FUNCTION_ENTRY(); + + /* Verify that this is a valid address */ - checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); + if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { + ACPI_ERROR((AE_INFO, + "Cannot read table header at %p", table_header)); + + return (AE_BAD_ADDRESS); + } - /* Checksum ok? (should be zero) */ + /* Ensure that the signature is 4 ASCII characters */ - if (checksum) { - ACPI_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", - table->signature, table->checksum, - (u8) (table->checksum - checksum))); + ACPI_MOVE_32_TO_32(&signature, table_header->signature); + if (!acpi_ut_valid_acpi_name(signature)) { + ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", + signature)); -#if (ACPI_CHECKSUM_ABORT) + ACPI_DUMP_BUFFER(table_header, + sizeof(struct acpi_table_header)); + return (AE_BAD_SIGNATURE); + } - return (AE_BAD_CHECKSUM); -#endif + /* Validate the table length */ + + if (table_header->length < sizeof(struct acpi_table_header)) { + ACPI_ERROR((AE_INFO, + "Invalid length 0x%X in table with signature %4.4s", + (u32) table_header->length, + ACPI_CAST_PTR(char, &signature))); + + ACPI_DUMP_BUFFER(table_header, + sizeof(struct acpi_table_header)); + return (AE_BAD_HEADER); } return (AE_OK); @@ -168,320 +186,157 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) /******************************************************************************* * - * FUNCTION: acpi_tb_checksum + * FUNCTION: acpi_tb_sum_table * - * PARAMETERS: Buffer - Pointer to memory region to be checked - * Length - Length of this memory region + * PARAMETERS: Buffer - Buffer to sum + * Length - Size of the buffer * - * RETURN: Checksum (u8) + * RETURN: 8 bit sum of buffer * - * DESCRIPTION: Calculates circular checksum of memory region. + * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. * ******************************************************************************/ -u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) +u8 acpi_tb_sum_table(void *buffer, u32 length) { + acpi_native_uint i; u8 sum = 0; - u8 *end = buffer + length; - while (buffer < end) { - sum = (u8) (sum + *(buffer++)); + if (!buffer || !length) { + return (0); } - return sum; + for (i = 0; i < length; i++) { + sum = (u8) (sum + ((u8 *) buffer)[i]); + } + return (sum); } /******************************************************************************* * - * FUNCTION: acpi_tb_install_table + * FUNCTION: acpi_tb_generate_checksum * - * PARAMETERS: Address - Physical address of DSDT or FACS - * Flags - Flags - * Signature - Table signature, NULL if no need to - * match - * table_index - Index into root table array + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) * - * RETURN: None + * RETURN: 8 bit checksum of buffer * - * DESCRIPTION: Install an ACPI table into the global data structure. + * DESCRIPTION: Computes an 8 bit checksum of the table. * ******************************************************************************/ -void -acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, acpi_native_uint table_index) +u8 acpi_tb_generate_checksum(struct acpi_table_header * table) { - struct acpi_table_header *table; - - if (!address) { - ACPI_ERROR((AE_INFO, - "Null physical address for ACPI table [%s]", - signature)); - return; - } - - /* Map just the table header */ - - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { - return; - } - - /* If a particular signature is expected, signature must match */ - - if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { - ACPI_ERROR((AE_INFO, - "Invalid signature 0x%X for ACPI table [%s]", - *ACPI_CAST_PTR(u32, table->signature), signature)); - goto unmap_and_exit; - } - - /* Initialize the table entry */ - - acpi_gbl_root_table_list.tables[table_index].address = address; - acpi_gbl_root_table_list.tables[table_index].length = table->length; - acpi_gbl_root_table_list.tables[table_index].flags = flags; + u8 checksum; - ACPI_MOVE_32_TO_32(& - (acpi_gbl_root_table_list.tables[table_index]. - signature), table->signature); + /* Sum the entire table as-is */ - acpi_tb_print_table_header(address, table); + checksum = acpi_tb_sum_table(table, table->length); - if (table_index == ACPI_TABLE_INDEX_DSDT) { + /* Subtract off the existing checksum value in the table */ - /* Global integer width is based upon revision of the DSDT */ + checksum = (u8) (checksum - table->checksum); - acpi_ut_set_integer_width(table->revision); - } + /* Compute the final checksum */ - unmap_and_exit: - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + checksum = (u8) (0 - checksum); + return (checksum); } /******************************************************************************* * - * FUNCTION: acpi_tb_get_root_table_entry + * FUNCTION: acpi_tb_set_checksum * - * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry - * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) * - * RETURN: Physical address extracted from the root table + * RETURN: None. Sets the table checksum field * - * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on - * both 32-bit and 64-bit platforms - * - * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on - * 64-bit platforms. + * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the + * checksum into the table header. * ******************************************************************************/ -static acpi_physical_address -acpi_tb_get_root_table_entry(u8 * table_entry, - acpi_native_uint table_entry_size) +void acpi_tb_set_checksum(struct acpi_table_header *table) { - u64 address64; - - /* - * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): - * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT - */ - if (table_entry_size == sizeof(u32)) { - /* - * 32-bit platform, RSDT: Return 32-bit table entry - * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return - */ - return ((acpi_physical_address) - (*ACPI_CAST_PTR(u32, table_entry))); - } else { - /* - * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return - * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit - */ - ACPI_MOVE_64_TO_64(&address64, table_entry); -#if ACPI_MACHINE_WIDTH == 32 - if (address64 > ACPI_UINT32_MAX) { - - /* Will truncate 64-bit address to 32 bits, issue warning */ - - ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", - ACPI_FORMAT_UINT64(address64))); - } -#endif - return ((acpi_physical_address) (address64)); - } + table->checksum = acpi_tb_generate_checksum(table); } /******************************************************************************* * - * FUNCTION: acpi_tb_parse_root_table - * - * PARAMETERS: Rsdp - Pointer to the RSDP - * Flags - Flags + * FUNCTION: acpi_tb_verify_table_checksum * - * RETURN: Status + * PARAMETERS: *table_header - ACPI table to verify * - * DESCRIPTION: This function is called to parse the Root System Description - * Table (RSDT or XSDT) + * RETURN: 8 bit checksum of table * - * NOTE: Tables are mapped (not copied) for efficiency. The FACS must - * be mapped and cannot be copied because it contains the actual - * memory location of the ACPI Global Lock. + * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares + * it to the existing checksum value. * ******************************************************************************/ -acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) +acpi_status +acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) { - struct acpi_table_rsdp *rsdp; - acpi_native_uint table_entry_size; - acpi_native_uint i; - u32 table_count; - struct acpi_table_header *table; - acpi_physical_address address; - u32 length; - u8 *table_entry; - acpi_status status; - - ACPI_FUNCTION_TRACE(tb_parse_root_table); - - /* - * Map the entire RSDP and extract the address of the RSDT or XSDT - */ - rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); - if (!rsdp) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - acpi_tb_print_table_header(rsdp_address, - ACPI_CAST_PTR(struct acpi_table_header, - rsdp)); - - /* Differentiate between RSDT and XSDT root tables */ + u8 checksum; - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - /* - * Root table is an XSDT (64-bit physical addresses). We must use the - * XSDT if the revision is > 1 and the XSDT pointer is present, as per - * the ACPI specification. - */ - address = (acpi_physical_address) rsdp->xsdt_physical_address; - table_entry_size = sizeof(u64); - } else { - /* Root table is an RSDT (32-bit physical addresses) */ + ACPI_FUNCTION_TRACE(tb_verify_table_checksum); - address = (acpi_physical_address) rsdp->rsdt_physical_address; - table_entry_size = sizeof(u32); - } + /* Compute the checksum on the table */ - /* - * It is not possible to map more than one entry in some environments, - * so unmap the RSDP here before mapping other tables - */ - acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); + checksum = acpi_tb_generate_checksum(table_header); - /* Map the RSDT/XSDT table header to get the full table length */ + /* Checksum ok? */ - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { - return_ACPI_STATUS(AE_NO_MEMORY); + if (checksum == table_header->checksum) { + return_ACPI_STATUS(AE_OK); } - acpi_tb_print_table_header(address, table); - - /* Get the length of the full table, verify length and map entire table */ + ACPI_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", + table_header->signature, table_header->checksum, + checksum)); - length = table->length; - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); - - if (length < sizeof(struct acpi_table_header)) { - ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", - length)); - return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); - } + return_ACPI_STATUS(AE_BAD_CHECKSUM); +} - table = acpi_os_map_memory(address, length); - if (!table) { - return_ACPI_STATUS(AE_NO_MEMORY); - } +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_tb_handle_to_object + * + * PARAMETERS: table_id - Id for which the function is searching + * table_desc - Pointer to return the matching table + * descriptor. + * + * RETURN: Search the tables to find one with a matching table_id and + * return a pointer to that table descriptor. + * + ******************************************************************************/ - /* Validate the root table checksum */ +acpi_status +acpi_tb_handle_to_object(u16 table_id, + struct acpi_table_desc **return_table_desc) +{ + u32 i; + struct acpi_table_desc *table_desc; - status = acpi_tb_verify_checksum(table, length); - if (ACPI_FAILURE(status)) { - acpi_os_unmap_memory(table, length); - return_ACPI_STATUS(status); - } + ACPI_FUNCTION_NAME(tb_handle_to_object); - /* Calculate the number of tables described in the root table */ - - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / table_entry_size); - - /* - * First two entries in the table array are reserved for the DSDT and FACS, - * which are not actually present in the RSDT/XSDT - they come from the FADT - */ - table_entry = - ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); - acpi_gbl_root_table_list.count = 2; - - /* - * Initialize the root table array from the RSDT/XSDT - */ - for (i = 0; i < table_count; i++) { - if (acpi_gbl_root_table_list.count >= - acpi_gbl_root_table_list.size) { - - /* There is no more room in the root table array, attempt resize */ - - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, - "Truncating %u table entries!", - (unsigned) - (acpi_gbl_root_table_list.size - - acpi_gbl_root_table_list. - count))); - break; + for (i = 0; i < ACPI_TABLE_MAX; i++) { + table_desc = acpi_gbl_table_lists[i].next; + while (table_desc) { + if (table_desc->table_id == table_id) { + *return_table_desc = table_desc; + return (AE_OK); } - } - - /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. - address = - acpi_tb_get_root_table_entry(table_entry, table_entry_size); - - table_entry += table_entry_size; - acpi_gbl_root_table_list.count++; - } - - /* - * It is not possible to map more than one entry in some environments, - * so unmap the root table here before mapping other tables - */ - acpi_os_unmap_memory(table, length); - - /* - * Complete the initialization of the root table array by examining - * the header of each table - */ - for (i = 2; i < acpi_gbl_root_table_list.count; i++) { - acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. - address, flags, NULL, i); - - /* Special case for FADT - get the DSDT and FACS */ - - if (ACPI_COMPARE_NAME - (&acpi_gbl_root_table_list.tables[i].signature, - ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(i, flags); + table_desc = table_desc->next; } } - return_ACPI_STATUS(AE_OK); + ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); + return (AE_BAD_PARAMETER); } +#endif diff --git a/trunk/drivers/acpi/tables/tbxface.c b/trunk/drivers/acpi/tables/tbxface.c index 807978d5381a..5ba9303293ad 100644 --- a/trunk/drivers/acpi/tables/tbxface.c +++ b/trunk/drivers/acpi/tables/tbxface.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,158 +49,80 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxface") -/* Local prototypes */ -static acpi_status acpi_tb_load_namespace(void); - /******************************************************************************* * - * FUNCTION: acpi_allocate_root_table + * FUNCTION: acpi_load_tables * - * PARAMETERS: initial_table_count - Size of initial_table_array, in number of - * struct acpi_table_desc structures + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and - * acpi_initialize_tables. + * DESCRIPTION: This function is called to load the ACPI tables from the + * provided RSDT * ******************************************************************************/ - -acpi_status acpi_allocate_root_table(u32 initial_table_count) +acpi_status acpi_load_tables(void) { + struct acpi_pointer rsdp_address; + acpi_status status; - acpi_gbl_root_table_list.size = initial_table_count; - acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; + ACPI_FUNCTION_TRACE(acpi_load_tables); - return (acpi_tb_resize_root_table_list()); -} + /* Get the RSDP */ -/******************************************************************************* - * - * FUNCTION: acpi_initialize_tables - * - * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated - * struct acpi_table_desc structures. If NULL, the - * array is dynamically allocated. - * initial_table_count - Size of initial_table_array, in number of - * struct acpi_table_desc structures - * allow_realloc - Flag to tell Table Manager if resize of - * pre-allocated array is allowed. Ignored - * if initial_table_array is NULL. - * - * RETURN: Status - * - * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. - * - * NOTE: Allows static allocation of the initial table array in order - * to avoid the use of dynamic memory in confined environments - * such as the kernel boot sequence where it may not be available. - * - * If the host OS memory managers are initialized, use NULL for - * initial_table_array, and the table will be dynamically allocated. - * - ******************************************************************************/ + status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, + &rsdp_address); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); + goto error_exit; + } -acpi_status __init -acpi_initialize_tables(struct acpi_table_desc * initial_table_array, - u32 initial_table_count, u8 allow_resize) -{ - acpi_physical_address rsdp_address; - acpi_status status; + /* Map and validate the RSDP */ - ACPI_FUNCTION_TRACE(acpi_initialize_tables); + acpi_gbl_table_flags = rsdp_address.pointer_type; - /* - * Set up the Root Table Array - * Allocate the table array if requested - */ - if (!initial_table_array) { - status = acpi_allocate_root_table(initial_table_count); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } else { - /* Root Table Array has been statically allocated by the host */ - - ACPI_MEMSET(initial_table_array, 0, - initial_table_count * - sizeof(struct acpi_table_desc)); - - acpi_gbl_root_table_list.tables = initial_table_array; - acpi_gbl_root_table_list.size = initial_table_count; - acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; - if (allow_resize) { - acpi_gbl_root_table_list.flags |= - ACPI_ROOT_ALLOW_RESIZE; - } + status = acpi_tb_verify_rsdp(&rsdp_address); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); + goto error_exit; } - /* Get the address of the RSDP */ + /* Get the RSDT via the RSDP */ - rsdp_address = acpi_os_get_root_pointer(); - if (!rsdp_address) { - return_ACPI_STATUS(AE_NOT_FOUND); + status = acpi_tb_get_table_rsdt(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); + goto error_exit; } - /* - * Get the root table (RSDT or XSDT) and extract all entries to the local - * Root Table Array. This array contains the information of the RSDT/XSDT - * in a common, more useable format. - */ - status = - acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_reallocate_root_table - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the - * root list from the previously provided scratch area. Should - * be called once dynamic memory allocation is available in the - * kernel - * - ******************************************************************************/ -acpi_status acpi_reallocate_root_table(void) -{ - struct acpi_table_desc *tables; - acpi_size new_size; - - ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); + /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ - /* - * Only reallocate the root table if the host provided a static buffer - * for the table array in the call to acpi_initialize_tables. - */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - return_ACPI_STATUS(AE_SUPPORT); + status = acpi_tb_get_required_tables(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not get all required tables (DSDT/FADT/FACS)")); + goto error_exit; } - new_size = - (acpi_gbl_root_table_list.count + - ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); + ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - /* Create new array and copy the old array */ + /* Load the namespace from the tables */ - tables = ACPI_ALLOCATE_ZEROED(new_size); - if (!tables) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = acpi_ns_load_namespace(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); + goto error_exit; } - ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); - - acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; - acpi_gbl_root_table_list.tables = tables; - acpi_gbl_root_table_list.flags = - ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; - return_ACPI_STATUS(AE_OK); + + error_exit: + ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); + return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_load_tables) + /******************************************************************************* * * FUNCTION: acpi_load_table @@ -219,405 +141,342 @@ acpi_status acpi_reallocate_root_table(void) acpi_status acpi_load_table(struct acpi_table_header *table_ptr) { acpi_status status; - acpi_native_uint table_index; - struct acpi_table_desc table_desc; + struct acpi_table_desc table_info; + struct acpi_pointer address; - if (!table_ptr) - return AE_BAD_PARAMETER; + ACPI_FUNCTION_TRACE(acpi_load_table); - ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); - table_desc.pointer = table_ptr; - table_desc.length = table_ptr->length; - table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; + if (!table_ptr) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } - /* - * Install the new table into the local data structures - */ - status = acpi_tb_add_table(&table_desc, &table_index); + /* Copy the table to a local buffer */ + + address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; + address.pointer.logical = table_ptr; + + status = acpi_tb_get_table_body(&address, table_ptr, &table_info); if (ACPI_FAILURE(status)) { - return status; + return_ACPI_STATUS(status); } - status = acpi_ns_load_table(table_index, acpi_gbl_root_node); - return status; -} -ACPI_EXPORT_SYMBOL(acpi_load_table) + /* Check signature for a valid table type */ -/****************************************************************************** - * - * FUNCTION: acpi_get_table_header - * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) - * out_table_header - The pointer to the table header to fill - * - * RETURN: Status and pointer to mapped table header - * - * DESCRIPTION: Finds an ACPI table header. - * - * NOTE: Caller is responsible in unmapping the header with - * acpi_os_unmap_memory - * - *****************************************************************************/ -acpi_status -acpi_get_table_header(char *signature, - acpi_native_uint instance, - struct acpi_table_header *out_table_header) -{ - acpi_native_uint i; - acpi_native_uint j; - struct acpi_table_header *header; + status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* Parameter validation */ + /* Install the new table into the local data structures */ - if (!signature || !out_table_header) { - return (AE_BAD_PARAMETER); - } + status = acpi_tb_install_table(&table_info); + if (ACPI_FAILURE(status)) { + if (status == AE_ALREADY_EXISTS) { - /* - * Walk the root table list - */ - for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { - if (!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - signature)) { - continue; - } + /* Table already exists, no error */ - if (++j < instance) { - continue; + status = AE_OK; } - if (!acpi_gbl_root_table_list.tables[i].pointer) { - if ((acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { - header = - acpi_os_map_memory(acpi_gbl_root_table_list. - tables[i].address, - sizeof(struct - acpi_table_header)); - if (!header) { - return AE_NO_MEMORY; - } - ACPI_MEMCPY(out_table_header, header, - sizeof(struct acpi_table_header)); - acpi_os_unmap_memory(header, - sizeof(struct - acpi_table_header)); - } else { - return AE_NOT_FOUND; - } - } else { - ACPI_MEMCPY(out_table_header, - acpi_gbl_root_table_list.tables[i].pointer, - sizeof(struct acpi_table_header)); - } - return (AE_OK); + /* Free table allocated by acpi_tb_get_table_body */ + + acpi_tb_delete_single_table(&table_info); + return_ACPI_STATUS(status); } - return (AE_NOT_FOUND); -} + /* Convert the table to common format if necessary */ -ACPI_EXPORT_SYMBOL(acpi_get_table_header) + switch (table_info.type) { + case ACPI_TABLE_ID_FADT: + status = acpi_tb_convert_table_fadt(); + break; -/****************************************************************************** + case ACPI_TABLE_ID_FACS: + + status = acpi_tb_build_common_facs(&table_info); + break; + + default: + /* Load table into namespace if it contains executable AML */ + + status = + acpi_ns_load_table(table_info.installed_desc, + acpi_gbl_root_node); + break; + } + + if (ACPI_FAILURE(status)) { + + /* Uninstall table and free the buffer */ + + (void)acpi_tb_uninstall_table(table_info.installed_desc); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_load_table) + +/******************************************************************************* * * FUNCTION: acpi_unload_table_id * - * PARAMETERS: id - Owner ID of the table to be removed. + * PARAMETERS: table_type - Type of table to be unloaded + * id - Owner ID of the table to be removed. * * RETURN: Status * * DESCRIPTION: This routine is used to force the unload of a table (by id) * ******************************************************************************/ -acpi_status acpi_unload_table_id(acpi_owner_id id) +acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id) { - int i; - acpi_status status = AE_NOT_EXIST; + struct acpi_table_desc *table_desc; + acpi_status status; ACPI_FUNCTION_TRACE(acpi_unload_table); + /* Parameter validation */ + if (table_type > ACPI_TABLE_ID_MAX) + return_ACPI_STATUS(AE_BAD_PARAMETER); + /* Find table from the requested type list */ - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if (id != acpi_gbl_root_table_list.tables[i].owner_id) { - continue; - } - /* - * Delete all namespace objects owned by this table. Note that these - * objects can appear anywhere in the namespace by virtue of the AML - * "Scope" operator. Thus, we need to track ownership by an ID, not - * simply a position within the hierarchy - */ - acpi_tb_delete_namespace_by_owner(i); - acpi_tb_release_owner_id(i); - acpi_tb_set_table_loaded_flag(i, FALSE); - } - return_ACPI_STATUS(status); + table_desc = acpi_gbl_table_lists[table_type].next; + while (table_desc && table_desc->owner_id != id) + table_desc = table_desc->next; + + if (!table_desc) + return_ACPI_STATUS(AE_NOT_EXIST); + + /* + * Delete all namespace objects owned by this table. Note that these + * objects can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ + acpi_ns_delete_namespace_by_owner(table_desc->owner_id); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + + (void)acpi_tb_uninstall_table(table_desc); + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_unload_table_id) +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * - * FUNCTION: acpi_get_table + * FUNCTION: acpi_unload_table * - * PARAMETERS: Signature - ACPI signature of needed table - * Instance - Which instance (for SSDTs) - * out_table - Where the pointer to the table is returned + * PARAMETERS: table_type - Type of table to be unloaded * - * RETURN: Status and pointer to table + * RETURN: Status * - * DESCRIPTION: Finds and verifies an ACPI table. + * DESCRIPTION: This routine is used to force the unload of a table * - *****************************************************************************/ -acpi_status -acpi_get_table(char *signature, - acpi_native_uint instance, struct acpi_table_header ** out_table) + ******************************************************************************/ +acpi_status acpi_unload_table(acpi_table_type table_type) { - acpi_native_uint i; - acpi_native_uint j; - acpi_status status; + struct acpi_table_desc *table_desc; + + ACPI_FUNCTION_TRACE(acpi_unload_table); /* Parameter validation */ - if (!signature || !out_table) { - return (AE_BAD_PARAMETER); + if (table_type > ACPI_TABLE_ID_MAX) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * Walk the root table list - */ - for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { - if (!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - signature)) { - continue; - } - - if (++j < instance) { - continue; - } - - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); - if (ACPI_SUCCESS(status)) { - *out_table = acpi_gbl_root_table_list.tables[i].pointer; - } + /* Find all tables of the requested type */ - if (!acpi_gbl_permanent_mmap) { - acpi_gbl_root_table_list.tables[i].pointer = 0; - } + table_desc = acpi_gbl_table_lists[table_type].next; + if (!table_desc) { + return_ACPI_STATUS(AE_NOT_EXIST); + } - return (status); + while (table_desc) { + /* + * Delete all namespace objects owned by this table. Note that these + * objects can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ + acpi_ns_delete_namespace_by_owner(table_desc->owner_id); + table_desc = table_desc->next; } - return (AE_NOT_FOUND); + /* Delete (or unmap) all tables of this type */ + + acpi_tb_delete_tables_by_type(table_type); + return_ACPI_STATUS(AE_OK); } -ACPI_EXPORT_SYMBOL(acpi_get_table) +ACPI_EXPORT_SYMBOL(acpi_unload_table) /******************************************************************************* * - * FUNCTION: acpi_get_table_by_index + * FUNCTION: acpi_get_table_header * - * PARAMETERS: table_index - Table index - * Table - Where the pointer to the table is returned + * PARAMETERS: table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see acpi_gbl_acpi_table_flag + * out_table_header - pointer to the struct acpi_table_header if successful * - * RETURN: Status and pointer to the table + * DESCRIPTION: This function is called to get an ACPI table header. The caller + * supplies an pointer to a data area sufficient to contain an ACPI + * struct acpi_table_header structure. * - * DESCRIPTION: Obtain a table by an index into the global table list. + * The header contains a length field that can be used to determine + * the size of the buffer needed to contain the entire table. This + * function is not valid for the RSD PTR table since it does not + * have a standard header and is fixed length. * ******************************************************************************/ acpi_status -acpi_get_table_by_index(acpi_native_uint table_index, - struct acpi_table_header ** table) +acpi_get_table_header(acpi_table_type table_type, + u32 instance, struct acpi_table_header *out_table_header) { + struct acpi_table_header *tbl_ptr; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_table_by_index); - - /* Parameter validation */ + ACPI_FUNCTION_TRACE(acpi_get_table_header); - if (!table) { + if ((instance == 0) || + (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Validate index */ + /* Check the table type and instance */ - if (table_index >= acpi_gbl_root_table_list.count) { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + if ((table_type > ACPI_TABLE_ID_MAX) || + (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && + instance > 1)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (!acpi_gbl_root_table_list.tables[table_index].pointer) { + /* Get a pointer to the entire table */ - /* Table is not mapped, map it */ + status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[table_index]); - if (ACPI_FAILURE(status)) { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); - } + /* The function will return a NULL pointer if the table is not loaded */ + + if (tbl_ptr == NULL) { + return_ACPI_STATUS(AE_NOT_EXIST); } - *table = acpi_gbl_root_table_list.tables[table_index].pointer; - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(AE_OK); + /* Copy the header to the caller's buffer */ + + ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), + ACPI_CAST_PTR(void, tbl_ptr), + sizeof(struct acpi_table_header)); + + return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) +ACPI_EXPORT_SYMBOL(acpi_get_table_header) +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * - * FUNCTION: acpi_tb_load_namespace + * FUNCTION: acpi_get_table * - * PARAMETERS: None + * PARAMETERS: table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see acpi_gbl_acpi_table_flag + * ret_buffer - pointer to a structure containing a buffer to + * receive the table * * RETURN: Status * - * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in - * the RSDT/XSDT. + * DESCRIPTION: This function is called to get an ACPI table. The caller + * supplies an out_buffer large enough to contain the entire ACPI + * table. The caller should call the acpi_get_table_header function + * first to determine the buffer size needed. Upon completion + * the out_buffer->Length field will indicate the number of bytes + * copied into the out_buffer->buf_ptr buffer. This table will be + * a complete table including the header. * ******************************************************************************/ -static acpi_status acpi_tb_load_namespace(void) +acpi_status +acpi_get_table(acpi_table_type table_type, + u32 instance, struct acpi_buffer *ret_buffer) { + struct acpi_table_header *tbl_ptr; acpi_status status; - struct acpi_table_header *table; - acpi_native_uint i; - - ACPI_FUNCTION_TRACE(tb_load_namespace); + acpi_size table_length; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + ACPI_FUNCTION_TRACE(acpi_get_table); - /* - * Load the namespace. The DSDT is required, but any SSDT and PSDT tables - * are optional. - */ - if (!acpi_gbl_root_table_list.count || - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].signature), - ACPI_SIG_DSDT) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]))) { - status = AE_NO_ACPI_TABLES; - goto unlock_and_exit; - } + /* Parameter validation */ - /* - * Find DSDT table - */ - status = - acpi_os_table_override(acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].pointer, - &table); - if (ACPI_SUCCESS(status) && table) { - /* - * DSDT table has been found - */ - acpi_tb_delete_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = - table; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = - table->length; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = - ACPI_TABLE_ORIGIN_UNKNOWN; - - ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); - acpi_tb_print_table_header(0, table); + if (instance == 0) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); + status = acpi_ut_validate_buffer(ret_buffer); if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* A valid DSDT is required */ + /* Check the table type and instance */ - status = AE_NO_ACPI_TABLES; - goto unlock_and_exit; + if ((table_type > ACPI_TABLE_ID_MAX) || + (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && + instance > 1)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + /* Get a pointer to the entire table */ - /* - * Load and parse tables. - */ - status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); + status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* - * Load any SSDT or PSDT tables. Note: Loop leaves tables locked + * acpi_tb_get_table_ptr will return a NULL pointer if the + * table is not loaded. */ - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { - if ((!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - ACPI_SIG_SSDT) - && - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list.tables[i]. - signature), ACPI_SIG_PSDT)) - || - ACPI_FAILURE(acpi_tb_verify_table - (&acpi_gbl_root_table_list.tables[i]))) { - continue; - } - - /* Ignore errors while loading tables, get as many as possible */ - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - (void)acpi_ns_load_table(i, acpi_gbl_root_node); - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (tbl_ptr == NULL) { + return_ACPI_STATUS(AE_NOT_EXIST); } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + /* Get the table length */ - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} + if (table_type == ACPI_TABLE_ID_RSDP) { -/******************************************************************************* - * - * FUNCTION: acpi_load_tables - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT - * - ******************************************************************************/ + /* RSD PTR is the only "table" without a header */ -acpi_status acpi_load_tables(void) -{ - acpi_status status; + table_length = sizeof(struct rsdp_descriptor); + } else { + table_length = (acpi_size) tbl_ptr->length; + } - ACPI_FUNCTION_TRACE(acpi_load_tables); + /* Validate/Allocate/Clear caller buffer */ - /* - * Load the namespace from the tables - */ - status = acpi_tb_load_namespace(); + status = acpi_ut_initialize_buffer(ret_buffer, table_length); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While loading namespace from ACPI tables")); + return_ACPI_STATUS(status); } - return_ACPI_STATUS(status); + /* Copy the table to the buffer */ + + ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), + ACPI_CAST_PTR(void, tbl_ptr), table_length); + + return_ACPI_STATUS(AE_OK); } -ACPI_EXPORT_SYMBOL(acpi_load_tables) +ACPI_EXPORT_SYMBOL(acpi_get_table) diff --git a/trunk/drivers/acpi/tables/tbxfroot.c b/trunk/drivers/acpi/tables/tbxfroot.c index cf8fa514189f..da2648bbdbc0 100644 --- a/trunk/drivers/acpi/tables/tbxfroot.c +++ b/trunk/drivers/acpi/tables/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,15 +48,16 @@ ACPI_MODULE_NAME("tbxfroot") /* Local prototypes */ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); +static acpi_status +acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags); -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); +static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); /******************************************************************************* * * FUNCTION: acpi_tb_validate_rsdp * - * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP * * RETURN: Status * @@ -64,18 +65,14 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); * ******************************************************************************/ -static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) +acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) { ACPI_FUNCTION_ENTRY(); /* - * The signature and checksum must both be correct - * - * Note: Sometimes there exists more than one RSDP in memory; the valid - * RSDP has a valid checksum, all others have an invalid checksum. + * The signature and checksum must both be correct */ - if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) - != 0) { + if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { /* Nope, BAD Signature */ @@ -84,14 +81,14 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) /* Check the standard checksum */ - if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && - (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { + (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } @@ -100,123 +97,314 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) /******************************************************************************* * - * FUNCTION: acpi_tb_find_rsdp + * FUNCTION: acpi_tb_find_table * - * PARAMETERS: table_address - Where the table pointer is returned + * PARAMETERS: Signature - String with ACPI table signature + * oem_id - String with the table OEM ID + * oem_table_id - String with the OEM Table ID + * table_ptr - Where the table pointer is returned * - * RETURN: Status, RSDP physical address + * RETURN: Status * - * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor - * pointer structure. If it is found, set *RSDP to point to it. + * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the + * Signature, OEM ID and OEM Table ID. * - * NOTE1: The RSDP must be either in the first 1_k of the Extended - * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) - * Only a 32-bit physical address is necessary. + ******************************************************************************/ + +acpi_status +acpi_tb_find_table(char *signature, + char *oem_id, + char *oem_table_id, struct acpi_table_header ** table_ptr) +{ + acpi_status status; + struct acpi_table_header *table; + + ACPI_FUNCTION_TRACE(tb_find_table); + + /* Validate string lengths */ + + if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) || + (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) || + (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) { + return_ACPI_STATUS(AE_AML_STRING_LIMIT); + } + + if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) { + /* + * The DSDT pointer is contained in the FADT, not the RSDT. + * This code should suffice, because the only code that would perform + * a "find" on the DSDT is the data_table_region() AML opcode -- in + * which case, the DSDT is guaranteed to be already loaded. + * If this becomes insufficient, the FADT will have to be found first. + */ + if (!acpi_gbl_DSDT) { + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + table = acpi_gbl_DSDT; + } else { + /* Find the table */ + + status = acpi_get_firmware_table(signature, 1, + ACPI_LOGICAL_ADDRESSING, + &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Check oem_id and oem_table_id */ + + if ((oem_id[0] && + ACPI_STRNCMP(oem_id, table->oem_id, + sizeof(table->oem_id))) || + (oem_table_id[0] && + ACPI_STRNCMP(oem_table_id, table->oem_table_id, + sizeof(table->oem_table_id)))) { + return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); + } + + ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n", + table->signature)); + + *table_ptr = table; + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* * - * NOTE2: This function is always available, regardless of the - * initialization state of the rest of ACPI. + * FUNCTION: acpi_get_firmware_table + * + * PARAMETERS: Signature - Any ACPI table signature + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * Flags - Physical/Virtual support + * table_pointer - Where a buffer containing the table is + * returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get an ACPI table. A buffer is + * allocated for the table and returned in table_pointer. + * This table will be a complete table including the header. * ******************************************************************************/ -acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) +acpi_status +acpi_get_firmware_table(acpi_string signature, + u32 instance, + u32 flags, struct acpi_table_header **table_pointer) { - u8 *table_ptr; - u8 *mem_rover; - u32 physical_address; + acpi_status status; + struct acpi_pointer address; + struct acpi_table_header *header = NULL; + struct acpi_table_desc *table_info = NULL; + struct acpi_table_desc *rsdt_info; + u32 table_count; + u32 i; + u32 j; - ACPI_FUNCTION_TRACE(acpi_find_root_pointer); + ACPI_FUNCTION_TRACE(acpi_get_firmware_table); - /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ + /* + * Ensure that at least the table manager is initialized. We don't + * require that the entire ACPI subsystem is up for this interface. + * If we have a buffer, we must have a length too + */ + if ((instance == 0) || (!signature) || (!table_pointer)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Ensure that we have a RSDP */ - table_ptr = acpi_os_map_memory((acpi_physical_address) - ACPI_EBDA_PTR_LOCATION, - ACPI_EBDA_PTR_LENGTH); - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); + if (!acpi_gbl_RSDP) { + /* Get the RSDP */ + + status = acpi_os_get_root_pointer(flags, &address); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + /* Map and validate the RSDP */ + + if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + status = acpi_os_map_memory(address.pointer.physical, + sizeof(struct + rsdp_descriptor), + (void *)&acpi_gbl_RSDP); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + acpi_gbl_RSDP = address.pointer.logical; + } + + /* The RDSP signature and checksum must both be correct */ + + status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Get the RSDT address via the RSDP */ + + acpi_tb_get_rsdt_address(&address); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "RSDP located at %p, RSDT physical=%8.8X%8.8X\n", + acpi_gbl_RSDP, + ACPI_FORMAT_UINT64(address.pointer.value))); + + /* Insert processor_mode flags */ + + address.pointer_type |= flags; + + /* Get and validate the RSDT */ + + rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); + if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MOVE_16_TO_32(&physical_address, table_ptr); + status = acpi_tb_get_table(&address, rsdt_info); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + status = acpi_tb_validate_rsdt(rsdt_info->pointer); + if (ACPI_FAILURE(status)) { + goto cleanup; + } - /* Convert segment part to physical address */ + /* Allocate a scratch table header and table descriptor */ - physical_address <<= 4; - acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); + header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); + if (!header) { + status = AE_NO_MEMORY; + goto cleanup; + } - /* EBDA present? */ + table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc)); + if (!table_info) { + status = AE_NO_MEMORY; + goto cleanup; + } - if (physical_address > 0x400) { + /* Get the number of table pointers within the RSDT */ + + table_count = + acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); + address.pointer_type = acpi_gbl_table_flags | flags; + + /* + * Search the RSDT/XSDT for the correct instance of the + * requested table + */ + for (i = 0, j = 0; i < table_count; i++) { /* - * 1b) Search EBDA paragraphs (EBDA is required to be a - * minimum of 1_k length) + * Get the next table pointer, handle RSDT vs. XSDT + * RSDT pointers are 32 bits, XSDT pointers are 64 bits */ - table_ptr = acpi_os_map_memory((acpi_native_uint) - physical_address, - ACPI_EBDA_WINDOW_SIZE); - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - physical_address, ACPI_EBDA_WINDOW_SIZE)); + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { + address.pointer.value = + (ACPI_CAST_PTR + (struct rsdt_descriptor, + rsdt_info->pointer))->table_offset_entry[i]; + } else { + address.pointer.value = + (ACPI_CAST_PTR + (struct xsdt_descriptor, + rsdt_info->pointer))->table_offset_entry[i]; + } + + /* Get the table header */ - return_ACPI_STATUS(AE_NO_MEMORY); + status = acpi_tb_get_table_header(&address, header); + if (ACPI_FAILURE(status)) { + goto cleanup; } - mem_rover = - acpi_tb_scan_memory_for_rsdp(table_ptr, - ACPI_EBDA_WINDOW_SIZE); - acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); + /* Compare table signatures and table instance */ - if (mem_rover) { + if (ACPI_COMPARE_NAME(header->signature, signature)) { - /* Return the physical address */ + /* An instance of the table was found */ - physical_address += - (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); + j++; + if (j >= instance) { - *table_address = physical_address; - return_ACPI_STATUS(AE_OK); + /* Found the correct instance, get the entire table */ + + status = + acpi_tb_get_table_body(&address, header, + table_info); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + *table_pointer = table_info->pointer; + goto cleanup; + } } } - /* - * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh - */ - table_ptr = acpi_os_map_memory((acpi_physical_address) - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE); + /* Did not find the table */ - if (!table_ptr) { - ACPI_ERROR((AE_INFO, - "Could not map memory at %8.8X for length %X", - ACPI_HI_RSDP_WINDOW_BASE, - ACPI_HI_RSDP_WINDOW_SIZE)); + status = AE_NOT_EXIST; - return_ACPI_STATUS(AE_NO_MEMORY); + cleanup: + if (rsdt_info->pointer) { + acpi_os_unmap_memory(rsdt_info->pointer, + (acpi_size) rsdt_info->pointer->length); } + ACPI_FREE(rsdt_info); - mem_rover = - acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); - acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); + if (header) { + ACPI_FREE(header); + } + if (table_info) { + ACPI_FREE(table_info); + } + return_ACPI_STATUS(status); +} - if (mem_rover) { +ACPI_EXPORT_SYMBOL(acpi_get_firmware_table) - /* Return the physical address */ +/* TBD: Move to a new file */ +#if ACPI_MACHINE_WIDTH != 16 +/******************************************************************************* + * + * FUNCTION: acpi_find_root_pointer + * + * PARAMETERS: Flags - Logical/Physical addressing + * rsdp_address - Where to place the RSDP address + * + * RETURN: Status, Physical address of the RSDP + * + * DESCRIPTION: Find the RSDP + * + ******************************************************************************/ +acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) +{ + struct acpi_table_desc table_info; + acpi_status status; - physical_address = (u32) - (ACPI_HI_RSDP_WINDOW_BASE + - ACPI_PTR_DIFF(mem_rover, table_ptr)); + ACPI_FUNCTION_TRACE(acpi_find_root_pointer); - *table_address = physical_address; - return_ACPI_STATUS(AE_OK); - } + /* Get the RSDP */ - /* A valid RSDP was not found */ + status = acpi_tb_find_rsdp(&table_info, flags); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "RSDP structure not found - Flags=%X", flags)); - ACPI_ERROR((AE_INFO, "A valid RSDP was not found")); - return_ACPI_STATUS(AE_NOT_FOUND); + return_ACPI_STATUS(AE_NO_ACPI_TABLES); + } + + rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER; + rsdp_address->pointer.physical = table_info.physical_address; + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) @@ -252,7 +440,7 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) status = acpi_tb_validate_rsdp(ACPI_CAST_PTR - (struct acpi_table_rsdp, mem_rover)); + (struct rsdp_descriptor, mem_rover)); if (ACPI_SUCCESS(status)) { /* Sig and checksum valid, we have found a real RSDP */ @@ -273,3 +461,189 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) start_address)); return_PTR(NULL); } + +/******************************************************************************* + * + * FUNCTION: acpi_tb_find_rsdp + * + * PARAMETERS: table_info - Where the table info is returned + * Flags - Current memory mode (logical vs. + * physical addressing) + * + * RETURN: Status, RSDP physical address + * + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE1: The RSDP must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) + * Only a 32-bit physical address is necessary. + * + * NOTE2: This function is always available, regardless of the + * initialization state of the rest of ACPI. + * + ******************************************************************************/ + +static acpi_status +acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) +{ + u8 *table_ptr; + u8 *mem_rover; + u32 physical_address; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_find_rsdp); + + /* + * Scan supports either logical addressing or physical addressing + */ + if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ + + status = acpi_os_map_memory((acpi_physical_address) + ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH, + (void *)&table_ptr); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH)); + + return_ACPI_STATUS(status); + } + + ACPI_MOVE_16_TO_32(&physical_address, table_ptr); + + /* Convert segment part to physical address */ + + physical_address <<= 4; + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); + + /* EBDA present? */ + + if (physical_address > 0x400) { + /* + * 1b) Search EBDA paragraphs (EBDA is required to be a + * minimum of 1_k length) + */ + status = acpi_os_map_memory((acpi_physical_address) + physical_address, + ACPI_EBDA_WINDOW_SIZE, + (void *)&table_ptr); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + physical_address, + ACPI_EBDA_WINDOW_SIZE)); + + return_ACPI_STATUS(status); + } + + mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr, + ACPI_EBDA_WINDOW_SIZE); + acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); + + if (mem_rover) { + + /* Return the physical address */ + + physical_address += + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); + + table_info->physical_address = + (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + } + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh + */ + status = acpi_os_map_memory((acpi_physical_address) + ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE, + (void *)&table_ptr); + + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X for length %X", + ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE)); + + return_ACPI_STATUS(status); + } + + mem_rover = + acpi_tb_scan_memory_for_rsdp(table_ptr, + ACPI_HI_RSDP_WINDOW_SIZE); + acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); + + if (mem_rover) { + + /* Return the physical address */ + + physical_address = (u32) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); + + table_info->physical_address = + (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + } + + /* + * Physical addressing + */ + else { + /* 1a) Get the location of the EBDA */ + + ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION); + physical_address <<= 4; /* Convert segment to physical address */ + + /* EBDA present? */ + + if (physical_address > 0x400) { + /* + * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of + * 1_k length) + */ + mem_rover = + acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR + (physical_address), + ACPI_EBDA_WINDOW_SIZE); + if (mem_rover) { + + /* Return the physical address */ + + table_info->physical_address = + ACPI_TO_INTEGER(mem_rover); + return_ACPI_STATUS(AE_OK); + } + } + + /* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ + + mem_rover = + acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR + (ACPI_HI_RSDP_WINDOW_BASE), + ACPI_HI_RSDP_WINDOW_SIZE); + if (mem_rover) { + + /* Found it, return the physical address */ + + table_info->physical_address = + ACPI_TO_INTEGER(mem_rover); + return_ACPI_STATUS(AE_OK); + } + } + + /* A valid RSDP was not found */ + + ACPI_ERROR((AE_INFO, "No valid RSDP was found")); + return_ACPI_STATUS(AE_NOT_FOUND); +} + +#endif diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index f76d3168c2b2..40ddb4dd9631 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -82,7 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_remove(struct acpi_device *device, int type); -static int acpi_thermal_resume(struct acpi_device *device); +static int acpi_thermal_resume(struct acpi_device *device, int state); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); @@ -1353,7 +1353,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) return 0; } -static int acpi_thermal_resume(struct acpi_device *device) +static int acpi_thermal_resume(struct acpi_device *device, int state) { struct acpi_thermal *tz = NULL; int i; diff --git a/trunk/drivers/acpi/utilities/utalloc.c b/trunk/drivers/acpi/utilities/utalloc.c index 55a764807499..f6cbc0b1bfd0 100644 --- a/trunk/drivers/acpi/utilities/utalloc.c +++ b/trunk/drivers/acpi/utilities/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ */ #include -#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") @@ -143,14 +142,6 @@ acpi_status acpi_ut_create_caches(void) acpi_status acpi_ut_delete_caches(void) { -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - char buffer[7]; - - if (acpi_gbl_display_final_mem_stats) { - ACPI_STRCPY(buffer, "MEMORY"); - acpi_db_display_statistics(buffer); - } -#endif (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); acpi_gbl_namespace_cache = NULL; diff --git a/trunk/drivers/acpi/utilities/utcache.c b/trunk/drivers/acpi/utilities/utcache.c index 870f6edeb5f2..1a1f8109159c 100644 --- a/trunk/drivers/acpi/utilities/utcache.c +++ b/trunk/drivers/acpi/utilities/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -289,14 +289,6 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) ACPI_MEM_TRACKING(cache->total_allocated++); -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - if ((cache->total_allocated - cache->total_freed) > - cache->max_occupied) { - cache->max_occupied = - cache->total_allocated - cache->total_freed; - } -#endif - /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ status = acpi_ut_release_mutex(ACPI_MTX_CACHES); diff --git a/trunk/drivers/acpi/utilities/utcopy.c b/trunk/drivers/acpi/utilities/utcopy.c index 84d529db0a66..5e1a80d1bc36 100644 --- a/trunk/drivers/acpi/utilities/utcopy.c +++ b/trunk/drivers/acpi/utilities/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -719,15 +719,6 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, acpi_ut_add_reference(source_desc->reference.object); break; - case ACPI_TYPE_REGION: - /* - * We copied the Region Handler, so we now must add a reference - */ - if (dest_desc->region.handler) { - acpi_ut_add_reference(dest_desc->region.handler); - } - break; - default: /* Nothing to do for other simple objects */ break; diff --git a/trunk/drivers/acpi/utilities/utdebug.c b/trunk/drivers/acpi/utilities/utdebug.c index 61ad4f2daee2..9e9054e155c1 100644 --- a/trunk/drivers/acpi/utilities/utdebug.c +++ b/trunk/drivers/acpi/utilities/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -181,7 +181,8 @@ acpi_ut_debug_print(u32 requested_debug_level, if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf ("\n**** Context Switch from TID %lX to TID %lX ****\n\n", - (unsigned long)acpi_gbl_prev_thread_id, (unsigned long)thread_id); + (unsigned long) acpi_gbl_prev_thread_id, + (unsigned long) thread_id); } acpi_gbl_prev_thread_id = thread_id; @@ -194,7 +195,7 @@ acpi_ut_debug_print(u32 requested_debug_level, acpi_os_printf("%8s-%04ld ", module_name, line_number); if (ACPI_LV_THREADS & acpi_dbg_level) { - acpi_os_printf("[%04lX] ", (unsigned long)thread_id); + acpi_os_printf("[%04lX] ", thread_id); } acpi_os_printf("[%02ld] %-22.22s: ", diff --git a/trunk/drivers/acpi/utilities/utdelete.c b/trunk/drivers/acpi/utilities/utdelete.c index f777cebdc46d..9d3f1149ba21 100644 --- a/trunk/drivers/acpi/utilities/utdelete.c +++ b/trunk/drivers/acpi/utilities/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -158,20 +158,16 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) "***** Mutex %p, OS Mutex %p\n", object, object->mutex.os_mutex)); - if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - - /* Global Lock has extra semaphore */ + if (object->mutex.os_mutex != ACPI_GLOBAL_LOCK) { + acpi_ex_unlink_mutex(object); + acpi_os_delete_mutex(object->mutex.os_mutex); + } else { + /* Global Lock "mutex" is actually a counting semaphore */ (void) acpi_os_delete_semaphore (acpi_gbl_global_lock_semaphore); acpi_gbl_global_lock_semaphore = NULL; - - acpi_os_delete_mutex(object->mutex.os_mutex); - acpi_gbl_global_lock_mutex = NULL; - } else { - acpi_ex_unlink_mutex(object); - acpi_os_delete_mutex(object->mutex.os_mutex); } break; diff --git a/trunk/drivers/acpi/utilities/uteval.c b/trunk/drivers/acpi/utilities/uteval.c index 13d5879cd98b..d6d7121583c0 100644 --- a/trunk/drivers/acpi/utilities/uteval.c +++ b/trunk/drivers/acpi/utilities/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utglobal.c b/trunk/drivers/acpi/utilities/utglobal.c index af33358a964b..014030af8b50 100644 --- a/trunk/drivers/acpi/utilities/utglobal.c +++ b/trunk/drivers/acpi/utilities/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,9 +46,89 @@ #include #include -ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) #define _COMPONENT ACPI_UTILITIES - ACPI_MODULE_NAME("utglobal") +ACPI_MODULE_NAME("utglobal") + +/******************************************************************************* + * + * FUNCTION: acpi_format_exception + * + * PARAMETERS: Status - The acpi_status code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string. + * + ******************************************************************************/ +const char *acpi_format_exception(acpi_status status) +{ + acpi_status sub_status; + const char *exception = NULL; + + ACPI_FUNCTION_ENTRY(); + + /* + * Status is composed of two parts, a "type" and an actual code + */ + sub_status = (status & ~AE_CODE_MASK); + + switch (status & AE_CODE_MASK) { + case AE_CODE_ENVIRONMENTAL: + + if (sub_status <= AE_CODE_ENV_MAX) { + exception = acpi_gbl_exception_names_env[sub_status]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (sub_status <= AE_CODE_PGM_MAX) { + exception = + acpi_gbl_exception_names_pgm[sub_status - 1]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (sub_status <= AE_CODE_TBL_MAX) { + exception = + acpi_gbl_exception_names_tbl[sub_status - 1]; + } + break; + + case AE_CODE_AML: + + if (sub_status <= AE_CODE_AML_MAX) { + exception = + acpi_gbl_exception_names_aml[sub_status - 1]; + } + break; + + case AE_CODE_CONTROL: + + if (sub_status <= AE_CODE_CTRL_MAX) { + exception = + acpi_gbl_exception_names_ctrl[sub_status - 1]; + } + break; + + default: + break; + } + + if (!exception) { + + /* Exception code was not recognized */ + + ACPI_ERROR((AE_INFO, + "Unknown exception code: 0x%8.8X", status)); + + exception = "UNKNOWN_STATUS_CODE"; + } + + return (ACPI_CAST_PTR(const char, exception)); +} /******************************************************************************* * @@ -83,6 +163,8 @@ u32 acpi_gbl_startup_flags = 0; u8 acpi_gbl_shutdown = TRUE; +const u8 acpi_gbl_decode_to8bit[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; + const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S0_", "\\_S1_", @@ -99,47 +181,12 @@ const char *acpi_gbl_highest_dstate_names[4] = { "_S4D" }; -/******************************************************************************* - * - * FUNCTION: acpi_format_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. A valid pointer is - * always returned. - * - * DESCRIPTION: This function translates an ACPI exception into an ASCII string - * It is here instead of utxface.c so it is always present. - * - ******************************************************************************/ - -const char *acpi_format_exception(acpi_status status) -{ - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - exception = acpi_ut_validate_exception(status); - if (!exception) { - - /* Exception code was not recognized */ - - ACPI_ERROR((AE_INFO, - "Unknown exception code: 0x%8.8X", status)); - - exception = "UNKNOWN_STATUS_CODE"; - } - - return (ACPI_CAST_PTR(const char, exception)); -} - -ACPI_EXPORT_SYMBOL(acpi_format_exception) - /******************************************************************************* * * Namespace globals * ******************************************************************************/ + /* * Predefined ACPI Names (Built-in to the Interpreter) * @@ -233,6 +280,53 @@ char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position) return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); } +/******************************************************************************* + * + * Table name globals + * + * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes. + * it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables + * that are not used by the subsystem are simply ignored. + * + * Do NOT add any table to this list that is not consumed directly by this + * subsystem (No MADT, ECDT, SBST, etc.) + * + ******************************************************************************/ + +struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; + +struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = { + /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ + + /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1, + ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE} + , + /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *)&acpi_gbl_DSDT, + sizeof(DSDT_SIG) - 1, + ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE | + ACPI_TABLE_EXECUTABLE} + , + /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *)&acpi_gbl_FADT, + sizeof(FADT_SIG) - 1, + ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE} + , + /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *)&acpi_gbl_FACS, + sizeof(FACS_SIG) - 1, + ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE} + , + /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof(PSDT_SIG) - 1, + ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | + ACPI_TABLE_EXECUTABLE} + , + /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof(SSDT_SIG) - 1, + ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | + ACPI_TABLE_EXECUTABLE} + , + /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof(RSDT_SIG) - 1, + ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE} + , +}; + /****************************************************************************** * * Event and Hardware globals @@ -518,7 +612,7 @@ char *acpi_ut_get_node_name(void *object) /* Name must be a valid ACPI name */ if (!acpi_ut_valid_acpi_name(node->name.integer)) { - node->name.integer = acpi_ut_repair_name(node->name.ascii); + node->name.integer = acpi_ut_repair_name(node->name.integer); } /* Return the name */ @@ -657,6 +751,13 @@ void acpi_ut_init_globals(void) return; } + /* ACPI table structure */ + + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { + acpi_gbl_table_lists[i].next = NULL; + acpi_gbl_table_lists[i].count = 0; + } + /* Mutex locked flags */ for (i = 0; i < ACPI_NUM_MUTEX; i++) { @@ -672,7 +773,6 @@ void acpi_ut_init_globals(void) /* GPE support */ - acpi_gpe_count = 0; acpi_gbl_gpe_xrupt_list_head = NULL; acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; @@ -684,15 +784,25 @@ void acpi_ut_init_globals(void) acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; + /* Global "typed" ACPI table pointers */ + + acpi_gbl_RSDP = NULL; + acpi_gbl_XSDT = NULL; + acpi_gbl_FACS = NULL; + acpi_gbl_FADT = NULL; + acpi_gbl_DSDT = NULL; + /* Global Lock support */ acpi_gbl_global_lock_semaphore = NULL; - acpi_gbl_global_lock_mutex = NULL; acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_thread_count = 0; acpi_gbl_global_lock_handle = 0; /* Miscellaneous variables */ + acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER; + acpi_gbl_rsdp_original_location = 0; acpi_gbl_cm_single_step = FALSE; acpi_gbl_db_terminate_threads = FALSE; acpi_gbl_shutdown = FALSE; @@ -727,13 +837,8 @@ void acpi_ut_init_globals(void) acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX; #endif -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_gbl_display_final_mem_stats = FALSE; -#endif - return_VOID; } ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) -ACPI_EXPORT_SYMBOL(acpi_gpe_count) diff --git a/trunk/drivers/acpi/utilities/utinit.c b/trunk/drivers/acpi/utilities/utinit.c index ad3c0d0a5cf8..ff76055eb7d6 100644 --- a/trunk/drivers/acpi/utilities/utinit.c +++ b/trunk/drivers/acpi/utilities/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,14 +44,119 @@ #include #include #include -#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utinit") /* Local prototypes */ +static void +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset); + static void acpi_ut_terminate(void); +/******************************************************************************* + * + * FUNCTION: acpi_ut_fadt_register_error + * + * PARAMETERS: register_name - Pointer to string identifying register + * Value - Actual register contents value + * Offset - Byte offset in the FADT + * + * RETURN: AE_BAD_VALUE + * + * DESCRIPTION: Display failure message + * + ******************************************************************************/ + +static void +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset) +{ + + ACPI_WARNING((AE_INFO, + "Invalid FADT value %s=%X at offset %X FADT=%p", + register_name, value, offset, acpi_gbl_FADT)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_ut_validate_fadt + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Validate various ACPI registers in the FADT + * + ******************************************************************************/ + +acpi_status acpi_ut_validate_fadt(void) +{ + + /* + * Verify Fixed ACPI Description Table fields, + * but don't abort on any problems, just display error + */ + if (acpi_gbl_FADT->pm1_evt_len < 4) { + acpi_ut_fadt_register_error("PM1_EVT_LEN", + (u32) acpi_gbl_FADT->pm1_evt_len, + ACPI_FADT_OFFSET(pm1_evt_len)); + } + + if (!acpi_gbl_FADT->pm1_cnt_len) { + acpi_ut_fadt_register_error("PM1_CNT_LEN", 0, + ACPI_FADT_OFFSET(pm1_cnt_len)); + } + + if (!acpi_gbl_FADT->xpm1a_evt_blk.address) { + acpi_ut_fadt_register_error("X_PM1a_EVT_BLK", 0, + ACPI_FADT_OFFSET(xpm1a_evt_blk. + address)); + } + + if (!acpi_gbl_FADT->xpm1a_cnt_blk.address) { + acpi_ut_fadt_register_error("X_PM1a_CNT_BLK", 0, + ACPI_FADT_OFFSET(xpm1a_cnt_blk. + address)); + } + + if (!acpi_gbl_FADT->xpm_tmr_blk.address) { + acpi_ut_fadt_register_error("X_PM_TMR_BLK", 0, + ACPI_FADT_OFFSET(xpm_tmr_blk. + address)); + } + + if ((acpi_gbl_FADT->xpm2_cnt_blk.address && + !acpi_gbl_FADT->pm2_cnt_len)) { + acpi_ut_fadt_register_error("PM2_CNT_LEN", + (u32) acpi_gbl_FADT->pm2_cnt_len, + ACPI_FADT_OFFSET(pm2_cnt_len)); + } + + if (acpi_gbl_FADT->pm_tm_len < 4) { + acpi_ut_fadt_register_error("PM_TM_LEN", + (u32) acpi_gbl_FADT->pm_tm_len, + ACPI_FADT_OFFSET(pm_tm_len)); + } + + /* Length of GPE blocks must be a multiple of 2 */ + + if (acpi_gbl_FADT->xgpe0_blk.address && + (acpi_gbl_FADT->gpe0_blk_len & 1)) { + acpi_ut_fadt_register_error("(x)GPE0_BLK_LEN", + (u32) acpi_gbl_FADT->gpe0_blk_len, + ACPI_FADT_OFFSET(gpe0_blk_len)); + } + + if (acpi_gbl_FADT->xgpe1_blk.address && + (acpi_gbl_FADT->gpe1_blk_len & 1)) { + acpi_ut_fadt_register_error("(x)GPE1_BLK_LEN", + (u32) acpi_gbl_FADT->gpe1_blk_len, + ACPI_FADT_OFFSET(gpe1_blk_len)); + } + + return (AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_ut_terminate @@ -73,6 +178,7 @@ static void acpi_ut_terminate(void) ACPI_FUNCTION_TRACE(ut_terminate); + /* Free global tables, etc. */ /* Free global GPE blocks and related info structures */ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; @@ -133,10 +239,6 @@ void acpi_ut_subsystem_shutdown(void) acpi_ns_terminate(); - /* Delete the ACPI tables */ - - acpi_tb_terminate(); - /* Close the globals */ acpi_ut_terminate(); diff --git a/trunk/drivers/acpi/utilities/utmath.c b/trunk/drivers/acpi/utilities/utmath.c index 0c56a0d20b29..19d74bedce27 100644 --- a/trunk/drivers/acpi/utilities/utmath.c +++ b/trunk/drivers/acpi/utilities/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utmisc.c b/trunk/drivers/acpi/utilities/utmisc.c index 50133fffe420..6d8a8211be90 100644 --- a/trunk/drivers/acpi/utilities/utmisc.c +++ b/trunk/drivers/acpi/utilities/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,78 +49,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") -/******************************************************************************* - * - * FUNCTION: acpi_ut_validate_exception - * - * PARAMETERS: Status - The acpi_status code to be formatted - * - * RETURN: A string containing the exception text. NULL if exception is - * not valid. - * - * DESCRIPTION: This function validates and translates an ACPI exception into - * an ASCII string. - * - ******************************************************************************/ -const char *acpi_ut_validate_exception(acpi_status status) -{ - acpi_status sub_status; - const char *exception = NULL; - - ACPI_FUNCTION_ENTRY(); - - /* - * Status is composed of two parts, a "type" and an actual code - */ - sub_status = (status & ~AE_CODE_MASK); - - switch (status & AE_CODE_MASK) { - case AE_CODE_ENVIRONMENTAL: - - if (sub_status <= AE_CODE_ENV_MAX) { - exception = acpi_gbl_exception_names_env[sub_status]; - } - break; - - case AE_CODE_PROGRAMMER: - - if (sub_status <= AE_CODE_PGM_MAX) { - exception = - acpi_gbl_exception_names_pgm[sub_status - 1]; - } - break; - - case AE_CODE_ACPI_TABLES: - - if (sub_status <= AE_CODE_TBL_MAX) { - exception = - acpi_gbl_exception_names_tbl[sub_status - 1]; - } - break; - - case AE_CODE_AML: - - if (sub_status <= AE_CODE_AML_MAX) { - exception = - acpi_gbl_exception_names_aml[sub_status - 1]; - } - break; - - case AE_CODE_CONTROL: - - if (sub_status <= AE_CODE_CTRL_MAX) { - exception = - acpi_gbl_exception_names_ctrl[sub_status - 1]; - } - break; - - default: - break; - } - - return (ACPI_CAST_PTR(const char, exception)); -} - /******************************************************************************* * * FUNCTION: acpi_ut_is_aml_table @@ -134,15 +62,14 @@ const char *acpi_ut_validate_exception(acpi_status status) * data tables that do not contain AML code. * ******************************************************************************/ - u8 acpi_ut_is_aml_table(struct acpi_table_header *table) { /* These are the only tables that contain executable AML */ - if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { + if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, PSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) { return (TRUE); } @@ -491,7 +418,7 @@ u32 acpi_ut_dword_byte_swap(u32 value) void acpi_ut_set_integer_width(u8 revision) { - if (revision < 2) { + if (revision <= 1) { /* 32-bit case */ @@ -655,25 +582,26 @@ u8 acpi_ut_valid_acpi_name(u32 name) * ******************************************************************************/ -acpi_name acpi_ut_repair_name(char *name) +acpi_name acpi_ut_repair_name(acpi_name name) { - acpi_native_uint i; + char *name_ptr = ACPI_CAST_PTR(char, &name); char new_name[ACPI_NAME_SIZE]; + acpi_native_uint i; for (i = 0; i < ACPI_NAME_SIZE; i++) { - new_name[i] = name[i]; + new_name[i] = name_ptr[i]; /* * Replace a bad character with something printable, yet technically * still invalid. This prevents any collisions with existing "good" * names in the namespace. */ - if (!acpi_ut_valid_acpi_char(name[i], i)) { + if (!acpi_ut_valid_acpi_char(name_ptr[i], i)) { new_name[i] = '*'; } } - return (*(u32 *) new_name); + return (*ACPI_CAST_PTR(u32, new_name)); } /******************************************************************************* @@ -1068,13 +996,9 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...) { va_list args; - /* - * Removed module_name, line_number, and acpica version, not needed - * for info output - */ - acpi_os_printf("ACPI: "); + acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number); va_start(args, format); acpi_os_vprintf(format, args); - acpi_os_printf("\n"); + acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } diff --git a/trunk/drivers/acpi/utilities/utmutex.c b/trunk/drivers/acpi/utilities/utmutex.c index cbad2ef5987d..180e73ceb6e2 100644 --- a/trunk/drivers/acpi/utilities/utmutex.c +++ b/trunk/drivers/acpi/utilities/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utobject.c b/trunk/drivers/acpi/utilities/utobject.c index 4696124759e1..ba7d8ac702df 100644 --- a/trunk/drivers/acpi/utilities/utobject.c +++ b/trunk/drivers/acpi/utilities/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utresrc.c b/trunk/drivers/acpi/utilities/utresrc.c index e8fe1ba6cc24..5a2de92831d3 100644 --- a/trunk/drivers/acpi/utilities/utresrc.c +++ b/trunk/drivers/acpi/utilities/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utstate.c b/trunk/drivers/acpi/utilities/utstate.c index edcaafad0a31..eaa13d05c859 100644 --- a/trunk/drivers/acpi/utilities/utstate.c +++ b/trunk/drivers/acpi/utilities/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/drivers/acpi/utilities/utxface.c b/trunk/drivers/acpi/utilities/utxface.c index de3276f4f468..3538f69c82a1 100644 --- a/trunk/drivers/acpi/utilities/utxface.c +++ b/trunk/drivers/acpi/utilities/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,7 +67,6 @@ acpi_status acpi_initialize_subsystem(void) ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); - acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); /* Initialize the OS-Dependent layer */ @@ -128,6 +127,20 @@ acpi_status acpi_enable_subsystem(u32 flags) ACPI_FUNCTION_TRACE(acpi_enable_subsystem); + /* + * We must initialize the hardware before we can enable ACPI. + * The values from the FADT are validated here. + */ + if (!(flags & ACPI_NO_HARDWARE_INIT)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "[Init] Initializing ACPI hardware\n")); + + status = acpi_hw_initialize(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + /* Enable ACPI mode */ if (!(flags & ACPI_NO_ACPI_ENABLE)) { @@ -385,6 +398,7 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) { struct acpi_system_info *info_ptr; acpi_status status; + u32 i; ACPI_FUNCTION_TRACE(acpi_get_system_info); @@ -417,7 +431,9 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) /* Timer resolution - 24 or 32 bits */ - if (acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) { + 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; @@ -433,6 +449,13 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) info_ptr->debug_layer = acpi_dbg_layer; info_ptr->debug_level = acpi_dbg_level; + /* Current status of the ACPI tables, per table type */ + + info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1; + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { + info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count; + } + return_ACPI_STATUS(AE_OK); } diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index e0b97add8c63..3d54680d0333 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -32,7 +32,6 @@ #include #include -#include #include #include @@ -57,12 +56,6 @@ #define ACPI_VIDEO_HEAD_INVALID (~0u - 1) #define ACPI_VIDEO_HEAD_END (~0u) -#define MAX_NAME_LEN 20 - -#define ACPI_VIDEO_DISPLAY_CRT 1 -#define ACPI_VIDEO_DISPLAY_TV 2 -#define ACPI_VIDEO_DISPLAY_DVI 3 -#define ACPI_VIDEO_DISPLAY_LCD 4 #define _COMPONENT ACPI_VIDEO_COMPONENT ACPI_MODULE_NAME("acpi_video") @@ -73,14 +66,16 @@ MODULE_LICENSE("GPL"); static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); +static int acpi_video_bus_match(struct acpi_device *device, + struct acpi_driver *driver); static struct acpi_driver acpi_video_bus = { .name = ACPI_VIDEO_DRIVER_NAME, .class = ACPI_VIDEO_CLASS, - .ids = ACPI_VIDEO_HID, .ops = { .add = acpi_video_bus_add, .remove = acpi_video_bus_remove, + .match = acpi_video_bus_match, }, }; @@ -138,21 +133,20 @@ struct acpi_video_device_flags { u8 crt:1; u8 lcd:1; u8 tvout:1; - u8 dvi:1; u8 bios:1; u8 unknown:1; - u8 reserved:2; + u8 reserved:3; }; struct acpi_video_device_cap { u8 _ADR:1; /*Return the unique ID */ u8 _BCL:1; /*Query list of brightness control levels supported */ u8 _BCM:1; /*Set the brightness level */ - u8 _BQC:1; /* Get current brightness level */ u8 _DDC:1; /*Return the EDID for this device */ u8 _DCS:1; /*Return status of output device */ u8 _DGS:1; /*Query graphics state */ u8 _DSS:1; /*Device state set */ + u8 _reserved:1; }; struct acpi_video_device_brightness { @@ -169,8 +163,6 @@ struct acpi_video_device { struct acpi_video_bus *video; struct acpi_device *dev; struct acpi_video_device_brightness *brightness; - struct backlight_device *backlight; - struct backlight_properties *data; }; /* bus */ @@ -265,35 +257,11 @@ static void acpi_video_device_bind(struct acpi_video_bus *video, struct acpi_video_device *device); static int acpi_video_device_enumerate(struct acpi_video_bus *video); static int acpi_video_switch_output(struct acpi_video_bus *video, int event); -static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, - int level); -static int acpi_video_device_lcd_get_level_current( - struct acpi_video_device *device, - unsigned long *level); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); static void acpi_video_switch_brightness(struct acpi_video_device *device, int event); -/*backlight device sysfs support*/ -static int acpi_video_get_brightness(struct backlight_device *bd) -{ - unsigned long cur_level; - struct acpi_video_device *vd = - (struct acpi_video_device *)class_get_devdata(&bd->class_dev); - acpi_video_device_lcd_get_level_current(vd, &cur_level); - return (int) cur_level; -} - -static int acpi_video_set_brightness(struct backlight_device *bd) -{ - int request_level = bd->props->brightness; - struct acpi_video_device *vd = - (struct acpi_video_device *)class_get_devdata(&bd->class_dev); - acpi_video_device_lcd_set_level(vd, request_level); - return 0; -} - /* -------------------------------------------------------------------------- Video Management -------------------------------------------------------------------------- */ @@ -531,7 +499,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) acpi_integer status; acpi_handle h_dummy1; int i; - u32 max_level = 0; union acpi_object *obj = NULL; struct acpi_video_device_brightness *br = NULL; @@ -547,8 +514,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { device->cap._BCM = 1; } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) - device->cap._BQC = 1; if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { device->cap._DDC = 1; } @@ -585,8 +550,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) continue; } br->levels[count] = (u32) o->integer.value; - if (br->levels[count] > max_level) - max_level = br->levels[count]; count++; } out: @@ -605,37 +568,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) kfree(obj); - if (device->cap._BCL && device->cap._BCM && device->cap._BQC){ - unsigned long tmp; - static int count = 0; - char *name; - struct backlight_properties *acpi_video_data; - - name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); - if (!name) - return; - - acpi_video_data = kzalloc( - sizeof(struct backlight_properties), - GFP_KERNEL); - if (!acpi_video_data){ - kfree(name); - return; - } - acpi_video_data->owner = THIS_MODULE; - acpi_video_data->get_brightness = - acpi_video_get_brightness; - acpi_video_data->update_status = - acpi_video_set_brightness; - sprintf(name, "acpi_video%d", count++); - device->data = acpi_video_data; - acpi_video_data->max_brightness = max_level; - acpi_video_device_lcd_get_level_current(device, &tmp); - acpi_video_data->brightness = (int)tmp; - device->backlight = backlight_device_register(name, - NULL, device, acpi_video_data); - kfree(name); - } return; } @@ -736,8 +668,6 @@ static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "LCD\n"); else if (dev->flags.tvout) seq_printf(seq, "TVOUT\n"); - else if (dev->flags.dvi) - seq_printf(seq, "DVI\n"); else seq_printf(seq, "UNKNOWN\n"); @@ -1312,16 +1242,6 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) -------------------------------------------------------------------------- */ /* device interface */ -static struct acpi_video_device_attrib* -acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) -{ - int count; - - for(count = 0; count < video->attached_count; count++) - if((video->attached_array[count].value.int_val & 0xffff) == device_id) - return &(video->attached_array[count].value.attrib); - return NULL; -} static int acpi_video_bus_get_one_device(struct acpi_device *device, @@ -1330,7 +1250,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device, unsigned long device_id; int status; struct acpi_video_device *data; - struct acpi_video_device_attrib* attribute; + if (!device || !video) return -EINVAL; @@ -1351,30 +1271,20 @@ acpi_video_bus_get_one_device(struct acpi_device *device, data->video = video; data->dev = device; - attribute = acpi_video_get_device_attr(video, device_id); - - if((attribute != NULL) && attribute->device_id_scheme) { - switch (attribute->display_type) { - case ACPI_VIDEO_DISPLAY_CRT: - data->flags.crt = 1; - break; - case ACPI_VIDEO_DISPLAY_TV: - data->flags.tvout = 1; - break; - case ACPI_VIDEO_DISPLAY_DVI: - data->flags.dvi = 1; - break; - case ACPI_VIDEO_DISPLAY_LCD: - data->flags.lcd = 1; - break; - default: - data->flags.unknown = 1; - break; - } - if(attribute->bios_can_detect) - data->flags.bios = 1; - } else + switch (device_id & 0xffff) { + case 0x0100: + data->flags.crt = 1; + break; + case 0x0400: + data->flags.lcd = 1; + break; + case 0x0200: + data->flags.tvout = 1; + break; + default: data->flags.unknown = 1; + break; + } acpi_video_device_bind(video, data); acpi_video_device_find_cap(data); @@ -1678,10 +1588,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) status = acpi_remove_notify_handler(device->dev->handle, ACPI_DEVICE_NOTIFY, acpi_video_device_notify); - if (device->backlight){ - backlight_device_unregister(device->backlight); - kfree(device->data); - } + return 0; } @@ -1883,6 +1790,39 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } +static int +acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver) +{ + acpi_handle h_dummy1; + acpi_handle h_dummy2; + acpi_handle h_dummy3; + + + if (!device || !driver) + return -EINVAL; + + /* Since there is no HID, CID for ACPI Video drivers, we have + * to check well known required nodes for each feature we support. + */ + + /* Does this device able to support video switching ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) + return 0; + + /* Does this device able to retrieve a video ROM ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) + return 0; + + /* Does this device able to configure which video head to be POSTed ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) + return 0; + + return -ENODEV; +} + static int __init acpi_video_init(void) { int result = 0; diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index a7b33d2f5991..f1afd26a509f 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -1802,7 +1802,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) return -ENODEV; } - if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) addr_space = IPMI_MEM_ADDR_SPACE; else addr_space = IPMI_IO_ADDR_SPACE; @@ -1848,19 +1848,19 @@ static __devinit int try_init_acpi(struct SPMITable *spmi) info->irq_setup = NULL; } - if (spmi->addr.bit_width) { + if (spmi->addr.register_bit_width) { /* A (hopefully) properly formed register bit width. */ - info->io.regspacing = spmi->addr.bit_width / 8; + info->io.regspacing = spmi->addr.register_bit_width / 8; } else { info->io.regspacing = DEFAULT_REGSPACING; } info->io.regsize = info->io.regspacing; - info->io.regshift = spmi->addr.bit_offset; + info->io.regshift = spmi->addr.register_bit_offset; - if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { info->io_setup = mem_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; - } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { + } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { info->io_setup = port_setup; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { @@ -1888,8 +1888,10 @@ static __devinit void acpi_find_bmc(void) return; for (i = 0; ; i++) { - status = acpi_get_table(ACPI_SIG_SPMI, i+1, - (struct acpi_table_header **)&spmi); + status = acpi_get_firmware_table("SPMI", i+1, + ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) + &spmi); if (status != AE_OK) return; diff --git a/trunk/drivers/char/tpm/tpm_bios.c b/trunk/drivers/char/tpm/tpm_bios.c index 7fca5f470beb..a611972024e6 100644 --- a/trunk/drivers/char/tpm/tpm_bios.c +++ b/trunk/drivers/char/tpm/tpm_bios.c @@ -372,8 +372,10 @@ static int read_log(struct tpm_bios_log *log) } /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ - status = acpi_get_table(ACPI_SIG_TCPA, 1, - (struct acpi_table_header **)&buff); + status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, + ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) + &buff); if (ACPI_FAILURE(status)) { printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", @@ -407,7 +409,7 @@ static int read_log(struct tpm_bios_log *log) log->bios_event_log_end = log->bios_event_log + len; - virt = acpi_os_map_memory(start, len); + acpi_os_map_memory(start, len, (void *) &virt); memcpy(log->bios_event_log, virt, len); diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index ff8c4beaace4..879250d3d069 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -51,8 +51,6 @@ config CRYPTO_DEV_PADLOCK_SHA If unsure say M. The compiled module will be called padlock-sha.ko -source "arch/s390/crypto/Kconfig" - config CRYPTO_DEV_GEODE tristate "Support for the Geode LX AES engine" depends on CRYPTO && X86_32 && PCI diff --git a/trunk/drivers/firmware/pcdp.c b/trunk/drivers/firmware/pcdp.c index 2b4b76e8bd72..c2ad72fefd9d 100644 --- a/trunk/drivers/firmware/pcdp.c +++ b/trunk/drivers/firmware/pcdp.c @@ -26,7 +26,7 @@ setup_serial_console(struct pcdp_uart *uart) static char options[64], *p = options; char parity; - mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); + mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); p += sprintf(p, "console=uart,%s,0x%lx", mmio ? "mmio" : "io", uart->addr.address); if (uart->baud) { diff --git a/trunk/drivers/hid/Kconfig b/trunk/drivers/hid/Kconfig index 850788f4dd2e..ec796ad087df 100644 --- a/trunk/drivers/hid/Kconfig +++ b/trunk/drivers/hid/Kconfig @@ -22,19 +22,5 @@ config HID If unsure, say Y -config HID_DEBUG - bool "HID debugging support" - depends on HID - ---help--- - This option lets the HID layer output diagnostics about its internal - state, resolve HID usages, dump HID fields, etc. Individual HID drivers - use this debugging facility to output information about individual HID - devices, etc. - - This feature is useful for those who are either debugging the HID parser - or any HID hardware device. - - If unsure, say N - endmenu diff --git a/trunk/drivers/hid/Makefile b/trunk/drivers/hid/Makefile index 52e97d8f3c95..6432392110bf 100644 --- a/trunk/drivers/hid/Makefile +++ b/trunk/drivers/hid/Makefile @@ -1,8 +1,15 @@ # # Makefile for the HID driver # -hid-objs := hid-core.o hid-input.o + +# Multipart objects. +hid-objs := hid-core.o hid-input.o + +# Optional parts of multipart objects. obj-$(CONFIG_HID) += hid.o -hid-$(CONFIG_HID_DEBUG) += hid-debug.o + +ifeq ($(CONFIG_INPUT_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index 8c7d48eff7b7..49f18f5b2514 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -28,9 +28,11 @@ #include #include +#undef DEBUG +#undef DEBUG_DATA + #include #include -#include /* * Version Information @@ -949,7 +951,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i return -1; } -#ifdef CONFIG_HID_DEBUG +#ifdef DEBUG_DATA printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); #endif @@ -959,7 +961,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i size--; } -#ifdef CONFIG_HID_DEBUG +#ifdef DEBUG_DATA { int i; printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); diff --git a/trunk/drivers/hid/hid-debug.c b/trunk/drivers/hid/hid-debug.c deleted file mode 100644 index 89241be4ec9b..000000000000 --- a/trunk/drivers/hid/hid-debug.c +++ /dev/null @@ -1,764 +0,0 @@ -/* - * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $ - * - * (c) 1999 Andreas Gal - * (c) 2000-2001 Vojtech Pavlik - * (c) 2007 Jiri Kosina - * - * Some debug stuff for the HID parser. - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include - -struct hid_usage_entry { - unsigned page; - unsigned usage; - char *description; -}; - -static const struct hid_usage_entry hid_usage_table[] = { - { 0, 0, "Undefined" }, - { 1, 0, "GenericDesktop" }, - {0, 0x01, "Pointer"}, - {0, 0x02, "Mouse"}, - {0, 0x04, "Joystick"}, - {0, 0x05, "GamePad"}, - {0, 0x06, "Keyboard"}, - {0, 0x07, "Keypad"}, - {0, 0x08, "MultiAxis"}, - {0, 0x30, "X"}, - {0, 0x31, "Y"}, - {0, 0x32, "Z"}, - {0, 0x33, "Rx"}, - {0, 0x34, "Ry"}, - {0, 0x35, "Rz"}, - {0, 0x36, "Slider"}, - {0, 0x37, "Dial"}, - {0, 0x38, "Wheel"}, - {0, 0x39, "HatSwitch"}, - {0, 0x3a, "CountedBuffer"}, - {0, 0x3b, "ByteCount"}, - {0, 0x3c, "MotionWakeup"}, - {0, 0x3d, "Start"}, - {0, 0x3e, "Select"}, - {0, 0x40, "Vx"}, - {0, 0x41, "Vy"}, - {0, 0x42, "Vz"}, - {0, 0x43, "Vbrx"}, - {0, 0x44, "Vbry"}, - {0, 0x45, "Vbrz"}, - {0, 0x46, "Vno"}, - {0, 0x80, "SystemControl"}, - {0, 0x81, "SystemPowerDown"}, - {0, 0x82, "SystemSleep"}, - {0, 0x83, "SystemWakeUp"}, - {0, 0x84, "SystemContextMenu"}, - {0, 0x85, "SystemMainMenu"}, - {0, 0x86, "SystemAppMenu"}, - {0, 0x87, "SystemMenuHelp"}, - {0, 0x88, "SystemMenuExit"}, - {0, 0x89, "SystemMenuSelect"}, - {0, 0x8a, "SystemMenuRight"}, - {0, 0x8b, "SystemMenuLeft"}, - {0, 0x8c, "SystemMenuUp"}, - {0, 0x8d, "SystemMenuDown"}, - {0, 0x90, "D-PadUp"}, - {0, 0x91, "D-PadDown"}, - {0, 0x92, "D-PadRight"}, - {0, 0x93, "D-PadLeft"}, - { 2, 0, "Simulation" }, - {0, 0xb0, "Aileron"}, - {0, 0xb1, "AileronTrim"}, - {0, 0xb2, "Anti-Torque"}, - {0, 0xb3, "Autopilot"}, - {0, 0xb4, "Chaff"}, - {0, 0xb5, "Collective"}, - {0, 0xb6, "DiveBrake"}, - {0, 0xb7, "ElectronicCountermeasures"}, - {0, 0xb8, "Elevator"}, - {0, 0xb9, "ElevatorTrim"}, - {0, 0xba, "Rudder"}, - {0, 0xbb, "Throttle"}, - {0, 0xbc, "FlightCommunications"}, - {0, 0xbd, "FlareRelease"}, - {0, 0xbe, "LandingGear"}, - {0, 0xbf, "ToeBrake"}, - { 7, 0, "Keyboard" }, - { 8, 0, "LED" }, - {0, 0x01, "NumLock"}, - {0, 0x02, "CapsLock"}, - {0, 0x03, "ScrollLock"}, - {0, 0x04, "Compose"}, - {0, 0x05, "Kana"}, - {0, 0x4b, "GenericIndicator"}, - { 9, 0, "Button" }, - { 10, 0, "Ordinal" }, - { 12, 0, "Consumer" }, - {0, 0x238, "HorizontalWheel"}, - { 13, 0, "Digitizers" }, - {0, 0x01, "Digitizer"}, - {0, 0x02, "Pen"}, - {0, 0x03, "LightPen"}, - {0, 0x04, "TouchScreen"}, - {0, 0x05, "TouchPad"}, - {0, 0x20, "Stylus"}, - {0, 0x21, "Puck"}, - {0, 0x22, "Finger"}, - {0, 0x30, "TipPressure"}, - {0, 0x31, "BarrelPressure"}, - {0, 0x32, "InRange"}, - {0, 0x33, "Touch"}, - {0, 0x34, "UnTouch"}, - {0, 0x35, "Tap"}, - {0, 0x39, "TabletFunctionKey"}, - {0, 0x3a, "ProgramChangeKey"}, - {0, 0x3c, "Invert"}, - {0, 0x42, "TipSwitch"}, - {0, 0x43, "SecondaryTipSwitch"}, - {0, 0x44, "BarrelSwitch"}, - {0, 0x45, "Eraser"}, - {0, 0x46, "TabletPick"}, - { 15, 0, "PhysicalInterfaceDevice" }, - {0, 0x00, "Undefined"}, - {0, 0x01, "Physical_Interface_Device"}, - {0, 0x20, "Normal"}, - {0, 0x21, "Set_Effect_Report"}, - {0, 0x22, "Effect_Block_Index"}, - {0, 0x23, "Parameter_Block_Offset"}, - {0, 0x24, "ROM_Flag"}, - {0, 0x25, "Effect_Type"}, - {0, 0x26, "ET_Constant_Force"}, - {0, 0x27, "ET_Ramp"}, - {0, 0x28, "ET_Custom_Force_Data"}, - {0, 0x30, "ET_Square"}, - {0, 0x31, "ET_Sine"}, - {0, 0x32, "ET_Triangle"}, - {0, 0x33, "ET_Sawtooth_Up"}, - {0, 0x34, "ET_Sawtooth_Down"}, - {0, 0x40, "ET_Spring"}, - {0, 0x41, "ET_Damper"}, - {0, 0x42, "ET_Inertia"}, - {0, 0x43, "ET_Friction"}, - {0, 0x50, "Duration"}, - {0, 0x51, "Sample_Period"}, - {0, 0x52, "Gain"}, - {0, 0x53, "Trigger_Button"}, - {0, 0x54, "Trigger_Repeat_Interval"}, - {0, 0x55, "Axes_Enable"}, - {0, 0x56, "Direction_Enable"}, - {0, 0x57, "Direction"}, - {0, 0x58, "Type_Specific_Block_Offset"}, - {0, 0x59, "Block_Type"}, - {0, 0x5A, "Set_Envelope_Report"}, - {0, 0x5B, "Attack_Level"}, - {0, 0x5C, "Attack_Time"}, - {0, 0x5D, "Fade_Level"}, - {0, 0x5E, "Fade_Time"}, - {0, 0x5F, "Set_Condition_Report"}, - {0, 0x60, "CP_Offset"}, - {0, 0x61, "Positive_Coefficient"}, - {0, 0x62, "Negative_Coefficient"}, - {0, 0x63, "Positive_Saturation"}, - {0, 0x64, "Negative_Saturation"}, - {0, 0x65, "Dead_Band"}, - {0, 0x66, "Download_Force_Sample"}, - {0, 0x67, "Isoch_Custom_Force_Enable"}, - {0, 0x68, "Custom_Force_Data_Report"}, - {0, 0x69, "Custom_Force_Data"}, - {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, - {0, 0x6B, "Set_Custom_Force_Report"}, - {0, 0x6C, "Custom_Force_Data_Offset"}, - {0, 0x6D, "Sample_Count"}, - {0, 0x6E, "Set_Periodic_Report"}, - {0, 0x6F, "Offset"}, - {0, 0x70, "Magnitude"}, - {0, 0x71, "Phase"}, - {0, 0x72, "Period"}, - {0, 0x73, "Set_Constant_Force_Report"}, - {0, 0x74, "Set_Ramp_Force_Report"}, - {0, 0x75, "Ramp_Start"}, - {0, 0x76, "Ramp_End"}, - {0, 0x77, "Effect_Operation_Report"}, - {0, 0x78, "Effect_Operation"}, - {0, 0x79, "Op_Effect_Start"}, - {0, 0x7A, "Op_Effect_Start_Solo"}, - {0, 0x7B, "Op_Effect_Stop"}, - {0, 0x7C, "Loop_Count"}, - {0, 0x7D, "Device_Gain_Report"}, - {0, 0x7E, "Device_Gain"}, - {0, 0x7F, "PID_Pool_Report"}, - {0, 0x80, "RAM_Pool_Size"}, - {0, 0x81, "ROM_Pool_Size"}, - {0, 0x82, "ROM_Effect_Block_Count"}, - {0, 0x83, "Simultaneous_Effects_Max"}, - {0, 0x84, "Pool_Alignment"}, - {0, 0x85, "PID_Pool_Move_Report"}, - {0, 0x86, "Move_Source"}, - {0, 0x87, "Move_Destination"}, - {0, 0x88, "Move_Length"}, - {0, 0x89, "PID_Block_Load_Report"}, - {0, 0x8B, "Block_Load_Status"}, - {0, 0x8C, "Block_Load_Success"}, - {0, 0x8D, "Block_Load_Full"}, - {0, 0x8E, "Block_Load_Error"}, - {0, 0x8F, "Block_Handle"}, - {0, 0x90, "PID_Block_Free_Report"}, - {0, 0x91, "Type_Specific_Block_Handle"}, - {0, 0x92, "PID_State_Report"}, - {0, 0x94, "Effect_Playing"}, - {0, 0x95, "PID_Device_Control_Report"}, - {0, 0x96, "PID_Device_Control"}, - {0, 0x97, "DC_Enable_Actuators"}, - {0, 0x98, "DC_Disable_Actuators"}, - {0, 0x99, "DC_Stop_All_Effects"}, - {0, 0x9A, "DC_Device_Reset"}, - {0, 0x9B, "DC_Device_Pause"}, - {0, 0x9C, "DC_Device_Continue"}, - {0, 0x9F, "Device_Paused"}, - {0, 0xA0, "Actuators_Enabled"}, - {0, 0xA4, "Safety_Switch"}, - {0, 0xA5, "Actuator_Override_Switch"}, - {0, 0xA6, "Actuator_Power"}, - {0, 0xA7, "Start_Delay"}, - {0, 0xA8, "Parameter_Block_Size"}, - {0, 0xA9, "Device_Managed_Pool"}, - {0, 0xAA, "Shared_Parameter_Blocks"}, - {0, 0xAB, "Create_New_Effect_Report"}, - {0, 0xAC, "RAM_Pool_Available"}, - { 0x84, 0, "Power Device" }, - { 0x84, 0x02, "PresentStatus" }, - { 0x84, 0x03, "ChangeStatus" }, - { 0x84, 0x04, "UPS" }, - { 0x84, 0x05, "PowerSupply" }, - { 0x84, 0x10, "BatterySystem" }, - { 0x84, 0x11, "BatterySystemID" }, - { 0x84, 0x12, "Battery" }, - { 0x84, 0x13, "BatteryID" }, - { 0x84, 0x14, "Charger" }, - { 0x84, 0x15, "ChargerID" }, - { 0x84, 0x16, "PowerConverter" }, - { 0x84, 0x17, "PowerConverterID" }, - { 0x84, 0x18, "OutletSystem" }, - { 0x84, 0x19, "OutletSystemID" }, - { 0x84, 0x1a, "Input" }, - { 0x84, 0x1b, "InputID" }, - { 0x84, 0x1c, "Output" }, - { 0x84, 0x1d, "OutputID" }, - { 0x84, 0x1e, "Flow" }, - { 0x84, 0x1f, "FlowID" }, - { 0x84, 0x20, "Outlet" }, - { 0x84, 0x21, "OutletID" }, - { 0x84, 0x22, "Gang" }, - { 0x84, 0x24, "PowerSummary" }, - { 0x84, 0x25, "PowerSummaryID" }, - { 0x84, 0x30, "Voltage" }, - { 0x84, 0x31, "Current" }, - { 0x84, 0x32, "Frequency" }, - { 0x84, 0x33, "ApparentPower" }, - { 0x84, 0x35, "PercentLoad" }, - { 0x84, 0x40, "ConfigVoltage" }, - { 0x84, 0x41, "ConfigCurrent" }, - { 0x84, 0x43, "ConfigApparentPower" }, - { 0x84, 0x53, "LowVoltageTransfer" }, - { 0x84, 0x54, "HighVoltageTransfer" }, - { 0x84, 0x56, "DelayBeforeStartup" }, - { 0x84, 0x57, "DelayBeforeShutdown" }, - { 0x84, 0x58, "Test" }, - { 0x84, 0x5a, "AudibleAlarmControl" }, - { 0x84, 0x60, "Present" }, - { 0x84, 0x61, "Good" }, - { 0x84, 0x62, "InternalFailure" }, - { 0x84, 0x65, "Overload" }, - { 0x84, 0x66, "OverCharged" }, - { 0x84, 0x67, "OverTemperature" }, - { 0x84, 0x68, "ShutdownRequested" }, - { 0x84, 0x69, "ShutdownImminent" }, - { 0x84, 0x6b, "SwitchOn/Off" }, - { 0x84, 0x6c, "Switchable" }, - { 0x84, 0x6d, "Used" }, - { 0x84, 0x6e, "Boost" }, - { 0x84, 0x73, "CommunicationLost" }, - { 0x84, 0xfd, "iManufacturer" }, - { 0x84, 0xfe, "iProduct" }, - { 0x84, 0xff, "iSerialNumber" }, - { 0x85, 0, "Battery System" }, - { 0x85, 0x01, "SMBBatteryMode" }, - { 0x85, 0x02, "SMBBatteryStatus" }, - { 0x85, 0x03, "SMBAlarmWarning" }, - { 0x85, 0x04, "SMBChargerMode" }, - { 0x85, 0x05, "SMBChargerStatus" }, - { 0x85, 0x06, "SMBChargerSpecInfo" }, - { 0x85, 0x07, "SMBSelectorState" }, - { 0x85, 0x08, "SMBSelectorPresets" }, - { 0x85, 0x09, "SMBSelectorInfo" }, - { 0x85, 0x29, "RemainingCapacityLimit" }, - { 0x85, 0x2c, "CapacityMode" }, - { 0x85, 0x42, "BelowRemainingCapacityLimit" }, - { 0x85, 0x44, "Charging" }, - { 0x85, 0x45, "Discharging" }, - { 0x85, 0x4b, "NeedReplacement" }, - { 0x85, 0x66, "RemainingCapacity" }, - { 0x85, 0x68, "RunTimeToEmpty" }, - { 0x85, 0x6a, "AverageTimeToFull" }, - { 0x85, 0x83, "DesignCapacity" }, - { 0x85, 0x85, "ManufacturerDate" }, - { 0x85, 0x89, "iDeviceChemistry" }, - { 0x85, 0x8b, "Rechargable" }, - { 0x85, 0x8f, "iOEMInformation" }, - { 0x85, 0x8d, "CapacityGranularity1" }, - { 0x85, 0xd0, "ACPresent" }, - /* pages 0xff00 to 0xffff are vendor-specific */ - { 0xffff, 0, "Vendor-specific-FF" }, - { 0, 0, NULL } -}; - -static void resolv_usage_page(unsigned page) { - const struct hid_usage_entry *p; - - for (p = hid_usage_table; p->description; p++) - if (p->page == page) { - printk("%s", p->description); - return; - } - printk("%04x", page); -} - -void hid_resolv_usage(unsigned usage) { - const struct hid_usage_entry *p; - - resolv_usage_page(usage >> 16); - printk("."); - for (p = hid_usage_table; p->description; p++) - if (p->page == (usage >> 16)) { - for(++p; p->description && p->usage != 0; p++) - if (p->usage == (usage & 0xffff)) { - printk("%s", p->description); - return; - } - break; - } - printk("%04x", usage & 0xffff); -} -EXPORT_SYMBOL_GPL(hid_resolv_usage); - -__inline__ static void tab(int n) { - while (n--) printk(" "); -} - -void hid_dump_field(struct hid_field *field, int n) { - int j; - - if (field->physical) { - tab(n); - printk("Physical("); - hid_resolv_usage(field->physical); printk(")\n"); - } - if (field->logical) { - tab(n); - printk("Logical("); - hid_resolv_usage(field->logical); printk(")\n"); - } - tab(n); printk("Usage(%d)\n", field->maxusage); - for (j = 0; j < field->maxusage; j++) { - tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n"); - } - if (field->logical_minimum != field->logical_maximum) { - tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); - tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); - } - if (field->physical_minimum != field->physical_maximum) { - tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); - tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); - } - if (field->unit_exponent) { - tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); - } - if (field->unit) { - char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; - char *units[5][8] = { - { "None", "None", "None", "None", "None", "None", "None", "None" }, - { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, - { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } - }; - - int i; - int sys; - __u32 data = field->unit; - - /* First nibble tells us which system we're in. */ - sys = data & 0xf; - data >>= 4; - - if(sys > 4) { - tab(n); printk("Unit(Invalid)\n"); - } - else { - int earlier_unit = 0; - - tab(n); printk("Unit(%s : ", systems[sys]); - - for (i=1 ; i>= 4; - if (nibble != 0) { - if(earlier_unit++ > 0) - printk("*"); - printk("%s", units[sys][i]); - if(nibble != 1) { - /* This is a _signed_ nibble(!) */ - - int val = nibble & 0x7; - if(nibble & 0x08) - val = -((0x7 & ~val) +1); - printk("^%d", val); - } - } - } - printk(")\n"); - } - } - tab(n); printk("Report Size(%u)\n", field->report_size); - tab(n); printk("Report Count(%u)\n", field->report_count); - tab(n); printk("Report Offset(%u)\n", field->report_offset); - - tab(n); printk("Flags( "); - j = field->flags; - printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); - printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); - printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); - printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); - printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); - printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); - printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); - printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); - printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); - printk(")\n"); -} -EXPORT_SYMBOL_GPL(hid_dump_field); - -void hid_dump_device(struct hid_device *device) { - struct hid_report_enum *report_enum; - struct hid_report *report; - struct list_head *list; - unsigned i,k; - static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - report_enum = device->report_enum + i; - list = report_enum->report_list.next; - while (list != &report_enum->report_list) { - report = (struct hid_report *) list; - tab(2); - printk("%s", table[i]); - if (report->id) - printk("(%d)", report->id); - printk("[%s]", table[report->type]); - printk("\n"); - for (k = 0; k < report->maxfield; k++) { - tab(4); - printk("Field(%d)\n", k); - hid_dump_field(report->field[k], 6); - } - list = list->next; - } - } -} -EXPORT_SYMBOL_GPL(hid_dump_device); - -void hid_dump_input(struct hid_usage *usage, __s32 value) { - printk("hid-debug: input "); - hid_resolv_usage(usage->hid); - printk(" = %d\n", value); -} -EXPORT_SYMBOL_GPL(hid_dump_input); - -static char *events[EV_MAX + 1] = { - [EV_SYN] = "Sync", [EV_KEY] = "Key", - [EV_REL] = "Relative", [EV_ABS] = "Absolute", - [EV_MSC] = "Misc", [EV_LED] = "LED", - [EV_SND] = "Sound", [EV_REP] = "Repeat", - [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", - [EV_FF_STATUS] = "ForceFeedbackStatus", -}; - -static char *syncs[2] = { - [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", -}; -static char *keys[KEY_MAX + 1] = { - [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", - [KEY_1] = "1", [KEY_2] = "2", - [KEY_3] = "3", [KEY_4] = "4", - [KEY_5] = "5", [KEY_6] = "6", - [KEY_7] = "7", [KEY_8] = "8", - [KEY_9] = "9", [KEY_0] = "0", - [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", - [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", - [KEY_Q] = "Q", [KEY_W] = "W", - [KEY_E] = "E", [KEY_R] = "R", - [KEY_T] = "T", [KEY_Y] = "Y", - [KEY_U] = "U", [KEY_I] = "I", - [KEY_O] = "O", [KEY_P] = "P", - [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", - [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", - [KEY_A] = "A", [KEY_S] = "S", - [KEY_D] = "D", [KEY_F] = "F", - [KEY_G] = "G", [KEY_H] = "H", - [KEY_J] = "J", [KEY_K] = "K", - [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", - [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", - [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", - [KEY_Z] = "Z", [KEY_X] = "X", - [KEY_C] = "C", [KEY_V] = "V", - [KEY_B] = "B", [KEY_N] = "N", - [KEY_M] = "M", [KEY_COMMA] = "Comma", - [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", - [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", - [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", - [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", - [KEY_F2] = "F2", [KEY_F3] = "F3", - [KEY_F4] = "F4", [KEY_F5] = "F5", - [KEY_F6] = "F6", [KEY_F7] = "F7", - [KEY_F8] = "F8", [KEY_F9] = "F9", - [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", - [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", - [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", - [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", - [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", - [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", - [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", - [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", - [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", - [KEY_F11] = "F11", [KEY_F12] = "F12", - [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", - [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", - [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", - [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", - [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", - [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", - [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", - [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", - [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", - [KEY_END] = "End", [KEY_DOWN] = "Down", - [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", - [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", - [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", - [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", - [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", - [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", - [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", - [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", - [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", - [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", - [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", - [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", - [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", - [KEY_FIND] = "Find", [KEY_CUT] = "Cut", - [KEY_HELP] = "Help", [KEY_MENU] = "Menu", - [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", - [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", - [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", - [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", - [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", - [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", - [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", - [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", - [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", - [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", - [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", - [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", - [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", - [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", - [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", - [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", - [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", - [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", - [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", - [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", - [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New", - [KEY_REDO] = "Redo", [KEY_F13] = "F13", - [KEY_F14] = "F14", [KEY_F15] = "F15", - [KEY_F16] = "F16", [KEY_F17] = "F17", - [KEY_F18] = "F18", [KEY_F19] = "F19", - [KEY_F20] = "F20", [KEY_F21] = "F21", - [KEY_F22] = "F22", [KEY_F23] = "F23", - [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", - [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", - [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", - [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", - [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", - [KEY_PRINT] = "Print", [KEY_HP] = "HP", - [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", - [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", - [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", - [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", - [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", - [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", - [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", - [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", - [BTN_0] = "Btn0", [BTN_1] = "Btn1", - [BTN_2] = "Btn2", [BTN_3] = "Btn3", - [BTN_4] = "Btn4", [BTN_5] = "Btn5", - [BTN_6] = "Btn6", [BTN_7] = "Btn7", - [BTN_8] = "Btn8", [BTN_9] = "Btn9", - [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", - [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", - [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", - [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", - [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", - [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", - [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", - [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", - [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", - [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", - [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", - [BTN_B] = "BtnB", [BTN_C] = "BtnC", - [BTN_X] = "BtnX", [BTN_Y] = "BtnY", - [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", - [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", - [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", - [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", - [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", - [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", - [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", - [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", - [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", - [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", - [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", - [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", - [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", - [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", - [KEY_OPTION] = "Option", [KEY_INFO] = "Info", - [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", - [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", - [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", - [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", - [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", - [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", - [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", - [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", - [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", - [KEY_TV] = "TV", [KEY_TV2] = "TV2", - [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", - [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", - [KEY_CD] = "CD", [KEY_TAPE] = "Tape", - [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", - [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", - [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", - [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", - [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", - [KEY_LIST] = "List", [KEY_MEMO] = "Memo", - [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", - [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", - [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", - [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", - [KEY_LAST] = "Last", [KEY_AB] = "AB", - [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", - [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", - [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", - [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", - [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", - [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", - [KEY_DEL_LINE] = "DeleteLine", - [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", - [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", - [KEY_DOCUMENTS] = "Documents", - [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", - [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", - [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", - [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F", - [KEY_FN_S] = "Fn+S", - [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2", - [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4", - [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6", - [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8", - [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10", - [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12", - [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle", - [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", - [KEY_KBDILLUMUP] = "KbdIlluminationUp", - [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", -}; - -static char *relatives[REL_MAX + 1] = { - [REL_X] = "X", [REL_Y] = "Y", - [REL_Z] = "Z", [REL_RX] = "Rx", - [REL_RY] = "Ry", [REL_RZ] = "Rz", - [REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial", - [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", -}; - -static char *absolutes[ABS_MAX + 1] = { - [ABS_X] = "X", [ABS_Y] = "Y", - [ABS_Z] = "Z", [ABS_RX] = "Rx", - [ABS_RY] = "Ry", [ABS_RZ] = "Rz", - [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", - [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", - [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", - [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", - [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", - [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", - [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", - [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", - [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", - [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", -}; - -static char *misc[MSC_MAX + 1] = { - [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", - [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" -}; - -static char *leds[LED_MAX + 1] = { - [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", - [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", - [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", - [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", - [LED_MISC] = "Misc", -}; - -static char *repeats[REP_MAX + 1] = { - [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" -}; - -static char *sounds[SND_MAX + 1] = { - [SND_CLICK] = "Click", [SND_BELL] = "Bell", - [SND_TONE] = "Tone" -}; - -static char **names[EV_MAX + 1] = { - [EV_SYN] = syncs, [EV_KEY] = keys, - [EV_REL] = relatives, [EV_ABS] = absolutes, - [EV_MSC] = misc, [EV_LED] = leds, - [EV_SND] = sounds, [EV_REP] = repeats, -}; - -void hid_resolv_event(__u8 type, __u16 code) { - - printk("%s.%s", events[type] ? events[type] : "?", - names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); -} -EXPORT_SYMBOL_GPL(hid_resolv_event); - diff --git a/trunk/drivers/hid/hid-input.c b/trunk/drivers/hid/hid-input.c index 25d180a24fc4..c7a6833f6821 100644 --- a/trunk/drivers/hid/hid-input.c +++ b/trunk/drivers/hid/hid-input.c @@ -31,8 +31,9 @@ #include #include +#undef DEBUG + #include -#include static int hid_pb_fnmode = 1; module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644); @@ -251,9 +252,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel field->hidinput = hidinput; -#ifdef CONFIG_HID_DEBUG +#ifdef DEBUG printk(KERN_DEBUG "Mapping: "); - hid_resolv_usage(usage->hid); + resolv_usage(usage->hid); printk(" ---> "); #endif @@ -681,14 +682,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel field->dpad = usage->code; } - hid_resolv_event(usage->type, usage->code); -#ifdef CONFIG_HID_DEBUG +#ifdef DEBUG + resolv_event(usage->type, usage->code); printk("\n"); #endif return; ignore: -#ifdef CONFIG_HID_DEBUG +#ifdef DEBUG printk("IGNORED\n"); #endif return; @@ -803,18 +804,6 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int } EXPORT_SYMBOL_GPL(hidinput_find_field); -static int hidinput_open(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - return hid->hid_open(hid); -} - -static void hidinput_close(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - hid->hid_close(hid); -} - /* * Register the input device; print a message. * Configure the input layer interface @@ -827,7 +816,6 @@ int hidinput_connect(struct hid_device *hid) struct hid_input *hidinput = NULL; struct input_dev *input_dev; int i, j, k; - int max_report_type = HID_OUTPUT_REPORT; INIT_LIST_HEAD(&hid->inputs); @@ -840,10 +828,7 @@ int hidinput_connect(struct hid_device *hid) if (i == hid->maxcollection) return -1; - if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) - max_report_type = HID_INPUT_REPORT; - - for (k = HID_INPUT_REPORT; k <= max_report_type; k++) + for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) list_for_each_entry(report, &hid->report_enum[k].report_list, list) { if (!report->maxfield) @@ -861,8 +846,8 @@ int hidinput_connect(struct hid_device *hid) input_dev->private = hid; input_dev->event = hid->hidinput_input_event; - input_dev->open = hidinput_open; - input_dev->close = hidinput_close; + input_dev->open = hid->hidinput_open; + input_dev->close = hid->hidinput_close; input_dev->name = hid->name; input_dev->phys = hid->phys; diff --git a/trunk/drivers/infiniband/core/addr.c b/trunk/drivers/infiniband/core/addr.c index d2bb5a9a303f..af939796750d 100644 --- a/trunk/drivers/infiniband/core/addr.c +++ b/trunk/drivers/infiniband/core/addr.c @@ -360,7 +360,8 @@ static int netevent_callback(struct notifier_block *self, unsigned long event, if (event == NETEVENT_NEIGH_UPDATE) { struct neighbour *neigh = ctx; - if (neigh->nud_state & NUD_VALID) { + if (neigh->dev->type == ARPHRD_INFINIBAND && + (neigh->nud_state & NUD_VALID)) { set_timeout(jiffies); } } diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index 13efd4170349..5ed141ebd1c8 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -642,8 +642,7 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info, spin_unlock_irqrestore(&qp_info->snoop_lock, flags); } -static void build_smp_wc(struct ib_qp *qp, - u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, +static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, struct ib_wc *wc) { memset(wc, 0, sizeof *wc); @@ -653,7 +652,7 @@ static void build_smp_wc(struct ib_qp *qp, wc->pkey_index = pkey_index; wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh); wc->src_qp = IB_QP0; - wc->qp = qp; + wc->qp_num = IB_QP0; wc->slid = slid; wc->sl = 0; wc->dlid_path_bits = 0; @@ -714,8 +713,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, goto out; } - build_smp_wc(mad_agent_priv->agent.qp, - send_wr->wr_id, be16_to_cpu(smp->dr_slid), + build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid), send_wr->wr.ud.pkey_index, send_wr->wr.ud.port_num, &mad_wc); @@ -2357,8 +2355,7 @@ static void local_completions(struct work_struct *work) * Defined behavior is to complete response * before request */ - build_smp_wc(recv_mad_agent->agent.qp, - (unsigned long) local->mad_send_wr, + build_smp_wc((unsigned long) local->mad_send_wr, be16_to_cpu(IB_LID_PERMISSIVE), 0, recv_mad_agent->agent.port_num, &wc); diff --git a/trunk/drivers/infiniband/core/uverbs_cmd.c b/trunk/drivers/infiniband/core/uverbs_cmd.c index df1efbc10882..743247ec065e 100644 --- a/trunk/drivers/infiniband/core/uverbs_cmd.c +++ b/trunk/drivers/infiniband/core/uverbs_cmd.c @@ -933,7 +933,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, resp->wc[i].vendor_err = wc[i].vendor_err; resp->wc[i].byte_len = wc[i].byte_len; resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; - resp->wc[i].qp_num = wc[i].qp->qp_num; + resp->wc[i].qp_num = wc[i].qp_num; resp->wc[i].src_qp = wc[i].src_qp; resp->wc[i].wc_flags = wc[i].wc_flags; resp->wc[i].pkey_index = wc[i].pkey_index; diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_cq.c b/trunk/drivers/infiniband/hw/amso1100/c2_cq.c index 5175c99ee586..05c9154d46f4 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_cq.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_cq.c @@ -153,7 +153,7 @@ static inline int c2_poll_one(struct c2_dev *c2dev, entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); entry->wr_id = ce->hdr.context; - entry->qp = &qp->ibqp; + entry->qp_num = ce->handle; entry->wc_flags = 0; entry->slid = 0; entry->sl = 0; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index cf95ee474b0f..1c722032319c 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -119,14 +119,13 @@ struct ehca_qp { struct ipz_qp_handle ipz_qp_handle; struct ehca_pfqp pf; struct ib_qp_init_attr init_attr; + u64 uspace_squeue; + u64 uspace_rqueue; + u64 uspace_fwh; struct ehca_cq *send_cq; struct ehca_cq *recv_cq; unsigned int sqerr_purgeflag; struct hlist_node list_entries; - /* mmap counter for resources mapped into user space */ - u32 mm_count_squeue; - u32 mm_count_rqueue; - u32 mm_count_galpa; }; /* must be power of 2 */ @@ -143,14 +142,13 @@ struct ehca_cq { struct ipz_cq_handle ipz_cq_handle; struct ehca_pfcq pf; spinlock_t cb_lock; + u64 uspace_queue; + u64 uspace_fwh; struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; struct list_head entry; u32 nr_callbacks; spinlock_t task_lock; u32 ownpid; - /* mmap counter for resources mapped into user space */ - u32 mm_count_queue; - u32 mm_count_galpa; }; enum ehca_mr_flag { @@ -250,6 +248,20 @@ struct ehca_ucontext { struct ib_ucontext ib_ucontext; }; +struct ehca_module *ehca_module_new(void); + +int ehca_module_delete(struct ehca_module *me); + +int ehca_eq_ctor(struct ehca_eq *eq); + +int ehca_eq_dtor(struct ehca_eq *eq); + +struct ehca_shca *ehca_shca_new(void); + +int ehca_shca_delete(struct ehca_shca *me); + +struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor); + int ehca_init_pd_cache(void); void ehca_cleanup_pd_cache(void); int ehca_init_cq_cache(void); @@ -271,6 +283,7 @@ extern int ehca_port_act_time; extern int ehca_use_hp_mr; struct ipzu_queue_resp { + u64 queue; /* points to first queue entry */ u32 qe_size; /* queue entry size */ u32 act_nr_of_sg; u32 queue_length; /* queue length allocated in bytes */ @@ -283,6 +296,7 @@ struct ehca_create_cq_resp { u32 cq_number; u32 token; struct ipzu_queue_resp ipz_queue; + struct h_galpas galpas; }; struct ehca_create_qp_resp { @@ -295,6 +309,7 @@ struct ehca_create_qp_resp { u32 dummy; /* padding for 8 byte alignment */ struct ipzu_queue_resp ipz_squeue; struct ipzu_queue_resp ipz_rqueue; + struct h_galpas galpas; }; struct ehca_alloc_cq_parms { diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c index 9291a86ca053..6074c897f51c 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c @@ -267,6 +267,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, if (context) { struct ipz_queue *ipz_queue = &my_cq->ipz_queue; struct ehca_create_cq_resp resp; + struct vm_area_struct *vma; memset(&resp, 0, sizeof(resp)); resp.cq_number = my_cq->cq_number; resp.token = my_cq->token; @@ -275,14 +276,40 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, resp.ipz_queue.queue_length = ipz_queue->queue_length; resp.ipz_queue.pagesize = ipz_queue->pagesize; resp.ipz_queue.toggle_state = ipz_queue->toggle_state; + ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000, + ipz_queue->queue_length, + (void**)&resp.ipz_queue.queue, + &vma); + if (ret) { + ehca_err(device, "Could not mmap queue pages"); + cq = ERR_PTR(ret); + goto create_cq_exit4; + } + my_cq->uspace_queue = resp.ipz_queue.queue; + resp.galpas = my_cq->galpas; + ret = ehca_mmap_register(my_cq->galpas.user.fw_handle, + (void**)&resp.galpas.kernel.fw_handle, + &vma); + if (ret) { + ehca_err(device, "Could not mmap fw_handle"); + cq = ERR_PTR(ret); + goto create_cq_exit5; + } + my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { ehca_err(device, "Copy to udata failed."); - goto create_cq_exit4; + goto create_cq_exit6; } } return cq; +create_cq_exit6: + ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); + +create_cq_exit5: + ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length); + create_cq_exit4: ipz_queue_dtor(&my_cq->ipz_queue); @@ -306,6 +333,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int ehca_destroy_cq(struct ib_cq *cq) { u64 h_ret; + int ret; struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); int cq_num = my_cq->cq_number; struct ib_device *device = cq->device; @@ -315,20 +343,6 @@ int ehca_destroy_cq(struct ib_cq *cq) u32 cur_pid = current->tgid; unsigned long flags; - if (cq->uobject) { - if (my_cq->mm_count_galpa || my_cq->mm_count_queue) { - ehca_err(device, "Resources still referenced in " - "user space cq_num=%x", my_cq->cq_number); - return -EINVAL; - } - if (my_cq->ownpid != cur_pid) { - ehca_err(device, "Invalid caller pid=%x ownpid=%x " - "cq_num=%x", - cur_pid, my_cq->ownpid, my_cq->cq_number); - return -EINVAL; - } - } - spin_lock_irqsave(&ehca_cq_idr_lock, flags); while (my_cq->nr_callbacks) { spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); @@ -339,6 +353,25 @@ int ehca_destroy_cq(struct ib_cq *cq) idr_remove(&ehca_cq_idr, my_cq->token); spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); + if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { + ehca_err(device, "Invalid caller pid=%x ownpid=%x", + cur_pid, my_cq->ownpid); + return -EINVAL; + } + + /* un-mmap if vma alloc */ + if (my_cq->uspace_queue ) { + ret = ehca_munmap(my_cq->uspace_queue, + my_cq->ipz_queue.queue_length); + if (ret) + ehca_err(device, "Could not munmap queue ehca_cq=%p " + "cq_num=%x", my_cq, cq_num); + ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); + if (ret) + ehca_err(device, "Could not munmap fwh ehca_cq=%p " + "cq_num=%x", my_cq, cq_num); + } + h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); if (h_ret == H_R_STATE) { /* cq in err: read err data and destroy it forcibly */ @@ -367,7 +400,7 @@ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); u32 cur_pid = current->tgid; - if (cq->uobject && my_cq->ownpid != cur_pid) { + if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", cur_pid, my_cq->ownpid); return -EINVAL; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h index 95fd59fb4528..cd7789f0d08e 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -171,6 +171,14 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); void ehca_poll_eqs(unsigned long data); +int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped, + struct vm_area_struct **vma); + +int ehca_mmap_register(u64 physical,void **mapped, + struct vm_area_struct **vma); + +int ehca_munmap(unsigned long addr, size_t len); + #ifdef CONFIG_PPC_64K_PAGES void *ehca_alloc_fw_ctrlblock(gfp_t flags); void ehca_free_fw_ctrlblock(void *ptr); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index 1155bcf48212..6574fbbaead5 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch "); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0020"); +MODULE_VERSION("SVNEHCA_0019"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -288,7 +288,7 @@ int ehca_init_device(struct ehca_shca *shca) strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); shca->ib_device.owner = THIS_MODULE; - shca->ib_device.uverbs_abi_ver = 6; + shca->ib_device.uverbs_abi_ver = 5; shca->ib_device.uverbs_cmd_mask = (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | @@ -790,7 +790,7 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0020)\n"); + "(Rel.: SVNEHCA_0019)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c index 95efef921f1d..34b85556d01e 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c @@ -637,6 +637,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; struct ehca_create_qp_resp resp; + struct vm_area_struct * vma; memset(&resp, 0, sizeof(resp)); resp.qp_num = my_qp->real_qp_num; @@ -650,21 +651,59 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; + ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000, + ipz_rqueue->queue_length, + (void**)&resp.ipz_rqueue.queue, + &vma); + if (ret) { + ehca_err(pd->device, "Could not mmap rqueue pages"); + goto create_qp_exit3; + } + my_qp->uspace_rqueue = resp.ipz_rqueue.queue; /* squeue properties */ resp.ipz_squeue.qe_size = ipz_squeue->qe_size; resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; resp.ipz_squeue.queue_length = ipz_squeue->queue_length; resp.ipz_squeue.pagesize = ipz_squeue->pagesize; resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; + ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000, + ipz_squeue->queue_length, + (void**)&resp.ipz_squeue.queue, + &vma); + if (ret) { + ehca_err(pd->device, "Could not mmap squeue pages"); + goto create_qp_exit4; + } + my_qp->uspace_squeue = resp.ipz_squeue.queue; + /* fw_handle */ + resp.galpas = my_qp->galpas; + ret = ehca_mmap_register(my_qp->galpas.user.fw_handle, + (void**)&resp.galpas.kernel.fw_handle, + &vma); + if (ret) { + ehca_err(pd->device, "Could not mmap fw_handle"); + goto create_qp_exit5; + } + my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; + if (ib_copy_to_udata(udata, &resp, sizeof resp)) { ehca_err(pd->device, "Copy to udata failed"); ret = -EINVAL; - goto create_qp_exit3; + goto create_qp_exit6; } } return &my_qp->ib_qp; +create_qp_exit6: + ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); + +create_qp_exit5: + ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length); + +create_qp_exit4: + ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length); + create_qp_exit3: ipz_queue_dtor(&my_qp->ipz_rqueue); ipz_queue_dtor(&my_qp->ipz_squeue); @@ -892,7 +931,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, my_qp->qp_type == IB_QPT_SMI) && statetrans == IB_QPST_SQE2RTS) { /* mark next free wqe if kernel */ - if (!ibqp->uobject) { + if (my_qp->uspace_squeue == 0) { struct ehca_wqe *wqe; /* lock send queue */ spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); @@ -1378,18 +1417,11 @@ int ehca_destroy_qp(struct ib_qp *ibqp) enum ib_qp_type qp_type; unsigned long flags; - if (ibqp->uobject) { - if (my_qp->mm_count_galpa || - my_qp->mm_count_rqueue || my_qp->mm_count_squeue) { - ehca_err(ibqp->device, "Resources still referenced in " - "user space qp_num=%x", ibqp->qp_num); - return -EINVAL; - } - if (my_pd->ownpid != cur_pid) { - ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && + my_pd->ownpid != cur_pid) { + ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", + cur_pid, my_pd->ownpid); + return -EINVAL; } if (my_qp->send_cq) { @@ -1407,6 +1439,24 @@ int ehca_destroy_qp(struct ib_qp *ibqp) idr_remove(&ehca_qp_idr, my_qp->token); spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); + /* un-mmap if vma alloc */ + if (my_qp->uspace_rqueue) { + ret = ehca_munmap(my_qp->uspace_rqueue, + my_qp->ipz_rqueue.queue_length); + if (ret) + ehca_err(ibqp->device, "Could not munmap rqueue " + "qp_num=%x", qp_num); + ret = ehca_munmap(my_qp->uspace_squeue, + my_qp->ipz_squeue.queue_length); + if (ret) + ehca_err(ibqp->device, "Could not munmap squeue " + "qp_num=%x", qp_num); + ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); + if (ret) + ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x", + qp_num); + } + h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); if (h_ret != H_SUCCESS) { ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c b/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c index 08d3f892d9f3..b46bda1bf85d 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -579,7 +579,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) } else wc->status = IB_WC_SUCCESS; - wc->qp = NULL; + wc->qp_num = cqe->local_qp_number; wc->byte_len = cqe->nr_bytes_transferred; wc->pkey_index = cqe->pkey_index; wc->slid = cqe->rlid; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c b/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c index 73db920b6945..e08764e4aef2 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c @@ -68,183 +68,105 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context) return 0; } -static void ehca_mm_open(struct vm_area_struct *vma) +struct page *ehca_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) { - u32 *count = (u32*)vma->vm_private_data; - if (!count) { - ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - return; - } - (*count)++; - if (!(*count)) - ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", - vma->vm_start, vma->vm_end, *count); -} - -static void ehca_mm_close(struct vm_area_struct *vma) -{ - u32 *count = (u32*)vma->vm_private_data; - if (!count) { - ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", - vma->vm_start, vma->vm_end); - return; - } - (*count)--; - ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", - vma->vm_start, vma->vm_end, *count); -} - -static struct vm_operations_struct vm_ops = { - .open = ehca_mm_open, - .close = ehca_mm_close, -}; - -static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas, - u32 *mm_count) -{ - int ret; - u64 vsize, physical; - - vsize = vma->vm_end - vma->vm_start; - if (vsize != EHCA_PAGESIZE) { - ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start); - return -EINVAL; - } - - physical = galpas->user.fw_handle; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical); - /* VM_IO | VM_RESERVED are set by remap_pfn_range() */ - ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, - vsize, vma->vm_page_prot); - if (unlikely(ret)) { - ehca_gen_err("remap_pfn_range() failed ret=%x", ret); - return -ENOMEM; - } - - vma->vm_private_data = mm_count; - (*mm_count)++; - vma->vm_ops = &vm_ops; + struct page *mypage = NULL; + u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; + u32 idr_handle = fileoffset >> 32; + u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ + u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ + u32 cur_pid = current->tgid; + unsigned long flags; + struct ehca_cq *cq; + struct ehca_qp *qp; + struct ehca_pd *pd; + u64 offset; + void *vaddr; - return 0; -} + switch (q_type) { + case 1: /* CQ */ + spin_lock_irqsave(&ehca_cq_idr_lock, flags); + cq = idr_find(&ehca_cq_idr, idr_handle); + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); -static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue, - u32 *mm_count) -{ - int ret; - u64 start, ofs; - struct page *page; - - vma->vm_flags |= VM_RESERVED; - start = vma->vm_start; - for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) { - u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs); - page = virt_to_page(virt_addr); - ret = vm_insert_page(vma, start, page); - if (unlikely(ret)) { - ehca_gen_err("vm_insert_page() failed rc=%x", ret); - return ret; + /* make sure this mmap really belongs to the authorized user */ + if (!cq) { + ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS"); + return NOPAGE_SIGBUS; } - start += PAGE_SIZE; - } - vma->vm_private_data = mm_count; - (*mm_count)++; - vma->vm_ops = &vm_ops; - return 0; -} - -static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq, - u32 rsrc_type) -{ - int ret; - - switch (rsrc_type) { - case 1: /* galpa fw handle */ - ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number); - ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa); - if (unlikely(ret)) { + if (cq->ownpid != cur_pid) { ehca_err(cq->ib_cq.device, - "ehca_mmap_fw() failed rc=%x cq_num=%x", - ret, cq->cq_number); - return ret; + "Invalid caller pid=%x ownpid=%x", + cur_pid, cq->ownpid); + return NOPAGE_SIGBUS; } - break; - case 2: /* cq queue_addr */ - ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number); - ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue); - if (unlikely(ret)) { - ehca_err(cq->ib_cq.device, - "ehca_mmap_queue() failed rc=%x cq_num=%x", - ret, cq->cq_number); - return ret; + if (rsrc_type == 2) { + ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq); + offset = address - vma->vm_start; + vaddr = ipz_qeit_calc(&cq->ipz_queue, offset); + ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p", + offset, vaddr); + mypage = virt_to_page(vaddr); } break; - default: - ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x", - rsrc_type, cq->cq_number); - return -EINVAL; - } - - return 0; -} - -static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp, - u32 rsrc_type) -{ - int ret; + case 2: /* QP */ + spin_lock_irqsave(&ehca_qp_idr_lock, flags); + qp = idr_find(&ehca_qp_idr, idr_handle); + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - switch (rsrc_type) { - case 1: /* galpa fw handle */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num); - ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "remap_pfn_range() failed ret=%x qp_num=%x", - ret, qp->ib_qp.qp_num); - return -ENOMEM; + /* make sure this mmap really belongs to the authorized user */ + if (!qp) { + ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS"); + return NOPAGE_SIGBUS; } - break; - case 2: /* qp rqueue_addr */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue", - qp->ib_qp.qp_num); - ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue); - if (unlikely(ret)) { + pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); + if (pd->ownpid != cur_pid) { ehca_err(qp->ib_qp.device, - "ehca_mmap_queue(rq) failed rc=%x qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; + "Invalid caller pid=%x ownpid=%x", + cur_pid, pd->ownpid); + return NOPAGE_SIGBUS; } - break; - case 3: /* qp squeue_addr */ - ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue", - qp->ib_qp.qp_num); - ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "ehca_mmap_queue(sq) failed rc=%x qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; + if (rsrc_type == 2) { /* rqueue */ + ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp); + offset = address - vma->vm_start; + vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset); + ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", + offset, vaddr); + mypage = virt_to_page(vaddr); + } else if (rsrc_type == 3) { /* squeue */ + ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp); + offset = address - vma->vm_start; + vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset); + ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", + offset, vaddr); + mypage = virt_to_page(vaddr); } break; default: - ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x", - rsrc_type, qp->ib_qp.qp_num); - return -EINVAL; + ehca_gen_err("bad queue type %x", q_type); + return NOPAGE_SIGBUS; } - return 0; + if (!mypage) { + ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS"); + return NOPAGE_SIGBUS; + } + get_page(mypage); + + return mypage; } +static struct vm_operations_struct ehcau_vm_ops = { + .nopage = ehca_nopage, +}; + int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) { u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; @@ -253,6 +175,7 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ u32 cur_pid = current->tgid; u32 ret; + u64 vsize, physical; unsigned long flags; struct ehca_cq *cq; struct ehca_qp *qp; @@ -278,12 +201,44 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) return -EINVAL; - ret = ehca_mmap_cq(vma, cq, rsrc_type); - if (unlikely(ret)) { - ehca_err(cq->ib_cq.device, - "ehca_mmap_cq() failed rc=%x cq_num=%x", - ret, cq->cq_number); - return ret; + switch (rsrc_type) { + case 1: /* galpa fw handle */ + ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq); + vma->vm_flags |= VM_RESERVED; + vsize = vma->vm_end - vma->vm_start; + if (vsize != EHCA_PAGESIZE) { + ehca_err(cq->ib_cq.device, "invalid vsize=%lx", + vma->vm_end - vma->vm_start); + return -EINVAL; + } + + physical = cq->galpas.user.fw_handle; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_IO | VM_RESERVED; + + ehca_dbg(cq->ib_cq.device, + "vsize=%lx physical=%lx", vsize, physical); + ret = remap_pfn_range(vma, vma->vm_start, + physical >> PAGE_SHIFT, vsize, + vma->vm_page_prot); + if (ret) { + ehca_err(cq->ib_cq.device, + "remap_pfn_range() failed ret=%x", + ret); + return -ENOMEM; + } + break; + + case 2: /* cq queue_addr */ + ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq); + vma->vm_flags |= VM_RESERVED; + vma->vm_ops = &ehcau_vm_ops; + break; + + default: + ehca_err(cq->ib_cq.device, "bad resource type %x", + rsrc_type); + return -EINVAL; } break; @@ -307,12 +262,50 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) return -EINVAL; - ret = ehca_mmap_qp(vma, qp, rsrc_type); - if (unlikely(ret)) { - ehca_err(qp->ib_qp.device, - "ehca_mmap_qp() failed rc=%x qp_num=%x", - ret, qp->ib_qp.qp_num); - return ret; + switch (rsrc_type) { + case 1: /* galpa fw handle */ + ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp); + vma->vm_flags |= VM_RESERVED; + vsize = vma->vm_end - vma->vm_start; + if (vsize != EHCA_PAGESIZE) { + ehca_err(qp->ib_qp.device, "invalid vsize=%lx", + vma->vm_end - vma->vm_start); + return -EINVAL; + } + + physical = qp->galpas.user.fw_handle; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_IO | VM_RESERVED; + + ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx", + vsize, physical); + ret = remap_pfn_range(vma, vma->vm_start, + physical >> PAGE_SHIFT, vsize, + vma->vm_page_prot); + if (ret) { + ehca_err(qp->ib_qp.device, + "remap_pfn_range() failed ret=%x", + ret); + return -ENOMEM; + } + break; + + case 2: /* qp rqueue_addr */ + ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp); + vma->vm_flags |= VM_RESERVED; + vma->vm_ops = &ehcau_vm_ops; + break; + + case 3: /* qp squeue_addr */ + ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp); + vma->vm_flags |= VM_RESERVED; + vma->vm_ops = &ehcau_vm_ops; + break; + + default: + ehca_err(qp->ib_qp.device, "bad resource type %x", + rsrc_type); + return -EINVAL; } break; @@ -323,3 +316,77 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) return 0; } + +int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped, + struct vm_area_struct **vma) +{ + down_write(¤t->mm->mmap_sem); + *mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + foffset); + up_write(¤t->mm->mmap_sem); + if (!(*mapped)) { + ehca_gen_err("couldn't mmap foffset=%lx length=%lx", + foffset, length); + return -EINVAL; + } + + *vma = find_vma(current->mm, (u64)*mapped); + if (!(*vma)) { + down_write(¤t->mm->mmap_sem); + do_munmap(current->mm, 0, length); + up_write(¤t->mm->mmap_sem); + ehca_gen_err("couldn't find vma queue=%p", *mapped); + return -EINVAL; + } + (*vma)->vm_flags |= VM_RESERVED; + (*vma)->vm_ops = &ehcau_vm_ops; + + return 0; +} + +int ehca_mmap_register(u64 physical, void **mapped, + struct vm_area_struct **vma) +{ + int ret; + unsigned long vsize; + /* ehca hw supports only 4k page */ + ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma); + if (ret) { + ehca_gen_err("could'nt mmap physical=%lx", physical); + return ret; + } + + (*vma)->vm_flags |= VM_RESERVED; + vsize = (*vma)->vm_end - (*vma)->vm_start; + if (vsize != EHCA_PAGESIZE) { + ehca_gen_err("invalid vsize=%lx", + (*vma)->vm_end - (*vma)->vm_start); + return -EINVAL; + } + + (*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot); + (*vma)->vm_flags |= VM_IO | VM_RESERVED; + + ret = remap_pfn_range((*vma), (*vma)->vm_start, + physical >> PAGE_SHIFT, vsize, + (*vma)->vm_page_prot); + if (ret) { + ehca_gen_err("remap_pfn_range() failed ret=%x", ret); + return -ENOMEM; + } + + return 0; + +} + +int ehca_munmap(unsigned long addr, size_t len) { + int ret = 0; + struct mm_struct *mm = current->mm; + if (mm) { + down_write(&mm->mmap_sem); + ret = do_munmap(mm, addr, len); + up_write(&mm->mmap_sem); + } + return ret; +} diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c index 64f07b19349f..46c1c89bf6ae 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c @@ -379,7 +379,7 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) wc.vendor_err = 0; wc.byte_len = 0; wc.imm_data = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = 0; wc.wc_flags = 0; wc.pkey_index = 0; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c index 5ff20cb04494..ce6038743c5c 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c @@ -702,7 +702,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc->vendor_err = 0; wc->byte_len = 0; - wc->qp = &qp->ibqp; + wc->qp_num = qp->ibqp.qp_num; wc->src_qp = qp->remote_qpn; wc->pkey_index = 0; wc->slid = qp->remote_ah_attr.dlid; @@ -836,7 +836,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.vendor_err = 0; wc.byte_len = wqe->length; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = qp->remote_qpn; wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; @@ -951,7 +951,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.vendor_err = 0; wc.byte_len = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = qp->remote_qpn; wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; @@ -1511,7 +1511,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; wc.vendor_err = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = qp->remote_qpn; wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c index e86cb171872e..f7530512045d 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -137,7 +137,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe) wc.vendor_err = 0; wc.byte_len = 0; wc.imm_data = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = 0; wc.wc_flags = 0; wc.pkey_index = 0; @@ -336,7 +336,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.vendor_err = 0; wc.byte_len = 0; - wc.qp = &sqp->ibqp; + wc.qp_num = sqp->ibqp.qp_num; wc.src_qp = sqp->remote_qpn; wc.pkey_index = 0; wc.slid = sqp->remote_ah_attr.dlid; @@ -426,7 +426,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) wc.status = IB_WC_SUCCESS; wc.vendor_err = 0; wc.byte_len = wqe->length; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = qp->remote_qpn; /* XXX do we know which pkey matched? Only needed for GSI. */ wc.pkey_index = 0; @@ -447,7 +447,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.vendor_err = 0; wc.byte_len = wqe->length; - wc.qp = &sqp->ibqp; + wc.qp_num = sqp->ibqp.qp_num; wc.src_qp = 0; wc.pkey_index = 0; wc.slid = 0; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_uc.c b/trunk/drivers/infiniband/hw/ipath/ipath_uc.c index 325d6634ff53..e636cfd67a82 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_uc.c @@ -49,7 +49,7 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe, wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc->vendor_err = 0; wc->byte_len = wqe->length; - wc->qp = &qp->ibqp; + wc->qp_num = qp->ibqp.qp_num; wc->src_qp = qp->remote_qpn; wc->pkey_index = 0; wc->slid = qp->remote_ah_attr.dlid; @@ -411,7 +411,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; wc.vendor_err = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = qp->remote_qpn; wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c index 9a3e54664ee4..49f1102af8b3 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c @@ -66,7 +66,7 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, wc.vendor_err = 0; wc.byte_len = 0; wc.imm_data = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = 0; wc.wc_flags = 0; wc.pkey_index = 0; @@ -255,7 +255,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, wc->status = IB_WC_SUCCESS; wc->opcode = IB_WC_RECV; wc->vendor_err = 0; - wc->qp = &qp->ibqp; + wc->qp_num = qp->ibqp.qp_num; wc->src_qp = sqp->ibqp.qp_num; /* XXX do we know which pkey matched? Only needed for GSI. */ wc->pkey_index = 0; @@ -474,7 +474,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) wc.vendor_err = 0; wc.opcode = IB_WC_SEND; wc.byte_len = len; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = 0; wc.wc_flags = 0; /* XXX initialize other fields? */ @@ -651,7 +651,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; wc.vendor_err = 0; - wc.qp = &qp->ibqp; + wc.qp_num = qp->ibqp.qp_num; wc.src_qp = src_qp; /* XXX do we know which pkey matched? Only needed for GSI. */ wc.pkey_index = 0; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c index 968d1519761c..768df7265b81 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1854,7 +1854,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, memset(inbox + 256, 0, 256); - MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET); + MTHCA_PUT(inbox, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET); MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); val = in_wc->sl << 4; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c index efd79ef109a6..1159c8a0f2c5 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c @@ -534,7 +534,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev, } } - entry->qp = &(*cur_qp)->ibqp; + entry->qp_num = (*cur_qp)->qpn; if (is_send) { wq = &(*cur_qp)->sq; diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 5e8ac577f0ad..72611fd15103 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -548,7 +548,6 @@ static int srp_reconnect_target(struct srp_target_port *target) target->tx_head = 0; target->tx_tail = 0; - target->qp_in_error = 0; ret = srp_connect_target(target); if (ret) goto err; @@ -879,7 +878,6 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) printk(KERN_ERR PFX "failed %s status %d\n", wc.wr_id & SRP_OP_RECV ? "receive" : "send", wc.status); - target->qp_in_error = 1; break; } @@ -1339,8 +1337,6 @@ static int srp_abort(struct scsi_cmnd *scmnd) printk(KERN_ERR "SRP abort called\n"); - if (target->qp_in_error) - return FAILED; if (srp_find_req(target, scmnd, &req)) return FAILED; if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) @@ -1369,8 +1365,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) printk(KERN_ERR "SRP reset_device called\n"); - if (target->qp_in_error) - return FAILED; if (srp_find_req(target, scmnd, &req)) return FAILED; if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET)) @@ -1807,7 +1801,6 @@ static ssize_t srp_create_target(struct class_device *class_dev, goto err_free; } - target->qp_in_error = 0; ret = srp_connect_target(target); if (ret) { printk(KERN_ERR PFX "Connection failed\n"); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.h b/trunk/drivers/infiniband/ulp/srp/ib_srp.h index 2f3319c719a5..c21772317b86 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.h +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.h @@ -158,7 +158,6 @@ struct srp_target_port { struct completion done; int status; enum srp_target_state state; - int qp_in_error; }; struct srp_iu { diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 89bba277da5f..00db31c314e0 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -69,25 +69,6 @@ config TIFM_7XX1 To compile this driver as a module, choose M here: the module will be called tifm_7xx1. -config ASUS_LAPTOP - tristate "Asus Laptop Extras (EXPERIMENTAL)" - depends on X86 - depends on ACPI - depends on EXPERIMENTAL && !ACPI_ASUS - depends on LEDS_CLASS - depends on BACKLIGHT_CLASS_DEVICE - ---help--- - This is the new Linux driver for Asus laptops. It may also support some - MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate - standard ACPI events that go through /proc/acpi/events. It also adds - support for video output switching, LCD backlight control, Bluetooth and - Wlan control, and most importantly, allows you to blink those fancy LEDs. - - For more information and a userspace daemon for handling the extra - buttons see . - - If you have an ACPI-compatible ASUS laptop, say Y or M here. - config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86 diff --git a/trunk/drivers/misc/Makefile b/trunk/drivers/misc/Makefile index 35da53c409c0..c9e98ab021c5 100644 --- a/trunk/drivers/misc/Makefile +++ b/trunk/drivers/misc/Makefile @@ -6,7 +6,6 @@ obj- := misc.o # Dummy rule to force built-in.o to be made obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o -obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o diff --git a/trunk/drivers/misc/asus-laptop.c b/trunk/drivers/misc/asus-laptop.c deleted file mode 100644 index 861c39935f99..000000000000 --- a/trunk/drivers/misc/asus-laptop.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * asus-laptop.c - Asus Laptop Support - * - * - * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor - * Copyright (C) 2006 Corentin Chary - * - * 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 - * - * - * The development page for this driver is located at - * http://sourceforge.net/projects/acpi4asus/ - * - * Credits: - * Pontus Fuchs - Helper functions, cleanup - * Johann Wiesner - Small compile fixes - * John Belmonte - ACPI code for Toshiba laptop was a good starting point. - * Eric Burghard - LED display support for W1N - * Josh Green - Light Sens support - * Thomas Tuttle - His first patch for led support was very helpfull - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ASUS_LAPTOP_VERSION "0.40" - -#define ASUS_HOTK_NAME "Asus Laptop Support" -#define ASUS_HOTK_CLASS "hotkey" -#define ASUS_HOTK_DEVICE_NAME "Hotkey" -#define ASUS_HOTK_HID "ATK0100" -#define ASUS_HOTK_FILE "asus-laptop" -#define ASUS_HOTK_PREFIX "\\_SB.ATKD." - -/* - * Some events we use, same for all Asus - */ -#define ATKD_BR_UP 0x10 -#define ATKD_BR_DOWN 0x20 -#define ATKD_LCD_ON 0x33 -#define ATKD_LCD_OFF 0x34 - -/* - * Known bits returned by \_SB.ATKD.HWRS - */ -#define WL_HWRS 0x80 -#define BT_HWRS 0x100 - -/* - * Flags for hotk status - * WL_ON and BT_ON are also used for wireless_status() - */ -#define WL_ON 0x01 //internal Wifi -#define BT_ON 0x02 //internal Bluetooth -#define MLED_ON 0x04 //mail LED -#define TLED_ON 0x08 //touchpad LED -#define RLED_ON 0x10 //Record LED -#define PLED_ON 0x20 //Phone LED -#define LCD_ON 0x40 //LCD backlight - -#define ASUS_LOG ASUS_HOTK_FILE ": " -#define ASUS_ERR KERN_ERR ASUS_LOG -#define ASUS_WARNING KERN_WARNING ASUS_LOG -#define ASUS_NOTICE KERN_NOTICE ASUS_LOG -#define ASUS_INFO KERN_INFO ASUS_LOG -#define ASUS_DEBUG KERN_DEBUG ASUS_LOG - -MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); -MODULE_DESCRIPTION(ASUS_HOTK_NAME); -MODULE_LICENSE("GPL"); - -#define ASUS_HANDLE(object, paths...) \ - static acpi_handle object##_handle = NULL; \ - static char *object##_paths[] = { paths } - -/* LED */ -ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED"); -ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED"); -ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */ -ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */ - -/* LEDD */ -ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); - -/* Bluetooth and WLAN - * WLED and BLED are not handled like other XLED, because in some dsdt - * they also control the WLAN/Bluetooth device. - */ -ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED"); -ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED"); -ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS"); /* All new models */ - -/* Brightness */ -ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV"); -ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV"); - -/* Backlight */ -ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ - "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */ - "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ - "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ - "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ - "\\_SB.PCI0.PX40.Q10", /* S1x */ - "\\Q10"); /* A2x, L2D, L3D, M2E */ - -/* Display */ -ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); -ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G - M6A M6V VX-1 V6J V6V W3Z */ - "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V - S5A M5A z33A W1Jc W2V */ - "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ - "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ - "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ - "\\_SB.PCI0.VGA.GETD", /* Z96F */ - "\\ACTD", /* A2D */ - "\\ADVG", /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ - "\\DNXT", /* P30 */ - "\\INFB", /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ - "\\SSTE"); /* A3F A6F A3N A3L M6N W3N W6A */ - -ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ -ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ - -/* - * This is the main structure, we can use it to store anything interesting - * about the hotk device - */ -struct asus_hotk { - char *name; //laptop name - struct acpi_device *device; //the device we are in - acpi_handle handle; //the handle of the hotk device - char status; //status of the hotk, for LEDs, ... - u32 ledd_status; //status of the LED display - u8 light_level; //light sensor level - u8 light_switch; //light sensor switch value - u16 event_count[128]; //count for each event TODO make this better -}; - -/* - * This header is made available to allow proper configuration given model, - * revision number , ... this info cannot go in struct asus_hotk because it is - * available before the hotk - */ -static struct acpi_table_header *asus_info; - -/* The actual device the driver binds to */ -static struct asus_hotk *hotk; - -/* - * The hotkey driver declaration - */ -static int asus_hotk_add(struct acpi_device *device); -static int asus_hotk_remove(struct acpi_device *device, int type); -static struct acpi_driver asus_hotk_driver = { - .name = ASUS_HOTK_NAME, - .class = ASUS_HOTK_CLASS, - .ids = ASUS_HOTK_HID, - .ops = { - .add = asus_hotk_add, - .remove = asus_hotk_remove, - }, -}; - -/* The backlight device /sys/class/backlight */ -static struct backlight_device *asus_backlight_device; - -/* - * The backlight class declaration - */ -static int read_brightness(struct backlight_device *bd); -static int update_bl_status(struct backlight_device *bd); -static struct backlight_properties asusbl_data = { - .owner = THIS_MODULE, - .get_brightness = read_brightness, - .update_status = update_bl_status, - .max_brightness = 15, -}; - -/* These functions actually update the LED's, and are called from a - * workqueue. By doing this as separate work rather than when the LED - * subsystem asks, we avoid messing with the Asus ACPI stuff during a - * potentially bad time, such as a timer interrupt. */ -static struct workqueue_struct *led_workqueue; - -#define ASUS_LED(object, ledname) \ - static void object##_led_set(struct led_classdev *led_cdev, \ - enum led_brightness value); \ - static void object##_led_update(struct work_struct *ignored); \ - static int object##_led_wk; \ - DECLARE_WORK(object##_led_work, object##_led_update); \ - static struct led_classdev object##_led = { \ - .name = "asus:" ledname, \ - .brightness_set = object##_led_set, \ - } - -ASUS_LED(mled, "mail"); -ASUS_LED(tled, "touchpad"); -ASUS_LED(rled, "record"); -ASUS_LED(pled, "phone"); - -/* - * This function evaluates an ACPI method, given an int as parameter, the - * method is searched within the scope of the handle, can be NULL. The output - * of the method is written is output, which can also be NULL - * - * returns 1 if write is successful, 0 else. - */ -static int write_acpi_int(acpi_handle handle, const char *method, int val, - struct acpi_buffer *output) -{ - struct acpi_object_list params; //list of input parameters (an int here) - union acpi_object in_obj; //the only param we use - acpi_status status; - - params.count = 1; - params.pointer = &in_obj; - in_obj.type = ACPI_TYPE_INTEGER; - in_obj.integer.value = val; - - status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); - return (status == AE_OK); -} - -static int read_acpi_int(acpi_handle handle, const char *method, int *val, - struct acpi_object_list *params) -{ - struct acpi_buffer output; - union acpi_object out_obj; - acpi_status status; - - output.length = sizeof(out_obj); - output.pointer = &out_obj; - - status = acpi_evaluate_object(handle, (char *)method, params, &output); - *val = out_obj.integer.value; - return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER); -} - -static int read_wireless_status(int mask) -{ - int status; - - if (!wireless_status_handle) - return (hotk->status & mask) ? 1 : 0; - - if (read_acpi_int(wireless_status_handle, NULL, &status, NULL)) { - return (status & mask) ? 1 : 0; - } else - printk(ASUS_WARNING "Error reading Wireless status\n"); - - return (hotk->status & mask) ? 1 : 0; -} - -/* Generic LED functions */ -static int read_status(int mask) -{ - /* There is a special method for both wireless devices */ - if (mask == BT_ON || mask == WL_ON) - return read_wireless_status(mask); - - return (hotk->status & mask) ? 1 : 0; -} - -static void write_status(acpi_handle handle, int out, int mask, int invert) -{ - hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask); - - if (invert) /* invert target value */ - out = !out & 0x1; - - if (handle && !write_acpi_int(handle, NULL, out, NULL)) - printk(ASUS_WARNING " write failed\n"); -} - -/* /sys/class/led handlers */ -#define ASUS_LED_HANDLER(object, mask, invert) \ - static void object##_led_set(struct led_classdev *led_cdev, \ - enum led_brightness value) \ - { \ - object##_led_wk = value; \ - queue_work(led_workqueue, &object##_led_work); \ - } \ - static void object##_led_update(struct work_struct *ignored) \ - { \ - int value = object##_led_wk; \ - write_status(object##_set_handle, value, (mask), (invert)); \ - } - -ASUS_LED_HANDLER(mled, MLED_ON, 1); -ASUS_LED_HANDLER(pled, PLED_ON, 0); -ASUS_LED_HANDLER(rled, RLED_ON, 0); -ASUS_LED_HANDLER(tled, TLED_ON, 0); - -static int get_lcd_state(void) -{ - return read_status(LCD_ON); -} - -static int set_lcd_state(int value) -{ - int lcd = 0; - acpi_status status = 0; - - lcd = value ? 1 : 0; - - if (lcd == get_lcd_state()) - return 0; - - if (lcd_switch_handle) { - status = acpi_evaluate_object(lcd_switch_handle, - NULL, NULL, NULL); - - if (ACPI_FAILURE(status)) - printk(ASUS_WARNING "Error switching LCD\n"); - } - - write_status(NULL, lcd, LCD_ON, 0); - return 0; -} - -static void lcd_blank(int blank) -{ - struct backlight_device *bd = asus_backlight_device; - - if (bd) { - down(&bd->sem); - if (likely(bd->props)) { - bd->props->power = blank; - if (likely(bd->props->update_status)) - bd->props->update_status(bd); - } - up(&bd->sem); - } -} - -static int read_brightness(struct backlight_device *bd) -{ - int value; - - if (!read_acpi_int(brightness_get_handle, NULL, &value, NULL)) - printk(ASUS_WARNING "Error reading brightness\n"); - - return value; -} - -static int set_brightness(struct backlight_device *bd, int value) -{ - int ret = 0; - - value = (0 < value) ? ((15 < value) ? 15 : value) : 0; - /* 0 <= value <= 15 */ - - if (!write_acpi_int(brightness_set_handle, NULL, value, NULL)) { - printk(ASUS_WARNING "Error changing brightness\n"); - ret = -EIO; - } - - return ret; -} - -static int update_bl_status(struct backlight_device *bd) -{ - int rv; - int value = bd->props->brightness; - - rv = set_brightness(bd, value); - if (rv) - return rv; - - value = (bd->props->power == FB_BLANK_UNBLANK) ? 1 : 0; - return set_lcd_state(value); -} - -/* - * Platform device handlers - */ - -/* - * We write our info in page, we begin at offset off and cannot write more - * than count bytes. We set eof to 1 if we handle those 2 values. We return the - * number of bytes written in page - */ -static ssize_t show_infos(struct device *dev, - struct device_attribute *attr, char *page) -{ - int len = 0; - int temp; - char buf[16]; //enough for all info - /* - * We use the easy way, we don't care of off and count, so we don't set eof - * to 1 - */ - - len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n"); - len += sprintf(page + len, "Model reference : %s\n", hotk->name); - /* - * The SFUN method probably allows the original driver to get the list - * of features supported by a given model. For now, 0x0100 or 0x0800 - * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. - * The significance of others is yet to be found. - */ - if (read_acpi_int(hotk->handle, "SFUN", &temp, NULL)) - len += - sprintf(page + len, "SFUN value : 0x%04x\n", temp); - /* - * Another value for userspace: the ASYM method returns 0x02 for - * battery low and 0x04 for battery critical, its readings tend to be - * more accurate than those provided by _BST. - * Note: since not all the laptops provide this method, errors are - * silently ignored. - */ - if (read_acpi_int(hotk->handle, "ASYM", &temp, NULL)) - len += - sprintf(page + len, "ASYM value : 0x%04x\n", temp); - if (asus_info) { - snprintf(buf, 16, "%d", asus_info->length); - len += sprintf(page + len, "DSDT length : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->checksum); - len += sprintf(page + len, "DSDT checksum : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->revision); - len += sprintf(page + len, "DSDT revision : %s\n", buf); - snprintf(buf, 7, "%s", asus_info->oem_id); - len += sprintf(page + len, "OEM id : %s\n", buf); - snprintf(buf, 9, "%s", asus_info->oem_table_id); - len += sprintf(page + len, "OEM table id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->oem_revision); - len += sprintf(page + len, "OEM revision : 0x%s\n", buf); - snprintf(buf, 5, "%s", asus_info->asl_compiler_id); - len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); - len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); - } - - return len; -} - -static int parse_arg(const char *buf, unsigned long count, int *val) -{ - if (!count) - return 0; - if (count > 31) - return -EINVAL; - if (sscanf(buf, "%i", val) != 1) - return -EINVAL; - return count; -} - -static ssize_t store_status(const char *buf, size_t count, - acpi_handle handle, int mask, int invert) -{ - int rv, value; - int out = 0; - - rv = parse_arg(buf, count, &value); - if (rv > 0) - out = value ? 1 : 0; - - write_status(handle, out, mask, invert); - - return rv; -} - -/* - * LEDD display - */ -static ssize_t show_ledd(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "0x%08x\n", hotk->ledd_status); -} - -static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int rv, value; - - rv = parse_arg(buf, count, &value); - if (rv > 0) { - if (!write_acpi_int(ledd_set_handle, NULL, value, NULL)) - printk(ASUS_WARNING "LED display write failed\n"); - else - hotk->ledd_status = (u32) value; - } - return rv; -} - -/* - * WLAN - */ -static ssize_t show_wlan(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", read_status(WL_ON)); -} - -static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_status(buf, count, wl_switch_handle, WL_ON, 0); -} - -/* - * Bluetooth - */ -static ssize_t show_bluetooth(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", read_status(BT_ON)); -} - -static ssize_t store_bluetooth(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - return store_status(buf, count, bt_switch_handle, BT_ON, 0); -} - -/* - * Display - */ -static void set_display(int value) -{ - /* no sanity check needed for now */ - if (!write_acpi_int(display_set_handle, NULL, value, NULL)) - printk(ASUS_WARNING "Error setting display\n"); - return; -} - -static int read_display(void) -{ - int value = 0; - - /* In most of the case, we know how to set the display, but sometime - we can't read it */ - if (display_get_handle) { - if (!read_acpi_int(display_get_handle, NULL, &value, NULL)) - printk(ASUS_WARNING "Error reading display status\n"); - } - - value &= 0x0F; /* needed for some models, shouldn't hurt others */ - - return value; -} - -/* - * Now, *this* one could be more user-friendly, but so far, no-one has - * complained. The significance of bits is the same as in store_disp() - */ -static ssize_t show_disp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", read_display()); -} - -/* - * Experimental support for display switching. As of now: 1 should activate - * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI. - * Any combination (bitwise) of these will suffice. I never actually tested 4 - * displays hooked up simultaneously, so be warned. See the acpi4asus README - * for more info. - */ -static ssize_t store_disp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int rv, value; - - rv = parse_arg(buf, count, &value); - if (rv > 0) - set_display(value); - return rv; -} - -/* - * Light Sens - */ -static void set_light_sens_switch(int value) -{ - if (!write_acpi_int(ls_switch_handle, NULL, value, NULL)) - printk(ASUS_WARNING "Error setting light sensor switch\n"); - hotk->light_switch = value; -} - -static ssize_t show_lssw(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", hotk->light_switch); -} - -static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int rv, value; - - rv = parse_arg(buf, count, &value); - if (rv > 0) - set_light_sens_switch(value ? 1 : 0); - - return rv; -} - -static void set_light_sens_level(int value) -{ - if (!write_acpi_int(ls_level_handle, NULL, value, NULL)) - printk(ASUS_WARNING "Error setting light sensor level\n"); - hotk->light_level = value; -} - -static ssize_t show_lslvl(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", hotk->light_level); -} - -static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int rv, value; - - rv = parse_arg(buf, count, &value); - if (rv > 0) { - value = (0 < value) ? ((15 < value) ? 15 : value) : 0; - /* 0 <= value <= 15 */ - set_light_sens_level(value); - } - - return rv; -} - -static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) -{ - /* TODO Find a better way to handle events count. */ - if (!hotk) - return; - - /* - * We need to tell the backlight device when the backlight power is - * switched - */ - if (event == ATKD_LCD_ON) { - write_status(NULL, 1, LCD_ON, 0); - lcd_blank(FB_BLANK_UNBLANK); - } else if (event == ATKD_LCD_OFF) { - write_status(NULL, 0, LCD_ON, 0); - lcd_blank(FB_BLANK_POWERDOWN); - } - - acpi_bus_generate_event(hotk->device, event, - hotk->event_count[event % 128]++); - - return; -} - -#define ASUS_CREATE_DEVICE_ATTR(_name) \ - struct device_attribute dev_attr_##_name = { \ - .attr = { \ - .name = __stringify(_name), \ - .mode = 0, \ - .owner = THIS_MODULE }, \ - .show = NULL, \ - .store = NULL, \ - } - -#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \ - do { \ - dev_attr_##_name.attr.mode = _mode; \ - dev_attr_##_name.show = _show; \ - dev_attr_##_name.store = _store; \ - } while(0) - -static ASUS_CREATE_DEVICE_ATTR(infos); -static ASUS_CREATE_DEVICE_ATTR(wlan); -static ASUS_CREATE_DEVICE_ATTR(bluetooth); -static ASUS_CREATE_DEVICE_ATTR(display); -static ASUS_CREATE_DEVICE_ATTR(ledd); -static ASUS_CREATE_DEVICE_ATTR(ls_switch); -static ASUS_CREATE_DEVICE_ATTR(ls_level); - -static struct attribute *asuspf_attributes[] = { - &dev_attr_infos.attr, - &dev_attr_wlan.attr, - &dev_attr_bluetooth.attr, - &dev_attr_display.attr, - &dev_attr_ledd.attr, - &dev_attr_ls_switch.attr, - &dev_attr_ls_level.attr, - NULL -}; - -static struct attribute_group asuspf_attribute_group = { - .attrs = asuspf_attributes -}; - -static struct platform_driver asuspf_driver = { - .driver = { - .name = ASUS_HOTK_FILE, - .owner = THIS_MODULE, - } -}; - -static struct platform_device *asuspf_device; - -static void asus_hotk_add_fs(void) -{ - ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); - - if (wl_switch_handle) - ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan); - - if (bt_switch_handle) - ASUS_SET_DEVICE_ATTR(bluetooth, 0644, - show_bluetooth, store_bluetooth); - - if (display_set_handle && display_get_handle) - ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp); - else if (display_set_handle) - ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp); - - if (ledd_set_handle) - ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd); - - if (ls_switch_handle && ls_level_handle) { - ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); - ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); - } -} - -static int asus_handle_init(char *name, acpi_handle * handle, - char **paths, int num_paths) -{ - int i; - acpi_status status; - - for (i = 0; i < num_paths; i++) { - status = acpi_get_handle(NULL, paths[i], handle); - if (ACPI_SUCCESS(status)) - return 0; - } - - *handle = NULL; - return -ENODEV; -} - -#define ASUS_HANDLE_INIT(object) \ - asus_handle_init(#object, &object##_handle, object##_paths, \ - ARRAY_SIZE(object##_paths)) - -/* - * This function is used to initialize the hotk with right values. In this - * method, we can make all the detection we want, and modify the hotk struct - */ -static int asus_hotk_get_info(void) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *model = NULL; - int bsts_result, hwrs_result; - char *string = NULL; - acpi_status status; - - /* - * Get DSDT headers early enough to allow for differentiating between - * models, but late enough to allow acpi_bus_register_driver() to fail - * before doing anything ACPI-specific. Should we encounter a machine, - * which needs special handling (i.e. its hotkey device has a different - * HID), this bit will be moved. A global variable asus_info contains - * the DSDT header. - */ - status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); - if (ACPI_FAILURE(status)) - printk(ASUS_WARNING "Couldn't get the DSDT table header\n"); - - /* We have to write 0 on init this far for all ASUS models */ - if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { - printk(ASUS_ERR "Hotkey initialization failed\n"); - return -ENODEV; - } - - /* This needs to be called for some laptops to init properly */ - if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result, NULL)) - printk(ASUS_WARNING "Error calling BSTS\n"); - else if (bsts_result) - printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n", - bsts_result); - - /* - * Try to match the object returned by INIT to the specific model. - * Handle every possible object (or the lack of thereof) the DSDT - * writers might throw at us. When in trouble, we pass NULL to - * asus_model_match() and try something completely different. - */ - if (buffer.pointer) { - model = buffer.pointer; - switch (model->type) { - case ACPI_TYPE_STRING: - string = model->string.pointer; - break; - case ACPI_TYPE_BUFFER: - string = model->buffer.pointer; - break; - default: - string = ""; - break; - } - } - hotk->name = kstrdup(string, GFP_KERNEL); - if (!hotk->name) - return -ENOMEM; - - if (*string) - printk(ASUS_NOTICE " %s model detected\n", string); - - ASUS_HANDLE_INIT(mled_set); - ASUS_HANDLE_INIT(tled_set); - ASUS_HANDLE_INIT(rled_set); - ASUS_HANDLE_INIT(pled_set); - - ASUS_HANDLE_INIT(ledd_set); - - /* - * The HWRS method return informations about the hardware. - * 0x80 bit is for WLAN, 0x100 for Bluetooth. - * The significance of others is yet to be found. - * If we don't find the method, we assume the device are present. - */ - if (!read_acpi_int(hotk->handle, "HRWS", &hwrs_result, NULL)) - hwrs_result = WL_HWRS | BT_HWRS; - - if (hwrs_result & WL_HWRS) - ASUS_HANDLE_INIT(wl_switch); - if (hwrs_result & BT_HWRS) - ASUS_HANDLE_INIT(bt_switch); - - ASUS_HANDLE_INIT(wireless_status); - - ASUS_HANDLE_INIT(brightness_set); - ASUS_HANDLE_INIT(brightness_get); - - ASUS_HANDLE_INIT(lcd_switch); - - ASUS_HANDLE_INIT(display_set); - ASUS_HANDLE_INIT(display_get); - - /* There is a lot of models with "ALSL", but a few get - a real light sens, so we need to check it. */ - if (ASUS_HANDLE_INIT(ls_switch)) - ASUS_HANDLE_INIT(ls_level); - - kfree(model); - - return AE_OK; -} - -static int asus_hotk_check(void) -{ - int result = 0; - - result = acpi_bus_get_status(hotk->device); - if (result) - return result; - - if (hotk->device->status.present) { - result = asus_hotk_get_info(); - } else { - printk(ASUS_ERR "Hotkey device not present, aborting\n"); - return -EINVAL; - } - - return result; -} - -static int asus_hotk_found; - -static int asus_hotk_add(struct acpi_device *device) -{ - acpi_status status = AE_OK; - int result; - - if (!device) - return -EINVAL; - - printk(ASUS_NOTICE "Asus Laptop Support version %s\n", - ASUS_LAPTOP_VERSION); - - hotk = kmalloc(sizeof(struct asus_hotk), GFP_KERNEL); - if (!hotk) - return -ENOMEM; - memset(hotk, 0, sizeof(struct asus_hotk)); - - hotk->handle = device->handle; - strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME); - strcpy(acpi_device_class(device), ASUS_HOTK_CLASS); - acpi_driver_data(device) = hotk; - hotk->device = device; - - result = asus_hotk_check(); - if (result) - goto end; - - asus_hotk_add_fs(); - - /* - * We install the handler, it will receive the hotk in parameter, so, we - * could add other data to the hotk struct - */ - status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, - asus_hotk_notify, hotk); - if (ACPI_FAILURE(status)) - printk(ASUS_ERR "Error installing notify handler\n"); - - asus_hotk_found = 1; - - /* WLED and BLED are on by default */ - write_status(bt_switch_handle, 1, BT_ON, 0); - write_status(wl_switch_handle, 1, WL_ON, 0); - - /* LCD Backlight is on by default */ - write_status(NULL, 1, LCD_ON, 0); - - /* LED display is off by default */ - hotk->ledd_status = 0xFFF; - - /* Set initial values of light sensor and level */ - hotk->light_switch = 1; /* Default to light sensor disabled */ - hotk->light_level = 0; /* level 5 for sensor sensitivity */ - - if (ls_switch_handle) - set_light_sens_switch(hotk->light_switch); - - if (ls_level_handle) - set_light_sens_level(hotk->light_level); - - end: - if (result) { - kfree(hotk->name); - kfree(hotk); - } - - return result; -} - -static int asus_hotk_remove(struct acpi_device *device, int type) -{ - acpi_status status = 0; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, - asus_hotk_notify); - if (ACPI_FAILURE(status)) - printk(ASUS_ERR "Error removing notify handler\n"); - - kfree(hotk->name); - kfree(hotk); - - return 0; -} - -static void asus_backlight_exit(void) -{ - if (asus_backlight_device) - backlight_device_unregister(asus_backlight_device); -} - -#define ASUS_LED_UNREGISTER(object) \ - if(object##_led.class_dev \ - && !IS_ERR(object##_led.class_dev)) \ - led_classdev_unregister(&object##_led) - -static void asus_led_exit(void) -{ - ASUS_LED_UNREGISTER(mled); - ASUS_LED_UNREGISTER(tled); - ASUS_LED_UNREGISTER(pled); - ASUS_LED_UNREGISTER(rled); - - destroy_workqueue(led_workqueue); -} - -static void __exit asus_laptop_exit(void) -{ - asus_backlight_exit(); - asus_led_exit(); - - acpi_bus_unregister_driver(&asus_hotk_driver); - sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); - platform_device_unregister(asuspf_device); - platform_driver_unregister(&asuspf_driver); -} - -static int asus_backlight_init(struct device *dev) -{ - struct backlight_device *bd; - - if (brightness_set_handle && lcd_switch_handle) { - bd = backlight_device_register(ASUS_HOTK_FILE, dev, - NULL, &asusbl_data); - if (IS_ERR(bd)) { - printk(ASUS_ERR - "Could not register asus backlight device\n"); - asus_backlight_device = NULL; - return PTR_ERR(bd); - } - - asus_backlight_device = bd; - - down(&bd->sem); - if (likely(bd->props)) { - bd->props->brightness = read_brightness(NULL); - bd->props->power = FB_BLANK_UNBLANK; - if (likely(bd->props->update_status)) - bd->props->update_status(bd); - } - up(&bd->sem); - } - return 0; -} - -static int asus_led_register(acpi_handle handle, - struct led_classdev *ldev, struct device *dev) -{ - if (!handle) - return 0; - - return led_classdev_register(dev, ldev); -} - -#define ASUS_LED_REGISTER(object, device) \ - asus_led_register(object##_set_handle, &object##_led, device) - -static int asus_led_init(struct device *dev) -{ - int rv; - - rv = ASUS_LED_REGISTER(mled, dev); - if (rv) - return rv; - - rv = ASUS_LED_REGISTER(tled, dev); - if (rv) - return rv; - - rv = ASUS_LED_REGISTER(rled, dev); - if (rv) - return rv; - - rv = ASUS_LED_REGISTER(pled, dev); - if (rv) - return rv; - - led_workqueue = create_singlethread_workqueue("led_workqueue"); - if (!led_workqueue) - return -ENOMEM; - - return 0; -} - -static int __init asus_laptop_init(void) -{ - struct device *dev; - int result; - - if (acpi_disabled) - return -ENODEV; - - if (!acpi_specific_hotkey_enabled) { - printk(ASUS_ERR "Using generic hotkey driver\n"); - return -ENODEV; - } - - result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 0) - return result; - - /* - * This is a bit of a kludge. We only want this module loaded - * for ASUS systems, but there's currently no way to probe the - * ACPI namespace for ASUS HIDs. So we just return failure if - * we didn't find one, which will cause the module to be - * unloaded. - */ - if (!asus_hotk_found) { - acpi_bus_unregister_driver(&asus_hotk_driver); - return -ENODEV; - } - - dev = acpi_get_physical_device(hotk->device->handle); - - result = asus_backlight_init(dev); - if (result) - goto fail_backlight; - - result = asus_led_init(dev); - if (result) - goto fail_led; - - /* Register platform stuff */ - result = platform_driver_register(&asuspf_driver); - if (result) - goto fail_platform_driver; - - asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1); - if (!asuspf_device) { - result = -ENOMEM; - goto fail_platform_device1; - } - - result = platform_device_add(asuspf_device); - if (result) - goto fail_platform_device2; - - result = sysfs_create_group(&asuspf_device->dev.kobj, - &asuspf_attribute_group); - if (result) - goto fail_sysfs; - - return 0; - - fail_sysfs: - platform_device_del(asuspf_device); - - fail_platform_device2: - platform_device_put(asuspf_device); - - fail_platform_device1: - platform_driver_unregister(&asuspf_driver); - - fail_platform_driver: - asus_led_exit(); - - fail_led: - asus_backlight_exit(); - - fail_backlight: - - return result; -} - -module_init(asus_laptop_init); -module_exit(asus_laptop_exit); diff --git a/trunk/drivers/misc/tifm_7xx1.c b/trunk/drivers/misc/tifm_7xx1.c index e21e490fedb0..2ab7add78f94 100644 --- a/trunk/drivers/misc/tifm_7xx1.c +++ b/trunk/drivers/misc/tifm_7xx1.c @@ -11,25 +11,66 @@ #include #include -#include #define DRIVER_NAME "tifm_7xx1" -#define DRIVER_VERSION "0.7" +#define DRIVER_VERSION "0.6" static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) { + int cnt; + unsigned long flags; + + spin_lock_irqsave(&fm->lock, flags); + if (!fm->inhibit_new_cards) { + for (cnt = 0; cnt < fm->max_sockets; cnt++) { + if (fm->sockets[cnt] == sock) { + fm->remove_mask |= (1 << cnt); + queue_work(fm->wq, &fm->media_remover); + break; + } + } + } + spin_unlock_irqrestore(&fm->lock, flags); +} + +static void tifm_7xx1_remove_media(struct work_struct *work) +{ + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_remover); unsigned long flags; + int cnt; + struct tifm_dev *sock; + if (!class_device_get(&fm->cdev)) + return; spin_lock_irqsave(&fm->lock, flags); - fm->socket_change_set |= 1 << sock->socket_id; - wake_up_all(&fm->change_set_notify); + for (cnt = 0; cnt < fm->max_sockets; cnt++) { + if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) { + printk(KERN_INFO DRIVER_NAME + ": demand removing card from socket %d\n", cnt); + sock = fm->sockets[cnt]; + fm->sockets[cnt] = NULL; + fm->remove_mask &= ~(1 << cnt); + + writel(0x0e00, sock->addr + SOCK_CONTROL); + + writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, + fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, + fm->addr + FM_SET_INTERRUPT_ENABLE); + + spin_unlock_irqrestore(&fm->lock, flags); + device_unregister(&sock->dev); + spin_lock_irqsave(&fm->lock, flags); + } + } spin_unlock_irqrestore(&fm->lock, flags); + class_device_put(&fm->cdev); } static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) { struct tifm_adapter *fm = dev_id; - struct tifm_dev *sock; unsigned int irq_status; unsigned int sock_irq_status, cnt; @@ -43,32 +84,42 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) if (irq_status & TIFM_IRQ_ENABLE) { writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); - for (cnt = 0; cnt < fm->num_sockets; cnt++) { - sock = fm->sockets[cnt]; - sock_irq_status = (irq_status >> cnt) - & (TIFM_IRQ_FIFOMASK(1) - | TIFM_IRQ_CARDMASK(1)); + for (cnt = 0; cnt < fm->max_sockets; cnt++) { + sock_irq_status = (irq_status >> cnt) & + (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK); - if (sock && sock_irq_status) - sock->signal_irq(sock, sock_irq_status); - } + if (fm->sockets[cnt]) { + if (sock_irq_status && + fm->sockets[cnt]->signal_irq) + sock_irq_status = fm->sockets[cnt]-> + signal_irq(fm->sockets[cnt], + sock_irq_status); - fm->socket_change_set |= irq_status - & ((1 << fm->num_sockets) - 1); + if (irq_status & (1 << cnt)) + fm->remove_mask |= 1 << cnt; + } else { + if (irq_status & (1 << cnt)) + fm->insert_mask |= 1 << cnt; + } + } } writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); - if (!fm->socket_change_set) - writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); - else - wake_up_all(&fm->change_set_notify); + if (!fm->inhibit_new_cards) { + if (!fm->remove_mask && !fm->insert_mask) { + writel(TIFM_IRQ_ENABLE, + fm->addr + FM_SET_INTERRUPT_ENABLE); + } else { + queue_work(fm->wq, &fm->media_remover); + queue_work(fm->wq, &fm->media_inserter); + } + } spin_unlock(&fm->lock); return IRQ_HANDLED; } -static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, - int is_x2) +static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2) { unsigned int s_state; int cnt; @@ -76,8 +127,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, writel(0x0e00, sock_addr + SOCK_CONTROL); for (cnt = 0; cnt < 100; cnt++) { - if (!(TIFM_SOCK_STATE_POWERED - & readl(sock_addr + SOCK_PRESENT_STATE))) + if (!(TIFM_SOCK_STATE_POWERED & + readl(sock_addr + SOCK_PRESENT_STATE))) break; msleep(10); } @@ -100,8 +151,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, } for (cnt = 0; cnt < 100; cnt++) { - if ((TIFM_SOCK_STATE_POWERED - & readl(sock_addr + SOCK_PRESENT_STATE))) + if ((TIFM_SOCK_STATE_POWERED & + readl(sock_addr + SOCK_PRESENT_STATE))) break; msleep(10); } @@ -119,209 +170,130 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) return base_addr + ((sock_num + 1) << 10); } -static int tifm_7xx1_switch_media(void *data) +static void tifm_7xx1_insert_media(struct work_struct *work) { - struct tifm_adapter *fm = data; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_inserter); unsigned long flags; tifm_media_id media_id; char *card_name = "xx"; - int cnt, rc; - struct tifm_dev *sock; - unsigned int socket_change_set; - - while (1) { - rc = wait_event_interruptible(fm->change_set_notify, - fm->socket_change_set); - if (rc == -ERESTARTSYS) - try_to_freeze(); - - spin_lock_irqsave(&fm->lock, flags); - socket_change_set = fm->socket_change_set; - fm->socket_change_set = 0; + int cnt, ok_to_register; + unsigned int insert_mask; + struct tifm_dev *new_sock = NULL; - dev_dbg(fm->dev, "checking media set %x\n", - socket_change_set); - - if (kthread_should_stop()) - socket_change_set = (1 << fm->num_sockets) - 1; + if (!class_device_get(&fm->cdev)) + return; + spin_lock_irqsave(&fm->lock, flags); + insert_mask = fm->insert_mask; + fm->insert_mask = 0; + if (fm->inhibit_new_cards) { spin_unlock_irqrestore(&fm->lock, flags); + class_device_put(&fm->cdev); + return; + } + spin_unlock_irqrestore(&fm->lock, flags); - if (!socket_change_set) + for (cnt = 0; cnt < fm->max_sockets; cnt++) { + if (!(insert_mask & (1 << cnt))) continue; - spin_lock_irqsave(&fm->lock, flags); - for (cnt = 0; cnt < fm->num_sockets; cnt++) { - if (!(socket_change_set & (1 << cnt))) - continue; - sock = fm->sockets[cnt]; - if (sock) { + media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt), + fm->max_sockets == 2); + if (media_id) { + ok_to_register = 0; + new_sock = tifm_alloc_device(fm, cnt); + if (new_sock) { + new_sock->addr = tifm_7xx1_sock_addr(fm->addr, + cnt); + new_sock->media_id = media_id; + switch (media_id) { + case 1: + card_name = "xd"; + break; + case 2: + card_name = "ms"; + break; + case 3: + card_name = "sd"; + break; + default: + break; + } + snprintf(new_sock->dev.bus_id, BUS_ID_SIZE, + "tifm_%s%u:%u", card_name, fm->id, cnt); printk(KERN_INFO DRIVER_NAME - ": demand removing card from socket %d\n", - cnt); - fm->sockets[cnt] = NULL; - spin_unlock_irqrestore(&fm->lock, flags); - device_unregister(&sock->dev); + ": %s card detected in socket %d\n", + card_name, cnt); spin_lock_irqsave(&fm->lock, flags); - writel(0x0e00, - tifm_7xx1_sock_addr(fm->addr, cnt) - + SOCK_CONTROL); - } - if (kthread_should_stop()) - continue; - - spin_unlock_irqrestore(&fm->lock, flags); - media_id = tifm_7xx1_toggle_sock_power( - tifm_7xx1_sock_addr(fm->addr, cnt), - fm->num_sockets == 2); - if (media_id) { - sock = tifm_alloc_device(fm); - if (sock) { - sock->addr = tifm_7xx1_sock_addr(fm->addr, - cnt); - sock->media_id = media_id; - sock->socket_id = cnt; - switch (media_id) { - case 1: - card_name = "xd"; - break; - case 2: - card_name = "ms"; - break; - case 3: - card_name = "sd"; - break; - default: - tifm_free_device(&sock->dev); - spin_lock_irqsave(&fm->lock, flags); - continue; - } - snprintf(sock->dev.bus_id, BUS_ID_SIZE, - "tifm_%s%u:%u", card_name, - fm->id, cnt); - printk(KERN_INFO DRIVER_NAME - ": %s card detected in socket %d\n", - card_name, cnt); - if (!device_register(&sock->dev)) { - spin_lock_irqsave(&fm->lock, flags); - if (!fm->sockets[cnt]) { - fm->sockets[cnt] = sock; - sock = NULL; - } - spin_unlock_irqrestore(&fm->lock, flags); - } - if (sock) - tifm_free_device(&sock->dev); + if (!fm->sockets[cnt]) { + fm->sockets[cnt] = new_sock; + ok_to_register = 1; } - spin_lock_irqsave(&fm->lock, flags); - } - } - - if (!kthread_should_stop()) { - writel(TIFM_IRQ_FIFOMASK(socket_change_set) - | TIFM_IRQ_CARDMASK(socket_change_set), - fm->addr + FM_CLEAR_INTERRUPT_ENABLE); - writel(TIFM_IRQ_FIFOMASK(socket_change_set) - | TIFM_IRQ_CARDMASK(socket_change_set), - fm->addr + FM_SET_INTERRUPT_ENABLE); - writel(TIFM_IRQ_ENABLE, - fm->addr + FM_SET_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&fm->lock, flags); - } else { - for (cnt = 0; cnt < fm->num_sockets; cnt++) { - if (fm->sockets[cnt]) - fm->socket_change_set |= 1 << cnt; - } - if (!fm->socket_change_set) { - spin_unlock_irqrestore(&fm->lock, flags); - return 0; - } else { spin_unlock_irqrestore(&fm->lock, flags); + if (!ok_to_register || + device_register(&new_sock->dev)) { + spin_lock_irqsave(&fm->lock, flags); + fm->sockets[cnt] = NULL; + spin_unlock_irqrestore(&fm->lock, + flags); + tifm_free_device(&new_sock->dev); + } } } + writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, + fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, + fm->addr + FM_SET_INTERRUPT_ENABLE); } - return 0; -} -#ifdef CONFIG_PM + writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); + class_device_put(&fm->cdev); +} static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) { - dev_dbg(&dev->dev, "suspending host\n"); + struct tifm_adapter *fm = pci_get_drvdata(dev); + unsigned long flags; - pci_save_state(dev); - pci_enable_wake(dev, pci_choose_state(dev, state), 0); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); + spin_lock_irqsave(&fm->lock, flags); + fm->inhibit_new_cards = 1; + fm->remove_mask = 0xf; + fm->insert_mask = 0; + writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + spin_unlock_irqrestore(&fm->lock, flags); + flush_workqueue(fm->wq); + + tifm_7xx1_remove_media(&fm->media_remover); + + pci_set_power_state(dev, PCI_D3hot); + pci_disable_device(dev); + pci_save_state(dev); return 0; } static int tifm_7xx1_resume(struct pci_dev *dev) { struct tifm_adapter *fm = pci_get_drvdata(dev); - int cnt, rc; unsigned long flags; - tifm_media_id new_ids[fm->num_sockets]; - pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); - rc = pci_enable_device(dev); - if (rc) - return rc; - pci_set_master(dev); + pci_enable_device(dev); + pci_set_power_state(dev, PCI_D0); + pci_set_master(dev); - dev_dbg(&dev->dev, "resuming host\n"); - - for (cnt = 0; cnt < fm->num_sockets; cnt++) - new_ids[cnt] = tifm_7xx1_toggle_sock_power( - tifm_7xx1_sock_addr(fm->addr, cnt), - fm->num_sockets == 2); spin_lock_irqsave(&fm->lock, flags); - fm->socket_change_set = 0; - for (cnt = 0; cnt < fm->num_sockets; cnt++) { - if (fm->sockets[cnt]) { - if (fm->sockets[cnt]->media_id == new_ids[cnt]) - fm->socket_change_set |= 1 << cnt; - - fm->sockets[cnt]->media_id = new_ids[cnt]; - } - } - - writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), - fm->addr + FM_SET_INTERRUPT_ENABLE); - if (!fm->socket_change_set) { - spin_unlock_irqrestore(&fm->lock, flags); - return 0; - } else { - fm->socket_change_set = 0; - spin_unlock_irqrestore(&fm->lock, flags); - } - - wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ); - - spin_lock_irqsave(&fm->lock, flags); - writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set) - | TIFM_IRQ_CARDMASK(fm->socket_change_set), - fm->addr + FM_CLEAR_INTERRUPT_ENABLE); - writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set) - | TIFM_IRQ_CARDMASK(fm->socket_change_set), - fm->addr + FM_SET_INTERRUPT_ENABLE); - writel(TIFM_IRQ_ENABLE, - fm->addr + FM_SET_INTERRUPT_ENABLE); - fm->socket_change_set = 0; - + fm->inhibit_new_cards = 0; + writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS); + writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, + fm->addr + FM_SET_INTERRUPT_ENABLE); + fm->insert_mask = 0xf; spin_unlock_irqrestore(&fm->lock, flags); return 0; } -#else - -#define tifm_7xx1_suspend NULL -#define tifm_7xx1_resume NULL - -#endif /* CONFIG_PM */ - static int tifm_7xx1_probe(struct pci_dev *dev, - const struct pci_device_id *dev_id) + const struct pci_device_id *dev_id) { struct tifm_adapter *fm; int pci_dev_busy = 0; @@ -352,18 +324,19 @@ static int tifm_7xx1_probe(struct pci_dev *dev, } fm->dev = &dev->dev; - fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM) - ? 4 : 2; - fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets, - GFP_KERNEL); + fm->max_sockets = (dev->device == 0x803B) ? 2 : 4; + fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets, + GFP_KERNEL); if (!fm->sockets) goto err_out_free; + INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media); + INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); fm->addr = ioremap(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); + pci_resource_len(dev, 0)); if (!fm->addr) goto err_out_free; @@ -371,15 +344,16 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (rc) goto err_out_unmap; - init_waitqueue_head(&fm->change_set_notify); - rc = tifm_add_adapter(fm, tifm_7xx1_switch_media); + rc = tifm_add_adapter(fm); if (rc) goto err_out_irq; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); - writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), - fm->addr + FM_SET_INTERRUPT_ENABLE); - wake_up_process(fm->media_switcher); + writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, + fm->addr + FM_SET_INTERRUPT_ENABLE); + + fm->insert_mask = 0xf; + return 0; err_out_irq: @@ -403,15 +377,19 @@ static void tifm_7xx1_remove(struct pci_dev *dev) struct tifm_adapter *fm = pci_get_drvdata(dev); unsigned long flags; - writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); - mmiowb(); - free_irq(dev->irq, fm); - spin_lock_irqsave(&fm->lock, flags); - fm->socket_change_set = (1 << fm->num_sockets) - 1; + fm->inhibit_new_cards = 1; + fm->remove_mask = 0xf; + fm->insert_mask = 0; + writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); spin_unlock_irqrestore(&fm->lock, flags); - kthread_stop(fm->media_switcher); + flush_workqueue(fm->wq); + + tifm_7xx1_remove_media(&fm->media_remover); + + writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + free_irq(dev->irq, fm); tifm_remove_adapter(fm); @@ -426,12 +404,10 @@ static void tifm_7xx1_remove(struct pci_dev *dev) } static struct pci_device_id tifm_7xx1_pci_tbl [] = { - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + 0 }, /* xx21 - the one I have */ + { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + 0 }, /* xx12 - should be also supported */ { } }; diff --git a/trunk/drivers/misc/tifm_core.c b/trunk/drivers/misc/tifm_core.c index 6b10ebe9d936..d61df5c3ac36 100644 --- a/trunk/drivers/misc/tifm_core.c +++ b/trunk/drivers/misc/tifm_core.c @@ -14,7 +14,7 @@ #include #define DRIVER_NAME "tifm_core" -#define DRIVER_VERSION "0.7" +#define DRIVER_VERSION "0.6" static DEFINE_IDR(tifm_adapter_idr); static DEFINE_SPINLOCK(tifm_adapter_lock); @@ -60,41 +60,10 @@ static int tifm_uevent(struct device *dev, char **envp, int num_envp, return 0; } -#ifdef CONFIG_PM - -static int tifm_device_suspend(struct device *dev, pm_message_t state) -{ - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *drv = fm_dev->drv; - - if (drv && drv->suspend) - return drv->suspend(fm_dev, state); - return 0; -} - -static int tifm_device_resume(struct device *dev) -{ - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *drv = fm_dev->drv; - - if (drv && drv->resume) - return drv->resume(fm_dev); - return 0; -} - -#else - -#define tifm_device_suspend NULL -#define tifm_device_resume NULL - -#endif /* CONFIG_PM */ - static struct bus_type tifm_bus_type = { .name = "tifm", .match = tifm_match, .uevent = tifm_uevent, - .suspend = tifm_device_suspend, - .resume = tifm_device_resume }; static void tifm_free(struct class_device *cdev) @@ -102,6 +71,8 @@ static void tifm_free(struct class_device *cdev) struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); kfree(fm->sockets); + if (fm->wq) + destroy_workqueue(fm->wq); kfree(fm); } @@ -130,8 +101,7 @@ void tifm_free_adapter(struct tifm_adapter *fm) } EXPORT_SYMBOL(tifm_free_adapter); -int tifm_add_adapter(struct tifm_adapter *fm, - int (*mediathreadfn)(void *data)) +int tifm_add_adapter(struct tifm_adapter *fm) { int rc; @@ -143,10 +113,10 @@ int tifm_add_adapter(struct tifm_adapter *fm, spin_unlock(&tifm_adapter_lock); if (!rc) { snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); - fm->media_switcher = kthread_create(mediathreadfn, - fm, "tifm/%u", fm->id); + strncpy(fm->wq_name, fm->cdev.class_id, KOBJ_NAME_LEN); - if (!IS_ERR(fm->media_switcher)) + fm->wq = create_singlethread_workqueue(fm->wq_name); + if (fm->wq) return class_device_add(&fm->cdev); spin_lock(&tifm_adapter_lock); @@ -171,27 +141,27 @@ EXPORT_SYMBOL(tifm_remove_adapter); void tifm_free_device(struct device *dev) { struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); + if (fm_dev->wq) + destroy_workqueue(fm_dev->wq); kfree(fm_dev); } EXPORT_SYMBOL(tifm_free_device); -static void tifm_dummy_signal_irq(struct tifm_dev *sock, - unsigned int sock_irq_status) -{ - return; -} - -struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) +struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id) { struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); if (dev) { spin_lock_init(&dev->lock); - + snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id); + dev->wq = create_singlethread_workqueue(dev->wq_name); + if (!dev->wq) { + kfree(dev); + return NULL; + } dev->dev.parent = fm->dev; dev->dev.bus = &tifm_bus_type; dev->dev.release = tifm_free_device; - dev->signal_irq = tifm_dummy_signal_irq; } return dev; } @@ -249,7 +219,6 @@ static int tifm_device_remove(struct device *dev) struct tifm_driver *drv = fm_dev->drv; if (drv) { - fm_dev->signal_irq = tifm_dummy_signal_irq; if (drv->remove) drv->remove(fm_dev); fm_dev->drv = NULL; @@ -264,8 +233,6 @@ int tifm_register_driver(struct tifm_driver *drv) drv->driver.bus = &tifm_bus_type; drv->driver.probe = tifm_device_probe; drv->driver.remove = tifm_device_remove; - drv->driver.suspend = tifm_device_suspend; - drv->driver.resume = tifm_device_resume; return driver_register(&drv->driver); } diff --git a/trunk/drivers/mmc/at91_mci.c b/trunk/drivers/mmc/at91_mci.c index 2ce50f38e3c7..aa152f31851e 100644 --- a/trunk/drivers/mmc/at91_mci.c +++ b/trunk/drivers/mmc/at91_mci.c @@ -823,9 +823,6 @@ static int __init at91_mci_probe(struct platform_device *pdev) mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_BYTEBLOCK; - mmc->max_blk_size = 4095; - mmc->max_blk_count = mmc->max_req_size; - host = mmc_priv(mmc); host->mmc = mmc; host->buffer = NULL; diff --git a/trunk/drivers/mmc/au1xmmc.c b/trunk/drivers/mmc/au1xmmc.c index b834be261ab7..800527cf40d5 100644 --- a/trunk/drivers/mmc/au1xmmc.c +++ b/trunk/drivers/mmc/au1xmmc.c @@ -152,9 +152,8 @@ static inline int au1xmmc_card_inserted(struct au1xmmc_host *host) ? 1 : 0; } -static int au1xmmc_card_readonly(struct mmc_host *mmc) +static inline int au1xmmc_card_readonly(struct au1xmmc_host *host) { - struct au1xmmc_host *host = mmc_priv(mmc); return (bcsr->status & au1xmmc_card_table[host->id].wpstatus) ? 1 : 0; } @@ -194,8 +193,6 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); switch (mmc_resp_type(cmd)) { - case MMC_RSP_NONE: - break; case MMC_RSP_R1: mmccmd |= SD_CMD_RT_1; break; @@ -208,10 +205,6 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, case MMC_RSP_R3: mmccmd |= SD_CMD_RT_3; break; - default: - printk(KERN_INFO "au1xmmc: unhandled response type %02x\n", - mmc_resp_type(cmd)); - return MMC_ERR_INVALID; } switch(cmd->opcode) { @@ -885,7 +878,6 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host) static const struct mmc_host_ops au1xmmc_ops = { .request = au1xmmc_request, .set_ios = au1xmmc_set_ios, - .get_ro = au1xmmc_card_readonly, }; static int __devinit au1xmmc_probe(struct platform_device *pdev) @@ -922,9 +914,6 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; - mmc->max_blk_size = 2048; - mmc->max_blk_count = 512; - mmc->ocr_avail = AU1XMMC_OCR; host = mmc_priv(mmc); diff --git a/trunk/drivers/mmc/imxmmc.c b/trunk/drivers/mmc/imxmmc.c index b060d4bfba29..bfb9ff693208 100644 --- a/trunk/drivers/mmc/imxmmc.c +++ b/trunk/drivers/mmc/imxmmc.c @@ -958,10 +958,8 @@ static int imxmci_probe(struct platform_device *pdev) /* MMC core transfer sizes tunable parameters */ mmc->max_hw_segs = 64; mmc->max_phys_segs = 64; + mmc->max_sectors = 64; /* default 1 << (PAGE_CACHE_SHIFT - 9) */ mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ - mmc->max_req_size = 64*512; /* default PAGE_CACHE_SIZE */ - mmc->max_blk_size = 2048; - mmc->max_blk_count = 65535; host = mmc_priv(mmc); host->mmc = mmc; diff --git a/trunk/drivers/mmc/mmc.c b/trunk/drivers/mmc/mmc.c index 5046a1661342..6f2a282e2b97 100644 --- a/trunk/drivers/mmc/mmc.c +++ b/trunk/drivers/mmc/mmc.c @@ -103,16 +103,11 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mmc_hostname(host), mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); - WARN_ON(!host->claimed); + WARN_ON(host->card_busy == NULL); mrq->cmd->error = 0; mrq->cmd->mrq = mrq; if (mrq->data) { - BUG_ON(mrq->data->blksz > host->max_blk_size); - BUG_ON(mrq->data->blocks > host->max_blk_count); - BUG_ON(mrq->data->blocks * mrq->data->blksz > - host->max_req_size); - mrq->cmd->data = mrq->data; mrq->data->error = 0; mrq->data->mrq = mrq; @@ -162,7 +157,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries { struct mmc_request mrq; - BUG_ON(!host->claimed); + BUG_ON(host->card_busy == NULL); memset(&mrq, 0, sizeof(struct mmc_request)); @@ -200,7 +195,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, int i, err; - BUG_ON(!host->claimed); + BUG_ON(host->card_busy == NULL); BUG_ON(retries < 0); err = MMC_ERR_INVALID; @@ -294,10 +289,7 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, else limit_us = 100000; - /* - * SDHC cards always use these fixed values. - */ - if (timeout_us > limit_us || mmc_card_blockaddr(card)) { + if (timeout_us > limit_us) { data->timeout_ns = limit_us * 1000; data->timeout_clks = 0; } @@ -328,14 +320,14 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card) spin_lock_irqsave(&host->lock, flags); while (1) { set_current_state(TASK_UNINTERRUPTIBLE); - if (!host->claimed) + if (host->card_busy == NULL) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); spin_lock_irqsave(&host->lock, flags); } set_current_state(TASK_RUNNING); - host->claimed = 1; + host->card_busy = card; spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); @@ -361,10 +353,10 @@ void mmc_release_host(struct mmc_host *host) { unsigned long flags; - BUG_ON(!host->claimed); + BUG_ON(host->card_busy == NULL); spin_lock_irqsave(&host->lock, flags); - host->claimed = 0; + host->card_busy = NULL; spin_unlock_irqrestore(&host->lock, flags); wake_up(&host->wq); @@ -380,7 +372,7 @@ static inline void mmc_set_ios(struct mmc_host *host) mmc_hostname(host), ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, ios->vdd, ios->bus_width); - + host->ops->set_ios(host, ios); } @@ -389,7 +381,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) int err; struct mmc_command cmd; - BUG_ON(!host->claimed); + BUG_ON(host->card_busy == NULL); if (host->card_selected == card) return MMC_ERR_NONE; @@ -596,65 +588,34 @@ static void mmc_decode_csd(struct mmc_card *card) if (mmc_card_sd(card)) { csd_struct = UNSTUFF_BITS(resp, 126, 2); - - switch (csd_struct) { - case 0: - m = UNSTUFF_BITS(resp, 115, 4); - e = UNSTUFF_BITS(resp, 112, 3); - csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; - csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; - - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); - csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - e = UNSTUFF_BITS(resp, 47, 3); - m = UNSTUFF_BITS(resp, 62, 12); - csd->capacity = (1 + m) << (e + 2); - - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); - csd->read_partial = UNSTUFF_BITS(resp, 79, 1); - csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); - csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); - csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); - csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); - csd->write_partial = UNSTUFF_BITS(resp, 21, 1); - break; - case 1: - /* - * This is a block-addressed SDHC card. Most - * interesting fields are unused and have fixed - * values. To avoid getting tripped by buggy cards, - * we assume those fixed values ourselves. - */ - mmc_card_set_blockaddr(card); - - csd->tacc_ns = 0; /* Unused */ - csd->tacc_clks = 0; /* Unused */ - - m = UNSTUFF_BITS(resp, 99, 4); - e = UNSTUFF_BITS(resp, 96, 3); - csd->max_dtr = tran_exp[e] * tran_mant[m]; - csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); - - m = UNSTUFF_BITS(resp, 48, 22); - csd->capacity = (1 + m) << 10; - - csd->read_blkbits = 9; - csd->read_partial = 0; - csd->write_misalign = 0; - csd->read_misalign = 0; - csd->r2w_factor = 4; /* Unused */ - csd->write_blkbits = 9; - csd->write_partial = 0; - break; - default: + if (csd_struct != 0) { printk("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } + + m = UNSTUFF_BITS(resp, 115, 4); + e = UNSTUFF_BITS(resp, 112, 3); + csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; + csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; + + m = UNSTUFF_BITS(resp, 99, 4); + e = UNSTUFF_BITS(resp, 96, 3); + csd->max_dtr = tran_exp[e] * tran_mant[m]; + csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); + + e = UNSTUFF_BITS(resp, 47, 3); + m = UNSTUFF_BITS(resp, 62, 12); + csd->capacity = (1 + m) << (e + 2); + + csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); + csd->read_partial = UNSTUFF_BITS(resp, 79, 1); + csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); + csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); + csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); + csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); + csd->write_partial = UNSTUFF_BITS(resp, 21, 1); } else { /* * We only understand CSD structure v1.1 and v1.2. @@ -887,41 +848,6 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) return err; } -static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2) -{ - struct mmc_command cmd; - int err, sd2; - static const u8 test_pattern = 0xAA; - - /* - * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND - * before SD_APP_OP_COND. This command will harmlessly fail for - * SD 1.0 cards. - */ - cmd.opcode = SD_SEND_IF_COND; - cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; - cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; - - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err == MMC_ERR_NONE) { - if ((cmd.resp[0] & 0xFF) == test_pattern) { - sd2 = 1; - } else { - sd2 = 0; - err = MMC_ERR_FAILED; - } - } else { - /* - * Treat errors as SD 1.0 card. - */ - sd2 = 0; - err = MMC_ERR_NONE; - } - if (rsd2) - *rsd2 = sd2; - return err; -} - /* * Discover cards by requesting their CID. If this command * times out, it is not an error; there are no further cards @@ -1092,8 +1018,7 @@ static void mmc_process_ext_csds(struct mmc_host *host) mmc_wait_for_req(host, &mrq); if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { - printk("%s: unable to read EXT_CSD, performance " - "might suffer.\n", mmc_hostname(card->host)); + mmc_card_set_dead(card); continue; } @@ -1109,6 +1034,7 @@ static void mmc_process_ext_csds(struct mmc_host *host) printk("%s: card is mmc v4 but doesn't support " "any high-speed modes.\n", mmc_hostname(card->host)); + mmc_card_set_bad(card); continue; } @@ -1289,9 +1215,7 @@ static void mmc_read_switch_caps(struct mmc_host *host) mmc_wait_for_req(host, &mrq); if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { - printk("%s: unable to read switch capabilities, " - "performance might suffer.\n", - mmc_hostname(card->host)); + mmc_card_set_dead(card); continue; } @@ -1323,8 +1247,12 @@ static void mmc_read_switch_caps(struct mmc_host *host) mmc_wait_for_req(host, &mrq); - if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE || - (status[16] & 0xF) != 1) { + if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + if ((status[16] & 0xF) != 1) { printk(KERN_WARNING "%s: Problem switching card " "into high-speed mode!\n", mmc_hostname(host)); @@ -1406,10 +1334,6 @@ static void mmc_setup(struct mmc_host *host) mmc_power_up(host); mmc_idle_cards(host); - err = mmc_send_if_cond(host, host->ocr_avail, NULL); - if (err != MMC_ERR_NONE) { - return; - } err = mmc_send_app_op_cond(host, 0, &ocr); /* @@ -1462,21 +1386,10 @@ static void mmc_setup(struct mmc_host *host) * all get the idea that they should be ready for CMD2. * (My SanDisk card seems to need this.) */ - if (host->mode == MMC_MODE_SD) { - int err, sd2; - err = mmc_send_if_cond(host, host->ocr, &sd2); - if (err == MMC_ERR_NONE) { - /* - * If SD_SEND_IF_COND indicates an SD 2.0 - * compliant card and we should set bit 30 - * of the ocr to indicate that we can handle - * block-addressed SDHC cards. - */ - mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL); - } - } else { + if (host->mode == MMC_MODE_SD) + mmc_send_app_op_cond(host, host->ocr, NULL); + else mmc_send_op_cond(host, host->ocr, NULL); - } mmc_discover_cards(host); @@ -1606,11 +1519,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) */ host->max_hw_segs = 1; host->max_phys_segs = 1; + host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); host->max_seg_size = PAGE_CACHE_SIZE; - - host->max_req_size = PAGE_CACHE_SIZE; - host->max_blk_size = 512; - host->max_blk_count = PAGE_CACHE_SIZE / 512; } return host; diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index 05ba8ace70e7..87713572293f 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -237,17 +237,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.mrq.cmd = &brq.cmd; brq.mrq.data = &brq.data; - brq.cmd.arg = req->sector; - if (!mmc_card_blockaddr(card)) - brq.cmd.arg <<= 9; + brq.cmd.arg = req->sector << 9; brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; brq.data.blksz = 1 << md->block_bits; + brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); brq.stop.opcode = MMC_STOP_TRANSMISSION; brq.stop.arg = 0; brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; - brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); - if (brq.data.blocks > card->host->max_blk_count) - brq.data.blocks = card->host->max_blk_count; mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); @@ -379,10 +375,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) spin_unlock_irq(&md->lock); } -flush_queue: - mmc_card_release_host(card); +flush_queue: spin_lock_irq(&md->lock); while (ret) { ret = end_that_request_chunk(req, 0, @@ -499,10 +494,6 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) struct mmc_command cmd; int err; - /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ - if (mmc_card_blockaddr(card)) - return 0; - mmc_card_claim_host(card); cmd.opcode = MMC_SET_BLOCKLEN; cmd.arg = 1 << md->block_bits; diff --git a/trunk/drivers/mmc/mmc_queue.c b/trunk/drivers/mmc/mmc_queue.c index c27e42645cdb..3e35a43819fb 100644 --- a/trunk/drivers/mmc/mmc_queue.c +++ b/trunk/drivers/mmc/mmc_queue.c @@ -147,7 +147,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_prep_rq(mq->queue, mmc_prep_request); blk_queue_bounce_limit(mq->queue, limit); - blk_queue_max_sectors(mq->queue, host->max_req_size / 512); + blk_queue_max_sectors(mq->queue, host->max_sectors); blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); diff --git a/trunk/drivers/mmc/mmc_sysfs.c b/trunk/drivers/mmc/mmc_sysfs.c index d32698b02d7f..e334acd045bc 100644 --- a/trunk/drivers/mmc/mmc_sysfs.c +++ b/trunk/drivers/mmc/mmc_sysfs.c @@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) memset(card, 0, sizeof(struct mmc_card)); card->host = host; device_initialize(&card->dev); - card->dev.parent = mmc_classdev(host); + card->dev.parent = mmc_dev(host); card->dev.bus = &mmc_bus_type; card->dev.release = mmc_release_card; } diff --git a/trunk/drivers/mmc/mmci.c b/trunk/drivers/mmc/mmci.c index 5941dd951e82..ccfe6561be24 100644 --- a/trunk/drivers/mmc/mmci.c +++ b/trunk/drivers/mmc/mmci.c @@ -524,24 +524,15 @@ static int mmci_probe(struct amba_device *dev, void *id) /* * Since we only have a 16-bit data length register, we must * ensure that we don't exceed 2^16-1 bytes in a single request. + * Choose 64 (512-byte) sectors as the limit. */ - mmc->max_req_size = 65535; + mmc->max_sectors = 64; /* * Set the maximum segment size. Since we aren't doing DMA * (yet) we are only limited by the data length register. */ - mmc->max_seg_size = mmc->max_req_size; - - /* - * Block size can be up to 2048 bytes, but must be a power of two. - */ - mmc->max_blk_size = 2048; - - /* - * No limit on the number of blocks transferred. - */ - mmc->max_blk_count = mmc->max_req_size; + mmc->max_seg_size = mmc->max_sectors << 9; spin_lock_init(&host->lock); diff --git a/trunk/drivers/mmc/omap.c b/trunk/drivers/mmc/omap.c index 1e96a2f65022..d30540b27614 100644 --- a/trunk/drivers/mmc/omap.c +++ b/trunk/drivers/mmc/omap.c @@ -1099,10 +1099,8 @@ static int __init mmc_omap_probe(struct platform_device *pdev) */ mmc->max_phys_segs = 32; mmc->max_hw_segs = 32; - mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */ - mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */ - mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - mmc->max_seg_size = mmc->max_req_size; + mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */ + mmc->max_seg_size = mmc->max_sectors * 512; if (host->power_pin >= 0) { if ((ret = omap_request_gpio(host->power_pin)) != 0) { diff --git a/trunk/drivers/mmc/pxamci.c b/trunk/drivers/mmc/pxamci.c index 9774fc68b61a..6073d998b11f 100644 --- a/trunk/drivers/mmc/pxamci.c +++ b/trunk/drivers/mmc/pxamci.c @@ -450,16 +450,6 @@ static int pxamci_probe(struct platform_device *pdev) */ mmc->max_seg_size = PAGE_SIZE; - /* - * Block length register is 10 bits. - */ - mmc->max_blk_size = 1023; - - /* - * Block count register is 16 bits. - */ - mmc->max_blk_count = 65535; - host = mmc_priv(mmc); host->mmc = mmc; host->dma = -1; diff --git a/trunk/drivers/mmc/sdhci.c b/trunk/drivers/mmc/sdhci.c index 4bf1fea5e2c4..c2d13d7e9911 100644 --- a/trunk/drivers/mmc/sdhci.c +++ b/trunk/drivers/mmc/sdhci.c @@ -37,7 +37,6 @@ static unsigned int debug_quirks = 0; #define SDHCI_QUIRK_FORCE_DMA (1<<1) /* Controller doesn't like some resets when there is no card inserted. */ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) -#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) static const struct pci_device_id pci_ids[] __devinitdata = { { @@ -66,14 +65,6 @@ static const struct pci_device_id pci_ids[] __devinitdata = { .driver_data = SDHCI_QUIRK_FORCE_DMA, }, - { - .vendor = PCI_VENDOR_ID_ENE, - .device = PCI_DEVICE_ID_ENE_CB712_SD, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, - }, - { /* Generic SD host controller */ PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) }, @@ -206,9 +197,15 @@ static void sdhci_deactivate_led(struct sdhci_host *host) * * \*****************************************************************************/ -static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) +static inline char* sdhci_kmap_sg(struct sdhci_host* host) { - return page_address(host->cur_sg->page) + host->cur_sg->offset; + host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ); + return host->mapped_sg + host->cur_sg->offset; +} + +static inline void sdhci_kunmap_sg(struct sdhci_host* host) +{ + kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); } static inline int sdhci_next_sg(struct sdhci_host* host) @@ -243,7 +240,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) chunk_remain = 0; data = 0; - buffer = sdhci_sg_to_buffer(host) + host->offset; + buffer = sdhci_kmap_sg(host) + host->offset; while (blksize) { if (chunk_remain == 0) { @@ -267,13 +264,16 @@ static void sdhci_read_block_pio(struct sdhci_host *host) } if (host->remain == 0) { + sdhci_kunmap_sg(host); if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; } - buffer = sdhci_sg_to_buffer(host); + buffer = sdhci_kmap_sg(host); } } + + sdhci_kunmap_sg(host); } static void sdhci_write_block_pio(struct sdhci_host *host) @@ -290,7 +290,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) data = 0; bytes = 0; - buffer = sdhci_sg_to_buffer(host) + host->offset; + buffer = sdhci_kmap_sg(host) + host->offset; while (blksize) { size = min(host->size, host->remain); @@ -314,13 +314,16 @@ static void sdhci_write_block_pio(struct sdhci_host *host) } if (host->remain == 0) { + sdhci_kunmap_sg(host); if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; } - buffer = sdhci_sg_to_buffer(host); + buffer = sdhci_kmap_sg(host); } } + + sdhci_kunmap_sg(host); } static void sdhci_transfer_pio(struct sdhci_host *host) @@ -369,7 +372,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) /* Sanity checks */ BUG_ON(data->blksz * data->blocks > 524288); - BUG_ON(data->blksz > host->mmc->max_blk_size); + BUG_ON(data->blksz > host->max_block); BUG_ON(data->blocks > 65535); /* timeout in us */ @@ -671,17 +674,10 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) if (host->power == power) return; - if (power == (unsigned short)-1) { - writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); - goto out; - } + writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); - /* - * Spec says that we should clear the power reg before setting - * a new value. Some controllers don't seem to like this though. - */ - if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) - writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); + if (power == (unsigned short)-1) + goto out; pwr = SDHCI_POWER_ON; @@ -1113,9 +1109,7 @@ static int sdhci_resume (struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - ret = pci_enable_device(pdev); - if (ret) - return ret; + pci_enable_device(pdev); for (i = 0;i < chip->num_slots;i++) { if (!chip->hosts[i]) @@ -1280,6 +1274,15 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) if (caps & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; + host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; + if (host->max_block >= 3) { + printk(KERN_ERR "%s: Invalid maximum block size.\n", + host->slot_descr); + ret = -ENODEV; + goto unmap; + } + host->max_block = 512 << host->max_block; + /* * Set host parameters. */ @@ -1291,9 +1294,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) mmc->ocr_avail = 0; if (caps & SDHCI_CAN_VDD_330) mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; - if (caps & SDHCI_CAN_VDD_300) + else if (caps & SDHCI_CAN_VDD_300) mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; - if (caps & SDHCI_CAN_VDD_180) + else if (caps & SDHCI_CAN_VDD_180) mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { @@ -1323,33 +1326,15 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) /* * Maximum number of sectors in one transfer. Limited by DMA boundary - * size (512KiB). + * size (512KiB), which means (512 KiB/512=) 1024 entries. */ - mmc->max_req_size = 524288; + mmc->max_sectors = 1024; /* * Maximum segment size. Could be one segment with the maximum number - * of bytes. - */ - mmc->max_seg_size = mmc->max_req_size; - - /* - * Maximum block size. This varies from controller to controller and - * is specified in the capabilities register. - */ - mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; - if (mmc->max_blk_size >= 3) { - printk(KERN_ERR "%s: Invalid maximum block size.\n", - host->slot_descr); - ret = -ENODEV; - goto unmap; - } - mmc->max_blk_size = 512 << mmc->max_blk_size; - - /* - * Maximum block count. + * of sectors. */ - mmc->max_blk_count = 65535; + mmc->max_seg_size = mmc->max_sectors * 512; /* * Init tasklets. diff --git a/trunk/drivers/mmc/sdhci.h b/trunk/drivers/mmc/sdhci.h index e324f0a623dc..f9d1a0a6f03a 100644 --- a/trunk/drivers/mmc/sdhci.h +++ b/trunk/drivers/mmc/sdhci.h @@ -174,6 +174,7 @@ struct sdhci_host { unsigned int max_clk; /* Max possible freq (MHz) */ unsigned int timeout_clk; /* Timeout freq (KHz) */ + unsigned int max_block; /* Max block size (bytes) */ unsigned int clock; /* Current clock (MHz) */ unsigned short power; /* Current voltage */ @@ -183,6 +184,7 @@ struct sdhci_host { struct mmc_data *data; /* Current data request */ struct scatterlist *cur_sg; /* We're working on this */ + char *mapped_sg; /* This is where it's mapped */ int num_sg; /* Entries left */ int offset; /* Offset into current sg */ int remain; /* Bytes left in current */ diff --git a/trunk/drivers/mmc/tifm_sd.c b/trunk/drivers/mmc/tifm_sd.c index e65f8a0a9349..fa4a52886b97 100644 --- a/trunk/drivers/mmc/tifm_sd.c +++ b/trunk/drivers/mmc/tifm_sd.c @@ -17,7 +17,7 @@ #include #define DRIVER_NAME "tifm_sd" -#define DRIVER_VERSION "0.7" +#define DRIVER_VERSION "0.6" static int no_dma = 0; static int fixed_timeout = 0; @@ -79,6 +79,7 @@ typedef enum { enum { FIFO_RDY = 0x0001, /* hardware dependent value */ + HOST_REG = 0x0002, EJECT = 0x0004, EJECT_DONE = 0x0008, CARD_BUSY = 0x0010, @@ -94,53 +95,46 @@ struct tifm_sd { card_state_t state; unsigned int clk_freq; unsigned int clk_div; - unsigned long timeout_jiffies; + unsigned long timeout_jiffies; // software timeout - 2 sec - struct tasklet_struct finish_tasklet; - struct timer_list timer; struct mmc_request *req; - wait_queue_head_t notify; + struct work_struct cmd_handler; + struct delayed_work abort_handler; + wait_queue_head_t can_eject; size_t written_blocks; + char *buffer; size_t buffer_size; size_t buffer_pos; }; -static char* tifm_sd_data_buffer(struct mmc_data *data) -{ - return page_address(data->sg->page) + data->sg->offset; -} - static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, - unsigned int host_status) + unsigned int host_status) { struct mmc_command *cmd = host->req->cmd; unsigned int t_val = 0, cnt = 0; - char *buffer; if (host_status & TIFM_MMCSD_BRS) { /* in non-dma rx mode BRS fires when fifo is still not empty */ - if (no_dma && (cmd->data->flags & MMC_DATA_READ)) { - buffer = tifm_sd_data_buffer(host->req->data); + if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) { while (host->buffer_size > host->buffer_pos) { t_val = readl(sock->addr + SOCK_MMCSD_DATA); - buffer[host->buffer_pos++] = t_val & 0xff; - buffer[host->buffer_pos++] = + host->buffer[host->buffer_pos++] = t_val & 0xff; + host->buffer[host->buffer_pos++] = (t_val >> 8) & 0xff; } } return 1; - } else if (no_dma) { - buffer = tifm_sd_data_buffer(host->req->data); + } else if (host->buffer) { if ((cmd->data->flags & MMC_DATA_READ) && (host_status & TIFM_MMCSD_AF)) { for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { t_val = readl(sock->addr + SOCK_MMCSD_DATA); if (host->buffer_size > host->buffer_pos) { - buffer[host->buffer_pos++] = + host->buffer[host->buffer_pos++] = t_val & 0xff; - buffer[host->buffer_pos++] = + host->buffer[host->buffer_pos++] = (t_val >> 8) & 0xff; } } @@ -148,12 +142,11 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, && (host_status & TIFM_MMCSD_AE)) { for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { if (host->buffer_size > host->buffer_pos) { - t_val = buffer[host->buffer_pos++] - & 0x00ff; - t_val |= ((buffer[host->buffer_pos++]) - << 8) & 0xff00; + t_val = host->buffer[host->buffer_pos++] & 0x00ff; + t_val |= ((host->buffer[host->buffer_pos++]) << 8) + & 0xff00; writel(t_val, - sock->addr + SOCK_MMCSD_DATA); + sock->addr + SOCK_MMCSD_DATA); } } } @@ -213,7 +206,7 @@ static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd) cmd_mask |= TIFM_MMCSD_READ; dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n", - cmd->opcode, cmd->arg, cmd_mask); + cmd->opcode, cmd->arg, cmd_mask); writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH); writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW); @@ -246,78 +239,65 @@ static void tifm_sd_process_cmd(struct tifm_dev *sock, struct tifm_sd *host, tifm_sd_fetch_resp(cmd, sock); if (cmd->data) { host->state = BRS; - } else { + } else host->state = READY; - } goto change_state; } break; case BRS: if (tifm_sd_transfer_data(sock, host, host_status)) { - if (cmd->data->flags & MMC_DATA_WRITE) { - host->state = CARD; - } else { - if (no_dma) { - if (host->req->stop) { - tifm_sd_exec(host, host->req->stop); - host->state = SCMD; - } else { - host->state = READY; - } + if (!host->req->stop) { + if (cmd->data->flags & MMC_DATA_WRITE) { + host->state = CARD; } else { - host->state = FIFO; + host->state = + host->buffer ? READY : FIFO; } + goto change_state; } - goto change_state; + tifm_sd_exec(host, host->req->stop); + host->state = SCMD; } break; case SCMD: if (host_status & TIFM_MMCSD_EOC) { tifm_sd_fetch_resp(host->req->stop, sock); - host->state = READY; + if (cmd->error) { + host->state = READY; + } else if (cmd->data->flags & MMC_DATA_WRITE) { + host->state = CARD; + } else { + host->state = host->buffer ? READY : FIFO; + } goto change_state; } break; case CARD: - dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n", - host->written_blocks); if (!(host->flags & CARD_BUSY) && (host->written_blocks == cmd->data->blocks)) { - if (no_dma) { - if (host->req->stop) { - tifm_sd_exec(host, host->req->stop); - host->state = SCMD; - } else { - host->state = READY; - } - } else { - host->state = FIFO; - } + host->state = host->buffer ? READY : FIFO; goto change_state; } break; case FIFO: if (host->flags & FIFO_RDY) { + host->state = READY; host->flags &= ~FIFO_RDY; - if (host->req->stop) { - tifm_sd_exec(host, host->req->stop); - host->state = SCMD; - } else { - host->state = READY; - } goto change_state; } break; case READY: - tasklet_schedule(&host->finish_tasklet); + queue_work(sock->wq, &host->cmd_handler); return; } + queue_delayed_work(sock->wq, &host->abort_handler, + host->timeout_jiffies); } /* Called from interrupt handler */ -static void tifm_sd_signal_irq(struct tifm_dev *sock, - unsigned int sock_irq_status) +static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, + unsigned int sock_irq_status) { struct tifm_sd *host; unsigned int host_status = 0, fifo_status = 0; @@ -325,6 +305,7 @@ static void tifm_sd_signal_irq(struct tifm_dev *sock, spin_lock(&sock->lock); host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); + cancel_delayed_work(&host->abort_handler); if (sock_irq_status & FIFO_EVENT) { fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); @@ -337,17 +318,19 @@ static void tifm_sd_signal_irq(struct tifm_dev *sock, host_status = readl(sock->addr + SOCK_MMCSD_STATUS); writel(host_status, sock->addr + SOCK_MMCSD_STATUS); + if (!(host->flags & HOST_REG)) + queue_work(sock->wq, &host->cmd_handler); if (!host->req) goto done; if (host_status & TIFM_MMCSD_ERRMASK) { if (host_status & TIFM_MMCSD_CERR) error_code = MMC_ERR_FAILED; - else if (host_status - & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) + else if (host_status & + (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) error_code = MMC_ERR_TIMEOUT; - else if (host_status - & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) + else if (host_status & + (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) error_code = MMC_ERR_BADCRC; writel(TIFM_FIFO_INT_SETALL, @@ -357,11 +340,12 @@ static void tifm_sd_signal_irq(struct tifm_dev *sock, if (host->req->stop) { if (host->state == SCMD) { host->req->stop->error = error_code; - } else if (host->state == BRS - || host->state == CARD - || host->state == FIFO) { + } else if(host->state == BRS) { host->req->cmd->error = error_code; tifm_sd_exec(host, host->req->stop); + queue_delayed_work(sock->wq, + &host->abort_handler, + host->timeout_jiffies); host->state = SCMD; goto done; } else { @@ -375,8 +359,8 @@ static void tifm_sd_signal_irq(struct tifm_dev *sock, if (host_status & TIFM_MMCSD_CB) host->flags |= CARD_BUSY; - if ((host_status & TIFM_MMCSD_EOFB) - && (host->flags & CARD_BUSY)) { + if ((host_status & TIFM_MMCSD_EOFB) && + (host->flags & CARD_BUSY)) { host->written_blocks++; host->flags &= ~CARD_BUSY; } @@ -386,22 +370,22 @@ static void tifm_sd_signal_irq(struct tifm_dev *sock, tifm_sd_process_cmd(sock, host, host_status); done: dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", - host_status, fifo_status); + host_status, fifo_status); spin_unlock(&sock->lock); + return sock_irq_status; } -static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) +static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) { - struct tifm_dev *sock = host->dev; + struct tifm_dev *sock = card->dev; unsigned int dest_cnt; /* DMA style IO */ - dev_dbg(&sock->dev, "setting dma for %d blocks\n", - cmd->data->blocks); + writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); writel(ilog2(cmd->data->blksz) - 2, - sock->addr + SOCK_FIFO_PAGE_SIZE); + sock->addr + SOCK_FIFO_PAGE_SIZE); writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); @@ -415,7 +399,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) if (cmd->data->flags & MMC_DATA_WRITE) { writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, - sock->addr + SOCK_DMA_CONTROL); + sock->addr + SOCK_DMA_CONTROL); } else { writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); @@ -423,7 +407,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) } static void tifm_sd_set_data_timeout(struct tifm_sd *host, - struct mmc_data *data) + struct mmc_data *data) { struct tifm_dev *sock = host->dev; unsigned int data_timeout = data->timeout_clks; @@ -432,21 +416,22 @@ static void tifm_sd_set_data_timeout(struct tifm_sd *host, return; data_timeout += data->timeout_ns / - ((1000000000UL / host->clk_freq) * host->clk_div); + ((1000000000 / host->clk_freq) * host->clk_div); + data_timeout *= 10; // call it fudge factor for now if (data_timeout < 0xffff) { - writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); - writel((~TIFM_MMCSD_DPE) - & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), + writel((~TIFM_MMCSD_DPE) & + readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); + writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); } else { + writel(TIFM_MMCSD_DPE | + readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), + sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); data_timeout = (data_timeout >> 10) + 1; - if (data_timeout > 0xffff) + if(data_timeout > 0xffff) data_timeout = 0; /* set to unlimited */ writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); - writel(TIFM_MMCSD_DPE - | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), - sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); } } @@ -489,10 +474,11 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) } host->req = mrq; - mod_timer(&host->timer, jiffies + host->timeout_jiffies); host->state = CMD; + queue_delayed_work(sock->wq, &host->abort_handler, + host->timeout_jiffies); writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + sock->addr + SOCK_CONTROL); tifm_sd_exec(host, mrq->cmd); spin_unlock_irqrestore(&sock->lock, flags); return; @@ -507,9 +493,9 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd(unsigned long data) +static void tifm_sd_end_cmd(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -518,7 +504,6 @@ static void tifm_sd_end_cmd(unsigned long data) spin_lock_irqsave(&sock->lock, flags); - del_timer(&host->timer); mrq = host->req; host->req = NULL; host->state = IDLE; @@ -532,8 +517,8 @@ static void tifm_sd_end_cmd(unsigned long data) r_data = mrq->cmd->data; if (r_data) { if (r_data->flags & MMC_DATA_WRITE) { - r_data->bytes_xfered = host->written_blocks - * r_data->blksz; + r_data->bytes_xfered = host->written_blocks * + r_data->blksz; } else { r_data->bytes_xfered = r_data->blocks - readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; @@ -547,7 +532,7 @@ static void tifm_sd_end_cmd(unsigned long data) } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + sock->addr + SOCK_CONTROL); spin_unlock_irqrestore(&sock->lock, flags); mmc_request_done(mmc, mrq); @@ -559,6 +544,15 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) struct tifm_dev *sock = host->dev; unsigned long flags; struct mmc_data *r_data = mrq->cmd->data; + char *t_buffer = NULL; + + if (r_data) { + t_buffer = kmap(r_data->sg->page); + if (!t_buffer) { + printk(KERN_ERR DRIVER_NAME ": kmap failed\n"); + goto err_out; + } + } spin_lock_irqsave(&sock->lock, flags); if (host->flags & EJECT) { @@ -575,14 +569,15 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) if (r_data) { tifm_sd_set_data_timeout(host, r_data); - host->buffer_size = mrq->cmd->data->blocks - * mrq->cmd->data->blksz; + host->buffer = t_buffer + r_data->sg->offset; + host->buffer_size = mrq->cmd->data->blocks * + mrq->cmd->data->blksz; - writel(TIFM_MMCSD_BUFINT - | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), + writel(TIFM_MMCSD_BUFINT | + readl(sock->addr + SOCK_MMCSD_INT_ENABLE), sock->addr + SOCK_MMCSD_INT_ENABLE); - writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) - | (TIFM_MMCSD_FIFO_SIZE - 1), + writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) | + (TIFM_MMCSD_FIFO_SIZE - 1), sock->addr + SOCK_MMCSD_BUFFER_CONFIG); host->written_blocks = 0; @@ -593,22 +588,26 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) } host->req = mrq; - mod_timer(&host->timer, jiffies + host->timeout_jiffies); host->state = CMD; + queue_delayed_work(sock->wq, &host->abort_handler, + host->timeout_jiffies); writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + sock->addr + SOCK_CONTROL); tifm_sd_exec(host, mrq->cmd); spin_unlock_irqrestore(&sock->lock, flags); return; err_out: + if (t_buffer) + kunmap(r_data->sg->page); + mrq->cmd->error = MMC_ERR_TIMEOUT; mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd_nodma(unsigned long data) +static void tifm_sd_end_cmd_nodma(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -617,7 +616,6 @@ static void tifm_sd_end_cmd_nodma(unsigned long data) spin_lock_irqsave(&sock->lock, flags); - del_timer(&host->timer); mrq = host->req; host->req = NULL; host->state = IDLE; @@ -635,8 +633,8 @@ static void tifm_sd_end_cmd_nodma(unsigned long data) sock->addr + SOCK_MMCSD_INT_ENABLE); if (r_data->flags & MMC_DATA_WRITE) { - r_data->bytes_xfered = host->written_blocks - * r_data->blksz; + r_data->bytes_xfered = host->written_blocks * + r_data->blksz; } else { r_data->bytes_xfered = r_data->blocks - readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; @@ -644,44 +642,29 @@ static void tifm_sd_end_cmd_nodma(unsigned long data) r_data->bytes_xfered += r_data->blksz - readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; } + host->buffer = NULL; host->buffer_pos = 0; host->buffer_size = 0; } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + sock->addr + SOCK_CONTROL); spin_unlock_irqrestore(&sock->lock, flags); - mmc_request_done(mmc, mrq); -} - -static void tifm_sd_terminate(struct tifm_sd *host) -{ - struct tifm_dev *sock = host->dev; - unsigned long flags; + if (r_data) + kunmap(r_data->sg->page); - writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); - mmiowb(); - spin_lock_irqsave(&sock->lock, flags); - host->flags |= EJECT; - if (host->req) { - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); - tasklet_schedule(&host->finish_tasklet); - } - spin_unlock_irqrestore(&sock->lock, flags); + mmc_request_done(mmc, mrq); } -static void tifm_sd_abort(unsigned long data) +static void tifm_sd_abort(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = + container_of(work, struct tifm_sd, abort_handler.work); printk(KERN_ERR DRIVER_NAME - ": card failed to respond for a long period of time"); - - tifm_sd_terminate(host); + ": card failed to respond for a long period of time"); tifm_eject(host->dev); } @@ -700,9 +683,9 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), sock->addr + SOCK_MMCSD_CONFIG); } else { - writel((~TIFM_MMCSD_4BBUS) - & readl(sock->addr + SOCK_MMCSD_CONFIG), - sock->addr + SOCK_MMCSD_CONFIG); + writel((~TIFM_MMCSD_4BBUS) & + readl(sock->addr + SOCK_MMCSD_CONFIG), + sock->addr + SOCK_MMCSD_CONFIG); } if (ios->clock) { @@ -721,24 +704,23 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) if ((20000000 / clk_div1) > (24000000 / clk_div2)) { host->clk_freq = 20000000; host->clk_div = clk_div1; - writel((~TIFM_CTRL_FAST_CLK) - & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + writel((~TIFM_CTRL_FAST_CLK) & + readl(sock->addr + SOCK_CONTROL), + sock->addr + SOCK_CONTROL); } else { host->clk_freq = 24000000; host->clk_div = clk_div2; - writel(TIFM_CTRL_FAST_CLK - | readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + writel(TIFM_CTRL_FAST_CLK | + readl(sock->addr + SOCK_CONTROL), + sock->addr + SOCK_CONTROL); } } else { host->clk_div = 0; } host->clk_div &= TIFM_MMCSD_CLKMASK; - writel(host->clk_div - | ((~TIFM_MMCSD_CLKMASK) - & readl(sock->addr + SOCK_MMCSD_CONFIG)), - sock->addr + SOCK_MMCSD_CONFIG); + writel(host->clk_div | ((~TIFM_MMCSD_CLKMASK) & + readl(sock->addr + SOCK_MMCSD_CONFIG)), + sock->addr + SOCK_MMCSD_CONFIG); if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) host->flags |= OPENDRAIN; @@ -752,7 +734,7 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) // allow removal. if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { host->flags |= EJECT_DONE; - wake_up_all(&host->notify); + wake_up_all(&host->can_eject); } spin_unlock_irqrestore(&sock->lock, flags); @@ -780,67 +762,20 @@ static struct mmc_host_ops tifm_sd_ops = { .get_ro = tifm_sd_ro }; -static int tifm_sd_initialize_host(struct tifm_sd *host) +static void tifm_sd_register_host(struct work_struct *work) { - int rc; - unsigned int host_status = 0; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; + struct mmc_host *mmc = tifm_get_drvdata(sock); + unsigned long flags; - writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); - mmiowb(); - host->clk_div = 61; - host->clk_freq = 20000000; - writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); - writel(host->clk_div | TIFM_MMCSD_POWER, - sock->addr + SOCK_MMCSD_CONFIG); - - /* wait up to 0.51 sec for reset */ - for (rc = 2; rc <= 256; rc <<= 1) { - if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { - rc = 0; - break; - } - msleep(rc); - } - - if (rc) { - printk(KERN_ERR DRIVER_NAME - ": controller failed to reset\n"); - return -ENODEV; - } - - writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); - writel(host->clk_div | TIFM_MMCSD_POWER, - sock->addr + SOCK_MMCSD_CONFIG); - writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); - - // command timeout fixed to 64 clocks for now - writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); - writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); - - /* INAB should take much less than reset */ - for (rc = 1; rc <= 16; rc <<= 1) { - host_status = readl(sock->addr + SOCK_MMCSD_STATUS); - writel(host_status, sock->addr + SOCK_MMCSD_STATUS); - if (!(host_status & TIFM_MMCSD_ERRMASK) - && (host_status & TIFM_MMCSD_EOC)) { - rc = 0; - break; - } - msleep(rc); - } - - if (rc) { - printk(KERN_ERR DRIVER_NAME - ": card not ready - probe failed on initialization\n"); - return -ENODEV; - } - - writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, - sock->addr + SOCK_MMCSD_INT_ENABLE); - mmiowb(); - - return 0; + spin_lock_irqsave(&sock->lock, flags); + host->flags |= HOST_REG; + PREPARE_WORK(&host->cmd_handler, + no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); + spin_unlock_irqrestore(&sock->lock, flags); + dev_dbg(&sock->dev, "adding host\n"); + mmc_add_host(mmc); } static int tifm_sd_probe(struct tifm_dev *sock) @@ -849,8 +784,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) struct tifm_sd *host; int rc = -EIO; - if (!(TIFM_SOCK_STATE_OCCUPIED - & readl(sock->addr + SOCK_PRESENT_STATE))) { + if (!(TIFM_SOCK_STATE_OCCUPIED & + readl(sock->addr + SOCK_PRESENT_STATE))) { printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); return rc; } @@ -860,99 +795,109 @@ static int tifm_sd_probe(struct tifm_dev *sock) return -ENOMEM; host = mmc_priv(mmc); - tifm_set_drvdata(sock, mmc); host->dev = sock; - host->timeout_jiffies = msecs_to_jiffies(1000); + host->clk_div = 61; + init_waitqueue_head(&host->can_eject); + INIT_WORK(&host->cmd_handler, tifm_sd_register_host); + INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); - init_waitqueue_head(&host->notify); - tasklet_init(&host->finish_tasklet, - no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, - (unsigned long)host); - setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); + tifm_set_drvdata(sock, mmc); + sock->signal_irq = tifm_sd_signal_irq; + + host->clk_freq = 20000000; + host->timeout_jiffies = msecs_to_jiffies(1000); tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; mmc->ops = &tifm_sd_ops; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; + mmc->caps = MMC_CAP_4_BIT_DATA; mmc->f_min = 20000000 / 60; mmc->f_max = 24000000; mmc->max_hw_segs = 1; mmc->max_phys_segs = 1; - // limited by DMA counter - it's safer to stick with - // block counter has 11 bits though - mmc->max_blk_count = 256; - // 2k maximum hw block length - mmc->max_blk_size = 2048; - mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - mmc->max_seg_size = mmc->max_req_size; - sock->signal_irq = tifm_sd_signal_irq; - rc = tifm_sd_initialize_host(host); + mmc->max_sectors = 127; + mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length - if (!rc) - rc = mmc_add_host(mmc); - if (rc) - goto out_free_mmc; + writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); + writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); + writel(host->clk_div | TIFM_MMCSD_POWER, + sock->addr + SOCK_MMCSD_CONFIG); - return 0; -out_free_mmc: - mmc_free_host(mmc); - return rc; -} + for (rc = 0; rc < 50; rc++) { + /* Wait for reset ack */ + if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { + rc = 0; + break; + } + msleep(10); + } -static void tifm_sd_remove(struct tifm_dev *sock) -{ - struct mmc_host *mmc = tifm_get_drvdata(sock); - struct tifm_sd *host = mmc_priv(mmc); + if (rc) { + printk(KERN_ERR DRIVER_NAME + ": card not ready - probe failed\n"); + mmc_free_host(mmc); + return -ENODEV; + } - del_timer_sync(&host->timer); - tifm_sd_terminate(host); - wait_event_timeout(host->notify, host->flags & EJECT_DONE, - host->timeout_jiffies); - tasklet_kill(&host->finish_tasklet); - mmc_remove_host(mmc); + writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); + writel(host->clk_div | TIFM_MMCSD_POWER, + sock->addr + SOCK_MMCSD_CONFIG); + writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); + writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, + sock->addr + SOCK_MMCSD_INT_ENABLE); - /* The meaning of the bit majority in this constant is unknown. */ - writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now + writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); + writel(host->clk_div | TIFM_MMCSD_POWER, + sock->addr + SOCK_MMCSD_CONFIG); - tifm_set_drvdata(sock, NULL); - mmc_free_host(mmc); -} + queue_delayed_work(sock->wq, &host->abort_handler, + host->timeout_jiffies); -#ifdef CONFIG_PM + return 0; +} -static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) +static int tifm_sd_host_is_down(struct tifm_dev *sock) { struct mmc_host *mmc = tifm_get_drvdata(sock); - int rc; + struct tifm_sd *host = mmc_priv(mmc); + unsigned long flags; + int rc = 0; - rc = mmc_suspend_host(mmc, state); - /* The meaning of the bit majority in this constant is unknown. */ - writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); + spin_lock_irqsave(&sock->lock, flags); + rc = (host->flags & EJECT_DONE); + spin_unlock_irqrestore(&sock->lock, flags); return rc; } -static int tifm_sd_resume(struct tifm_dev *sock) +static void tifm_sd_remove(struct tifm_dev *sock) { struct mmc_host *mmc = tifm_get_drvdata(sock); struct tifm_sd *host = mmc_priv(mmc); + unsigned long flags; - if (sock->media_id != FM_SD - || tifm_sd_initialize_host(host)) { - tifm_eject(sock); - return 0; - } else { - return mmc_resume_host(mmc); - } -} + spin_lock_irqsave(&sock->lock, flags); + host->flags |= EJECT; + if (host->req) + queue_work(sock->wq, &host->cmd_handler); + spin_unlock_irqrestore(&sock->lock, flags); + wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock), + host->timeout_jiffies); -#else + if (host->flags & HOST_REG) + mmc_remove_host(mmc); -#define tifm_sd_suspend NULL -#define tifm_sd_resume NULL + /* The meaning of the bit majority in this constant is unknown. */ + writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), + sock->addr + SOCK_CONTROL); + writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); -#endif /* CONFIG_PM */ + tifm_set_drvdata(sock, NULL); + mmc_free_host(mmc); +} static tifm_media_id tifm_sd_id_tbl[] = { FM_SD, 0 @@ -965,9 +910,7 @@ static struct tifm_driver tifm_sd_driver = { }, .id_table = tifm_sd_id_tbl, .probe = tifm_sd_probe, - .remove = tifm_sd_remove, - .suspend = tifm_sd_suspend, - .resume = tifm_sd_resume + .remove = tifm_sd_remove }; static int __init tifm_sd_init(void) diff --git a/trunk/drivers/mmc/wbsd.c b/trunk/drivers/mmc/wbsd.c index a44d8777ab9f..7a282672f8e9 100644 --- a/trunk/drivers/mmc/wbsd.c +++ b/trunk/drivers/mmc/wbsd.c @@ -1,7 +1,7 @@ /* * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver * - * Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved. + * Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved. * * 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 @@ -272,9 +272,16 @@ static inline int wbsd_next_sg(struct wbsd_host *host) return host->num_sg; } -static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) +static inline char *wbsd_kmap_sg(struct wbsd_host *host) { - return page_address(host->cur_sg->page) + host->cur_sg->offset; + host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) + + host->cur_sg->offset; + return host->mapped_sg; +} + +static inline void wbsd_kunmap_sg(struct wbsd_host *host) +{ + kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); } static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) @@ -295,11 +302,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) * we do not transfer too much. */ for (i = 0; i < len; i++) { - sgbuf = page_address(sg[i].page) + sg[i].offset; + sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; if (size < sg[i].length) memcpy(dmabuf, sgbuf, size); else memcpy(dmabuf, sgbuf, sg[i].length); + kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); dmabuf += sg[i].length; if (size < sg[i].length) @@ -339,7 +347,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) * we do not transfer too much. */ for (i = 0; i < len; i++) { - sgbuf = page_address(sg[i].page) + sg[i].offset; + sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; if (size < sg[i].length) memcpy(sgbuf, dmabuf, size); else @@ -489,7 +497,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host) if (data->bytes_xfered == host->size) return; - buffer = wbsd_sg_to_buffer(host) + host->offset; + buffer = wbsd_kmap_sg(host) + host->offset; /* * Drain the fifo. This has a tendency to loop longer @@ -518,13 +526,17 @@ static void wbsd_empty_fifo(struct wbsd_host *host) /* * Transfer done? */ - if (data->bytes_xfered == host->size) + if (data->bytes_xfered == host->size) { + wbsd_kunmap_sg(host); return; + } /* * End of scatter list entry? */ if (host->remain == 0) { + wbsd_kunmap_sg(host); + /* * Get next entry. Check if last. */ @@ -542,11 +554,13 @@ static void wbsd_empty_fifo(struct wbsd_host *host) return; } - buffer = wbsd_sg_to_buffer(host); + buffer = wbsd_kmap_sg(host); } } } + wbsd_kunmap_sg(host); + /* * This is a very dirty hack to solve a * hardware problem. The chip doesn't trigger @@ -569,7 +583,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host) if (data->bytes_xfered == host->size) return; - buffer = wbsd_sg_to_buffer(host) + host->offset; + buffer = wbsd_kmap_sg(host) + host->offset; /* * Fill the fifo. This has a tendency to loop longer @@ -598,13 +612,17 @@ static void wbsd_fill_fifo(struct wbsd_host *host) /* * Transfer done? */ - if (data->bytes_xfered == host->size) + if (data->bytes_xfered == host->size) { + wbsd_kunmap_sg(host); return; + } /* * End of scatter list entry? */ if (host->remain == 0) { + wbsd_kunmap_sg(host); + /* * Get next entry. Check if last. */ @@ -622,11 +640,13 @@ static void wbsd_fill_fifo(struct wbsd_host *host) return; } - buffer = wbsd_sg_to_buffer(host); + buffer = wbsd_kmap_sg(host); } } } + wbsd_kunmap_sg(host); + /* * The controller stops sending interrupts for * 'FIFO empty' under certain conditions. So we @@ -889,45 +909,6 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq) * transfered. */ if (cmd->data && (cmd->error == MMC_ERR_NONE)) { - /* - * The hardware is so delightfully stupid that it has a list - * of "data" commands. If a command isn't on this list, it'll - * just go back to the idle state and won't send any data - * interrupts. - */ - switch (cmd->opcode) { - case 11: - case 17: - case 18: - case 20: - case 24: - case 25: - case 26: - case 27: - case 30: - case 42: - case 56: - break; - - /* ACMDs. We don't keep track of state, so we just treat them - * like any other command. */ - case 51: - break; - - default: -#ifdef CONFIG_MMC_DEBUG - printk(KERN_WARNING "%s: Data command %d is not " - "supported by this controller.\n", - mmc_hostname(host->mmc), cmd->opcode); -#endif - cmd->data->error = MMC_ERR_INVALID; - - if (cmd->data->stop) - wbsd_send_command(host, cmd->data->stop); - - goto done; - }; - /* * Dirty fix for hardware bug. */ @@ -1362,27 +1343,16 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) mmc->max_phys_segs = 128; /* - * Maximum request size. Also limited by 64KiB buffer. + * Maximum number of sectors in one transfer. Also limited by 64kB + * buffer. */ - mmc->max_req_size = 65536; + mmc->max_sectors = 128; /* * Maximum segment size. Could be one segment with the maximum number - * of bytes. - */ - mmc->max_seg_size = mmc->max_req_size; - - /* - * Maximum block size. We have 12 bits (= 4095) but have to subtract - * space for CRC. So the maximum is 4095 - 4*2 = 4087. - */ - mmc->max_blk_size = 4087; - - /* - * Maximum block count. There is no real limit so the maximum - * request size will be the only restriction. + * of segments. */ - mmc->max_blk_count = mmc->max_req_size; + mmc->max_seg_size = mmc->max_sectors * 512; dev_set_drvdata(dev, mmc); diff --git a/trunk/drivers/mmc/wbsd.h b/trunk/drivers/mmc/wbsd.h index d06718b0e2ab..6072993f01e3 100644 --- a/trunk/drivers/mmc/wbsd.h +++ b/trunk/drivers/mmc/wbsd.h @@ -154,6 +154,7 @@ struct wbsd_host struct scatterlist* cur_sg; /* Current SG entry */ unsigned int num_sg; /* Number of entries left */ + void* mapped_sg; /* vaddr of mapped sg */ unsigned int offset; /* Offset into current entry */ unsigned int remain; /* Data left in curren entry */ diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c index cf2a279307e1..f8862e203ac9 100644 --- a/trunk/drivers/net/e1000/e1000_param.c +++ b/trunk/drivers/net/e1000/e1000_param.c @@ -760,22 +760,13 @@ e1000_check_copper_options(struct e1000_adapter *adapter) case SPEED_1000: DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without " "Duplex\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at 1000 Mbps " - "Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; + goto full_duplex_only; case SPEED_1000 + HALF_DUPLEX: DPRINTK(PROBE, INFO, "Half Duplex is not supported at 1000 Mbps\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at 1000 Mbps " - "Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; + /* fall through */ case SPEED_1000 + FULL_DUPLEX: +full_duplex_only: DPRINTK(PROBE, INFO, "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index fca978fb158e..bd1faebf61a0 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -773,13 +773,13 @@ static int get_gsi_base(acpi_handle handle, u32 *gsi_base) goto out; table = obj->buffer.pointer; - switch (((struct acpi_subtable_header *)table)->type) { - case ACPI_MADT_TYPE_IO_SAPIC: - *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base; + switch (((acpi_table_entry_header *)table)->type) { + case ACPI_MADT_IOSAPIC: + *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base; result = 0; break; - case ACPI_MADT_TYPE_IO_APIC: - *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base; + case ACPI_MADT_IOAPIC: + *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base; result = 0; break; default: diff --git a/trunk/drivers/pci/hotplug/sgi_hotplug.c b/trunk/drivers/pci/hotplug/sgi_hotplug.c index 78cf0711d1fa..5d188c558386 100644 --- a/trunk/drivers/pci/hotplug/sgi_hotplug.c +++ b/trunk/drivers/pci/hotplug/sgi_hotplug.c @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include "../pci.h" @@ -37,17 +35,14 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); - -/* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */ +#define PCIIO_ASIC_TYPE_TIOCA 4 #define PCI_SLOT_ALREADY_UP 2 /* slot already up */ #define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ #define PCI_L1_ERR 7 /* L1 console command error */ #define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ - - -#define PCIIO_ASIC_TYPE_TIOCA 4 #define PCI_L1_QSIZE 128 /* our L1 message buffer size */ #define SN_MAX_HP_SLOTS 32 /* max hotplug slots */ +#define SGI_HOTPLUG_PROM_REV 0x0430 /* Min. required PROM version */ #define SN_SLOT_NAME_SIZE 33 /* size of name string */ /* internal list head */ @@ -232,7 +227,7 @@ static void sn_bus_free_data(struct pci_dev *dev) } static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, - int device_num, char **ssdt) + int device_num) { struct slot *slot = bss_hotplug_slot->private; struct pcibus_info *pcibus_info; @@ -245,8 +240,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, * Power-on and initialize the slot in the SN * PCI infrastructure. */ - rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp, ssdt); - + rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp); if (rc == PCI_SLOT_ALREADY_UP) { dev_dbg(slot->pci_bus->self, "is already active\n"); @@ -341,7 +335,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) int func, num_funcs; int new_ppb = 0; int rc; - char *ssdt = NULL; void pcibios_fixup_device_resources(struct pci_dev *); /* Serialize the Linux PCI infrastructure */ @@ -349,29 +342,14 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) /* * Power-on and initialize the slot in the SN - * PCI infrastructure. Also, retrieve the ACPI SSDT - * table for the slot (if ACPI capable PROM). + * PCI infrastructure. */ - rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt); + rc = sn_slot_enable(bss_hotplug_slot, slot->device_num); if (rc) { mutex_unlock(&sn_hotplug_mutex); return rc; } - if (ssdt) - ssdt = __va(ssdt); - /* Add the new SSDT for the slot to the ACPI namespace */ - if (SN_ACPI_BASE_SUPPORT() && ssdt) { - acpi_status ret; - - ret = acpi_load_table((struct acpi_table_header *)ssdt); - if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n", - __FUNCTION__, ret); - /* try to continue on */ - } - } - num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num + 1, 0)); if (!num_funcs) { @@ -396,10 +374,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) * pdi_host_pcidev_info). */ pcibios_fixup_device_resources(dev); - if (SN_ACPI_BASE_SUPPORT()) - sn_acpi_slot_fixup(dev); - else - sn_io_slot_fixup(dev); + sn_pci_fixup_slot(dev); if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { unsigned char sec_bus; pci_read_config_byte(dev, PCI_SECONDARY_BUS, @@ -413,63 +388,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) } } - /* - * Add the slot's devices to the ACPI infrastructure */ - if (SN_ACPI_BASE_SUPPORT() && ssdt) { - unsigned long adr; - struct acpi_device *pdevice; - struct acpi_device *device; - acpi_handle phandle; - acpi_handle chandle = NULL; - acpi_handle rethandle; - acpi_status ret; - - phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; - - if (acpi_bus_get_device(phandle, &pdevice)) { - dev_dbg(slot->pci_bus->self, - "no parent device, assuming NULL\n"); - pdevice = NULL; - } - - /* - * Walk the rootbus node's immediate children looking for - * the slot's device node(s). There can be more than - * one for multifunction devices. - */ - for (;;) { - rethandle = NULL; - ret = acpi_get_next_object(ACPI_TYPE_DEVICE, - phandle, chandle, - &rethandle); - - if (ret == AE_NOT_FOUND || rethandle == NULL) - break; - - chandle = rethandle; - - ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR, - NULL, &adr); - - if (ACPI_SUCCESS(ret) && - (adr>>16) == (slot->device_num + 1)) { - - ret = acpi_bus_add(&device, pdevice, chandle, - ACPI_BUS_TYPE_DEVICE); - if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_bus_add " - "failed (0x%x) for slot %d " - "func %d\n", __FUNCTION__, - ret, (int)(adr>>16), - (int)(adr&0xffff)); - /* try to continue on */ - } else { - acpi_bus_start(device); - } - } - } - } - /* Call the driver for the new device */ pci_bus_add_devices(slot->pci_bus); /* Call the drivers for the new devices subordinate to PPB */ @@ -494,7 +412,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) struct pci_dev *dev; int func; int rc; - acpi_owner_id ssdt_id = 0; /* Acquire update access to the bus */ mutex_lock(&sn_hotplug_mutex); @@ -505,52 +422,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) if (rc) goto leaving; - /* free the ACPI resources for the slot */ - if (SN_ACPI_BASE_SUPPORT() && - PCI_CONTROLLER(slot->pci_bus)->acpi_handle) { - unsigned long adr; - struct acpi_device *device; - acpi_handle phandle; - acpi_handle chandle = NULL; - acpi_handle rethandle; - acpi_status ret; - - /* Get the rootbus node pointer */ - phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; - - /* - * Walk the rootbus node's immediate children looking for - * the slot's device node(s). There can be more than - * one for multifunction devices. - */ - for (;;) { - rethandle = NULL; - ret = acpi_get_next_object(ACPI_TYPE_DEVICE, - phandle, chandle, - &rethandle); - - if (ret == AE_NOT_FOUND || rethandle == NULL) - break; - - chandle = rethandle; - - ret = acpi_evaluate_integer(chandle, - METHOD_NAME__ADR, - NULL, &adr); - if (ACPI_SUCCESS(ret) && - (adr>>16) == (slot->device_num + 1)) { - /* retain the owner id */ - acpi_get_id(chandle, &ssdt_id); - - ret = acpi_bus_get_device(chandle, - &device); - if (ACPI_SUCCESS(ret)) - acpi_bus_trim(device, 1); - } - } - - } - /* Free the SN resources assigned to the Linux device.*/ for (func = 0; func < 8; func++) { dev = pci_get_slot(slot->pci_bus, @@ -563,18 +434,6 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) } } - /* Remove the SSDT for the slot from the ACPI namespace */ - if (SN_ACPI_BASE_SUPPORT() && ssdt_id) { - acpi_status ret; - ret = acpi_unload_table_id(ssdt_id); - if (ACPI_FAILURE(ret)) { - printk(KERN_ERR "%s: acpi_unload_table_id " - "failed (0x%x) for id %d\n", - __FUNCTION__, ret, ssdt_id); - /* try to continue on */ - } - } - /* free the collected sysdata pointers */ sn_bus_free_sysdata(); diff --git a/trunk/drivers/pnp/pnpacpi/Kconfig b/trunk/drivers/pnp/pnpacpi/Kconfig index ad27e5e0101f..b1854171b963 100644 --- a/trunk/drivers/pnp/pnpacpi/Kconfig +++ b/trunk/drivers/pnp/pnpacpi/Kconfig @@ -2,8 +2,8 @@ # Plug and Play ACPI configuration # config PNPACPI - bool "Plug and Play ACPI support" - depends on PNP && ACPI + bool "Plug and Play ACPI support (EXPERIMENTAL)" + depends on PNP && ACPI && EXPERIMENTAL default y ---help--- Linux uses the PNPACPI to autodetect built-in diff --git a/trunk/drivers/pnp/system.c b/trunk/drivers/pnp/system.c index 2065e74bb63f..d42015c382af 100644 --- a/trunk/drivers/pnp/system.c +++ b/trunk/drivers/pnp/system.c @@ -3,8 +3,7 @@ * * Some code is based on pnpbios_core.c * Copyright 2002 Adam Belay - * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. - * Bjorn Helgaas + * */ #include @@ -22,21 +21,18 @@ static const struct pnp_device_id pnp_dev_table[] = { { "", 0 } }; -static void reserve_range(char *pnpid, int start, int end, int port) +static void reserve_ioport_range(char *pnpid, int start, int end) { struct resource *res; char *regionid; regionid = kmalloc(16, GFP_KERNEL); - if (regionid == NULL) + if ( regionid == NULL ) return; snprintf(regionid, 16, "pnp %s", pnpid); - if (port) - res = request_region(start,end-start+1,regionid); - else - res = request_mem_region(start,end-start+1,regionid); - if (res == NULL) - kfree(regionid); + res = request_region(start,end-start+1,regionid); + if ( res == NULL ) + kfree( regionid ); else res->flags &= ~IORESOURCE_BUSY; /* @@ -45,20 +41,26 @@ static void reserve_range(char *pnpid, int start, int end, int port) * have double reservations. */ printk(KERN_INFO - "pnp: %s: %s range 0x%x-0x%x %s reserved\n", - pnpid, port ? "ioport" : "iomem", start, end, - NULL != res ? "has been" : "could not be"); + "pnp: %s: ioport range 0x%x-0x%x %s reserved\n", + pnpid, start, end, + NULL != res ? "has been" : "could not be" + ); + + return; } -static void reserve_resources_of_dev(struct pnp_dev *dev) +static void reserve_resources_of_dev( struct pnp_dev *dev ) { int i; - for (i = 0; i < PNP_MAX_PORT; i++) { + for (i=0;idev.bus_id, pnp_port_start(dev, i), - pnp_port_end(dev, i), 1); - } - - for (i = 0; i < PNP_MAX_MEM; i++) { - if (!pnp_mem_valid(dev, i)) + /* invalid endpoint */ + /* Do nothing */ continue; - - reserve_range(dev->dev.bus_id, pnp_mem_start(dev, i), - pnp_mem_end(dev, i), 0); + reserve_ioport_range( + dev->dev.bus_id, + pnp_port_start(dev, i), + pnp_port_end(dev, i) + ); } return; diff --git a/trunk/drivers/s390/Kconfig b/trunk/drivers/s390/Kconfig index 165af398fdea..ae89b9b88743 100644 --- a/trunk/drivers/s390/Kconfig +++ b/trunk/drivers/s390/Kconfig @@ -103,8 +103,14 @@ config CCW_CONSOLE depends on TN3215_CONSOLE || TN3270_CONSOLE default y +config SCLP + bool "Support for SCLP" + help + Include support for the SCLP interface to the service element. + config SCLP_TTY bool "Support for SCLP line mode terminal" + depends on SCLP help Include support for IBM SCLP line-mode terminals. @@ -117,6 +123,7 @@ config SCLP_CONSOLE config SCLP_VT220_TTY bool "Support for SCLP VT220-compatible terminal" + depends on SCLP help Include support for an IBM SCLP VT220-compatible terminal. @@ -129,6 +136,7 @@ config SCLP_VT220_CONSOLE config SCLP_CPI tristate "Control-Program Identification" + depends on SCLP help This option enables the hardware console interface for system identification. This is commonly used for workload management and diff --git a/trunk/drivers/s390/Makefile b/trunk/drivers/s390/Makefile index 5a888704a8d0..9803c9352d78 100644 --- a/trunk/drivers/s390/Makefile +++ b/trunk/drivers/s390/Makefile @@ -2,8 +2,6 @@ # Makefile for the S/390 specific device drivers # -CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w - obj-y += s390mach.o sysinfo.o s390_rdev.o obj-y += cio/ block/ char/ crypto/ net/ scsi/ diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index eb5dc62f0d9c..492b68bcd7cc 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -37,7 +37,6 @@ */ debug_info_t *dasd_debug_area; struct dasd_discipline *dasd_diag_discipline_pointer; -void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); MODULE_AUTHOR("Holger Smolinski "); MODULE_DESCRIPTION("Linux on S/390 DASD device driver," @@ -52,6 +51,7 @@ static int dasd_alloc_queue(struct dasd_device * device); static void dasd_setup_queue(struct dasd_device * device); static void dasd_free_queue(struct dasd_device * device); static void dasd_flush_request_queue(struct dasd_device *); +static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static int dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(struct work_struct *); @@ -483,7 +483,7 @@ unsigned int dasd_profile_level = DASD_PROFILE_OFF; /* * Add profiling information for cqr before execution. */ -static void +static inline void dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr, struct request *req) { @@ -505,7 +505,7 @@ dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr, /* * Add profiling information for cqr after execution. */ -static void +static inline void dasd_profile_end(struct dasd_device *device, struct dasd_ccw_req * cqr, struct request *req) { @@ -1022,6 +1022,8 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, irb->scsw.cstat == 0 && !irb->esw.esw0.erw.cons) era = dasd_era_none; + else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) + era = dasd_era_fatal; /* don't recover this request */ else if (irb->esw.esw0.erw.cons) era = device->discipline->examine_error(cqr, irb); else @@ -1102,7 +1104,7 @@ __dasd_process_erp(struct dasd_device *device, struct dasd_ccw_req *cqr) /* * Process ccw request queue. */ -static void +static inline void __dasd_process_ccw_queue(struct dasd_device * device, struct list_head *final_queue) { @@ -1125,9 +1127,7 @@ __dasd_process_ccw_queue(struct dasd_device * device, cqr->status = DASD_CQR_FAILED; cqr->stopclk = get_clock(); } else { - if (cqr->irb.esw.esw0.erw.cons && - test_bit(DASD_CQR_FLAGS_USE_ERP, - &cqr->flags)) { + if (cqr->irb.esw.esw0.erw.cons) { erp_fn = device->discipline-> erp_action(cqr); erp_fn(cqr); @@ -1181,7 +1181,7 @@ dasd_end_request_cb(struct dasd_ccw_req * cqr, void *data) /* * Fetch requests from the block device queue. */ -static void +static inline void __dasd_process_blk_queue(struct dasd_device * device) { request_queue_t *queue; @@ -1232,19 +1232,6 @@ __dasd_process_blk_queue(struct dasd_device * device) if (IS_ERR(cqr)) { if (PTR_ERR(cqr) == -ENOMEM) break; /* terminate request queue loop */ - if (PTR_ERR(cqr) == -EAGAIN) { - /* - * The current request cannot be build right - * now, we have to try later. If this request - * is the head-of-queue we stop the device - * for 1/2 second. - */ - if (!list_empty(&device->ccw_queue)) - break; - device->stopped |= DASD_STOPPED_PENDING; - dasd_set_timer(device, HZ/2); - break; - } DBF_DEV_EVENT(DBF_ERR, device, "CCW creation failed (rc=%ld) " "on request %p", @@ -1267,7 +1254,7 @@ __dasd_process_blk_queue(struct dasd_device * device) * Take a look at the first request on the ccw queue and check * if it reached its expire time. If so, terminate the IO. */ -static void +static inline void __dasd_check_expire(struct dasd_device * device) { struct dasd_ccw_req *cqr; @@ -1298,7 +1285,7 @@ __dasd_check_expire(struct dasd_device * device) * Take a look at the first request on the ccw queue and check * if it needs to be started. */ -static void +static inline void __dasd_start_head(struct dasd_device * device) { struct dasd_ccw_req *cqr; diff --git a/trunk/drivers/s390/block/dasd_3990_erp.c b/trunk/drivers/s390/block/dasd_3990_erp.c index 8b9d68f6e016..4d01040c2c63 100644 --- a/trunk/drivers/s390/block/dasd_3990_erp.c +++ b/trunk/drivers/s390/block/dasd_3990_erp.c @@ -170,6 +170,7 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) /* log the erp chain if fatal error occurred */ if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) { dasd_log_sense(cqr, irb); + dasd_log_ccw(cqr, 0, irb->scsw.cpa); } return era; @@ -2639,6 +2640,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) struct dasd_ccw_req *erp = NULL; struct dasd_device *device = cqr->device; + __u32 cpa = cqr->irb.scsw.cpa; struct dasd_ccw_req *temp_erp = NULL; if (device->features & DASD_FEATURE_ERPLOG) { @@ -2704,6 +2706,9 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) } } + if (erp->status == DASD_CQR_FAILED) + dasd_log_ccw(erp, 1, cpa); + /* enqueue added ERP request */ if (erp->status == DASD_CQR_FILLED) { erp->status = DASD_CQR_QUEUED; diff --git a/trunk/drivers/s390/block/dasd_devmap.c b/trunk/drivers/s390/block/dasd_devmap.c index ed70852cc915..5943266152f5 100644 --- a/trunk/drivers/s390/block/dasd_devmap.c +++ b/trunk/drivers/s390/block/dasd_devmap.c @@ -136,7 +136,7 @@ __setup ("dasd=", dasd_call_setup); /* * Read a device busid/devno from a string. */ -static int +static inline int dasd_busid(char **str, int *id0, int *id1, int *devno) { int val, old_style; @@ -182,7 +182,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) * only one: "ro" for read-only devices. The default feature set * is empty (value 0). */ -static int +static inline int dasd_feature_list(char *str, char **endp) { int features, len, rc; @@ -341,7 +341,7 @@ dasd_parse_range( char *parsestring ) { return ERR_PTR(-EINVAL); } -static char * +static inline char * dasd_parse_next_element( char *parsestring ) { char * residual_str; residual_str = dasd_parse_keyword(parsestring); diff --git a/trunk/drivers/s390/block/dasd_diag.c b/trunk/drivers/s390/block/dasd_diag.c index ab782bb46ac1..53db58a68617 100644 --- a/trunk/drivers/s390/block/dasd_diag.c +++ b/trunk/drivers/s390/block/dasd_diag.c @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); #define DIAG_MAX_RETRIES 32 #define DIAG_TIMEOUT 50 * HZ -static struct dasd_discipline dasd_diag_discipline; +struct dasd_discipline dasd_diag_discipline; struct dasd_diag_private { struct dasd_diag_characteristics rdc_data; @@ -90,7 +90,7 @@ static inline int dia250(void *iob, int cmd) * block offset. On success, return zero and set end_block to contain the * number of blocks on the device minus the specified offset. Return non-zero * otherwise. */ -static inline int +static __inline__ int mdsk_init_io(struct dasd_device *device, unsigned int blocksize, blocknum_t offset, blocknum_t *end_block) { @@ -117,7 +117,7 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize, /* Remove block I/O environment for device. Return zero on success, non-zero * otherwise. */ -static inline int +static __inline__ int mdsk_term_io(struct dasd_device * device) { struct dasd_diag_private *private; @@ -576,7 +576,7 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, "dump sense not available for DIAG data"); } -static struct dasd_discipline dasd_diag_discipline = { +struct dasd_discipline dasd_diag_discipline = { .owner = THIS_MODULE, .name = "DIAG", .ebcname = "DIAG", diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index cecab2274a6e..fdaa471e845f 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -134,7 +134,44 @@ ceil_quot(unsigned int d1, unsigned int d2) return (d1 + (d2 - 1)) / d2; } -static unsigned int +static inline int +bytes_per_record(struct dasd_eckd_characteristics *rdc, int kl, int dl) +{ + unsigned int fl1, fl2, int1, int2; + int bpr; + + switch (rdc->formula) { + case 0x01: + fl1 = round_up_multiple(ECKD_F2(rdc) + dl, ECKD_F1(rdc)); + fl2 = round_up_multiple(kl ? ECKD_F2(rdc) + kl : 0, + ECKD_F1(rdc)); + bpr = fl1 + fl2; + break; + case 0x02: + int1 = ceil_quot(dl + ECKD_F6(rdc), ECKD_F5(rdc) << 1); + int2 = ceil_quot(kl + ECKD_F6(rdc), ECKD_F5(rdc) << 1); + fl1 = round_up_multiple(ECKD_F1(rdc) * ECKD_F2(rdc) + dl + + ECKD_F6(rdc) + ECKD_F4(rdc) * int1, + ECKD_F1(rdc)); + fl2 = round_up_multiple(ECKD_F1(rdc) * ECKD_F3(rdc) + kl + + ECKD_F6(rdc) + ECKD_F4(rdc) * int2, + ECKD_F1(rdc)); + bpr = fl1 + fl2; + break; + default: + bpr = 0; + break; + } + return bpr; +} + +static inline unsigned int +bytes_per_track(struct dasd_eckd_characteristics *rdc) +{ + return *(unsigned int *) (rdc->byte_per_track) >> 8; +} + +static inline unsigned int recs_per_track(struct dasd_eckd_characteristics * rdc, unsigned int kl, unsigned int dl) { @@ -167,39 +204,37 @@ recs_per_track(struct dasd_eckd_characteristics * rdc, return 0; } -static int +static inline void check_XRC (struct ccw1 *de_ccw, struct DE_eckd_data *data, struct dasd_device *device) { struct dasd_eckd_private *private; - int rc; private = (struct dasd_eckd_private *) device->private; - if (!private->rdc_data.facilities.XRC_supported) - return 0; /* switch on System Time Stamp - needed for XRC Support */ - data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ - data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ + if (private->rdc_data.facilities.XRC_supported) { - rc = get_sync_clock(&data->ep_sys_time); - /* Ignore return code if sync clock is switched off. */ - if (rc == -ENOSYS || rc == -EACCES) - rc = 0; + data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ + data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ - de_ccw->count = sizeof (struct DE_eckd_data); - de_ccw->flags |= CCW_FLAG_SLI; - return rc; -} + data->ep_sys_time = get_clock (); -static int + de_ccw->count = sizeof (struct DE_eckd_data); + de_ccw->flags |= CCW_FLAG_SLI; + } + + return; + +} /* end check_XRC */ + +static inline void define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, int totrk, int cmd, struct dasd_device * device) { struct dasd_eckd_private *private; struct ch_t geo, beg, end; - int rc = 0; private = (struct dasd_eckd_private *) device->private; @@ -228,12 +263,12 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, case DASD_ECKD_CCW_WRITE_KD_MT: data->mask.perm = 0x02; data->attributes.operation = private->attrib.operation; - rc = check_XRC (ccw, data, device); + check_XRC (ccw, data, device); break; case DASD_ECKD_CCW_WRITE_CKD: case DASD_ECKD_CCW_WRITE_CKD_MT: data->attributes.operation = DASD_BYPASS_CACHE; - rc = check_XRC (ccw, data, device); + check_XRC (ccw, data, device); break; case DASD_ECKD_CCW_ERASE: case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: @@ -241,7 +276,7 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, data->mask.perm = 0x3; data->mask.auth = 0x1; data->attributes.operation = DASD_BYPASS_CACHE; - rc = check_XRC (ccw, data, device); + check_XRC (ccw, data, device); break; default: DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); @@ -277,10 +312,9 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, data->beg_ext.head = beg.head; data->end_ext.cyl = end.cyl; data->end_ext.head = end.head; - return rc; } -static void +static inline void locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, int rec_on_trk, int no_rec, int cmd, struct dasd_device * device, int reclen) @@ -514,7 +548,7 @@ dasd_eckd_read_conf(struct dasd_device *device) /* * Build CP for Perform Subsystem Function - SSC. */ -static struct dasd_ccw_req * +struct dasd_ccw_req * dasd_eckd_build_psf_ssc(struct dasd_device *device) { struct dasd_ccw_req *cqr; @@ -1166,12 +1200,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) return cqr; ccw = cqr->cpaddr; /* First ccw is define extent. */ - if (define_extent(ccw++, cqr->data, first_trk, - last_trk, cmd, device) == -EAGAIN) { - /* Clock not in sync and XRC is enabled. Try again later. */ - dasd_sfree_request(cqr, device); - return ERR_PTR(-EAGAIN); - } + define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device); /* Build locate_record+read/write/ccws. */ idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data)); LO_data = (struct LO_eckd_data *) (idaws + cidaw); @@ -1351,7 +1380,7 @@ dasd_eckd_release(struct dasd_device *device) cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); - cqr->retries = 2; /* set retry counter to enable basic ERP */ + cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; @@ -1391,7 +1420,7 @@ dasd_eckd_reserve(struct dasd_device *device) cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); - cqr->retries = 2; /* set retry counter to enable basic ERP */ + cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; @@ -1430,7 +1459,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); - cqr->retries = 2; /* set retry counter to enable basic ERP */ + cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; @@ -1580,7 +1609,7 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) * Dump the range of CCWs into 'page' buffer * and return number of printed chars. */ -static int +static inline int dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) { int len, count; diff --git a/trunk/drivers/s390/block/dasd_eer.c b/trunk/drivers/s390/block/dasd_eer.c index 6cedc914077e..e0bf30ebb215 100644 --- a/trunk/drivers/s390/block/dasd_eer.c +++ b/trunk/drivers/s390/block/dasd_eer.c @@ -658,24 +658,18 @@ static struct file_operations dasd_eer_fops = { .owner = THIS_MODULE, }; -static struct miscdevice *dasd_eer_dev = NULL; +static struct miscdevice dasd_eer_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dasd_eer", + .fops = &dasd_eer_fops, +}; int __init dasd_eer_init(void) { int rc; - dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL); - if (!dasd_eer_dev) - return -ENOMEM; - - dasd_eer_dev->minor = MISC_DYNAMIC_MINOR; - dasd_eer_dev->name = "dasd_eer"; - dasd_eer_dev->fops = &dasd_eer_fops; - - rc = misc_register(dasd_eer_dev); + rc = misc_register(&dasd_eer_dev); if (rc) { - kfree(dasd_eer_dev); - dasd_eer_dev = NULL; MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " "register misc device"); return rc; @@ -686,9 +680,5 @@ int __init dasd_eer_init(void) void dasd_eer_exit(void) { - if (dasd_eer_dev) { - WARN_ON(misc_deregister(dasd_eer_dev) != 0); - kfree(dasd_eer_dev); - dasd_eer_dev = NULL; - } + WARN_ON(misc_deregister(&dasd_eer_dev) != 0); } diff --git a/trunk/drivers/s390/block/dasd_erp.c b/trunk/drivers/s390/block/dasd_erp.c index caa5d91420f8..58a65097922b 100644 --- a/trunk/drivers/s390/block/dasd_erp.c +++ b/trunk/drivers/s390/block/dasd_erp.c @@ -152,6 +152,25 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr) } /* end default_erp_postaction */ +/* + * Print the hex dump of the memory used by a request. This includes + * all error recovery ccws that have been chained in from of the + * real request. + */ +static inline void +hex_dump_memory(struct dasd_device *device, void *data, int len) +{ + int *pint; + + pint = (int *) data; + while (len > 0) { + DEV_MESSAGE(KERN_ERR, device, "%p: %08x %08x %08x %08x", + pint, pint[0], pint[1], pint[2], pint[3]); + pint += 4; + len -= 16; + } +} + void dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) { @@ -163,8 +182,69 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) device->discipline->dump_sense(device, cqr, irb); } +void +dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa) +{ + struct dasd_device *device; + struct dasd_ccw_req *lcqr; + struct ccw1 *ccw; + int cplength; + + device = cqr->device; + /* log the channel program */ + for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) { + DEV_MESSAGE(KERN_ERR, device, + "(%s) ERP chain report for req: %p", + caller == 0 ? "EXAMINE" : "ACTION", lcqr); + hex_dump_memory(device, lcqr, sizeof(struct dasd_ccw_req)); + + cplength = 1; + ccw = lcqr->cpaddr; + while (ccw++->flags & (CCW_FLAG_DC | CCW_FLAG_CC)) + cplength++; + + if (cplength > 40) { /* log only parts of the CP */ + DEV_MESSAGE(KERN_ERR, device, "%s", + "Start of channel program:"); + hex_dump_memory(device, lcqr->cpaddr, + 40*sizeof(struct ccw1)); + + DEV_MESSAGE(KERN_ERR, device, "%s", + "End of channel program:"); + hex_dump_memory(device, lcqr->cpaddr + cplength - 10, + 10*sizeof(struct ccw1)); + } else { /* log the whole CP */ + DEV_MESSAGE(KERN_ERR, device, "%s", + "Channel program (complete):"); + hex_dump_memory(device, lcqr->cpaddr, + cplength*sizeof(struct ccw1)); + } + + if (lcqr != cqr) + continue; + + /* + * Log bytes arround failed CCW but only if we did + * not log the whole CP of the CCW is outside the + * logged CP. + */ + if (cplength > 40 || + ((addr_t) cpa < (addr_t) lcqr->cpaddr && + (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) { + + DEV_MESSAGE(KERN_ERR, device, + "Failed CCW (%p) (area):", + (void *) (long) cpa); + hex_dump_memory(device, cqr->cpaddr - 10, + 20*sizeof(struct ccw1)); + } + } + +} /* end log_erp_chain */ + EXPORT_SYMBOL(dasd_default_erp_action); EXPORT_SYMBOL(dasd_default_erp_postaction); EXPORT_SYMBOL(dasd_alloc_erp_request); EXPORT_SYMBOL(dasd_free_erp_request); EXPORT_SYMBOL(dasd_log_sense); +EXPORT_SYMBOL(dasd_log_ccw); diff --git a/trunk/drivers/s390/block/dasd_fba.c b/trunk/drivers/s390/block/dasd_fba.c index be0909e39226..b857fd5893fd 100644 --- a/trunk/drivers/s390/block/dasd_fba.c +++ b/trunk/drivers/s390/block/dasd_fba.c @@ -75,7 +75,7 @@ static struct ccw_driver dasd_fba_driver = { .notify = dasd_generic_notify, }; -static void +static inline void define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, int blksize, int beg, int nr) { @@ -95,7 +95,7 @@ define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, data->ext_end = nr - 1; } -static void +static inline void locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw, int block_nr, int block_ct) { diff --git a/trunk/drivers/s390/block/dasd_genhd.c b/trunk/drivers/s390/block/dasd_genhd.c index 47ba4462708d..d163632101d2 100644 --- a/trunk/drivers/s390/block/dasd_genhd.c +++ b/trunk/drivers/s390/block/dasd_genhd.c @@ -147,7 +147,7 @@ dasd_destroy_partitions(struct dasd_device * device) */ memset(&bpart, 0, sizeof(struct blkpg_partition)); memset(&barg, 0, sizeof(struct blkpg_ioctl_arg)); - barg.data = (void __force __user *) &bpart; + barg.data = (void __user *) &bpart; barg.op = BLKPG_DEL_PARTITION; for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--) ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg); diff --git a/trunk/drivers/s390/block/dasd_int.h b/trunk/drivers/s390/block/dasd_int.h index a2cc69e11410..fb725e3b08fe 100644 --- a/trunk/drivers/s390/block/dasd_int.h +++ b/trunk/drivers/s390/block/dasd_int.h @@ -559,6 +559,7 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int, struct dasd_device *); void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); void dasd_log_sense(struct dasd_ccw_req *, struct irb *); +void dasd_log_ccw(struct dasd_ccw_req *, int, __u32); /* externals in dasd_3370_erp.c */ dasd_era_t dasd_3370_erp_examine(struct dasd_ccw_req *, struct irb *); diff --git a/trunk/drivers/s390/block/dasd_proc.c b/trunk/drivers/s390/block/dasd_proc.c index 8b7e11815d70..bfa010f6dab2 100644 --- a/trunk/drivers/s390/block/dasd_proc.c +++ b/trunk/drivers/s390/block/dasd_proc.c @@ -28,7 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL; static struct proc_dir_entry *dasd_devices_entry = NULL; static struct proc_dir_entry *dasd_statistics_entry = NULL; -static char * +static inline char * dasd_get_user_string(const char __user *user_buf, size_t user_len) { char *buffer; @@ -154,7 +154,7 @@ static struct file_operations dasd_devices_file_ops = { .release = seq_release, }; -static int +static inline int dasd_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) { @@ -167,8 +167,8 @@ dasd_calc_metrics(char *page, char **start, off_t off, return len; } -static char * -dasd_statistics_array(char *str, unsigned int *array, int shift) +static inline char * +dasd_statistics_array(char *str, int *array, int shift) { int i; diff --git a/trunk/drivers/s390/block/dcssblk.c b/trunk/drivers/s390/block/dcssblk.c index 1340451ea408..be9b05347b4f 100644 --- a/trunk/drivers/s390/block/dcssblk.c +++ b/trunk/drivers/s390/block/dcssblk.c @@ -102,7 +102,7 @@ dcssblk_release_segment(struct device *dev) * device needs to be enqueued before the semaphore is * freed. */ -static int +static inline int dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) { int minor, found; @@ -230,7 +230,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch SEGMENT_SHARED); if (rc < 0) { BUG_ON(rc == -EINVAL); - if (rc != -EAGAIN) + if (rc == -EIO || rc == -ENOENT) goto removeseg; } else { dev_info->is_shared = 1; @@ -253,7 +253,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch SEGMENT_EXCLUSIVE); if (rc < 0) { BUG_ON(rc == -EINVAL); - if (rc != -EAGAIN) + if (rc == -EIO || rc == -ENOENT) goto removeseg; } else { dev_info->is_shared = 0; diff --git a/trunk/drivers/s390/char/Makefile b/trunk/drivers/s390/char/Makefile index 293e667b50f2..c3e97b4fc186 100644 --- a/trunk/drivers/s390/char/Makefile +++ b/trunk/drivers/s390/char/Makefile @@ -2,8 +2,7 @@ # S/390 character devices # -obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ - sclp_info.o +obj-y += ctrlchar.o keyboard.o defkeymap.o obj-$(CONFIG_TN3270) += raw3270.o obj-$(CONFIG_TN3270_CONSOLE) += con3270.o @@ -12,6 +11,7 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o obj-$(CONFIG_TN3215) += con3215.o +obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o obj-$(CONFIG_SCLP_TTY) += sclp_tty.o obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o diff --git a/trunk/drivers/s390/char/con3215.c b/trunk/drivers/s390/char/con3215.c index 9a328f14a641..25b5d7a66417 100644 --- a/trunk/drivers/s390/char/con3215.c +++ b/trunk/drivers/s390/char/con3215.c @@ -1121,7 +1121,7 @@ static const struct tty_operations tty3215_ops = { * 3215 tty registration code called from tty_init(). * Most kernel services (incl. kmalloc) are available at this poimt. */ -static int __init +int __init tty3215_init(void) { struct tty_driver *driver; diff --git a/trunk/drivers/s390/char/con3270.c b/trunk/drivers/s390/char/con3270.c index 8e7f2d7633d6..7566be890688 100644 --- a/trunk/drivers/s390/char/con3270.c +++ b/trunk/drivers/s390/char/con3270.c @@ -69,7 +69,8 @@ static void con3270_update(struct con3270 *); /* * Setup timeout for a device. On timeout trigger an update. */ -static void con3270_set_timer(struct con3270 *cp, int expires) +void +con3270_set_timer(struct con3270 *cp, int expires) { if (expires == 0) { if (timer_pending(&cp->timer)) diff --git a/trunk/drivers/s390/char/defkeymap.c b/trunk/drivers/s390/char/defkeymap.c index 564baca01b7c..17027d918cf7 100644 --- a/trunk/drivers/s390/char/defkeymap.c +++ b/trunk/drivers/s390/char/defkeymap.c @@ -5,8 +5,6 @@ #include #include #include -#include -#include u_short plain_map[NR_KEYS] = { 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, diff --git a/trunk/drivers/s390/char/fs3270.c b/trunk/drivers/s390/char/fs3270.c index e1a746269c4c..0893d306ae80 100644 --- a/trunk/drivers/s390/char/fs3270.c +++ b/trunk/drivers/s390/char/fs3270.c @@ -23,7 +23,7 @@ #include "raw3270.h" #include "ctrlchar.h" -static struct raw3270_fn fs3270_fn; +struct raw3270_fn fs3270_fn; struct fs3270 { struct raw3270_view view; @@ -401,7 +401,7 @@ fs3270_release(struct raw3270_view *view) } /* View to a 3270 device. Can be console, tty or fullscreen. */ -static struct raw3270_fn fs3270_fn = { +struct raw3270_fn fs3270_fn = { .activate = fs3270_activate, .deactivate = fs3270_deactivate, .intv = (void *) fs3270_irq, diff --git a/trunk/drivers/s390/char/keyboard.c b/trunk/drivers/s390/char/keyboard.c index f62f9a4e8950..3e86fd1756e5 100644 --- a/trunk/drivers/s390/char/keyboard.c +++ b/trunk/drivers/s390/char/keyboard.c @@ -148,7 +148,6 @@ kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc) } } -#if 0 /* * Generate ebcdic -> ascii translation table from kbd_data. */ @@ -174,7 +173,6 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc) } } } -#endif /* * We have a combining character DIACR here, followed by the character CH. diff --git a/trunk/drivers/s390/char/monwriter.c b/trunk/drivers/s390/char/monwriter.c index 9e451acc6491..cdb24f528112 100644 --- a/trunk/drivers/s390/char/monwriter.c +++ b/trunk/drivers/s390/char/monwriter.c @@ -67,8 +67,8 @@ static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn) return -EINVAL; } -static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, - struct monwrite_hdr *monhdr) +static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, + struct monwrite_hdr *monhdr) { struct mon_buf *entry, *next; diff --git a/trunk/drivers/s390/char/raw3270.c b/trunk/drivers/s390/char/raw3270.c index 8facd14adb7c..7a84014f2037 100644 --- a/trunk/drivers/s390/char/raw3270.c +++ b/trunk/drivers/s390/char/raw3270.c @@ -29,7 +29,7 @@ #include #include -static struct class *class3270; +struct class *class3270; /* The main 3270 data structure. */ struct raw3270 { @@ -86,7 +86,7 @@ DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue); /* * Encode array for 12 bit 3270 addresses. */ -static unsigned char raw3270_ebcgraf[64] = { +unsigned char raw3270_ebcgraf[64] = { 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, diff --git a/trunk/drivers/s390/char/sclp.c b/trunk/drivers/s390/char/sclp.c index f171de3b0b11..8a056df09d6b 100644 --- a/trunk/drivers/s390/char/sclp.c +++ b/trunk/drivers/s390/char/sclp.c @@ -59,8 +59,7 @@ static volatile enum sclp_init_state_t { /* Internal state: is a request active at the sclp? */ static volatile enum sclp_running_state_t { sclp_running_state_idle, - sclp_running_state_running, - sclp_running_state_reset_pending + sclp_running_state_running } sclp_running_state = sclp_running_state_idle; /* Internal state: is a read request pending? */ @@ -89,15 +88,15 @@ static volatile enum sclp_mask_state_t { /* Timeout intervals in seconds.*/ #define SCLP_BUSY_INTERVAL 10 -#define SCLP_RETRY_INTERVAL 30 +#define SCLP_RETRY_INTERVAL 15 static void sclp_process_queue(void); static int sclp_init_mask(int calculate); static int sclp_init(void); /* Perform service call. Return 0 on success, non-zero otherwise. */ -int -sclp_service_call(sclp_cmdw_t command, void *sccb) +static int +service_call(sclp_cmdw_t command, void *sccb) { int cc; @@ -114,17 +113,19 @@ sclp_service_call(sclp_cmdw_t command, void *sccb) return 0; } -static inline void __sclp_make_read_req(void); - +/* Request timeout handler. Restart the request queue. If DATA is non-zero, + * force restart of running request. */ static void -__sclp_queue_read_req(void) +sclp_request_timeout(unsigned long data) { - if (sclp_reading_state == sclp_reading_state_idle) { - sclp_reading_state = sclp_reading_state_reading; - __sclp_make_read_req(); - /* Add request to head of queue */ - list_add(&sclp_read_req.list, &sclp_req_queue); + unsigned long flags; + + if (data) { + spin_lock_irqsave(&sclp_lock, flags); + sclp_running_state = sclp_running_state_idle; + spin_unlock_irqrestore(&sclp_lock, flags); } + sclp_process_queue(); } /* Set up request retry timer. Called while sclp_lock is locked. */ @@ -139,29 +140,6 @@ __sclp_set_request_timer(unsigned long time, void (*function)(unsigned long), add_timer(&sclp_request_timer); } -/* Request timeout handler. Restart the request queue. If DATA is non-zero, - * force restart of running request. */ -static void -sclp_request_timeout(unsigned long data) -{ - unsigned long flags; - - spin_lock_irqsave(&sclp_lock, flags); - if (data) { - if (sclp_running_state == sclp_running_state_running) { - /* Break running state and queue NOP read event request - * to get a defined interface state. */ - __sclp_queue_read_req(); - sclp_running_state = sclp_running_state_idle; - } - } else { - __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ, - sclp_request_timeout, 0); - } - spin_unlock_irqrestore(&sclp_lock, flags); - sclp_process_queue(); -} - /* Try to start a request. Return zero if the request was successfully * started or if it will be started at a later time. Return non-zero otherwise. * Called while sclp_lock is locked. */ @@ -173,7 +151,7 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; del_timer(&sclp_request_timer); - rc = sclp_service_call(req->command, req->sccb); + rc = service_call(req->command, req->sccb); req->start_count++; if (rc == 0) { @@ -213,15 +191,7 @@ sclp_process_queue(void) rc = __sclp_start_request(req); if (rc == 0) break; - /* Request failed */ - if (req->start_count > 1) { - /* Cannot abort already submitted request - could still - * be active at the SCLP */ - __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ, - sclp_request_timeout, 0); - break; - } - /* Post-processing for aborted request */ + /* Request failed. */ list_del(&req->list); if (req->callback) { spin_unlock_irqrestore(&sclp_lock, flags); @@ -251,8 +221,7 @@ sclp_add_request(struct sclp_req *req) list_add_tail(&req->list, &sclp_req_queue); rc = 0; /* Start if request is first in list */ - if (sclp_running_state == sclp_running_state_idle && - req->list.prev == &sclp_req_queue) { + if (req->list.prev == &sclp_req_queue) { rc = __sclp_start_request(req); if (rc) list_del(&req->list); @@ -325,7 +294,7 @@ __sclp_make_read_req(void) sccb = (struct sccb_header *) sclp_read_sccb; clear_page(sccb); memset(&sclp_read_req, 0, sizeof(struct sclp_req)); - sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA; + sclp_read_req.command = SCLP_CMDW_READDATA; sclp_read_req.status = SCLP_REQ_QUEUED; sclp_read_req.start_count = 0; sclp_read_req.callback = sclp_read_cb; @@ -365,8 +334,6 @@ sclp_interrupt_handler(__u16 code) finished_sccb = S390_lowcore.ext_params & 0xfffffff8; evbuf_pending = S390_lowcore.ext_params & 0x3; if (finished_sccb) { - del_timer(&sclp_request_timer); - sclp_running_state = sclp_running_state_reset_pending; req = __sclp_find_req(finished_sccb); if (req) { /* Request post-processing */ @@ -381,8 +348,13 @@ sclp_interrupt_handler(__u16 code) sclp_running_state = sclp_running_state_idle; } if (evbuf_pending && sclp_receive_mask != 0 && - sclp_activation_state == sclp_activation_state_active) - __sclp_queue_read_req(); + sclp_reading_state == sclp_reading_state_idle && + sclp_activation_state == sclp_activation_state_active ) { + sclp_reading_state = sclp_reading_state_reading; + __sclp_make_read_req(); + /* Add request to head of queue */ + list_add(&sclp_read_req.list, &sclp_req_queue); + } spin_unlock(&sclp_lock); sclp_process_queue(); } @@ -402,7 +374,6 @@ sclp_sync_wait(void) unsigned long flags; unsigned long cr0, cr0_sync; u64 timeout; - int irq_context; /* We'll be disabling timer interrupts, so we need a custom timeout * mechanism */ @@ -415,9 +386,7 @@ sclp_sync_wait(void) } local_irq_save(flags); /* Prevent bottom half from executing once we force interrupts open */ - irq_context = in_interrupt(); - if (!irq_context) - local_bh_disable(); + local_bh_disable(); /* Enable service-signal interruption, disable timer interrupts */ trace_hardirqs_on(); __ctl_store(cr0, 0, 0); @@ -433,19 +402,19 @@ sclp_sync_wait(void) get_clock() > timeout && del_timer(&sclp_request_timer)) sclp_request_timer.function(sclp_request_timer.data); + barrier(); cpu_relax(); } local_irq_disable(); __ctl_load(cr0, 0, 0); - if (!irq_context) - _local_bh_enable(); + _local_bh_enable(); local_irq_restore(flags); } EXPORT_SYMBOL(sclp_sync_wait); /* Dispatch changes in send and receive mask to registered listeners. */ -static void +static inline void sclp_dispatch_state_change(void) { struct list_head *l; @@ -628,7 +597,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask) sccb = (struct init_sccb *) sclp_init_sccb; clear_page(sccb); memset(&sclp_init_req, 0, sizeof(struct sclp_req)); - sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK; + sclp_init_req.command = SCLP_CMDW_WRITEMASK; sclp_init_req.status = SCLP_REQ_FILLED; sclp_init_req.start_count = 0; sclp_init_req.callback = NULL; @@ -831,7 +800,7 @@ sclp_check_interface(void) for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { __sclp_make_init_req(0, 0); sccb = (struct init_sccb *) sclp_init_req.sccb; - rc = sclp_service_call(sclp_init_req.command, sccb); + rc = service_call(sclp_init_req.command, sccb); if (rc == -EIO) break; sclp_init_req.status = SCLP_REQ_RUNNING; diff --git a/trunk/drivers/s390/char/sclp.h b/trunk/drivers/s390/char/sclp.h index 7d29ab45a6ed..2c71d6ee7b5b 100644 --- a/trunk/drivers/s390/char/sclp.h +++ b/trunk/drivers/s390/char/sclp.h @@ -12,7 +12,7 @@ #include #include -#include + #include /* maximum number of pages concerning our own memory management */ @@ -49,11 +49,9 @@ typedef unsigned int sclp_cmdw_t; -#define SCLP_CMDW_READ_EVENT_DATA 0x00770005 -#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005 -#define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005 -#define SCLP_CMDW_READ_SCP_INFO 0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 +#define SCLP_CMDW_READDATA 0x00770005 +#define SCLP_CMDW_WRITEDATA 0x00760005 +#define SCLP_CMDW_WRITEMASK 0x00780005 #define GDS_ID_MDSMU 0x1310 #define GDS_ID_MDSRouteInfo 0x1311 @@ -68,6 +66,13 @@ typedef unsigned int sclp_cmdw_t; typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ +struct sccb_header { + u16 length; + u8 function_code; + u8 control_mask[3]; + u16 response_code; +} __attribute__((packed)); + struct gds_subvector { u8 length; u8 key; @@ -126,7 +131,6 @@ void sclp_unregister(struct sclp_register *reg); int sclp_remove_processed(struct sccb_header *sccb); int sclp_deactivate(void); int sclp_reactivate(void); -int sclp_service_call(sclp_cmdw_t command, void *sccb); /* useful inlines */ diff --git a/trunk/drivers/s390/char/sclp_con.c b/trunk/drivers/s390/char/sclp_con.c index ead1043d788e..86864f641716 100644 --- a/trunk/drivers/s390/char/sclp_con.c +++ b/trunk/drivers/s390/char/sclp_con.c @@ -66,7 +66,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback)); } -static void +static inline void sclp_conbuf_emit(void) { struct sclp_buffer* buffer; diff --git a/trunk/drivers/s390/char/sclp_cpi.c b/trunk/drivers/s390/char/sclp_cpi.c index 65aa2c85737f..4f873ae148b7 100644 --- a/trunk/drivers/s390/char/sclp_cpi.c +++ b/trunk/drivers/s390/char/sclp_cpi.c @@ -169,7 +169,7 @@ cpi_prepare_req(void) } /* prepare request data structure presented to SCLP driver */ - req->command = SCLP_CMDW_WRITE_EVENT_DATA; + req->command = SCLP_CMDW_WRITEDATA; req->sccb = sccb; req->status = SCLP_REQ_FILLED; req->callback = cpi_callback; diff --git a/trunk/drivers/s390/char/sclp_info.c b/trunk/drivers/s390/char/sclp_info.c deleted file mode 100644 index 7bcbe643b087..000000000000 --- a/trunk/drivers/s390/char/sclp_info.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * drivers/s390/char/sclp_info.c - * - * Copyright IBM Corp. 2007 - * Author(s): Heiko Carstens - */ - -#include -#include -#include -#include -#include "sclp.h" - -struct sclp_readinfo_sccb s390_readinfo_sccb; - -void __init sclp_readinfo_early(void) -{ - sclp_cmdw_t command; - struct sccb_header *sccb; - int ret; - - __ctl_set_bit(0, 9); /* enable service signal subclass mask */ - - sccb = &s390_readinfo_sccb.header; - command = SCLP_CMDW_READ_SCP_INFO_FORCED; - while (1) { - u16 response; - - memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); - sccb->length = sizeof(s390_readinfo_sccb); - sccb->control_mask[2] = 0x80; - - ret = sclp_service_call(command, &s390_readinfo_sccb); - - if (ret == -EIO) - goto out; - if (ret == -EBUSY) - continue; - - __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | - PSW_MASK_WAIT | PSW_DEFAULT_KEY); - local_irq_disable(); - barrier(); - - response = sccb->response_code; - - if (response == 0x10) - break; - - if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) - break; - - command = SCLP_CMDW_READ_SCP_INFO; - } -out: - __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ -} diff --git a/trunk/drivers/s390/char/sclp_rw.c b/trunk/drivers/s390/char/sclp_rw.c index 2486783ea58e..0c92d3909cca 100644 --- a/trunk/drivers/s390/char/sclp_rw.c +++ b/trunk/drivers/s390/char/sclp_rw.c @@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer, sccb->msg_buf.header.type = EvTyp_PMsgCmd; else return -ENOSYS; - buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; + buffer->request.command = SCLP_CMDW_WRITEDATA; buffer->request.status = SCLP_REQ_FILLED; buffer->request.callback = sclp_writedata_callback; buffer->request.callback_data = buffer; diff --git a/trunk/drivers/s390/char/sclp_tty.c b/trunk/drivers/s390/char/sclp_tty.c index 90536f60bf50..2d173e5c8a09 100644 --- a/trunk/drivers/s390/char/sclp_tty.c +++ b/trunk/drivers/s390/char/sclp_tty.c @@ -721,7 +721,7 @@ static const struct tty_operations sclp_ops = { .ioctl = sclp_tty_ioctl, }; -static int __init +int __init sclp_tty_init(void) { struct tty_driver *driver; diff --git a/trunk/drivers/s390/char/sclp_vt220.c b/trunk/drivers/s390/char/sclp_vt220.c index 544f137d70d7..723bf4191bfe 100644 --- a/trunk/drivers/s390/char/sclp_vt220.c +++ b/trunk/drivers/s390/char/sclp_vt220.c @@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request) request->sclp_req.status = SCLP_REQ_FAILED; return -EIO; } - request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA; + request->sclp_req.command = SCLP_CMDW_WRITEDATA; request->sclp_req.status = SCLP_REQ_FILLED; request->sclp_req.callback = sclp_vt220_callback; request->sclp_req.callback_data = (void *) request; @@ -669,7 +669,7 @@ static const struct tty_operations sclp_vt220_ops = { /* * Register driver with SCLP and Linux and initialize internal tty structures. */ -static int __init +int __init sclp_vt220_tty_init(void) { struct tty_driver *driver; diff --git a/trunk/drivers/s390/char/tape.h b/trunk/drivers/s390/char/tape.h index bb4ff537729d..c9f1c4c8bb13 100644 --- a/trunk/drivers/s390/char/tape.h +++ b/trunk/drivers/s390/char/tape.h @@ -3,7 +3,7 @@ * tape device driver for 3480/3490E/3590 tapes. * * S390 and zSeries version - * Copyright IBM Corp. 2001,2006 + * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Carsten Otte * Tuan Ngo-Anh * Martin Schwidefsky @@ -99,11 +99,7 @@ enum tape_op { TO_DIS, /* Tape display */ TO_ASSIGN, /* Assign tape to channel path */ TO_UNASSIGN, /* Unassign tape from channel path */ - TO_CRYPT_ON, /* Enable encrpytion */ - TO_CRYPT_OFF, /* Disable encrpytion */ - TO_KEKL_SET, /* Set KEK label */ - TO_KEKL_QUERY, /* Query KEK label */ - TO_SIZE, /* #entries in tape_op_t */ + TO_SIZE /* #entries in tape_op_t */ }; /* Forward declaration */ @@ -116,7 +112,6 @@ enum tape_request_status { TAPE_REQUEST_IN_IO, /* request is currently in IO */ TAPE_REQUEST_DONE, /* request is completed. */ TAPE_REQUEST_CANCEL, /* request should be canceled. */ - TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */ }; /* Tape CCW request */ @@ -169,11 +164,10 @@ struct tape_discipline { * The discipline irq function either returns an error code (<0) which * means that the request has failed with an error or one of the following: */ -#define TAPE_IO_SUCCESS 0 /* request successful */ -#define TAPE_IO_PENDING 1 /* request still running */ -#define TAPE_IO_RETRY 2 /* retry to current request */ -#define TAPE_IO_STOP 3 /* stop the running request */ -#define TAPE_IO_LONG_BUSY 4 /* delay the running request */ +#define TAPE_IO_SUCCESS 0 /* request successful */ +#define TAPE_IO_PENDING 1 /* request still running */ +#define TAPE_IO_RETRY 2 /* retry to current request */ +#define TAPE_IO_STOP 3 /* stop the running request */ /* Char Frontend Data */ struct tape_char_data { @@ -248,10 +242,6 @@ struct tape_device { /* Function to start or stop the next request later. */ struct delayed_work tape_dnr; - - /* Timer for long busy */ - struct timer_list lb_timeout; - }; /* Externals from tape_core.c */ diff --git a/trunk/drivers/s390/char/tape_3590.c b/trunk/drivers/s390/char/tape_3590.c index 50f5edab83d7..9df912f63188 100644 --- a/trunk/drivers/s390/char/tape_3590.c +++ b/trunk/drivers/s390/char/tape_3590.c @@ -2,7 +2,7 @@ * drivers/s390/char/tape_3590.c * tape device discipline for 3590 tapes. * - * Copyright IBM Corp. 2001,2006 + * Copyright (C) IBM Corp. 2001,2006 * Author(s): Stefan Bader * Michael Holzheu * Martin Schwidefsky @@ -11,7 +11,6 @@ #include #include #include -#include #define TAPE_DBF_AREA tape_3590_dbf @@ -31,7 +30,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA); * - Read Device (buffered) log: BRA * - Read Library log: BRA * - Swap Devices: BRA - * - Long Busy: implemented + * - Long Busy: BRA * - Special Intercept: BRA * - Read Alternate: implemented *******************************************************************/ @@ -95,332 +94,6 @@ static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { [0xae] = "Subsystem environmental alert", }; -static int crypt_supported(struct tape_device *device) -{ - return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device)); -} - -static int crypt_enabled(struct tape_device *device) -{ - return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device)); -} - -static void ext_to_int_kekl(struct tape390_kekl *in, - struct tape3592_kekl *out) -{ - int i; - - memset(out, 0, sizeof(*out)); - if (in->type == TAPE390_KEKL_TYPE_HASH) - out->flags |= 0x40; - if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH) - out->flags |= 0x80; - strncpy(out->label, in->label, 64); - for (i = strlen(in->label); i < sizeof(out->label); i++) - out->label[i] = ' '; - ASCEBC(out->label, sizeof(out->label)); -} - -static void int_to_ext_kekl(struct tape3592_kekl *in, - struct tape390_kekl *out) -{ - memset(out, 0, sizeof(*out)); - if(in->flags & 0x40) - out->type = TAPE390_KEKL_TYPE_HASH; - else - out->type = TAPE390_KEKL_TYPE_LABEL; - if(in->flags & 0x80) - out->type_on_tape = TAPE390_KEKL_TYPE_HASH; - else - out->type_on_tape = TAPE390_KEKL_TYPE_LABEL; - memcpy(out->label, in->label, sizeof(in->label)); - EBCASC(out->label, sizeof(in->label)); - strstrip(out->label); -} - -static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in, - struct tape390_kekl_pair *out) -{ - if (in->count == 0) { - out->kekl[0].type = TAPE390_KEKL_TYPE_NONE; - out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE; - out->kekl[1].type = TAPE390_KEKL_TYPE_NONE; - out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE; - } else if (in->count == 1) { - int_to_ext_kekl(&in->kekl[0], &out->kekl[0]); - out->kekl[1].type = TAPE390_KEKL_TYPE_NONE; - out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE; - } else if (in->count == 2) { - int_to_ext_kekl(&in->kekl[0], &out->kekl[0]); - int_to_ext_kekl(&in->kekl[1], &out->kekl[1]); - } else { - printk("Invalid KEKL number: %d\n", in->count); - BUG(); - } -} - -static int check_ext_kekl(struct tape390_kekl *kekl) -{ - if (kekl->type == TAPE390_KEKL_TYPE_NONE) - goto invalid; - if (kekl->type > TAPE390_KEKL_TYPE_HASH) - goto invalid; - if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE) - goto invalid; - if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH) - goto invalid; - if ((kekl->type == TAPE390_KEKL_TYPE_HASH) && - (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL)) - goto invalid; - - return 0; -invalid: - return -EINVAL; -} - -static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls) -{ - if (check_ext_kekl(&kekls->kekl[0])) - goto invalid; - if (check_ext_kekl(&kekls->kekl[1])) - goto invalid; - - return 0; -invalid: - return -EINVAL; -} - -/* - * Query KEKLs - */ -static int tape_3592_kekl_query(struct tape_device *device, - struct tape390_kekl_pair *ext_kekls) -{ - struct tape_request *request; - struct tape3592_kekl_query_order *order; - struct tape3592_kekl_query_data *int_kekls; - int rc; - - DBF_EVENT(6, "tape3592_kekl_query\n"); - int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA); - if (!int_kekls) - return -ENOMEM; - request = tape_alloc_request(2, sizeof(*order)); - if (IS_ERR(request)) { - rc = PTR_ERR(request); - goto fail_malloc; - } - order = request->cpdata; - memset(order,0,sizeof(*order)); - order->code = 0xe2; - order->max_count = 2; - request->op = TO_KEKL_QUERY; - tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order); - tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls), - int_kekls); - rc = tape_do_io(device, request); - if (rc) - goto fail_request; - int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls); - - rc = 0; -fail_request: - tape_free_request(request); -fail_malloc: - kfree(int_kekls); - return rc; -} - -/* - * IOCTL: Query KEKLs - */ -static int tape_3592_ioctl_kekl_query(struct tape_device *device, - unsigned long arg) -{ - int rc; - struct tape390_kekl_pair *ext_kekls; - - DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n"); - if (!crypt_supported(device)) - return -ENOSYS; - if (!crypt_enabled(device)) - return -EUNATCH; - ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL); - if (!ext_kekls) - return -ENOMEM; - rc = tape_3592_kekl_query(device, ext_kekls); - if (rc != 0) - goto fail; - if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) { - rc = -EFAULT; - goto fail; - } - rc = 0; -fail: - kfree(ext_kekls); - return rc; -} - -static int tape_3590_mttell(struct tape_device *device, int mt_count); - -/* - * Set KEKLs - */ -static int tape_3592_kekl_set(struct tape_device *device, - struct tape390_kekl_pair *ext_kekls) -{ - struct tape_request *request; - struct tape3592_kekl_set_order *order; - - DBF_EVENT(6, "tape3592_kekl_set\n"); - if (check_ext_kekl_pair(ext_kekls)) { - DBF_EVENT(6, "invalid kekls\n"); - return -EINVAL; - } - if (tape_3590_mttell(device, 0) != 0) - return -EBADSLT; - request = tape_alloc_request(1, sizeof(*order)); - if (IS_ERR(request)) - return PTR_ERR(request); - order = request->cpdata; - memset(order, 0, sizeof(*order)); - order->code = 0xe3; - order->kekls.count = 2; - ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]); - ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]); - request->op = TO_KEKL_SET; - tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order); - - return tape_do_io_free(device, request); -} - -/* - * IOCTL: Set KEKLs - */ -static int tape_3592_ioctl_kekl_set(struct tape_device *device, - unsigned long arg) -{ - int rc; - struct tape390_kekl_pair *ext_kekls; - - DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n"); - if (!crypt_supported(device)) - return -ENOSYS; - if (!crypt_enabled(device)) - return -EUNATCH; - ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL); - if (!ext_kekls) - return -ENOMEM; - if (copy_from_user(ext_kekls, (char __user *)arg, sizeof(*ext_kekls))) { - rc = -EFAULT; - goto out; - } - rc = tape_3592_kekl_set(device, ext_kekls); -out: - kfree(ext_kekls); - return rc; -} - -/* - * Enable encryption - */ -static int tape_3592_enable_crypt(struct tape_device *device) -{ - struct tape_request *request; - char *data; - - DBF_EVENT(6, "tape_3592_enable_crypt\n"); - if (!crypt_supported(device)) - return -ENOSYS; - request = tape_alloc_request(2, 72); - if (IS_ERR(request)) - return PTR_ERR(request); - data = request->cpdata; - memset(data,0,72); - - data[0] = 0x05; - data[36 + 0] = 0x03; - data[36 + 1] = 0x03; - data[36 + 4] = 0x40; - data[36 + 6] = 0x01; - data[36 + 14] = 0x2f; - data[36 + 18] = 0xc3; - data[36 + 35] = 0x72; - request->op = TO_CRYPT_ON; - tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); - tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); - return tape_do_io_free(device, request); -} - -/* - * Disable encryption - */ -static int tape_3592_disable_crypt(struct tape_device *device) -{ - struct tape_request *request; - char *data; - - DBF_EVENT(6, "tape_3592_disable_crypt\n"); - if (!crypt_supported(device)) - return -ENOSYS; - request = tape_alloc_request(2, 72); - if (IS_ERR(request)) - return PTR_ERR(request); - data = request->cpdata; - memset(data,0,72); - - data[0] = 0x05; - data[36 + 0] = 0x03; - data[36 + 1] = 0x03; - data[36 + 35] = 0x32; - - request->op = TO_CRYPT_OFF; - tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); - tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); - - return tape_do_io_free(device, request); -} - -/* - * IOCTL: Set encryption status - */ -static int tape_3592_ioctl_crypt_set(struct tape_device *device, - unsigned long arg) -{ - struct tape390_crypt_info info; - - DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n"); - if (!crypt_supported(device)) - return -ENOSYS; - if (copy_from_user(&info, (char __user *)arg, sizeof(info))) - return -EFAULT; - if (info.status & ~TAPE390_CRYPT_ON_MASK) - return -EINVAL; - if (info.status & TAPE390_CRYPT_ON_MASK) - return tape_3592_enable_crypt(device); - else - return tape_3592_disable_crypt(device); -} - -static int tape_3590_sense_medium(struct tape_device *device); - -/* - * IOCTL: Query enryption status - */ -static int tape_3592_ioctl_crypt_query(struct tape_device *device, - unsigned long arg) -{ - DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n"); - if (!crypt_supported(device)) - return -ENOSYS; - tape_3590_sense_medium(device); - if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device), - sizeof(TAPE_3590_CRYPT_INFO(device)))) - return -EFAULT; - else - return 0; -} - /* * 3590 IOCTL Overload */ @@ -436,14 +109,6 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg) return tape_std_display(device, &disp); } - case TAPE390_KEKL_SET: - return tape_3592_ioctl_kekl_set(device, arg); - case TAPE390_KEKL_QUERY: - return tape_3592_ioctl_kekl_query(device, arg); - case TAPE390_CRYPT_SET: - return tape_3592_ioctl_crypt_set(device, arg); - case TAPE390_CRYPT_QUERY: - return tape_3592_ioctl_crypt_query(device, arg); default: return -EINVAL; /* no additional ioctls */ } @@ -583,12 +248,6 @@ tape_3590_work_handler(struct work_struct *work) case TO_READ_ATTMSG: tape_3590_read_attmsg(p->device); break; - case TO_CRYPT_ON: - tape_3592_enable_crypt(p->device); - break; - case TO_CRYPT_OFF: - tape_3592_disable_crypt(p->device); - break; default: DBF_EVENT(3, "T3590: work handler undefined for " "operation 0x%02x\n", p->op); @@ -706,33 +365,6 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request) } #endif -static void tape_3590_med_state_set(struct tape_device *device, - struct tape_3590_med_sense *sense) -{ - struct tape390_crypt_info *c_info; - - c_info = &TAPE_3590_CRYPT_INFO(device); - - if (sense->masst == MSENSE_UNASSOCIATED) { - tape_med_state_set(device, MS_UNLOADED); - TAPE_3590_CRYPT_INFO(device).medium_status = 0; - return; - } - if (sense->masst != MSENSE_ASSOCIATED_MOUNT) { - PRINT_ERR("Unknown medium state: %x\n", sense->masst); - return; - } - tape_med_state_set(device, MS_LOADED); - c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; - if (sense->flags & MSENSE_CRYPT_MASK) { - PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); - c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK; - } else { - DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags); - c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK; - } -} - /* * The done handler is called at device/channel end and wakes up the sleeping * process @@ -740,10 +372,9 @@ static void tape_3590_med_state_set(struct tape_device *device, static int tape_3590_done(struct tape_device *device, struct tape_request *request) { - struct tape_3590_disc_data *disc_data; + struct tape_3590_med_sense *sense; DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); - disc_data = device->discdata; switch (request->op) { case TO_BSB: @@ -763,20 +394,13 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) break; case TO_RUN: tape_med_state_set(device, MS_UNLOADED); - tape_3590_schedule_work(device, TO_CRYPT_OFF); break; case TO_MSEN: - tape_3590_med_state_set(device, request->cpdata); - break; - case TO_CRYPT_ON: - TAPE_3590_CRYPT_INFO(device).status - |= TAPE390_CRYPT_ON_MASK; - *(device->modeset_byte) |= 0x03; - break; - case TO_CRYPT_OFF: - TAPE_3590_CRYPT_INFO(device).status - &= ~TAPE390_CRYPT_ON_MASK; - *(device->modeset_byte) &= ~0x03; + sense = (struct tape_3590_med_sense *) request->cpdata; + if (sense->masst == MSENSE_UNASSOCIATED) + tape_med_state_set(device, MS_UNLOADED); + if (sense->masst == MSENSE_ASSOCIATED_MOUNT) + tape_med_state_set(device, MS_LOADED); break; case TO_RBI: /* RBI seems to succeed even without medium loaded. */ case TO_NOP: /* Same to NOP. */ @@ -785,9 +409,8 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) case TO_DIS: case TO_ASSIGN: case TO_UNASSIGN: + break; case TO_SIZE: - case TO_KEKL_SET: - case TO_KEKL_QUERY: break; } return TAPE_IO_SUCCESS; @@ -917,8 +540,10 @@ static int tape_3590_erp_long_busy(struct tape_device *device, struct tape_request *request, struct irb *irb) { - DBF_EVENT(6, "Device is busy\n"); - return TAPE_IO_LONG_BUSY; + /* FIXME: how about WAITING for a minute ? */ + PRINT_WARN("(%s): Device is busy! Please wait a minute!\n", + device->cdev->dev.bus_id); + return tape_3590_erp_basic(device, request, irb, -EBUSY); } /* @@ -1326,34 +951,6 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) device->cdev->dev.bus_id, sense->mc); } -static int tape_3590_crypt_error(struct tape_device *device, - struct tape_request *request, struct irb *irb) -{ - u8 cu_rc, ekm_rc1; - u16 ekm_rc2; - u32 drv_rc; - char *bus_id, *sense; - - sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data; - bus_id = device->cdev->dev.bus_id; - cu_rc = sense[0]; - drv_rc = *((u32*) &sense[5]) & 0xffffff; - ekm_rc1 = sense[9]; - ekm_rc2 = *((u16*) &sense[10]); - if ((cu_rc == 0) && (ekm_rc2 == 0xee31)) - /* key not defined on EKM */ - return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED); - if ((cu_rc == 1) || (cu_rc == 2)) - /* No connection to EKM */ - return tape_3590_erp_basic(device, request, irb, -ENOTCONN); - - PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id); - PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc, - drv_rc, ekm_rc1, ekm_rc2); - - return tape_3590_erp_basic(device, request, irb, -ENOKEY); -} - /* * 3590 error Recovery routine: * If possible, it tries to recover from the error. If this is not possible, @@ -1382,8 +979,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, sense = (struct tape_3590_sense *) irb->ecw; - DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc); - /* * First check all RC-QRCs where we want to do something special * - "break": basic error recovery is done @@ -1404,8 +999,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, case 0x2231: tape_3590_print_era_msg(device, irb); return tape_3590_erp_special_interrupt(device, request, irb); - case 0x2240: - return tape_3590_crypt_error(device, request, irb); case 0x3010: DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", @@ -1427,7 +1020,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, DBF_EVENT(2, "(%08x): Rewind Unload complete\n", device->cdev_id); tape_med_state_set(device, MS_UNLOADED); - tape_3590_schedule_work(device, TO_CRYPT_OFF); return tape_3590_erp_basic(device, request, irb, 0); case 0x4010: @@ -1438,15 +1030,9 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, PRINT_WARN("(%s): Tape operation when medium not loaded\n", device->cdev->dev.bus_id); tape_med_state_set(device, MS_UNLOADED); - tape_3590_schedule_work(device, TO_CRYPT_OFF); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); case 0x4012: /* Device Long Busy */ - /* XXX: Also use long busy handling here? */ - DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id); tape_3590_print_era_msg(device, irb); - return tape_3590_erp_basic(device, request, irb, -EBUSY); - case 0x4014: - DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id); return tape_3590_erp_long_busy(device, request, irb); case 0x5010: @@ -1478,7 +1064,6 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, case 0x5120: case 0x1120: tape_med_state_set(device, MS_UNLOADED); - tape_3590_schedule_work(device, TO_CRYPT_OFF); return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); case 0x6020: @@ -1557,47 +1142,21 @@ tape_3590_setup_device(struct tape_device *device) { int rc; struct tape_3590_disc_data *data; - char *rdc_data; DBF_EVENT(6, "3590 device setup\n"); - data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA); + data = kmalloc(sizeof(struct tape_3590_disc_data), + GFP_KERNEL | GFP_DMA); if (data == NULL) return -ENOMEM; data->read_back_op = READ_PREVIOUS; device->discdata = data; - rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA); - if (!rdc_data) { - rc = -ENOMEM; - goto fail_kmalloc; - } - rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64); - if (rc) { - DBF_LH(3, "Read device characteristics failed!\n"); - goto fail_kmalloc; - } - rc = tape_std_assign(device); - if (rc) - goto fail_rdc_data; - if (rdc_data[31] == 0x13) { - PRINT_INFO("Device has crypto support\n"); - data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; - tape_3592_disable_crypt(device); - } else { - DBF_EVENT(6, "Device has NO crypto support\n"); + if ((rc = tape_std_assign(device)) == 0) { + /* Try to find out if medium is loaded */ + if ((rc = tape_3590_sense_medium(device)) != 0) + DBF_LH(3, "3590 medium sense returned %d\n", rc); } - /* Try to find out if medium is loaded */ - rc = tape_3590_sense_medium(device); - if (rc) { - DBF_LH(3, "3590 medium sense returned %d\n", rc); - goto fail_rdc_data; - } - return 0; -fail_rdc_data: - kfree(rdc_data); -fail_kmalloc: - kfree(data); return rc; } diff --git a/trunk/drivers/s390/char/tape_3590.h b/trunk/drivers/s390/char/tape_3590.h index aa5138807af1..cf274b9445a6 100644 --- a/trunk/drivers/s390/char/tape_3590.h +++ b/trunk/drivers/s390/char/tape_3590.h @@ -2,7 +2,7 @@ * drivers/s390/char/tape_3590.h * tape device discipline for 3590 tapes. * - * Copyright IBM Corp. 2001,2006 + * Copyright (C) IBM Corp. 2001,2006 * Author(s): Stefan Bader * Michael Holzheu * Martin Schwidefsky @@ -38,22 +38,16 @@ #define MSENSE_UNASSOCIATED 0x00 #define MSENSE_ASSOCIATED_MOUNT 0x01 #define MSENSE_ASSOCIATED_UMOUNT 0x02 -#define MSENSE_CRYPT_MASK 0x00000010 #define TAPE_3590_MAX_MSG 0xb0 /* Datatypes */ struct tape_3590_disc_data { - struct tape390_crypt_info crypt_info; + unsigned char modeset_byte; int read_back_op; }; -#define TAPE_3590_CRYPT_INFO(device) \ - ((struct tape_3590_disc_data*)(device->discdata))->crypt_info -#define TAPE_3590_READ_BACK_OP(device) \ - ((struct tape_3590_disc_data*)(device->discdata))->read_back_op - struct tape_3590_sense { unsigned int command_rej:1; @@ -124,48 +118,7 @@ struct tape_3590_sense { struct tape_3590_med_sense { unsigned int macst:4; unsigned int masst:4; - char pad1[7]; - unsigned int flags; - char pad2[116]; -} __attribute__ ((packed)); - -/* Datastructures for 3592 encryption support */ - -struct tape3592_kekl { - __u8 flags; - char label[64]; -} __attribute__ ((packed)); - -struct tape3592_kekl_pair { - __u8 count; - struct tape3592_kekl kekl[2]; -} __attribute__ ((packed)); - -struct tape3592_kekl_query_data { - __u16 len; - __u8 fmt; - __u8 mc; - __u32 id; - __u8 flags; - struct tape3592_kekl_pair kekls; - char reserved[116]; -} __attribute__ ((packed)); - -struct tape3592_kekl_query_order { - __u8 code; - __u8 flags; - char reserved1[2]; - __u8 max_count; - char reserved2[35]; -} __attribute__ ((packed)); - -struct tape3592_kekl_set_order { - __u8 code; - __u8 flags; - char reserved1[2]; - __u8 op; - struct tape3592_kekl_pair kekls; - char reserved2[120]; + char pad[127]; } __attribute__ ((packed)); #endif /* _TAPE_3590_H */ diff --git a/trunk/drivers/s390/char/tape_block.c b/trunk/drivers/s390/char/tape_block.c index dd0ecaed592e..c8a89b3b87d4 100644 --- a/trunk/drivers/s390/char/tape_block.c +++ b/trunk/drivers/s390/char/tape_block.c @@ -73,7 +73,7 @@ tapeblock_trigger_requeue(struct tape_device *device) /* * Post finished request. */ -static void +static inline void tapeblock_end_request(struct request *req, int uptodate) { if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) @@ -108,7 +108,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data) /* * Feed the tape device CCW queue with requests supplied in a list. */ -static int +static inline int tapeblock_start_request(struct tape_device *device, struct request *req) { struct tape_request * ccw_req; diff --git a/trunk/drivers/s390/char/tape_char.c b/trunk/drivers/s390/char/tape_char.c index 9faea04e11e9..31198c8f2718 100644 --- a/trunk/drivers/s390/char/tape_char.c +++ b/trunk/drivers/s390/char/tape_char.c @@ -3,7 +3,7 @@ * character device frontend for tape device driver * * S390 and zSeries version - * Copyright IBM Corp. 2001,2006 + * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Carsten Otte * Michael Holzheu * Tuan Ngo-Anh @@ -89,7 +89,22 @@ tapechar_cleanup_device(struct tape_device *device) device->nt = NULL; } -static int +/* + * Terminate write command (we write two TMs and skip backward over last) + * This ensures that the tape is always correctly terminated. + * When the user writes afterwards a new file, he will overwrite the + * second TM and therefore one TM will remain to separate the + * two files on the tape... + */ +static inline void +tapechar_terminate_write(struct tape_device *device) +{ + if (tape_mtop(device, MTWEOF, 1) == 0 && + tape_mtop(device, MTWEOF, 1) == 0) + tape_mtop(device, MTBSR, 1); +} + +static inline int tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) { struct idal_buffer *new; @@ -122,7 +137,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) /* * Tape device read function */ -static ssize_t +ssize_t tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) { struct tape_device *device; @@ -186,7 +201,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) /* * Tape device write function */ -static ssize_t +ssize_t tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos) { struct tape_device *device; @@ -276,7 +291,7 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t /* * Character frontend tape device open function. */ -static int +int tapechar_open (struct inode *inode, struct file *filp) { struct tape_device *device; @@ -311,7 +326,7 @@ tapechar_open (struct inode *inode, struct file *filp) * Character frontend tape device release function. */ -static int +int tapechar_release(struct inode *inode, struct file *filp) { struct tape_device *device; diff --git a/trunk/drivers/s390/char/tape_core.c b/trunk/drivers/s390/char/tape_core.c index e2a8a1a04bab..c6c2e918b990 100644 --- a/trunk/drivers/s390/char/tape_core.c +++ b/trunk/drivers/s390/char/tape_core.c @@ -3,7 +3,7 @@ * basic function of the tape device driver * * S390 and zSeries version - * Copyright IBM Corp. 2001,2006 + * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Carsten Otte * Michael Holzheu * Tuan Ngo-Anh @@ -26,11 +26,9 @@ #include "tape_std.h" #define PRINTK_HEADER "TAPE_CORE: " -#define LONG_BUSY_TIMEOUT 180 /* seconds */ static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); static void tape_delayed_next_request(struct work_struct *); -static void tape_long_busy_timeout(unsigned long data); /* * One list to contain all tape devices of all disciplines, so @@ -71,12 +69,10 @@ const char *tape_op_verbose[TO_SIZE] = [TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF", [TO_READ_ATTMSG] = "RAT", [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", - [TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON", - [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS", - [TO_KEKL_QUERY] = "KLQ", + [TO_UNASSIGN] = "UAS" }; -static int +static inline int busid_to_int(char *bus_id) { int dec; @@ -256,7 +252,7 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) /* * Stop running ccw. Has to be called with the device lock held. */ -static int +static inline int __tape_cancel_io(struct tape_device *device, struct tape_request *request) { int retries; @@ -350,9 +346,6 @@ tape_generic_online(struct tape_device *device, return -EINVAL; } - init_timer(&device->lb_timeout); - device->lb_timeout.function = tape_long_busy_timeout; - /* Let the discipline have a go at the device. */ device->discipline = discipline; if (!try_module_get(discipline->owner)) { @@ -392,7 +385,7 @@ tape_generic_online(struct tape_device *device, return rc; } -static void +static inline void tape_cleanup_device(struct tape_device *device) { tapeblock_cleanup_device(device); @@ -570,7 +563,7 @@ tape_generic_probe(struct ccw_device *cdev) return ret; } -static void +static inline void __tape_discard_requests(struct tape_device *device) { struct tape_request * request; @@ -710,7 +703,7 @@ tape_free_request (struct tape_request * request) kfree(request); } -static int +static inline int __tape_start_io(struct tape_device *device, struct tape_request *request) { int rc; @@ -740,7 +733,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request) return rc; } -static void +static inline void __tape_start_next_request(struct tape_device *device) { struct list_head *l, *n; @@ -808,23 +801,7 @@ tape_delayed_next_request(struct work_struct *work) spin_unlock_irq(get_ccwdev_lock(device->cdev)); } -static void tape_long_busy_timeout(unsigned long data) -{ - struct tape_request *request; - struct tape_device *device; - - device = (struct tape_device *) data; - spin_lock_irq(get_ccwdev_lock(device->cdev)); - request = list_entry(device->req_queue.next, struct tape_request, list); - if (request->status != TAPE_REQUEST_LONG_BUSY) - BUG(); - DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); - __tape_start_next_request(device); - device->lb_timeout.data = (unsigned long) tape_put_device(device); - spin_unlock_irq(get_ccwdev_lock(device->cdev)); -} - -static void +static inline void __tape_end_request( struct tape_device * device, struct tape_request * request, @@ -901,7 +878,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request, * and starts it if the tape is idle. Has to be called with * the device lock held. */ -static int +static inline int __tape_start_request(struct tape_device *device, struct tape_request *request) { int rc; @@ -1117,22 +1094,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) /* May be an unsolicited irq */ if(request != NULL) request->rescnt = irb->scsw.count; - else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) && - !list_empty(&device->req_queue)) { - /* Not Ready to Ready after long busy ? */ - struct tape_request *req; - req = list_entry(device->req_queue.next, - struct tape_request, list); - if (req->status == TAPE_REQUEST_LONG_BUSY) { - DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); - if (del_timer(&device->lb_timeout)) { - device->lb_timeout.data = (unsigned long) - tape_put_device(device); - __tape_start_next_request(device); - } - return; - } - } + if (irb->scsw.dstat != 0x0c) { /* Set the 'ONLINE' flag depending on sense byte 1 */ if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) @@ -1180,15 +1142,6 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) break; case TAPE_IO_PENDING: break; - case TAPE_IO_LONG_BUSY: - device->lb_timeout.data = - (unsigned long)tape_get_device_reference(device); - device->lb_timeout.expires = jiffies + - LONG_BUSY_TIMEOUT * HZ; - DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); - add_timer(&device->lb_timeout); - request->status = TAPE_REQUEST_LONG_BUSY; - break; case TAPE_IO_RETRY: rc = __tape_start_io(device, request); if (rc) diff --git a/trunk/drivers/s390/char/tty3270.c b/trunk/drivers/s390/char/tty3270.c index bc33068b9ce2..09844621edc0 100644 --- a/trunk/drivers/s390/char/tty3270.c +++ b/trunk/drivers/s390/char/tty3270.c @@ -36,7 +36,7 @@ struct tty_driver *tty3270_driver; static int tty3270_max_index; -static struct raw3270_fn tty3270_fn; +struct raw3270_fn tty3270_fn; struct tty3270_cell { unsigned char character; @@ -119,7 +119,8 @@ static void tty3270_update(struct tty3270 *); /* * Setup timeout for a device. On timeout trigger an update. */ -static void tty3270_set_timer(struct tty3270 *tp, int expires) +void +tty3270_set_timer(struct tty3270 *tp, int expires) { if (expires == 0) { if (timer_pending(&tp->timer) && del_timer(&tp->timer)) @@ -840,7 +841,7 @@ tty3270_del_views(void) } } -static struct raw3270_fn tty3270_fn = { +struct raw3270_fn tty3270_fn = { .activate = tty3270_activate, .deactivate = tty3270_deactivate, .intv = (void *) tty3270_irq, @@ -1753,7 +1754,8 @@ static const struct tty_operations tty3270_ops = { .set_termios = tty3270_set_termios }; -static void tty3270_notifier(int index, int active) +void +tty3270_notifier(int index, int active) { if (active) tty_register_device(tty3270_driver, index, NULL); @@ -1765,7 +1767,8 @@ static void tty3270_notifier(int index, int active) * 3270 tty registration code called from tty_init(). * Most kernel services (incl. kmalloc) are available at this poimt. */ -static int __init tty3270_init(void) +int __init +tty3270_init(void) { struct tty_driver *driver; int ret; diff --git a/trunk/drivers/s390/char/vmlogrdr.c b/trunk/drivers/s390/char/vmlogrdr.c index 4f894dc2373b..6cb23040954b 100644 --- a/trunk/drivers/s390/char/vmlogrdr.c +++ b/trunk/drivers/s390/char/vmlogrdr.c @@ -128,8 +128,9 @@ static iucv_interrupt_ops_t vmlogrdr_iucvops = { .MessagePending = vmlogrdr_iucv_MessagePending, }; -static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue); -static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); + +DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue); +DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); /* * pointer to system service private structure diff --git a/trunk/drivers/s390/cio/blacklist.c b/trunk/drivers/s390/cio/blacklist.c index aa65df4dfced..12c2d6b746e6 100644 --- a/trunk/drivers/s390/cio/blacklist.c +++ b/trunk/drivers/s390/cio/blacklist.c @@ -43,7 +43,7 @@ typedef enum {add, free} range_action; * Function: blacklist_range * (Un-)blacklist the devices from-to */ -static void +static inline void blacklist_range (range_action action, unsigned int from, unsigned int to, unsigned int ssid) { @@ -69,7 +69,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to, * Get devno/busid from given string. * Shamelessly grabbed from dasd_devmap.c. */ -static int +static inline int blacklist_busid(char **str, int *id0, int *ssid, int *devno) { int val, old_style; @@ -123,10 +123,10 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno) return 1; } -static int +static inline int blacklist_parse_parameters (char *str, range_action action) { - int from, to, from_id0, to_id0, from_ssid, to_ssid; + unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid; while (*str != 0 && *str != '\n') { range_action ra = action; @@ -227,7 +227,7 @@ is_blacklisted (int ssid, int devno) * Function: blacklist_parse_proc_parameters * parse the stuff which is piped to /proc/cio_ignore */ -static void +static inline void blacklist_parse_proc_parameters (char *buf) { if (strncmp (buf, "free ", 5) == 0) { diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index d48e3ca4752c..38954f5cd14c 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -53,7 +53,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, static struct bus_type ccwgroup_bus_type; -static void +static inline void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) { int i; @@ -104,7 +104,7 @@ ccwgroup_release (struct device *dev) kfree(gdev); } -static int +static inline int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) { char str[8]; @@ -424,7 +424,7 @@ ccwgroup_probe_ccwdev(struct ccw_device *cdev) return 0; } -static struct ccwgroup_device * +static inline struct ccwgroup_device * __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) { struct ccwgroup_device *gdev; diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 6f05a44e3817..cbab8d2ce5cf 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -93,7 +93,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) u16 sch; /* subchannel */ u8 chpid[8]; /* chpids 0-7 */ u16 fla[8]; /* full link addresses 0-7 */ - } __attribute__ ((packed)) *ssd_area; + } *ssd_area; ssd_area = page; @@ -277,7 +277,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) return 0; } -static void +static inline void s390_set_chpid_offline( __u8 chpid) { char dbf_txt[15]; @@ -338,7 +338,7 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) return 0x80 >> chp; } -static int +static inline int s390_process_res_acc_new_sch(struct subchannel_id schid) { struct schib schib; @@ -444,7 +444,7 @@ __get_chpid_from_lir(void *data) u32 andesc[28]; /* incident-specific information */ u32 isinfo[28]; - } __attribute__ ((packed)) *lir; + } *lir; lir = data; if (!(lir->iq&0x80)) @@ -461,146 +461,154 @@ __get_chpid_from_lir(void *data) return (u16) (lir->indesc[0]&0x000000ff); } -struct chsc_sei_area { - struct chsc_header request; - u32 reserved1; - u32 reserved2; - u32 reserved3; - struct chsc_header response; - u32 reserved4; - u8 flags; - u8 vf; /* validity flags */ - u8 rs; /* reporting source */ - u8 cc; /* content code */ - u16 fla; /* full link address */ - u16 rsid; /* reporting source id */ - u32 reserved5; - u32 reserved6; - u8 ccdf[4096 - 16 - 24]; /* content-code dependent field */ - /* ccdf has to be big enough for a link-incident record */ -} __attribute__ ((packed)); - -static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) -{ - int chpid; - - CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", - sei_area->rs, sei_area->rsid); - if (sei_area->rs != 4) - return 0; - chpid = __get_chpid_from_lir(sei_area->ccdf); - if (chpid < 0) - CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); - else - s390_set_chpid_offline(chpid); - - return 0; -} - -static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) +int +chsc_process_crw(void) { + int chpid, ret; struct res_acc_data res_data; - struct device *dev; - int status; - int rc; - - CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, " - "rs_id=%04x)\n", sei_area->rs, sei_area->rsid); - if (sei_area->rs != 4) - return 0; - /* allocate a new channel path structure, if needed */ - status = get_chp_status(sei_area->rsid); - if (status < 0) - new_channel_path(sei_area->rsid); - else if (!status) - return 0; - dev = get_device(&css[0]->chps[sei_area->rsid]->dev); - memset(&res_data, 0, sizeof(struct res_acc_data)); - res_data.chp = to_channelpath(dev); - if ((sei_area->vf & 0xc0) != 0) { - res_data.fla = sei_area->fla; - if ((sei_area->vf & 0xc0) == 0xc0) - /* full link address */ - res_data.fla_mask = 0xffff; - else - /* link address */ - res_data.fla_mask = 0xff00; - } - rc = s390_process_res_acc(&res_data); - put_device(dev); - - return rc; -} - -static int chsc_process_sei(struct chsc_sei_area *sei_area) -{ - int rc; - - /* Check if we might have lost some information. */ - if (sei_area->flags & 0x40) - CIO_CRW_EVENT(2, "chsc: event overflow\n"); - /* which kind of information was stored? */ - rc = 0; - switch (sei_area->cc) { - case 1: /* link incident*/ - rc = chsc_process_sei_link_incident(sei_area); - break; - case 2: /* i/o resource accessibiliy */ - rc = chsc_process_sei_res_acc(sei_area); - break; - default: /* other stuff */ - CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n", - sei_area->cc); - break; - } - - return rc; -} - -int chsc_process_crw(void) -{ - struct chsc_sei_area *sei_area; - int ret; - int rc; + struct { + struct chsc_header request; + u32 reserved1; + u32 reserved2; + u32 reserved3; + struct chsc_header response; + u32 reserved4; + u8 flags; + u8 vf; /* validity flags */ + u8 rs; /* reporting source */ + u8 cc; /* content code */ + u16 fla; /* full link address */ + u16 rsid; /* reporting source id */ + u32 reserved5; + u32 reserved6; + u32 ccdf[96]; /* content-code dependent field */ + /* ccdf has to be big enough for a link-incident record */ + } *sei_area; if (!sei_page) return 0; - /* Access to sei_page is serialized through machine check handler - * thread, so no need for locking. */ + /* + * build the chsc request block for store event information + * and do the call + * This function is only called by the machine check handler thread, + * so we don't need locking for the sei_page. + */ sei_area = sei_page; CIO_TRACE_EVENT( 2, "prcss"); ret = 0; do { + int ccode, status; + struct device *dev; memset(sei_area, 0, sizeof(*sei_area)); + memset(&res_data, 0, sizeof(struct res_acc_data)); sei_area->request.length = 0x0010; sei_area->request.code = 0x000e; - if (chsc(sei_area)) - break; - if (sei_area->response.code == 0x0001) { - CIO_CRW_EVENT(4, "chsc: sei successful\n"); - rc = chsc_process_sei(sei_area); - if (rc) - ret = rc; - } else { - CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", + ccode = chsc(sei_area); + if (ccode > 0) + return 0; + + switch (sei_area->response.code) { + /* for debug purposes, check for problems */ + case 0x0001: + CIO_CRW_EVENT(4, "chsc_process_crw: event information " + "successfully stored\n"); + break; /* everything ok */ + case 0x0002: + CIO_CRW_EVENT(2, + "chsc_process_crw: invalid command!\n"); + return 0; + case 0x0003: + CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc " + "request block!\n"); + return 0; + case 0x0005: + CIO_CRW_EVENT(2, "chsc_process_crw: no event " + "information stored\n"); + return 0; + default: + CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n", sei_area->response.code); - ret = 0; + return 0; + } + + /* Check if we might have lost some information. */ + if (sei_area->flags & 0x40) + CIO_CRW_EVENT(2, "chsc_process_crw: Event information " + "has been lost due to overflow!\n"); + + if (sei_area->rs != 4) { + CIO_CRW_EVENT(2, "chsc_process_crw: reporting source " + "(%04X) isn't a chpid!\n", + sei_area->rsid); + continue; + } + + /* which kind of information was stored? */ + switch (sei_area->cc) { + case 1: /* link incident*/ + CIO_CRW_EVENT(4, "chsc_process_crw: " + "channel subsystem reports link incident," + " reporting source is chpid %x\n", + sei_area->rsid); + chpid = __get_chpid_from_lir(sei_area->ccdf); + if (chpid < 0) + CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n", + __FUNCTION__); + else + s390_set_chpid_offline(chpid); + break; + + case 2: /* i/o resource accessibiliy */ + CIO_CRW_EVENT(4, "chsc_process_crw: " + "channel subsystem reports some I/O " + "devices may have become accessible\n"); + pr_debug("Data received after sei: \n"); + pr_debug("Validity flags: %x\n", sei_area->vf); + + /* allocate a new channel path structure, if needed */ + status = get_chp_status(sei_area->rsid); + if (status < 0) + new_channel_path(sei_area->rsid); + else if (!status) + break; + dev = get_device(&css[0]->chps[sei_area->rsid]->dev); + res_data.chp = to_channelpath(dev); + pr_debug("chpid: %x", sei_area->rsid); + if ((sei_area->vf & 0xc0) != 0) { + res_data.fla = sei_area->fla; + if ((sei_area->vf & 0xc0) == 0xc0) { + pr_debug(" full link addr: %x", + sei_area->fla); + res_data.fla_mask = 0xffff; + } else { + pr_debug(" link addr: %x", + sei_area->fla); + res_data.fla_mask = 0xff00; + } + } + ret = s390_process_res_acc(&res_data); + pr_debug("\n\n"); + put_device(dev); + break; + + default: /* other stuff */ + CIO_CRW_EVENT(4, "chsc_process_crw: event %d\n", + sei_area->cc); break; } } while (sei_area->flags & 0x80); - return ret; } -static int +static inline int __chp_add_new_sch(struct subchannel_id schid) { struct schib schib; int ret; - if (stsch_err(schid, &schib)) + if (stsch(schid, &schib)) /* We're through */ return need_rescan ? -EAGAIN : -ENXIO; @@ -701,7 +709,7 @@ chp_process_crw(int chpid, int on) return chp_add(chpid); } -static int check_for_io_on_path(struct subchannel *sch, int index) +static inline int check_for_io_on_path(struct subchannel *sch, int index) { int cc; @@ -733,7 +741,7 @@ static void terminate_internal_io(struct subchannel *sch) sch->driver->termination(&sch->dev); } -static void +static inline void __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) { int chp, old_lpm; @@ -959,8 +967,8 @@ static struct bin_attribute chp_measurement_attr = { static void chsc_remove_chp_cmg_attr(struct channel_path *chp) { - device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); - device_remove_bin_file(&chp->dev, &chp_measurement_attr); + sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_chars_attr); + sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_attr); } static int @@ -968,12 +976,14 @@ chsc_add_chp_cmg_attr(struct channel_path *chp) { int ret; - ret = device_create_bin_file(&chp->dev, &chp_measurement_chars_attr); + ret = sysfs_create_bin_file(&chp->dev.kobj, + &chp_measurement_chars_attr); if (ret) return ret; - ret = device_create_bin_file(&chp->dev, &chp_measurement_attr); + ret = sysfs_create_bin_file(&chp->dev.kobj, &chp_measurement_attr); if (ret) - device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); + sysfs_remove_bin_file(&chp->dev.kobj, + &chp_measurement_chars_attr); return ret; } @@ -1032,7 +1042,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) u32 : 4; u32 fmt : 4; u32 : 16; - } __attribute__ ((packed)) *secm_area; + } *secm_area; int ret, ccode; secm_area = page; @@ -1243,7 +1253,7 @@ chsc_determine_channel_path_description(int chpid, struct chsc_header response; u32 zeroes2; struct channel_path_desc desc; - } __attribute__ ((packed)) *scpd_area; + } *scpd_area; scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scpd_area) @@ -1340,7 +1350,7 @@ chsc_get_channel_measurement_chars(struct channel_path *chp) u32 cmg : 8; u32 zeroes3; u32 data[NR_MEASUREMENT_CHARS]; - } __attribute__ ((packed)) *scmc_area; + } *scmc_area; scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scmc_area) @@ -1507,7 +1517,7 @@ chsc_enable_facility(int operation_code) u32 reserved5:4; u32 format2:4; u32 reserved6:24; - } __attribute__ ((packed)) *sda_area; + } *sda_area; sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); if (!sda_area) @@ -1559,7 +1569,7 @@ chsc_determine_css_characteristics(void) u32 reserved4; u32 general_char[510]; u32 chsc_char[518]; - } __attribute__ ((packed)) *scsc_area; + } *scsc_area; scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scsc_area) { diff --git a/trunk/drivers/s390/cio/chsc.h b/trunk/drivers/s390/cio/chsc.h index 0fb2b024208f..a259245780ae 100644 --- a/trunk/drivers/s390/cio/chsc.h +++ b/trunk/drivers/s390/cio/chsc.h @@ -10,17 +10,17 @@ struct chsc_header { u16 length; u16 code; -} __attribute__ ((packed)); +}; #define NR_MEASUREMENT_CHARS 5 struct cmg_chars { u32 values[NR_MEASUREMENT_CHARS]; -} __attribute__ ((packed)); +}; #define NR_MEASUREMENT_ENTRIES 8 struct cmg_entry { u32 values[NR_MEASUREMENT_ENTRIES]; -} __attribute__ ((packed)); +}; struct channel_path_desc { u8 flags; @@ -31,7 +31,7 @@ struct channel_path_desc { u8 zeroes; u8 chla; u8 chpp; -} __attribute__ ((packed)); +}; struct channel_path { int id; @@ -47,9 +47,6 @@ struct channel_path { extern void s390_process_css( void ); extern void chsc_validate_chpids(struct subchannel *); extern void chpid_is_actually_online(int); -extern int css_get_ssd_info(struct subchannel *); -extern int chsc_process_crw(void); -extern int chp_process_crw(int, int); struct css_general_char { u64 : 41; diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index b3a56dc5f68a..ae1bf231d089 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -122,7 +122,7 @@ cio_get_options (struct subchannel *sch) * Use tpi to get a pending interrupt, call the interrupt handler and * return a pointer to the subchannel structure. */ -static int +static inline int cio_tpi(void) { struct tpi_info *tpi_info; @@ -152,7 +152,7 @@ cio_tpi(void) return 1; } -static int +static inline int cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) { char dbf_text[15]; @@ -585,7 +585,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) * This device must not be known to Linux. So we simply * say that there is no device and return ENODEV. */ - CIO_MSG_EVENT(4, "Blacklisted device detected " + CIO_MSG_EVENT(0, "Blacklisted device detected " "at devno %04X, subchannel set %x\n", sch->schib.pmcw.dev, sch->schid.ssid); err = -ENODEV; @@ -646,7 +646,7 @@ do_IRQ (struct pt_regs *regs) * Make sure that the i/o interrupt did not "overtake" * the last HZ timer interrupt. */ - account_ticks(S390_lowcore.int_clock); + account_ticks(); /* * Get interrupt information from lowcore */ @@ -832,7 +832,7 @@ cio_get_console_subchannel(void) } #endif -static int +static inline int __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) { int retry, cc; @@ -850,20 +850,7 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) return -EBUSY; /* uhm... */ } -/* we can't use the normal udelay here, since it enables external interrupts */ - -static void udelay_reset(unsigned long usecs) -{ - uint64_t start_cc, end_cc; - - asm volatile ("STCK %0" : "=m" (start_cc)); - do { - cpu_relax(); - asm volatile ("STCK %0" : "=m" (end_cc)); - } while (((end_cc - start_cc)/4096) < usecs); -} - -static int +static inline int __clear_subchannel_easy(struct subchannel_id schid) { int retry; @@ -878,7 +865,7 @@ __clear_subchannel_easy(struct subchannel_id schid) if (schid_equal(&ti.schid, &schid)) return 0; } - udelay_reset(100); + udelay(100); } return -EBUSY; } @@ -895,11 +882,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) int rc; pgm_check_occured = 0; - s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; + s390_reset_pgm_handler = cio_reset_pgm_check_handler; rc = stsch(schid, addr); - s390_base_pgm_handler_fn = NULL; + s390_reset_pgm_handler = NULL; - /* The program check handler could have changed pgm_check_occured. */ + /* The program check handler could have changed pgm_check_occured */ barrier(); if (pgm_check_occured) @@ -957,7 +944,7 @@ static void css_reset(void) /* Reset subchannels. */ for_each_subchannel(__shutdown_subchannel_easy, NULL); /* Reset channel paths. */ - s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; + s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; /* Enable channel report machine checks. */ __ctl_set_bit(14, 28); /* Temporarily reenable machine checks. */ @@ -982,7 +969,7 @@ static void css_reset(void) local_mcck_disable(); /* Disable channel report machine checks. */ __ctl_clear_bit(14, 28); - s390_base_mcck_handler_fn = NULL; + s390_reset_mcck_handler = NULL; } static struct reset_call css_reset_call = { diff --git a/trunk/drivers/s390/cio/cmf.c b/trunk/drivers/s390/cio/cmf.c index 90b22faabbf7..828b2d334f0a 100644 --- a/trunk/drivers/s390/cio/cmf.c +++ b/trunk/drivers/s390/cio/cmf.c @@ -519,8 +519,8 @@ struct cmb { /* insert a single device into the cmb_area list * called with cmb_area.lock held from alloc_cmb */ -static int alloc_cmb_single(struct ccw_device *cdev, - struct cmb_data *cmb_data) +static inline int alloc_cmb_single (struct ccw_device *cdev, + struct cmb_data *cmb_data) { struct cmb *cmb; struct ccw_device_private *node; diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index fe0ace7aece8..9d6c02446863 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -30,7 +30,7 @@ struct channel_subsystem *css[__MAX_CSSID + 1]; int css_characteristics_avail = 0; -int +inline int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) { struct subchannel_id schid; @@ -108,6 +108,9 @@ css_subchannel_release(struct device *dev) } } +extern int css_get_ssd_info(struct subchannel *sch); + + int css_sch_device_register(struct subchannel *sch) { int ret; @@ -184,7 +187,7 @@ get_subchannel_by_schid(struct subchannel_id schid) return dev ? to_subchannel(dev) : NULL; } -static int css_get_subchannel_status(struct subchannel *sch) +static inline int css_get_subchannel_status(struct subchannel *sch) { struct schib schib; @@ -296,7 +299,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) /* Will be done on the slow path. */ return -EAGAIN; } - if (stsch_err(schid, &schib) || !schib.pmcw.dnv) { + if (stsch(schid, &schib) || !schib.pmcw.dnv) { /* Unusable - ignore. */ return 0; } @@ -414,7 +417,7 @@ static void reprobe_all(struct work_struct *unused) need_reprobe); } -static DECLARE_WORK(css_reprobe_work, reprobe_all); +DECLARE_WORK(css_reprobe_work, reprobe_all); /* Schedule reprobing of all unregistered subchannels. */ void css_schedule_reprobe(void) @@ -575,7 +578,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); -static int __init setup_css(int nr) +static inline int __init setup_css(int nr) { u32 tod_high; int ret; diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index ca2bab932a8a..3464c5b875c4 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -143,8 +143,6 @@ extern void css_sch_device_unregister(struct subchannel *); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); extern int css_init_done; extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); -extern int css_process_crw(int, int); -extern void css_reiterate_subchannels(void); #define __MAX_SUBCHANNEL 65535 #define __MAX_SSID 3 diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index e322111fb369..803579053c2f 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -138,6 +138,7 @@ struct bus_type ccw_bus_type; static int io_subchannel_probe (struct subchannel *); static int io_subchannel_remove (struct subchannel *); +void io_subchannel_irq (struct device *); static int io_subchannel_notify(struct device *, int); static void io_subchannel_verify(struct device *); static void io_subchannel_ioterm(struct device *); @@ -234,8 +235,11 @@ chpids_show (struct device * dev, struct device_attribute *attr, char * buf) ssize_t ret = 0; int chp; - for (chp = 0; chp < 8; chp++) - ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]); + if (ssd) + for (chp = 0; chp < 8; chp++) + ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]); + else + ret += sprintf (buf, "n/a"); ret += sprintf (buf+ret, "\n"); return min((ssize_t)PAGE_SIZE, ret); } @@ -548,13 +552,13 @@ static struct attribute_group ccwdev_attr_group = { .attrs = ccwdev_attrs, }; -static int +static inline int device_add_files (struct device *dev) { return sysfs_create_group(&dev->kobj, &ccwdev_attr_group); } -static void +static inline void device_remove_files(struct device *dev) { sysfs_remove_group(&dev->kobj, &ccwdev_attr_group); diff --git a/trunk/drivers/s390/cio/device.h b/trunk/drivers/s390/cio/device.h index b66338b76579..29db6341d632 100644 --- a/trunk/drivers/s390/cio/device.h +++ b/trunk/drivers/s390/cio/device.h @@ -74,7 +74,6 @@ extern struct workqueue_struct *ccw_device_notify_work; extern wait_queue_head_t ccw_device_init_wq; extern atomic_t ccw_device_init_count; -void io_subchannel_irq (struct device *pdev); void io_subchannel_recog_done(struct ccw_device *cdev); int ccw_device_cancel_halt_clear(struct ccw_device *); @@ -119,7 +118,6 @@ int ccw_device_stlck(struct ccw_device *); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); -extern struct bus_type ccw_bus_type; /* Channel measurement facility related */ void retry_set_schib(struct ccw_device *cdev); diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index 51238e7555bb..eed14572fc3b 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -206,7 +206,7 @@ ccw_device_handle_oper(struct ccw_device *cdev) * been varied online on the SE so we have to find out by magic (i. e. driving * the channel subsystem to device selection and updating our path masks). */ -static void +static inline void __recover_lost_chpids(struct subchannel *sch, int old_lpm) { int mask, i; @@ -387,7 +387,7 @@ ccw_device_done(struct ccw_device *cdev, int state) put_device (&cdev->dev); } -static int cmp_pgid(struct pgid *p1, struct pgid *p2) +static inline int cmp_pgid(struct pgid *p1, struct pgid *p2) { char *c1; char *c2; @@ -842,8 +842,6 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) call_handler_unsol: if (cdev->handler) cdev->handler (cdev, 0, irb); - if (cdev->private->flags.doverify) - ccw_device_online_verify(cdev, 0); return; } /* Accumulate status and find out if a basic sense is needed. */ @@ -894,7 +892,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event) /* * Got an interrupt for a basic sense. */ -static void +void ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) { struct irb *irb; diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index d7b25b8f71d2..d269607336ec 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -302,7 +302,7 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) wake_up(&cdev->private->wait_q); } -static int +static inline int __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm) { int ret; diff --git a/trunk/drivers/s390/cio/device_status.c b/trunk/drivers/s390/cio/device_status.c index 6b1caea622ea..bdcf930f7beb 100644 --- a/trunk/drivers/s390/cio/device_status.c +++ b/trunk/drivers/s390/cio/device_status.c @@ -25,7 +25,7 @@ * Check for any kind of channel or interface control check but don't * issue the message for the console device */ -static void +static inline void ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) { if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK | @@ -72,7 +72,7 @@ ccw_device_path_notoper(struct ccw_device *cdev) /* * Copy valid bits from the extended control word to device irb. */ -static void +static inline void ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) { /* @@ -94,7 +94,7 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) /* * Check if extended status word is valid. */ -static int +static inline int ccw_device_accumulate_esw_valid(struct irb *irb) { if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) @@ -109,7 +109,7 @@ ccw_device_accumulate_esw_valid(struct irb *irb) /* * Copy valid bits from the extended status word to device irb. */ -static void +static inline void ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb) { struct irb *cdev_irb; diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index d726cd5777de..6fd1940842eb 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -66,6 +66,7 @@ MODULE_LICENSE("GPL"); /******************** HERE WE GO ***********************************/ static const char version[] = "QDIO base support version 2"; +extern struct bus_type ccw_bus_type; static int qdio_performance_stats = 0; static int proc_perf_file_registration; @@ -137,7 +138,7 @@ qdio_release_q(struct qdio_q *q) } /*check ccq */ -static int +static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) { char dbf_text[15]; @@ -152,7 +153,7 @@ qdio_check_ccq(struct qdio_q *q, unsigned int ccq) return -EIO; } /* EQBS: extract buffer states */ -static int +static inline int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, unsigned int *start, unsigned int *cnt) { @@ -187,7 +188,7 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, } /* SQBS: set buffer states */ -static int +static inline int qdio_do_sqbs(struct qdio_q *q, unsigned char state, unsigned int *start, unsigned int *cnt) { @@ -314,7 +315,7 @@ __do_siga_output(struct qdio_q *q, unsigned int *busy_bit) * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns * an access exception */ -static int +static inline int qdio_siga_output(struct qdio_q *q) { int cc; @@ -348,7 +349,7 @@ qdio_siga_output(struct qdio_q *q) return cc; } -static int +static inline int qdio_siga_input(struct qdio_q *q) { int cc; @@ -420,7 +421,7 @@ tiqdio_sched_tl(void) tasklet_hi_schedule(&tiqdio_tasklet); } -static void +static inline void qdio_mark_tiq(struct qdio_q *q) { unsigned long flags; @@ -470,7 +471,7 @@ qdio_mark_q(struct qdio_q *q) tasklet_schedule(&q->tasklet); } -static int +static inline int qdio_stop_polling(struct qdio_q *q) { #ifdef QDIO_USE_PROCESSING_STATE @@ -524,7 +525,7 @@ qdio_stop_polling(struct qdio_q *q) * sophisticated locking outside of unmark_q, so that we don't need to * disable the interrupts :-) */ -static void +static inline void qdio_unmark_q(struct qdio_q *q) { unsigned long flags; @@ -690,7 +691,7 @@ qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q) return q->first_to_check; } -static int +static inline int qdio_get_outbound_buffer_frontier(struct qdio_q *q) { struct qdio_irq *irq; @@ -773,7 +774,7 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) } /* all buffers are processed */ -static int +static inline int qdio_is_outbound_q_done(struct qdio_q *q) { int no_used; @@ -795,7 +796,7 @@ qdio_is_outbound_q_done(struct qdio_q *q) return (no_used==0); } -static int +static inline int qdio_has_outbound_q_moved(struct qdio_q *q) { int i; @@ -815,7 +816,7 @@ qdio_has_outbound_q_moved(struct qdio_q *q) } } -static void +static inline void qdio_kick_outbound_q(struct qdio_q *q) { int result; @@ -904,7 +905,7 @@ qdio_kick_outbound_q(struct qdio_q *q) } } -static void +static inline void qdio_kick_outbound_handler(struct qdio_q *q) { int start, end, real_end, count; @@ -941,7 +942,7 @@ qdio_kick_outbound_handler(struct qdio_q *q) q->error_status_flags=0; } -static void +static inline void __qdio_outbound_processing(struct qdio_q *q) { int siga_attempts; @@ -1001,7 +1002,7 @@ qdio_outbound_processing(struct qdio_q *q) /************************* INBOUND ROUTINES *******************************/ -static int +static inline int qdio_get_inbound_buffer_frontier(struct qdio_q *q) { struct qdio_irq *irq; @@ -1132,7 +1133,7 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) return q->first_to_check; } -static int +static inline int qdio_has_inbound_q_moved(struct qdio_q *q) { int i; @@ -1166,7 +1167,7 @@ qdio_has_inbound_q_moved(struct qdio_q *q) } /* means, no more buffers to be filled */ -static int +static inline int tiqdio_is_inbound_q_done(struct qdio_q *q) { int no_used; @@ -1227,7 +1228,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) return 0; } -static int +static inline int qdio_is_inbound_q_done(struct qdio_q *q) { int no_used; @@ -1295,7 +1296,7 @@ qdio_is_inbound_q_done(struct qdio_q *q) } } -static void +static inline void qdio_kick_inbound_handler(struct qdio_q *q) { int count, start, end, real_end, i; @@ -1342,7 +1343,7 @@ qdio_kick_inbound_handler(struct qdio_q *q) } } -static void +static inline void __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) { struct qdio_irq *irq_ptr; @@ -1441,7 +1442,7 @@ tiqdio_inbound_processing(struct qdio_q *q) __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); } -static void +static inline void __qdio_inbound_processing(struct qdio_q *q) { int q_laps=0; @@ -1492,7 +1493,7 @@ qdio_inbound_processing(struct qdio_q *q) /************************* MAIN ROUTINES *******************************/ #ifdef QDIO_USE_PROCESSING_STATE -static int +static inline int tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) { if (!q) { @@ -1544,7 +1545,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) } #endif /* QDIO_USE_PROCESSING_STATE */ -static void +static inline void tiqdio_inbound_checks(void) { struct qdio_q *q; @@ -1948,7 +1949,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state) mb(); } -static void +static inline void qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) { char dbf_text[15]; @@ -1965,7 +1966,7 @@ qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) } -static void +static inline void qdio_handle_pci(struct qdio_irq *irq_ptr) { int i; @@ -2001,7 +2002,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) static void qdio_establish_handle_irq(struct ccw_device*, int, int); -static void +static inline void qdio_handle_activate_check(struct ccw_device *cdev, unsigned long intparm, int cstat, int dstat) { @@ -2228,7 +2229,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, return cc; } -static void +static inline void qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, unsigned long token) { @@ -2739,7 +2740,7 @@ qdio_free(struct ccw_device *cdev) return 0; } -static void +static inline void qdio_allocate_do_dbf(struct qdio_initialize *init_data) { char dbf_text[20]; /* if a printf printed out more than 8 chars */ @@ -2772,7 +2773,7 @@ qdio_allocate_do_dbf(struct qdio_initialize *init_data) QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*)); } -static void +static inline void qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) { irq_ptr->input_qs[i]->is_iqdio_q = iqfmt; @@ -2791,7 +2792,7 @@ qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY; } -static void +static inline void qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i, int j, int iqfmt) { @@ -2812,7 +2813,7 @@ qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i, } -static void +static inline void qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr) { int i; @@ -2838,7 +2839,7 @@ qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr) } } -static void +static inline void qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr) { int i; @@ -2864,7 +2865,7 @@ qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr) } } -static int +static inline int qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, int dstat) { @@ -3013,7 +3014,7 @@ qdio_allocate(struct qdio_initialize *init_data) return 0; } -static int qdio_fill_irq(struct qdio_initialize *init_data) +int qdio_fill_irq(struct qdio_initialize *init_data) { int i; char dbf_text[15]; @@ -3366,7 +3367,7 @@ qdio_activate(struct ccw_device *cdev, int flags) } /* buffers filled forwards again to make Rick happy */ -static void +static inline void qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { @@ -3385,7 +3386,7 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, } } -static void +static inline void qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { @@ -3406,7 +3407,7 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, } } -static void +static inline void do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) @@ -3442,7 +3443,7 @@ do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, qdio_mark_q(q); } -static void +static inline void do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index c7d1355237b6..81b5899f4010 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -465,7 +465,7 @@ static int ap_device_probe(struct device *dev) * Flush all requests from the request/pending queue of an AP device. * @ap_dev: pointer to the AP device. */ -static void __ap_flush_queue(struct ap_device *ap_dev) +static inline void __ap_flush_queue(struct ap_device *ap_dev) { struct ap_message *ap_msg, *next; @@ -587,7 +587,7 @@ static struct bus_attribute *const ap_bus_attrs[] = { /** * Pick one of the 16 ap domains. */ -static int ap_select_domain(void) +static inline int ap_select_domain(void) { int queue_depth, device_type, count, max_count, best_domain; int rc, i, j; @@ -825,7 +825,7 @@ static inline void ap_schedule_poll_timer(void) * required, bit 2^1 is set if the poll timer needs to get armed * Returns 0 if the device is still present, -ENODEV if not. */ -static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) +static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) { struct ap_queue_status status; struct ap_message *ap_msg; @@ -872,7 +872,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) * required, bit 2^1 is set if the poll timer needs to get armed * Returns 0 if the device is still present, -ENODEV if not. */ -static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) +static inline int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) { struct ap_queue_status status; struct ap_message *ap_msg; diff --git a/trunk/drivers/s390/crypto/zcrypt_api.c b/trunk/drivers/s390/crypto/zcrypt_api.c index b9e59bc9435a..1edc10a7a6f2 100644 --- a/trunk/drivers/s390/crypto/zcrypt_api.c +++ b/trunk/drivers/s390/crypto/zcrypt_api.c @@ -791,7 +791,7 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd, return rc; } -static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, +long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if (cmd == ICARSAMODEXPO) @@ -833,8 +833,8 @@ static struct miscdevice zcrypt_misc_device = { */ static struct proc_dir_entry *zcrypt_entry; -static int sprintcl(unsigned char *outaddr, unsigned char *addr, - unsigned int len) +static inline int sprintcl(unsigned char *outaddr, unsigned char *addr, + unsigned int len) { int hl, i; @@ -845,8 +845,8 @@ static int sprintcl(unsigned char *outaddr, unsigned char *addr, return hl; } -static int sprintrw(unsigned char *outaddr, unsigned char *addr, - unsigned int len) +static inline int sprintrw(unsigned char *outaddr, unsigned char *addr, + unsigned int len) { int hl, inl, c, cx; @@ -865,8 +865,8 @@ static int sprintrw(unsigned char *outaddr, unsigned char *addr, return hl; } -static int sprinthx(unsigned char *title, unsigned char *outaddr, - unsigned char *addr, unsigned int len) +static inline int sprinthx(unsigned char *title, unsigned char *outaddr, + unsigned char *addr, unsigned int len) { int hl, inl, r, rx; @@ -885,8 +885,8 @@ static int sprinthx(unsigned char *title, unsigned char *outaddr, return hl; } -static int sprinthx4(unsigned char *title, unsigned char *outaddr, - unsigned int *array, unsigned int len) +static inline int sprinthx4(unsigned char *title, unsigned char *outaddr, + unsigned int *array, unsigned int len) { int hl, r; @@ -943,7 +943,7 @@ static int zcrypt_status_read(char *resp_buff, char **start, off_t offset, zcrypt_qdepth_mask(workarea); len += sprinthx("Waiting work element counts", resp_buff+len, workarea, AP_DEVICES); - zcrypt_perdev_reqcnt((int *) workarea); + zcrypt_perdev_reqcnt((unsigned int *) workarea); len += sprinthx4("Per-device successfully completed request counts", resp_buff+len,(unsigned int *) workarea, AP_DEVICES); *eof = 1; diff --git a/trunk/drivers/s390/crypto/zcrypt_pcica.c b/trunk/drivers/s390/crypto/zcrypt_pcica.c index 818ffe05ac00..32e37014345c 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcica.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcica.c @@ -191,10 +191,10 @@ static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev, * * Returns 0 on success or -EFAULT. */ -static int convert_type84(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) +static inline int convert_type84(struct zcrypt_device *zdev, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) { struct type84_hdr *t84h = reply->message; char *data; diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c index 252443b6bd1b..b7153c1e15cd 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c @@ -709,8 +709,7 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, * PCIXCC/CEX2C device to the request distributor * @xcRB: pointer to the send_cprb request buffer */ -static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, - struct ica_xcRB *xcRB) +long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB) { struct ap_message ap_msg; struct response_type resp_type = { diff --git a/trunk/drivers/s390/net/claw.c b/trunk/drivers/s390/net/claw.c index 7809a79feec7..95f4e105cb96 100644 --- a/trunk/drivers/s390/net/claw.c +++ b/trunk/drivers/s390/net/claw.c @@ -121,7 +121,7 @@ MODULE_LICENSE("GPL"); #define DEBUG #endif -static char debug_buffer[255]; + char debug_buffer[255]; /** * Debug Facility Stuff */ @@ -223,14 +223,16 @@ static void claw_timer ( struct chbk * p_ch ); /* Functions */ static int add_claw_reads(struct net_device *dev, struct ccwbk* p_first, struct ccwbk* p_last); -static void ccw_check_return_code (struct ccw_device *cdev, int return_code); -static void ccw_check_unit_check (struct chbk * p_ch, unsigned char sense ); +static void inline ccw_check_return_code (struct ccw_device *cdev, + int return_code); +static void inline ccw_check_unit_check (struct chbk * p_ch, + unsigned char sense ); static int find_link(struct net_device *dev, char *host_name, char *ws_name ); static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid); static int init_ccw_bk(struct net_device *dev); static void probe_error( struct ccwgroup_device *cgdev); static struct net_device_stats *claw_stats(struct net_device *dev); -static int pages_to_order_of_mag(int num_of_pages); +static int inline pages_to_order_of_mag(int num_of_pages); static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr); #ifdef DEBUG static void dumpit (char *buf, int len); @@ -1308,7 +1310,7 @@ claw_timer ( struct chbk * p_ch ) * of magnitude get_free_pages() has an upper order of 9 * *--------------------------------------------------------------------*/ -static int +static int inline pages_to_order_of_mag(int num_of_pages) { int order_of_mag=1; /* assume 2 pages */ @@ -1480,7 +1482,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, * * *-------------------------------------------------------------------*/ -static void +static void inline ccw_check_return_code(struct ccw_device *cdev, int return_code) { #ifdef FUNCTRACE @@ -1527,7 +1529,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code) * ccw_check_unit_check * *--------------------------------------------------------------------*/ -static void +static void inline ccw_check_unit_check(struct chbk * p_ch, unsigned char sense ) { struct net_device *dev = p_ch->ndev; diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index 5a84fbbc6611..03cc263fe0da 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -369,7 +369,7 @@ ctc_dump_skb(struct sk_buff *skb, int offset) * @param ch The channel where this skb has been received. * @param pskb The received skb. */ -static void +static __inline__ void ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) { struct net_device *dev = ch->netdev; @@ -512,7 +512,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) * @param ch The channel, the error belongs to. * @param return_code The error code to inspect. */ -static void +static void inline ccw_check_return_code(struct channel *ch, int return_code, char *msg) { DBF_TEXT(trace, 5, __FUNCTION__); @@ -547,7 +547,7 @@ ccw_check_return_code(struct channel *ch, int return_code, char *msg) * @param ch The channel, the sense code belongs to. * @param sense The sense code to inspect. */ -static void +static void inline ccw_unit_check(struct channel *ch, unsigned char sense) { DBF_TEXT(trace, 5, __FUNCTION__); @@ -603,7 +603,7 @@ ctc_purge_skb_queue(struct sk_buff_head *q) } } -static int +static __inline__ int ctc_checkalloc_buffer(struct channel *ch, int warn) { DBF_TEXT(trace, 5, __FUNCTION__); diff --git a/trunk/drivers/s390/net/cu3088.c b/trunk/drivers/s390/net/cu3088.c index 76728ae4b843..e965f03a7291 100644 --- a/trunk/drivers/s390/net/cu3088.c +++ b/trunk/drivers/s390/net/cu3088.c @@ -57,7 +57,7 @@ static struct ccw_device_id cu3088_ids[] = { static struct ccw_driver cu3088_driver; -static struct device *cu3088_root_dev; +struct device *cu3088_root_dev; static ssize_t group_write(struct device_driver *drv, const char *buf, size_t count) diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index b97dd15bdb9a..e5665b6743a1 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -828,7 +828,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) /** * Emit buffer of a lan comand. */ -static void +void lcs_lancmd_timeout(unsigned long data) { struct lcs_reply *reply, *list_reply, *r; @@ -1360,7 +1360,7 @@ lcs_get_problem(struct ccw_device *cdev, struct irb *irb) return 0; } -static void +void lcs_schedule_recovery(struct lcs_card *card) { LCS_DBF_TEXT(2, trace, "startrec"); @@ -1990,7 +1990,7 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char } -static DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store); +DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store); static ssize_t lcs_dev_recover_store(struct device *dev, struct device_attribute *attr, diff --git a/trunk/drivers/s390/net/netiucv.c b/trunk/drivers/s390/net/netiucv.c index 3346088f47e0..d7d1cc0a5c8e 100644 --- a/trunk/drivers/s390/net/netiucv.c +++ b/trunk/drivers/s390/net/netiucv.c @@ -2053,7 +2053,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) return ret; } -static DRIVER_ATTR(connection, 0200, NULL, conn_write); +DRIVER_ATTR(connection, 0200, NULL, conn_write); static ssize_t remove_write (struct device_driver *drv, const char *buf, size_t count) @@ -2112,7 +2112,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) return -EINVAL; } -static DRIVER_ATTR(remove, 0200, NULL, remove_write); +DRIVER_ATTR(remove, 0200, NULL, remove_write); static void netiucv_banner(void) diff --git a/trunk/drivers/s390/net/qeth_eddp.c b/trunk/drivers/s390/net/qeth_eddp.c index 7c735e1fe063..6bb558a9a032 100644 --- a/trunk/drivers/s390/net/qeth_eddp.c +++ b/trunk/drivers/s390/net/qeth_eddp.c @@ -49,7 +49,7 @@ qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue, return buffers_needed; } -static void +static inline void qeth_eddp_free_context(struct qeth_eddp_context *ctx) { int i; @@ -91,7 +91,7 @@ qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) } } -static int +static inline int qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf, struct qeth_eddp_context *ctx) { @@ -196,7 +196,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, return flush_cnt; } -static void +static inline void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, struct qeth_eddp_data *eddp, int data_len) { @@ -256,7 +256,7 @@ qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, ctx->offset += eddp->thl; } -static void +static inline void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, __wsum *hcsum) { @@ -302,7 +302,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, } } -static void +static inline void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, struct qeth_eddp_data *eddp, int data_len, __wsum hcsum) @@ -349,7 +349,7 @@ qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum); } -static __wsum +static inline __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) { __wsum phcsum; /* pseudo header checksum */ @@ -363,7 +363,7 @@ qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum); } -static __wsum +static inline __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) { __be32 proto; @@ -381,7 +381,7 @@ qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) return phcsum; } -static struct qeth_eddp_data * +static inline struct qeth_eddp_data * qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) { struct qeth_eddp_data *eddp; @@ -399,7 +399,7 @@ qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) return eddp; } -static void +static inline void __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct qeth_eddp_data *eddp) { @@ -464,7 +464,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, } } -static int +static inline int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct sk_buff *skb, struct qeth_hdr *qhdr) { @@ -505,7 +505,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, return 0; } -static void +static inline void qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, int hdr_len) { @@ -529,7 +529,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, (skb_shinfo(skb)->gso_segs + 1); } -static struct qeth_eddp_context * +static inline struct qeth_eddp_context * qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, int hdr_len) { @@ -581,7 +581,7 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, return ctx; } -static struct qeth_eddp_context * +static inline struct qeth_eddp_context * qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *qhdr) { @@ -625,3 +625,5 @@ qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb, } return NULL; } + + diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 2257e45594b3..d2efa5ff125d 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -651,7 +651,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, return 0; } -static int +static inline int __qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr, int same_type) { @@ -795,7 +795,7 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) return rc; } -static void +static inline void __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) { struct qeth_ipaddr *addr, *tmp; @@ -882,7 +882,7 @@ static void qeth_layer2_add_multicast(struct qeth_card *); static void qeth_add_multicast_ipv6(struct qeth_card *); #endif -static int +static inline int qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread) { unsigned long flags; @@ -920,7 +920,7 @@ qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread) wake_up(&card->wait_q); } -static int +static inline int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread) { unsigned long flags; @@ -1764,9 +1764,9 @@ qeth_send_control_data_cb(struct qeth_channel *channel, qeth_release_buffer(channel,iob); } -static void +static inline void qeth_prepare_control_data(struct qeth_card *card, int len, - struct qeth_cmd_buffer *iob) +struct qeth_cmd_buffer *iob) { qeth_setup_ccw(&card->write,iob->data,len); iob->callback = qeth_release_buffer; @@ -2160,7 +2160,7 @@ qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, return 0; } -static struct sk_buff * +static inline struct sk_buff * qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) { struct sk_buff* skb; @@ -2179,7 +2179,7 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) return skb; } -static struct sk_buff * +static inline struct sk_buff * qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, struct qdio_buffer_element **__element, int *__offset, struct qeth_hdr **hdr) @@ -2264,7 +2264,7 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, return NULL; } -static __be16 +static inline __be16 qeth_type_trans(struct sk_buff *skb, struct net_device *dev) { struct qeth_card *card; @@ -2297,7 +2297,7 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_802_2); } -static void +static inline void qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { @@ -2351,7 +2351,7 @@ qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, fake_llc->ethertype = ETH_P_IP; } -static void +static inline void qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { @@ -2420,7 +2420,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; } -static __u16 +static inline __u16 qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { @@ -2476,7 +2476,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, return vlan_id; } -static void +static inline void qeth_process_inbound_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf, int index) { @@ -2528,7 +2528,7 @@ qeth_process_inbound_buffer(struct qeth_card *card, } } -static struct qeth_buffer_pool_entry * +static inline struct qeth_buffer_pool_entry * qeth_get_buffer_pool_entry(struct qeth_card *card) { struct qeth_buffer_pool_entry *entry; @@ -2543,7 +2543,7 @@ qeth_get_buffer_pool_entry(struct qeth_card *card) return NULL; } -static void +static inline void qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) { struct qeth_buffer_pool_entry *pool_entry; @@ -2570,7 +2570,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) buf->state = QETH_QDIO_BUF_EMPTY; } -static void +static inline void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf) { @@ -2595,7 +2595,7 @@ qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } -static void +static inline void qeth_queue_input_buffer(struct qeth_card *card, int index) { struct qeth_qdio_q *queue = card->qdio.in_q; @@ -2699,7 +2699,7 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, card->perf_stats.inbound_start_time; } -static int +static inline int qeth_handle_send_error(struct qeth_card *card, struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err, unsigned int siga_err) @@ -2821,7 +2821,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, * Switched to packing state if the number of used buffers on a queue * reaches a certain limit. */ -static void +static inline void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) { if (!queue->do_pack) { @@ -2842,7 +2842,7 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) * In that case 1 is returned to inform the caller. If no buffer * has to be flushed, zero is returned. */ -static int +static inline int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) { struct qeth_qdio_out_buffer *buffer; @@ -2877,7 +2877,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) * Checks if there is a packing buffer and prepares it to be flushed. * In that case returns 1, otherwise zero. */ -static int +static inline int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) { struct qeth_qdio_out_buffer *buffer; @@ -2894,7 +2894,7 @@ qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) return 0; } -static void +static inline void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) { int index; @@ -3594,7 +3594,7 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev, } } -static int +static inline int qeth_send_packet(struct qeth_card *, struct sk_buff *); static int @@ -3759,7 +3759,7 @@ qeth_stop(struct net_device *dev) return 0; } -static int +static inline int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) { int cast_type = RTN_UNSPEC; @@ -3806,7 +3806,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) return cast_type; } -static int +static inline int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, int ipv, int cast_type) { @@ -3853,7 +3853,7 @@ qeth_get_ip_version(struct sk_buff *skb) } } -static struct qeth_hdr * +static inline struct qeth_hdr * __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) { #ifdef CONFIG_QETH_VLAN @@ -3882,14 +3882,14 @@ __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); } -static void +static inline void __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) { if (orig_skb != new_skb) dev_kfree_skb_any(new_skb); } -static struct sk_buff * +static inline struct sk_buff * qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr **hdr, int ipv) { @@ -3940,7 +3940,7 @@ qeth_get_qeth_hdr_flags6(int cast_type) return ct | QETH_CAST_UNICAST; } -static void +static inline void qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb) { @@ -3977,7 +3977,7 @@ qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, } } -static void +static inline void qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int cast_type) { @@ -4068,7 +4068,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } } -static void +static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill) { @@ -4112,7 +4112,7 @@ __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, *next_element_to_fill = element; } -static int +static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf, struct sk_buff *skb) @@ -4171,7 +4171,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, return flush_cnt; } -static int +static inline int qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, int elements_needed, @@ -4222,7 +4222,7 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, return -EBUSY; } -static int +static inline int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, int elements_needed, struct qeth_eddp_context *ctx) @@ -4328,7 +4328,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, return rc; } -static int +static inline int qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb, int elems) { @@ -4349,7 +4349,7 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, } -static int +static inline int qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) { int ipv = 0; @@ -4536,7 +4536,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) } -static const char * +static inline const char * qeth_arp_get_error_cause(int *rc) { switch (*rc) { @@ -4597,7 +4597,7 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) return rc; } -static void +static inline void qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo, struct qeth_arp_query_data *qdata, int entry_size, int uentry_size) @@ -5214,7 +5214,7 @@ qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) spin_unlock_irqrestore(&card->vlanlock, flags); } -static void +static inline void qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf, unsigned short vid) { @@ -5625,7 +5625,7 @@ qeth_delete_mc_addresses(struct qeth_card *card) spin_unlock_irqrestore(&card->ip_lock, flags); } -static void +static inline void qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev) { struct qeth_ipaddr *ipm; @@ -5711,7 +5711,7 @@ qeth_layer2_add_multicast(struct qeth_card *card) } #ifdef CONFIG_QETH_IPV6 -static void +static inline void qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) { struct qeth_ipaddr *ipm; @@ -6022,7 +6022,7 @@ qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd) return rc; } -static void +static inline void qeth_fill_netmask(u8 *netmask, unsigned int len) { int i,j; @@ -6626,7 +6626,7 @@ qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode) return rc; } -static int +static inline int qeth_setadapter_hstr(struct qeth_card *card) { int rc; @@ -6889,7 +6889,7 @@ qeth_send_simple_setassparms(struct qeth_card *card, return rc; } -static int +static inline int qeth_start_ipa_arp_processing(struct qeth_card *card) { int rc; @@ -7529,7 +7529,7 @@ qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads, wake_up(&card->wait_q); } -static int +static inline int qeth_threads_running(struct qeth_card *card, unsigned long threads) { unsigned long flags; @@ -8118,7 +8118,7 @@ qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto, spin_unlock_irqrestore(&card->ip_lock, flags); } -static void +static inline void qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len) { int i, j; diff --git a/trunk/drivers/s390/net/qeth_sys.c b/trunk/drivers/s390/net/qeth_sys.c index d518419cd0c6..5836737ac58f 100644 --- a/trunk/drivers/s390/net/qeth_sys.c +++ b/trunk/drivers/s390/net/qeth_sys.c @@ -328,7 +328,7 @@ qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const c static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show, qeth_dev_bufcnt_store); -static ssize_t +static inline ssize_t qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, char *buf) { @@ -368,7 +368,7 @@ qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *bu return qeth_dev_route_show(card, &card->options.route4, buf); } -static ssize_t +static inline ssize_t qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route, enum qeth_prot_versions prot, const char *buf, size_t count) { @@ -998,7 +998,7 @@ struct device_attribute dev_attr_##_id = { \ .store = _store, \ }; -static int +int qeth_check_layer2(struct qeth_card *card) { if (card->options.layer2) @@ -1100,7 +1100,7 @@ static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644, qeth_dev_ipato_invert4_show, qeth_dev_ipato_invert4_store); -static ssize_t +static inline ssize_t qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1146,7 +1146,7 @@ qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4); } -static int +static inline int qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, u8 *addr, int *mask_bits) { @@ -1178,7 +1178,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, return 0; } -static ssize_t +static inline ssize_t qeth_dev_ipato_add_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1223,7 +1223,7 @@ static QETH_DEVICE_ATTR(ipato_add4, add4, 0644, qeth_dev_ipato_add4_show, qeth_dev_ipato_add4_store); -static ssize_t +static inline ssize_t qeth_dev_ipato_del_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1361,7 +1361,7 @@ static struct attribute_group qeth_device_ipato_group = { .attrs = (struct attribute **)qeth_ipato_device_attrs, }; -static ssize_t +static inline ssize_t qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1407,7 +1407,7 @@ qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4); } -static int +static inline int qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, u8 *addr) { @@ -1418,7 +1418,7 @@ qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, return 0; } -static ssize_t +static inline ssize_t qeth_dev_vipa_add_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1451,7 +1451,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644, qeth_dev_vipa_add4_show, qeth_dev_vipa_add4_store); -static ssize_t +static inline ssize_t qeth_dev_vipa_del_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1542,7 +1542,7 @@ static struct attribute_group qeth_device_vipa_group = { .attrs = (struct attribute **)qeth_vipa_device_attrs, }; -static ssize_t +static inline ssize_t qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1588,7 +1588,7 @@ qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4); } -static int +static inline int qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, u8 *addr) { @@ -1599,7 +1599,7 @@ qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, return 0; } -static ssize_t +static inline ssize_t qeth_dev_rxip_add_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { @@ -1632,7 +1632,7 @@ static QETH_DEVICE_ATTR(rxip_add4, add4, 0644, qeth_dev_rxip_add4_show, qeth_dev_rxip_add4_store); -static ssize_t +static inline ssize_t qeth_dev_rxip_del_store(const char *buf, size_t count, struct qeth_card *card, enum qeth_prot_versions proto) { diff --git a/trunk/drivers/s390/s390mach.c b/trunk/drivers/s390/s390mach.c index 806bb1a921eb..e088b5e28711 100644 --- a/trunk/drivers/s390/s390mach.c +++ b/trunk/drivers/s390/s390mach.c @@ -13,18 +13,22 @@ #include #include #include -#include #include -#include + #include -#include -#include "cio/cio.h" -#include "cio/chsc.h" -#include "cio/css.h" + #include "s390mach.h" static struct semaphore m_sem; +extern int css_process_crw(int, int); +extern int chsc_process_crw(void); +extern int chp_process_crw(int, int); +extern void css_reiterate_subchannels(void); + +extern struct workqueue_struct *slow_path_wq; +extern struct work_struct slow_path_work; + static NORET_TYPE void s390_handle_damage(char *msg) { @@ -466,19 +470,6 @@ s390_do_machine_check(struct pt_regs *regs) s390_handle_damage("unable to revalidate registers."); } - if (mci->cd) { - /* Timing facility damage */ - s390_handle_damage("TOD clock damaged"); - } - - if (mci->ed && mci->ec) { - /* External damage */ - if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) - etr_sync_check(); - if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH)) - etr_switch_to_local(); - } - if (mci->se) /* Storage error uncorrected */ s390_handle_damage("received storage error uncorrected " @@ -517,7 +508,7 @@ static int machine_check_init(void) { init_MUTEX_LOCKED(&m_sem); - ctl_set_bit(14, 25); /* enable external damage MCH */ + ctl_clear_bit(14, 25); /* disable external damage MCH */ ctl_set_bit(14, 27); /* enable system recovery MCH */ #ifdef CONFIG_MACHCHK_WARNING ctl_set_bit(14, 24); /* enable warning MCH */ @@ -538,11 +529,7 @@ arch_initcall(machine_check_init); static int __init machine_check_crw_init (void) { - struct task_struct *task; - - task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); - if (IS_ERR(task)) - return PTR_ERR(task); + kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); ctl_set_bit(14, 28); /* enable channel report MCH */ return 0; } diff --git a/trunk/drivers/s390/s390mach.h b/trunk/drivers/s390/s390mach.h index d3ca4281a494..7abb42a09ae2 100644 --- a/trunk/drivers/s390/s390mach.h +++ b/trunk/drivers/s390/s390mach.h @@ -102,7 +102,4 @@ static inline int stcrw(struct crw *pcrw ) return ccode; } -#define ED_ETR_SYNC 12 /* External damage ETR sync check */ -#define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ - #endif /* __s390mach */ diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index 39a885266790..85093b71f9fa 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/drivers/s390/scsi/zfcp_aux.c @@ -47,12 +47,13 @@ static int __init zfcp_module_init(void); static void zfcp_ns_gid_pn_handler(unsigned long); /* miscellaneous */ -static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); -static void zfcp_sg_list_free(struct zfcp_sg_list *); -static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, - void __user *, size_t); -static int zfcp_sg_list_copy_to_user(void __user *, - struct zfcp_sg_list *, size_t); +static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); +static inline void zfcp_sg_list_free(struct zfcp_sg_list *); +static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, + void __user *, size_t); +static inline int zfcp_sg_list_copy_to_user(void __user *, + struct zfcp_sg_list *, size_t); + static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long); #define ZFCP_CFDC_IOC_MAGIC 0xDD @@ -604,7 +605,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, * elements of the scatter-gather list. The maximum size of a single element * in the scatter-gather list is PAGE_SIZE. */ -static int +static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) { struct scatterlist *sg; @@ -651,7 +652,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) * Memory for each element in the scatter-gather list is freed. * Finally sg_list->sg is freed itself and sg_list->count is reset. */ -static void +static inline void zfcp_sg_list_free(struct zfcp_sg_list *sg_list) { struct scatterlist *sg; @@ -696,7 +697,7 @@ zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) * @size: number of bytes to be copied * Return: 0 on success, -EFAULT if copy_from_user fails. */ -static int +static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void __user *user_buffer, size_t size) @@ -734,7 +735,7 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, * @size: number of bytes to be copied * Return: 0 on success, -EFAULT if copy_to_user fails */ -static int +static inline int zfcp_sg_list_copy_to_user(void __user *user_buffer, struct zfcp_sg_list *sg_list, size_t size) @@ -1798,7 +1799,7 @@ static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { * @code: reason code * @rc_table: table of reason codes and descriptions */ -static const char * +static inline const char * zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) { const char *descr = "unknown reason code"; @@ -1846,7 +1847,7 @@ zfcp_check_ct_response(struct ct_hdr *rjt) * @rjt_par: reject parameter acc. to FC-PH/FC-FS * @rc_table: table of reason codes and descriptions */ -static void +static inline void zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, const struct zfcp_rc_entry *rc_table) { diff --git a/trunk/drivers/s390/scsi/zfcp_dbf.c b/trunk/drivers/s390/scsi/zfcp_dbf.c index d8191d115c14..0aa3b1ac76af 100644 --- a/trunk/drivers/s390/scsi/zfcp_dbf.c +++ b/trunk/drivers/s390/scsi/zfcp_dbf.c @@ -31,7 +31,7 @@ MODULE_PARM_DESC(dbfsize, #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER -static int +static inline int zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) { unsigned long long sec; @@ -106,7 +106,7 @@ zfcp_dbf_view_dump(char *out_buf, const char *label, return len; } -static int +static inline int zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, debug_entry_t * entry, char *out_buf) { @@ -130,7 +130,7 @@ zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, return len; } -void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) +inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) { struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_qtcb *qtcb = fsf_req->qtcb; @@ -241,7 +241,7 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); } -void +inline void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { @@ -295,7 +295,7 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); } -void +inline void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, unsigned int qdio_error, unsigned int siga_error, int sbal_index, int sbal_count) @@ -316,7 +316,7 @@ zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); } -static int +static inline int zfcp_hba_dbf_view_response(char *out_buf, struct zfcp_hba_dbf_record_response *rec) { @@ -403,7 +403,7 @@ zfcp_hba_dbf_view_response(char *out_buf, return len; } -static int +static inline int zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) { int len = 0; @@ -424,7 +424,7 @@ zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) return len; } -static int +static inline int zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec) { int len = 0; @@ -469,7 +469,7 @@ zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view, return len; } -static struct debug_view zfcp_hba_dbf_view = { +struct debug_view zfcp_hba_dbf_view = { "structured", NULL, &zfcp_dbf_view_header, @@ -478,7 +478,7 @@ static struct debug_view zfcp_hba_dbf_view = { NULL }; -void +inline void _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id, void *buffer, int buflen) { @@ -519,7 +519,7 @@ _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); } -void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) +inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; struct zfcp_port *port = ct->port; @@ -531,7 +531,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) ct->req->length); } -void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) +inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; struct zfcp_port *port = ct->port; @@ -543,7 +543,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) ct->resp->length); } -static void +static inline void _zfcp_san_dbf_event_common_els(const char *tag, int level, struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id, u8 ls_code, void *buffer, int buflen) @@ -585,7 +585,7 @@ _zfcp_san_dbf_event_common_els(const char *tag, int level, spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); } -void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) +inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; @@ -597,7 +597,7 @@ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) els->req->length); } -void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) +inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; @@ -608,7 +608,7 @@ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) els->resp->length); } -void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) +inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) { struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_status_read_buffer *status_buffer = @@ -693,7 +693,7 @@ zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view, return len; } -static struct debug_view zfcp_san_dbf_view = { +struct debug_view zfcp_san_dbf_view = { "structured", NULL, &zfcp_dbf_view_header, @@ -702,7 +702,7 @@ static struct debug_view zfcp_san_dbf_view = { NULL }; -static void +static inline void _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, @@ -786,7 +786,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags); } -void +inline void zfcp_scsi_dbf_event_result(const char *tag, int level, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, @@ -796,7 +796,7 @@ zfcp_scsi_dbf_event_result(const char *tag, int level, adapter, scsi_cmnd, fsf_req, 0); } -void +inline void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, struct zfcp_fsf_req *new_fsf_req, @@ -806,7 +806,7 @@ zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, adapter, scsi_cmnd, new_fsf_req, old_req_id); } -void +inline void zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, struct scsi_cmnd *scsi_cmnd) { @@ -884,7 +884,7 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, return len; } -static struct debug_view zfcp_scsi_dbf_view = { +struct debug_view zfcp_scsi_dbf_view = { "structured", NULL, &zfcp_dbf_view_header, diff --git a/trunk/drivers/s390/scsi/zfcp_erp.c b/trunk/drivers/s390/scsi/zfcp_erp.c index 88642dec080c..c88babce9bca 100644 --- a/trunk/drivers/s390/scsi/zfcp_erp.c +++ b/trunk/drivers/s390/scsi/zfcp_erp.c @@ -200,7 +200,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) * returns: 0 - initiated action successfully * <0 - failed to initiate action */ -static int +int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask) { int retval; @@ -295,7 +295,7 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) * zfcp_erp_adisc - send ADISC ELS command * @port: port structure */ -static int +int zfcp_erp_adisc(struct zfcp_port *port) { struct zfcp_adapter *adapter = port->adapter; @@ -380,7 +380,7 @@ zfcp_erp_adisc(struct zfcp_port *port) * * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. */ -static void +void zfcp_erp_adisc_handler(unsigned long data) { struct zfcp_send_els *send_els; @@ -3141,6 +3141,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result != ZFCP_ERP_SUCCEEDED) { + struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) if (port->rport && !atomic_test_mask(ZFCP_STATUS_PORT_WKA, diff --git a/trunk/drivers/s390/scsi/zfcp_ext.h b/trunk/drivers/s390/scsi/zfcp_ext.h index cda0cc095ad1..b8794d77285d 100644 --- a/trunk/drivers/s390/scsi/zfcp_ext.h +++ b/trunk/drivers/s390/scsi/zfcp_ext.h @@ -119,8 +119,8 @@ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *); -extern void set_host_byte(int *, char); -extern void set_driver_byte(int *, char); +extern void set_host_byte(u32 *, char); +extern void set_driver_byte(u32 *, char); extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *); diff --git a/trunk/drivers/s390/scsi/zfcp_fsf.c b/trunk/drivers/s390/scsi/zfcp_fsf.c index 4b3ae3f22e78..067f1519eb04 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.c +++ b/trunk/drivers/s390/scsi/zfcp_fsf.c @@ -4563,7 +4563,7 @@ zfcp_fsf_req_sbal_check(unsigned long *flags, /* * set qtcb pointer in fsf_req and initialize QTCB */ -static void +static inline void zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) { if (likely(fsf_req->qtcb != NULL)) { diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index 1e12a78e8edd..dbd9f48e863e 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -21,22 +21,22 @@ #include "zfcp_ext.h" -static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); +static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get (struct zfcp_qdio_queue *, int, int); static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp (struct zfcp_fsf_req *, int, int); -static volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain (struct zfcp_fsf_req *, unsigned long); -static volatile struct qdio_buffer_element *zfcp_qdio_sbale_next +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next (struct zfcp_fsf_req *, unsigned long); -static int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int); +static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int); static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *); -static void zfcp_qdio_sbale_fill +static inline void zfcp_qdio_sbale_fill (struct zfcp_fsf_req *, unsigned long, void *, int); -static int zfcp_qdio_sbals_from_segment +static inline int zfcp_qdio_sbals_from_segment (struct zfcp_fsf_req *, unsigned long, void *, unsigned long); -static int zfcp_qdio_sbals_from_buffer +static inline int zfcp_qdio_sbals_from_buffer (struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int); static qdio_handler_t zfcp_qdio_request_handler; @@ -201,7 +201,7 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter) * returns: error flag * */ -static int +static inline int zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, unsigned int qdio_error, unsigned int siga_error, int first_element, int elements_processed) @@ -462,7 +462,7 @@ zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale) * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for * a struct zfcp_fsf_req */ -volatile struct qdio_buffer_element * +inline volatile struct qdio_buffer_element * zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) { return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue, @@ -484,7 +484,7 @@ zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) * zfcp_qdio_sbale_curr - return current SBALE on request_queue for * a struct zfcp_fsf_req */ -volatile struct qdio_buffer_element * +inline volatile struct qdio_buffer_element * zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) { return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, @@ -499,7 +499,7 @@ zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) * * Note: We can assume at least one free SBAL in the request_queue when called. */ -static void +static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) { int count = atomic_read(&fsf_req->adapter->request_queue.free_count); @@ -517,7 +517,7 @@ zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) * * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req. */ -static volatile struct qdio_buffer_element * +static inline volatile struct qdio_buffer_element * zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) { volatile struct qdio_buffer_element *sbale; @@ -554,7 +554,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) /** * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed */ -static volatile struct qdio_buffer_element * +static inline volatile struct qdio_buffer_element * zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) { if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) @@ -569,7 +569,7 @@ zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue * with zero from */ -static int +static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last) { struct qdio_buffer **buf = queue->buffer; @@ -603,7 +603,7 @@ zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req) * zfcp_qdio_sbale_fill - set address and lenght in current SBALE * on request_queue */ -static void +static inline void zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, void *addr, int length) { @@ -624,7 +624,7 @@ zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, * Alignment and length of the segment determine how many SBALEs are needed * for the memory segment. */ -static int +static inline int zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, void *start_addr, unsigned long total_length) { @@ -659,7 +659,7 @@ zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, * @sg_count: number of elements in scatter-gather list * @max_sbals: upper bound for number of SBALs to be used */ -int +inline int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, struct scatterlist *sg, int sg_count, int max_sbals) { @@ -707,7 +707,7 @@ zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, * @length: length of buffer * @max_sbals: upper bound for number of SBALs to be used */ -static int +static inline int zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, void *buffer, unsigned long length, int max_sbals) { @@ -728,7 +728,7 @@ zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, * @scsi_cmnd: either scatter-gather list or buffer contained herein is used * to fill SBALs */ -int +inline int zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, struct scsi_cmnd *scsi_cmnd) { diff --git a/trunk/drivers/s390/scsi/zfcp_scsi.c b/trunk/drivers/s390/scsi/zfcp_scsi.c index 99db02062c3b..452d96f92a14 100644 --- a/trunk/drivers/s390/scsi/zfcp_scsi.c +++ b/trunk/drivers/s390/scsi/zfcp_scsi.c @@ -90,7 +90,7 @@ zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) return fcp_sns_info_ptr; } -static fcp_dl_t * +fcp_dl_t * zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd) { int additional_length = fcp_cmd->add_fcp_cdb_length << 2; @@ -124,19 +124,19 @@ zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl) * regarding the specified byte */ static inline void -set_byte(int *result, char status, char pos) +set_byte(u32 * result, char status, char pos) { *result |= status << (pos * 8); } void -set_host_byte(int *result, char status) +set_host_byte(u32 * result, char status) { set_byte(result, status, 2); } void -set_driver_byte(int *result, char status) +set_driver_byte(u32 * result, char status) { set_byte(result, status, 3); } @@ -280,7 +280,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, return retval; } -static void +void zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) { struct completion *wait = (struct completion *) scpnt->SCp.ptr; @@ -324,7 +324,7 @@ zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, * returns: 0 - success, SCSI command enqueued * !0 - failure */ -static int +int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, void (*done) (struct scsi_cmnd *)) { @@ -380,7 +380,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, * will handle late commands. (Usually, the normal completion of late * commands is ignored with respect to the running abort operation.) */ -static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) +int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) { struct Scsi_Host *scsi_host; struct zfcp_adapter *adapter; @@ -445,7 +445,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) return retval; } -static int +int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { int retval; @@ -541,7 +541,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, /** * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset */ -static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) +int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { struct zfcp_unit *unit; struct zfcp_adapter *adapter; diff --git a/trunk/drivers/s390/sysinfo.c b/trunk/drivers/s390/sysinfo.c index 090743d2f914..1e788e815ce7 100644 --- a/trunk/drivers/s390/sysinfo.c +++ b/trunk/drivers/s390/sysinfo.c @@ -9,14 +9,8 @@ #include #include #include -#include #include -/* Sigh, math-emu. Don't ask. */ -#include -#include -#include - struct sysinfo_1_1_1 { char reserved_0[32]; char manufacturer[16]; @@ -204,7 +198,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) * if the higher order 8 bits are not zero. Printing * a floating point number in the kernel is a no-no, * always print the number as 32 bit unsigned integer. - * The user-space needs to know about the strange + * The user-space needs to know about the stange * encoding of the alternate cpu capability. */ len += sprintf(page + len, "Capability: %u %u\n", @@ -357,58 +351,3 @@ static __init int create_proc_sysinfo(void) __initcall(create_proc_sysinfo); -/* - * CPU capability might have changed. Therefore recalculate loops_per_jiffy. - */ -void s390_adjust_jiffies(void) -{ - struct sysinfo_1_2_2 *info; - const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */ - FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); - FP_DECL_EX; - unsigned int capability; - - info = (void *) get_zeroed_page(GFP_KERNEL); - if (!info) - return; - - if (stsi(info, 1, 2, 2) != -ENOSYS) { - /* - * Major sigh. The cpu capability encoding is "special". - * If the first 9 bits of info->capability are 0 then it - * is a 32 bit unsigned integer in the range 0 .. 2^23. - * If the first 9 bits are != 0 then it is a 32 bit float. - * In addition a lower value indicates a proportionally - * higher cpu capacity. Bogomips are the other way round. - * To get to a halfway suitable number we divide 1e7 - * by the cpu capability number. Yes, that means a floating - * point division .. math-emu here we come :-) - */ - FP_UNPACK_SP(SA, &fmil); - if ((info->capability >> 23) == 0) - FP_FROM_INT_S(SB, info->capability, 32, int); - else - FP_UNPACK_SP(SB, &info->capability); - FP_DIV_S(SR, SA, SB); - FP_TO_INT_S(capability, SR, 32, 0); - } else - /* - * Really old machine without stsi block for basic - * cpu information. Report 42.0 bogomips. - */ - capability = 42; - loops_per_jiffy = capability * (500000/HZ); - free_page((unsigned long) info); -} - -/* - * calibrate the delay loop - */ -void __init calibrate_delay(void) -{ - s390_adjust_jiffies(); - /* Print the good old Bogomips line .. */ - printk(KERN_DEBUG "Calibrating delay loop (skipped)... " - "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100); -} diff --git a/trunk/drivers/usb/input/Kconfig b/trunk/drivers/usb/input/Kconfig index aa6a620c162f..c7d887540d8d 100644 --- a/trunk/drivers/usb/input/Kconfig +++ b/trunk/drivers/usb/input/Kconfig @@ -69,14 +69,6 @@ config LOGITECH_FF Note: if you say N here, this device will still be supported, but without force feedback. -config PANTHERLORD_FF - bool "PantherLord USB/PS2 2in1 Adapter support" - depends on HID_FF - select INPUT_FF_MEMLESS if USB_HID - help - Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want - to enable force feedback support for it. - config THRUSTMASTER_FF bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" depends on HID_FF && EXPERIMENTAL diff --git a/trunk/drivers/usb/input/Makefile b/trunk/drivers/usb/input/Makefile index a06024e5cd56..1a24b5bfa05f 100644 --- a/trunk/drivers/usb/input/Makefile +++ b/trunk/drivers/usb/input/Makefile @@ -17,9 +17,6 @@ endif ifeq ($(CONFIG_LOGITECH_FF),y) usbhid-objs += hid-lgff.o endif -ifeq ($(CONFIG_PANTHERLORD_FF),y) - usbhid-objs += hid-plff.o -endif ifeq ($(CONFIG_THRUSTMASTER_FF),y) usbhid-objs += hid-tmff.o endif diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index e07a30490726..c6c9e72e5fd9 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -35,7 +35,6 @@ #include #include -#include #include "usbhid.h" /* @@ -221,6 +220,23 @@ static void hid_irq_in(struct urb *urb) } } +/* + * Find a report field with a specified HID usage. + */ +#if 0 +struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) +{ + struct hid_report *report; + int i; + + list_for_each_entry(report, &hid->report_enum[type].report_list, list) + for (i = 0; i < report->maxfield; i++) + if (report->field[i]->logical == wanted_usage) + return report->field[i]; + return NULL; +} +#endif /* 0 */ + static int hid_submit_out(struct hid_device *hid) { struct hid_report *report; @@ -485,7 +501,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, { int result, retries = 4; - memset(buf, 0, size); + memset(buf,0,size); // Make sure we parse really received data do { result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), @@ -512,6 +528,18 @@ void usbhid_close(struct hid_device *hid) usb_kill_urb(usbhid->urbin); } +static int hidinput_open(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + return usbhid_open(hid); +} + +static void hidinput_close(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + usbhid_close(hid); +} + #define USB_VENDOR_ID_PANJIT 0x134c #define USB_VENDOR_ID_TURBOX 0x062a @@ -742,7 +770,6 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b -#define USB_DEVICE_ID_APPLE_IR 0x8240 #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 @@ -765,9 +792,6 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 -#define USB_VENDOR_ID_PANTHERLORD 0x0810 -#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 - /* * Alphabetically sorted blacklist by quirk type. */ @@ -922,21 +946,19 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, - - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, @@ -947,8 +969,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, - { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { 0, 0 } }; @@ -1044,11 +1064,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (quirks & HID_QUIRK_IGNORE) return NULL; - if ((quirks & HID_QUIRK_IGNORE_MOUSE) && - (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) - return NULL; - - if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && (!interface->desc.bNumEndpoints || usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { @@ -1220,8 +1235,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); hid->hidinput_input_event = usb_hidinput_input_event; - hid->hid_open = usbhid_open; - hid->hid_close = usbhid_close; + hid->hidinput_open = hidinput_open; + hid->hidinput_close = hidinput_close; #ifdef CONFIG_USB_HIDDEV hid->hiddev_hid_event = hiddev_hid_event; hid->hiddev_report_event = hiddev_report_event; @@ -1300,7 +1315,11 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) return -ENODEV; } - if ((hid->claimed & HID_CLAIMED_INPUT)) + /* This only gets called when we are a single-input (most of the + * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is + * only useful in this case, and not for multi-input quirks. */ + if ((hid->claimed & HID_CLAIMED_INPUT) && + !(hid->quirks & HID_QUIRK_MULTI_INPUT)) hid_ff_init(hid); printk(KERN_INFO); diff --git a/trunk/drivers/usb/input/hid-ff.c b/trunk/drivers/usb/input/hid-ff.c index 5d145058a5cb..59ed65e7a621 100644 --- a/trunk/drivers/usb/input/hid-ff.c +++ b/trunk/drivers/usb/input/hid-ff.c @@ -58,9 +58,6 @@ static struct hid_ff_initializer inits[] = { { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ #endif -#ifdef CONFIG_PANTHERLORD_FF - { 0x810, 0x0001, hid_plff_init }, -#endif #ifdef CONFIG_THRUSTMASTER_FF { 0x44f, 0xb304, hid_tmff_init }, #endif diff --git a/trunk/drivers/usb/input/hid-plff.c b/trunk/drivers/usb/input/hid-plff.c deleted file mode 100644 index 76d2e6e14db4..000000000000 --- a/trunk/drivers/usb/input/hid-plff.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices - * - * Copyright (c) 2007 Anssi Hannula - */ - -/* - * 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 - */ - - -/* #define DEBUG */ - -#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) - -#include -#include -#include -#include "usbhid.h" - -struct plff_device { - struct hid_report *report; -}; - -static int hid_plff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = dev->private; - struct plff_device *plff = data; - int left, right; - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - debug("called with 0x%04x 0x%04x", left, right); - - left = left * 0x7f / 0xffff; - right = right * 0x7f / 0xffff; - - plff->report->field[0]->value[2] = left; - plff->report->field[0]->value[3] = right; - debug("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); - - return 0; -} - -int hid_plff_init(struct hid_device *hid) -{ - struct plff_device *plff; - struct hid_report *report; - struct hid_input *hidinput; - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct list_head *report_ptr = report_list; - struct input_dev *dev; - int error; - - /* The device contains 2 output reports (one for each - HID_QUIRK_MULTI_INPUT device), both containing 1 field, which - contains 4 ff00.0002 usages and 4 16bit absolute values. - - The 2 input reports also contain a field which contains - 8 ff00.0001 usages and 8 boolean values. Their meaning is - currently unknown. */ - - if (list_empty(report_list)) { - printk(KERN_ERR "hid-plff: no output reports found\n"); - return -ENODEV; - } - - list_for_each_entry(hidinput, &hid->inputs, list) { - - report_ptr = report_ptr->next; - - if (report_ptr == report_list) { - printk(KERN_ERR "hid-plff: required output report is missing\n"); - return -ENODEV; - } - - report = list_entry(report_ptr, struct hid_report, list); - if (report->maxfield < 1) { - printk(KERN_ERR "hid-plff: no fields in the report\n"); - return -ENODEV; - } - - if (report->field[0]->report_count < 4) { - printk(KERN_ERR "hid-plff: not enough values in the field\n"); - return -ENODEV; - } - - plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); - if (!plff) - return -ENOMEM; - - dev = hidinput->input; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, plff, hid_plff_play); - if (error) { - kfree(plff); - return error; - } - - plff->report = report; - plff->report->field[0]->value[0] = 0x00; - plff->report->field[0]->value[1] = 0x00; - plff->report->field[0]->value[2] = 0x00; - plff->report->field[0]->value[3] = 0x00; - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); - } - - printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " - "2in1 Adapters by Anssi Hannula \n"); - - return 0; -} diff --git a/trunk/drivers/video/output.c b/trunk/drivers/video/output.c deleted file mode 100644 index 1473f2c892d2..000000000000 --- a/trunk/drivers/video/output.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * output.c - Display Output Switch driver - * - * Copyright (C) 2006 Luming Yu - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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 -#include -#include -#include - - -MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Luming Yu "); - -static ssize_t video_output_show_state(struct class_device *dev,char *buf) -{ - ssize_t ret_size = 0; - struct output_device *od = to_output_device(dev); - if (od->props) - ret_size = sprintf(buf,"%.8x\n",od->props->get_status(od)); - return ret_size; -} - -static ssize_t video_output_store_state(struct class_device *dev, - const char *buf,size_t count) -{ - char *endp; - struct output_device *od = to_output_device(dev); - int request_state = simple_strtoul(buf,&endp,0); - size_t size = endp - buf; - - if (*endp && isspace(*endp)) - size++; - if (size != count) - return -EINVAL; - - if (od->props) { - od->request_state = request_state; - od->props->set_state(od); - } - return count; -} - -static void video_output_class_release(struct class_device *dev) -{ - struct output_device *od = to_output_device(dev); - kfree(od); -} - -static struct class_device_attribute video_output_attributes[] = { - __ATTR(state, 0644, video_output_show_state, video_output_store_state), - __ATTR_NULL, -}; - -static struct class video_output_class = { - .name = "video_output", - .release = video_output_class_release, - .class_dev_attrs = video_output_attributes, -}; - -struct output_device *video_output_register(const char *name, - struct device *dev, - void *devdata, - struct output_properties *op) -{ - struct output_device *new_dev; - int ret_code = 0; - - new_dev = kzalloc(sizeof(struct output_device),GFP_KERNEL); - if (!new_dev) { - ret_code = -ENOMEM; - goto error_return; - } - new_dev->props = op; - new_dev->class_dev.class = &video_output_class; - new_dev->class_dev.dev = dev; - strlcpy(new_dev->class_dev.class_id,name,KOBJ_NAME_LEN); - class_set_devdata(&new_dev->class_dev,devdata); - ret_code = class_device_register(&new_dev->class_dev); - if (ret_code) { - kfree(new_dev); - goto error_return; - } - return new_dev; - -error_return: - return ERR_PTR(ret_code); -} -EXPORT_SYMBOL(video_output_register); - -void video_output_unregister(struct output_device *dev) -{ - if (!dev) - return; - class_device_unregister(&dev->class_dev); -} -EXPORT_SYMBOL(video_output_unregister); - -static void __exit video_output_class_exit(void) -{ - class_unregister(&video_output_class); -} - -static int __init video_output_class_init(void) -{ - return class_register(&video_output_class); -} - -postcore_initcall(video_output_class_init); -module_exit(video_output_class_exit); diff --git a/trunk/fs/cifs/CHANGES b/trunk/fs/cifs/CHANGES index 85e3850bf2c9..d04d2f7448d9 100644 --- a/trunk/fs/cifs/CHANGES +++ b/trunk/fs/cifs/CHANGES @@ -1,8 +1,6 @@ Version 1.47 ------------ Fix oops in list_del during mount caused by unaligned string. -Seek to SEEK_END forces check for update of file size for non-cached -files. Version 1.46 ------------ diff --git a/trunk/fs/cifs/cifsfs.c b/trunk/fs/cifs/cifsfs.c index 93ef09971d2f..10c90294cd18 100644 --- a/trunk/fs/cifs/cifsfs.c +++ b/trunk/fs/cifs/cifsfs.c @@ -511,15 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) { /* origin == SEEK_END => we must revalidate the cached file length */ if (origin == SEEK_END) { - int retval; - - /* some applications poll for the file length in this strange - way so we must seek to end on non-oplocked files by - setting the revalidate time to zero */ - if(file->f_path.dentry->d_inode) - CIFS_I(file->f_path.dentry->d_inode)->time = 0; - - retval = cifs_revalidate(file->f_path.dentry); + int retval = cifs_revalidate(file->f_path.dentry); if (retval < 0) return (loff_t)retval; } diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index e9dcf5ee29a2..8a49b2e77d37 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -1146,7 +1146,7 @@ static int cifs_writepages(struct address_space *mapping, pgoff_t end; pgoff_t index; int range_whole = 0; - struct kvec * iov; + struct kvec iov[32]; int len; int n_iov = 0; pgoff_t next; @@ -1171,21 +1171,15 @@ static int cifs_writepages(struct address_space *mapping, if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server)) if(cifs_sb->tcon->ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - if(!experimEnabled) + if(!experimEnabled) return generic_writepages(mapping, wbc); - iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL); - if(iov == NULL) - return generic_writepages(mapping, wbc); - - /* * BB: Is this meaningful for a non-block-device file system? * If it is, we should test it again after we do I/O */ if (wbc->nonblocking && bdi_write_congested(bdi)) { wbc->encountered_congestion = 1; - kfree(iov); return 0; } @@ -1351,7 +1345,7 @@ static int cifs_writepages(struct address_space *mapping, mapping->writeback_index = index; FreeXid(xid); - kfree(iov); + return rc; } diff --git a/trunk/fs/cifs/readdir.c b/trunk/fs/cifs/readdir.c index 782940be550f..99dfb5337e31 100644 --- a/trunk/fs/cifs/readdir.c +++ b/trunk/fs/cifs/readdir.c @@ -156,9 +156,9 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, tmp_inode->i_atime = cnvrtDosUnixTm( le16_to_cpu(pfindData->LastAccessDate), le16_to_cpu(pfindData->LastAccessTime)); - tmp_inode->i_ctime = cnvrtDosUnixTm( - le16_to_cpu(pfindData->LastWriteDate), - le16_to_cpu(pfindData->LastWriteTime)); + tmp_inode->i_ctime = cnvrtDosUnixTm( + le16_to_cpu(pfindData->LastWriteDate), + le16_to_cpu(pfindData->LastWriteTime)); AdjustForTZ(cifs_sb->tcon, tmp_inode); attr = le16_to_cpu(pfindData->Attributes); allocation_size = le32_to_cpu(pfindData->AllocationSize); diff --git a/trunk/fs/cifs/smbdes.c b/trunk/fs/cifs/smbdes.c index 1b1daf63f062..7a1b2b961ec8 100644 --- a/trunk/fs/cifs/smbdes.c +++ b/trunk/fs/cifs/smbdes.c @@ -196,7 +196,7 @@ dohash(char *out, char *in, char *key, int forw) char c[28]; char d[28]; char *cd; - char (*ki)[48]; + char ki[16][48]; char *pd1; char l[32], r[32]; char *rl; @@ -206,12 +206,6 @@ dohash(char *out, char *in, char *key, int forw) if(pk1 == NULL) return; - ki = kmalloc(16*48, GFP_KERNEL); - if(ki == NULL) { - kfree(pk1); - return; - } - cd = pk1 + 56; pd1= cd + 56; rl = pd1 + 64; @@ -249,7 +243,6 @@ dohash(char *out, char *in, char *key, int forw) er = kmalloc(48+48+32+32+32, GFP_KERNEL); if(er == NULL) { kfree(pk1); - kfree(ki); return; } erk = er+48; @@ -297,7 +290,6 @@ dohash(char *out, char *in, char *key, int forw) permute(out, rl, perm6, 64); kfree(pk1); - kfree(ki); } static void diff --git a/trunk/fs/dlm/Kconfig b/trunk/fs/dlm/Kconfig index 6fa7b0d5c043..b5654a284fef 100644 --- a/trunk/fs/dlm/Kconfig +++ b/trunk/fs/dlm/Kconfig @@ -3,21 +3,21 @@ menu "Distributed Lock Manager" config DLM tristate "Distributed Lock Manager (DLM)" - depends on SYSFS && (IPV6 || IPV6=n) + depends on IPV6 || IPV6=n select CONFIGFS_FS select IP_SCTP if DLM_SCTP help - A general purpose distributed lock manager for kernel or userspace - applications. + A general purpose distributed lock manager for kernel or userspace + applications. choice prompt "Select DLM communications protocol" depends on DLM default DLM_TCP help - The DLM Can use TCP or SCTP for it's network communications. - SCTP supports multi-homed operations whereas TCP doesn't. - However, SCTP seems to have stability problems at the moment. + The DLM Can use TCP or SCTP for it's network communications. + SCTP supports multi-homed operations whereas TCP doesn't. + However, SCTP seems to have stability problems at the moment. config DLM_TCP bool "TCP/IP" @@ -31,8 +31,8 @@ config DLM_DEBUG bool "DLM debugging" depends on DLM help - Under the debugfs mount point, the name of each lockspace will - appear as a file in the "dlm" directory. The output is the - list of resource and locks the local node knows about. + Under the debugfs mount point, the name of each lockspace will + appear as a file in the "dlm" directory. The output is the + list of resource and locks the local node knows about. endmenu diff --git a/trunk/fs/dlm/config.c b/trunk/fs/dlm/config.c index 8665c88e5af2..88553054bbfa 100644 --- a/trunk/fs/dlm/config.c +++ b/trunk/fs/dlm/config.c @@ -54,11 +54,6 @@ static struct config_item *make_node(struct config_group *, const char *); static void drop_node(struct config_group *, struct config_item *); static void release_node(struct config_item *); -static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, - char *buf); -static ssize_t store_cluster(struct config_item *i, - struct configfs_attribute *a, - const char *buf, size_t len); static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, char *buf); static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a, @@ -78,101 +73,6 @@ static ssize_t node_nodeid_write(struct node *nd, const char *buf, size_t len); static ssize_t node_weight_read(struct node *nd, char *buf); static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len); -struct cluster { - struct config_group group; - unsigned int cl_tcp_port; - unsigned int cl_buffer_size; - unsigned int cl_rsbtbl_size; - unsigned int cl_lkbtbl_size; - unsigned int cl_dirtbl_size; - unsigned int cl_recover_timer; - unsigned int cl_toss_secs; - unsigned int cl_scan_secs; - unsigned int cl_log_debug; -}; - -enum { - CLUSTER_ATTR_TCP_PORT = 0, - CLUSTER_ATTR_BUFFER_SIZE, - CLUSTER_ATTR_RSBTBL_SIZE, - CLUSTER_ATTR_LKBTBL_SIZE, - CLUSTER_ATTR_DIRTBL_SIZE, - CLUSTER_ATTR_RECOVER_TIMER, - CLUSTER_ATTR_TOSS_SECS, - CLUSTER_ATTR_SCAN_SECS, - CLUSTER_ATTR_LOG_DEBUG, -}; - -struct cluster_attribute { - struct configfs_attribute attr; - ssize_t (*show)(struct cluster *, char *); - ssize_t (*store)(struct cluster *, const char *, size_t); -}; - -static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field, - unsigned int *info_field, int check_zero, - const char *buf, size_t len) -{ - unsigned int x; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - x = simple_strtoul(buf, NULL, 0); - - if (check_zero && !x) - return -EINVAL; - - *cl_field = x; - *info_field = x; - - return len; -} - -#define __CONFIGFS_ATTR(_name,_mode,_read,_write) { \ - .attr = { .ca_name = __stringify(_name), \ - .ca_mode = _mode, \ - .ca_owner = THIS_MODULE }, \ - .show = _read, \ - .store = _write, \ -} - -#define CLUSTER_ATTR(name, check_zero) \ -static ssize_t name##_write(struct cluster *cl, const char *buf, size_t len) \ -{ \ - return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name, \ - check_zero, buf, len); \ -} \ -static ssize_t name##_read(struct cluster *cl, char *buf) \ -{ \ - return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name); \ -} \ -static struct cluster_attribute cluster_attr_##name = \ -__CONFIGFS_ATTR(name, 0644, name##_read, name##_write) - -CLUSTER_ATTR(tcp_port, 1); -CLUSTER_ATTR(buffer_size, 1); -CLUSTER_ATTR(rsbtbl_size, 1); -CLUSTER_ATTR(lkbtbl_size, 1); -CLUSTER_ATTR(dirtbl_size, 1); -CLUSTER_ATTR(recover_timer, 1); -CLUSTER_ATTR(toss_secs, 1); -CLUSTER_ATTR(scan_secs, 1); -CLUSTER_ATTR(log_debug, 0); - -static struct configfs_attribute *cluster_attrs[] = { - [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, - [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr, - [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr, - [CLUSTER_ATTR_LKBTBL_SIZE] = &cluster_attr_lkbtbl_size.attr, - [CLUSTER_ATTR_DIRTBL_SIZE] = &cluster_attr_dirtbl_size.attr, - [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr, - [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr, - [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr, - [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr, - NULL, -}; - enum { COMM_ATTR_NODEID = 0, COMM_ATTR_LOCAL, @@ -252,6 +152,10 @@ struct clusters { struct configfs_subsystem subsys; }; +struct cluster { + struct config_group group; +}; + struct spaces { struct config_group ss_group; }; @@ -293,8 +197,6 @@ static struct configfs_group_operations clusters_ops = { static struct configfs_item_operations cluster_ops = { .release = release_cluster, - .show_attribute = show_cluster, - .store_attribute = store_cluster, }; static struct configfs_group_operations spaces_ops = { @@ -335,7 +237,6 @@ static struct config_item_type clusters_type = { static struct config_item_type cluster_type = { .ct_item_ops = &cluster_ops, - .ct_attrs = cluster_attrs, .ct_owner = THIS_MODULE, }; @@ -416,16 +317,6 @@ static struct config_group *make_cluster(struct config_group *g, cl->group.default_groups[1] = &cms->cs_group; cl->group.default_groups[2] = NULL; - cl->cl_tcp_port = dlm_config.ci_tcp_port; - cl->cl_buffer_size = dlm_config.ci_buffer_size; - cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size; - cl->cl_lkbtbl_size = dlm_config.ci_lkbtbl_size; - cl->cl_dirtbl_size = dlm_config.ci_dirtbl_size; - cl->cl_recover_timer = dlm_config.ci_recover_timer; - cl->cl_toss_secs = dlm_config.ci_toss_secs; - cl->cl_scan_secs = dlm_config.ci_scan_secs; - cl->cl_log_debug = dlm_config.ci_log_debug; - space_list = &sps->ss_group; comm_list = &cms->cs_group; return &cl->group; @@ -618,25 +509,6 @@ void dlm_config_exit(void) * Functions for user space to read/write attributes */ -static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a, - char *buf) -{ - struct cluster *cl = to_cluster(i); - struct cluster_attribute *cla = - container_of(a, struct cluster_attribute, attr); - return cla->show ? cla->show(cl, buf) : 0; -} - -static ssize_t store_cluster(struct config_item *i, - struct configfs_attribute *a, - const char *buf, size_t len) -{ - struct cluster *cl = to_cluster(i); - struct cluster_attribute *cla = - container_of(a, struct cluster_attribute, attr); - return cla->store ? cla->store(cl, buf, len) : -EINVAL; -} - static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a, char *buf) { @@ -903,17 +775,15 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num) #define DEFAULT_RECOVER_TIMER 5 #define DEFAULT_TOSS_SECS 10 #define DEFAULT_SCAN_SECS 5 -#define DEFAULT_LOG_DEBUG 0 struct dlm_config_info dlm_config = { - .ci_tcp_port = DEFAULT_TCP_PORT, - .ci_buffer_size = DEFAULT_BUFFER_SIZE, - .ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE, - .ci_lkbtbl_size = DEFAULT_LKBTBL_SIZE, - .ci_dirtbl_size = DEFAULT_DIRTBL_SIZE, - .ci_recover_timer = DEFAULT_RECOVER_TIMER, - .ci_toss_secs = DEFAULT_TOSS_SECS, - .ci_scan_secs = DEFAULT_SCAN_SECS, - .ci_log_debug = DEFAULT_LOG_DEBUG + .tcp_port = DEFAULT_TCP_PORT, + .buffer_size = DEFAULT_BUFFER_SIZE, + .rsbtbl_size = DEFAULT_RSBTBL_SIZE, + .lkbtbl_size = DEFAULT_LKBTBL_SIZE, + .dirtbl_size = DEFAULT_DIRTBL_SIZE, + .recover_timer = DEFAULT_RECOVER_TIMER, + .toss_secs = DEFAULT_TOSS_SECS, + .scan_secs = DEFAULT_SCAN_SECS }; diff --git a/trunk/fs/dlm/config.h b/trunk/fs/dlm/config.h index 1e978611a96e..9da7839958a9 100644 --- a/trunk/fs/dlm/config.h +++ b/trunk/fs/dlm/config.h @@ -17,15 +17,14 @@ #define DLM_MAX_ADDR_COUNT 3 struct dlm_config_info { - int ci_tcp_port; - int ci_buffer_size; - int ci_rsbtbl_size; - int ci_lkbtbl_size; - int ci_dirtbl_size; - int ci_recover_timer; - int ci_toss_secs; - int ci_scan_secs; - int ci_log_debug; + int tcp_port; + int buffer_size; + int rsbtbl_size; + int lkbtbl_size; + int dirtbl_size; + int recover_timer; + int toss_secs; + int scan_secs; }; extern struct dlm_config_info dlm_config; diff --git a/trunk/fs/dlm/dlm_internal.h b/trunk/fs/dlm/dlm_internal.h index 61d93201e1b2..1ee8195e6fc0 100644 --- a/trunk/fs/dlm/dlm_internal.h +++ b/trunk/fs/dlm/dlm_internal.h @@ -41,7 +41,6 @@ #include #include -#include "config.h" #define DLM_LOCKSPACE_LEN 64 @@ -70,12 +69,12 @@ struct dlm_mhandle; #define log_error(ls, fmt, args...) \ printk(KERN_ERR "dlm: %s: " fmt "\n", (ls)->ls_name , ##args) -#define log_debug(ls, fmt, args...) \ -do { \ - if (dlm_config.ci_log_debug) \ - printk(KERN_DEBUG "dlm: %s: " fmt "\n", \ - (ls)->ls_name , ##args); \ -} while (0) +#define DLM_LOG_DEBUG +#ifdef DLM_LOG_DEBUG +#define log_debug(ls, fmt, args...) log_error(ls, fmt, ##args) +#else +#define log_debug(ls, fmt, args...) +#endif #define DLM_ASSERT(x, do) \ { \ @@ -310,8 +309,8 @@ static inline int rsb_flag(struct dlm_rsb *r, enum rsb_flags flag) /* dlm_header is first element of all structs sent between nodes */ -#define DLM_HEADER_MAJOR 0x00030000 -#define DLM_HEADER_MINOR 0x00000000 +#define DLM_HEADER_MAJOR 0x00020000 +#define DLM_HEADER_MINOR 0x00000001 #define DLM_MSG 1 #define DLM_RCOM 2 @@ -387,8 +386,6 @@ struct dlm_rcom { uint32_t rc_type; /* DLM_RCOM_ */ int rc_result; /* multi-purpose */ uint64_t rc_id; /* match reply with request */ - uint64_t rc_seq; /* sender's ls_recover_seq */ - uint64_t rc_seq_reply; /* remote ls_recover_seq */ char rc_buf[0]; }; @@ -526,7 +523,6 @@ struct dlm_user_proc { spinlock_t asts_spin; struct list_head locks; spinlock_t locks_spin; - struct list_head unlocking; wait_queue_head_t wait; }; diff --git a/trunk/fs/dlm/lock.c b/trunk/fs/dlm/lock.c index e725005fafd0..30878defaeb6 100644 --- a/trunk/fs/dlm/lock.c +++ b/trunk/fs/dlm/lock.c @@ -754,11 +754,6 @@ static void add_to_waiters(struct dlm_lkb *lkb, int mstype) mutex_unlock(&ls->ls_waiters_mutex); } -/* We clear the RESEND flag because we might be taking an lkb off the waiters - list as part of process_requestqueue (e.g. a lookup that has an optimized - request reply on the requestqueue) between dlm_recover_waiters_pre() which - set RESEND and dlm_recover_waiters_post() */ - static int _remove_from_waiters(struct dlm_lkb *lkb) { int error = 0; @@ -769,7 +764,6 @@ static int _remove_from_waiters(struct dlm_lkb *lkb) goto out; } lkb->lkb_wait_type = 0; - lkb->lkb_flags &= ~DLM_IFL_RESEND; list_del(&lkb->lkb_wait_reply); unhold_lkb(lkb); out: @@ -816,7 +810,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b) list_for_each_entry_reverse(r, &ls->ls_rsbtbl[b].toss, res_hashchain) { if (!time_after_eq(jiffies, r->res_toss_time + - dlm_config.ci_toss_secs * HZ)) + dlm_config.toss_secs * HZ)) continue; found = 1; break; @@ -2150,24 +2144,12 @@ static void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb, if (lkb->lkb_astaddr) ms->m_asts |= AST_COMP; - /* compare with switch in create_message; send_remove() doesn't - use send_args() */ - - switch (ms->m_type) { - case DLM_MSG_REQUEST: - case DLM_MSG_LOOKUP: + if (ms->m_type == DLM_MSG_REQUEST || ms->m_type == DLM_MSG_LOOKUP) memcpy(ms->m_extra, r->res_name, r->res_length); - break; - case DLM_MSG_CONVERT: - case DLM_MSG_UNLOCK: - case DLM_MSG_REQUEST_REPLY: - case DLM_MSG_CONVERT_REPLY: - case DLM_MSG_GRANT: - if (!lkb->lkb_lvbptr) - break; + + else if (lkb->lkb_lvbptr) memcpy(ms->m_extra, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); - break; - } + } static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype) @@ -2436,12 +2418,8 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, DLM_ASSERT(is_master_copy(lkb), dlm_print_lkb(lkb);); - if (lkb->lkb_exflags & DLM_LKF_VALBLK) { - /* lkb was just created so there won't be an lvb yet */ - lkb->lkb_lvbptr = allocate_lvb(ls); - if (!lkb->lkb_lvbptr) - return -ENOMEM; - } + if (receive_lvb(ls, lkb, ms)) + return -ENOMEM; return 0; } @@ -3024,7 +3002,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) { struct dlm_message *ms = (struct dlm_message *) hd; struct dlm_ls *ls; - int error = 0; + int error; if (!recovery) dlm_message_in(ms); @@ -3141,7 +3119,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) out: dlm_put_lockspace(ls); dlm_astd_wake(); - return error; + return 0; } @@ -3154,7 +3132,6 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) if (middle_conversion(lkb)) { hold_lkb(lkb); ls->ls_stub_ms.m_result = -EINPROGRESS; - ls->ls_stub_ms.m_flags = lkb->lkb_flags; _remove_from_waiters(lkb); _receive_convert_reply(lkb, &ls->ls_stub_ms); @@ -3228,7 +3205,6 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) case DLM_MSG_UNLOCK: hold_lkb(lkb); ls->ls_stub_ms.m_result = -DLM_EUNLOCK; - ls->ls_stub_ms.m_flags = lkb->lkb_flags; _remove_from_waiters(lkb); _receive_unlock_reply(lkb, &ls->ls_stub_ms); dlm_put_lkb(lkb); @@ -3237,7 +3213,6 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) case DLM_MSG_CANCEL: hold_lkb(lkb); ls->ls_stub_ms.m_result = -DLM_ECANCEL; - ls->ls_stub_ms.m_flags = lkb->lkb_flags; _remove_from_waiters(lkb); _receive_cancel_reply(lkb, &ls->ls_stub_ms); dlm_put_lkb(lkb); @@ -3596,14 +3571,6 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) lock_rsb(r); switch (error) { - case -EBADR: - /* There's a chance the new master received our lock before - dlm_recover_master_reply(), this wouldn't happen if we did - a barrier between recover_masters and recover_locks. */ - log_debug(ls, "master copy not ready %x r %lx %s", lkb->lkb_id, - (unsigned long)r, r->res_name); - dlm_send_rcom_lock(r, lkb); - goto out; case -EEXIST: log_debug(ls, "master copy exists %x", lkb->lkb_id); /* fall through */ @@ -3618,7 +3585,7 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) /* an ack for dlm_recover_locks() which waits for replies from all the locks it sends to new masters */ dlm_recovered_lock(r); - out: + unlock_rsb(r); put_rsb(r); dlm_put_lkb(lkb); @@ -3643,7 +3610,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, } if (flags & DLM_LKF_VALBLK) { - ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL); + ua->lksb.sb_lvbptr = kmalloc(DLM_USER_LVB_LEN, GFP_KERNEL); if (!ua->lksb.sb_lvbptr) { kfree(ua); __put_lkb(ls, lkb); @@ -3712,7 +3679,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, ua = (struct dlm_user_args *)lkb->lkb_astparam; if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) { - ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL); + ua->lksb.sb_lvbptr = kmalloc(DLM_USER_LVB_LEN, GFP_KERNEL); if (!ua->lksb.sb_lvbptr) { error = -ENOMEM; goto out_put; @@ -3778,10 +3745,12 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, goto out_put; spin_lock(&ua->proc->locks_spin); - /* dlm_user_add_ast() may have already taken lkb off the proc list */ - if (!list_empty(&lkb->lkb_ownqueue)) - list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking); + list_del_init(&lkb->lkb_ownqueue); spin_unlock(&ua->proc->locks_spin); + + /* this removes the reference for the proc->locks list added by + dlm_user_request */ + unhold_lkb(lkb); out_put: dlm_put_lkb(lkb); out: @@ -3821,8 +3790,9 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, /* this lkb was removed from the WAITING queue */ if (lkb->lkb_grmode == DLM_LOCK_IV) { spin_lock(&ua->proc->locks_spin); - list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking); + list_del_init(&lkb->lkb_ownqueue); spin_unlock(&ua->proc->locks_spin); + unhold_lkb(lkb); } out_put: dlm_put_lkb(lkb); @@ -3883,6 +3853,11 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) mutex_lock(&ls->ls_clear_proc_locks); list_for_each_entry_safe(lkb, safe, &proc->locks, lkb_ownqueue) { + if (lkb->lkb_ast_type) { + list_del(&lkb->lkb_astqueue); + unhold_lkb(lkb); + } + list_del_init(&lkb->lkb_ownqueue); if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) { @@ -3899,20 +3874,6 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) dlm_put_lkb(lkb); } - - /* in-progress unlocks */ - list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) { - list_del_init(&lkb->lkb_ownqueue); - lkb->lkb_flags |= DLM_IFL_DEAD; - dlm_put_lkb(lkb); - } - - list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { - list_del(&lkb->lkb_astqueue); - dlm_put_lkb(lkb); - } - mutex_unlock(&ls->ls_clear_proc_locks); unlock_recovery(ls); } - diff --git a/trunk/fs/dlm/lockspace.c b/trunk/fs/dlm/lockspace.c index f40817b53c6f..59012b089e8d 100644 --- a/trunk/fs/dlm/lockspace.c +++ b/trunk/fs/dlm/lockspace.c @@ -236,7 +236,7 @@ static int dlm_scand(void *data) while (!kthread_should_stop()) { list_for_each_entry(ls, &lslist, ls_list) dlm_scan_rsbs(ls); - schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); + schedule_timeout_interruptible(dlm_config.scan_secs * HZ); } return 0; } @@ -422,7 +422,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, ls->ls_count = 0; ls->ls_flags = 0; - size = dlm_config.ci_rsbtbl_size; + size = dlm_config.rsbtbl_size; ls->ls_rsbtbl_size = size; ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL); @@ -434,7 +434,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, rwlock_init(&ls->ls_rsbtbl[i].lock); } - size = dlm_config.ci_lkbtbl_size; + size = dlm_config.lkbtbl_size; ls->ls_lkbtbl_size = size; ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL); @@ -446,7 +446,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, ls->ls_lkbtbl[i].counter = 1; } - size = dlm_config.ci_dirtbl_size; + size = dlm_config.dirtbl_size; ls->ls_dirtbl_size = size; ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL); @@ -489,7 +489,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, mutex_init(&ls->ls_requestqueue_mutex); mutex_init(&ls->ls_clear_proc_locks); - ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); + ls->ls_recover_buf = kmalloc(dlm_config.buffer_size, GFP_KERNEL); if (!ls->ls_recover_buf) goto out_dirfree; diff --git a/trunk/fs/dlm/lowcomms-sctp.c b/trunk/fs/dlm/lowcomms-sctp.c index dc83a9d979b5..fe158d7a9285 100644 --- a/trunk/fs/dlm/lowcomms-sctp.c +++ b/trunk/fs/dlm/lowcomms-sctp.c @@ -72,8 +72,6 @@ struct nodeinfo { struct list_head writequeue; /* outgoing writequeue_entries */ spinlock_t writequeue_lock; int nodeid; - struct work_struct swork; /* Send workqueue */ - struct work_struct lwork; /* Locking workqueue */ }; static DEFINE_IDR(nodeinfo_idr); @@ -98,7 +96,6 @@ struct connection { atomic_t waiting_requests; struct cbuf cb; int eagain_flag; - struct work_struct work; /* Send workqueue */ }; /* An entry waiting to be sent */ @@ -140,23 +137,19 @@ static void cbuf_eat(struct cbuf *cb, int n) static LIST_HEAD(write_nodes); static DEFINE_SPINLOCK(write_nodes_lock); - /* Maximum number of incoming messages to process before * doing a schedule() */ #define MAX_RX_MSG_COUNT 25 -/* Work queues */ -static struct workqueue_struct *recv_workqueue; -static struct workqueue_struct *send_workqueue; -static struct workqueue_struct *lock_workqueue; +/* Manage daemons */ +static struct task_struct *recv_task; +static struct task_struct *send_task; +static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_wait); /* The SCTP connection */ static struct connection sctp_con; -static void process_send_sockets(struct work_struct *work); -static void process_recv_sockets(struct work_struct *work); -static void process_lock_request(struct work_struct *work); static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr) { @@ -229,8 +222,6 @@ static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc) spin_lock_init(&ni->lock); INIT_LIST_HEAD(&ni->writequeue); spin_lock_init(&ni->writequeue_lock); - INIT_WORK(&ni->lwork, process_lock_request); - INIT_WORK(&ni->swork, process_send_sockets); ni->nodeid = nodeid; if (nodeid > max_nodeid) @@ -258,8 +249,11 @@ static struct nodeinfo *assoc2nodeinfo(sctp_assoc_t assoc) /* Data or notification available on socket */ static void lowcomms_data_ready(struct sock *sk, int count_unused) { + atomic_inc(&sctp_con.waiting_requests); if (test_and_set_bit(CF_READ_PENDING, &sctp_con.flags)) - queue_work(recv_workqueue, &sctp_con.work); + return; + + wake_up_interruptible(&lowcomms_recv_wait); } @@ -367,10 +361,10 @@ static void init_failed(void) spin_lock_bh(&write_nodes_lock); list_add_tail(&ni->write_list, &write_nodes); spin_unlock_bh(&write_nodes_lock); - queue_work(send_workqueue, &ni->swork); } } } + wake_up_process(send_task); } /* Something happened to an association */ @@ -452,8 +446,8 @@ static void process_sctp_notification(struct msghdr *msg, char *buf) spin_lock_bh(&write_nodes_lock); list_add_tail(&ni->write_list, &write_nodes); spin_unlock_bh(&write_nodes_lock); - queue_work(send_workqueue, &ni->swork); } + wake_up_process(send_task); } break; @@ -586,8 +580,8 @@ static int receive_from_sock(void) spin_lock_bh(&write_nodes_lock); list_add_tail(&ni->write_list, &write_nodes); spin_unlock_bh(&write_nodes_lock); - queue_work(send_workqueue, &ni->swork); } + wake_up_process(send_task); } } @@ -596,7 +590,6 @@ static int receive_from_sock(void) return 0; cbuf_add(&sctp_con.cb, ret); - // PJC: TODO: Add to node's workqueue....can we ?? ret = dlm_process_incoming_buffer(cpu_to_le32(sinfo->sinfo_ppid), page_address(sctp_con.rx_page), sctp_con.cb.base, sctp_con.cb.len, @@ -642,7 +635,7 @@ static int add_bind_addr(struct sockaddr_storage *addr, int addr_len, int num) if (result < 0) log_print("Can't bind to port %d addr number %d", - dlm_config.ci_tcp_port, num); + dlm_config.tcp_port, num); return result; } @@ -718,7 +711,7 @@ static int init_sock(void) /* Bind to all interfaces. */ for (i = 0; i < dlm_local_count; i++) { memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr)); - make_sockaddr(&localaddr, dlm_config.ci_tcp_port, &addr_len); + make_sockaddr(&localaddr, dlm_config.tcp_port, &addr_len); result = add_bind_addr(&localaddr, addr_len, num); if (result) @@ -827,8 +820,7 @@ void dlm_lowcomms_commit_buffer(void *arg) spin_lock_bh(&write_nodes_lock); list_add_tail(&ni->write_list, &write_nodes); spin_unlock_bh(&write_nodes_lock); - - queue_work(send_workqueue, &ni->swork); + wake_up_process(send_task); } return; @@ -871,7 +863,7 @@ static void initiate_association(int nodeid) return; } - make_sockaddr(&rem_addr, dlm_config.ci_tcp_port, &addrlen); + make_sockaddr(&rem_addr, dlm_config.tcp_port, &addrlen); outmessage.msg_name = &rem_addr; outmessage.msg_namelen = addrlen; @@ -1096,75 +1088,101 @@ int dlm_lowcomms_close(int nodeid) return 0; } -// PJC: The work queue function for receiving. -static void process_recv_sockets(struct work_struct *work) +static int write_list_empty(void) { - if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) { - int ret; - int count = 0; + int status; - do { - ret = receive_from_sock(); + spin_lock_bh(&write_nodes_lock); + status = list_empty(&write_nodes); + spin_unlock_bh(&write_nodes_lock); - /* Don't starve out everyone else */ - if (++count >= MAX_RX_MSG_COUNT) { - cond_resched(); - count = 0; - } - } while (!kthread_should_stop() && ret >=0); - } - cond_resched(); + return status; } -// PJC: the work queue function for sending -static void process_send_sockets(struct work_struct *work) +static int dlm_recvd(void *data) { - if (sctp_con.eagain_flag) { - sctp_con.eagain_flag = 0; - refill_write_queue(); + DECLARE_WAITQUEUE(wait, current); + + while (!kthread_should_stop()) { + int count = 0; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&lowcomms_recv_wait, &wait); + if (!test_bit(CF_READ_PENDING, &sctp_con.flags)) + cond_resched(); + remove_wait_queue(&lowcomms_recv_wait, &wait); + set_current_state(TASK_RUNNING); + + if (test_and_clear_bit(CF_READ_PENDING, &sctp_con.flags)) { + int ret; + + do { + ret = receive_from_sock(); + + /* Don't starve out everyone else */ + if (++count >= MAX_RX_MSG_COUNT) { + cond_resched(); + count = 0; + } + } while (!kthread_should_stop() && ret >=0); + } + cond_resched(); } - process_output_queue(); + + return 0; } -// PJC: Process lock requests from a particular node. -// TODO: can we optimise this out on UP ?? -static void process_lock_request(struct work_struct *work) +static int dlm_sendd(void *data) { + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (write_list_empty()) + cond_resched(); + set_current_state(TASK_RUNNING); + + if (sctp_con.eagain_flag) { + sctp_con.eagain_flag = 0; + refill_write_queue(); + } + process_output_queue(); + } + + remove_wait_queue(sctp_con.sock->sk->sk_sleep, &wait); + + return 0; } static void daemons_stop(void) { - destroy_workqueue(recv_workqueue); - destroy_workqueue(send_workqueue); - destroy_workqueue(lock_workqueue); + kthread_stop(recv_task); + kthread_stop(send_task); } static int daemons_start(void) { + struct task_struct *p; int error; - recv_workqueue = create_workqueue("dlm_recv"); - error = IS_ERR(recv_workqueue); - if (error) { - log_print("can't start dlm_recv %d", error); - return error; - } - send_workqueue = create_singlethread_workqueue("dlm_send"); - error = IS_ERR(send_workqueue); + p = kthread_run(dlm_recvd, NULL, "dlm_recvd"); + error = IS_ERR(p); if (error) { - log_print("can't start dlm_send %d", error); - destroy_workqueue(recv_workqueue); + log_print("can't start dlm_recvd %d", error); return error; } + recv_task = p; - lock_workqueue = create_workqueue("dlm_rlock"); - error = IS_ERR(lock_workqueue); + p = kthread_run(dlm_sendd, NULL, "dlm_sendd"); + error = IS_ERR(p); if (error) { - log_print("can't start dlm_rlock %d", error); - destroy_workqueue(send_workqueue); - destroy_workqueue(recv_workqueue); + log_print("can't start dlm_sendd %d", error); + kthread_stop(recv_task); return error; } + send_task = p; return 0; } @@ -1176,8 +1194,6 @@ int dlm_lowcomms_start(void) { int error; - INIT_WORK(&sctp_con.work, process_recv_sockets); - error = init_sock(); if (error) goto fail_sock; @@ -1208,3 +1224,4 @@ void dlm_lowcomms_stop(void) for (i = 0; i < dlm_local_count; i++) kfree(dlm_local_addr[i]); } + diff --git a/trunk/fs/dlm/lowcomms-tcp.c b/trunk/fs/dlm/lowcomms-tcp.c index f1efd17b2614..9be3a440c42a 100644 --- a/trunk/fs/dlm/lowcomms-tcp.c +++ b/trunk/fs/dlm/lowcomms-tcp.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions @@ -96,7 +96,10 @@ static bool cbuf_empty(struct cbuf *cb) struct connection { struct socket *sock; /* NULL if not connected */ uint32_t nodeid; /* So we know who we are in the list */ - struct mutex sock_mutex; + struct rw_semaphore sock_sem; /* Stop connect races */ + struct list_head read_list; /* On this list when ready for reading */ + struct list_head write_list; /* On this list when ready for writing */ + struct list_head state_list; /* On this list when ready to connect */ unsigned long flags; /* bit 1,2 = We are on the read/write lists */ #define CF_READ_PENDING 1 #define CF_WRITE_PENDING 2 @@ -109,10 +112,9 @@ struct connection { struct page *rx_page; struct cbuf cb; int retries; + atomic_t waiting_requests; #define MAX_CONNECT_RETRIES 3 struct connection *othercon; - struct work_struct rwork; /* Receive workqueue */ - struct work_struct swork; /* Send workqueue */ }; #define sock2con(x) ((struct connection *)(x)->sk_user_data) @@ -129,9 +131,14 @@ struct writequeue_entry { static struct sockaddr_storage dlm_local_addr; -/* Work queues */ -static struct workqueue_struct *recv_workqueue; -static struct workqueue_struct *send_workqueue; +/* Manage daemons */ +static struct task_struct *recv_task; +static struct task_struct *send_task; + +static wait_queue_t lowcomms_send_waitq_head; +static DECLARE_WAIT_QUEUE_HEAD(lowcomms_send_waitq); +static wait_queue_t lowcomms_recv_waitq_head; +static DECLARE_WAIT_QUEUE_HEAD(lowcomms_recv_waitq); /* An array of pointers to connections, indexed by NODEID */ static struct connection **connections; @@ -139,8 +146,17 @@ static DECLARE_MUTEX(connections_lock); static struct kmem_cache *con_cache; static int conn_array_size; -static void process_recv_sockets(struct work_struct *work); -static void process_send_sockets(struct work_struct *work); +/* List of sockets that have reads pending */ +static LIST_HEAD(read_sockets); +static DEFINE_SPINLOCK(read_sockets_lock); + +/* List of sockets which have writes pending */ +static LIST_HEAD(write_sockets); +static DEFINE_SPINLOCK(write_sockets_lock); + +/* List of sockets which have connects pending */ +static LIST_HEAD(state_sockets); +static DEFINE_SPINLOCK(state_sockets_lock); static struct connection *nodeid2con(int nodeid, gfp_t allocation) { @@ -170,11 +186,9 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation) goto finish; con->nodeid = nodeid; - mutex_init(&con->sock_mutex); + init_rwsem(&con->sock_sem); INIT_LIST_HEAD(&con->writequeue); spin_lock_init(&con->writequeue_lock); - INIT_WORK(&con->swork, process_send_sockets); - INIT_WORK(&con->rwork, process_recv_sockets); connections[nodeid] = con; } @@ -189,22 +203,41 @@ static void lowcomms_data_ready(struct sock *sk, int count_unused) { struct connection *con = sock2con(sk); - if (!test_and_set_bit(CF_READ_PENDING, &con->flags)) - queue_work(recv_workqueue, &con->rwork); + atomic_inc(&con->waiting_requests); + if (test_and_set_bit(CF_READ_PENDING, &con->flags)) + return; + + spin_lock_bh(&read_sockets_lock); + list_add_tail(&con->read_list, &read_sockets); + spin_unlock_bh(&read_sockets_lock); + + wake_up_interruptible(&lowcomms_recv_waitq); } static void lowcomms_write_space(struct sock *sk) { struct connection *con = sock2con(sk); - if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) - queue_work(send_workqueue, &con->swork); + if (test_and_set_bit(CF_WRITE_PENDING, &con->flags)) + return; + + spin_lock_bh(&write_sockets_lock); + list_add_tail(&con->write_list, &write_sockets); + spin_unlock_bh(&write_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); } static inline void lowcomms_connect_sock(struct connection *con) { - if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags)) - queue_work(send_workqueue, &con->swork); + if (test_and_set_bit(CF_CONNECT_PENDING, &con->flags)) + return; + + spin_lock_bh(&state_sockets_lock); + list_add_tail(&con->state_list, &state_sockets); + spin_unlock_bh(&state_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); } static void lowcomms_state_change(struct sock *sk) @@ -246,7 +279,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port, /* Close a remote connection and tidy up */ static void close_connection(struct connection *con, bool and_other) { - mutex_lock(&con->sock_mutex); + down_write(&con->sock_sem); if (con->sock) { sock_release(con->sock); @@ -261,7 +294,7 @@ static void close_connection(struct connection *con, bool and_other) con->rx_page = NULL; } con->retries = 0; - mutex_unlock(&con->sock_mutex); + up_write(&con->sock_sem); } /* Data received from remote end */ @@ -275,13 +308,10 @@ static int receive_from_sock(struct connection *con) int r; int call_again_soon = 0; - mutex_lock(&con->sock_mutex); - - if (con->sock == NULL) { - ret = -EAGAIN; - goto out_close; - } + down_read(&con->sock_sem); + if (con->sock == NULL) + goto out; if (con->rx_page == NULL) { /* * This doesn't need to be atomic, but I think it should @@ -329,9 +359,6 @@ static int receive_from_sock(struct connection *con) if (ret <= 0) goto out_close; - if (ret == -EAGAIN) - goto out_resched; - if (ret == len) call_again_soon = 1; cbuf_add(&con->cb, ret); @@ -354,26 +381,24 @@ static int receive_from_sock(struct connection *con) con->rx_page = NULL; } +out: if (call_again_soon) goto out_resched; - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); return 0; out_resched: - if (!test_and_set_bit(CF_READ_PENDING, &con->flags)) - queue_work(recv_workqueue, &con->rwork); - mutex_unlock(&con->sock_mutex); - return -EAGAIN; + lowcomms_data_ready(con->sock->sk, 0); + up_read(&con->sock_sem); + cond_resched(); + return 0; out_close: - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) { close_connection(con, false); /* Reconnect when there is something to send */ } - /* Don't return success if we really got EOF */ - if (ret == 0) - ret = -EAGAIN; return ret; } @@ -387,7 +412,6 @@ static int accept_from_sock(struct connection *con) int len; int nodeid; struct connection *newcon; - struct connection *addcon; memset(&peeraddr, 0, sizeof(peeraddr)); result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM, @@ -395,7 +419,7 @@ static int accept_from_sock(struct connection *con) if (result < 0) return -ENOMEM; - mutex_lock_nested(&con->sock_mutex, 0); + down_read(&con->sock_sem); result = -ENOTCONN; if (con->sock == NULL) @@ -421,7 +445,7 @@ static int accept_from_sock(struct connection *con) if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) { printk("dlm: connect from non cluster node\n"); sock_release(newsock); - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); return -1; } @@ -438,7 +462,7 @@ static int accept_from_sock(struct connection *con) result = -ENOMEM; goto accept_err; } - mutex_lock_nested(&newcon->sock_mutex, 1); + down_write(&newcon->sock_sem); if (newcon->sock) { struct connection *othercon = newcon->othercon; @@ -446,45 +470,41 @@ static int accept_from_sock(struct connection *con) othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL); if (!othercon) { printk("dlm: failed to allocate incoming socket\n"); - mutex_unlock(&newcon->sock_mutex); + up_write(&newcon->sock_sem); result = -ENOMEM; goto accept_err; } othercon->nodeid = nodeid; othercon->rx_action = receive_from_sock; - mutex_init(&othercon->sock_mutex); - INIT_WORK(&othercon->swork, process_send_sockets); - INIT_WORK(&othercon->rwork, process_recv_sockets); + init_rwsem(&othercon->sock_sem); set_bit(CF_IS_OTHERCON, &othercon->flags); newcon->othercon = othercon; } othercon->sock = newsock; newsock->sk->sk_user_data = othercon; add_sock(newsock, othercon); - addcon = othercon; } else { newsock->sk->sk_user_data = newcon; newcon->rx_action = receive_from_sock; add_sock(newsock, newcon); - addcon = newcon; + } - mutex_unlock(&newcon->sock_mutex); + up_write(&newcon->sock_sem); /* * Add it to the active queue in case we got data * beween processing the accept adding the socket * to the read_sockets list */ - if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags)) - queue_work(recv_workqueue, &addcon->rwork); - mutex_unlock(&con->sock_mutex); + lowcomms_data_ready(newsock->sk, 0); + up_read(&con->sock_sem); return 0; accept_err: - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); sock_release(newsock); if (result != -EAGAIN) @@ -505,7 +525,7 @@ static void connect_to_sock(struct connection *con) return; } - mutex_lock(&con->sock_mutex); + down_write(&con->sock_sem); if (con->retries++ > MAX_CONNECT_RETRIES) goto out; @@ -528,7 +548,7 @@ static void connect_to_sock(struct connection *con) sock->sk->sk_user_data = con; con->rx_action = receive_from_sock; - make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len); + make_sockaddr(&saddr, dlm_config.tcp_port, &addr_len); add_sock(sock, con); @@ -557,7 +577,7 @@ static void connect_to_sock(struct connection *con) result = 0; } out: - mutex_unlock(&con->sock_mutex); + up_write(&con->sock_sem); return; } @@ -596,10 +616,10 @@ static struct socket *create_listen_sock(struct connection *con, con->sock = sock; /* Bind to our port */ - make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len); + make_sockaddr(saddr, dlm_config.tcp_port, &addr_len); result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len); if (result < 0) { - printk("dlm: Can't bind to port %d\n", dlm_config.ci_tcp_port); + printk("dlm: Can't bind to port %d\n", dlm_config.tcp_port); sock_release(sock); sock = NULL; con->sock = NULL; @@ -618,7 +638,7 @@ static struct socket *create_listen_sock(struct connection *con, result = sock->ops->listen(sock, 5); if (result < 0) { - printk("dlm: Can't listen on port %d\n", dlm_config.ci_tcp_port); + printk("dlm: Can't listen on port %d\n", dlm_config.tcp_port); sock_release(sock); sock = NULL; goto create_out; @@ -689,7 +709,6 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, if (!con) return NULL; - spin_lock(&con->writequeue_lock); e = list_entry(con->writequeue.prev, struct writequeue_entry, list); if ((&e->list == &con->writequeue) || (PAGE_CACHE_SIZE - e->end < len)) { @@ -728,7 +747,6 @@ void dlm_lowcomms_commit_buffer(void *mh) struct connection *con = e->con; int users; - spin_lock(&con->writequeue_lock); users = --e->users; if (users) goto out; @@ -736,8 +754,12 @@ void dlm_lowcomms_commit_buffer(void *mh) kunmap(e->page); spin_unlock(&con->writequeue_lock); - if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) { - queue_work(send_workqueue, &con->swork); + if (test_and_set_bit(CF_WRITE_PENDING, &con->flags) == 0) { + spin_lock_bh(&write_sockets_lock); + list_add_tail(&con->write_list, &write_sockets); + spin_unlock_bh(&write_sockets_lock); + + wake_up_interruptible(&lowcomms_send_waitq); } return; @@ -761,7 +783,7 @@ static void send_to_sock(struct connection *con) struct writequeue_entry *e; int len, offset; - mutex_lock(&con->sock_mutex); + down_read(&con->sock_sem); if (con->sock == NULL) goto out_connect; @@ -778,7 +800,6 @@ static void send_to_sock(struct connection *con) offset = e->offset; BUG_ON(len == 0 && e->users == 0); spin_unlock(&con->writequeue_lock); - kmap(e->page); ret = 0; if (len) { @@ -807,18 +828,18 @@ static void send_to_sock(struct connection *con) } spin_unlock(&con->writequeue_lock); out: - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); return; send_error: - mutex_unlock(&con->sock_mutex); + up_read(&con->sock_sem); close_connection(con, false); lowcomms_connect_sock(con); return; out_connect: - mutex_unlock(&con->sock_mutex); - connect_to_sock(con); + up_read(&con->sock_sem); + lowcomms_connect_sock(con); return; } @@ -851,6 +872,7 @@ int dlm_lowcomms_close(int nodeid) if (con) { clean_one_writequeue(con); close_connection(con, true); + atomic_set(&con->waiting_requests, 0); } return 0; @@ -858,29 +880,102 @@ int dlm_lowcomms_close(int nodeid) return -1; } +/* API send message call, may queue the request */ +/* N.B. This is the old interface - use the new one for new calls */ +int lowcomms_send_message(int nodeid, char *buf, int len, gfp_t allocation) +{ + struct writequeue_entry *e; + char *b; + + e = dlm_lowcomms_get_buffer(nodeid, len, allocation, &b); + if (e) { + memcpy(b, buf, len); + dlm_lowcomms_commit_buffer(e); + return 0; + } + return -ENOBUFS; +} + /* Look for activity on active sockets */ -static void process_recv_sockets(struct work_struct *work) +static void process_sockets(void) { - struct connection *con = container_of(work, struct connection, rwork); - int err; + struct list_head *list; + struct list_head *temp; + int count = 0; + + spin_lock_bh(&read_sockets_lock); + list_for_each_safe(list, temp, &read_sockets) { - clear_bit(CF_READ_PENDING, &con->flags); - do { - err = con->rx_action(con); - } while (!err); + struct connection *con = + list_entry(list, struct connection, read_list); + list_del(&con->read_list); + clear_bit(CF_READ_PENDING, &con->flags); + + spin_unlock_bh(&read_sockets_lock); + + /* This can reach zero if we are processing requests + * as they come in. + */ + if (atomic_read(&con->waiting_requests) == 0) { + spin_lock_bh(&read_sockets_lock); + continue; + } + + do { + con->rx_action(con); + + /* Don't starve out everyone else */ + if (++count >= MAX_RX_MSG_COUNT) { + cond_resched(); + count = 0; + } + + } while (!atomic_dec_and_test(&con->waiting_requests) && + !kthread_should_stop()); + + spin_lock_bh(&read_sockets_lock); + } + spin_unlock_bh(&read_sockets_lock); } +/* Try to send any messages that are pending + */ +static void process_output_queue(void) +{ + struct list_head *list; + struct list_head *temp; + + spin_lock_bh(&write_sockets_lock); + list_for_each_safe(list, temp, &write_sockets) { + struct connection *con = + list_entry(list, struct connection, write_list); + clear_bit(CF_WRITE_PENDING, &con->flags); + list_del(&con->write_list); + + spin_unlock_bh(&write_sockets_lock); + send_to_sock(con); + spin_lock_bh(&write_sockets_lock); + } + spin_unlock_bh(&write_sockets_lock); +} -static void process_send_sockets(struct work_struct *work) +static void process_state_queue(void) { - struct connection *con = container_of(work, struct connection, swork); + struct list_head *list; + struct list_head *temp; + + spin_lock_bh(&state_sockets_lock); + list_for_each_safe(list, temp, &state_sockets) { + struct connection *con = + list_entry(list, struct connection, state_list); + list_del(&con->state_list); + clear_bit(CF_CONNECT_PENDING, &con->flags); + spin_unlock_bh(&state_sockets_lock); - if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) { connect_to_sock(con); + spin_lock_bh(&state_sockets_lock); } - - clear_bit(CF_WRITE_PENDING, &con->flags); - send_to_sock(con); + spin_unlock_bh(&state_sockets_lock); } @@ -897,33 +992,109 @@ static void clean_writequeues(void) } } -static void work_stop(void) +static int read_list_empty(void) { - destroy_workqueue(recv_workqueue); - destroy_workqueue(send_workqueue); + int status; + + spin_lock_bh(&read_sockets_lock); + status = list_empty(&read_sockets); + spin_unlock_bh(&read_sockets_lock); + + return status; +} + +/* DLM Transport comms receive daemon */ +static int dlm_recvd(void *data) +{ + init_waitqueue_entry(&lowcomms_recv_waitq_head, current); + add_wait_queue(&lowcomms_recv_waitq, &lowcomms_recv_waitq_head); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (read_list_empty()) + cond_resched(); + set_current_state(TASK_RUNNING); + + process_sockets(); + } + + return 0; } -static int work_start(void) +static int write_and_state_lists_empty(void) { + int status; + + spin_lock_bh(&write_sockets_lock); + status = list_empty(&write_sockets); + spin_unlock_bh(&write_sockets_lock); + + spin_lock_bh(&state_sockets_lock); + if (list_empty(&state_sockets) == 0) + status = 0; + spin_unlock_bh(&state_sockets_lock); + + return status; +} + +/* DLM Transport send daemon */ +static int dlm_sendd(void *data) +{ + init_waitqueue_entry(&lowcomms_send_waitq_head, current); + add_wait_queue(&lowcomms_send_waitq, &lowcomms_send_waitq_head); + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + if (write_and_state_lists_empty()) + cond_resched(); + set_current_state(TASK_RUNNING); + + process_state_queue(); + process_output_queue(); + } + + return 0; +} + +static void daemons_stop(void) +{ + kthread_stop(recv_task); + kthread_stop(send_task); +} + +static int daemons_start(void) +{ + struct task_struct *p; int error; - recv_workqueue = create_workqueue("dlm_recv"); - error = IS_ERR(recv_workqueue); + + p = kthread_run(dlm_recvd, NULL, "dlm_recvd"); + error = IS_ERR(p); if (error) { - log_print("can't start dlm_recv %d", error); + log_print("can't start dlm_recvd %d", error); return error; } + recv_task = p; - send_workqueue = create_singlethread_workqueue("dlm_send"); - error = IS_ERR(send_workqueue); + p = kthread_run(dlm_sendd, NULL, "dlm_sendd"); + error = IS_ERR(p); if (error) { - log_print("can't start dlm_send %d", error); - destroy_workqueue(recv_workqueue); + log_print("can't start dlm_sendd %d", error); + kthread_stop(recv_task); return error; } + send_task = p; return 0; } +/* + * Return the largest buffer size we can cope with. + */ +int lowcomms_max_buffer_size(void) +{ + return PAGE_CACHE_SIZE; +} + void dlm_lowcomms_stop(void) { int i; @@ -936,7 +1107,7 @@ void dlm_lowcomms_stop(void) connections[i]->flags |= 0xFF; } - work_stop(); + daemons_stop(); clean_writequeues(); for (i = 0; i < conn_array_size; i++) { @@ -988,7 +1159,7 @@ int dlm_lowcomms_start(void) if (error) goto fail_unlisten; - error = work_start(); + error = daemons_start(); if (error) goto fail_unlisten; diff --git a/trunk/fs/dlm/midcomms.c b/trunk/fs/dlm/midcomms.c index a5126e0c68a6..c9b1c3d535f4 100644 --- a/trunk/fs/dlm/midcomms.c +++ b/trunk/fs/dlm/midcomms.c @@ -82,7 +82,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, if (msglen < sizeof(struct dlm_header)) break; err = -E2BIG; - if (msglen > dlm_config.ci_buffer_size) { + if (msglen > dlm_config.buffer_size) { log_print("message size %d from %d too big, buf len %d", msglen, nodeid, len); break; @@ -103,7 +103,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, if (msglen > sizeof(__tmp) && msg == (struct dlm_header *) __tmp) { - msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); + msg = kmalloc(dlm_config.buffer_size, GFP_KERNEL); if (msg == NULL) return ret; } diff --git a/trunk/fs/dlm/rcom.c b/trunk/fs/dlm/rcom.c index 6bfbd6153809..4cc31be9cd9d 100644 --- a/trunk/fs/dlm/rcom.c +++ b/trunk/fs/dlm/rcom.c @@ -56,10 +56,6 @@ static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len, rc->rc_type = type; - spin_lock(&ls->ls_recover_lock); - rc->rc_seq = ls->ls_recover_seq; - spin_unlock(&ls->ls_recover_lock); - *mh_ret = mh; *rc_ret = rc; return 0; @@ -82,17 +78,8 @@ static void make_config(struct dlm_ls *ls, struct rcom_config *rf) rf->rf_lsflags = ls->ls_exflags; } -static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) +static int check_config(struct dlm_ls *ls, struct rcom_config *rf, int nodeid) { - struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; - - if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { - log_error(ls, "version mismatch: %x nodeid %d: %x", - DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid, - rc->rc_header.h_version); - return -EINVAL; - } - if (rf->rf_lvblen != ls->ls_lvblen || rf->rf_lsflags != ls->ls_exflags) { log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", @@ -138,7 +125,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) goto out; allow_sync_reply(ls, &rc->rc_id); - memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); + memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); send_rcom(ls, mh, rc); @@ -154,7 +141,8 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) log_debug(ls, "remote node %d not ready", nodeid); rc->rc_result = 0; } else - error = check_config(ls, rc, nodeid); + error = check_config(ls, (struct rcom_config *) rc->rc_buf, + nodeid); /* the caller looks at rc_result for the remote recovery status */ out: return error; @@ -171,7 +159,6 @@ static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in) if (error) return; rc->rc_id = rc_in->rc_id; - rc->rc_seq_reply = rc_in->rc_seq; rc->rc_result = dlm_recover_status(ls); make_config(ls, (struct rcom_config *) rc->rc_buf); @@ -213,7 +200,7 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) if (nodeid == dlm_our_nodeid()) { dlm_copy_master_names(ls, last_name, last_len, ls->ls_recover_buf + len, - dlm_config.ci_buffer_size - len, nodeid); + dlm_config.buffer_size - len, nodeid); goto out; } @@ -223,7 +210,7 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) memcpy(rc->rc_buf, last_name, last_len); allow_sync_reply(ls, &rc->rc_id); - memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size); + memset(ls->ls_recover_buf, 0, dlm_config.buffer_size); send_rcom(ls, mh, rc); @@ -237,17 +224,30 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in) { struct dlm_rcom *rc; struct dlm_mhandle *mh; - int error, inlen, outlen, nodeid; + int error, inlen, outlen; + int nodeid = rc_in->rc_header.h_nodeid; + uint32_t status = dlm_recover_status(ls); + + /* + * We can't run dlm_dir_rebuild_send (which uses ls_nodes) while + * dlm_recoverd is running ls_nodes_reconfig (which changes ls_nodes). + * It could only happen in rare cases where we get a late NAMES + * message from a previous instance of recovery. + */ + + if (!(status & DLM_RS_NODES)) { + log_debug(ls, "ignoring RCOM_NAMES from %u", nodeid); + return; + } nodeid = rc_in->rc_header.h_nodeid; inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom); - outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom); + outlen = dlm_config.buffer_size - sizeof(struct dlm_rcom); error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh); if (error) return; rc->rc_id = rc_in->rc_id; - rc->rc_seq_reply = rc_in->rc_seq; dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen, nodeid); @@ -294,7 +294,6 @@ static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in) ret_nodeid = error; rc->rc_result = ret_nodeid; rc->rc_id = rc_in->rc_id; - rc->rc_seq_reply = rc_in->rc_seq; send_rcom(ls, mh, rc); } @@ -376,13 +375,20 @@ static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock)); rc->rc_id = rc_in->rc_id; - rc->rc_seq_reply = rc_in->rc_seq; send_rcom(ls, mh, rc); } static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) { + uint32_t status = dlm_recover_status(ls); + + if (!(status & DLM_RS_DIR)) { + log_debug(ls, "ignoring RCOM_LOCK_REPLY from %u", + rc_in->rc_header.h_nodeid); + return; + } + dlm_recover_process_copy(ls, rc_in); } @@ -409,7 +415,6 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) rc->rc_type = DLM_RCOM_STATUS_REPLY; rc->rc_id = rc_in->rc_id; - rc->rc_seq_reply = rc_in->rc_seq; rc->rc_result = -ESRCH; rf = (struct rcom_config *) rc->rc_buf; @@ -421,31 +426,6 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) return 0; } -static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc) -{ - uint64_t seq; - int rv = 0; - - switch (rc->rc_type) { - case DLM_RCOM_STATUS_REPLY: - case DLM_RCOM_NAMES_REPLY: - case DLM_RCOM_LOOKUP_REPLY: - case DLM_RCOM_LOCK_REPLY: - spin_lock(&ls->ls_recover_lock); - seq = ls->ls_recover_seq; - spin_unlock(&ls->ls_recover_lock); - if (rc->rc_seq_reply != seq) { - log_debug(ls, "ignoring old reply %x from %d " - "seq_reply %llx expect %llx", - rc->rc_type, rc->rc_header.h_nodeid, - (unsigned long long)rc->rc_seq_reply, - (unsigned long long)seq); - rv = 1; - } - } - return rv; -} - /* Called by dlm_recvd; corresponds to dlm_receive_message() but special recovery-only comms are sent through here. */ @@ -469,14 +449,11 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) } if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { - log_debug(ls, "ignoring recovery message %x from %d", + log_error(ls, "ignoring recovery message %x from %d", rc->rc_type, nodeid); goto out; } - if (is_old_reply(ls, rc)) - goto out; - if (nodeid != rc->rc_header.h_nodeid) { log_error(ls, "bad rcom nodeid %d from %d", rc->rc_header.h_nodeid, nodeid); diff --git a/trunk/fs/dlm/recover.c b/trunk/fs/dlm/recover.c index c2cc7694cd16..cf9f6831bab5 100644 --- a/trunk/fs/dlm/recover.c +++ b/trunk/fs/dlm/recover.c @@ -44,7 +44,7 @@ static void dlm_wait_timer_fn(unsigned long data) { struct dlm_ls *ls = (struct dlm_ls *) data; - mod_timer(&ls->ls_timer, jiffies + (dlm_config.ci_recover_timer * HZ)); + mod_timer(&ls->ls_timer, jiffies + (dlm_config.recover_timer * HZ)); wake_up(&ls->ls_wait_general); } @@ -55,7 +55,7 @@ int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls)) init_timer(&ls->ls_timer); ls->ls_timer.function = dlm_wait_timer_fn; ls->ls_timer.data = (long) ls; - ls->ls_timer.expires = jiffies + (dlm_config.ci_recover_timer * HZ); + ls->ls_timer.expires = jiffies + (dlm_config.recover_timer * HZ); add_timer(&ls->ls_timer); wait_event(ls->ls_wait_general, testfn(ls) || dlm_recovery_stopped(ls)); @@ -397,9 +397,7 @@ int dlm_recover_masters(struct dlm_ls *ls) if (dlm_no_directory(ls)) count += recover_master_static(r); - else if (!is_master(r) && - (dlm_is_removed(ls, r->res_nodeid) || - rsb_flag(r, RSB_NEW_MASTER))) { + else if (!is_master(r) && dlm_is_removed(ls, r->res_nodeid)) { recover_master(r); count++; } diff --git a/trunk/fs/dlm/recoverd.c b/trunk/fs/dlm/recoverd.c index 3cb636d60249..650536aa5139 100644 --- a/trunk/fs/dlm/recoverd.c +++ b/trunk/fs/dlm/recoverd.c @@ -77,7 +77,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_members(ls, rv, &neg); if (error) { - log_debug(ls, "recover_members failed %d", error); + log_error(ls, "recover_members failed %d", error); goto fail; } start = jiffies; @@ -89,7 +89,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_directory(ls); if (error) { - log_debug(ls, "recover_directory failed %d", error); + log_error(ls, "recover_directory failed %d", error); goto fail; } @@ -99,7 +99,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_directory_wait(ls); if (error) { - log_debug(ls, "recover_directory_wait failed %d", error); + log_error(ls, "recover_directory_wait failed %d", error); goto fail; } @@ -129,7 +129,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_masters(ls); if (error) { - log_debug(ls, "recover_masters failed %d", error); + log_error(ls, "recover_masters failed %d", error); goto fail; } @@ -139,13 +139,13 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_locks(ls); if (error) { - log_debug(ls, "recover_locks failed %d", error); + log_error(ls, "recover_locks failed %d", error); goto fail; } error = dlm_recover_locks_wait(ls); if (error) { - log_debug(ls, "recover_locks_wait failed %d", error); + log_error(ls, "recover_locks_wait failed %d", error); goto fail; } @@ -166,7 +166,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = dlm_recover_locks_wait(ls); if (error) { - log_debug(ls, "recover_locks_wait failed %d", error); + log_error(ls, "recover_locks_wait failed %d", error); goto fail; } } @@ -184,7 +184,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) dlm_set_recover_status(ls, DLM_RS_DONE); error = dlm_recover_done_wait(ls); if (error) { - log_debug(ls, "recover_done_wait failed %d", error); + log_error(ls, "recover_done_wait failed %d", error); goto fail; } @@ -192,19 +192,19 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) error = enable_locking(ls, rv->seq); if (error) { - log_debug(ls, "enable_locking failed %d", error); + log_error(ls, "enable_locking failed %d", error); goto fail; } error = dlm_process_requestqueue(ls); if (error) { - log_debug(ls, "process_requestqueue failed %d", error); + log_error(ls, "process_requestqueue failed %d", error); goto fail; } error = dlm_recover_waiters_post(ls); if (error) { - log_debug(ls, "recover_waiters_post failed %d", error); + log_error(ls, "recover_waiters_post failed %d", error); goto fail; } diff --git a/trunk/fs/dlm/user.c b/trunk/fs/dlm/user.c index d378b7fe2a1e..c37e93e4f2df 100644 --- a/trunk/fs/dlm/user.c +++ b/trunk/fs/dlm/user.c @@ -180,14 +180,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue)) remove_ownqueue = 1; - /* unlocks or cancels of waiting requests need to be removed from the - proc's unlocking list, again there must be a better way... */ - - if (ua->lksb.sb_status == -DLM_EUNLOCK || - (ua->lksb.sb_status == -DLM_ECANCEL && - lkb->lkb_grmode == DLM_LOCK_IV)) - remove_ownqueue = 1; - /* We want to copy the lvb to userspace when the completion ast is read if the status is 0, the lock has an lvb and lvb_ops says we should. We could probably have set_lvb_lock() @@ -531,7 +523,6 @@ static int device_open(struct inode *inode, struct file *file) proc->lockspace = ls->ls_local_handle; INIT_LIST_HEAD(&proc->asts); INIT_LIST_HEAD(&proc->locks); - INIT_LIST_HEAD(&proc->unlocking); spin_lock_init(&proc->asts_spin); spin_lock_init(&proc->locks_spin); init_waitqueue_head(&proc->wait); diff --git a/trunk/fs/dlm/util.c b/trunk/fs/dlm/util.c index 963889cf6740..767197db9944 100644 --- a/trunk/fs/dlm/util.c +++ b/trunk/fs/dlm/util.c @@ -134,8 +134,6 @@ void dlm_rcom_out(struct dlm_rcom *rc) rc->rc_type = cpu_to_le32(rc->rc_type); rc->rc_result = cpu_to_le32(rc->rc_result); rc->rc_id = cpu_to_le64(rc->rc_id); - rc->rc_seq = cpu_to_le64(rc->rc_seq); - rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply); if (type == DLM_RCOM_LOCK) rcom_lock_out((struct rcom_lock *) rc->rc_buf); @@ -153,8 +151,6 @@ void dlm_rcom_in(struct dlm_rcom *rc) rc->rc_type = le32_to_cpu(rc->rc_type); rc->rc_result = le32_to_cpu(rc->rc_result); rc->rc_id = le64_to_cpu(rc->rc_id); - rc->rc_seq = le64_to_cpu(rc->rc_seq); - rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply); if (rc->rc_type == DLM_RCOM_LOCK) rcom_lock_in((struct rcom_lock *) rc->rc_buf); diff --git a/trunk/fs/gfs2/Kconfig b/trunk/fs/gfs2/Kconfig index de8e64c03f73..6a2ffa2db14f 100644 --- a/trunk/fs/gfs2/Kconfig +++ b/trunk/fs/gfs2/Kconfig @@ -4,43 +4,44 @@ config GFS2_FS select FS_POSIX_ACL select CRC32 help - A cluster filesystem. + A cluster filesystem. - Allows a cluster of computers to simultaneously use a block device - that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads - and writes to the block device like a local filesystem, but also uses - a lock module to allow the computers coordinate their I/O so - filesystem consistency is maintained. One of the nifty features of - GFS is perfect consistency -- changes made to the filesystem on one - machine show up immediately on all other machines in the cluster. + Allows a cluster of computers to simultaneously use a block device + that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads + and writes to the block device like a local filesystem, but also uses + a lock module to allow the computers coordinate their I/O so + filesystem consistency is maintained. One of the nifty features of + GFS is perfect consistency -- changes made to the filesystem on one + machine show up immediately on all other machines in the cluster. - To use the GFS2 filesystem, you will need to enable one or more of - the below locking modules. Documentation and utilities for GFS2 can - be found here: http://sources.redhat.com/cluster + To use the GFS2 filesystem, you will need to enable one or more of + the below locking modules. Documentation and utilities for GFS2 can + be found here: http://sources.redhat.com/cluster config GFS2_FS_LOCKING_NOLOCK tristate "GFS2 \"nolock\" locking module" depends on GFS2_FS help - Single node locking module for GFS2. + Single node locking module for GFS2. - Use this module if you want to use GFS2 on a single node without - its clustering features. You can still take advantage of the - large file support, and upgrade to running a full cluster later on - if required. + Use this module if you want to use GFS2 on a single node without + its clustering features. You can still take advantage of the + large file support, and upgrade to running a full cluster later on + if required. - If you will only be using GFS2 in cluster mode, you do not need this - module. + If you will only be using GFS2 in cluster mode, you do not need this + module. config GFS2_FS_LOCKING_DLM tristate "GFS2 DLM locking module" - depends on GFS2_FS && SYSFS && NET && INET && (IPV6 || IPV6=n) + depends on GFS2_FS && NET && INET && (IPV6 || IPV6=n) select IP_SCTP if DLM_SCTP select CONFIGFS_FS select DLM help - Multiple node locking module for GFS2 + Multiple node locking module for GFS2 + + Most users of GFS2 will require this module. It provides the locking + interface between GFS2 and the DLM, which is required to use GFS2 + in a cluster environment. - Most users of GFS2 will require this module. It provides the locking - interface between GFS2 and the DLM, which is required to use GFS2 - in a cluster environment. diff --git a/trunk/fs/gfs2/bmap.c b/trunk/fs/gfs2/bmap.c index 113f6c9110c7..8240c1ff94f4 100644 --- a/trunk/fs/gfs2/bmap.c +++ b/trunk/fs/gfs2/bmap.c @@ -773,7 +773,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, gfs2_free_data(ip, bstart, blen); } - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, dibh->b_data); @@ -848,7 +848,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size) } ip->i_di.di_size = size; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); error = gfs2_meta_inode_buffer(ip, &dibh); if (error) @@ -963,7 +963,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) if (gfs2_is_stuffed(ip)) { ip->i_di.di_size = size; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size); @@ -975,7 +975,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) if (!error) { ip->i_di.di_size = size; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1048,7 +1048,7 @@ static int trunc_end(struct gfs2_inode *ip) ip->i_num.no_addr; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); } - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); diff --git a/trunk/fs/gfs2/dir.c b/trunk/fs/gfs2/dir.c index c93ca8f361b5..0fdcb7713cd9 100644 --- a/trunk/fs/gfs2/dir.c +++ b/trunk/fs/gfs2/dir.c @@ -131,7 +131,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); if (ip->i_di.di_size < offset + size) ip->i_di.di_size = offset + size; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -229,7 +229,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, if (ip->i_di.di_size < offset + copied) ip->i_di.di_size = offset + copied; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -1198,11 +1198,12 @@ static int compare_dents(const void *a, const void *b) */ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, - void *opaque, filldir_t filldir, + void *opaque, gfs2_filldir_t filldir, const struct gfs2_dirent **darr, u32 entries, int *copied) { const struct gfs2_dirent *dent, *dent_next; + struct gfs2_inum_host inum; u64 off, off_next; unsigned int x, y; int run = 0; @@ -1239,9 +1240,11 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, *offset = off; } + gfs2_inum_in(&inum, (char *)&dent->de_inum); + error = filldir(opaque, (const char *)(dent + 1), be16_to_cpu(dent->de_name_len), - off, be64_to_cpu(dent->de_inum.no_addr), + off, &inum, be16_to_cpu(dent->de_type)); if (error) return 1; @@ -1259,8 +1262,8 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, } static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, - filldir_t filldir, int *copied, unsigned *depth, - u64 leaf_no) + gfs2_filldir_t filldir, int *copied, + unsigned *depth, u64 leaf_no) { struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *bh; @@ -1340,7 +1343,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, */ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, - filldir_t filldir) + gfs2_filldir_t filldir) { struct gfs2_inode *dip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); @@ -1399,7 +1402,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, } int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, - filldir_t filldir) + gfs2_filldir_t filldir) { struct gfs2_inode *dip = GFS2_I(inode); struct dirent_gather g; @@ -1565,7 +1568,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, break; gfs2_trans_add_bh(ip->i_gl, bh, 1); ip->i_di.di_entries++; - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; @@ -1651,7 +1654,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) gfs2_consist_inode(dip); gfs2_trans_add_bh(dip->i_gl, bh, 1); dip->i_di.di_entries--; - dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1699,7 +1702,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, gfs2_trans_add_bh(dip->i_gl, bh, 1); } - dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; + dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; diff --git a/trunk/fs/gfs2/dir.h b/trunk/fs/gfs2/dir.h index 48fe89046bba..b21b33668a5b 100644 --- a/trunk/fs/gfs2/dir.h +++ b/trunk/fs/gfs2/dir.h @@ -16,13 +16,30 @@ struct inode; struct gfs2_inode; struct gfs2_inum; +/** + * gfs2_filldir_t - Report a directory entry to the caller of gfs2_dir_read() + * @opaque: opaque data used by the function + * @name: the name of the directory entry + * @length: the length of the name + * @offset: the entry's offset in the directory + * @inum: the inode number the entry points to + * @type: the type of inode the entry points to + * + * Returns: 0 on success, 1 if buffer full + */ + +typedef int (*gfs2_filldir_t) (void *opaque, + const char *name, unsigned int length, + u64 offset, + struct gfs2_inum_host *inum, unsigned int type); + int gfs2_dir_search(struct inode *dir, const struct qstr *filename, struct gfs2_inum_host *inum, unsigned int *type); int gfs2_dir_add(struct inode *inode, const struct qstr *filename, const struct gfs2_inum_host *inum, unsigned int type); int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); -int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, - filldir_t filldir); +int gfs2_dir_read(struct inode *inode, u64 * offset, void *opaque, + gfs2_filldir_t filldir); int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, struct gfs2_inum_host *new_inum, unsigned int new_type); diff --git a/trunk/fs/gfs2/eattr.c b/trunk/fs/gfs2/eattr.c index 0c83c7f4dda8..ebebbdcd7057 100644 --- a/trunk/fs/gfs2/eattr.c +++ b/trunk/fs/gfs2/eattr.c @@ -301,7 +301,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -718,7 +718,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, (er->er_mode & S_IFMT)); ip->i_inode.i_mode = er->er_mode; } - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -853,7 +853,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT)); ip->i_inode.i_mode = er->er_mode; } - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1134,7 +1134,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); diff --git a/trunk/fs/gfs2/glock.c b/trunk/fs/gfs2/glock.c index 6618c1190252..438146904b58 100644 --- a/trunk/fs/gfs2/glock.c +++ b/trunk/fs/gfs2/glock.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include "gfs2.h" @@ -35,6 +33,11 @@ #include "super.h" #include "util.h" +struct greedy { + struct gfs2_holder gr_gh; + struct delayed_work gr_work; +}; + struct gfs2_gl_hash_bucket { struct hlist_head hb_list; }; @@ -44,9 +47,6 @@ typedef void (*glock_examiner) (struct gfs2_glock * gl); static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); static int dump_glock(struct gfs2_glock *gl); static int dump_inode(struct gfs2_inode *ip); -static void gfs2_glock_xmote_th(struct gfs2_holder *gh); -static void gfs2_glock_drop_th(struct gfs2_glock *gl); -static DECLARE_RWSEM(gfs2_umount_flush_sem); #define GFS2_GL_HASH_SHIFT 15 #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) @@ -212,6 +212,30 @@ int gfs2_glock_put(struct gfs2_glock *gl) return rv; } +/** + * queue_empty - check to see if a glock's queue is empty + * @gl: the glock + * @head: the head of the queue to check + * + * This function protects the list in the event that a process already + * has a holder on the list and is adding a second holder for itself. + * The glmutex lock is what generally prevents processes from working + * on the same glock at once, but the special case of adding a second + * holder for yourself ("recursive" locking) doesn't involve locking + * glmutex, making the spin lock necessary. + * + * Returns: 1 if the queue is empty + */ + +static inline int queue_empty(struct gfs2_glock *gl, struct list_head *head) +{ + int empty; + spin_lock(&gl->gl_spin); + empty = list_empty(head); + spin_unlock(&gl->gl_spin); + return empty; +} + /** * search_bucket() - Find struct gfs2_glock by lock number * @bucket: the bucket to search @@ -371,6 +395,11 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, gh->gh_flags = flags; gh->gh_error = 0; gh->gh_iflags = 0; + init_completion(&gh->gh_wait); + + if (gh->gh_state == LM_ST_EXCLUSIVE) + gh->gh_flags |= GL_LOCAL_EXCL; + gfs2_glock_hold(gl); } @@ -388,6 +417,9 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder * { gh->gh_state = state; gh->gh_flags = flags; + if (gh->gh_state == LM_ST_EXCLUSIVE) + gh->gh_flags |= GL_LOCAL_EXCL; + gh->gh_iflags &= 1 << HIF_ALLOCED; gh->gh_ip = (unsigned long)__builtin_return_address(0); } @@ -447,29 +479,6 @@ static void gfs2_holder_put(struct gfs2_holder *gh) kfree(gh); } -static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh) -{ - if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) { - gfs2_holder_put(gh); - return; - } - clear_bit(HIF_WAIT, &gh->gh_iflags); - smp_mb(); - wake_up_bit(&gh->gh_iflags, HIF_WAIT); -} - -static int holder_wait(void *word) -{ - schedule(); - return 0; -} - -static void wait_on_holder(struct gfs2_holder *gh) -{ - might_sleep(); - wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE); -} - /** * rq_mutex - process a mutex request in the queue * @gh: the glock holder @@ -484,9 +493,7 @@ static int rq_mutex(struct gfs2_holder *gh) list_del_init(&gh->gh_list); /* gh->gh_error never examined. */ set_bit(GLF_LOCK, &gl->gl_flags); - clear_bit(HIF_WAIT, &gh->gh_iflags); - smp_mb(); - wake_up_bit(&gh->gh_iflags, HIF_WAIT); + complete(&gh->gh_wait); return 1; } @@ -504,6 +511,7 @@ static int rq_promote(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; struct gfs2_sbd *sdp = gl->gl_sbd; + const struct gfs2_glock_operations *glops = gl->gl_ops; if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) { if (list_empty(&gl->gl_holders)) { @@ -518,7 +526,7 @@ static int rq_promote(struct gfs2_holder *gh) gfs2_reclaim_glock(sdp); } - gfs2_glock_xmote_th(gh); + glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags); spin_lock(&gl->gl_spin); } return 1; @@ -529,11 +537,11 @@ static int rq_promote(struct gfs2_holder *gh) set_bit(GLF_LOCK, &gl->gl_flags); } else { struct gfs2_holder *next_gh; - if (gh->gh_state == LM_ST_EXCLUSIVE) + if (gh->gh_flags & GL_LOCAL_EXCL) return 1; next_gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); - if (next_gh->gh_state == LM_ST_EXCLUSIVE) + if (next_gh->gh_flags & GL_LOCAL_EXCL) return 1; } @@ -541,7 +549,7 @@ static int rq_promote(struct gfs2_holder *gh) gh->gh_error = 0; set_bit(HIF_HOLDER, &gh->gh_iflags); - gfs2_holder_dispose_or_wake(gh); + complete(&gh->gh_wait); return 0; } @@ -556,6 +564,7 @@ static int rq_promote(struct gfs2_holder *gh) static int rq_demote(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; + const struct gfs2_glock_operations *glops = gl->gl_ops; if (!list_empty(&gl->gl_holders)) return 1; @@ -564,7 +573,10 @@ static int rq_demote(struct gfs2_holder *gh) list_del_init(&gh->gh_list); gh->gh_error = 0; spin_unlock(&gl->gl_spin); - gfs2_holder_dispose_or_wake(gh); + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs2_holder_put(gh); + else + complete(&gh->gh_wait); spin_lock(&gl->gl_spin); } else { gl->gl_req_gh = gh; @@ -573,9 +585,9 @@ static int rq_demote(struct gfs2_holder *gh) if (gh->gh_state == LM_ST_UNLOCKED || gl->gl_state != LM_ST_EXCLUSIVE) - gfs2_glock_drop_th(gl); + glops->go_drop_th(gl); else - gfs2_glock_xmote_th(gh); + glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags); spin_lock(&gl->gl_spin); } @@ -583,6 +595,30 @@ static int rq_demote(struct gfs2_holder *gh) return 0; } +/** + * rq_greedy - process a queued request to drop greedy status + * @gh: the glock holder + * + * Returns: 1 if the queue is blocked + */ + +static int rq_greedy(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + list_del_init(&gh->gh_list); + /* gh->gh_error never examined. */ + clear_bit(GLF_GREEDY, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + gfs2_holder_uninit(gh); + kfree(container_of(gh, struct greedy, gr_gh)); + + spin_lock(&gl->gl_spin); + + return 0; +} + /** * run_queue - process holder structures on a glock * @gl: the glock @@ -613,6 +649,8 @@ static void run_queue(struct gfs2_glock *gl) if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) blocked = rq_demote(gh); + else if (test_bit(HIF_GREEDY, &gh->gh_iflags)) + blocked = rq_greedy(gh); else gfs2_assert_warn(gl->gl_sbd, 0); @@ -646,8 +684,6 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl) gfs2_holder_init(gl, 0, 0, &gh); set_bit(HIF_MUTEX, &gh.gh_iflags); - if (test_and_set_bit(HIF_WAIT, &gh.gh_iflags)) - BUG(); spin_lock(&gl->gl_spin); if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { @@ -655,13 +691,11 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl) } else { gl->gl_owner = current; gl->gl_ip = (unsigned long)__builtin_return_address(0); - clear_bit(HIF_WAIT, &gh.gh_iflags); - smp_mb(); - wake_up_bit(&gh.gh_iflags, HIF_WAIT); + complete(&gh.gh_wait); } spin_unlock(&gl->gl_spin); - wait_on_holder(&gh); + wait_for_completion(&gh.gh_wait); gfs2_holder_uninit(&gh); } @@ -740,7 +774,6 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state) return; set_bit(HIF_DEMOTE, &new_gh->gh_iflags); set_bit(HIF_DEALLOC, &new_gh->gh_iflags); - set_bit(HIF_WAIT, &new_gh->gh_iflags); goto restart; } @@ -792,7 +825,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) int op_done = 1; gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); - gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); + gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC)); state_change(gl, ret & LM_OUT_ST_MASK); @@ -875,8 +908,12 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) gfs2_glock_put(gl); - if (gh) - gfs2_holder_dispose_or_wake(gh); + if (gh) { + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs2_holder_put(gh); + else + complete(&gh->gh_wait); + } } /** @@ -887,26 +924,23 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) * */ -void gfs2_glock_xmote_th(struct gfs2_holder *gh) +void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags) { - struct gfs2_glock *gl = gh->gh_gl; struct gfs2_sbd *sdp = gl->gl_sbd; - int flags = gh->gh_flags; - unsigned state = gh->gh_state; const struct gfs2_glock_operations *glops = gl->gl_ops; int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP | LM_FLAG_ANY | LM_FLAG_PRIORITY); unsigned int lck_ret; - if (glops->go_xmote_th) - glops->go_xmote_th(gl); - gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); - gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); + gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); gfs2_assert_warn(sdp, state != LM_ST_UNLOCKED); gfs2_assert_warn(sdp, state != gl->gl_state); + if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync) + glops->go_sync(gl); + gfs2_glock_hold(gl); gl->gl_req_bh = xmote_bh; @@ -937,8 +971,10 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) const struct gfs2_glock_operations *glops = gl->gl_ops; struct gfs2_holder *gh = gl->gl_req_gh; + clear_bit(GLF_PREFETCH, &gl->gl_flags); + gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); - gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); + gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); gfs2_assert_warn(sdp, !ret); state_change(gl, LM_ST_UNLOCKED); @@ -965,8 +1001,12 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) gfs2_glock_put(gl); - if (gh) - gfs2_holder_dispose_or_wake(gh); + if (gh) { + if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) + gfs2_holder_put(gh); + else + complete(&gh->gh_wait); + } } /** @@ -975,19 +1015,19 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) * */ -static void gfs2_glock_drop_th(struct gfs2_glock *gl) +void gfs2_glock_drop_th(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_sbd; const struct gfs2_glock_operations *glops = gl->gl_ops; unsigned int ret; - if (glops->go_drop_th) - glops->go_drop_th(gl); - gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); - gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); + gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders)); gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED); + if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync) + glops->go_sync(gl); + gfs2_glock_hold(gl); gl->gl_req_bh = drop_bh; @@ -1067,7 +1107,8 @@ static int glock_wait_internal(struct gfs2_holder *gh) if (gh->gh_flags & LM_FLAG_PRIORITY) do_cancels(gh); - wait_on_holder(gh); + wait_for_completion(&gh->gh_wait); + if (gh->gh_error) return gh->gh_error; @@ -1123,8 +1164,6 @@ static void add_to_queue(struct gfs2_holder *gh) struct gfs2_holder *existing; BUG_ON(!gh->gh_owner); - if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) - BUG(); existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner); if (existing) { @@ -1188,6 +1227,8 @@ int gfs2_glock_nq(struct gfs2_holder *gh) } } + clear_bit(GLF_PREFETCH, &gl->gl_flags); + return error; } @@ -1279,6 +1320,98 @@ void gfs2_glock_dq(struct gfs2_holder *gh) spin_unlock(&gl->gl_spin); } +/** + * gfs2_glock_prefetch - Try to prefetch a glock + * @gl: the glock + * @state: the state to prefetch in + * @flags: flags passed to go_xmote_th() + * + */ + +static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state, + int flags) +{ + const struct gfs2_glock_operations *glops = gl->gl_ops; + + spin_lock(&gl->gl_spin); + + if (test_bit(GLF_LOCK, &gl->gl_flags) || !list_empty(&gl->gl_holders) || + !list_empty(&gl->gl_waiters1) || !list_empty(&gl->gl_waiters2) || + !list_empty(&gl->gl_waiters3) || + relaxed_state_ok(gl->gl_state, state, flags)) { + spin_unlock(&gl->gl_spin); + return; + } + + set_bit(GLF_PREFETCH, &gl->gl_flags); + set_bit(GLF_LOCK, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + + glops->go_xmote_th(gl, state, flags); +} + +static void greedy_work(struct work_struct *work) +{ + struct greedy *gr = container_of(work, struct greedy, gr_work.work); + struct gfs2_holder *gh = &gr->gr_gh; + struct gfs2_glock *gl = gh->gh_gl; + const struct gfs2_glock_operations *glops = gl->gl_ops; + + clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); + + if (glops->go_greedy) + glops->go_greedy(gl); + + spin_lock(&gl->gl_spin); + + if (list_empty(&gl->gl_waiters2)) { + clear_bit(GLF_GREEDY, &gl->gl_flags); + spin_unlock(&gl->gl_spin); + gfs2_holder_uninit(gh); + kfree(gr); + } else { + gfs2_glock_hold(gl); + list_add_tail(&gh->gh_list, &gl->gl_waiters2); + run_queue(gl); + spin_unlock(&gl->gl_spin); + gfs2_glock_put(gl); + } +} + +/** + * gfs2_glock_be_greedy - + * @gl: + * @time: + * + * Returns: 0 if go_greedy will be called, 1 otherwise + */ + +int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time) +{ + struct greedy *gr; + struct gfs2_holder *gh; + + if (!time || gl->gl_sbd->sd_args.ar_localcaching || + test_and_set_bit(GLF_GREEDY, &gl->gl_flags)) + return 1; + + gr = kmalloc(sizeof(struct greedy), GFP_KERNEL); + if (!gr) { + clear_bit(GLF_GREEDY, &gl->gl_flags); + return 1; + } + gh = &gr->gr_gh; + + gfs2_holder_init(gl, 0, 0, gh); + set_bit(HIF_GREEDY, &gh->gh_iflags); + INIT_DELAYED_WORK(&gr->gr_work, greedy_work); + + set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); + schedule_delayed_work(&gr->gr_work, time); + + return 0; +} + /** * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it * @gh: the holder structure @@ -1337,7 +1470,10 @@ static int glock_compare(const void *arg_a, const void *arg_b) return 1; if (a->ln_number < b->ln_number) return -1; - BUG_ON(gh_a->gh_gl->gl_ops->go_type == gh_b->gh_gl->gl_ops->go_type); + if (gh_a->gh_state == LM_ST_SHARED && gh_b->gh_state == LM_ST_EXCLUSIVE) + return 1; + if (!(gh_a->gh_flags & GL_LOCAL_EXCL) && (gh_b->gh_flags & GL_LOCAL_EXCL)) + return 1; return 0; } @@ -1481,6 +1617,34 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs) gfs2_glock_dq_uninit(&ghs[x]); } +/** + * gfs2_glock_prefetch_num - prefetch a glock based on lock number + * @sdp: the filesystem + * @number: the lock number + * @glops: the glock operations for the type of glock + * @state: the state to acquire the glock in + * @flags: modifier flags for the aquisition + * + * Returns: errno + */ + +void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number, + const struct gfs2_glock_operations *glops, + unsigned int state, int flags) +{ + struct gfs2_glock *gl; + int error; + + if (atomic_read(&sdp->sd_reclaim_count) < + gfs2_tune_get(sdp, gt_reclaim_limit)) { + error = gfs2_glock_get(sdp, number, glops, CREATE, &gl); + if (!error) { + gfs2_glock_prefetch(gl, state, flags); + gfs2_glock_put(gl); + } + } +} + /** * gfs2_lvb_hold - attach a LVB from a glock * @gl: The glock in question @@ -1539,6 +1703,8 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, if (!gl) return; + if (gl->gl_ops->go_callback) + gl->gl_ops->go_callback(gl, state); handle_callback(gl, state); spin_lock(&gl->gl_spin); @@ -1580,14 +1746,12 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data) struct lm_async_cb *async = data; struct gfs2_glock *gl; - down_read(&gfs2_umount_flush_sem); gl = gfs2_glock_find(sdp, &async->lc_name); if (gfs2_assert_warn(sdp, gl)) return; if (!gfs2_assert_warn(sdp, gl->gl_req_bh)) gl->gl_req_bh(gl, async->lc_ret); gfs2_glock_put(gl); - up_read(&gfs2_umount_flush_sem); return; } @@ -1617,11 +1781,15 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data) static int demote_ok(struct gfs2_glock *gl) { + struct gfs2_sbd *sdp = gl->gl_sbd; const struct gfs2_glock_operations *glops = gl->gl_ops; int demote = 1; if (test_bit(GLF_STICKY, &gl->gl_flags)) demote = 0; + else if (test_bit(GLF_PREFETCH, &gl->gl_flags)) + demote = time_after_eq(jiffies, gl->gl_stamp + + gfs2_tune_get(sdp, gt_prefetch_secs) * HZ); else if (glops->go_demote_ok) demote = glops->go_demote_ok(gl); @@ -1677,7 +1845,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp) atomic_inc(&sdp->sd_reclaimed); if (gfs2_glmutex_trylock(gl)) { - if (list_empty(&gl->gl_holders) && + if (queue_empty(gl, &gl->gl_holders) && gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) handle_callback(gl, LM_ST_UNLOCKED); gfs2_glmutex_unlock(gl); @@ -1741,7 +1909,7 @@ static void scan_glock(struct gfs2_glock *gl) return; if (gfs2_glmutex_trylock(gl)) { - if (list_empty(&gl->gl_holders) && + if (queue_empty(gl, &gl->gl_holders) && gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) goto out_schedule; gfs2_glmutex_unlock(gl); @@ -1790,7 +1958,7 @@ static void clear_glock(struct gfs2_glock *gl) } if (gfs2_glmutex_trylock(gl)) { - if (list_empty(&gl->gl_holders) && + if (queue_empty(gl, &gl->gl_holders) && gl->gl_state != LM_ST_UNLOCKED) handle_callback(gl, LM_ST_UNLOCKED); gfs2_glmutex_unlock(gl); @@ -1832,9 +2000,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait) t = jiffies; } - down_write(&gfs2_umount_flush_sem); invalidate_inodes(sdp->sd_vfs); - up_write(&gfs2_umount_flush_sem); msleep(10); } } diff --git a/trunk/fs/gfs2/glock.h b/trunk/fs/gfs2/glock.h index f50e40ceca43..fb39108fc05c 100644 --- a/trunk/fs/gfs2/glock.h +++ b/trunk/fs/gfs2/glock.h @@ -20,6 +20,7 @@ #define LM_FLAG_ANY 0x00000008 #define LM_FLAG_PRIORITY 0x00000010 */ +#define GL_LOCAL_EXCL 0x00000020 #define GL_ASYNC 0x00000040 #define GL_EXACT 0x00000080 #define GL_SKIP 0x00000100 @@ -82,11 +83,17 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *gh); void gfs2_holder_uninit(struct gfs2_holder *gh); + +void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags); +void gfs2_glock_drop_th(struct gfs2_glock *gl); + int gfs2_glock_nq(struct gfs2_holder *gh); int gfs2_glock_poll(struct gfs2_holder *gh); int gfs2_glock_wait(struct gfs2_holder *gh); void gfs2_glock_dq(struct gfs2_holder *gh); +int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time); + void gfs2_glock_dq_uninit(struct gfs2_holder *gh); int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number, const struct gfs2_glock_operations *glops, @@ -96,6 +103,10 @@ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs); void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs); void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs); +void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number, + const struct gfs2_glock_operations *glops, + unsigned int state, int flags); + /** * gfs2_glock_nq_init - intialize a holder and enqueue it on a glock * @gl: the glock diff --git a/trunk/fs/gfs2/glops.c b/trunk/fs/gfs2/glops.c index c4b0391b7aa2..b068d10bcb6e 100644 --- a/trunk/fs/gfs2/glops.c +++ b/trunk/fs/gfs2/glops.c @@ -117,14 +117,12 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) static void meta_go_sync(struct gfs2_glock *gl) { - if (gl->gl_state != LM_ST_EXCLUSIVE) - return; - if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { gfs2_log_flush(gl->gl_sbd, gl); gfs2_meta_sync(gl); gfs2_ail_empty_gl(gl); } + } /** @@ -143,37 +141,6 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) gl->gl_vn++; } -/** - * inode_go_sync - Sync the dirty data and/or metadata for an inode glock - * @gl: the glock protecting the inode - * - */ - -static void inode_go_sync(struct gfs2_glock *gl) -{ - struct gfs2_inode *ip = gl->gl_object; - - if (ip && !S_ISREG(ip->i_inode.i_mode)) - ip = NULL; - - if (test_bit(GLF_DIRTY, &gl->gl_flags)) { - gfs2_log_flush(gl->gl_sbd, gl); - if (ip) - filemap_fdatawrite(ip->i_inode.i_mapping); - gfs2_meta_sync(gl); - if (ip) { - struct address_space *mapping = ip->i_inode.i_mapping; - int error = filemap_fdatawait(mapping); - if (error == -ENOSPC) - set_bit(AS_ENOSPC, &mapping->flags); - else if (error) - set_bit(AS_EIO, &mapping->flags); - } - clear_bit(GLF_DIRTY, &gl->gl_flags); - gfs2_ail_empty_gl(gl); - } -} - /** * inode_go_xmote_th - promote/demote a glock * @gl: the glock @@ -182,12 +149,12 @@ static void inode_go_sync(struct gfs2_glock *gl) * */ -static void inode_go_xmote_th(struct gfs2_glock *gl) +static void inode_go_xmote_th(struct gfs2_glock *gl, unsigned int state, + int flags) { if (gl->gl_state != LM_ST_UNLOCKED) gfs2_pte_inval(gl); - if (gl->gl_state == LM_ST_EXCLUSIVE) - inode_go_sync(gl); + gfs2_glock_xmote_th(gl, state, flags); } /** @@ -222,8 +189,38 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl) static void inode_go_drop_th(struct gfs2_glock *gl) { gfs2_pte_inval(gl); - if (gl->gl_state == LM_ST_EXCLUSIVE) - inode_go_sync(gl); + gfs2_glock_drop_th(gl); +} + +/** + * inode_go_sync - Sync the dirty data and/or metadata for an inode glock + * @gl: the glock protecting the inode + * + */ + +static void inode_go_sync(struct gfs2_glock *gl) +{ + struct gfs2_inode *ip = gl->gl_object; + + if (ip && !S_ISREG(ip->i_inode.i_mode)) + ip = NULL; + + if (test_bit(GLF_DIRTY, &gl->gl_flags)) { + gfs2_log_flush(gl->gl_sbd, gl); + if (ip) + filemap_fdatawrite(ip->i_inode.i_mapping); + gfs2_meta_sync(gl); + if (ip) { + struct address_space *mapping = ip->i_inode.i_mapping; + int error = filemap_fdatawait(mapping); + if (error == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + else if (error) + set_bit(AS_EIO, &mapping->flags); + } + clear_bit(GLF_DIRTY, &gl->gl_flags); + gfs2_ail_empty_gl(gl); + } } /** @@ -298,7 +295,7 @@ static int inode_go_lock(struct gfs2_holder *gh) if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) && (gl->gl_state == LM_ST_EXCLUSIVE) && - (gh->gh_state == LM_ST_EXCLUSIVE)) + (gh->gh_flags & GL_LOCAL_EXCL)) error = gfs2_truncatei_resume(ip); return error; @@ -321,6 +318,39 @@ static void inode_go_unlock(struct gfs2_holder *gh) gfs2_meta_cache_flush(ip); } +/** + * inode_greedy - + * @gl: the glock + * + */ + +static void inode_greedy(struct gfs2_glock *gl) +{ + struct gfs2_sbd *sdp = gl->gl_sbd; + struct gfs2_inode *ip = gl->gl_object; + unsigned int quantum = gfs2_tune_get(sdp, gt_greedy_quantum); + unsigned int max = gfs2_tune_get(sdp, gt_greedy_max); + unsigned int new_time; + + spin_lock(&ip->i_spin); + + if (time_after(ip->i_last_pfault + quantum, jiffies)) { + new_time = ip->i_greedy + quantum; + if (new_time > max) + new_time = max; + } else { + new_time = ip->i_greedy - quantum; + if (!new_time || new_time > max) + new_time = 1; + } + + ip->i_greedy = new_time; + + spin_unlock(&ip->i_spin); + + iput(&ip->i_inode); +} + /** * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock * @gl: the glock @@ -368,7 +398,8 @@ static void rgrp_go_unlock(struct gfs2_holder *gh) * */ -static void trans_go_xmote_th(struct gfs2_glock *gl) +static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state, + int flags) { struct gfs2_sbd *sdp = gl->gl_sbd; @@ -377,6 +408,8 @@ static void trans_go_xmote_th(struct gfs2_glock *gl) gfs2_meta_syncfs(sdp); gfs2_log_shutdown(sdp); } + + gfs2_glock_xmote_th(gl, state, flags); } /** @@ -428,6 +461,8 @@ static void trans_go_drop_th(struct gfs2_glock *gl) gfs2_meta_syncfs(sdp); gfs2_log_shutdown(sdp); } + + gfs2_glock_drop_th(gl); } /** @@ -443,8 +478,8 @@ static int quota_go_demote_ok(struct gfs2_glock *gl) } const struct gfs2_glock_operations gfs2_meta_glops = { - .go_xmote_th = meta_go_sync, - .go_drop_th = meta_go_sync, + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_type = LM_TYPE_META, }; @@ -452,14 +487,19 @@ const struct gfs2_glock_operations gfs2_inode_glops = { .go_xmote_th = inode_go_xmote_th, .go_xmote_bh = inode_go_xmote_bh, .go_drop_th = inode_go_drop_th, + .go_sync = inode_go_sync, .go_inval = inode_go_inval, .go_demote_ok = inode_go_demote_ok, .go_lock = inode_go_lock, .go_unlock = inode_go_unlock, + .go_greedy = inode_greedy, .go_type = LM_TYPE_INODE, }; const struct gfs2_glock_operations gfs2_rgrp_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, + .go_sync = meta_go_sync, .go_inval = meta_go_inval, .go_demote_ok = rgrp_go_demote_ok, .go_lock = rgrp_go_lock, @@ -475,23 +515,33 @@ const struct gfs2_glock_operations gfs2_trans_glops = { }; const struct gfs2_glock_operations gfs2_iopen_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_type = LM_TYPE_IOPEN, }; const struct gfs2_glock_operations gfs2_flock_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_type = LM_TYPE_FLOCK, }; const struct gfs2_glock_operations gfs2_nondisk_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_type = LM_TYPE_NONDISK, }; const struct gfs2_glock_operations gfs2_quota_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_demote_ok = quota_go_demote_ok, .go_type = LM_TYPE_QUOTA, }; const struct gfs2_glock_operations gfs2_journal_glops = { + .go_xmote_th = gfs2_glock_xmote_th, + .go_drop_th = gfs2_glock_drop_th, .go_type = LM_TYPE_JOURNAL, }; diff --git a/trunk/fs/gfs2/incore.h b/trunk/fs/gfs2/incore.h index 12c80fd28db5..734421edae85 100644 --- a/trunk/fs/gfs2/incore.h +++ b/trunk/fs/gfs2/incore.h @@ -101,14 +101,17 @@ struct gfs2_bufdata { }; struct gfs2_glock_operations { - void (*go_xmote_th) (struct gfs2_glock *gl); + void (*go_xmote_th) (struct gfs2_glock *gl, unsigned int state, int flags); void (*go_xmote_bh) (struct gfs2_glock *gl); void (*go_drop_th) (struct gfs2_glock *gl); void (*go_drop_bh) (struct gfs2_glock *gl); + void (*go_sync) (struct gfs2_glock *gl); void (*go_inval) (struct gfs2_glock *gl, int flags); int (*go_demote_ok) (struct gfs2_glock *gl); int (*go_lock) (struct gfs2_holder *gh); void (*go_unlock) (struct gfs2_holder *gh); + void (*go_callback) (struct gfs2_glock *gl, unsigned int state); + void (*go_greedy) (struct gfs2_glock *gl); const int go_type; }; @@ -117,6 +120,7 @@ enum { HIF_MUTEX = 0, HIF_PROMOTE = 1, HIF_DEMOTE = 2, + HIF_GREEDY = 3, /* States */ HIF_ALLOCED = 4, @@ -124,7 +128,6 @@ enum { HIF_HOLDER = 6, HIF_FIRST = 7, HIF_ABORTED = 9, - HIF_WAIT = 10, }; struct gfs2_holder { @@ -137,14 +140,17 @@ struct gfs2_holder { int gh_error; unsigned long gh_iflags; + struct completion gh_wait; unsigned long gh_ip; }; enum { GLF_LOCK = 1, GLF_STICKY = 2, + GLF_PREFETCH = 3, GLF_DIRTY = 5, GLF_SKIP_WAITERS2 = 6, + GLF_GREEDY = 7, }; struct gfs2_glock { @@ -161,7 +167,7 @@ struct gfs2_glock { unsigned long gl_ip; struct list_head gl_holders; struct list_head gl_waiters1; /* HIF_MUTEX */ - struct list_head gl_waiters2; /* HIF_DEMOTE */ + struct list_head gl_waiters2; /* HIF_DEMOTE, HIF_GREEDY */ struct list_head gl_waiters3; /* HIF_PROMOTE */ const struct gfs2_glock_operations *gl_ops; @@ -230,6 +236,7 @@ struct gfs2_inode { spinlock_t i_spin; struct rw_semaphore i_rw_mutex; + unsigned int i_greedy; unsigned long i_last_pfault; struct buffer_head *i_cache[GFS2_MAX_META_HEIGHT]; @@ -411,12 +418,17 @@ struct gfs2_tune { unsigned int gt_atime_quantum; /* Min secs between atime updates */ unsigned int gt_new_files_jdata; unsigned int gt_new_files_directio; + unsigned int gt_max_atomic_write; /* Split big writes into this size */ unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ unsigned int gt_lockdump_size; unsigned int gt_stall_secs; /* Detects trouble! */ unsigned int gt_complain_secs; unsigned int gt_reclaim_limit; /* Max num of glocks in reclaim list */ unsigned int gt_entries_per_readdir; + unsigned int gt_prefetch_secs; /* Usage window for prefetched glocks */ + unsigned int gt_greedy_default; + unsigned int gt_greedy_quantum; + unsigned int gt_greedy_max; unsigned int gt_statfs_quantum; unsigned int gt_statfs_slow; }; diff --git a/trunk/fs/gfs2/inode.c b/trunk/fs/gfs2/inode.c index 0d6831a40565..d122074c45e1 100644 --- a/trunk/fs/gfs2/inode.c +++ b/trunk/fs/gfs2/inode.c @@ -287,8 +287,10 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) * * Returns: errno */ + int gfs2_change_nlink(struct gfs2_inode *ip, int diff) { + struct gfs2_sbd *sdp = ip->i_inode.i_sb->s_fs_info; struct buffer_head *dibh; u32 nlink; int error; @@ -313,34 +315,42 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) else drop_nlink(&ip->i_inode); - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); mark_inode_dirty(&ip->i_inode); - if (ip->i_inode.i_nlink == 0) - gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ + if (ip->i_inode.i_nlink == 0) { + struct gfs2_rgrpd *rgd; + struct gfs2_holder ri_gh, rg_gh; + + error = gfs2_rindex_hold(sdp, &ri_gh); + if (error) + goto out; + error = -EIO; + rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); + if (!rgd) + goto out_norgrp; + error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, &rg_gh); + if (error) + goto out_norgrp; + gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ + gfs2_glock_dq_uninit(&rg_gh); +out_norgrp: + gfs2_glock_dq_uninit(&ri_gh); + } +out: return error; } struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) { struct qstr qstr; - struct inode *inode; gfs2_str2qstr(&qstr, name); - inode = gfs2_lookupi(dip, &qstr, 1, NULL); - /* gfs2_lookupi has inconsistent callers: vfs - * related routines expect NULL for no entry found, - * gfs2_lookup_simple callers expect ENOENT - * and do not check for NULL. - */ - if (inode == NULL) - return ERR_PTR(-ENOENT); - else - return inode; + return gfs2_lookupi(dip, &qstr, 1, NULL); } @@ -351,10 +361,8 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) * @is_root: If 1, ignore the caller's permissions * @i_gh: An uninitialized holder for the new inode glock * - * This can be called via the VFS filldir function when NFS is doing - * a readdirplus and the inode which its intending to stat isn't - * already in cache. In this case we must not take the directory glock - * again, since the readdir call will have already taken that lock. + * There will always be a vnode (Linux VFS inode) for the d_gh inode unless + * @is_root is true. * * Returns: errno */ @@ -367,9 +375,8 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, struct gfs2_holder d_gh; struct gfs2_inum_host inum; unsigned int type; - int error; + int error = 0; struct inode *inode = NULL; - int unlock = 0; if (!name->len || name->len > GFS2_FNAMESIZE) return ERR_PTR(-ENAMETOOLONG); @@ -381,12 +388,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, return dir; } - if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); - if (error) - return ERR_PTR(error); - unlock = 1; - } + error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + if (error) + return ERR_PTR(error); if (!is_root) { error = permission(dir, MAY_EXEC, NULL); @@ -401,11 +405,10 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, inode = gfs2_inode_lookup(sb, &inum, type); out: - if (unlock) - gfs2_glock_dq_uninit(&d_gh); + gfs2_glock_dq_uninit(&d_gh); if (error == -ENOENT) return NULL; - return inode ? inode : ERR_PTR(error); + return inode; } static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino) diff --git a/trunk/fs/gfs2/lm.c b/trunk/fs/gfs2/lm.c index e30673dd37e0..effe4a337c1d 100644 --- a/trunk/fs/gfs2/lm.c +++ b/trunk/fs/gfs2/lm.c @@ -104,9 +104,15 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) vprintk(fmt, args); va_end(args); - fs_err(sdp, "about to withdraw this file system\n"); + fs_err(sdp, "about to withdraw from the cluster\n"); BUG_ON(sdp->sd_args.ar_debug); + + fs_err(sdp, "waiting for outstanding I/O\n"); + + /* FIXME: suspend dm device so oustanding bio's complete + and all further io requests fail */ + fs_err(sdp, "telling LM to withdraw\n"); gfs2_withdraw_lockproto(&sdp->sd_lockstruct); fs_err(sdp, "withdrawn\n"); diff --git a/trunk/fs/gfs2/locking/dlm/lock_dlm.h b/trunk/fs/gfs2/locking/dlm/lock_dlm.h index a87c7bf3c568..33af707a4d3f 100644 --- a/trunk/fs/gfs2/locking/dlm/lock_dlm.h +++ b/trunk/fs/gfs2/locking/dlm/lock_dlm.h @@ -36,7 +36,7 @@ #define GDLM_STRNAME_BYTES 24 #define GDLM_LVB_SIZE 32 -#define GDLM_DROP_COUNT 200000 +#define GDLM_DROP_COUNT 50000 #define GDLM_DROP_PERIOD 60 #define GDLM_NAME_LEN 128 diff --git a/trunk/fs/gfs2/locking/dlm/main.c b/trunk/fs/gfs2/locking/dlm/main.c index a0e7eda643ed..2194b1d5b5ec 100644 --- a/trunk/fs/gfs2/locking/dlm/main.c +++ b/trunk/fs/gfs2/locking/dlm/main.c @@ -11,6 +11,9 @@ #include "lock_dlm.h" +extern int gdlm_drop_count; +extern int gdlm_drop_period; + extern struct lm_lockops gdlm_ops; static int __init init_lock_dlm(void) @@ -37,6 +40,9 @@ static int __init init_lock_dlm(void) return error; } + gdlm_drop_count = GDLM_DROP_COUNT; + gdlm_drop_period = GDLM_DROP_PERIOD; + printk(KERN_INFO "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__); return 0; diff --git a/trunk/fs/gfs2/locking/dlm/mount.c b/trunk/fs/gfs2/locking/dlm/mount.c index 1d8faa3da8af..cdd1694e889b 100644 --- a/trunk/fs/gfs2/locking/dlm/mount.c +++ b/trunk/fs/gfs2/locking/dlm/mount.c @@ -9,6 +9,8 @@ #include "lock_dlm.h" +int gdlm_drop_count; +int gdlm_drop_period; const struct lm_lockops gdlm_ops; @@ -22,8 +24,8 @@ static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp, if (!ls) return NULL; - ls->drop_locks_count = GDLM_DROP_COUNT; - ls->drop_locks_period = GDLM_DROP_PERIOD; + ls->drop_locks_count = gdlm_drop_count; + ls->drop_locks_period = gdlm_drop_period; ls->fscb = cb; ls->sdp = sdp; ls->fsflags = flags; diff --git a/trunk/fs/gfs2/locking/dlm/sysfs.c b/trunk/fs/gfs2/locking/dlm/sysfs.c index 4746b884662d..29ae06f94944 100644 --- a/trunk/fs/gfs2/locking/dlm/sysfs.c +++ b/trunk/fs/gfs2/locking/dlm/sysfs.c @@ -116,17 +116,6 @@ static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf) return sprintf(buf, "%d\n", ls->recover_jid_status); } -static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf) -{ - return sprintf(buf, "%d\n", ls->drop_locks_count); -} - -static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len) -{ - ls->drop_locks_count = simple_strtol(buf, NULL, 0); - return len; -} - struct gdlm_attr { struct attribute attr; ssize_t (*show)(struct gdlm_ls *, char *); @@ -146,7 +135,6 @@ GDLM_ATTR(first_done, 0444, first_done_show, NULL); GDLM_ATTR(recover, 0644, recover_show, recover_store); GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); -GDLM_ATTR(drop_count, 0644, drop_count_show, drop_count_store); static struct attribute *gdlm_attrs[] = { &gdlm_attr_proto_name.attr, @@ -159,7 +147,6 @@ static struct attribute *gdlm_attrs[] = { &gdlm_attr_recover.attr, &gdlm_attr_recover_done.attr, &gdlm_attr_recover_status.attr, - &gdlm_attr_drop_count.attr, NULL, }; diff --git a/trunk/fs/gfs2/lops.c b/trunk/fs/gfs2/lops.c index 16bb4b4561ae..4d7f94d8c7bd 100644 --- a/trunk/fs/gfs2/lops.c +++ b/trunk/fs/gfs2/lops.c @@ -69,16 +69,13 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); struct gfs2_trans *tr; - gfs2_log_lock(sdp); - if (!list_empty(&bd->bd_list_tr)) { - gfs2_log_unlock(sdp); + if (!list_empty(&bd->bd_list_tr)) return; - } + tr = current->journal_info; tr->tr_touched = 1; tr->tr_num_buf++; list_add(&bd->bd_list_tr, &tr->tr_list_buf); - gfs2_log_unlock(sdp); if (!list_empty(&le->le_list)) return; @@ -87,6 +84,7 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) gfs2_meta_check(sdp, bd->bd_bh); gfs2_pin(sdp, bd->bd_bh); + gfs2_log_lock(sdp); sdp->sd_log_num_buf++; list_add(&le->le_list, &sdp->sd_log_le_buf); @@ -100,13 +98,11 @@ static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) struct list_head *head = &tr->tr_list_buf; struct gfs2_bufdata *bd; - gfs2_log_lock(sdp); while (!list_empty(head)) { bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr); list_del_init(&bd->bd_list_tr); tr->tr_num_buf--; } - gfs2_log_unlock(sdp); gfs2_assert_warn(sdp, !tr->tr_num_buf); } @@ -466,17 +462,13 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - gfs2_log_lock(sdp); tr->tr_touched = 1; if (list_empty(&bd->bd_list_tr) && (ip->i_di.di_flags & GFS2_DIF_JDATA)) { tr->tr_num_buf++; list_add(&bd->bd_list_tr, &tr->tr_list_buf); - gfs2_log_unlock(sdp); gfs2_pin(sdp, bd->bd_bh); tr->tr_num_buf_new++; - } else { - gfs2_log_unlock(sdp); } gfs2_trans_add_gl(bd->bd_gl); gfs2_log_lock(sdp); diff --git a/trunk/fs/gfs2/ops_address.c b/trunk/fs/gfs2/ops_address.c index 56e33590b656..d8d69a72a10d 100644 --- a/trunk/fs/gfs2/ops_address.c +++ b/trunk/fs/gfs2/ops_address.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -157,32 +156,6 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc) return 0; } -/** - * gfs2_writepages - Write a bunch of dirty pages back to disk - * @mapping: The mapping to write - * @wbc: Write-back control - * - * For journaled files and/or ordered writes this just falls back to the - * kernel's default writepages path for now. We will probably want to change - * that eventually (i.e. when we look at allocate on flush). - * - * For the data=writeback case though we can already ignore buffer heads - * and write whole extents at once. This is a big reduction in the - * number of I/O requests we send and the bmap calls we make in this case. - */ -static int gfs2_writepages(struct address_space *mapping, - struct writeback_control *wbc) -{ - struct inode *inode = mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_sbd *sdp = GFS2_SB(inode); - - if (sdp->sd_args.ar_data == GFS2_DATA_WRITEBACK && !gfs2_is_jdata(ip)) - return mpage_writepages(mapping, wbc, gfs2_get_block_noalloc); - - return generic_writepages(mapping, wbc); -} - /** * stuffed_readpage - Fill in a Linux page with stuffed file data * @ip: the inode @@ -283,7 +256,7 @@ static int gfs2_readpage(struct file *file, struct page *page) * the page lock and the glock) and return having done no I/O. Its * obviously not something we'd want to do on too regular a basis. * Any I/O we ignore at this time will be done via readpage later. - * 2. We don't handle stuffed files here we let readpage do the honours. + * 2. We have to handle stuffed files here too. * 3. mpage_readpages() does most of the heavy lifting in the common case. * 4. gfs2_get_block() is relied upon to set BH_Boundary in the right places. * 5. We use LM_FLAG_TRY_1CB here, effectively we then have lock-ahead as @@ -296,7 +269,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_holder gh; - int ret = 0; + unsigned page_idx; + int ret; int do_unlock = 0; if (likely(file != &gfs2_internal_file_sentinel)) { @@ -315,8 +289,29 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping, goto out_unlock; } skip_lock: - if (!gfs2_is_stuffed(ip)) + if (gfs2_is_stuffed(ip)) { + struct pagevec lru_pvec; + pagevec_init(&lru_pvec, 0); + for (page_idx = 0; page_idx < nr_pages; page_idx++) { + struct page *page = list_entry(pages->prev, struct page, lru); + prefetchw(&page->flags); + list_del(&page->lru); + if (!add_to_page_cache(page, mapping, + page->index, GFP_KERNEL)) { + ret = stuffed_readpage(ip, page); + unlock_page(page); + if (!pagevec_add(&lru_pvec, page)) + __pagevec_lru_add(&lru_pvec); + } else { + page_cache_release(page); + } + } + pagevec_lru_add(&lru_pvec); + ret = 0; + } else { + /* What we really want to do .... */ ret = mpage_readpages(mapping, pages, nr_pages, gfs2_get_block); + } if (do_unlock) { gfs2_glock_dq_m(1, &gh); @@ -361,10 +356,8 @@ static int gfs2_prepare_write(struct file *file, struct page *page, gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh); error = gfs2_glock_nq_atime(&ip->i_gh); if (unlikely(error)) { - if (error == GLR_TRYFAILED) { - unlock_page(page); + if (error == GLR_TRYFAILED) error = AOP_TRUNCATED_PAGE; - } goto out_uninit; } @@ -601,36 +594,6 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset) return; } -/** - * gfs2_ok_for_dio - check that dio is valid on this file - * @ip: The inode - * @rw: READ or WRITE - * @offset: The offset at which we are reading or writing - * - * Returns: 0 (to ignore the i/o request and thus fall back to buffered i/o) - * 1 (to accept the i/o request) - */ -static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset) -{ - /* - * Should we return an error here? I can't see that O_DIRECT for - * a journaled file makes any sense. For now we'll silently fall - * back to buffered I/O, likewise we do the same for stuffed - * files since they are (a) small and (b) unaligned. - */ - if (gfs2_is_jdata(ip)) - return 0; - - if (gfs2_is_stuffed(ip)) - return 0; - - if (offset > i_size_read(&ip->i_inode)) - return 0; - return 1; -} - - - static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) @@ -641,28 +604,42 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, struct gfs2_holder gh; int rv; + if (rw == READ) + mutex_lock(&inode->i_mutex); /* - * Deferred lock, even if its a write, since we do no allocation - * on this path. All we need change is atime, and this lock mode - * ensures that other nodes have flushed their buffered read caches - * (i.e. their page cache entries for this inode). We do not, - * unfortunately have the option of only flushing a range like - * the VFS does. + * Shared lock, even if its a write, since we do no allocation + * on this path. All we need change is atime. */ - gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); rv = gfs2_glock_nq_atime(&gh); if (rv) - return rv; - rv = gfs2_ok_for_dio(ip, rw, offset); - if (rv != 1) - goto out; /* dio not valid, fall back to buffered i/o */ - - rv = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev, - iov, offset, nr_segs, - gfs2_get_block_direct, NULL); + goto out; + + if (offset > i_size_read(inode)) + goto out; + + /* + * Should we return an error here? I can't see that O_DIRECT for + * a journaled file makes any sense. For now we'll silently fall + * back to buffered I/O, likewise we do the same for stuffed + * files since they are (a) small and (b) unaligned. + */ + if (gfs2_is_jdata(ip)) + goto out; + + if (gfs2_is_stuffed(ip)) + goto out; + + rv = blockdev_direct_IO_own_locking(rw, iocb, inode, + inode->i_sb->s_bdev, + iov, offset, nr_segs, + gfs2_get_block_direct, NULL); out: gfs2_glock_dq_m(1, &gh); gfs2_holder_uninit(&gh); + if (rw == READ) + mutex_unlock(&inode->i_mutex); + return rv; } @@ -786,7 +763,6 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) const struct address_space_operations gfs2_file_aops = { .writepage = gfs2_writepage, - .writepages = gfs2_writepages, .readpage = gfs2_readpage, .readpages = gfs2_readpages, .sync_page = block_sync_page, diff --git a/trunk/fs/gfs2/ops_dentry.c b/trunk/fs/gfs2/ops_dentry.c index 9187eb174b43..d355899585d8 100644 --- a/trunk/fs/gfs2/ops_dentry.c +++ b/trunk/fs/gfs2/ops_dentry.c @@ -46,7 +46,6 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) struct gfs2_inum_host inum; unsigned int type; int error; - int had_lock=0; if (inode && is_bad_inode(inode)) goto invalid; @@ -54,12 +53,9 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) if (sdp->sd_args.ar_localcaching) goto valid; - had_lock = gfs2_glock_is_locked_by_me(dip->i_gl); - if (!had_lock) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); - if (error) - goto fail; - } + error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + if (error) + goto fail; error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type); switch (error) { @@ -86,15 +82,13 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) } valid_gunlock: - if (!had_lock) - gfs2_glock_dq_uninit(&d_gh); + gfs2_glock_dq_uninit(&d_gh); valid: dput(parent); return 1; invalid_gunlock: - if (!had_lock) - gfs2_glock_dq_uninit(&d_gh); + gfs2_glock_dq_uninit(&d_gh); invalid: if (inode && S_ISDIR(inode->i_mode)) { if (have_submounts(dentry)) diff --git a/trunk/fs/gfs2/ops_export.c b/trunk/fs/gfs2/ops_export.c index 4855e8cca622..b4e7b8775315 100644 --- a/trunk/fs/gfs2/ops_export.c +++ b/trunk/fs/gfs2/ops_export.c @@ -22,7 +22,6 @@ #include "glock.h" #include "glops.h" #include "inode.h" -#include "ops_dentry.h" #include "ops_export.h" #include "rgrp.h" #include "util.h" @@ -113,12 +112,13 @@ struct get_name_filldir { char *name; }; -static int get_name_filldir(void *opaque, const char *name, int length, - loff_t offset, u64 inum, unsigned int type) +static int get_name_filldir(void *opaque, const char *name, unsigned int length, + u64 offset, struct gfs2_inum_host *inum, + unsigned int type) { - struct get_name_filldir *gnfd = opaque; + struct get_name_filldir *gnfd = (struct get_name_filldir *)opaque; - if (inum != gnfd->inum.no_addr) + if (!gfs2_inum_equal(inum, &gnfd->inum)) return 0; memcpy(gnfd->name, name, length); @@ -189,7 +189,6 @@ static struct dentry *gfs2_get_parent(struct dentry *child) return ERR_PTR(-ENOMEM); } - dentry->d_op = &gfs2_dops; return dentry; } @@ -216,7 +215,8 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) } error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops, - LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + LM_ST_SHARED, LM_FLAG_ANY | GL_LOCAL_EXCL, + &i_gh); if (error) return ERR_PTR(error); @@ -269,7 +269,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) return ERR_PTR(-ENOMEM); } - dentry->d_op = &gfs2_dops; return dentry; fail_rgd: diff --git a/trunk/fs/gfs2/ops_file.c b/trunk/fs/gfs2/ops_file.c index c996aa739a05..faa07e4b97d0 100644 --- a/trunk/fs/gfs2/ops_file.c +++ b/trunk/fs/gfs2/ops_file.c @@ -43,6 +43,15 @@ #include "util.h" #include "eaops.h" +/* For regular, non-NFS */ +struct filldir_reg { + struct gfs2_sbd *fdr_sbd; + int fdr_prefetch; + + filldir_t fdr_filldir; + void *fdr_opaque; +}; + /* * Most fields left uninitialised to catch anybody who tries to * use them. f_flags set to prevent file_accessed() from touching @@ -118,6 +127,41 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) return error; } +/** + * filldir_func - Report a directory entry to the caller of gfs2_dir_read() + * @opaque: opaque data used by the function + * @name: the name of the directory entry + * @length: the length of the name + * @offset: the entry's offset in the directory + * @inum: the inode number the entry points to + * @type: the type of inode the entry points to + * + * Returns: 0 on success, 1 if buffer full + */ + +static int filldir_func(void *opaque, const char *name, unsigned int length, + u64 offset, struct gfs2_inum_host *inum, + unsigned int type) +{ + struct filldir_reg *fdr = (struct filldir_reg *)opaque; + struct gfs2_sbd *sdp = fdr->fdr_sbd; + int error; + + error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset, + inum->no_addr, type); + if (error) + return 1; + + if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { + gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops, + LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); + gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops, + LM_ST_SHARED, LM_FLAG_TRY); + } + + return 0; +} + /** * gfs2_readdir - Read directory entries from a directory * @file: The directory to read from @@ -131,10 +175,16 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) { struct inode *dir = file->f_mapping->host; struct gfs2_inode *dip = GFS2_I(dir); + struct filldir_reg fdr; struct gfs2_holder d_gh; u64 offset = file->f_pos; int error; + fdr.fdr_sbd = GFS2_SB(dir); + fdr.fdr_prefetch = 1; + fdr.fdr_filldir = filldir; + fdr.fdr_opaque = dirent; + gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); error = gfs2_glock_nq_atime(&d_gh); if (error) { @@ -142,7 +192,7 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) return error; } - error = gfs2_dir_read(dir, &offset, dirent, filldir); + error = gfs2_dir_read(dir, &offset, &fdr, filldir_func); gfs2_glock_dq_uninit(&d_gh); diff --git a/trunk/fs/gfs2/ops_inode.c b/trunk/fs/gfs2/ops_inode.c index f40a84807d75..636dda4c7d38 100644 --- a/trunk/fs/gfs2/ops_inode.c +++ b/trunk/fs/gfs2/ops_inode.c @@ -264,23 +264,13 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_sbd *sdp = GFS2_SB(dir); struct gfs2_inode *ip = GFS2_I(dentry->d_inode); - struct gfs2_holder ghs[3]; - struct gfs2_rgrpd *rgd; - struct gfs2_holder ri_gh; + struct gfs2_holder ghs[2]; int error; - error = gfs2_rindex_hold(sdp, &ri_gh); - if (error) - return error; - gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); - - rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); - gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); - + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); - error = gfs2_glock_nq_m(3, ghs); + error = gfs2_glock_nq_m(2, ghs); if (error) goto out; @@ -301,12 +291,10 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) out_end_trans: gfs2_trans_end(sdp); out_gunlock: - gfs2_glock_dq_m(3, ghs); + gfs2_glock_dq_m(2, ghs); out: gfs2_holder_uninit(ghs); gfs2_holder_uninit(ghs + 1); - gfs2_holder_uninit(ghs + 2); - gfs2_glock_dq_uninit(&ri_gh); return error; } @@ -461,22 +449,13 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_sbd *sdp = GFS2_SB(dir); struct gfs2_inode *ip = GFS2_I(dentry->d_inode); - struct gfs2_holder ghs[3]; - struct gfs2_rgrpd *rgd; - struct gfs2_holder ri_gh; + struct gfs2_holder ghs[2]; int error; - - error = gfs2_rindex_hold(sdp, &ri_gh); - if (error) - return error; gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); - rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); - gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); - - error = gfs2_glock_nq_m(3, ghs); + error = gfs2_glock_nq_m(2, ghs); if (error) goto out; @@ -504,12 +483,10 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) gfs2_trans_end(sdp); out_gunlock: - gfs2_glock_dq_m(3, ghs); + gfs2_glock_dq_m(2, ghs); out: gfs2_holder_uninit(ghs); gfs2_holder_uninit(ghs + 1); - gfs2_holder_uninit(ghs + 2); - gfs2_glock_dq_uninit(&ri_gh); return error; } @@ -570,8 +547,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, struct gfs2_inode *ip = GFS2_I(odentry->d_inode); struct gfs2_inode *nip = NULL; struct gfs2_sbd *sdp = GFS2_SB(odir); - struct gfs2_holder ghs[5], r_gh; - struct gfs2_rgrpd *nrgd; + struct gfs2_holder ghs[4], r_gh; unsigned int num_gh; int dir_rename = 0; int alloc_required; @@ -611,13 +587,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (nip) { gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); num_gh++; - /* grab the resource lock for unlink flag twiddling - * this is the case of the target file already existing - * so we unlink before doing the rename - */ - nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); - if (nrgd) - gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); } error = gfs2_glock_nq_m(num_gh, ghs); @@ -715,12 +684,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + al->al_rgd->rd_ri.ri_length + 4 * RES_DINODE + 4 * RES_LEAF + - RES_STATFS + RES_QUOTA + 4, 0); + RES_STATFS + RES_QUOTA, 0); if (error) goto out_ipreserv; } else { error = gfs2_trans_begin(sdp, 4 * RES_DINODE + - 5 * RES_LEAF + 4, 0); + 5 * RES_LEAF, 0); if (error) goto out_gunlock; } @@ -759,7 +728,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, error = gfs2_meta_inode_buffer(ip, &dibh); if (error) goto out_end_trans; - ip->i_inode.i_ctime = CURRENT_TIME_SEC; + ip->i_inode.i_ctime.tv_sec = get_seconds(); gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1049,7 +1018,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, } generic_fillattr(inode, stat); - if (unlock) + if (unlock); gfs2_glock_dq_uninit(&gh); return 0; diff --git a/trunk/fs/gfs2/ops_super.c b/trunk/fs/gfs2/ops_super.c index 47369d011214..7685b46f934b 100644 --- a/trunk/fs/gfs2/ops_super.c +++ b/trunk/fs/gfs2/ops_super.c @@ -173,9 +173,6 @@ static void gfs2_write_super_lockfs(struct super_block *sb) struct gfs2_sbd *sdp = sb->s_fs_info; int error; - if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) - return; - for (;;) { error = gfs2_freeze_fs(sdp); if (!error) @@ -429,12 +426,6 @@ static void gfs2_delete_inode(struct inode *inode) } error = gfs2_dinode_dealloc(ip); - /* - * Must do this before unlock to avoid trying to write back - * potentially dirty data now that inode no longer exists - * on disk. - */ - truncate_inode_pages(&inode->i_data, 0); out_unlock: gfs2_glock_dq(&ip->i_iopen_gh); @@ -452,12 +443,14 @@ static void gfs2_delete_inode(struct inode *inode) static struct inode *gfs2_alloc_inode(struct super_block *sb) { + struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_inode *ip; ip = kmem_cache_alloc(gfs2_inode_cachep, GFP_KERNEL); if (ip) { ip->i_flags = 0; ip->i_gl = NULL; + ip->i_greedy = gfs2_tune_get(sdp, gt_greedy_default); ip->i_last_pfault = jiffies; } return &ip->i_inode; diff --git a/trunk/fs/gfs2/ops_vm.c b/trunk/fs/gfs2/ops_vm.c index 14b380fb0602..45a5f11fc39a 100644 --- a/trunk/fs/gfs2/ops_vm.c +++ b/trunk/fs/gfs2/ops_vm.c @@ -28,13 +28,34 @@ #include "trans.h" #include "util.h" +static void pfault_be_greedy(struct gfs2_inode *ip) +{ + unsigned int time; + + spin_lock(&ip->i_spin); + time = ip->i_greedy; + ip->i_last_pfault = jiffies; + spin_unlock(&ip->i_spin); + + igrab(&ip->i_inode); + if (gfs2_glock_be_greedy(ip->i_gl, time)) + iput(&ip->i_inode); +} + static struct page *gfs2_private_nopage(struct vm_area_struct *area, unsigned long address, int *type) { struct gfs2_inode *ip = GFS2_I(area->vm_file->f_mapping->host); + struct page *result; set_bit(GIF_PAGED, &ip->i_flags); - return filemap_nopage(area, address, type); + + result = filemap_nopage(area, address, type); + + if (result && result != NOPAGE_OOM) + pfault_be_greedy(ip); + + return result; } static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) @@ -146,6 +167,7 @@ static struct page *gfs2_sharewrite_nopage(struct vm_area_struct *area, set_page_dirty(result); } + pfault_be_greedy(ip); out: gfs2_glock_dq_uninit(&i_gh); diff --git a/trunk/fs/gfs2/super.c b/trunk/fs/gfs2/super.c index 70f424fcf1cd..43a24f2e5905 100644 --- a/trunk/fs/gfs2/super.c +++ b/trunk/fs/gfs2/super.c @@ -71,12 +71,17 @@ void gfs2_tune_init(struct gfs2_tune *gt) gt->gt_atime_quantum = 3600; gt->gt_new_files_jdata = 0; gt->gt_new_files_directio = 0; + gt->gt_max_atomic_write = 4 << 20; gt->gt_max_readahead = 1 << 18; gt->gt_lockdump_size = 131072; gt->gt_stall_secs = 600; gt->gt_complain_secs = 10; gt->gt_reclaim_limit = 5000; gt->gt_entries_per_readdir = 32; + gt->gt_prefetch_secs = 10; + gt->gt_greedy_default = HZ / 10; + gt->gt_greedy_quantum = HZ / 40; + gt->gt_greedy_max = HZ / 4; gt->gt_statfs_quantum = 30; gt->gt_statfs_slow = 0; } @@ -354,7 +359,8 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) mutex_lock(&sdp->sd_jindex_mutex); for (;;) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh); + error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, + GL_LOCAL_EXCL, ji_gh); if (error) break; @@ -523,7 +529,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) struct gfs2_log_header_host head; int error; - error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh); + error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, + GL_LOCAL_EXCL, &t_gh); if (error) return error; @@ -576,8 +583,9 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp) gfs2_quota_sync(sdp); gfs2_statfs_sync(sdp); - error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, - &t_gh); + error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, + GL_LOCAL_EXCL | GL_NOCACHE, + &t_gh); if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) return error; diff --git a/trunk/fs/gfs2/sys.c b/trunk/fs/gfs2/sys.c index d01f9f0fda26..983eaf1e06be 100644 --- a/trunk/fs/gfs2/sys.c +++ b/trunk/fs/gfs2/sys.c @@ -436,12 +436,17 @@ TUNE_ATTR(atime_quantum, 0); TUNE_ATTR(max_readahead, 0); TUNE_ATTR(complain_secs, 0); TUNE_ATTR(reclaim_limit, 0); +TUNE_ATTR(prefetch_secs, 0); TUNE_ATTR(statfs_slow, 0); TUNE_ATTR(new_files_jdata, 0); TUNE_ATTR(new_files_directio, 0); TUNE_ATTR(quota_simul_sync, 1); TUNE_ATTR(quota_cache_secs, 1); +TUNE_ATTR(max_atomic_write, 1); TUNE_ATTR(stall_secs, 1); +TUNE_ATTR(greedy_default, 1); +TUNE_ATTR(greedy_quantum, 1); +TUNE_ATTR(greedy_max, 1); TUNE_ATTR(statfs_quantum, 1); TUNE_ATTR_DAEMON(scand_secs, scand_process); TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); @@ -460,10 +465,15 @@ static struct attribute *tune_attrs[] = { &tune_attr_max_readahead.attr, &tune_attr_complain_secs.attr, &tune_attr_reclaim_limit.attr, + &tune_attr_prefetch_secs.attr, &tune_attr_statfs_slow.attr, &tune_attr_quota_simul_sync.attr, &tune_attr_quota_cache_secs.attr, + &tune_attr_max_atomic_write.attr, &tune_attr_stall_secs.attr, + &tune_attr_greedy_default.attr, + &tune_attr_greedy_quantum.attr, + &tune_attr_greedy_max.attr, &tune_attr_statfs_quantum.attr, &tune_attr_scand_secs.attr, &tune_attr_recoverd_secs.attr, diff --git a/trunk/fs/jfs/inode.c b/trunk/fs/jfs/inode.c index e285022f006c..f5719117edfe 100644 --- a/trunk/fs/jfs/inode.c +++ b/trunk/fs/jfs/inode.c @@ -182,9 +182,9 @@ int jfs_get_block(struct inode *ip, sector_t lblock, * Take appropriate lock on inode */ if (create) - IWRITE_LOCK(ip, RDWRLOCK_NORMAL); + IWRITE_LOCK(ip); else - IREAD_LOCK(ip, RDWRLOCK_NORMAL); + IREAD_LOCK(ip); if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && @@ -359,7 +359,7 @@ void jfs_truncate(struct inode *ip) nobh_truncate_page(ip->i_mapping, ip->i_size); - IWRITE_LOCK(ip, RDWRLOCK_NORMAL); + IWRITE_LOCK(ip); jfs_truncate_nolock(ip, ip->i_size); IWRITE_UNLOCK(ip); } diff --git a/trunk/fs/jfs/jfs_debug.h b/trunk/fs/jfs/jfs_debug.h index 7378798f0b21..ddffbbd4d955 100644 --- a/trunk/fs/jfs/jfs_debug.h +++ b/trunk/fs/jfs/jfs_debug.h @@ -39,6 +39,10 @@ extern void jfs_proc_clean(void); /* * assert with traditional printf/panic */ +#ifdef CONFIG_KERNEL_ASSERTS +/* kgdb stuff */ +#define assert(p) KERNEL_ASSERT(#p, p) +#else #define assert(p) do { \ if (!(p)) { \ printk(KERN_CRIT "BUG at %s:%d assert(%s)\n", \ @@ -46,6 +50,7 @@ extern void jfs_proc_clean(void); BUG(); \ } \ } while (0) +#endif /* * debug ON diff --git a/trunk/fs/jfs/jfs_dmap.c b/trunk/fs/jfs/jfs_dmap.c index 82b0544bd76d..23546c8fd48b 100644 --- a/trunk/fs/jfs/jfs_dmap.c +++ b/trunk/fs/jfs/jfs_dmap.c @@ -337,7 +337,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); + IREAD_LOCK(ipbmap); /* block to be freed better be within the mapsize. */ if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) { @@ -733,7 +733,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) * allocation group size, try to allocate anywhere. */ if (l2nb > bmp->db_agl2size) { - IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP); + IWRITE_LOCK(ipbmap); rc = dbAllocAny(bmp, nblocks, l2nb, results); @@ -774,7 +774,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) * the hint using a tiered strategy. */ if (nblocks <= BPERDMAP) { - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); + IREAD_LOCK(ipbmap); /* get the buffer for the dmap containing the hint. */ @@ -844,7 +844,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) /* try to satisfy the allocation request with blocks within * the same allocation group as the hint. */ - IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP); + IWRITE_LOCK(ipbmap); if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC) goto write_unlock; @@ -856,7 +856,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) * Let dbNextAG recommend a preferred allocation group */ agno = dbNextAG(ipbmap); - IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP); + IWRITE_LOCK(ipbmap); /* Try to allocate within this allocation group. if that fails, try to * allocate anywhere in the map. @@ -900,7 +900,7 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks) s64 lblkno; struct metapage *mp; - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); + IREAD_LOCK(ipbmap); /* * validate extent request: @@ -1050,7 +1050,7 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) */ extblkno = lastblkno + 1; - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); + IREAD_LOCK(ipbmap); /* better be within the file system */ bmp = sbi->bmap; @@ -3116,7 +3116,7 @@ int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks) struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); + IREAD_LOCK(ipbmap); /* block to be allocated better be within the mapsize. */ ASSERT(nblocks <= bmp->db_mapsize - blkno); diff --git a/trunk/fs/jfs/jfs_imap.c b/trunk/fs/jfs/jfs_imap.c index aa5124b643b1..53f63b47a6d3 100644 --- a/trunk/fs/jfs/jfs_imap.c +++ b/trunk/fs/jfs/jfs_imap.c @@ -331,7 +331,7 @@ int diRead(struct inode *ip) /* read the iag */ imap = JFS_IP(ipimap)->i_imap; - IREAD_LOCK(ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(ipimap); rc = diIAGRead(imap, iagno, &mp); IREAD_UNLOCK(ipimap); if (rc) { @@ -920,7 +920,7 @@ int diFree(struct inode *ip) /* Obtain read lock in imap inode. Don't release it until we have * read all of the IAG's that we are going to. */ - IREAD_LOCK(ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(ipimap); /* read the iag. */ @@ -1415,7 +1415,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) AG_LOCK(imap, agno); /* Get read lock on imap inode */ - IREAD_LOCK(ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(ipimap); /* get the iag number and read the iag */ iagno = INOTOIAG(inum); @@ -1808,7 +1808,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) return -ENOSPC; /* obtain read lock on imap inode */ - IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(imap->im_ipimap); /* read the iag at the head of the list. */ @@ -1946,7 +1946,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) } else { /* read the iag. */ - IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(imap->im_ipimap); if ((rc = diIAGRead(imap, iagno, &mp))) { IREAD_UNLOCK(imap->im_ipimap); jfs_error(ip->i_sb, "diAllocExt: error reading iag"); @@ -2509,7 +2509,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) */ /* acquire inode map lock */ - IWRITE_LOCK(ipimap, RDWRLOCK_IMAP); + IWRITE_LOCK(ipimap); if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) { IWRITE_UNLOCK(ipimap); @@ -2648,7 +2648,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) } /* obtain read lock on map */ - IREAD_LOCK(ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(ipimap); /* read the iag */ if ((rc = diIAGRead(imap, iagno, &mp))) { @@ -2779,7 +2779,7 @@ diUpdatePMap(struct inode *ipimap, return -EIO; } /* read the iag */ - IREAD_LOCK(ipimap, RDWRLOCK_IMAP); + IREAD_LOCK(ipimap); rc = diIAGRead(imap, iagno, &mp); IREAD_UNLOCK(ipimap); if (rc) diff --git a/trunk/fs/jfs/jfs_incore.h b/trunk/fs/jfs/jfs_incore.h index 8f453eff3c83..94005584445a 100644 --- a/trunk/fs/jfs/jfs_incore.h +++ b/trunk/fs/jfs/jfs_incore.h @@ -109,11 +109,9 @@ struct jfs_inode_info { #define JFS_ACL_NOT_CACHED ((void *)-1) -#define IREAD_LOCK(ip, subclass) \ - down_read_nested(&JFS_IP(ip)->rdwrlock, subclass) +#define IREAD_LOCK(ip) down_read(&JFS_IP(ip)->rdwrlock) #define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock) -#define IWRITE_LOCK(ip, subclass) \ - down_write_nested(&JFS_IP(ip)->rdwrlock, subclass) +#define IWRITE_LOCK(ip) down_write(&JFS_IP(ip)->rdwrlock) #define IWRITE_UNLOCK(ip) up_write(&JFS_IP(ip)->rdwrlock) /* @@ -129,29 +127,6 @@ enum cflags { COMMIT_Synclist, /* metadata pages on group commit synclist */ }; -/* - * commit_mutex nesting subclasses: - */ -enum commit_mutex_class -{ - COMMIT_MUTEX_PARENT, - COMMIT_MUTEX_CHILD, - COMMIT_MUTEX_SECOND_PARENT, /* Renaming */ - COMMIT_MUTEX_VICTIM /* Inode being unlinked due to rename */ -}; - -/* - * rdwrlock subclasses: - * The dmap inode may be locked while a normal inode or the imap inode are - * locked. - */ -enum rdwrlock_class -{ - RDWRLOCK_NORMAL, - RDWRLOCK_IMAP, - RDWRLOCK_DMAP -}; - #define set_cflag(flag, ip) set_bit(flag, &(JFS_IP(ip)->cflag)) #define clear_cflag(flag, ip) clear_bit(flag, &(JFS_IP(ip)->cflag)) #define test_cflag(flag, ip) test_bit(flag, &(JFS_IP(ip)->cflag)) diff --git a/trunk/fs/jfs/jfs_lock.h b/trunk/fs/jfs/jfs_lock.h index df48ece4b7a3..7d78e83d7c40 100644 --- a/trunk/fs/jfs/jfs_lock.h +++ b/trunk/fs/jfs/jfs_lock.h @@ -42,7 +42,7 @@ do { \ if (cond) \ break; \ unlock_cmd; \ - io_schedule(); \ + schedule(); \ lock_cmd; \ } \ current->state = TASK_RUNNING; \ diff --git a/trunk/fs/jfs/jfs_metapage.c b/trunk/fs/jfs/jfs_metapage.c index 58deae007507..ceaf03b94935 100644 --- a/trunk/fs/jfs/jfs_metapage.c +++ b/trunk/fs/jfs/jfs_metapage.c @@ -56,7 +56,7 @@ static inline void __lock_metapage(struct metapage *mp) set_current_state(TASK_UNINTERRUPTIBLE); if (metapage_locked(mp)) { unlock_page(mp->page); - io_schedule(); + schedule(); lock_page(mp->page); } } while (trylock_metapage(mp)); diff --git a/trunk/fs/jfs/jfs_txnmgr.c b/trunk/fs/jfs/jfs_txnmgr.c index 6988a1082f58..d558e51b0df8 100644 --- a/trunk/fs/jfs/jfs_txnmgr.c +++ b/trunk/fs/jfs/jfs_txnmgr.c @@ -135,7 +135,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event) add_wait_queue(event, &wait); set_current_state(TASK_UNINTERRUPTIBLE); TXN_UNLOCK(); - io_schedule(); + schedule(); current->state = TASK_RUNNING; remove_wait_queue(event, &wait); } diff --git a/trunk/fs/jfs/jfs_xtree.c b/trunk/fs/jfs/jfs_xtree.c index acc97c46d8a4..e98eb03e5310 100644 --- a/trunk/fs/jfs/jfs_xtree.c +++ b/trunk/fs/jfs/jfs_xtree.c @@ -757,11 +757,6 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, nsplit = 0; /* push (bn, index) of the parent page/entry */ - if (BT_STACK_FULL(btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtSearch!"); - XT_PUTPAGE(mp); - return -EIO; - } BT_PUSH(btstack, bn, index); /* get the child page block number */ @@ -3920,11 +3915,6 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) */ getChild: /* save current parent entry for the child page */ - if (BT_STACK_FULL(&btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtTruncate!"); - XT_PUTPAGE(mp); - return -EIO; - } BT_PUSH(&btstack, bn, index); /* get child page */ @@ -4122,11 +4112,6 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) */ getChild: /* save current parent entry for the child page */ - if (BT_STACK_FULL(&btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtTruncate_pmap!"); - XT_PUTPAGE(mp); - return -EIO; - } BT_PUSH(&btstack, bn, index); /* get child page */ diff --git a/trunk/fs/jfs/namei.c b/trunk/fs/jfs/namei.c index 7ab47561b68d..a6a8c16c872c 100644 --- a/trunk/fs/jfs/namei.c +++ b/trunk/fs/jfs/namei.c @@ -104,8 +104,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, tid = txBegin(dip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dip)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); rc = jfs_init_acl(tid, ip, dip); if (rc) @@ -238,8 +238,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) tid = txBegin(dip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dip)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); rc = jfs_init_acl(tid, ip, dip); if (rc) @@ -365,8 +365,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry) tid = txBegin(dip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dip)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); iplist[0] = dip; iplist[1] = ip; @@ -483,12 +483,12 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry) if ((rc = get_UCSname(&dname, dentry))) goto out; - IWRITE_LOCK(ip, RDWRLOCK_NORMAL); + IWRITE_LOCK(ip); tid = txBegin(dip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dip)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); iplist[0] = dip; iplist[1] = ip; @@ -802,8 +802,8 @@ static int jfs_link(struct dentry *old_dentry, tid = txBegin(ip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dir)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); /* * scan parent directory for entry/freespace @@ -913,8 +913,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, tid = txBegin(dip->i_sb, 0); - mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dip)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); rc = jfs_init_security(tid, ip, dip); if (rc) @@ -1127,7 +1127,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, goto out3; } } else if (new_ip) { - IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); + IWRITE_LOCK(new_ip); /* Init inode for quota operations. */ DQUOT_INIT(new_ip); } @@ -1137,21 +1137,13 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ tid = txBegin(new_dir->i_sb, 0); - /* - * How do we know the locking is safe from deadlocks? - * The vfs does the hard part for us. Any time we are taking nested - * commit_mutexes, the vfs already has i_mutex held on the parent. - * Here, the vfs has already taken i_mutex on both old_dir and new_dir. - */ - mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(new_dir)->commit_mutex); + mutex_lock(&JFS_IP(old_ip)->commit_mutex); if (old_dir != new_dir) - mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex, - COMMIT_MUTEX_SECOND_PARENT); + mutex_lock(&JFS_IP(old_dir)->commit_mutex); if (new_ip) { - mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex, - COMMIT_MUTEX_VICTIM); + mutex_lock(&JFS_IP(new_ip)->commit_mutex); /* * Change existing directory entry to new inode number */ @@ -1365,8 +1357,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, tid = txBegin(dir->i_sb, 0); - mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); - mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); + mutex_lock(&JFS_IP(dir)->commit_mutex); + mutex_lock(&JFS_IP(ip)->commit_mutex); rc = jfs_init_acl(tid, ip, dir); if (rc) diff --git a/trunk/fs/ocfs2/journal.h b/trunk/fs/ocfs2/journal.h index d026b4f27757..e1216364d191 100644 --- a/trunk/fs/ocfs2/journal.h +++ b/trunk/fs/ocfs2/journal.h @@ -306,8 +306,8 @@ int ocfs2_journal_dirty_data(handle_t *handle, * for the dinode, one for the new block. */ #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2) -/* file update (nlink, etc) + directory mtime/ctime + dir entry block */ -#define OCFS2_LINK_CREDITS (2*OCFS2_INODE_UPDATE_CREDITS + 1) +/* file update (nlink, etc) + dir entry block */ +#define OCFS2_LINK_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1) /* inode + dir inode (if we unlink a dir), + dir entry block + orphan * dir inode link */ diff --git a/trunk/include/acpi/acconfig.h b/trunk/include/acpi/acconfig.h index 422f29c06c77..ebc1f697615a 100644 --- a/trunk/include/acpi/acconfig.h +++ b/trunk/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20070126 +#define ACPI_CA_VERSION 0x20060707 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, @@ -115,10 +115,6 @@ #define ACPI_NUM_OWNERID_MASKS 8 -/* Size of the root table array is increased by this increment */ - -#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 - /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) @@ -156,11 +152,6 @@ #define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ #define ACPI_PATH_SEPARATOR '.' -/* Sizes for ACPI table headers */ - -#define ACPI_OEM_ID_SIZE 6 -#define ACPI_OEM_TABLE_ID_SIZE 8 - /* Constants used in searching for the RSDP in low memory */ #define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ diff --git a/trunk/include/acpi/acdebug.h b/trunk/include/acpi/acdebug.h index d626bb1d2973..d8167095caf3 100644 --- a/trunk/include/acpi/acdebug.h +++ b/trunk/include/acpi/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -159,10 +159,6 @@ void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); -#ifdef ACPI_DBG_TRACK_ALLOCATIONS -u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); -#endif - /* * dbfileio - Debugger file I/O commands */ @@ -218,6 +214,4 @@ void acpi_db_prep_namestring(char *name); struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name); -void acpi_db_uint32_to_hex_string(u32 value, char *buffer); - #endif /* __ACDEBUG_H__ */ diff --git a/trunk/include/acpi/acdisasm.h b/trunk/include/acpi/acdisasm.h index 389d772c7d5b..9a7d6921f534 100644 --- a/trunk/include/acpi/acdisasm.h +++ b/trunk/include/acpi/acdisasm.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,11 +97,9 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_CHKSUM 20 #define ACPI_DMT_SPACEID 21 #define ACPI_DMT_GAS 22 -#define ACPI_DMT_DMAR 23 -#define ACPI_DMT_MADT 24 -#define ACPI_DMT_SRAT 25 -#define ACPI_DMT_EXIT 26 -#define ACPI_DMT_SIG 27 +#define ACPI_DMT_MADT 23 +#define ACPI_DMT_SRAT 24 +#define ACPI_DMT_EXIT 25 typedef void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table); @@ -110,7 +108,6 @@ struct acpi_dmtable_data { char *signature; struct acpi_dmtable_info *table_info; ACPI_TABLE_HANDLER table_handler; - char *name; }; struct acpi_op_walk_info { @@ -142,9 +139,7 @@ extern const char *acpi_gbl_match_ops[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf0[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf1[]; -extern struct acpi_dmtable_info acpi_dm_table_info_asf1a[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf2[]; -extern struct acpi_dmtable_info acpi_dm_table_info_asf2a[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf3[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf4[]; extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[]; @@ -152,11 +147,6 @@ extern struct acpi_dmtable_info acpi_dm_table_info_boot[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep[]; extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[]; extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar_hdr[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar_scope[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar0[]; -extern struct acpi_dmtable_info acpi_dm_table_info_dmar1[]; extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[]; extern struct acpi_dmtable_info acpi_dm_table_info_facs[]; extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[]; @@ -211,8 +201,6 @@ void acpi_dm_dump_asf(struct acpi_table_header *table); void acpi_dm_dump_cpep(struct acpi_table_header *table); -void acpi_dm_dump_dmar(struct acpi_table_header *table); - void acpi_dm_dump_fadt(struct acpi_table_header *table); void acpi_dm_dump_srat(struct acpi_table_header *table); @@ -326,7 +314,7 @@ acpi_dm_resource_template(struct acpi_op_walk_info *info, union acpi_parse_object *op, u8 * byte_data, u32 byte_count); -acpi_status acpi_dm_is_resource_template(union acpi_parse_object *op); +u8 acpi_dm_is_resource_template(union acpi_parse_object *op); void acpi_dm_indent(u32 level); diff --git a/trunk/include/acpi/acdispat.h b/trunk/include/acpi/acdispat.h index cb8d2868c8ac..a22fe9cf8493 100644 --- a/trunk/include/acpi/acdispat.h +++ b/trunk/include/acpi/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -210,7 +210,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state); * dsinit */ acpi_status -acpi_ds_initialize_objects(acpi_native_uint table_index, +acpi_ds_initialize_objects(struct acpi_table_desc *table_desc, struct acpi_namespace_node *start_node); /* diff --git a/trunk/include/acpi/acevents.h b/trunk/include/acpi/acevents.h index d23cdf326808..234142828e1a 100644 --- a/trunk/include/acpi/acevents.h +++ b/trunk/include/acpi/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acexcep.h b/trunk/include/acpi/acexcep.h index b73f18a48785..797ca1ea5214 100644 --- a/trunk/include/acpi/acexcep.h +++ b/trunk/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -178,10 +178,8 @@ #define AE_CTRL_BREAK (acpi_status) (0x0009 | AE_CODE_CONTROL) #define AE_CTRL_CONTINUE (acpi_status) (0x000A | AE_CODE_CONTROL) #define AE_CTRL_SKIP (acpi_status) (0x000B | AE_CODE_CONTROL) -#define AE_CTRL_PARSE_CONTINUE (acpi_status) (0x000C | AE_CODE_CONTROL) -#define AE_CTRL_PARSE_PENDING (acpi_status) (0x000D | AE_CODE_CONTROL) -#define AE_CODE_CTRL_MAX 0x000D +#define AE_CODE_CTRL_MAX 0x000B #ifdef DEFINE_ACPI_GLOBALS @@ -293,9 +291,7 @@ char const *acpi_gbl_exception_names_ctrl[] = { "AE_CTRL_TRANSFER", "AE_CTRL_BREAK", "AE_CTRL_CONTINUE", - "AE_CTRL_SKIP", - "AE_CTRL_PARSE_CONTINUE", - "AE_CTRL_PARSE_PENDING" + "AE_CTRL_SKIP" }; #endif /* ACPI GLOBALS */ diff --git a/trunk/include/acpi/acglobal.h b/trunk/include/acpi/acglobal.h index 24c3f05ab367..06972e6637de 100644 --- a/trunk/include/acpi/acglobal.h +++ b/trunk/include/acpi/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,37 @@ #define ACPI_INIT_GLOBAL(a,b) a #endif +/* + * Keep local copies of these FADT-based registers. NOTE: These globals + * are first in this file for alignment reasons on 64-bit systems. + */ +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; + +/***************************************************************************** + * + * Debug support + * + ****************************************************************************/ + +/* Runtime configuration of debug print levels */ + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + +/* Procedure nesting level for debug output */ + +extern u32 acpi_gbl_nesting_level; + +/* Support for dynamic control method tracing mechanism */ + +ACPI_EXTERN u32 acpi_gbl_original_dbg_level; +ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; +ACPI_EXTERN acpi_name acpi_gbl_trace_method_name; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; +ACPI_EXTERN u32 acpi_gbl_trace_flags; + /***************************************************************************** * * Runtime configuration (static defaults that can be overriden at runtime) @@ -102,34 +133,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); */ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); -/***************************************************************************** - * - * Debug support - * - ****************************************************************************/ - -/* Runtime configuration of debug print levels */ - -extern u32 acpi_dbg_level; -extern u32 acpi_dbg_layer; - -/* Procedure nesting level for debug output */ - -extern u32 acpi_gbl_nesting_level; - -/* Event counters */ - -ACPI_EXTERN u32 acpi_gpe_count; - -/* Support for dynamic control method tracing mechanism */ - -ACPI_EXTERN u32 acpi_gbl_original_dbg_level; -ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; -ACPI_EXTERN acpi_name acpi_gbl_trace_method_name; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; -ACPI_EXTERN u32 acpi_gbl_trace_flags; - /***************************************************************************** * * ACPI Table globals @@ -137,29 +140,47 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags; ****************************************************************************/ /* - * acpi_gbl_root_table_list is the master list of ACPI tables found in the - * RSDT/XSDT. + * Table pointers. + * Although these pointers are somewhat redundant with the global acpi_table, + * they are convenient because they are typed pointers. * - * acpi_gbl_FADT is a local copy of the FADT, converted to a common format. + * These tables are single-table only; meaning that there can be at most one + * of each in the system. Each global points to the actual table. + */ +ACPI_EXTERN u32 acpi_gbl_table_flags; +ACPI_EXTERN u32 acpi_gbl_rsdt_table_count; +ACPI_EXTERN struct rsdp_descriptor *acpi_gbl_RSDP; +ACPI_EXTERN struct xsdt_descriptor *acpi_gbl_XSDT; +ACPI_EXTERN struct fadt_descriptor *acpi_gbl_FADT; +ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT; +ACPI_EXTERN struct facs_descriptor *acpi_gbl_FACS; +ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS; +/* + * Since there may be multiple SSDTs and PSDTs, a single pointer is not + * sufficient; Therefore, there isn't one! */ -ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; -ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; -extern acpi_native_uint acpi_gbl_permanent_mmap; -/* These addresses are calculated from FADT address values */ +/* The root table can be either an RSDT or an XSDT */ -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; -ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; +ACPI_EXTERN u8 acpi_gbl_root_table_type; +#define ACPI_TABLE_TYPE_RSDT 'R' +#define ACPI_TABLE_TYPE_XSDT 'X' /* - * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is - * determined by the revision of the DSDT: If the DSDT revision is less than - * 2, use only the lower 32 bits of the internal 64-bit Integer. + * Handle both ACPI 1.0 and ACPI 2.0 Integer widths: + * If we are executing a method that exists in a 32-bit ACPI table, + * use only the lower 32 bits of the (internal) 64-bit Integer. */ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; +/* + * ACPI Table info arrays + */ +extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; +extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1]; + /***************************************************************************** * * Mutual exlusion within ACPICA subsystem @@ -167,7 +188,7 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; ****************************************************************************/ /* - * Predefined mutex objects. This array contains the + * Predefined mutex objects. This array contains the * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. * (The table maps local handles to the real OS handles) */ @@ -176,7 +197,6 @@ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; /* * Global lock semaphore works in conjunction with the actual HW global lock */ -ACPI_EXTERN acpi_mutex acpi_gbl_global_lock_mutex; ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; /* @@ -200,7 +220,6 @@ ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock; /* For ACPI H/W except GPE regis ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; -ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; #endif /* Object caches */ @@ -221,6 +240,7 @@ ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; /* Misc */ +ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count; ACPI_EXTERN u32 acpi_gbl_original_mode; ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; @@ -240,19 +260,12 @@ ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; +extern const u8 acpi_gbl_decode_to8bit[8]; extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; -/* Exception codes */ - -extern char const *acpi_gbl_exception_names_env[]; -extern char const *acpi_gbl_exception_names_pgm[]; -extern char const *acpi_gbl_exception_names_tbl[]; -extern char const *acpi_gbl_exception_names_aml[]; -extern char const *acpi_gbl_exception_names_ctrl[]; - /***************************************************************************** * * Namespace globals diff --git a/trunk/include/acpi/achware.h b/trunk/include/acpi/achware.h index 9df275cf7bc1..29b60a8c0593 100644 --- a/trunk/include/acpi/achware.h +++ b/trunk/include/acpi/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,6 +61,8 @@ /* * hwacpi - high level functions */ +acpi_status acpi_hw_initialize(void); + acpi_status acpi_hw_set_mode(u32 mode); u32 acpi_hw_get_mode(void); @@ -82,7 +84,7 @@ acpi_hw_low_level_read(u32 width, acpi_status acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address *reg); -acpi_status acpi_hw_clear_acpi_status(void); +acpi_status acpi_hw_clear_acpi_status(u32 flags); /* * hwgpe - GPE support diff --git a/trunk/include/acpi/acinterp.h b/trunk/include/acpi/acinterp.h index ce7c9d653910..91586d0d5bb5 100644 --- a/trunk/include/acpi/acinterp.h +++ b/trunk/include/acpi/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -277,6 +277,12 @@ acpi_status acpi_ex_system_do_suspend(acpi_integer time); acpi_status acpi_ex_system_do_stall(u32 time); +acpi_status +acpi_ex_system_acquire_mutex(union acpi_operand_object *time, + union acpi_operand_object *obj_desc); + +acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc); + acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc); acpi_status @@ -445,14 +451,10 @@ acpi_ex_copy_integer_to_buffer_field(union acpi_operand_object *source_desc, /* * exutils - interpreter/scanner utilities */ -void acpi_ex_enter_interpreter(void); +acpi_status acpi_ex_enter_interpreter(void); void acpi_ex_exit_interpreter(void); -void acpi_ex_reacquire_interpreter(void); - -void acpi_ex_relinquish_interpreter(void); - void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); u8 acpi_ex_acquire_global_lock(u32 rule); diff --git a/trunk/include/acpi/aclocal.h b/trunk/include/acpi/aclocal.h index 6f83ddbed3af..063c4b54290f 100644 --- a/trunk/include/acpi/aclocal.h +++ b/trunk/include/acpi/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,8 +80,8 @@ union acpi_parse_object; * table below also! */ #define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */ -#define ACPI_MTX_NAMESPACE 1 /* ACPI Namespace */ -#define ACPI_MTX_TABLES 2 /* Data for ACPI tables */ +#define ACPI_MTX_TABLES 1 /* Data for ACPI tables */ +#define ACPI_MTX_NAMESPACE 2 /* ACPI Namespace */ #define ACPI_MTX_EVENTS 3 /* Data for ACPI events */ #define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */ #define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ @@ -162,7 +162,7 @@ struct acpi_mutex_info { typedef enum { ACPI_IMODE_LOAD_PASS1 = 0x01, ACPI_IMODE_LOAD_PASS2 = 0x02, - ACPI_IMODE_EXECUTE = 0x03 + ACPI_IMODE_EXECUTE = 0x0E } acpi_interpreter_mode; union acpi_name_union { @@ -204,7 +204,7 @@ struct acpi_namespace_node { /* Namespace Node flags */ #define ANOBJ_END_OF_PEER_LIST 0x01 /* End-of-list, Peer field points to parent */ -#define ANOBJ_TEMPORARY 0x02 /* Node is create by a method and is temporary */ +#define ANOBJ_RESERVED 0x02 /* Available for future use */ #define ANOBJ_METHOD_ARG 0x04 /* Node is a method argument */ #define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */ #define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */ @@ -219,42 +219,25 @@ struct acpi_namespace_node { * ACPI Table Descriptor. One per ACPI table */ struct acpi_table_desc { - acpi_physical_address address; + struct acpi_table_desc *prev; + struct acpi_table_desc *next; + struct acpi_table_desc *installed_desc; struct acpi_table_header *pointer; - u32 length; /* Length fixed at 32 bits */ - union acpi_name_union signature; + u8 *aml_start; + u64 physical_address; + acpi_size length; + u32 aml_length; acpi_owner_id owner_id; - u8 flags; + u8 type; + u8 allocation; + u8 loaded_into_namespace; }; -/* Flags for above */ - -#define ACPI_TABLE_ORIGIN_UNKNOWN (0) -#define ACPI_TABLE_ORIGIN_MAPPED (1) -#define ACPI_TABLE_ORIGIN_ALLOCATED (2) -#define ACPI_TABLE_ORIGIN_MASK (3) -#define ACPI_TABLE_IS_LOADED (4) - -/* One internal RSDT for table management */ - -struct acpi_internal_rsdt { - struct acpi_table_desc *tables; +struct acpi_table_list { + struct acpi_table_desc *next; u32 count; - u32 size; - u8 flags; }; -/* Flags for above */ - -#define ACPI_ROOT_ORIGIN_UNKNOWN (0) /* ~ORIGIN_ALLOCATED */ -#define ACPI_ROOT_ORIGIN_ALLOCATED (1) -#define ACPI_ROOT_ALLOW_RESIZE (2) - -/* Predefined (fixed) table indexes */ - -#define ACPI_TABLE_INDEX_DSDT (0) -#define ACPI_TABLE_INDEX_FACS (1) - struct acpi_find_context { char *search_for; acpi_handle *list; @@ -367,7 +350,7 @@ struct acpi_gpe_event_info { union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */ struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ u8 flags; /* Misc info about this GPE */ - u8 gpe_number; /* This GPE */ + u8 register_bit; /* This GPE bit within the register */ }; /* Information about a GPE register pair, one per each status/enable pair in an array */ @@ -872,30 +855,12 @@ struct acpi_bit_register_info { ****************************************************************************/ struct acpi_db_method_info { - acpi_handle main_thread_gate; - acpi_handle thread_complete_gate; - u32 *threads; - u32 num_threads; - u32 num_created; - u32 num_completed; - + acpi_handle thread_gate; char *name; + char **args; u32 flags; u32 num_loops; char pathname[128]; - char **args; - - /* - * Arguments to be passed to method for the command - * Threads - - * the Number of threads, ID of current thread and - * Index of current thread inside all them created. - */ - char init_args; - char *arguments[4]; - char num_threads_str[11]; - char id_of_thread_str[11]; - char index_of_thread_str[11]; }; struct acpi_integrity_info { @@ -954,8 +919,6 @@ struct acpi_memory_list { u32 total_allocated; u32 total_freed; - u32 max_occupied; - u32 total_size; u32 current_total_size; u32 requests; u32 hits; diff --git a/trunk/include/acpi/acmacros.h b/trunk/include/acpi/acmacros.h index 8948a6461834..192fa095a515 100644 --- a/trunk/include/acpi/acmacros.h +++ b/trunk/include/acpi/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,12 +55,25 @@ #define ACPI_SET_BIT(target,bit) ((target) |= (bit)) #define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit)) #define ACPI_MIN(a,b) (((a)<(b))?(a):(b)) -#define ACPI_MAX(a,b) (((a)>(b))?(a):(b)) /* Size calculation */ #define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) +#if ACPI_MACHINE_WIDTH == 16 + +/* + * For 16-bit addresses, we have to assume that the upper 32 bits + * (out of 64) are zero. + */ +#define ACPI_LODWORD(l) ((u32)(l)) +#define ACPI_HIDWORD(l) ((u32)(0)) + +#define ACPI_GET_ADDRESS(a) ((a).lo) +#define ACPI_STORE_ADDRESS(a,b) {(a).hi=0;(a).lo=(u32)(b);} +#define ACPI_VALID_ADDRESS(a) ((a).hi | (a).lo) + +#else #ifdef ACPI_NO_INTEGER64_SUPPORT /* * acpi_integer is 32-bits, no 64-bit support on this platform @@ -68,6 +81,10 @@ #define ACPI_LODWORD(l) ((u32)(l)) #define ACPI_HIDWORD(l) ((u32)(0)) +#define ACPI_GET_ADDRESS(a) (a) +#define ACPI_STORE_ADDRESS(a,b) ((a)=(b)) +#define ACPI_VALID_ADDRESS(a) (a) + #else /* @@ -75,6 +92,11 @@ */ #define ACPI_LODWORD(l) ((u32)(u64)(l)) #define ACPI_HIDWORD(l) ((u32)(((*(struct uint64_struct *)(void *)(&l))).hi)) + +#define ACPI_GET_ADDRESS(a) (a) +#define ACPI_STORE_ADDRESS(a,b) ((a)=(acpi_physical_address)(b)) +#define ACPI_VALID_ADDRESS(a) (a) +#endif #endif /* @@ -112,8 +134,15 @@ #define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i) #define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p,(void *) NULL) #define ACPI_OFFSET(d,f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL) + +#if ACPI_MACHINE_WIDTH == 16 +#define ACPI_STORE_POINTER(d,s) ACPI_MOVE_32_TO_32(d,s) +#define ACPI_PHYSADDR_TO_PTR(i) (void *)(i) +#define ACPI_PTR_TO_PHYSADDR(i) (u32) ACPI_CAST_PTR (u8,(i)) +#else #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) +#endif #ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED #define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b))) @@ -194,6 +223,28 @@ /* The hardware supports unaligned transfers, just do the little-endian move */ +#if ACPI_MACHINE_WIDTH == 16 + +/* No 64-bit integers */ +/* 16-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_16_TO_16(d,s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s) +#define ACPI_MOVE_16_TO_32(d,s) *(u32 *)(void *)(d) = *(u16 *)(void *)(s) +#define ACPI_MOVE_16_TO_64(d,s) ACPI_MOVE_16_TO_32(d,s) + +/* 32-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_32_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */ +#define ACPI_MOVE_32_TO_32(d,s) *(u32 *)(void *)(d) = *(u32 *)(void *)(s) +#define ACPI_MOVE_32_TO_64(d,s) ACPI_MOVE_32_TO_32(d,s) + +/* 64-bit source, 16/32/64 destination */ + +#define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */ +#define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */ +#define ACPI_MOVE_64_TO_64(d,s) ACPI_MOVE_32_TO_32(d,s) + +#else /* 16-bit source, 16/32/64 destination */ #define ACPI_MOVE_16_TO_16(d,s) *(u16 *)(void *)(d) = *(u16 *)(void *)(s) @@ -211,6 +262,7 @@ #define ACPI_MOVE_64_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) /* Truncate to 16 */ #define ACPI_MOVE_64_TO_32(d,s) ACPI_MOVE_32_TO_32(d,s) /* Truncate to 32 */ #define ACPI_MOVE_64_TO_64(d,s) *(u64 *)(void *)(d) = *(u64 *)(void *)(s) +#endif #else /* @@ -255,7 +307,10 @@ /* Macros based on machine integer width */ -#if ACPI_MACHINE_WIDTH == 32 +#if ACPI_MACHINE_WIDTH == 16 +#define ACPI_MOVE_SIZE_TO_16(d,s) ACPI_MOVE_16_TO_16(d,s) + +#elif ACPI_MACHINE_WIDTH == 32 #define ACPI_MOVE_SIZE_TO_16(d,s) ACPI_MOVE_32_TO_16(d,s) #elif ACPI_MACHINE_WIDTH == 64 @@ -640,6 +695,16 @@ #define ACPI_DEBUGGER_EXEC(a) #endif +/* + * For 16-bit code, we want to shrink some things even though + * we are using ACPI_DEBUG_OUTPUT to get the debug output + */ +#if ACPI_MACHINE_WIDTH == 16 +#undef ACPI_DEBUG_ONLY_MEMBERS +#undef _VERBOSE_STRUCTURES +#define ACPI_DEBUG_ONLY_MEMBERS(a) +#endif + #ifdef ACPI_DEBUG_OUTPUT /* * 1) Set name to blanks diff --git a/trunk/include/acpi/acnames.h b/trunk/include/acpi/acnames.h index 34bfae8a05f3..b67da3636899 100644 --- a/trunk/include/acpi/acnames.h +++ b/trunk/include/acpi/acnames.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acnamesp.h b/trunk/include/acpi/acnamesp.h index 535b7e1c41bc..83b52f9f899a 100644 --- a/trunk/include/acpi/acnamesp.h +++ b/trunk/include/acpi/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,13 +65,9 @@ #define ACPI_NS_ERROR_IF_FOUND 0x08 #define ACPI_NS_PREFIX_IS_SCOPE 0x10 #define ACPI_NS_EXTERNAL 0x20 -#define ACPI_NS_TEMPORARY 0x40 -/* Flags for acpi_ns_walk_namespace */ - -#define ACPI_NS_WALK_NO_UNLOCK 0 -#define ACPI_NS_WALK_UNLOCK 0x01 -#define ACPI_NS_WALK_TEMP_NODES 0x02 +#define ACPI_NS_WALK_UNLOCK TRUE +#define ACPI_NS_WALK_NO_UNLOCK FALSE /* * nsinit - Namespace initialization @@ -86,7 +82,7 @@ acpi_status acpi_ns_initialize_devices(void); acpi_status acpi_ns_load_namespace(void); acpi_status -acpi_ns_load_table(acpi_native_uint table_index, +acpi_ns_load_table(struct acpi_table_desc *table_desc, struct acpi_namespace_node *node); /* @@ -96,7 +92,7 @@ acpi_status acpi_ns_walk_namespace(acpi_object_type type, acpi_handle start_object, u32 max_depth, - u32 flags, + u8 unlock_before_callback, acpi_walk_callback user_function, void *context, void **return_value); @@ -110,12 +106,11 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, * nsparse - table parsing */ acpi_status -acpi_ns_parse_table(acpi_native_uint table_index, - struct acpi_namespace_node *start_node); +acpi_ns_parse_table(struct acpi_table_desc *table_desc, + struct acpi_namespace_node *scope); acpi_status -acpi_ns_one_complete_parse(acpi_native_uint pass_number, - acpi_native_uint table_index); +acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc); /* * nsaccess - Top-level namespace access diff --git a/trunk/include/acpi/acobject.h b/trunk/include/acpi/acobject.h index 04e9735a6742..8fdee31119f3 100644 --- a/trunk/include/acpi/acobject.h +++ b/trunk/include/acpi/acobject.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,15 +52,7 @@ * to the interpreter, and to keep track of the various handlers such as * address space handlers and notify handlers. The object is a constant * size in order to allow it to be cached and reused. - * - * Note: The object is optimized to be aligned and will not work if it is - * byte-packed. */ -#if ACPI_MACHINE_WIDTH == 64 -#pragma pack(8) -#else -#pragma pack(4) -#endif /******************************************************************************* * @@ -109,8 +101,7 @@ struct acpi_object_common { ACPI_OBJECT_COMMON_HEADER}; struct acpi_object_integer { - ACPI_OBJECT_COMMON_HEADER u8 fill[3]; /* Prevent warning on some compilers */ - acpi_integer value; + ACPI_OBJECT_COMMON_HEADER acpi_integer value; }; /* @@ -212,9 +203,7 @@ struct acpi_object_power_resource { }; struct acpi_object_processor { - ACPI_OBJECT_COMMON_HEADER - /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */ - u8 proc_id; + ACPI_OBJECT_COMMON_HEADER u8 proc_id; u8 length; ACPI_COMMON_NOTIFY_INFO acpi_io_address address; }; @@ -417,6 +406,4 @@ union acpi_descriptor { union acpi_parse_object op; }; -#pragma pack() - #endif /* _ACOBJECT_H */ diff --git a/trunk/include/acpi/acopcode.h b/trunk/include/acpi/acopcode.h index e6f76a280a94..7659a46bc432 100644 --- a/trunk/include/acpi/acopcode.h +++ b/trunk/include/acpi/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -257,7 +257,7 @@ #define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE #define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE -#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION_OR_BUFFER,ARGI_TARGETREF) +#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION_OR_FIELD,ARGI_TARGETREF) #define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_ANYTYPE) #define ARGI_LOCAL0 ARG_NONE #define ARGI_LOCAL1 ARG_NONE diff --git a/trunk/include/acpi/acoutput.h b/trunk/include/acpi/acoutput.h index 7812267b577f..8d5039d0b430 100644 --- a/trunk/include/acpi/acoutput.h +++ b/trunk/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acparser.h b/trunk/include/acpi/acparser.h index 85c358e21014..9d49d3c41cd9 100644 --- a/trunk/include/acpi/acparser.h +++ b/trunk/include/acpi/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acpi.h b/trunk/include/acpi/acpi.h index 2e5f00d3ea0d..b9a39d1009bd 100644 --- a/trunk/include/acpi/acpi.h +++ b/trunk/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 0d9f984a60a1..fdd10953b2b6 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -59,6 +59,7 @@ acpi_evaluate_reference(acpi_handle handle, #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; +extern struct fadt_descriptor acpi_fadt; enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, @@ -91,12 +92,13 @@ typedef int (*acpi_op_remove) (struct acpi_device * device, int type); typedef int (*acpi_op_lock) (struct acpi_device * device, int type); typedef int (*acpi_op_start) (struct acpi_device * device); typedef int (*acpi_op_stop) (struct acpi_device * device, int type); -typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state); -typedef int (*acpi_op_resume) (struct acpi_device * device); +typedef int (*acpi_op_suspend) (struct acpi_device * device, int state); +typedef int (*acpi_op_resume) (struct acpi_device * device, int state); typedef int (*acpi_op_scan) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); -typedef int (*acpi_op_shutdown) (struct acpi_device * device); +typedef int (*acpi_op_match) (struct acpi_device * device, + struct acpi_driver * driver); struct acpi_bus_ops { u32 acpi_op_add:1; @@ -109,7 +111,7 @@ struct acpi_bus_ops { u32 acpi_op_scan:1; u32 acpi_op_bind:1; u32 acpi_op_unbind:1; - u32 acpi_op_shutdown:1; + u32 acpi_op_match:1; u32 reserved:21; }; @@ -124,16 +126,16 @@ struct acpi_device_ops { acpi_op_scan scan; acpi_op_bind bind; acpi_op_unbind unbind; - acpi_op_shutdown shutdown; + acpi_op_match match; }; struct acpi_driver { + struct list_head node; char name[80]; char class[80]; + atomic_t references; char *ids; /* Supported Hardware IDs */ struct acpi_device_ops ops; - struct device_driver drv; - struct module *owner; }; /* @@ -183,7 +185,7 @@ struct acpi_device_dir { typedef char acpi_bus_id[5]; typedef unsigned long acpi_bus_address; -typedef char acpi_hardware_id[15]; +typedef char acpi_hardware_id[9]; typedef char acpi_unique_id[9]; typedef char acpi_device_name[40]; typedef char acpi_device_class[20]; @@ -294,14 +296,11 @@ struct acpi_device { struct acpi_device_ops ops; struct acpi_driver *driver; void *driver_data; + struct kobject kobj; struct device dev; - struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ - enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ }; #define acpi_driver_data(d) ((d)->driver_data) -#define to_acpi_device(d) container_of(d, struct acpi_device, dev) -#define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) /* * Events diff --git a/trunk/include/acpi/acpi_drivers.h b/trunk/include/acpi/acpi_drivers.h index 4dc8a5043ef0..6a5bdcefec64 100644 --- a/trunk/include/acpi/acpi_drivers.h +++ b/trunk/include/acpi/acpi_drivers.h @@ -36,14 +36,13 @@ /* _HID definitions */ -#define ACPI_POWER_HID "power_resource" -#define ACPI_PROCESSOR_HID "ACPI0007" -#define ACPI_SYSTEM_HID "acpi_system" -#define ACPI_THERMAL_HID "thermal" -#define ACPI_BUTTON_HID_POWERF "button_power" -#define ACPI_BUTTON_HID_SLEEPF "button_sleep" -#define ACPI_VIDEO_HID "video" -#define ACPI_BAY_HID "bay" +#define ACPI_POWER_HID "ACPI_PWR" +#define ACPI_PROCESSOR_HID "ACPI_CPU" +#define ACPI_SYSTEM_HID "ACPI_SYS" +#define ACPI_THERMAL_HID "ACPI_THM" +#define ACPI_BUTTON_HID_POWERF "ACPI_FPB" +#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB" + /* -------------------------------------------------------------------------- PCI -------------------------------------------------------------------------- */ diff --git a/trunk/include/acpi/acpiosxf.h b/trunk/include/acpi/acpiosxf.h index 781394b9efe0..0cd63bce0ae4 100644 --- a/trunk/include/acpi/acpiosxf.h +++ b/trunk/include/acpi/acpiosxf.h @@ -8,7 +8,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -85,7 +85,7 @@ acpi_status acpi_os_terminate(void); /* * ACPI Table interfaces */ -acpi_physical_address acpi_os_get_root_pointer(void); +acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *address); acpi_status acpi_os_predefined_override(const struct acpi_predefined_names *init_val, @@ -143,7 +143,9 @@ void acpi_os_release_mutex(acpi_mutex handle); */ void *acpi_os_allocate(acpi_size size); -void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_native_uint length); +acpi_status +acpi_os_map_memory(acpi_physical_address physical_address, + acpi_size size, void __iomem ** logical_address); void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); diff --git a/trunk/include/acpi/acpixf.h b/trunk/include/acpi/acpixf.h index e08f7df85a4f..81458767a90e 100644 --- a/trunk/include/acpi/acpixf.h +++ b/trunk/include/acpi/acpixf.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,10 +51,6 @@ /* * Global interfaces */ -acpi_status -acpi_initialize_tables(struct acpi_table_desc *initial_storage, - u32 initial_table_count, u8 allow_resize); - acpi_status acpi_initialize_subsystem(void); acpi_status acpi_enable_subsystem(u32 flags); @@ -96,28 +92,30 @@ void acpi_free(void *address); /* * ACPI table manipulation interfaces */ -acpi_status acpi_reallocate_root_table(void); - -acpi_status acpi_find_root_pointer(acpi_native_uint * rsdp_address); +acpi_status +acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address); acpi_status acpi_load_tables(void); acpi_status acpi_load_table(struct acpi_table_header *table_ptr); -acpi_status acpi_unload_table_id(acpi_owner_id id); +acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id); +#ifdef ACPI_FUTURE_USAGE +acpi_status acpi_unload_table(acpi_table_type table_type); acpi_status -acpi_get_table_header(acpi_string signature, - acpi_native_uint instance, - struct acpi_table_header *out_table_header); +acpi_get_table_header(acpi_table_type table_type, + u32 instance, struct acpi_table_header *out_table_header); +#endif /* ACPI_FUTURE_USAGE */ acpi_status -acpi_get_table(acpi_string signature, - acpi_native_uint instance, struct acpi_table_header **out_table); +acpi_get_table(acpi_table_type table_type, + u32 instance, struct acpi_buffer *ret_buffer); acpi_status -acpi_get_table_by_index(acpi_native_uint table_index, - struct acpi_table_header **out_table); +acpi_get_firmware_table(acpi_string signature, + u32 instance, + u32 flags, struct acpi_table_header **table_pointer); /* * Namespace and name interfaces @@ -312,9 +310,9 @@ acpi_resource_to_address64(struct acpi_resource *resource, /* * Hardware (ACPI device) interfaces */ -acpi_status acpi_get_register(u32 register_id, u32 * return_value); +acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags); -acpi_status acpi_set_register(u32 register_id, u32 value); +acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags); acpi_status acpi_set_firmware_waking_vector(acpi_physical_address physical_address); diff --git a/trunk/include/acpi/acresrc.h b/trunk/include/acpi/acresrc.h index 9486ab266a5e..80a3b33571b4 100644 --- a/trunk/include/acpi/acresrc.h +++ b/trunk/include/acpi/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/acstruct.h b/trunk/include/acpi/acstruct.h index aeb4498e5e06..5e8095f0f78f 100644 --- a/trunk/include/acpi/acstruct.h +++ b/trunk/include/acpi/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -139,8 +139,7 @@ struct acpi_init_walk_info { u16 buffer_init; u16 package_init; u16 object_count; - acpi_owner_id owner_id; - acpi_native_uint table_index; + struct acpi_table_desc *table_desc; }; struct acpi_get_devices_info { diff --git a/trunk/include/acpi/actables.h b/trunk/include/acpi/actables.h index 2b9f46f9da4d..4dbaf02fe526 100644 --- a/trunk/include/acpi/actables.h +++ b/trunk/include/acpi/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,75 +44,105 @@ #ifndef __ACTABLES_H__ #define __ACTABLES_H__ -acpi_status acpi_allocate_root_table(u32 initial_table_count); +/* Used in acpi_tb_map_acpi_table for size parameter if table header is to be used */ + +#define SIZE_IN_HEADER 0 /* - * tbfadt - FADT parse/convert/validate + * tbconvrt - Table conversion routines */ -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); +acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info); + +acpi_status acpi_tb_convert_table_fadt(void); -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); +acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info); + +u32 +acpi_tb_get_table_count(struct rsdp_descriptor *RSDP, + struct acpi_table_header *RSDT); /* - * tbfind - find ACPI table + * tbget - Table "get" routines */ acpi_status -acpi_tb_find_table(char *signature, - char *oem_id, - char *oem_table_id, acpi_native_uint * table_index); +acpi_tb_get_table(struct acpi_pointer *address, + struct acpi_table_desc *table_info); + +acpi_status +acpi_tb_get_table_header(struct acpi_pointer *address, + struct acpi_table_header *return_header); + +acpi_status +acpi_tb_get_table_body(struct acpi_pointer *address, + struct acpi_table_header *header, + struct acpi_table_desc *table_info); + +acpi_status +acpi_tb_get_table_ptr(acpi_table_type table_type, + u32 instance, struct acpi_table_header **table_ptr_loc); + +acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address); + +void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address); + +acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr); /* - * tbinstal - Table removal and deletion + * tbgetall - get multiple required tables */ -acpi_status acpi_tb_resize_root_table_list(void); +acpi_status acpi_tb_get_required_tables(void); -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); +/* + * tbinstall - Table installation + */ +acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info); acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, - acpi_native_uint * table_index); +acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type); acpi_status -acpi_tb_store_table(acpi_physical_address address, - struct acpi_table_header *table, - u32 length, u8 flags, acpi_native_uint * table_index); +acpi_tb_init_table_descriptor(acpi_table_type table_type, + struct acpi_table_desc *table_info); -void acpi_tb_delete_table(struct acpi_table_desc *table_desc); - -void acpi_tb_terminate(void); +/* + * tbremove - Table removal and deletion + */ +void acpi_tb_delete_all_tables(void); -void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index); +void acpi_tb_delete_tables_by_type(acpi_table_type type); -acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index); +void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc); -acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index); +struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc + *table_desc); +/* + * tbxfroot - RSDP, RSDT utilities + */ acpi_status -acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id); +acpi_tb_find_table(char *signature, + char *oem_id, + char *oem_table_id, struct acpi_table_header **table_ptr); -u8 acpi_tb_is_table_loaded(acpi_native_uint table_index); +acpi_status acpi_tb_get_table_rsdt(void); -void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded); +acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp); /* - * tbutils - table manager utilities + * tbutils - common table utilities */ -u8 acpi_tb_tables_loaded(void); +acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc); -void -acpi_tb_print_table_header(acpi_physical_address address, - struct acpi_table_header *header); +acpi_status +acpi_tb_verify_table_checksum(struct acpi_table_header *table_header); -u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length); +u8 acpi_tb_sum_table(void *buffer, u32 length); -acpi_status -acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); +u8 acpi_tb_generate_checksum(struct acpi_table_header *table); -void -acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, acpi_native_uint table_index); +void acpi_tb_set_checksum(struct acpi_table_header *table); acpi_status -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags); +acpi_tb_validate_table_header(struct acpi_table_header *table_header); #endif /* __ACTABLES_H__ */ diff --git a/trunk/include/acpi/actbl.h b/trunk/include/acpi/actbl.h index 09469e7db6a5..b125ceed9cb7 100644 --- a/trunk/include/acpi/actbl.h +++ b/trunk/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,15 +48,15 @@ * Values for description table header signatures. Useful because they make * it more difficult to inadvertently type in the wrong signature. */ -#define ACPI_SIG_DSDT "DSDT" /* Differentiated System Description Table */ -#define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */ -#define ACPI_SIG_FACS "FACS" /* Firmware ACPI Control Structure */ -#define ACPI_SIG_PSDT "PSDT" /* Persistent System Description Table */ -#define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Pointer */ -#define ACPI_SIG_RSDT "RSDT" /* Root System Description Table */ -#define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */ -#define ACPI_SIG_SSDT "SSDT" /* Secondary System Description Table */ -#define ACPI_RSDP_NAME "RSDP" /* Short name for RSDP, not signature */ +#define DSDT_SIG "DSDT" /* Differentiated System Description Table */ +#define FADT_SIG "FACP" /* Fixed ACPI Description Table */ +#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ +#define PSDT_SIG "PSDT" /* Persistent System Description Table */ +#define RSDP_SIG "RSD PTR " /* Root System Description Pointer */ +#define RSDT_SIG "RSDT" /* Root System Description Table */ +#define XSDT_SIG "XSDT" /* Extended System Description Table */ +#define SSDT_SIG "SSDT" /* Secondary System Description Table */ +#define RSDP_NAME "RSDP" /* * All tables and structures must be byte-packed to match the ACPI @@ -83,29 +83,27 @@ * ******************************************************************************/ +#define ACPI_TABLE_HEADER_DEF \ + char signature[4]; /* ASCII table signature */\ + u32 length; /* Length of table in bytes, including this header */\ + u8 revision; /* ACPI Specification minor version # */\ + u8 checksum; /* To make sum of entire table == 0 */\ + char oem_id[6]; /* ASCII OEM identification */\ + char oem_table_id[8]; /* ASCII OEM table identification */\ + u32 oem_revision; /* OEM revision number */\ + char asl_compiler_id[4]; /* ASCII ASL compiler vendor ID */\ + u32 asl_compiler_revision; /* ASL compiler version */ + struct acpi_table_header { - char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ - u32 length; /* Length of table in bytes, including this header */ - u8 revision; /* ACPI Specification minor version # */ - u8 checksum; /* To make sum of entire table == 0 */ - char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ - char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ - u32 oem_revision; /* OEM revision number */ - char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */ - u32 asl_compiler_revision; /* ASL compiler version */ -}; +ACPI_TABLE_HEADER_DEF}; /* * GAS - Generic Address Structure (ACPI 2.0+) - * - * Note: Since this structure is used in the ACPI tables, it is byte aligned. - * If misalignment is not supported, access to the Address field must be - * performed with care. */ struct acpi_generic_address { - u8 space_id; /* Address space where struct or register exists */ - u8 bit_width; /* Size in bits of given register */ - u8 bit_offset; /* Bit offset within the register */ + u8 address_space_id; /* Address space where struct or register exists */ + u8 register_bit_width; /* Size in bits of given register */ + u8 register_bit_offset; /* Bit offset within the register */ u8 access_width; /* Minimum Access size (ACPI 3.0) */ u64 address; /* 64-bit address of struct or register */ }; @@ -116,10 +114,10 @@ struct acpi_generic_address { * ******************************************************************************/ -struct acpi_table_rsdp { +struct rsdp_descriptor { char signature[8]; /* ACPI signature, contains "RSD PTR " */ u8 checksum; /* ACPI 1.0 checksum */ - char oem_id[ACPI_OEM_ID_SIZE]; /* OEM identification */ + char oem_id[6]; /* OEM identification */ u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */ u32 length; /* Table length in bytes, including header (ACPI 2.0+) */ @@ -136,14 +134,12 @@ struct acpi_table_rsdp { * ******************************************************************************/ -struct acpi_table_rsdt { - struct acpi_table_header header; /* Common ACPI table header */ - u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +struct rsdt_descriptor { + ACPI_TABLE_HEADER_DEF u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ }; -struct acpi_table_xsdt { - struct acpi_table_header header; /* Common ACPI table header */ - u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ +struct xsdt_descriptor { + ACPI_TABLE_HEADER_DEF u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ }; /******************************************************************************* @@ -152,27 +148,36 @@ struct acpi_table_xsdt { * ******************************************************************************/ -struct acpi_table_facs { +struct facs_descriptor { char signature[4]; /* ASCII table signature */ u32 length; /* Length of structure, in bytes */ u32 hardware_signature; /* Hardware configuration signature */ u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector */ u32 global_lock; /* Global Lock for shared hardware resources */ - u32 flags; + + /* Flags (32 bits) */ + + u8 S4bios_f:1; /* 00: S4BIOS support is present */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved1[3]; /* 08-31: Reserved, must be zero */ + u64 xfirmware_waking_vector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */ u8 version; /* Version of this table (ACPI 2.0+) */ u8 reserved[31]; /* Reserved, must be zero */ }; -/* Flag macros */ - -#define ACPI_FACS_S4_BIOS_PRESENT (1) /* 00: S4BIOS support is present */ - -/* Global lock flags */ - #define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */ #define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */ +/* + * Common FACS - This is a version-independent FACS structure used for internal use only + */ +struct acpi_common_facs { + u32 *global_lock; + u64 *firmware_waking_vector; + u8 vector_width; +}; + /******************************************************************************* * * FADT - Fixed ACPI Description Table (Signature "FACP") @@ -181,98 +186,121 @@ struct acpi_table_facs { /* Fields common to all versions of the FADT */ -struct acpi_table_fadt { - struct acpi_table_header header; /* Common ACPI table header */ - u32 facs; /* 32-bit physical address of FACS */ - u32 dsdt; /* 32-bit physical address of DSDT */ - u8 model; /* System Interrupt Model (ACPI 1.0) - not used in ACPI 2.0+ */ - u8 preferred_profile; /* Conveys preferred power management profile to OSPM. */ - u16 sci_interrupt; /* System vector of SCI interrupt */ - u32 smi_command; /* 32-bit Port address of SMI command port */ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ - u8 S4bios_request; /* Value to write to SMI CMD to enter S4BIOS state */ - u8 pstate_control; /* Processor performance state control */ - u32 pm1a_event_block; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */ - u32 pm1b_event_block; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */ - u32 pm1a_control_block; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */ - u32 pm1b_control_block; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */ - u32 pm2_control_block; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */ - u32 pm_timer_block; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 gpe0_block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */ - u32 gpe1_block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */ - u8 pm1_event_length; /* Byte Length of ports at pm1x_event_block */ - u8 pm1_control_length; /* Byte Length of ports at pm1x_control_block */ - u8 pm2_control_length; /* Byte Length of ports at pm2_control_block */ - u8 pm_timer_length; /* Byte Length of ports at pm_timer_block */ - u8 gpe0_block_length; /* Byte Length of ports at gpe0_block */ - u8 gpe1_block_length; /* Byte Length of ports at gpe1_block */ - u8 gpe1_base; /* Offset in GPE number space where GPE1 events start */ - u8 cst_control; /* Support for the _CST object and C States change notification */ - u16 C2latency; /* Worst case HW latency to enter/exit C2 state */ - u16 C3latency; /* Worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* Processor's memory cache line width, in bytes */ - u16 flush_stride; /* Number of flush strides that need to be read */ - u8 duty_offset; /* Processor duty cycle index in processor's P_CNT reg */ - u8 duty_width; /* Processor duty cycle value bit width in P_CNT register. */ - u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */ - u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* Index to century in RTC CMOS RAM */ - u16 boot_flags; /* IA-PC Boot Architecture Flags. See Table 5-10 for description */ - u8 reserved; /* Reserved, must be zero */ - u32 flags; /* Miscellaneous flag bits (see below for individual flags) */ - struct acpi_generic_address reset_register; /* 64-bit address of the Reset register */ +#define ACPI_FADT_COMMON \ + ACPI_TABLE_HEADER_DEF \ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ + u16 sci_int; /* System vector of SCI interrupt */ \ + u32 smi_cmd; /* Port address of SMI command port */ \ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ + u8 pstate_cnt; /* Processor performance state control*/ \ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Event Reg Blk */ \ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Event Reg Blk */ \ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ + u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ + u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ \ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ \ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ + u16 flush_size; /* Processor's memory cache line width, in bytes */ \ + u16 flush_stride; /* Number of flush strides that need to be read */ \ + 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 */ \ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \ + u8 reserved2; /* Reserved, must be zero */ + +/* + * ACPI 2.0+ FADT + */ +struct fadt_descriptor { + ACPI_FADT_COMMON + /* Flags (32 bits) */ + u8 wb_invd:1; /* 00: The wbinvd instruction works properly */ + u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */ + u8 proc_c1:1; /* 02: All processors support C1 state */ + u8 plvl2_up:1; /* 03: C2 state works on MP system */ + u8 pwr_button:1; /* 04: Power button is handled as a generic feature */ + u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */ + u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */ + u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */ + u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */ + u8 dock_cap:1; /* 09: Docking supported */ + u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */ + u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */ + u8 headless:1; /* 12: No local video capabilities or local input devices */ + u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */ + + u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ + u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ + u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ + u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */ + u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */ + u8 force_apic_physical_destination_mode:1; /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */ + u8:4; /* 20-23: Reserved, must be zero */ + u8 reserved3; /* 24-31: Reserved, must be zero */ + + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ u8 reset_value; /* Value to write to the reset_register port to reset the system */ - u8 reserved4[3]; /* Reserved, must be zero */ - u64 Xfacs; /* 64-bit physical address of FACS */ + u8 reserved4[3]; /* These three bytes must be zero */ + u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ u64 Xdsdt; /* 64-bit physical address of DSDT */ - struct acpi_generic_address xpm1a_event_block; /* 64-bit Extended Power Mgt 1a Event Reg Blk address */ - struct acpi_generic_address xpm1b_event_block; /* 64-bit Extended Power Mgt 1b Event Reg Blk address */ - struct acpi_generic_address xpm1a_control_block; /* 64-bit Extended Power Mgt 1a Control Reg Blk address */ - struct acpi_generic_address xpm1b_control_block; /* 64-bit Extended Power Mgt 1b Control Reg Blk address */ - struct acpi_generic_address xpm2_control_block; /* 64-bit Extended Power Mgt 2 Control Reg Blk address */ - struct acpi_generic_address xpm_timer_block; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ - struct acpi_generic_address xgpe0_block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ - struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ + struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */ + struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */ + struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ + struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ + struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ + struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ + struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */ + struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */ }; -/* FADT flags */ - -#define ACPI_FADT_WBINVD (1) /* 00: The wbinvd instruction works properly */ -#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: The wbinvd flushes but does not invalidate */ -#define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: All processors support C1 state */ -#define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: C2 state works on MP system */ -#define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: Power button is handled as a generic feature */ -#define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: Sleep button is handled as a generic feature, or not present */ -#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: RTC wakeup stat not in fixed register space */ -#define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: RTC wakeup stat not possible from S4 */ -#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: tmr_val is 32 bits 0=24-bits */ -#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: Docking supported */ -#define ACPI_FADT_RESET_REGISTER (1<<10) /* 10: System reset via the FADT RESET_REG supported */ -#define ACPI_FADT_SEALED_CASE (1<<11) /* 11: No internal expansion capabilities and case is sealed */ -#define ACPI_FADT_HEADLESS (1<<12) /* 12: No local video capabilities or local input devices */ -#define ACPI_FADT_SLEEP_TYPE (1<<13) /* 13: Must execute native instruction after writing SLP_TYPx register */ -#define ACPI_FADT_PCI_EXPRESS_WAKE (1<<14) /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ -#define ACPI_FADT_PLATFORM_CLOCK (1<<15) /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ -#define ACPI_FADT_S4_RTC_VALID (1<<16) /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ -#define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: System is compatible with remote power on (ACPI 3.0) */ -#define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: All local APICs must use cluster model (ACPI 3.0) */ -#define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */ +/* + * "Down-revved" ACPI 2.0 FADT descriptor + * Defined here to allow compiler to generate the length of the struct + */ +struct fadt_descriptor_rev2_minus { + ACPI_FADT_COMMON u32 flags; + struct acpi_generic_address reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the reset_register port to reset the system. */ + u8 reserved7[3]; /* Reserved, must be zero */ +}; /* - * FADT Prefered Power Management Profiles + * ACPI 1.0 FADT + * Defined here to allow compiler to generate the length of the struct */ -enum acpi_prefered_pm_profiles { - PM_UNSPECIFIED = 0, - PM_DESKTOP = 1, - PM_MOBILE = 2, - PM_WORKSTATION = 3, - PM_ENTERPRISE_SERVER = 4, - PM_SOHO_SERVER = 5, - PM_APPLIANCE_PC = 6 +struct fadt_descriptor_rev1 { + ACPI_FADT_COMMON u32 flags; }; -/* FADT Boot Arch Flags */ +/* FADT: Prefered Power Management Profiles */ + +#define PM_UNSPECIFIED 0 +#define PM_DESKTOP 1 +#define PM_MOBILE 2 +#define PM_WORKSTATION 3 +#define PM_ENTERPRISE_SERVER 4 +#define PM_SOHO_SERVER 5 +#define PM_APPLIANCE_PC 6 + +/* FADT: Boot Arch Flags */ #define BAF_LEGACY_DEVICES 0x0001 #define BAF_8042_KEYBOARD_CONTROLLER 0x0002 @@ -284,12 +312,59 @@ enum acpi_prefered_pm_profiles { #pragma pack() -#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_fadt, f) - +/* + * This macro is temporary until the table bitfield flag definitions + * are removed and replaced by a Flags field. + */ +#define ACPI_FLAG_OFFSET(d,f,o) (u8) (ACPI_OFFSET (d,f) + \ + sizeof(((d *)0)->f) + o) /* * Get the remaining ACPI tables */ +#include "actbl1.h" + +/* + * ACPI Table information. We save the table address, length, + * and type of memory allocation (mapped or allocated) for each + * table for 1) when we exit, and 2) if a new table is installed + */ +#define ACPI_MEM_NOT_ALLOCATED 0 +#define ACPI_MEM_ALLOCATED 1 +#define ACPI_MEM_MAPPED 2 + +/* Definitions for the Flags bitfield member of struct acpi_table_support */ + +#define ACPI_TABLE_SINGLE 0x00 +#define ACPI_TABLE_MULTIPLE 0x01 +#define ACPI_TABLE_EXECUTABLE 0x02 + +#define ACPI_TABLE_ROOT 0x00 +#define ACPI_TABLE_PRIMARY 0x10 +#define ACPI_TABLE_SECONDARY 0x20 +#define ACPI_TABLE_ALL 0x30 +#define ACPI_TABLE_TYPE_MASK 0x30 + +/* Data about each known table type */ + +struct acpi_table_support { + char *name; + char *signature; + void **global_ptr; + u8 sig_length; + u8 flags; +}; + +extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1, + * needed for certain workarounds */ +/* Macros used to generate offsets to specific table fields */ + +#define ACPI_FACS_OFFSET(f) (u8) ACPI_OFFSET (struct facs_descriptor,f) +#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct fadt_descriptor, f) +#define ACPI_GAS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_generic_address,f) +#define ACPI_HDR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_header,f) +#define ACPI_RSDP_OFFSET(f) (u8) ACPI_OFFSET (struct rsdp_descriptor,f) -#include +#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct fadt_descriptor,f,o) +#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct facs_descriptor,f,o) #endif /* __ACTBL_H__ */ diff --git a/trunk/include/acpi/actbl1.h b/trunk/include/acpi/actbl1.h index 4e5d3ca53a8e..745a6445a4f9 100644 --- a/trunk/include/acpi/actbl1.h +++ b/trunk/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,6 @@ #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ #define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ -#define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ #define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ @@ -74,6 +73,12 @@ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ #define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ +/* Legacy names */ + +#define APIC_SIG "APIC" /* Multiple APIC Description Table */ +#define BOOT_SIG "BOOT" /* Simple Boot Flag Table */ +#define SBST_SIG "SBST" /* Smart Battery Specification Table */ + /* * All tables must be byte-packed to match the ACPI specification, since * the tables are provided by the system BIOS. @@ -86,43 +91,31 @@ * portable, so do not use any other bitfield types. */ -/* Common Sub-table header (used in MADT, SRAT, etc.) */ - -struct acpi_subtable_header { - u8 type; - u8 length; -}; - /******************************************************************************* * * ASF - Alert Standard Format table (Signature "ASF!") * - * Conforms to the Alert Standard Format Specification V2.0, 23 April 2003 - * ******************************************************************************/ struct acpi_table_asf { - struct acpi_table_header header; /* Common ACPI table header */ -}; +ACPI_TABLE_HEADER_DEF}; -/* ASF subtable header */ +#define ACPI_ASF_HEADER_DEF \ + u8 type; \ + u8 reserved; \ + u16 length; struct acpi_asf_header { - u8 type; - u8 reserved; - u16 length; -}; +ACPI_ASF_HEADER_DEF}; -/* Values for Type field above */ +/* Values for Type field */ -enum acpi_asf_type { - ACPI_ASF_TYPE_INFO = 0, - ACPI_ASF_TYPE_ALERT = 1, - ACPI_ASF_TYPE_CONTROL = 2, - ACPI_ASF_TYPE_BOOT = 3, - ACPI_ASF_TYPE_ADDRESS = 4, - ACPI_ASF_TYPE_RESERVED = 5 -}; +#define ASF_INFO 0 +#define ASF_ALERT 1 +#define ASF_CONTROL 2 +#define ASF_BOOT 3 +#define ASF_ADDRESS 4 +#define ASF_RESERVED 5 /* * ASF subtables @@ -131,8 +124,7 @@ enum acpi_asf_type { /* 0: ASF Information */ struct acpi_asf_info { - struct acpi_asf_header header; - u8 min_reset_value; + ACPI_ASF_HEADER_DEF u8 min_reset_value; u8 min_poll_interval; u16 system_id; u32 mfg_id; @@ -143,49 +135,26 @@ struct acpi_asf_info { /* 1: ASF Alerts */ struct acpi_asf_alert { - struct acpi_asf_header header; - u8 assert_mask; + ACPI_ASF_HEADER_DEF u8 assert_mask; u8 deassert_mask; u8 alerts; u8 data_length; -}; - -struct acpi_asf_alert_data { - u8 address; - u8 command; - u8 mask; - u8 value; - u8 sensor_type; - u8 type; - u8 offset; - u8 source_type; - u8 severity; - u8 sensor_number; - u8 entity; - u8 instance; + u8 array[1]; }; /* 2: ASF Remote Control */ struct acpi_asf_remote { - struct acpi_asf_header header; - u8 controls; + ACPI_ASF_HEADER_DEF u8 controls; u8 data_length; u16 reserved2; -}; - -struct acpi_asf_control_data { - u8 function; - u8 address; - u8 command; - u8 value; + u8 array[1]; }; /* 3: ASF RMCP Boot Options */ struct acpi_asf_rmcp { - struct acpi_asf_header header; - u8 capabilities[7]; + ACPI_ASF_HEADER_DEF u8 capabilities[7]; u8 completion_code; u32 enterprise_id; u8 command; @@ -197,9 +166,9 @@ struct acpi_asf_rmcp { /* 4: ASF Address */ struct acpi_asf_address { - struct acpi_asf_header header; - u8 eprom_address; + ACPI_ASF_HEADER_DEF u8 eprom_address; u8 devices; + u8 smbus_addresses[1]; }; /******************************************************************************* @@ -209,8 +178,7 @@ struct acpi_asf_address { ******************************************************************************/ struct acpi_table_boot { - struct acpi_table_header header; /* Common ACPI table header */ - u8 cmos_index; /* Index in CMOS RAM for the boot register */ + ACPI_TABLE_HEADER_DEF u8 cmos_index; /* Index in CMOS RAM for the boot register */ u8 reserved[3]; }; @@ -221,8 +189,7 @@ struct acpi_table_boot { ******************************************************************************/ struct acpi_table_cpep { - struct acpi_table_header header; /* Common ACPI table header */ - u64 reserved; + ACPI_TABLE_HEADER_DEF u64 reserved; }; /* Subtable */ @@ -230,9 +197,9 @@ struct acpi_table_cpep { struct acpi_cpep_polling { u8 type; u8 length; - u8 id; /* Processor ID */ - u8 eid; /* Processor EID */ - u32 interval; /* Polling interval (msec) */ + u8 processor_id; /* Processor ID */ + u8 processor_eid; /* Processor EID */ + u32 polling_interval; /* Polling interval (msec) */ }; /******************************************************************************* @@ -242,97 +209,23 @@ struct acpi_cpep_polling { ******************************************************************************/ struct acpi_table_dbgp { - struct acpi_table_header header; /* Common ACPI table header */ - u8 type; /* 0=full 16550, 1=subset of 16550 */ + ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ u8 reserved[3]; struct acpi_generic_address debug_port; }; -/******************************************************************************* - * - * DMAR - DMA Remapping table - * - ******************************************************************************/ - -struct acpi_table_dmar { - struct acpi_table_header header; /* Common ACPI table header */ - u8 width; /* Host Address Width */ - u8 reserved[11]; -}; - -/* DMAR subtable header */ - -struct acpi_dmar_header { - u16 type; - u16 length; - u8 flags; - u8 reserved[3]; -}; - -/* Values for subtable type in struct acpi_dmar_header */ - -enum acpi_dmar_type { - ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, - ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, - ACPI_DMAR_TYPE_RESERVED = 2 /* 2 and greater are reserved */ -}; - -struct acpi_dmar_device_scope { - u8 entry_type; - u8 length; - u8 segment; - u8 bus; -}; - -/* Values for entry_type in struct acpi_dmar_device_scope */ - -enum acpi_dmar_scope_type { - ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0, - ACPI_DMAR_SCOPE_TYPE_ENDPOINT = 1, - ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2, - ACPI_DMAR_SCOPE_TYPE_RESERVED = 3 /* 3 and greater are reserved */ -}; - -/* - * DMAR Sub-tables, correspond to Type in struct acpi_dmar_header - */ - -/* 0: Hardware Unit Definition */ - -struct acpi_dmar_hardware_unit { - struct acpi_dmar_header header; - u64 address; /* Register Base Address */ -}; - -/* Flags */ - -#define ACPI_DMAR_INCLUDE_ALL (1) - -/* 1: Reserved Memory Defininition */ - -struct acpi_dmar_reserved_memory { - struct acpi_dmar_header header; - u64 address; /* 4_k aligned base address */ - u64 end_address; /* 4_k aligned limit address */ -}; - -/* Flags */ - -#define ACPI_DMAR_ALLOW_ALL (1) - /******************************************************************************* * * ECDT - Embedded Controller Boot Resources Table * ******************************************************************************/ -struct acpi_table_ecdt { - struct acpi_table_header header; /* Common ACPI table header */ - struct acpi_generic_address control; /* Address of EC command/status register */ - struct acpi_generic_address data; /* Address of EC data register */ +struct ec_boot_resources { + ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */ + struct acpi_generic_address ec_data; /* Address of EC data register */ u32 uid; /* Unique ID - must be same as the EC _UID method */ - u8 gpe; /* The GPE for the EC */ - u8 id[1]; /* Full namepath of the EC in the ACPI namespace */ + u8 gpe_bit; /* The GPE for the EC */ + u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ }; /******************************************************************************* @@ -341,22 +234,22 @@ struct acpi_table_ecdt { * ******************************************************************************/ -struct acpi_table_hpet { - struct acpi_table_header header; /* Common ACPI table header */ - u32 id; /* Hardware ID of event timer block */ - struct acpi_generic_address address; /* Address of event timer block */ - u8 sequence; /* HPET sequence number */ - u16 minimum_tick; /* Main counter min tick, periodic mode */ - u8 flags; +struct acpi_hpet_table { + ACPI_TABLE_HEADER_DEF u32 hardware_id; /* Hardware ID of event timer block */ + struct acpi_generic_address base_address; /* Address of event timer block */ + u8 hpet_number; /* HPET sequence number */ + u16 clock_tick; /* Main counter min tick, periodic mode */ + u8 attributes; }; -/*! Flags */ - -#define ACPI_HPET_PAGE_PROTECT (1) /* 00: No page protection */ -#define ACPI_HPET_PAGE_PROTECT_4 (1<<1) /* 01: 4KB page protected */ -#define ACPI_HPET_PAGE_PROTECT_64 (1<<2) /* 02: 64KB page protected */ - -/*! [End] no source code translation !*/ +#if 0 /* HPET flags to be converted to macros */ +struct { /* Flags (8 bits) */ + u8 page_protect:1; /* 00: No page protection */ + u8 page_protect4:1; /* 01: 4_kB page protected */ + u8 page_protect64:1; /* 02: 64_kB page protected */ + u8:5; /* 03-07: Reserved, must be zero */ +} flags; +#endif /******************************************************************************* * @@ -364,159 +257,148 @@ struct acpi_table_hpet { * ******************************************************************************/ -struct acpi_table_madt { - struct acpi_table_header header; /* Common ACPI table header */ - u32 address; /* Physical address of local APIC */ - u32 flags; +struct multiple_apic_table { + ACPI_TABLE_HEADER_DEF u32 local_apic_address; /* Physical address of local APIC */ + + /* Flags (32 bits) */ + + u8 PCATcompat:1; /* 00: System also has dual 8259s */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved1[3]; /* 08-31: Reserved, must be zero */ }; -/* Flags */ +/* Values for MADT PCATCompat */ -#define ACPI_MADT_PCAT_COMPAT (1) /* 00: System also has dual 8259s */ +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 -/* Values for PCATCompat flag */ +/* Common MADT Sub-table header */ -#define ACPI_MADT_DUAL_PIC 0 -#define ACPI_MADT_MULTIPLE_APIC 1 +#define APIC_HEADER_DEF \ + u8 type; \ + u8 length; -/* Values for subtable type in struct acpi_subtable_header */ +struct apic_header { +APIC_HEADER_DEF}; -enum acpi_madt_type { - ACPI_MADT_TYPE_LOCAL_APIC = 0, - ACPI_MADT_TYPE_IO_APIC = 1, - ACPI_MADT_TYPE_INTERRUPT_OVERRIDE = 2, - ACPI_MADT_TYPE_NMI_SOURCE = 3, - ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4, - ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE = 5, - ACPI_MADT_TYPE_IO_SAPIC = 6, - ACPI_MADT_TYPE_LOCAL_SAPIC = 7, - ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8, - ACPI_MADT_TYPE_RESERVED = 9 /* 9 and greater are reserved */ -}; +/* Values for Type in struct apic_header */ + +#define APIC_PROCESSOR 0 +#define APIC_IO 1 +#define APIC_XRUPT_OVERRIDE 2 +#define APIC_NMI 3 +#define APIC_LOCAL_NMI 4 +#define APIC_ADDRESS_OVERRIDE 5 +#define APIC_IO_SAPIC 6 +#define APIC_LOCAL_SAPIC 7 +#define APIC_XRUPT_SOURCE 8 +#define APIC_RESERVED 9 /* 9 and greater are reserved */ + +/* Flag definitions for MADT sub-tables */ + +#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \ + u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\ + u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\ + u8 : 4; /* 04-07: Reserved, must be zero */\ + u8 reserved1; /* 08-15: Reserved, must be zero */ + +#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \ + u8 processor_enabled: 1; /* 00: Processor is usable if set */\ + u8 : 7; /* 01-07: Reserved, must be zero */\ + u8 reserved2[3]; /* 08-31: Reserved, must be zero */ + +/* Values for MPS INTI flags */ + +#define POLARITY_CONFORMS 0 +#define POLARITY_ACTIVE_HIGH 1 +#define POLARITY_RESERVED 2 +#define POLARITY_ACTIVE_LOW 3 + +#define TRIGGER_CONFORMS 0 +#define TRIGGER_EDGE 1 +#define TRIGGER_RESERVED 2 +#define TRIGGER_LEVEL 3 /* - * MADT Sub-tables, correspond to Type in struct acpi_subtable_header + * MADT Sub-tables, correspond to Type in struct apic_header */ -/* 0: Processor Local APIC */ +/* 0: processor APIC */ -struct acpi_madt_local_apic { - struct acpi_subtable_header header; - u8 processor_id; /* ACPI processor id */ - u8 id; /* Processor's local APIC id */ - u32 lapic_flags; -}; +struct madt_processor_apic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_apic_id; /* Processor's local APIC id */ + ACPI_MADT_LFLAGS}; /* 1: IO APIC */ -struct acpi_madt_io_apic { - struct acpi_subtable_header header; - u8 id; /* I/O APIC ID */ +struct madt_io_apic { + APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */ u8 reserved; /* Reserved - must be zero */ u32 address; /* APIC physical address */ - u32 global_irq_base; /* Global system interrupt where INTI lines start */ + u32 interrupt; /* Global system interrupt where INTI lines start */ }; /* 2: Interrupt Override */ -struct acpi_madt_interrupt_override { - struct acpi_subtable_header header; - u8 bus; /* 0 - ISA */ - u8 source_irq; /* Interrupt source (IRQ) */ - u32 global_irq; /* Global system interrupt */ - u16 inti_flags; -}; +struct madt_interrupt_override { + APIC_HEADER_DEF u8 bus; /* 0 - ISA */ + u8 source; /* Interrupt source (IRQ) */ + u32 interrupt; /* Global system interrupt */ + ACPI_MADT_IFLAGS}; -/* 3: NMI Source */ +/* 3: NMI Sources */ -struct acpi_madt_nmi_source { - struct acpi_subtable_header header; - u16 inti_flags; - u32 global_irq; /* Global system interrupt */ +struct madt_nmi_source { + APIC_HEADER_DEF ACPI_MADT_IFLAGS u32 interrupt; /* Global system interrupt */ }; /* 4: Local APIC NMI */ -struct acpi_madt_local_apic_nmi { - struct acpi_subtable_header header; - u8 processor_id; /* ACPI processor id */ - u16 inti_flags; - u8 lint; /* LINTn to which NMI is connected */ +struct madt_local_apic_nmi { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + ACPI_MADT_IFLAGS u8 lint; /* LINTn to which NMI is connected */ }; /* 5: Address Override */ -struct acpi_madt_local_apic_override { - struct acpi_subtable_header header; - u16 reserved; /* Reserved, must be zero */ +struct madt_address_override { + APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */ u64 address; /* APIC physical address */ }; /* 6: I/O Sapic */ -struct acpi_madt_io_sapic { - struct acpi_subtable_header header; - u8 id; /* I/O SAPIC ID */ +struct madt_io_sapic { + APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */ u8 reserved; /* Reserved, must be zero */ - u32 global_irq_base; /* Global interrupt for SAPIC start */ + u32 interrupt_base; /* Glocal interrupt for SAPIC start */ u64 address; /* SAPIC physical address */ }; /* 7: Local Sapic */ -struct acpi_madt_local_sapic { - struct acpi_subtable_header header; - u8 processor_id; /* ACPI processor id */ - u8 id; /* SAPIC ID */ - u8 eid; /* SAPIC EID */ +struct madt_local_sapic { + APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ + u8 local_sapic_id; /* SAPIC ID */ + u8 local_sapic_eid; /* SAPIC EID */ u8 reserved[3]; /* Reserved, must be zero */ - u32 lapic_flags; - u32 uid; /* Numeric UID - ACPI 3.0 */ - char uid_string[1]; /* String UID - ACPI 3.0 */ + ACPI_MADT_LFLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */ + char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ }; /* 8: Platform Interrupt Source */ -struct acpi_madt_interrupt_source { - struct acpi_subtable_header header; - u16 inti_flags; - u8 type; /* 1=PMI, 2=INIT, 3=corrected */ - u8 id; /* Processor ID */ - u8 eid; /* Processor EID */ +struct madt_interrupt_source { + APIC_HEADER_DEF ACPI_MADT_IFLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */ + u8 processor_id; /* Processor ID */ + u8 processor_eid; /* Processor EID */ u8 io_sapic_vector; /* Vector value for PMI interrupts */ - u32 global_irq; /* Global system interrupt */ + u32 interrupt; /* Global system interrupt */ u32 flags; /* Interrupt Source Flags */ }; -/* Flags field above */ - -#define ACPI_MADT_CPEI_OVERRIDE (1) - -/* - * Common flags fields for MADT subtables - */ - -/* MADT Local APIC flags (lapic_flags) */ - -#define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */ - -/* MADT MPS INTI flags (inti_flags) */ - -#define ACPI_MADT_POLARITY_MASK (3) /* 00-01: Polarity of APIC I/O input signals */ -#define ACPI_MADT_TRIGGER_MASK (3<<2) /* 02-03: Trigger mode of APIC input signals */ - -/* Values for MPS INTI flags */ - -#define ACPI_MADT_POLARITY_CONFORMS 0 -#define ACPI_MADT_POLARITY_ACTIVE_HIGH 1 -#define ACPI_MADT_POLARITY_RESERVED 2 -#define ACPI_MADT_POLARITY_ACTIVE_LOW 3 - -#define ACPI_MADT_TRIGGER_CONFORMS (0) -#define ACPI_MADT_TRIGGER_EDGE (1<<2) -#define ACPI_MADT_TRIGGER_RESERVED (2<<2) -#define ACPI_MADT_TRIGGER_LEVEL (3<<2) - +#ifdef DUPLICATE_DEFINITION_WITH_LINUX_ACPI_H /******************************************************************************* * * MCFG - PCI Memory Mapped Configuration table and sub-table @@ -524,19 +406,17 @@ struct acpi_madt_interrupt_source { ******************************************************************************/ struct acpi_table_mcfg { - struct acpi_table_header header; /* Common ACPI table header */ - u8 reserved[8]; + ACPI_TABLE_HEADER_DEF u8 reserved[8]; }; -/* Subtable */ - struct acpi_mcfg_allocation { - u64 address; /* Base address, processor-relative */ + u64 base_address; /* Base address, processor-relative */ u16 pci_segment; /* PCI segment group number */ u8 start_bus_number; /* Starting PCI Bus number */ u8 end_bus_number; /* Final PCI Bus number */ u32 reserved; }; +#endif /******************************************************************************* * @@ -544,9 +424,8 @@ struct acpi_mcfg_allocation { * ******************************************************************************/ -struct acpi_table_sbst { - struct acpi_table_header header; /* Common ACPI table header */ - u32 warning_level; +struct smart_battery_table { + ACPI_TABLE_HEADER_DEF u32 warning_level; u32 low_level; u32 critical_level; }; @@ -557,10 +436,9 @@ struct acpi_table_sbst { * ******************************************************************************/ -struct acpi_table_slit { - struct acpi_table_header header; /* Common ACPI table header */ - u64 locality_count; - u8 entry[1]; /* Real size = localities^2 */ +struct system_locality_info { + ACPI_TABLE_HEADER_DEF u64 locality_count; + u8 entry[1][1]; }; /******************************************************************************* @@ -570,8 +448,7 @@ struct acpi_table_slit { ******************************************************************************/ struct acpi_table_spcr { - struct acpi_table_header header; /* Common ACPI table header */ - u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ + ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ u8 reserved[3]; struct acpi_generic_address serial_port; u8 interrupt_type; @@ -582,7 +459,7 @@ struct acpi_table_spcr { u8 stop_bits; u8 flow_control; u8 terminal_type; - u8 reserved1; + u8 reserved2; u16 pci_device_id; u16 pci_vendor_id; u8 pci_bus; @@ -590,7 +467,7 @@ struct acpi_table_spcr { u8 pci_function; u32 pci_flags; u8 pci_segment; - u32 reserved2; + u32 reserved3; }; /******************************************************************************* @@ -600,13 +477,12 @@ struct acpi_table_spcr { ******************************************************************************/ struct acpi_table_spmi { - struct acpi_table_header header; /* Common ACPI table header */ - u8 reserved; + ACPI_TABLE_HEADER_DEF u8 reserved; u8 interface_type; u16 spec_revision; /* Version of IPMI */ u8 interrupt_type; u8 gpe_number; /* GPE assigned */ - u8 reserved1; + u8 reserved2; u8 pci_device_flag; u32 interrupt; struct acpi_generic_address ipmi_register; @@ -622,52 +498,57 @@ struct acpi_table_spmi { * ******************************************************************************/ -struct acpi_table_srat { - struct acpi_table_header header; /* Common ACPI table header */ - u32 table_revision; /* Must be value '1' */ - u64 reserved; /* Reserved, must be zero */ +struct system_resource_affinity { + ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */ + u64 reserved2; /* Reserved, must be zero */ }; -/* Values for subtable type in struct acpi_subtable_header */ +/* SRAT common sub-table header */ -enum acpi_srat_type { - ACPI_SRAT_TYPE_CPU_AFFINITY = 0, - ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1, - ACPI_SRAT_TYPE_RESERVED = 2 -}; +#define SRAT_SUBTABLE_HEADER \ + u8 type; \ + u8 length; + +/* Values for Type above */ + +#define SRAT_CPU_AFFINITY 0 +#define SRAT_MEMORY_AFFINITY 1 +#define SRAT_RESERVED 2 /* SRAT sub-tables */ -struct acpi_srat_cpu_affinity { - struct acpi_subtable_header header; - u8 proximity_domain_lo; +struct static_resource_alloc { + SRAT_SUBTABLE_HEADER u8 proximity_domain_lo; u8 apic_id; - u32 flags; + + /* Flags (32 bits) */ + + u8 enabled:1; /* 00: Use affinity structure */ + u8:7; /* 01-07: Reserved, must be zero */ + u8 reserved3[3]; /* 08-31: Reserved, must be zero */ + u8 local_sapic_eid; u8 proximity_domain_hi[3]; - u32 reserved; /* Reserved, must be zero */ + u32 reserved4; /* Reserved, must be zero */ }; -/* Flags */ - -#define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */ - -struct acpi_srat_mem_affinity { - struct acpi_subtable_header header; - u32 proximity_domain; - u16 reserved; /* Reserved, must be zero */ +struct memory_affinity { + SRAT_SUBTABLE_HEADER u32 proximity_domain; + u16 reserved3; u64 base_address; - u64 length; - u32 memory_type; /* See acpi_address_range_id */ - u32 flags; - u64 reserved1; /* Reserved, must be zero */ -}; + u64 address_length; + u32 reserved4; -/* Flags */ + /* Flags (32 bits) */ -#define ACPI_SRAT_MEM_ENABLED (1) /* 00: Use affinity structure */ -#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1) /* 01: Memory region is hot pluggable */ -#define ACPI_SRAT_MEM_NON_VOLATILE (1<<2) /* 02: Memory region is non-volatile */ + u8 enabled:1; /* 00: Use affinity structure */ + u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */ + u8 non_volatile:1; /* 02: Memory is non-volatile */ + u8:5; /* 03-07: Reserved, must be zero */ + u8 reserved5[3]; /* 08-31: Reserved, must be zero */ + + u64 reserved6; /* Reserved, must be zero */ +}; /******************************************************************************* * @@ -676,8 +557,7 @@ struct acpi_srat_mem_affinity { ******************************************************************************/ struct acpi_table_tcpa { - struct acpi_table_header header; /* Common ACPI table header */ - u16 reserved; + ACPI_TABLE_HEADER_DEF u16 reserved; u32 max_log_length; /* Maximum length for the event log area */ u64 log_address; /* Address of the event log area */ }; @@ -689,8 +569,7 @@ struct acpi_table_tcpa { ******************************************************************************/ struct acpi_table_wdrt { - struct acpi_table_header header; /* Common ACPI table header */ - u32 header_length; /* Watchdog Header Length */ + ACPI_TABLE_HEADER_DEF u32 header_length; /* Watchdog Header Length */ u8 pci_segment; /* PCI Segment number */ u8 pci_bus; /* PCI Bus number */ u8 pci_device; /* PCI Device number */ @@ -703,9 +582,58 @@ struct acpi_table_wdrt { u32 entries; /* Number of watchdog entries that follow */ }; -/* Flags */ - -#define ACPI_WDRT_TIMER_ENABLED (1) /* 00: Timer enabled */ +#if 0 /* Flags, will be converted to macros */ +u8 enabled:1; /* 00: Timer enabled */ +u8:6; /* 01-06: Reserved */ +u8 sleep_stop:1; /* 07: Timer stopped in sleep state */ +#endif + +/* Macros used to generate offsets to specific table fields */ + +#define ACPI_ASF0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_info,f) +#define ACPI_ASF1_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_alert,f) +#define ACPI_ASF2_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_remote,f) +#define ACPI_ASF3_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_rmcp,f) +#define ACPI_ASF4_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_address,f) +#define ACPI_BOOT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_boot,f) +#define ACPI_CPEP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_cpep,f) +#define ACPI_CPEP0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_cpep_polling,f) +#define ACPI_DBGP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_dbgp,f) +#define ACPI_ECDT_OFFSET(f) (u8) ACPI_OFFSET (struct ec_boot_resources,f) +#define ACPI_HPET_OFFSET(f) (u8) ACPI_OFFSET (struct hpet_table,f) +#define ACPI_MADT_OFFSET(f) (u8) ACPI_OFFSET (struct multiple_apic_table,f) +#define ACPI_MADT0_OFFSET(f) (u8) ACPI_OFFSET (struct madt_processor_apic,f) +#define ACPI_MADT1_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_apic,f) +#define ACPI_MADT2_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_override,f) +#define ACPI_MADT3_OFFSET(f) (u8) ACPI_OFFSET (struct madt_nmi_source,f) +#define ACPI_MADT4_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_apic_nmi,f) +#define ACPI_MADT5_OFFSET(f) (u8) ACPI_OFFSET (struct madt_address_override,f) +#define ACPI_MADT6_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_sapic,f) +#define ACPI_MADT7_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_sapic,f) +#define ACPI_MADT8_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_source,f) +#define ACPI_MADTH_OFFSET(f) (u8) ACPI_OFFSET (struct apic_header,f) +#define ACPI_MCFG_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_mcfg,f) +#define ACPI_MCFG0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_mcfg_allocation,f) +#define ACPI_SBST_OFFSET(f) (u8) ACPI_OFFSET (struct smart_battery_table,f) +#define ACPI_SLIT_OFFSET(f) (u8) ACPI_OFFSET (struct system_locality_info,f) +#define ACPI_SPCR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spcr,f) +#define ACPI_SPMI_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spmi,f) +#define ACPI_SRAT_OFFSET(f) (u8) ACPI_OFFSET (struct system_resource_affinity,f) +#define ACPI_SRAT0_OFFSET(f) (u8) ACPI_OFFSET (struct static_resource_alloc,f) +#define ACPI_SRAT1_OFFSET(f) (u8) ACPI_OFFSET (struct memory_affinity,f) +#define ACPI_TCPA_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_tcpa,f) +#define ACPI_WDRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_wdrt,f) + +#define ACPI_HPET_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct hpet_table,f,o) +#define ACPI_SRAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct static_resource_alloc,f,o) +#define ACPI_SRAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct memory_affinity,f,o) +#define ACPI_MADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct multiple_apic_table,f,o) +#define ACPI_MADT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_processor_apic,f,o) +#define ACPI_MADT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_override,f,o) +#define ACPI_MADT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_nmi_source,f,o) +#define ACPI_MADT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_apic_nmi,f,o) +#define ACPI_MADT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_sapic,f,o) +#define ACPI_MADT8_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_source,f,o) /* Reset to default packing */ diff --git a/trunk/include/acpi/actbl2.h b/trunk/include/acpi/actbl2.h new file mode 100644 index 000000000000..67efe6cad27b --- /dev/null +++ b/trunk/include/acpi/actbl2.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Name: actbl2.h - ACPI Specification Revision 2.0 Tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef __ACTBL2_H__ +#define __ACTBL2_H__ + +/* Code moved to both actbl.h and actbl1.h */ + +#endif /* __ACTBL2_H__ */ diff --git a/trunk/include/acpi/actbl71.h b/trunk/include/acpi/actbl71.h new file mode 100644 index 000000000000..10ac05bb36bc --- /dev/null +++ b/trunk/include/acpi/actbl71.h @@ -0,0 +1,134 @@ +/****************************************************************************** + * + * Name: actbl71.h - IA-64 Extensions to the ACPI Spec Rev. 0.71 + * This file includes tables specific to this + * specification revision. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2003, 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 + */ + +#ifndef __ACTBL71_H__ +#define __ACTBL71_H__ + +/* 0.71 FADT address_space data item bitmasks defines */ +/* If the associated bit is zero then it is in memory space else in io space */ + +#define SMI_CMD_ADDRESS_SPACE 0x01 +#define PM1_BLK_ADDRESS_SPACE 0x02 +#define PM2_CNT_BLK_ADDRESS_SPACE 0x04 +#define PM_TMR_BLK_ADDRESS_SPACE 0x08 +#define GPE0_BLK_ADDRESS_SPACE 0x10 +#define GPE1_BLK_ADDRESS_SPACE 0x20 + +/* Only for clarity in declarations */ + +typedef u64 IO_ADDRESS; + +#pragma pack(1) +struct { /* Root System Descriptor Pointer */ + NATIVE_CHAR signature[8]; /* contains "RSD PTR " */ + u8 checksum; /* to make sum of struct == 0 */ + NATIVE_CHAR oem_id[6]; /* OEM identification */ + u8 reserved; /* Must be 0 for 1.0, 2 for 2.0 */ + u64 rsdt_physical_address; /* 64-bit physical address of RSDT */ +}; + +/*****************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Root System Description Table */ +/*****************************************/ +struct { + struct acpi_table_header header; /* Table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + u64 table_offset_entry[1]; /* Array of pointers to other */ + /* tables' headers */ +}; + +/*******************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Firmware ACPI Control Structure */ +/*******************************************/ +struct { + NATIVE_CHAR signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 reserved4; /* must be 0 */ + u64 firmware_waking_vector; /* ACPI OS waking vector */ + u64 global_lock; /* Global Lock */ + u32 S4bios_f:1; /* Indicates if S4BIOS support is present */ + u32 reserved1:31; /* must be 0 */ + u8 reserved3[28]; /* reserved - must be zero */ +}; + +/******************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Fixed ACPI Description Table */ +/******************************************/ +struct { + struct acpi_table_header header; /* table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + u64 firmware_ctrl; /* 64-bit Physical address of FACS */ + u64 dsdt; /* 64-bit Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 address_space; /* Address Space Bitmask */ + u16 sci_int; /* System vector of SCI interrupt */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ + u8 reserved2; /* reserved - must be zero */ + u64 smi_cmd; /* Port address of SMI command port */ + u64 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ + u64 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ + u64 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u64 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u64 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u64 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u64 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ + u64 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 reserved3; /* reserved */ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + 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 */ + u8 reserved4; /* reserved */ + u32 flush_cash:1; /* PAL_FLUSH_CACHE is correctly supported */ + u32 reserved5:1; /* reserved - must be zero */ + u32 proc_c1:1; /* all processors support C1 state */ + u32 plvl2_up:1; /* C2 state works on MP system */ + u32 pwr_button:1; /* Power button is handled as a generic feature */ + u32 sleep_button:1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC:1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4:1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext:1; /* tmr_val is 32 bits */ + u32 dock_cap:1; /* Supports Docking */ + u32 reserved6:22; /* reserved - must be zero */ +}; + +#pragma pack() + +#endif /* __ACTBL71_H__ */ diff --git a/trunk/include/acpi/actypes.h b/trunk/include/acpi/actypes.h index 72a6e2c3a536..64b603cfe92e 100644 --- a/trunk/include/acpi/actypes.h +++ b/trunk/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,8 +48,7 @@ /* * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header - * and must be either 32 or 64. 16-bit ACPICA is no longer supported, as of - * 12/2006. + * and must be either 16, 32, or 64 */ #ifndef ACPI_MACHINE_WIDTH #error ACPI_MACHINE_WIDTH not defined @@ -150,6 +149,7 @@ typedef int INT32; typedef u64 acpi_native_uint; typedef s64 acpi_native_int; +typedef u64 acpi_table_ptr; typedef u64 acpi_io_address; typedef u64 acpi_physical_address; @@ -189,15 +189,48 @@ typedef int INT32; typedef u32 acpi_native_uint; typedef s32 acpi_native_int; +typedef u64 acpi_table_ptr; typedef u32 acpi_io_address; -typedef u32 acpi_physical_address; +typedef u64 acpi_physical_address; #define ACPI_MAX_PTR ACPI_UINT32_MAX #define ACPI_SIZE_MAX ACPI_UINT32_MAX +/******************************************************************************* + * + * Types specific to 16-bit targets + * + ******************************************************************************/ + +#elif ACPI_MACHINE_WIDTH == 16 + +/*! [Begin] no source code translation (keep the typedefs as-is) */ + +typedef unsigned long UINT32; +typedef short INT16; +typedef long INT32; + +/*! [End] no source code translation !*/ + +typedef u16 acpi_native_uint; +typedef s16 acpi_native_int; + +typedef u32 acpi_table_ptr; +typedef u32 acpi_io_address; +typedef char *acpi_physical_address; + +#define ACPI_MAX_PTR ACPI_UINT16_MAX +#define ACPI_SIZE_MAX ACPI_UINT16_MAX + +#define ACPI_USE_NATIVE_DIVIDE /* No 64-bit integers, ok to use native divide */ + +/* 64-bit integers cannot be supported */ + +#define ACPI_NO_INTEGER64_SUPPORT + #else -/* ACPI_MACHINE_WIDTH must be either 64 or 32 */ +/* ACPI_MACHINE_WIDTH must be either 64, 32, or 16 */ #error unknown ACPI_MACHINE_WIDTH #endif @@ -278,6 +311,36 @@ typedef acpi_native_uint acpi_size; * ******************************************************************************/ +/* + * Pointer overlays to avoid lots of typecasting for + * code that accepts both physical and logical pointers. + */ +union acpi_pointers { + acpi_physical_address physical; + void *logical; + acpi_table_ptr value; +}; + +struct acpi_pointer { + u32 pointer_type; + union acpi_pointers pointer; +}; + +/* pointer_types for above */ + +#define ACPI_PHYSICAL_POINTER 0x01 +#define ACPI_LOGICAL_POINTER 0x02 + +/* Processor mode */ + +#define ACPI_PHYSICAL_ADDRESSING 0x04 +#define ACPI_LOGICAL_ADDRESSING 0x08 +#define ACPI_MEMORY_MODE 0x0C + +#define ACPI_PHYSMODE_PHYSPTR ACPI_PHYSICAL_ADDRESSING | ACPI_PHYSICAL_POINTER +#define ACPI_LOGMODE_PHYSPTR ACPI_LOGICAL_ADDRESSING | ACPI_PHYSICAL_POINTER +#define ACPI_LOGMODE_LOGPTR ACPI_LOGICAL_ADDRESSING | ACPI_LOGICAL_POINTER + /* Logical defines and NULL */ #ifdef FALSE @@ -379,8 +442,7 @@ typedef u64 acpi_integer; /* * Initialization state */ -#define ACPI_SUBSYSTEM_INITIALIZE 0x01 -#define ACPI_INITIALIZED_OK 0x02 +#define ACPI_INITIALIZED_OK 0x01 /* * Power state values @@ -428,6 +490,21 @@ typedef u64 acpi_integer; #define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 #define ACPI_NOTIFY_POWER_FAULT (u8) 7 +/* + * Table types. These values are passed to the table related APIs + */ +typedef u32 acpi_table_type; + +#define ACPI_TABLE_ID_RSDP (acpi_table_type) 0 +#define ACPI_TABLE_ID_DSDT (acpi_table_type) 1 +#define ACPI_TABLE_ID_FADT (acpi_table_type) 2 +#define ACPI_TABLE_ID_FACS (acpi_table_type) 3 +#define ACPI_TABLE_ID_PSDT (acpi_table_type) 4 +#define ACPI_TABLE_ID_SSDT (acpi_table_type) 5 +#define ACPI_TABLE_ID_XSDT (acpi_table_type) 6 +#define ACPI_TABLE_ID_MAX 6 +#define ACPI_NUM_TABLE_TYPES (ACPI_TABLE_ID_MAX+1) + /* * Types associated with ACPI names and objects. The first group of * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition @@ -560,7 +637,7 @@ typedef u32 acpi_event_status; * | | | +--- Type of dispatch -- to method, handler, or none * | | +--- Enabled for runtime? * | +--- Enabled for wake? - * +--- Unused + * +--- System state when GPE ocurred (running/waking) */ #define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01 #define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01 @@ -586,6 +663,10 @@ typedef u32 acpi_event_status; #define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */ +#define ACPI_GPE_SYSTEM_MASK (u8) 0x80 +#define ACPI_GPE_SYSTEM_RUNNING (u8) 0x80 +#define ACPI_GPE_SYSTEM_WAKING (u8) 0x00 + /* * Flags for GPE and Lock interfaces */ @@ -734,6 +815,13 @@ struct acpi_buffer { #define ACPI_SYS_MODE_LEGACY 0x0002 #define ACPI_SYS_MODES_MASK 0x0003 +/* + * ACPI Table Info. One per ACPI table _type_ + */ +struct acpi_table_info { + u32 count; +}; + /* * System info returned by acpi_get_system_info() */ @@ -745,6 +833,8 @@ struct acpi_system_info { u32 reserved2; u32 debug_level; u32 debug_layer; + u32 num_table_types; + struct acpi_table_info table_info[ACPI_TABLE_ID_MAX + 1]; }; /* diff --git a/trunk/include/acpi/acutils.h b/trunk/include/acpi/acutils.h index 883ffe92148f..ba039ea1a057 100644 --- a/trunk/include/acpi/acutils.h +++ b/trunk/include/acpi/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -141,6 +141,8 @@ acpi_status acpi_ut_hardware_initialize(void); void acpi_ut_subsystem_shutdown(void); +acpi_status acpi_ut_validate_fadt(void); + /* * utclib - Local implementations of C library functions */ @@ -451,8 +453,6 @@ acpi_ut_short_divide(acpi_integer in_dividend, /* * utmisc */ -const char *acpi_ut_validate_exception(acpi_status status); - u8 acpi_ut_is_aml_table(struct acpi_table_header *table); acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); @@ -470,7 +470,7 @@ void acpi_ut_print_string(char *string, u8 max_length); u8 acpi_ut_valid_acpi_name(u32 name); -acpi_name acpi_ut_repair_name(char *name); +acpi_name acpi_ut_repair_name(acpi_name name); u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position); diff --git a/trunk/include/acpi/amlcode.h b/trunk/include/acpi/amlcode.h index da53a4ef287a..cf18426a87b1 100644 --- a/trunk/include/acpi/amlcode.h +++ b/trunk/include/acpi/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -273,7 +273,7 @@ #define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a Node - Used only by size_of operator */ #define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */ #define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */ -#define ARGI_REGION_OR_BUFFER 0x15 /* Used by LOAD op only */ +#define ARGI_REGION_OR_FIELD 0x15 /* Used by LOAD op only */ #define ARGI_DATAREFOBJ 0x16 /* Note: types above can expand to 0x1F maximum */ diff --git a/trunk/include/acpi/amlresrc.h b/trunk/include/acpi/amlresrc.h index f7d541239da4..be03818af9d1 100644 --- a/trunk/include/acpi/amlresrc.h +++ b/trunk/include/acpi/amlresrc.h @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/platform/acenv.h b/trunk/include/acpi/platform/acenv.h index dab2ec59a3b0..453a469fd397 100644 --- a/trunk/include/acpi/platform/acenv.h +++ b/trunk/include/acpi/platform/acenv.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/platform/acgcc.h b/trunk/include/acpi/platform/acgcc.h index 3bb50494a38a..da80933963db 100644 --- a/trunk/include/acpi/platform/acgcc.h +++ b/trunk/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/acpi/platform/aclinux.h b/trunk/include/acpi/platform/aclinux.h index 5f532d2ac180..7f1e92930b62 100644 --- a/trunk/include/acpi/platform/aclinux.h +++ b/trunk/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2006, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/trunk/include/asm-i386/acpi.h b/trunk/include/asm-i386/acpi.h index 5e657eb8946c..7cfad93edf10 100644 --- a/trunk/include/asm-i386/acpi.h +++ b/trunk/include/asm-i386/acpi.h @@ -39,7 +39,7 @@ * Calling conventions: * * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) - * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_EXTERNAL_XFACE - External ACPI interfaces * ACPI_INTERNAL_XFACE - Internal ACPI interfaces * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces */ @@ -59,11 +59,11 @@ int __acpi_acquire_global_lock(unsigned int *lock); int __acpi_release_global_lock(unsigned int *lock); -#define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = __acpi_acquire_global_lock(&facs->global_lock)) +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr)) -#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = __acpi_release_global_lock(&facs->global_lock)) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = __acpi_release_global_lock((unsigned int *) GLptr)) /* * Math helper asm macros @@ -87,7 +87,7 @@ extern void check_acpi_pci(void); static inline void check_acpi_pci(void) { } #endif -#ifdef CONFIG_ACPI +#ifdef CONFIG_ACPI extern int acpi_lapic; extern int acpi_ioapic; extern int acpi_noirq; @@ -95,9 +95,9 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_ht; extern int acpi_pci_disabled; -static inline void disable_acpi(void) -{ - acpi_disabled = 1; +static inline void disable_acpi(void) +{ + acpi_disabled = 1; acpi_ht = 0; acpi_pci_disabled = 1; acpi_noirq = 1; @@ -114,9 +114,9 @@ extern int acpi_use_timer_override; #endif static inline void acpi_noirq_set(void) { acpi_noirq = 1; } -static inline void acpi_disable_pci(void) +static inline void acpi_disable_pci(void) { - acpi_pci_disabled = 1; + acpi_pci_disabled = 1; acpi_noirq_set(); } extern int acpi_irq_balance_set(char *str); @@ -144,6 +144,8 @@ extern void acpi_reserve_bootmem(void); #endif /*CONFIG_ACPI_SLEEP*/ +extern u8 x86_acpiid_to_apicid[]; + #define ARCH_HAS_POWER_INIT 1 #endif /*__KERNEL__*/ diff --git a/trunk/include/asm-i386/mach-es7000/mach_mpparse.h b/trunk/include/asm-i386/mach-es7000/mach_mpparse.h index 24990e546da3..99f66be240be 100644 --- a/trunk/include/asm-i386/mach-es7000/mach_mpparse.h +++ b/trunk/include/asm-i386/mach-es7000/mach_mpparse.h @@ -3,13 +3,13 @@ #include -static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, +static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name, struct mpc_config_translation *translation) { Dprintk("Bus #%d is %s\n", m->mpc_busid, name); } -static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, +static inline void mpc_oem_pci_bus(struct mpc_config_bus *m, struct mpc_config_translation *translation) { } @@ -22,7 +22,7 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) { if (mpc->mpc_oemptr) { - struct mp_config_oemtable *oem_table = + struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)mpc->mpc_oemptr; if (!strncmp(oem, "UNISYS", 6)) return parse_unisys_oem((char *)oem_table); @@ -31,13 +31,12 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, } #ifdef CONFIG_ACPI - static inline int es7000_check_dsdt(void) { - struct acpi_table_header header; - memcpy(&header, 0, sizeof(struct acpi_table_header)); - acpi_get_table_header(ACPI_SIG_DSDT, 0, &header); - if (!strncmp(header.oem_id, "UNISYS", 6)) + struct acpi_table_header *header = NULL; + if(!acpi_get_table_header_early(ACPI_DSDT, &header)) + acpi_table_print(header, 0); + if (!strncmp(header->oem_id, "UNISYS", 6)) return 1; return 0; } @@ -45,7 +44,7 @@ static inline int es7000_check_dsdt(void) /* Hook from generic ACPI tables.c */ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - unsigned long oem_addr; + unsigned long oem_addr; if (!find_unisys_acpi_oem_table(&oem_addr)) { if (es7000_check_dsdt()) return parse_unisys_oem((char *)oem_addr); diff --git a/trunk/include/asm-ia64/acpi.h b/trunk/include/asm-ia64/acpi.h index 5d03792d4f65..09a5dd0e44a8 100644 --- a/trunk/include/asm-ia64/acpi.h +++ b/trunk/include/asm-ia64/acpi.h @@ -82,11 +82,11 @@ ia64_acpi_release_global_lock (unsigned int *lock) return old & 0x1; } -#define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = ia64_acpi_acquire_global_lock(&facs->global_lock)) +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = ia64_acpi_acquire_global_lock((unsigned int *) GLptr)) -#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = ia64_acpi_release_global_lock(&facs->global_lock)) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr)) #define acpi_disabled 0 /* ACPI always enabled on IA64 */ #define acpi_noirq 0 /* ACPI always enabled on IA64 */ @@ -119,6 +119,8 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif +extern u16 ia64_acpiid_to_sapicid[]; + /* * Refer Intel ACPI _PDC support document for bit definitions */ diff --git a/trunk/include/asm-ia64/dma.h b/trunk/include/asm-ia64/dma.h index 4d97f60f1ef5..dad3a735df8b 100644 --- a/trunk/include/asm-ia64/dma.h +++ b/trunk/include/asm-ia64/dma.h @@ -19,6 +19,4 @@ extern unsigned long MAX_DMA_ADDRESS; #define free_dma(x) -void dma_mark_clean(void *addr, size_t size); - #endif /* _ASM_IA64_DMA_H */ diff --git a/trunk/include/asm-ia64/esi.h b/trunk/include/asm-ia64/esi.h index 40991c6ba647..84aac0e0b583 100644 --- a/trunk/include/asm-ia64/esi.h +++ b/trunk/include/asm-ia64/esi.h @@ -19,6 +19,7 @@ enum esi_proc_type { ESI_PROC_REENTRANT /* MP-safe and reentrant */ }; +extern int ia64_esi_init (void); extern struct ia64_sal_retval esi_call_phys (void *, u64 *); extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *, enum esi_proc_type, diff --git a/trunk/include/asm-ia64/meminit.h b/trunk/include/asm-ia64/meminit.h index 6dd476b652c6..c8df75901083 100644 --- a/trunk/include/asm-ia64/meminit.h +++ b/trunk/include/asm-ia64/meminit.h @@ -51,13 +51,12 @@ extern void efi_memmap_init(unsigned long *, unsigned long *); #define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ -extern int register_active_ranges(u64 start, u64 end, void *arg); - #ifdef CONFIG_VIRTUAL_MEM_MAP # define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ extern unsigned long vmalloc_end; extern struct page *vmem_map; extern int find_largest_hole (u64 start, u64 end, void *arg); + extern int register_active_ranges (u64 start, u64 end, void *arg); extern int create_mem_map_page_table (u64 start, u64 end, void *arg); extern int vmemmap_find_next_valid_pfn(int, int); #else diff --git a/trunk/include/asm-ia64/pgalloc.h b/trunk/include/asm-ia64/pgalloc.h index 560c287b1233..393e04c42a2c 100644 --- a/trunk/include/asm-ia64/pgalloc.h +++ b/trunk/include/asm-ia64/pgalloc.h @@ -137,8 +137,7 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte) static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr) { - void *pg = pgtable_quicklist_alloc(); - return pg ? virt_to_page(pg) : NULL; + return virt_to_page(pgtable_quicklist_alloc()); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, diff --git a/trunk/include/asm-ia64/sn/acpi.h b/trunk/include/asm-ia64/sn/acpi.h index 9ce2801cbd57..2850a7ef5e71 100644 --- a/trunk/include/asm-ia64/sn/acpi.h +++ b/trunk/include/asm-ia64/sn/acpi.h @@ -11,7 +11,6 @@ #include "acpi/acglobal.h" -extern int sn_acpi_rev; -#define SN_ACPI_BASE_SUPPORT() (sn_acpi_rev >= 0x20101) +#define SN_ACPI_BASE_SUPPORT() (acpi_gbl_DSDT->oem_revision >= 0x20101) #endif /* _ASM_IA64_SN_ACPI_H */ diff --git a/trunk/include/asm-ia64/sn/pcibr_provider.h b/trunk/include/asm-ia64/sn/pcibr_provider.h index 17cb6cc3f21a..da3eade0cae2 100644 --- a/trunk/include/asm-ia64/sn/pcibr_provider.h +++ b/trunk/include/asm-ia64/sn/pcibr_provider.h @@ -142,7 +142,7 @@ extern int pcibr_ate_alloc(struct pcibus_info *, int); extern void pcibr_ate_free(struct pcibus_info *, int); extern void ate_write(struct pcibus_info *, int, int, u64); extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device, - void *resp, char **ssdt); + void *resp); extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, void *resp); extern u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus); diff --git a/trunk/include/asm-ia64/sn/pcidev.h b/trunk/include/asm-ia64/sn/pcidev.h index 1c2382cea807..9fe89a93d880 100644 --- a/trunk/include/asm-ia64/sn/pcidev.h +++ b/trunk/include/asm-ia64/sn/pcidev.h @@ -70,16 +70,10 @@ extern void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info); extern void sn_irq_unfixup(struct pci_dev *pci_dev); extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *); -extern void sn_bus_fixup(struct pci_bus *); -extern void sn_acpi_bus_fixup(struct pci_bus *); -extern void sn_common_bus_fixup(struct pci_bus *, struct pcibus_bussoft *); extern void sn_bus_store_sysdata(struct pci_dev *dev); extern void sn_bus_free_sysdata(void); extern void sn_generate_path(struct pci_bus *pci_bus, char *address); -extern void sn_io_slot_fixup(struct pci_dev *); -extern void sn_acpi_slot_fixup(struct pci_dev *); -extern void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *, - struct sn_irq_info *); +extern void sn_pci_fixup_slot(struct pci_dev *dev); extern void sn_pci_unfixup_slot(struct pci_dev *dev); extern void sn_irq_lh_init(void); #endif /* _ASM_IA64_SN_PCI_PCIDEV_H */ diff --git a/trunk/include/asm-ia64/swiotlb.h b/trunk/include/asm-ia64/swiotlb.h deleted file mode 100644 index 452c162dee4e..000000000000 --- a/trunk/include/asm-ia64/swiotlb.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _ASM_SWIOTLB_H -#define _ASM_SWIOTLB_H 1 - -#include - -#define SWIOTLB_ARCH_NEED_LATE_INIT -#define SWIOTLB_ARCH_NEED_ALLOC - -#endif /* _ASM_SWIOTLB_H */ diff --git a/trunk/include/asm-ia64/thread_info.h b/trunk/include/asm-ia64/thread_info.h index 91698599f918..9b505b25544f 100644 --- a/trunk/include/asm-ia64/thread_info.h +++ b/trunk/include/asm-ia64/thread_info.h @@ -84,7 +84,6 @@ struct thread_info { #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_SYSCALL_TRACE 3 /* syscall trace active */ #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ -#define TIF_SINGLESTEP 5 /* restore singlestep on return to user mode */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ @@ -93,8 +92,7 @@ struct thread_info { #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) -#define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP) +#define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/trunk/include/asm-ia64/unistd.h b/trunk/include/asm-ia64/unistd.h index a9e1fa4cac4d..53c5c0ee122c 100644 --- a/trunk/include/asm-ia64/unistd.h +++ b/trunk/include/asm-ia64/unistd.h @@ -291,13 +291,11 @@ #define __NR_sync_file_range 1300 #define __NR_tee 1301 #define __NR_vmsplice 1302 -/* 1303 reserved for move_pages */ -#define __NR_getcpu 1304 #ifdef __KERNEL__ -#define NR_syscalls 281 /* length of syscall table */ +#define NR_syscalls 279 /* length of syscall table */ #define __ARCH_WANT_SYS_RT_SIGACTION diff --git a/trunk/include/asm-mips/bootinfo.h b/trunk/include/asm-mips/bootinfo.h index c7c945baf1ee..8e321f53a382 100644 --- a/trunk/include/asm-mips/bootinfo.h +++ b/trunk/include/asm-mips/bootinfo.h @@ -243,10 +243,6 @@ extern struct boot_mem_map boot_mem_map; extern void add_memory_region(phys_t start, phys_t size, long type); extern void prom_init(void); -extern void prom_free_prom_memory(void); - -extern void free_init_pages(const char *what, - unsigned long begin, unsigned long end); /* * Initial kernel command line, usually setup by prom_init() diff --git a/trunk/include/asm-mips/ddb5xxx/ddb5477.h b/trunk/include/asm-mips/ddb5xxx/ddb5477.h index 6cf177caf6d5..c5af4b73fdd7 100644 --- a/trunk/include/asm-mips/ddb5xxx/ddb5477.h +++ b/trunk/include/asm-mips/ddb5xxx/ddb5477.h @@ -17,7 +17,6 @@ #ifndef __ASM_DDB5XXX_DDB5477_H #define __ASM_DDB5XXX_DDB5477_H -#include /* * This contains macros that are specific to DDB5477 or renamed from @@ -252,10 +251,14 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq); */ #define NUM_CPU_IRQ 8 +#define NUM_I8259_IRQ 16 #define NUM_VRC5477_IRQ 32 -#define CPU_IRQ_BASE MIPS_CPU_IRQ_BASE -#define VRC5477_IRQ_BASE (CPU_IRQ_BASE + NUM_CPU_IRQ) +#define DDB_IRQ_BASE 0 + +#define I8259_IRQ_BASE DDB_IRQ_BASE +#define VRC5477_IRQ_BASE (I8259_IRQ_BASE + NUM_I8259_IRQ) +#define CPU_IRQ_BASE (VRC5477_IRQ_BASE + NUM_VRC5477_IRQ) /* * vrc5477 irq defs @@ -297,22 +300,22 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq); /* * i2859 irq assignment */ -#define I8259_IRQ_RESERVED_0 (0 + I8259A_IRQ_BASE) -#define I8259_IRQ_KEYBOARD (1 + I8259A_IRQ_BASE) /* M1543 default */ -#define I8259_IRQ_CASCADE (2 + I8259A_IRQ_BASE) -#define I8259_IRQ_UART_B (3 + I8259A_IRQ_BASE) /* M1543 default, may conflict with RTC according to schematic diagram */ -#define I8259_IRQ_UART_A (4 + I8259A_IRQ_BASE) /* M1543 default */ -#define I8259_IRQ_PARALLEL (5 + I8259A_IRQ_BASE) /* M1543 default */ -#define I8259_IRQ_RESERVED_6 (6 + I8259A_IRQ_BASE) -#define I8259_IRQ_RESERVED_7 (7 + I8259A_IRQ_BASE) -#define I8259_IRQ_RTC (8 + I8259A_IRQ_BASE) /* who set this? */ -#define I8259_IRQ_USB (9 + I8259A_IRQ_BASE) /* ddb_setup */ -#define I8259_IRQ_PMU (10 + I8259A_IRQ_BASE) /* ddb_setup */ -#define I8259_IRQ_RESERVED_11 (11 + I8259A_IRQ_BASE) -#define I8259_IRQ_RESERVED_12 (12 + I8259A_IRQ_BASE) /* m1543_irq_setup */ -#define I8259_IRQ_RESERVED_13 (13 + I8259A_IRQ_BASE) -#define I8259_IRQ_HDC1 (14 + I8259A_IRQ_BASE) /* default and ddb_setup */ -#define I8259_IRQ_HDC2 (15 + I8259A_IRQ_BASE) /* default */ +#define I8259_IRQ_RESERVED_0 (0 + I8259_IRQ_BASE) +#define I8259_IRQ_KEYBOARD (1 + I8259_IRQ_BASE) /* M1543 default */ +#define I8259_IRQ_CASCADE (2 + I8259_IRQ_BASE) +#define I8259_IRQ_UART_B (3 + I8259_IRQ_BASE) /* M1543 default, may conflict with RTC according to schematic diagram */ +#define I8259_IRQ_UART_A (4 + I8259_IRQ_BASE) /* M1543 default */ +#define I8259_IRQ_PARALLEL (5 + I8259_IRQ_BASE) /* M1543 default */ +#define I8259_IRQ_RESERVED_6 (6 + I8259_IRQ_BASE) +#define I8259_IRQ_RESERVED_7 (7 + I8259_IRQ_BASE) +#define I8259_IRQ_RTC (8 + I8259_IRQ_BASE) /* who set this? */ +#define I8259_IRQ_USB (9 + I8259_IRQ_BASE) /* ddb_setup */ +#define I8259_IRQ_PMU (10 + I8259_IRQ_BASE) /* ddb_setup */ +#define I8259_IRQ_RESERVED_11 (11 + I8259_IRQ_BASE) +#define I8259_IRQ_RESERVED_12 (12 + I8259_IRQ_BASE) /* m1543_irq_setup */ +#define I8259_IRQ_RESERVED_13 (13 + I8259_IRQ_BASE) +#define I8259_IRQ_HDC1 (14 + I8259_IRQ_BASE) /* default and ddb_setup */ +#define I8259_IRQ_HDC2 (15 + I8259_IRQ_BASE) /* default */ /* diff --git a/trunk/include/asm-mips/dec/interrupts.h b/trunk/include/asm-mips/dec/interrupts.h index e10d341067c8..273e4d65bfe6 100644 --- a/trunk/include/asm-mips/dec/interrupts.h +++ b/trunk/include/asm-mips/dec/interrupts.h @@ -14,7 +14,6 @@ #ifndef __ASM_DEC_INTERRUPTS_H #define __ASM_DEC_INTERRUPTS_H -#include #include @@ -88,7 +87,7 @@ #define DEC_CPU_INR_SW1 1 /* software #1 */ #define DEC_CPU_INR_SW0 0 /* software #0 */ -#define DEC_CPU_IRQ_BASE MIPS_CPU_IRQ_BASE /* first IRQ assigned to CPU */ +#define DEC_CPU_IRQ_BASE 0 /* first IRQ assigned to CPU */ #define DEC_CPU_IRQ_NR(n) ((n) + DEC_CPU_IRQ_BASE) #define DEC_CPU_IRQ_MASK(n) (1 << ((n) + CAUSEB_IP)) diff --git a/trunk/include/asm-mips/dma.h b/trunk/include/asm-mips/dma.h index e06ef0776d48..23f789c80845 100644 --- a/trunk/include/asm-mips/dma.h +++ b/trunk/include/asm-mips/dma.h @@ -91,7 +91,6 @@ #else #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) #endif -#define MAX_DMA_PFN PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS)) /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ diff --git a/trunk/include/asm-mips/emma2rh/emma2rh.h b/trunk/include/asm-mips/emma2rh/emma2rh.h index 6a1af0af51e3..4fb8df71caa9 100644 --- a/trunk/include/asm-mips/emma2rh/emma2rh.h +++ b/trunk/include/asm-mips/emma2rh/emma2rh.h @@ -24,8 +24,6 @@ #ifndef __ASM_EMMA2RH_EMMA2RH_H #define __ASM_EMMA2RH_EMMA2RH_H -#include - /* * EMMA2RH registers */ @@ -106,8 +104,7 @@ #define NUM_EMMA2RH_IRQ 96 #define CPU_EMMA2RH_CASCADE 2 -#define CPU_IRQ_BASE MIPS_CPU_IRQ_BASE -#define EMMA2RH_IRQ_BASE (CPU_IRQ_BASE + NUM_CPU_IRQ) +#define EMMA2RH_IRQ_BASE 0 /* * emma2rh irq defs diff --git a/trunk/include/asm-mips/emma2rh/markeins.h b/trunk/include/asm-mips/emma2rh/markeins.h index 973b0628490d..8fa766795078 100644 --- a/trunk/include/asm-mips/emma2rh/markeins.h +++ b/trunk/include/asm-mips/emma2rh/markeins.h @@ -33,6 +33,7 @@ #define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) #define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) +#define CPU_IRQ_BASE (EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO) #define EMMA2RH_SW_IRQ_INT0 (0+EMMA2RH_SW_IRQ_BASE) #define EMMA2RH_SW_IRQ_INT1 (1+EMMA2RH_SW_IRQ_BASE) diff --git a/trunk/include/asm-mips/i8259.h b/trunk/include/asm-mips/i8259.h index e88a01607fea..4df8d8b118c0 100644 --- a/trunk/include/asm-mips/i8259.h +++ b/trunk/include/asm-mips/i8259.h @@ -18,7 +18,6 @@ #include #include -#include /* i8259A PIC registers */ #define PIC_MASTER_CMD 0x20 @@ -43,6 +42,8 @@ extern void disable_8259A_irq(unsigned int irq); extern void init_i8259_irqs(void); +#define I8259A_IRQ_BASE 0 + /* * Do the traditional i8259 interrupt polling thing. This is for the few * cases where no better interrupt acknowledge method is available and we diff --git a/trunk/include/asm-mips/io.h b/trunk/include/asm-mips/io.h index 67f081078904..d77b657c09c7 100644 --- a/trunk/include/asm-mips/io.h +++ b/trunk/include/asm-mips/io.h @@ -115,7 +115,7 @@ static inline void set_io_port_base(unsigned long base) */ static inline unsigned long virt_to_phys(volatile const void *address) { - return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET; + return (unsigned long)address - PAGE_OFFSET; } /* @@ -132,7 +132,7 @@ static inline unsigned long virt_to_phys(volatile const void *address) */ static inline void * phys_to_virt(unsigned long address) { - return (void *)(address + PAGE_OFFSET - PHYS_OFFSET); + return (void *)(address + PAGE_OFFSET); } /* diff --git a/trunk/include/asm-mips/irq.h b/trunk/include/asm-mips/irq.h index 91803ba30ff2..386da82e5774 100644 --- a/trunk/include/asm-mips/irq.h +++ b/trunk/include/asm-mips/irq.h @@ -18,7 +18,7 @@ #ifdef CONFIG_I8259 static inline int irq_canonicalize(int irq) { - return ((irq == I8259A_IRQ_BASE + 2) ? I8259A_IRQ_BASE + 9 : irq); + return ((irq == 2) ? 9 : irq); } #else #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ diff --git a/trunk/include/asm-mips/irq_cpu.h b/trunk/include/asm-mips/irq_cpu.h index ef6a07cddb23..ed3d1e3d09ec 100644 --- a/trunk/include/asm-mips/irq_cpu.h +++ b/trunk/include/asm-mips/irq_cpu.h @@ -13,8 +13,8 @@ #ifndef _ASM_IRQ_CPU_H #define _ASM_IRQ_CPU_H -extern void mips_cpu_irq_init(void); -extern void rm7k_cpu_irq_init(void); -extern void rm9k_cpu_irq_init(void); +extern void mips_cpu_irq_init(int irq_base); +extern void rm7k_cpu_irq_init(int irq_base); +extern void rm9k_cpu_irq_init(int irq_base); #endif /* _ASM_IRQ_CPU_H */ diff --git a/trunk/include/asm-mips/mach-au1x00/au1000.h b/trunk/include/asm-mips/mach-au1x00/au1000.h index 58fca8a5a9a6..582acd8adb81 100644 --- a/trunk/include/asm-mips/mach-au1x00/au1000.h +++ b/trunk/include/asm-mips/mach-au1x00/au1000.h @@ -39,7 +39,6 @@ #ifndef _LANGUAGE_ASSEMBLY #include -#include #include /* cpu pipeline flush */ diff --git a/trunk/include/asm-mips/mach-cobalt/cobalt.h b/trunk/include/asm-mips/mach-cobalt/cobalt.h index 24a8d51a55a3..00b0fc68d5cb 100644 --- a/trunk/include/asm-mips/mach-cobalt/cobalt.h +++ b/trunk/include/asm-mips/mach-cobalt/cobalt.h @@ -12,8 +12,6 @@ #ifndef __ASM_COBALT_H #define __ASM_COBALT_H -#include - /* * i8259 legacy interrupts used on Cobalt: * @@ -27,7 +25,7 @@ /* * CPU IRQs are 16 ... 23 */ -#define COBALT_CPU_IRQ MIPS_CPU_IRQ_BASE +#define COBALT_CPU_IRQ 16 #define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2) #define COBALT_SCC_IRQ (COBALT_CPU_IRQ + 3) /* pre-production has 85C30 */ diff --git a/trunk/include/asm-mips/mach-emma2rh/irq.h b/trunk/include/asm-mips/mach-emma2rh/irq.h index 5439eb856461..bce64244b800 100644 --- a/trunk/include/asm-mips/mach-emma2rh/irq.h +++ b/trunk/include/asm-mips/mach-emma2rh/irq.h @@ -10,6 +10,4 @@ #define NR_IRQS 256 -#include_next - #endif /* __ASM_MACH_EMMA2RH_IRQ_H */ diff --git a/trunk/include/asm-mips/mach-generic/irq.h b/trunk/include/asm-mips/mach-generic/irq.h index 70d9a25132c5..500e10ff24de 100644 --- a/trunk/include/asm-mips/mach-generic/irq.h +++ b/trunk/include/asm-mips/mach-generic/irq.h @@ -8,38 +8,6 @@ #ifndef __ASM_MACH_GENERIC_IRQ_H #define __ASM_MACH_GENERIC_IRQ_H -#ifndef NR_IRQS #define NR_IRQS 128 -#endif - -#ifdef CONFIG_I8259 -#ifndef I8259A_IRQ_BASE -#define I8259A_IRQ_BASE 0 -#endif -#endif - -#ifdef CONFIG_IRQ_CPU - -#ifndef MIPS_CPU_IRQ_BASE -#ifdef CONFIG_I8259 -#define MIPS_CPU_IRQ_BASE 16 -#else -#define MIPS_CPU_IRQ_BASE 0 -#endif /* CONFIG_I8259 */ -#endif - -#ifdef CONFIG_IRQ_CPU_RM7K -#ifndef RM7K_CPU_IRQ_BASE -#define RM7K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+8) -#endif -#endif - -#ifdef CONFIG_IRQ_CPU_RM9K -#ifndef RM9K_CPU_IRQ_BASE -#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12) -#endif -#endif - -#endif /* CONFIG_IRQ_CPU */ #endif /* __ASM_MACH_GENERIC_IRQ_H */ diff --git a/trunk/include/asm-mips/mach-mips/irq.h b/trunk/include/asm-mips/mach-mips/irq.h index 9b9da26683c2..e994b0c01227 100644 --- a/trunk/include/asm-mips/mach-mips/irq.h +++ b/trunk/include/asm-mips/mach-mips/irq.h @@ -4,6 +4,4 @@ #define NR_IRQS 256 -#include_next - #endif /* __ASM_MACH_MIPS_IRQ_H */ diff --git a/trunk/include/asm-mips/mach-vr41xx/irq.h b/trunk/include/asm-mips/mach-vr41xx/irq.h deleted file mode 100644 index 848812296052..000000000000 --- a/trunk/include/asm-mips/mach-vr41xx/irq.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_VR41XX_IRQ_H -#define __ASM_MACH_VR41XX_IRQ_H - -#include /* for MIPS_CPU_IRQ_BASE */ -#ifdef CONFIG_NEC_CMBVR4133 -#include /* for I8259A_IRQ_BASE */ -#endif - -#include_next - -#endif /* __ASM_MACH_VR41XX_IRQ_H */ diff --git a/trunk/include/asm-mips/mips-boards/atlasint.h b/trunk/include/asm-mips/mips-boards/atlasint.h index 76add42e486e..b15e4ea0b091 100644 --- a/trunk/include/asm-mips/mips-boards/atlasint.h +++ b/trunk/include/asm-mips/mips-boards/atlasint.h @@ -26,12 +26,10 @@ #ifndef _MIPS_ATLASINT_H #define _MIPS_ATLASINT_H -#include - /* * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode) */ -#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE +#define MIPSCPU_INT_BASE 0 /* CPU interrupt offsets */ #define MIPSCPU_INT_SW0 0 diff --git a/trunk/include/asm-mips/mips-boards/maltaint.h b/trunk/include/asm-mips/mips-boards/maltaint.h index 9180d6466113..da6cc2fbbc78 100644 --- a/trunk/include/asm-mips/mips-boards/maltaint.h +++ b/trunk/include/asm-mips/mips-boards/maltaint.h @@ -25,8 +25,6 @@ #ifndef _MIPS_MALTAINT_H #define _MIPS_MALTAINT_H -#include - /* * Interrupts 0..15 are used for Malta ISA compatible interrupts */ @@ -35,7 +33,7 @@ /* * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode) */ -#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE +#define MIPSCPU_INT_BASE 16 /* CPU interrupt offsets */ #define MIPSCPU_INT_SW0 0 diff --git a/trunk/include/asm-mips/mips-boards/prom.h b/trunk/include/asm-mips/mips-boards/prom.h index 7bf6f5f6ab9c..4168c7fcd43e 100644 --- a/trunk/include/asm-mips/mips-boards/prom.h +++ b/trunk/include/asm-mips/mips-boards/prom.h @@ -33,6 +33,7 @@ extern void prom_printf(char *fmt, ...); extern void prom_init_cmdline(void); extern void prom_meminit(void); extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); +extern unsigned long prom_free_prom_memory (void); extern void mips_display_message(const char *str); extern void mips_display_word(unsigned int num); extern int get_ethernet_addr(char *ethernet_addr); diff --git a/trunk/include/asm-mips/mips-boards/seadint.h b/trunk/include/asm-mips/mips-boards/seadint.h index 4f6a3933699d..365c2a3c64f5 100644 --- a/trunk/include/asm-mips/mips-boards/seadint.h +++ b/trunk/include/asm-mips/mips-boards/seadint.h @@ -20,12 +20,10 @@ #ifndef _MIPS_SEADINT_H #define _MIPS_SEADINT_H -#include - /* * Interrupts 0..7 are used for SEAD CPU interrupts */ -#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE +#define MIPSCPU_INT_BASE 0 #define MIPSCPU_INT_UART0 2 #define MIPSCPU_INT_UART1 3 diff --git a/trunk/include/asm-mips/mips-boards/simint.h b/trunk/include/asm-mips/mips-boards/simint.h index 54f2fe621d69..4952e0b3bf11 100644 --- a/trunk/include/asm-mips/mips-boards/simint.h +++ b/trunk/include/asm-mips/mips-boards/simint.h @@ -17,11 +17,10 @@ #ifndef _MIPS_SIMINT_H #define _MIPS_SIMINT_H -#include #define SIM_INT_BASE 0 #define MIPSCPU_INT_MB0 2 -#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE +#define MIPSCPU_INT_BASE 16 #define MIPS_CPU_TIMER_IRQ 7 diff --git a/trunk/include/asm-mips/mipsmtregs.h b/trunk/include/asm-mips/mipsmtregs.h index 294bca12cd3f..3e9468f424f4 100644 --- a/trunk/include/asm-mips/mipsmtregs.h +++ b/trunk/include/asm-mips/mipsmtregs.h @@ -165,6 +165,8 @@ #ifndef __ASSEMBLY__ +extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value); + static inline unsigned int dvpe(void) { int res = 0; diff --git a/trunk/include/asm-mips/page.h b/trunk/include/asm-mips/page.h index d3fbd83ff545..2f9e1a9ec51f 100644 --- a/trunk/include/asm-mips/page.h +++ b/trunk/include/asm-mips/page.h @@ -34,20 +34,6 @@ #ifndef __ASSEMBLY__ -/* - * This gives the physical RAM offset. - */ -#ifndef PHYS_OFFSET -#define PHYS_OFFSET 0UL -#endif - -/* - * It's normally defined only for FLATMEM config but it's - * used in our early mem init code for all memory models. - * So always define it. - */ -#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET) - #include #include @@ -146,23 +132,20 @@ typedef struct { unsigned long pgprot; } pgprot_t; /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) -/* - * __pa()/__va() should be used only during mem init. - */ #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64) #define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0) #else #define __pa_page_offset(x) PAGE_OFFSET #endif -#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET) -#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) -#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0)) +#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x)) +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0)) +#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) #ifdef CONFIG_FLATMEM -#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr) +#define pfn_valid(pfn) ((pfn) < max_mapnr) #elif defined(CONFIG_SPARSEMEM) diff --git a/trunk/include/asm-mips/rtlx.h b/trunk/include/asm-mips/rtlx.h index 59162f74a798..76cd51c6be39 100644 --- a/trunk/include/asm-mips/rtlx.h +++ b/trunk/include/asm-mips/rtlx.h @@ -6,10 +6,9 @@ #ifndef __ASM_RTLX_H #define __ASM_RTLX_H_ -#include - #define LX_NODE_BASE 10 +#define MIPSCPU_INT_BASE 16 #define MIPS_CPU_RTLX_IRQ 0 #define RTLX_VERSION 2 diff --git a/trunk/include/asm-mips/sections.h b/trunk/include/asm-mips/sections.h index b7e37262c246..f7016278b266 100644 --- a/trunk/include/asm-mips/sections.h +++ b/trunk/include/asm-mips/sections.h @@ -3,4 +3,6 @@ #include +extern char _fdata; + #endif /* _ASM_SECTIONS_H */ diff --git a/trunk/include/asm-mips/sgi/ip22.h b/trunk/include/asm-mips/sgi/ip22.h index 6592f3bd1999..bbfc05c3cab9 100644 --- a/trunk/include/asm-mips/sgi/ip22.h +++ b/trunk/include/asm-mips/sgi/ip22.h @@ -21,16 +21,15 @@ * HAL2 driver). This will prevent many complications, trust me ;-) */ -#include #include #define SGINT_EISA 0 /* 16 EISA irq levels (Indigo2) */ -#define SGINT_CPU MIPS_CPU_IRQ_BASE /* MIPS CPU define 8 interrupt sources */ -#define SGINT_LOCAL0 (SGINT_CPU+8) /* 8 local0 irq levels */ -#define SGINT_LOCAL1 (SGINT_CPU+16) /* 8 local1 irq levels */ -#define SGINT_LOCAL2 (SGINT_CPU+24) /* 8 local2 vectored irq levels */ -#define SGINT_LOCAL3 (SGINT_CPU+32) /* 8 local3 vectored irq levels */ -#define SGINT_END (SGINT_CPU+40) /* End of 'spaces' */ +#define SGINT_CPU 16 /* MIPS CPU define 8 interrupt sources */ +#define SGINT_LOCAL0 24 /* 8 local0 irq levels */ +#define SGINT_LOCAL1 32 /* 8 local1 irq levels */ +#define SGINT_LOCAL2 40 /* 8 local2 vectored irq levels */ +#define SGINT_LOCAL3 48 /* 8 local3 vectored irq levels */ +#define SGINT_END 56 /* End of 'spaces' */ /* * Individual interrupt definitions for the Indy and Indigo2 diff --git a/trunk/include/asm-mips/smtc_ipi.h b/trunk/include/asm-mips/smtc_ipi.h index 55f3419f6546..f22c3e2f993a 100644 --- a/trunk/include/asm-mips/smtc_ipi.h +++ b/trunk/include/asm-mips/smtc_ipi.h @@ -44,6 +44,9 @@ struct smtc_ipi_q { int depth; }; +extern struct smtc_ipi_q IPIQ[NR_CPUS]; +extern struct smtc_ipi_q freeIPIq; + static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) { long flags; diff --git a/trunk/include/asm-mips/uaccess.h b/trunk/include/asm-mips/uaccess.h index c12ebc53ef31..1cdd4eeb2f73 100644 --- a/trunk/include/asm-mips/uaccess.h +++ b/trunk/include/asm-mips/uaccess.h @@ -488,8 +488,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n); }) /* - * __copy_from_user: - Copy a block of data from user space, with less checking. - * @to: Destination address, in kernel space. + * __copy_from_user: - Copy a block of data from user space, with less checking. * @to: Destination address, in kernel space. * @from: Source address, in user space. * @n: Number of bytes to copy. * diff --git a/trunk/include/asm-mips/vr41xx/cmbvr4133.h b/trunk/include/asm-mips/vr41xx/cmbvr4133.h index 42300037d593..9490ade58b46 100644 --- a/trunk/include/asm-mips/vr41xx/cmbvr4133.h +++ b/trunk/include/asm-mips/vr41xx/cmbvr4133.h @@ -35,8 +35,8 @@ #define CMBVR41XX_INTD_IRQ GIU_IRQ(CMBVR41XX_INTD_PIN) #define CMBVR41XX_INTE_IRQ GIU_IRQ(CMBVR41XX_INTE_PIN) -#define I8259A_IRQ_BASE 72 -#define I8259_IRQ(x) (I8259A_IRQ_BASE + (x)) +#define I8259_IRQ_BASE 72 +#define I8259_IRQ(x) (I8259_IRQ_BASE + (x)) #define TIMER_IRQ I8259_IRQ(0) #define KEYBOARD_IRQ I8259_IRQ(1) #define I8259_SLAVE_IRQ I8259_IRQ(2) @@ -52,5 +52,6 @@ #define AUX_IRQ I8259_IRQ(12) #define IDE_PRIMARY_IRQ I8259_IRQ(14) #define IDE_SECONDARY_IRQ I8259_IRQ(15) +#define I8259_IRQ_LAST IDE_SECONDARY_IRQ #endif /* __NEC_CMBVR4133_H */ diff --git a/trunk/include/asm-s390/compat.h b/trunk/include/asm-s390/compat.h index 296f4f1a20e1..356a0b183539 100644 --- a/trunk/include/asm-s390/compat.h +++ b/trunk/include/asm-s390/compat.h @@ -6,34 +6,6 @@ #include #include -#define PSW32_MASK_PER 0x40000000UL -#define PSW32_MASK_DAT 0x04000000UL -#define PSW32_MASK_IO 0x02000000UL -#define PSW32_MASK_EXT 0x01000000UL -#define PSW32_MASK_KEY 0x00F00000UL -#define PSW32_MASK_MCHECK 0x00040000UL -#define PSW32_MASK_WAIT 0x00020000UL -#define PSW32_MASK_PSTATE 0x00010000UL -#define PSW32_MASK_ASC 0x0000C000UL -#define PSW32_MASK_CC 0x00003000UL -#define PSW32_MASK_PM 0x00000f00UL - -#define PSW32_ADDR_AMODE31 0x80000000UL -#define PSW32_ADDR_INSN 0x7FFFFFFFUL - -#define PSW32_BASE_BITS 0x00080000UL - -#define PSW32_ASC_PRIMARY 0x00000000UL -#define PSW32_ASC_ACCREG 0x00004000UL -#define PSW32_ASC_SECONDARY 0x00008000UL -#define PSW32_ASC_HOME 0x0000C000UL - -#define PSW32_MASK_MERGE(CURRENT,NEW) \ - (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \ - ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM))) - -extern long psw32_user_bits; - #define COMPAT_USER_HZ 100 typedef u32 compat_size_t; diff --git a/trunk/include/asm-s390/etr.h b/trunk/include/asm-s390/etr.h deleted file mode 100644 index b498f19bb9a7..000000000000 --- a/trunk/include/asm-s390/etr.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * include/asm-s390/etr.h - * - * Copyright IBM Corp. 2006 - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) - */ -#ifndef __S390_ETR_H -#define __S390_ETR_H - -/* ETR attachment control register */ -struct etr_eacr { - unsigned int e0 : 1; /* port 0 stepping control */ - unsigned int e1 : 1; /* port 1 stepping control */ - unsigned int _pad0 : 5; /* must be 00100 */ - unsigned int dp : 1; /* data port control */ - unsigned int p0 : 1; /* port 0 change recognition control */ - unsigned int p1 : 1; /* port 1 change recognition control */ - unsigned int _pad1 : 3; /* must be 000 */ - unsigned int ea : 1; /* ETR alert control */ - unsigned int es : 1; /* ETR sync check control */ - unsigned int sl : 1; /* switch to local control */ -} __attribute__ ((packed)); - -/* Port state returned by steai */ -enum etr_psc { - etr_psc_operational = 0, - etr_psc_semi_operational = 1, - etr_psc_protocol_error = 4, - etr_psc_no_symbols = 8, - etr_psc_no_signal = 12, - etr_psc_pps_mode = 13 -}; - -/* Logical port state returned by stetr */ -enum etr_lpsc { - etr_lpsc_operational_step = 0, - etr_lpsc_operational_alt = 1, - etr_lpsc_semi_operational = 2, - etr_lpsc_protocol_error = 4, - etr_lpsc_no_symbol_sync = 8, - etr_lpsc_no_signal = 12, - etr_lpsc_pps_mode = 13 -}; - -/* ETR status words */ -struct etr_esw { - struct etr_eacr eacr; /* attachment control register */ - unsigned int y : 1; /* stepping mode */ - unsigned int _pad0 : 5; /* must be 00000 */ - unsigned int p : 1; /* stepping port number */ - unsigned int q : 1; /* data port number */ - unsigned int psc0 : 4; /* port 0 state code */ - unsigned int psc1 : 4; /* port 1 state code */ -} __attribute__ ((packed)); - -/* Second level data register status word */ -struct etr_slsw { - unsigned int vv1 : 1; /* copy of validity bit data frame 1 */ - unsigned int vv2 : 1; /* copy of validity bit data frame 2 */ - unsigned int vv3 : 1; /* copy of validity bit data frame 3 */ - unsigned int vv4 : 1; /* copy of validity bit data frame 4 */ - unsigned int _pad0 : 19; /* must by all zeroes */ - unsigned int n : 1; /* EAF port number */ - unsigned int v1 : 1; /* validity bit ETR data frame 1 */ - unsigned int v2 : 1; /* validity bit ETR data frame 2 */ - unsigned int v3 : 1; /* validity bit ETR data frame 3 */ - unsigned int v4 : 1; /* validity bit ETR data frame 4 */ - unsigned int _pad1 : 4; /* must be 0000 */ -} __attribute__ ((packed)); - -/* ETR data frames */ -struct etr_edf1 { - unsigned int u : 1; /* untuned bit */ - unsigned int _pad0 : 1; /* must be 0 */ - unsigned int r : 1; /* service request bit */ - unsigned int _pad1 : 4; /* must be 0000 */ - unsigned int a : 1; /* time adjustment bit */ - unsigned int net_id : 8; /* ETR network id */ - unsigned int etr_id : 8; /* id of ETR which sends data frames */ - unsigned int etr_pn : 8; /* port number of ETR output port */ -} __attribute__ ((packed)); - -struct etr_edf2 { - unsigned int etv : 32; /* Upper 32 bits of TOD. */ -} __attribute__ ((packed)); - -struct etr_edf3 { - unsigned int rc : 8; /* failure reason code */ - unsigned int _pad0 : 3; /* must be 000 */ - unsigned int c : 1; /* ETR coupled bit */ - unsigned int tc : 4; /* ETR type code */ - unsigned int blto : 8; /* biased local time offset */ - /* (blto - 128) * 15 = minutes */ - unsigned int buo : 8; /* biased utc offset */ - /* (buo - 128) = leap seconds */ -} __attribute__ ((packed)); - -struct etr_edf4 { - unsigned int ed : 8; /* ETS device dependent data */ - unsigned int _pad0 : 1; /* must be 0 */ - unsigned int buc : 5; /* biased ut1 correction */ - /* (buc - 16) * 0.1 seconds */ - unsigned int em : 6; /* ETS error magnitude */ - unsigned int dc : 6; /* ETS drift code */ - unsigned int sc : 6; /* ETS steering code */ -} __attribute__ ((packed)); - -/* - * ETR attachment information block, two formats - * format 1 has 4 reserved words with a size of 64 bytes - * format 2 has 16 reserved words with a size of 96 bytes - */ -struct etr_aib { - struct etr_esw esw; - struct etr_slsw slsw; - unsigned long long tsp; - struct etr_edf1 edf1; - struct etr_edf2 edf2; - struct etr_edf3 edf3; - struct etr_edf4 edf4; - unsigned int reserved[16]; -} __attribute__ ((packed,aligned(8))); - -/* ETR interruption parameter */ -struct etr_interruption_parameter { - unsigned int _pad0 : 8; - unsigned int pc0 : 1; /* port 0 state change */ - unsigned int pc1 : 1; /* port 1 state change */ - unsigned int _pad1 : 3; - unsigned int eai : 1; /* ETR alert indication */ - unsigned int _pad2 : 18; -} __attribute__ ((packed)); - -/* Query TOD offset result */ -struct etr_ptff_qto { - unsigned long long physical_clock; - unsigned long long tod_offset; - unsigned long long logical_tod_offset; - unsigned long long tod_epoch_difference; -} __attribute__ ((packed)); - -/* Inline assembly helper functions */ -static inline int etr_setr(struct etr_eacr *ctrl) -{ - int rc = -ENOSYS; - - asm volatile( - " .insn s,0xb2160000,0(%2)\n" - "0: la %0,0\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (rc) : "m" (*ctrl), "a" (ctrl)); - return rc; -} - -/* Stores a format 1 aib with 64 bytes */ -static inline int etr_stetr(struct etr_aib *aib) -{ - int rc = -ENOSYS; - - asm volatile( - " .insn s,0xb2170000,0(%2)\n" - "0: la %0,0\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (rc) : "m" (*aib), "a" (aib)); - return rc; -} - -/* Stores a format 2 aib with 96 bytes for specified port */ -static inline int etr_steai(struct etr_aib *aib, unsigned int func) -{ - register unsigned int reg0 asm("0") = func; - int rc = -ENOSYS; - - asm volatile( - " .insn s,0xb2b30000,0(%2)\n" - "0: la %0,0\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0)); - return rc; -} - -/* Function codes for the steai instruction. */ -#define ETR_STEAI_STEPPING_PORT 0x10 -#define ETR_STEAI_ALTERNATE_PORT 0x11 -#define ETR_STEAI_PORT_0 0x12 -#define ETR_STEAI_PORT_1 0x13 - -static inline int etr_ptff(void *ptff_block, unsigned int func) -{ - register unsigned int reg0 asm("0") = func; - register unsigned long reg1 asm("1") = (unsigned long) ptff_block; - int rc = -ENOSYS; - - asm volatile( - " .word 0x0104\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (rc), "=m" (ptff_block) - : "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc"); - return rc; -} - -/* Function codes for the ptff instruction. */ -#define ETR_PTFF_QAF 0x00 /* query available functions */ -#define ETR_PTFF_QTO 0x01 /* query tod offset */ -#define ETR_PTFF_QSI 0x02 /* query steering information */ -#define ETR_PTFF_ATO 0x40 /* adjust tod offset */ -#define ETR_PTFF_STO 0x41 /* set tod offset */ -#define ETR_PTFF_SFS 0x42 /* set fine steering rate */ -#define ETR_PTFF_SGS 0x43 /* set gross steering rate */ - -/* Functions needed by the machine check handler */ -extern void etr_switch_to_local(void); -extern void etr_sync_check(void); - -#endif /* __S390_ETR_H */ diff --git a/trunk/include/asm-s390/hardirq.h b/trunk/include/asm-s390/hardirq.h index 31beb18cb3d1..c2f6a8782d31 100644 --- a/trunk/include/asm-s390/hardirq.h +++ b/trunk/include/asm-s390/hardirq.h @@ -32,6 +32,6 @@ typedef struct { #define HARDIRQ_BITS 8 -extern void account_ticks(u64 time); +extern void account_ticks(void); #endif /* __ASM_HARDIRQ_H */ diff --git a/trunk/include/asm-s390/io.h b/trunk/include/asm-s390/io.h index a4c2d550dad4..efb7de9c1c6b 100644 --- a/trunk/include/asm-s390/io.h +++ b/trunk/include/asm-s390/io.h @@ -28,7 +28,11 @@ static inline unsigned long virt_to_phys(volatile void * address) { unsigned long real_address; asm volatile( +#ifndef __s390x__ " lra %0,0(%1)\n" +#else /* __s390x__ */ + " lrag %0,0(%1)\n" +#endif /* __s390x__ */ " jz 0f\n" " la %0,0\n" "0:" diff --git a/trunk/include/asm-s390/kdebug.h b/trunk/include/asm-s390/kdebug.h index 1b50f89819a4..40cc68025e01 100644 --- a/trunk/include/asm-s390/kdebug.h +++ b/trunk/include/asm-s390/kdebug.h @@ -26,6 +26,7 @@ extern int register_page_fault_notifier(struct notifier_block *); extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head s390die_chain; + enum die_val { DIE_OOPS = 1, DIE_BPT, @@ -55,6 +56,4 @@ static inline int notify_die(enum die_val val, const char *str, return atomic_notifier_call_chain(&s390die_chain, val, &args); } -extern void die(const char *, struct pt_regs *, long); - #endif diff --git a/trunk/include/asm-s390/lowcore.h b/trunk/include/asm-s390/lowcore.h index 4a31d0a7ee83..74f7389bd3ee 100644 --- a/trunk/include/asm-s390/lowcore.h +++ b/trunk/include/asm-s390/lowcore.h @@ -220,8 +220,7 @@ struct _lowcore __u32 kernel_asce; /* 0xc4c */ __u32 user_asce; /* 0xc50 */ __u32 panic_stack; /* 0xc54 */ - __u32 user_exec_asce; /* 0xc58 */ - __u8 pad10[0xc60-0xc5c]; /* 0xc5c */ + __u8 pad10[0xc60-0xc58]; /* 0xc58 */ /* entry.S sensitive area start */ struct cpuinfo_S390 cpu_data; /* 0xc60 */ __u32 ipl_device; /* 0xc7c */ @@ -311,8 +310,7 @@ struct _lowcore __u64 kernel_asce; /* 0xd58 */ __u64 user_asce; /* 0xd60 */ __u64 panic_stack; /* 0xd68 */ - __u64 user_exec_asce; /* 0xd70 */ - __u8 pad10[0xd80-0xd78]; /* 0xd78 */ + __u8 pad10[0xd80-0xd70]; /* 0xd70 */ /* entry.S sensitive area start */ struct cpuinfo_S390 cpu_data; /* 0xd80 */ __u32 ipl_device; /* 0xdb8 */ diff --git a/trunk/include/asm-s390/mmu_context.h b/trunk/include/asm-s390/mmu_context.h index 1d21da220d49..bcf24a873874 100644 --- a/trunk/include/asm-s390/mmu_context.h +++ b/trunk/include/asm-s390/mmu_context.h @@ -9,7 +9,6 @@ #ifndef __S390_MMU_CONTEXT_H #define __S390_MMU_CONTEXT_H -#include /* * get a new mmu context.. S390 don't know about contexts. */ @@ -17,44 +16,29 @@ #define destroy_context(mm) do { } while (0) -#ifndef __s390x__ -#define LCTL_OPCODE "lctl" -#define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK) -#else -#define LCTL_OPCODE "lctlg" -#define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK) -#endif - static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) + struct task_struct *tsk) { - pgd_t *shadow_pgd = get_shadow_pgd(next->pgd); - - if (prev != next) { - S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) | - PGTABLE_BITS; - if (shadow_pgd) { - /* Load primary/secondary space page table origin. */ - S390_lowcore.user_exec_asce = - (__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS; - asm volatile(LCTL_OPCODE" 1,1,%0\n" - LCTL_OPCODE" 7,7,%1" - : : "m" (S390_lowcore.user_exec_asce), - "m" (S390_lowcore.user_asce) ); - } else if (switch_amode) { - /* Load primary space page table origin. */ - asm volatile(LCTL_OPCODE" 1,1,%0" - : : "m" (S390_lowcore.user_asce) ); - } else - /* Load home space page table origin. */ - asm volatile(LCTL_OPCODE" 13,13,%0" - : : "m" (S390_lowcore.user_asce) ); - } + if (prev != next) { +#ifndef __s390x__ + S390_lowcore.user_asce = (__pa(next->pgd)&PAGE_MASK) | + (_SEGMENT_TABLE|USER_STD_MASK); + /* Load home space page table origin. */ + asm volatile("lctl 13,13,%0" + : : "m" (S390_lowcore.user_asce) ); +#else /* __s390x__ */ + S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) | + (_REGION_TABLE|USER_STD_MASK); + /* Load home space page table origin. */ + asm volatile("lctlg 13,13,%0" + : : "m" (S390_lowcore.user_asce) ); +#endif /* __s390x__ */ + } cpu_set(smp_processor_id(), next->cpu_vm_mask); } @@ -67,4 +51,4 @@ static inline void activate_mm(struct mm_struct *prev, set_fs(current->thread.mm_segment); } -#endif /* __S390_MMU_CONTEXT_H */ +#endif diff --git a/trunk/include/asm-s390/pgalloc.h b/trunk/include/asm-s390/pgalloc.h index 56c8a6c80e2e..0707a7e2fc16 100644 --- a/trunk/include/asm-s390/pgalloc.h +++ b/trunk/include/asm-s390/pgalloc.h @@ -47,17 +47,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) if (!pgd) return NULL; - if (s390_noexec) { - pgd_t *shadow_pgd = (pgd_t *) - __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER); - struct page *page = virt_to_page(pgd); - - if (!shadow_pgd) { - free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); - return NULL; - } - page->lru.next = (void *) shadow_pgd; - } for (i = 0; i < PTRS_PER_PGD; i++) #ifndef __s390x__ pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); @@ -69,10 +58,6 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) static inline void pgd_free(pgd_t *pgd) { - pgd_t *shadow_pgd = get_shadow_pgd(pgd); - - if (shadow_pgd) - free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER); free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); } @@ -86,7 +71,6 @@ static inline void pgd_free(pgd_t *pgd) #define pmd_free(x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0) #define pgd_populate(mm, pmd, pte) BUG() -#define pgd_populate_kernel(mm, pmd, pte) BUG() #else /* __s390x__ */ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) { @@ -95,17 +79,6 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) if (!pmd) return NULL; - if (s390_noexec) { - pmd_t *shadow_pmd = (pmd_t *) - __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER); - struct page *page = virt_to_page(pmd); - - if (!shadow_pmd) { - free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); - return NULL; - } - page->lru.next = (void *) shadow_pmd; - } for (i=0; i < PTRS_PER_PMD; i++) pmd_clear(pmd + i); return pmd; @@ -113,10 +86,6 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) static inline void pmd_free (pmd_t *pmd) { - pmd_t *shadow_pmd = get_shadow_pmd(pmd); - - if (shadow_pmd) - free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER); free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); } @@ -126,20 +95,9 @@ static inline void pmd_free (pmd_t *pmd) pmd_free(pmd); \ } while (0) -static inline void -pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) -{ - pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); -} - static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) { - pgd_t *shadow_pgd = get_shadow_pgd(pgd); - pmd_t *shadow_pmd = get_shadow_pmd(pmd); - - if (shadow_pgd && shadow_pmd) - pgd_populate_kernel(mm, shadow_pgd, shadow_pmd); - pgd_populate_kernel(mm, pgd, pmd); + pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd); } #endif /* __s390x__ */ @@ -161,13 +119,7 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) { - pte_t *pte = (pte_t *)page_to_phys(page); - pmd_t *shadow_pmd = get_shadow_pmd(pmd); - pte_t *shadow_pte = get_shadow_pte(pte); - - pmd_populate_kernel(mm, pmd, pte); - if (shadow_pmd && shadow_pte) - pmd_populate_kernel(mm, shadow_pmd, shadow_pte); + pmd_populate_kernel(mm, pmd, (pte_t *)page_to_phys(page)); } /* @@ -181,17 +133,6 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr) if (!pte) return NULL; - if (s390_noexec) { - pte_t *shadow_pte = (pte_t *) - __get_free_page(GFP_KERNEL|__GFP_REPEAT); - struct page *page = virt_to_page(pte); - - if (!shadow_pte) { - free_page((unsigned long) pte); - return NULL; - } - page->lru.next = (void *) shadow_pte; - } for (i=0; i < PTRS_PER_PTE; i++) { pte_clear(mm, vmaddr, pte + i); vmaddr += PAGE_SIZE; @@ -210,30 +151,14 @@ pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr) static inline void pte_free_kernel(pte_t *pte) { - pte_t *shadow_pte = get_shadow_pte(pte); - - if (shadow_pte) - free_page((unsigned long) shadow_pte); - free_page((unsigned long) pte); + free_page((unsigned long) pte); } static inline void pte_free(struct page *pte) { - struct page *shadow_page = get_shadow_page(pte); - - if (shadow_page) - __free_page(shadow_page); - __free_page(pte); + __free_page(pte); } -#define __pte_free_tlb(tlb, pte) \ -({ \ - struct mmu_gather *__tlb = (tlb); \ - struct page *__pte = (pte); \ - struct page *shadow_page = get_shadow_page(__pte); \ - if (shadow_page) \ - tlb_remove_page(__tlb, shadow_page); \ - tlb_remove_page(__tlb, __pte); \ -}) +#define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte) #endif /* _S390_PGALLOC_H */ diff --git a/trunk/include/asm-s390/pgtable.h b/trunk/include/asm-s390/pgtable.h index 13c16546eff5..ae61aca5d483 100644 --- a/trunk/include/asm-s390/pgtable.h +++ b/trunk/include/asm-s390/pgtable.h @@ -40,7 +40,6 @@ struct mm_struct; extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); extern void paging_init(void); -extern void vmem_map_init(void); /* * The S390 doesn't have any external MMU info: the kernel page @@ -224,8 +223,6 @@ extern unsigned long vmalloc_end; #define _PAGE_TYPE_FILE 0x601 /* bit 0x002 is used for offset !! */ #define _PAGE_TYPE_RO 0x200 #define _PAGE_TYPE_RW 0x000 -#define _PAGE_TYPE_EX_RO 0x202 -#define _PAGE_TYPE_EX_RW 0x002 /* * PTE type bits are rather complicated. handle_pte_fault uses pte_present, @@ -246,13 +243,11 @@ extern unsigned long vmalloc_end; * _PAGE_TYPE_FILE 11?1 -> 11?1 * _PAGE_TYPE_RO 0100 -> 1100 * _PAGE_TYPE_RW 0000 -> 1000 - * _PAGE_TYPE_EX_RO 0110 -> 1110 - * _PAGE_TYPE_EX_RW 0010 -> 1010 * - * pte_none is true for bits combinations 1000, 1010, 1100, 1110 + * pte_none is true for bits combinations 1000, 1100 * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 * pte_file is true for bits combinations 1101, 1111 - * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. + * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid. */ #ifndef __s390x__ @@ -317,100 +312,33 @@ extern unsigned long vmalloc_end; #define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) #define PAGE_RO __pgprot(_PAGE_TYPE_RO) #define PAGE_RW __pgprot(_PAGE_TYPE_RW) -#define PAGE_EX_RO __pgprot(_PAGE_TYPE_EX_RO) -#define PAGE_EX_RW __pgprot(_PAGE_TYPE_EX_RW) #define PAGE_KERNEL PAGE_RW #define PAGE_COPY PAGE_RO /* - * Dependent on the EXEC_PROTECT option s390 can do execute protection. - * Write permission always implies read permission. In theory with a - * primary/secondary page table execute only can be implemented but - * it would cost an additional bit in the pte to distinguish all the - * different pte types. To avoid that execute permission currently - * implies read permission as well. + * The S390 can't do page protection for execute, and considers that the + * same are read. Also, write permissions imply read permissions. This is + * the closest we can get.. */ /*xwr*/ #define __P000 PAGE_NONE #define __P001 PAGE_RO #define __P010 PAGE_RO #define __P011 PAGE_RO -#define __P100 PAGE_EX_RO -#define __P101 PAGE_EX_RO -#define __P110 PAGE_EX_RO -#define __P111 PAGE_EX_RO +#define __P100 PAGE_RO +#define __P101 PAGE_RO +#define __P110 PAGE_RO +#define __P111 PAGE_RO #define __S000 PAGE_NONE #define __S001 PAGE_RO #define __S010 PAGE_RW #define __S011 PAGE_RW -#define __S100 PAGE_EX_RO -#define __S101 PAGE_EX_RO -#define __S110 PAGE_EX_RW -#define __S111 PAGE_EX_RW - -#ifndef __s390x__ -# define PMD_SHADOW_SHIFT 1 -# define PGD_SHADOW_SHIFT 1 -#else /* __s390x__ */ -# define PMD_SHADOW_SHIFT 2 -# define PGD_SHADOW_SHIFT 2 -#endif /* __s390x__ */ - -static inline struct page *get_shadow_page(struct page *page) -{ - if (s390_noexec && !list_empty(&page->lru)) - return virt_to_page(page->lru.next); - return NULL; -} - -static inline pte_t *get_shadow_pte(pte_t *ptep) -{ - unsigned long pteptr = (unsigned long) (ptep); - - if (s390_noexec) { - unsigned long offset = pteptr & (PAGE_SIZE - 1); - void *addr = (void *) (pteptr ^ offset); - struct page *page = virt_to_page(addr); - if (!list_empty(&page->lru)) - return (pte_t *) ((unsigned long) page->lru.next | - offset); - } - return NULL; -} - -static inline pmd_t *get_shadow_pmd(pmd_t *pmdp) -{ - unsigned long pmdptr = (unsigned long) (pmdp); - - if (s390_noexec) { - unsigned long offset = pmdptr & - ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1); - void *addr = (void *) (pmdptr ^ offset); - struct page *page = virt_to_page(addr); - if (!list_empty(&page->lru)) - return (pmd_t *) ((unsigned long) page->lru.next | - offset); - } - return NULL; -} - -static inline pgd_t *get_shadow_pgd(pgd_t *pgdp) -{ - unsigned long pgdptr = (unsigned long) (pgdp); - - if (s390_noexec) { - unsigned long offset = pgdptr & - ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1); - void *addr = (void *) (pgdptr ^ offset); - struct page *page = virt_to_page(addr); - if (!list_empty(&page->lru)) - return (pgd_t *) ((unsigned long) page->lru.next | - offset); - } - return NULL; -} +#define __S100 PAGE_RO +#define __S101 PAGE_RO +#define __S110 PAGE_RW +#define __S111 PAGE_RW /* * Certain architectures need to do special things when PTEs @@ -419,16 +347,7 @@ static inline pgd_t *get_shadow_pgd(pgd_t *pgdp) */ static inline void set_pte(pte_t *pteptr, pte_t pteval) { - pte_t *shadow_pte = get_shadow_pte(pteptr); - *pteptr = pteval; - if (shadow_pte) { - if (!(pte_val(pteval) & _PAGE_INVALID) && - (pte_val(pteval) & _PAGE_SWX)) - pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO; - else - pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; - } } #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) @@ -546,7 +465,7 @@ static inline int pte_read(pte_t pte) static inline void pgd_clear(pgd_t * pgdp) { } -static inline void pmd_clear_kernel(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(pmdp[0]) = _PAGE_TABLE_INV; pmd_val(pmdp[1]) = _PAGE_TABLE_INV; @@ -554,55 +473,24 @@ static inline void pmd_clear_kernel(pmd_t * pmdp) pmd_val(pmdp[3]) = _PAGE_TABLE_INV; } -static inline void pmd_clear(pmd_t * pmdp) -{ - pmd_t *shadow_pmd = get_shadow_pmd(pmdp); - - pmd_clear_kernel(pmdp); - if (shadow_pmd) - pmd_clear_kernel(shadow_pmd); -} - #else /* __s390x__ */ -static inline void pgd_clear_kernel(pgd_t * pgdp) -{ - pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; -} - static inline void pgd_clear(pgd_t * pgdp) { - pgd_t *shadow_pgd = get_shadow_pgd(pgdp); - - pgd_clear_kernel(pgdp); - if (shadow_pgd) - pgd_clear_kernel(shadow_pgd); + pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; } -static inline void pmd_clear_kernel(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; } -static inline void pmd_clear(pmd_t * pmdp) -{ - pmd_t *shadow_pmd = get_shadow_pmd(pmdp); - - pmd_clear_kernel(pmdp); - if (shadow_pmd) - pmd_clear_kernel(shadow_pmd); -} - #endif /* __s390x__ */ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_t *shadow_pte = get_shadow_pte(ptep); - pte_val(*ptep) = _PAGE_TYPE_EMPTY; - if (shadow_pte) - pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY; } /* @@ -720,11 +608,8 @@ ptep_clear_flush(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { pte_t pte = *ptep; - pte_t *shadow_pte = get_shadow_pte(ptep); __ptep_ipte(address, ptep); - if (shadow_pte) - __ptep_ipte(address, shadow_pte); return pte; } diff --git a/trunk/include/asm-s390/processor.h b/trunk/include/asm-s390/processor.h index 4c1b73940351..cbbedc63ba25 100644 --- a/trunk/include/asm-s390/processor.h +++ b/trunk/include/asm-s390/processor.h @@ -50,7 +50,6 @@ struct cpuinfo_S390 unsigned long pgtable_cache_sz; }; -extern void s390_adjust_jiffies(void); extern void print_cpu_info(struct cpuinfo_S390 *); /* Lazy FPU handling on uni-processor */ @@ -145,8 +144,7 @@ struct stack_frame { #ifndef __s390x__ #define start_thread(regs, new_psw, new_stackp) do { \ - set_fs(USER_DS); \ - regs->psw.mask = psw_user_bits; \ + regs->psw.mask = PSW_USER_BITS; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ regs->gprs[15] = new_stackp ; \ } while (0) @@ -154,15 +152,13 @@ struct stack_frame { #else /* __s390x__ */ #define start_thread(regs, new_psw, new_stackp) do { \ - set_fs(USER_DS); \ - regs->psw.mask = psw_user_bits; \ + regs->psw.mask = PSW_USER_BITS; \ regs->psw.addr = new_psw; \ regs->gprs[15] = new_stackp; \ } while (0) #define start_thread31(regs, new_psw, new_stackp) do { \ - set_fs(USER_DS); \ - regs->psw.mask = psw_user32_bits; \ + regs->psw.mask = PSW_USER32_BITS; \ regs->psw.addr = new_psw; \ regs->gprs[15] = new_stackp; \ } while (0) @@ -205,8 +201,9 @@ unsigned long get_wchan(struct task_struct *p); static inline void cpu_relax(void) { if (MACHINE_HAS_DIAG44) - asm volatile("diag 0,0,68"); - barrier(); + asm volatile("diag 0,0,68" : : : "memory"); + else + barrier(); } /* @@ -330,18 +327,6 @@ static inline void disabled_wait(unsigned long code) #endif /* __s390x__ */ } -/* - * Basic Machine Check/Program Check Handler. - */ - -extern void s390_base_mcck_handler(void); -extern void s390_base_pgm_handler(void); -extern void s390_base_ext_handler(void); - -extern void (*s390_base_mcck_handler_fn)(void); -extern void (*s390_base_pgm_handler_fn)(void); -extern void (*s390_base_ext_handler_fn)(void); - /* * CPU idle notifier chain. */ diff --git a/trunk/include/asm-s390/ptrace.h b/trunk/include/asm-s390/ptrace.h index fa6ca87080e8..7b768c5c68a8 100644 --- a/trunk/include/asm-s390/ptrace.h +++ b/trunk/include/asm-s390/ptrace.h @@ -266,12 +266,17 @@ typedef struct #define PSW_ASC_SECONDARY 0x0000800000000000UL #define PSW_ASC_HOME 0x0000C00000000000UL -extern long psw_user32_bits; +#define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ + PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ + PSW_MASK_PSTATE | PSW_DEFAULT_KEY) #endif /* __s390x__ */ -extern long psw_kernel_bits; -extern long psw_user_bits; +#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ + PSW_MASK_MCHECK | PSW_DEFAULT_KEY) +#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ + PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ + PSW_MASK_PSTATE | PSW_DEFAULT_KEY) /* This macro merges a NEW PSW mask specified by the user into the currently active PSW mask CURRENT, modifying only those diff --git a/trunk/include/asm-s390/reset.h b/trunk/include/asm-s390/reset.h index f584f4a52581..532e65a2aafc 100644 --- a/trunk/include/asm-s390/reset.h +++ b/trunk/include/asm-s390/reset.h @@ -18,4 +18,7 @@ struct reset_call { extern void register_reset_call(struct reset_call *reset); extern void unregister_reset_call(struct reset_call *reset); extern void s390_reset_system(void); +extern void (*s390_reset_mcck_handler)(void); +extern void (*s390_reset_pgm_handler)(void); + #endif /* _ASM_S390_RESET_H */ diff --git a/trunk/include/asm-s390/sclp.h b/trunk/include/asm-s390/sclp.h deleted file mode 100644 index 468b97018405..000000000000 --- a/trunk/include/asm-s390/sclp.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * include/asm-s390/sclp.h - * - * Copyright IBM Corp. 2007 - * Author(s): Heiko Carstens - */ - -#ifndef _ASM_S390_SCLP_H -#define _ASM_S390_SCLP_H - -#include - -struct sccb_header { - u16 length; - u8 function_code; - u8 control_mask[3]; - u16 response_code; -} __attribute__((packed)); - -#define LOADPARM_LEN 8 - -struct sclp_readinfo_sccb { - struct sccb_header header; /* 0-7 */ - u16 rnmax; /* 8-9 */ - u8 rnsize; /* 10 */ - u8 _reserved0[24 - 11]; /* 11-23 */ - u8 loadparm[LOADPARM_LEN]; /* 24-31 */ - u8 _reserved1[91 - 32]; /* 32-90 */ - u8 flags; /* 91 */ - u8 _reserved2[100 - 92]; /* 92-99 */ - u32 rnsize2; /* 100-103 */ - u64 rnmax2; /* 104-111 */ - u8 _reserved3[4096 - 112]; /* 112-4095 */ -} __attribute__((packed, aligned(4096))); - -extern struct sclp_readinfo_sccb s390_readinfo_sccb; -extern void sclp_readinfo_early(void); - -#endif /* _ASM_S390_SCLP_H */ diff --git a/trunk/include/asm-s390/sections.h b/trunk/include/asm-s390/sections.h index 1c5a2c4ccdad..3a0b8ffeab7a 100644 --- a/trunk/include/asm-s390/sections.h +++ b/trunk/include/asm-s390/sections.h @@ -3,6 +3,4 @@ #include -extern char _eshared[]; - #endif diff --git a/trunk/include/asm-s390/setup.h b/trunk/include/asm-s390/setup.h index 3388bb52597c..9574fe80a046 100644 --- a/trunk/include/asm-s390/setup.h +++ b/trunk/include/asm-s390/setup.h @@ -42,18 +42,6 @@ struct mem_chunk { extern struct mem_chunk memory_chunk[]; -#ifdef CONFIG_S390_SWITCH_AMODE -extern unsigned int switch_amode; -#else -#define switch_amode (0) -#endif - -#ifdef CONFIG_S390_EXEC_PROTECT -extern unsigned int s390_noexec; -#else -#define s390_noexec (0) -#endif - /* * Machine features detected in head.S */ @@ -86,9 +74,6 @@ extern unsigned int console_mode; extern unsigned int console_devno; extern unsigned int console_irq; -extern char vmhalt_cmd[]; -extern char vmpoff_cmd[]; - #define CONSOLE_IS_UNDEFINED (console_mode == 0) #define CONSOLE_IS_SCLP (console_mode == 1) #define CONSOLE_IS_3215 (console_mode == 2) @@ -156,19 +141,13 @@ struct ipl_parameter_block { extern u32 ipl_flags; extern u16 ipl_devno; -extern void do_reipl(void); -extern void ipl_save_parameters(void); +void do_reipl(void); enum { IPL_DEVNO_VALID = 1, IPL_PARMBLOCK_VALID = 2, - IPL_NSS_VALID = 4, }; -#define NSS_NAME_SIZE 8 - -extern char kernel_nss_name[]; - #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ IPL_PARMBLOCK_ORIGIN) #define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.len) diff --git a/trunk/include/asm-s390/smp.h b/trunk/include/asm-s390/smp.h index b957e4cda464..7097c96ed026 100644 --- a/trunk/include/asm-s390/smp.h +++ b/trunk/include/asm-s390/smp.h @@ -31,10 +31,6 @@ typedef struct __u16 cpu; } sigp_info; -extern void machine_restart_smp(char *); -extern void machine_halt_smp(void); -extern void machine_power_off_smp(void); - extern void smp_setup_cpu_possible_map(void); extern int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic, int wait, int cpu); @@ -110,7 +106,7 @@ smp_call_function_on(void (*func) (void *info), void *info, static inline void smp_send_stop(void) { /* Disable all interrupts/machine checks */ - __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); + __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK); } #define smp_cpu_not_running(cpu) 1 diff --git a/trunk/include/asm-s390/system.h b/trunk/include/asm-s390/system.h index bbe137c3ed69..bd0b05ae87d2 100644 --- a/trunk/include/asm-s390/system.h +++ b/trunk/include/asm-s390/system.h @@ -373,8 +373,8 @@ __set_psw_mask(unsigned long mask) __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8))); } -#define local_mcck_enable() __set_psw_mask(psw_kernel_bits) -#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK) +#define local_mcck_enable() __set_psw_mask(PSW_KERNEL_BITS) +#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK) #ifdef CONFIG_SMP diff --git a/trunk/include/asm-s390/tape390.h b/trunk/include/asm-s390/tape390.h index 884fba48f1ff..f1d66ba0deef 100644 --- a/trunk/include/asm-s390/tape390.h +++ b/trunk/include/asm-s390/tape390.h @@ -1,11 +1,11 @@ /************************************************************************* * * tape390.h - * enables user programs to display messages and control encryption - * on s390 tape devices + * enables user programs to display messages on the tape device * - * Copyright IBM Corp. 2001,2006 - * Author(s): Michael Holzheu + * S390 and zSeries version + * Copyright (C) 2001 IBM Corporation + * Author(s): Despina Papadopoulou * *************************************************************************/ @@ -36,68 +36,4 @@ typedef struct display_struct { char message2[8]; } display_struct; -/* - * Tape encryption support - */ - -struct tape390_crypt_info { - char capability; - char status; - char medium_status; -} __attribute__ ((packed)); - - -/* Macros for "capable" field */ -#define TAPE390_CRYPT_SUPPORTED_MASK 0x01 -#define TAPE390_CRYPT_SUPPORTED(x) \ - ((x.capability & TAPE390_CRYPT_SUPPORTED_MASK)) - -/* Macros for "status" field */ -#define TAPE390_CRYPT_ON_MASK 0x01 -#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK)) - -/* Macros for "medium status" field */ -#define TAPE390_MEDIUM_LOADED_MASK 0x01 -#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02 -#define TAPE390_MEDIUM_ENCRYPTED(x) \ - (((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK)) -#define TAPE390_MEDIUM_LOADED(x) \ - (((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK)) - -/* - * The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption. - * The "encryption_capable" and "tape_status" fields are ignored for this ioctl! - */ -#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info) - -/* - * The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state. - */ -#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info) - -/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */ -#define TAPE390_KEKL_TYPE_NONE 0 -#define TAPE390_KEKL_TYPE_LABEL 1 -#define TAPE390_KEKL_TYPE_HASH 2 - -struct tape390_kekl { - unsigned char type; - unsigned char type_on_tape; - char label[65]; -} __attribute__ ((packed)); - -struct tape390_kekl_pair { - struct tape390_kekl kekl[2]; -} __attribute__ ((packed)); - -/* - * The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels. - */ -#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair) - -/* - * The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels. - */ -#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair) - #endif diff --git a/trunk/include/asm-s390/timer.h b/trunk/include/asm-s390/timer.h index adb34860a543..30e5cbe570f2 100644 --- a/trunk/include/asm-s390/timer.h +++ b/trunk/include/asm-s390/timer.h @@ -45,9 +45,6 @@ extern void add_virt_timer_periodic(void *new); extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); extern int del_virt_timer(struct vtimer_list *timer); -extern void init_cpu_vtimer(void); -extern void vtime_init(void); - #endif /* __KERNEL__ */ #endif /* _ASM_S390_TIMER_H */ diff --git a/trunk/include/asm-s390/timex.h b/trunk/include/asm-s390/timex.h index 98229db24314..4df4a41029a3 100644 --- a/trunk/include/asm-s390/timex.h +++ b/trunk/include/asm-s390/timex.h @@ -11,41 +11,6 @@ #ifndef _ASM_S390_TIMEX_H #define _ASM_S390_TIMEX_H -/* Inline functions for clock register access. */ -static inline int set_clock(__u64 time) -{ - int cc; - - asm volatile( - " sck 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc) : "m" (time), "a" (&time) : "cc"); - return cc; -} - -static inline int store_clock(__u64 *time) -{ - int cc; - - asm volatile( - " stck 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc), "=m" (*time) : "a" (time) : "cc"); - return cc; -} - -static inline void set_clock_comparator(__u64 time) -{ - asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time)); -} - -static inline void store_clock_comparator(__u64 *time) -{ - asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time)); -} - #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ typedef unsigned long long cycles_t; @@ -62,24 +27,9 @@ static inline unsigned long long get_clock (void) return clk; } -static inline void get_clock_extended(void *dest) -{ - typedef struct { unsigned long long clk[2]; } __clock_t; - -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) - asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc"); -#else /* __GNUC__ */ - asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest)) - : "a" ((__clock_t *)dest) : "cc"); -#endif /* __GNUC__ */ -} - static inline cycles_t get_cycles(void) { return (cycles_t) get_clock() >> 2; } -int get_sync_clock(unsigned long long *clock); -void init_cpu_timer(void); - #endif diff --git a/trunk/include/asm-s390/tlbflush.h b/trunk/include/asm-s390/tlbflush.h index 66793f55c8b2..fa4dc916a9bf 100644 --- a/trunk/include/asm-s390/tlbflush.h +++ b/trunk/include/asm-s390/tlbflush.h @@ -3,7 +3,6 @@ #include #include -#include /* * TLB flushing: @@ -103,14 +102,6 @@ static inline void __flush_tlb_mm(struct mm_struct * mm) if (unlikely(cpus_empty(mm->cpu_vm_mask))) return; if (MACHINE_HAS_IDTE) { - pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd); - - if (shadow_pgd) { - asm volatile( - " .insn rrf,0xb98e0000,0,%0,%1,0" - : : "a" (2048), - "a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" ); - } asm volatile( " .insn rrf,0xb98e0000,0,%0,%1,0" : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc"); diff --git a/trunk/include/asm-s390/uaccess.h b/trunk/include/asm-s390/uaccess.h index 0235970278f0..73ac4e82217b 100644 --- a/trunk/include/asm-s390/uaccess.h +++ b/trunk/include/asm-s390/uaccess.h @@ -90,8 +90,6 @@ struct uaccess_ops { extern struct uaccess_ops uaccess; extern struct uaccess_ops uaccess_std; extern struct uaccess_ops uaccess_mvcos; -extern struct uaccess_ops uaccess_mvcos_switch; -extern struct uaccess_ops uaccess_pt; static inline int __put_user_fn(size_t size, void __user *ptr, void *x) { diff --git a/trunk/include/asm-x86_64/acpi.h b/trunk/include/asm-x86_64/acpi.h index a29f05087a31..6b6fc6f8be7e 100644 --- a/trunk/include/asm-x86_64/acpi.h +++ b/trunk/include/asm-x86_64/acpi.h @@ -37,7 +37,7 @@ * Calling conventions: * * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) - * ACPI_EXTERNAL_XFACE - External ACPI interfaces + * ACPI_EXTERNAL_XFACE - External ACPI interfaces * ACPI_INTERNAL_XFACE - Internal ACPI interfaces * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces */ @@ -57,11 +57,11 @@ int __acpi_acquire_global_lock(unsigned int *lock); int __acpi_release_global_lock(unsigned int *lock); -#define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = __acpi_acquire_global_lock(&facs->global_lock)) +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = __acpi_acquire_global_lock((unsigned int *) GLptr)) -#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \ - ((Acq) = __acpi_release_global_lock(&facs->global_lock)) +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = __acpi_release_global_lock((unsigned int *) GLptr)) /* * Math helper asm macros @@ -87,10 +87,10 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_pci_disabled; extern int acpi_ht; -static inline void disable_acpi(void) -{ - acpi_disabled = 1; - acpi_ht = 0; +static inline void disable_acpi(void) +{ + acpi_disabled = 1; + acpi_ht = 0; acpi_pci_disabled = 1; acpi_noirq = 1; } @@ -100,9 +100,9 @@ static inline void disable_acpi(void) extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); static inline void acpi_noirq_set(void) { acpi_noirq = 1; } -static inline void acpi_disable_pci(void) +static inline void acpi_disable_pci(void) { - acpi_pci_disabled = 1; + acpi_pci_disabled = 1; acpi_noirq_set(); } extern int acpi_irq_balance_set(char *str); @@ -136,6 +136,8 @@ extern void acpi_reserve_bootmem(void); extern int acpi_disabled; extern int acpi_pci_disabled; +extern u8 x86_acpiid_to_apicid[]; + #define ARCH_HAS_POWER_INIT 1 extern int acpi_skip_timer_override; diff --git a/trunk/include/asm-x86_64/swiotlb.h b/trunk/include/asm-x86_64/swiotlb.h index ab913ffcad56..ba94ab3d2673 100644 --- a/trunk/include/asm-x86_64/swiotlb.h +++ b/trunk/include/asm-x86_64/swiotlb.h @@ -1,5 +1,6 @@ #ifndef _ASM_SWIOTLB_H -#define _ASM_SWIOTLB_H 1 +#define _ASM_SWTIOLB_H 1 + #include @@ -44,7 +45,6 @@ extern void swiotlb_init(void); extern int swiotlb_force; #ifdef CONFIG_SWIOTLB -#define SWIOTLB_ARCH_NEED_ALLOC extern int swiotlb; #else #define swiotlb 0 @@ -52,6 +52,4 @@ extern int swiotlb; extern void pci_swiotlb_init(void); -static inline void dma_mark_clean(void *addr, size_t size) {} - -#endif /* _ASM_SWIOTLB_H */ +#endif /* _ASM_SWTIOLB_H */ diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 815f1fb4ce21..91f1f2363870 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -53,6 +53,166 @@ enum acpi_irq_model_id { extern enum acpi_irq_model_id acpi_irq_model; + +/* Root System Description Pointer (RSDP) */ + +struct acpi_table_rsdp { + char signature[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_address; +} __attribute__ ((packed)); + +struct acpi20_table_rsdp { + char signature[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_address; + u32 length; + u64 xsdt_address; + u8 ext_checksum; + u8 reserved[3]; +} __attribute__ ((packed)); + +typedef struct { + u8 type; + u8 length; +} __attribute__ ((packed)) acpi_table_entry_header; + +/* Root System Description Table (RSDT) */ + +struct acpi_table_rsdt { + struct acpi_table_header header; + u32 entry[8]; +} __attribute__ ((packed)); + +/* Extended System Description Table (XSDT) */ + +struct acpi_table_xsdt { + struct acpi_table_header header; + u64 entry[1]; +} __attribute__ ((packed)); + +/* Fixed ACPI Description Table (FADT) */ + +struct acpi_table_fadt { + struct acpi_table_header header; + u32 facs_addr; + u32 dsdt_addr; + /* ... */ +} __attribute__ ((packed)); + +/* Multiple APIC Description Table (MADT) */ + +struct acpi_table_madt { + struct acpi_table_header header; + u32 lapic_address; + struct { + u32 pcat_compat:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +enum acpi_madt_entry_id { + ACPI_MADT_LAPIC = 0, + ACPI_MADT_IOAPIC, + ACPI_MADT_INT_SRC_OVR, + ACPI_MADT_NMI_SRC, + ACPI_MADT_LAPIC_NMI, + ACPI_MADT_LAPIC_ADDR_OVR, + ACPI_MADT_IOSAPIC, + ACPI_MADT_LSAPIC, + ACPI_MADT_PLAT_INT_SRC, + ACPI_MADT_ENTRY_COUNT +}; + +typedef struct { + u16 polarity:2; + u16 trigger:2; + u16 reserved:12; +} __attribute__ ((packed)) acpi_interrupt_flags; + +struct acpi_table_lapic { + acpi_table_entry_header header; + u8 acpi_id; + u8 id; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +struct acpi_table_ioapic { + acpi_table_entry_header header; + u8 id; + u8 reserved; + u32 address; + u32 global_irq_base; +} __attribute__ ((packed)); + +struct acpi_table_int_src_ovr { + acpi_table_entry_header header; + u8 bus; + u8 bus_irq; + u32 global_irq; + acpi_interrupt_flags flags; +} __attribute__ ((packed)); + +struct acpi_table_nmi_src { + acpi_table_entry_header header; + acpi_interrupt_flags flags; + u32 global_irq; +} __attribute__ ((packed)); + +struct acpi_table_lapic_nmi { + acpi_table_entry_header header; + u8 acpi_id; + acpi_interrupt_flags flags; + u8 lint; +} __attribute__ ((packed)); + +struct acpi_table_lapic_addr_ovr { + acpi_table_entry_header header; + u8 reserved[2]; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_iosapic { + acpi_table_entry_header header; + u8 id; + u8 reserved; + u32 global_irq_base; + u64 address; +} __attribute__ ((packed)); + +struct acpi_table_lsapic { + acpi_table_entry_header header; + u8 acpi_id; + u8 id; + u8 eid; + u8 reserved[3]; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; +} __attribute__ ((packed)); + +struct acpi_table_plat_int_src { + acpi_table_entry_header header; + acpi_interrupt_flags flags; + u8 type; /* See acpi_interrupt_type */ + u8 id; + u8 eid; + u8 iosapic_vector; + u32 global_irq; + struct { + u32 cpei_override_flag:1; + u32 reserved:31; + } plint_flags; +} __attribute__ ((packed)); + enum acpi_interrupt_id { ACPI_INTERRUPT_PMI = 1, ACPI_INTERRUPT_INIT, @@ -62,6 +222,89 @@ enum acpi_interrupt_id { #define ACPI_SPACE_MEM 0 +struct acpi_gen_regaddr { + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 resv; + u32 addrl; + u32 addrh; +} __attribute__ ((packed)); + +struct acpi_table_hpet { + struct acpi_table_header header; + u32 id; + struct acpi_gen_regaddr addr; + u8 number; + u16 min_tick; + u8 page_protect; +} __attribute__ ((packed)); + +/* + * Simple Boot Flags + * http://www.microsoft.com/whdc/hwdev/resources/specs/simp_bios.mspx + */ +struct acpi_table_sbf +{ + u8 sbf_signature[4]; + u32 sbf_len; + u8 sbf_revision; + u8 sbf_csum; + u8 sbf_oemid[6]; + u8 sbf_oemtable[8]; + u8 sbf_revdata[4]; + u8 sbf_creator[4]; + u8 sbf_crearev[4]; + u8 sbf_cmos; + u8 sbf_spare[3]; +} __attribute__ ((packed)); + +/* + * System Resource Affinity Table (SRAT) + * http://www.microsoft.com/whdc/hwdev/platform/proc/SRAT.mspx + */ + +struct acpi_table_srat { + struct acpi_table_header header; + u32 table_revision; + u64 reserved; +} __attribute__ ((packed)); + +enum acpi_srat_entry_id { + ACPI_SRAT_PROCESSOR_AFFINITY = 0, + ACPI_SRAT_MEMORY_AFFINITY, + ACPI_SRAT_ENTRY_COUNT +}; + +struct acpi_table_processor_affinity { + acpi_table_entry_header header; + u8 proximity_domain; + u8 apic_id; + struct { + u32 enabled:1; + u32 reserved:31; + } flags; + u8 lsapic_eid; + u8 reserved[7]; +} __attribute__ ((packed)); + +struct acpi_table_memory_affinity { + acpi_table_entry_header header; + u8 proximity_domain; + u8 reserved1[5]; + u32 base_addr_lo; + u32 base_addr_hi; + u32 length_lo; + u32 length_hi; + u32 memory_type; /* See acpi_address_range_id */ + struct { + u32 enabled:1; + u32 hot_pluggable:1; + u32 reserved:30; + } flags; + u64 reserved2; +} __attribute__ ((packed)); + enum acpi_address_range_id { ACPI_ADDRESS_RANGE_MEMORY = 1, ACPI_ADDRESS_RANGE_RESERVED = 2, @@ -70,12 +313,84 @@ enum acpi_address_range_id { ACPI_ADDRESS_RANGE_COUNT }; +/* + * System Locality Information Table (SLIT) + * see http://devresource.hp.com/devresource/docs/techpapers/ia64/slit.pdf + */ + +struct acpi_table_slit { + struct acpi_table_header header; + u64 localities; + u8 entry[1]; /* real size = localities^2 */ +} __attribute__ ((packed)); + +/* Smart Battery Description Table (SBST) */ + +struct acpi_table_sbst { + struct acpi_table_header header; + u32 warning; /* Warn user */ + u32 low; /* Critical sleep */ + u32 critical; /* Critical shutdown */ +} __attribute__ ((packed)); + +/* Embedded Controller Boot Resources Table (ECDT) */ + +struct acpi_table_ecdt { + struct acpi_table_header header; + struct acpi_generic_address ec_control; + struct acpi_generic_address ec_data; + u32 uid; + u8 gpe_bit; + char ec_id[0]; +} __attribute__ ((packed)); + +/* PCI MMCONFIG */ + +/* Defined in PCI Firmware Specification 3.0 */ +struct acpi_table_mcfg_config { + u32 base_address; + u32 base_reserved; + u16 pci_segment_group_number; + u8 start_bus_number; + u8 end_bus_number; + u8 reserved[4]; +} __attribute__ ((packed)); +struct acpi_table_mcfg { + struct acpi_table_header header; + u8 reserved[8]; + struct acpi_table_mcfg_config config[0]; +} __attribute__ ((packed)); /* Table Handlers */ -typedef int (*acpi_table_handler) (struct acpi_table_header *table); +enum acpi_table_id { + ACPI_TABLE_UNKNOWN = 0, + ACPI_APIC, + ACPI_BOOT, + ACPI_DBGP, + ACPI_DSDT, + ACPI_ECDT, + ACPI_ETDT, + ACPI_FADT, + ACPI_FACS, + ACPI_OEMX, + ACPI_PSDT, + ACPI_SBST, + ACPI_SLIT, + ACPI_SPCR, + ACPI_SRAT, + ACPI_SSDT, + ACPI_SPMI, + ACPI_HPET, + ACPI_MCFG, + ACPI_TABLE_COUNT +}; + +typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long size); + +extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT]; -typedef int (*acpi_madt_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); +typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); unsigned long acpi_find_rsdp (void); @@ -84,12 +399,14 @@ int acpi_boot_table_init (void); int acpi_numa_init (void); int acpi_table_init (void); -int acpi_table_parse (char *id, acpi_table_handler handler); -int acpi_table_parse_madt (enum acpi_madt_type id, acpi_madt_entry_handler handler, unsigned int max_entries); -int acpi_table_parse_srat (enum acpi_srat_type id, acpi_madt_entry_handler handler, unsigned int max_entries); -int acpi_parse_mcfg (struct acpi_table_header *header); -void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); -void acpi_table_print_srat_entry (struct acpi_subtable_header *srat); +int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler); +int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); +int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_parse_mcfg (unsigned long phys_addr, unsigned long size); +void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr); +void acpi_table_print_madt_entry (acpi_table_entry_header *madt); +void acpi_table_print_srat_entry (acpi_table_entry_header *srat); /* the following four functions are architecture-dependent */ #ifdef CONFIG_HAVE_ARCH_PARSE_SRAT @@ -100,8 +417,8 @@ void acpi_table_print_srat_entry (struct acpi_subtable_header *srat); #define acpi_numa_arch_fixup() do {} while (0) #else void acpi_numa_slit_init (struct acpi_table_slit *slit); -void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); -void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); +void acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa); +void acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma); void acpi_numa_arch_fixup(void); #endif @@ -116,7 +433,7 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base); extern int acpi_mp_config; -extern struct acpi_mcfg_allocation *pci_mmcfg_config; +extern struct acpi_table_mcfg_config *pci_mmcfg_config; extern int pci_mmcfg_config_num; extern int sbf_port; diff --git a/trunk/include/linux/hid-debug.h b/trunk/include/linux/hid-debug.h index 50d568ec178a..8e4dbb51fc70 100644 --- a/trunk/include/linux/hid-debug.h +++ b/trunk/include/linux/hid-debug.h @@ -1,8 +1,10 @@ -#ifndef __HID_DEBUG_H -#define __HID_DEBUG_H - /* - * Copyright (c) 2007 Jiri Kosina + * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $ + * + * (c) 1999 Andreas Gal + * (c) 2000-2001 Vojtech Pavlik + * + * Some debug stuff for the HID parser. */ /* @@ -20,26 +22,737 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * Should you need to contact me, the author, you can do so either by + * e-mail - mail your message to , or by paper mail: + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#ifdef CONFIG_HID_DEBUG +#include + +struct hid_usage_entry { + unsigned page; + unsigned usage; + char *description; +}; + +static const struct hid_usage_entry hid_usage_table[] = { + { 0, 0, "Undefined" }, + { 1, 0, "GenericDesktop" }, + {0, 0x01, "Pointer"}, + {0, 0x02, "Mouse"}, + {0, 0x04, "Joystick"}, + {0, 0x05, "GamePad"}, + {0, 0x06, "Keyboard"}, + {0, 0x07, "Keypad"}, + {0, 0x08, "MultiAxis"}, + {0, 0x30, "X"}, + {0, 0x31, "Y"}, + {0, 0x32, "Z"}, + {0, 0x33, "Rx"}, + {0, 0x34, "Ry"}, + {0, 0x35, "Rz"}, + {0, 0x36, "Slider"}, + {0, 0x37, "Dial"}, + {0, 0x38, "Wheel"}, + {0, 0x39, "HatSwitch"}, + {0, 0x3a, "CountedBuffer"}, + {0, 0x3b, "ByteCount"}, + {0, 0x3c, "MotionWakeup"}, + {0, 0x3d, "Start"}, + {0, 0x3e, "Select"}, + {0, 0x40, "Vx"}, + {0, 0x41, "Vy"}, + {0, 0x42, "Vz"}, + {0, 0x43, "Vbrx"}, + {0, 0x44, "Vbry"}, + {0, 0x45, "Vbrz"}, + {0, 0x46, "Vno"}, + {0, 0x80, "SystemControl"}, + {0, 0x81, "SystemPowerDown"}, + {0, 0x82, "SystemSleep"}, + {0, 0x83, "SystemWakeUp"}, + {0, 0x84, "SystemContextMenu"}, + {0, 0x85, "SystemMainMenu"}, + {0, 0x86, "SystemAppMenu"}, + {0, 0x87, "SystemMenuHelp"}, + {0, 0x88, "SystemMenuExit"}, + {0, 0x89, "SystemMenuSelect"}, + {0, 0x8a, "SystemMenuRight"}, + {0, 0x8b, "SystemMenuLeft"}, + {0, 0x8c, "SystemMenuUp"}, + {0, 0x8d, "SystemMenuDown"}, + {0, 0x90, "D-PadUp"}, + {0, 0x91, "D-PadDown"}, + {0, 0x92, "D-PadRight"}, + {0, 0x93, "D-PadLeft"}, + { 2, 0, "Simulation" }, + {0, 0xb0, "Aileron"}, + {0, 0xb1, "AileronTrim"}, + {0, 0xb2, "Anti-Torque"}, + {0, 0xb3, "Autopilot"}, + {0, 0xb4, "Chaff"}, + {0, 0xb5, "Collective"}, + {0, 0xb6, "DiveBrake"}, + {0, 0xb7, "ElectronicCountermeasures"}, + {0, 0xb8, "Elevator"}, + {0, 0xb9, "ElevatorTrim"}, + {0, 0xba, "Rudder"}, + {0, 0xbb, "Throttle"}, + {0, 0xbc, "FlightCommunications"}, + {0, 0xbd, "FlareRelease"}, + {0, 0xbe, "LandingGear"}, + {0, 0xbf, "ToeBrake"}, + { 7, 0, "Keyboard" }, + { 8, 0, "LED" }, + {0, 0x01, "NumLock"}, + {0, 0x02, "CapsLock"}, + {0, 0x03, "ScrollLock"}, + {0, 0x04, "Compose"}, + {0, 0x05, "Kana"}, + {0, 0x4b, "GenericIndicator"}, + { 9, 0, "Button" }, + { 10, 0, "Ordinal" }, + { 12, 0, "Consumer" }, + {0, 0x238, "HorizontalWheel"}, + { 13, 0, "Digitizers" }, + {0, 0x01, "Digitizer"}, + {0, 0x02, "Pen"}, + {0, 0x03, "LightPen"}, + {0, 0x04, "TouchScreen"}, + {0, 0x05, "TouchPad"}, + {0, 0x20, "Stylus"}, + {0, 0x21, "Puck"}, + {0, 0x22, "Finger"}, + {0, 0x30, "TipPressure"}, + {0, 0x31, "BarrelPressure"}, + {0, 0x32, "InRange"}, + {0, 0x33, "Touch"}, + {0, 0x34, "UnTouch"}, + {0, 0x35, "Tap"}, + {0, 0x39, "TabletFunctionKey"}, + {0, 0x3a, "ProgramChangeKey"}, + {0, 0x3c, "Invert"}, + {0, 0x42, "TipSwitch"}, + {0, 0x43, "SecondaryTipSwitch"}, + {0, 0x44, "BarrelSwitch"}, + {0, 0x45, "Eraser"}, + {0, 0x46, "TabletPick"}, + { 15, 0, "PhysicalInterfaceDevice" }, + {0, 0x00, "Undefined"}, + {0, 0x01, "Physical_Interface_Device"}, + {0, 0x20, "Normal"}, + {0, 0x21, "Set_Effect_Report"}, + {0, 0x22, "Effect_Block_Index"}, + {0, 0x23, "Parameter_Block_Offset"}, + {0, 0x24, "ROM_Flag"}, + {0, 0x25, "Effect_Type"}, + {0, 0x26, "ET_Constant_Force"}, + {0, 0x27, "ET_Ramp"}, + {0, 0x28, "ET_Custom_Force_Data"}, + {0, 0x30, "ET_Square"}, + {0, 0x31, "ET_Sine"}, + {0, 0x32, "ET_Triangle"}, + {0, 0x33, "ET_Sawtooth_Up"}, + {0, 0x34, "ET_Sawtooth_Down"}, + {0, 0x40, "ET_Spring"}, + {0, 0x41, "ET_Damper"}, + {0, 0x42, "ET_Inertia"}, + {0, 0x43, "ET_Friction"}, + {0, 0x50, "Duration"}, + {0, 0x51, "Sample_Period"}, + {0, 0x52, "Gain"}, + {0, 0x53, "Trigger_Button"}, + {0, 0x54, "Trigger_Repeat_Interval"}, + {0, 0x55, "Axes_Enable"}, + {0, 0x56, "Direction_Enable"}, + {0, 0x57, "Direction"}, + {0, 0x58, "Type_Specific_Block_Offset"}, + {0, 0x59, "Block_Type"}, + {0, 0x5A, "Set_Envelope_Report"}, + {0, 0x5B, "Attack_Level"}, + {0, 0x5C, "Attack_Time"}, + {0, 0x5D, "Fade_Level"}, + {0, 0x5E, "Fade_Time"}, + {0, 0x5F, "Set_Condition_Report"}, + {0, 0x60, "CP_Offset"}, + {0, 0x61, "Positive_Coefficient"}, + {0, 0x62, "Negative_Coefficient"}, + {0, 0x63, "Positive_Saturation"}, + {0, 0x64, "Negative_Saturation"}, + {0, 0x65, "Dead_Band"}, + {0, 0x66, "Download_Force_Sample"}, + {0, 0x67, "Isoch_Custom_Force_Enable"}, + {0, 0x68, "Custom_Force_Data_Report"}, + {0, 0x69, "Custom_Force_Data"}, + {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, + {0, 0x6B, "Set_Custom_Force_Report"}, + {0, 0x6C, "Custom_Force_Data_Offset"}, + {0, 0x6D, "Sample_Count"}, + {0, 0x6E, "Set_Periodic_Report"}, + {0, 0x6F, "Offset"}, + {0, 0x70, "Magnitude"}, + {0, 0x71, "Phase"}, + {0, 0x72, "Period"}, + {0, 0x73, "Set_Constant_Force_Report"}, + {0, 0x74, "Set_Ramp_Force_Report"}, + {0, 0x75, "Ramp_Start"}, + {0, 0x76, "Ramp_End"}, + {0, 0x77, "Effect_Operation_Report"}, + {0, 0x78, "Effect_Operation"}, + {0, 0x79, "Op_Effect_Start"}, + {0, 0x7A, "Op_Effect_Start_Solo"}, + {0, 0x7B, "Op_Effect_Stop"}, + {0, 0x7C, "Loop_Count"}, + {0, 0x7D, "Device_Gain_Report"}, + {0, 0x7E, "Device_Gain"}, + {0, 0x7F, "PID_Pool_Report"}, + {0, 0x80, "RAM_Pool_Size"}, + {0, 0x81, "ROM_Pool_Size"}, + {0, 0x82, "ROM_Effect_Block_Count"}, + {0, 0x83, "Simultaneous_Effects_Max"}, + {0, 0x84, "Pool_Alignment"}, + {0, 0x85, "PID_Pool_Move_Report"}, + {0, 0x86, "Move_Source"}, + {0, 0x87, "Move_Destination"}, + {0, 0x88, "Move_Length"}, + {0, 0x89, "PID_Block_Load_Report"}, + {0, 0x8B, "Block_Load_Status"}, + {0, 0x8C, "Block_Load_Success"}, + {0, 0x8D, "Block_Load_Full"}, + {0, 0x8E, "Block_Load_Error"}, + {0, 0x8F, "Block_Handle"}, + {0, 0x90, "PID_Block_Free_Report"}, + {0, 0x91, "Type_Specific_Block_Handle"}, + {0, 0x92, "PID_State_Report"}, + {0, 0x94, "Effect_Playing"}, + {0, 0x95, "PID_Device_Control_Report"}, + {0, 0x96, "PID_Device_Control"}, + {0, 0x97, "DC_Enable_Actuators"}, + {0, 0x98, "DC_Disable_Actuators"}, + {0, 0x99, "DC_Stop_All_Effects"}, + {0, 0x9A, "DC_Device_Reset"}, + {0, 0x9B, "DC_Device_Pause"}, + {0, 0x9C, "DC_Device_Continue"}, + {0, 0x9F, "Device_Paused"}, + {0, 0xA0, "Actuators_Enabled"}, + {0, 0xA4, "Safety_Switch"}, + {0, 0xA5, "Actuator_Override_Switch"}, + {0, 0xA6, "Actuator_Power"}, + {0, 0xA7, "Start_Delay"}, + {0, 0xA8, "Parameter_Block_Size"}, + {0, 0xA9, "Device_Managed_Pool"}, + {0, 0xAA, "Shared_Parameter_Blocks"}, + {0, 0xAB, "Create_New_Effect_Report"}, + {0, 0xAC, "RAM_Pool_Available"}, + { 0x84, 0, "Power Device" }, + { 0x84, 0x02, "PresentStatus" }, + { 0x84, 0x03, "ChangeStatus" }, + { 0x84, 0x04, "UPS" }, + { 0x84, 0x05, "PowerSupply" }, + { 0x84, 0x10, "BatterySystem" }, + { 0x84, 0x11, "BatterySystemID" }, + { 0x84, 0x12, "Battery" }, + { 0x84, 0x13, "BatteryID" }, + { 0x84, 0x14, "Charger" }, + { 0x84, 0x15, "ChargerID" }, + { 0x84, 0x16, "PowerConverter" }, + { 0x84, 0x17, "PowerConverterID" }, + { 0x84, 0x18, "OutletSystem" }, + { 0x84, 0x19, "OutletSystemID" }, + { 0x84, 0x1a, "Input" }, + { 0x84, 0x1b, "InputID" }, + { 0x84, 0x1c, "Output" }, + { 0x84, 0x1d, "OutputID" }, + { 0x84, 0x1e, "Flow" }, + { 0x84, 0x1f, "FlowID" }, + { 0x84, 0x20, "Outlet" }, + { 0x84, 0x21, "OutletID" }, + { 0x84, 0x22, "Gang" }, + { 0x84, 0x24, "PowerSummary" }, + { 0x84, 0x25, "PowerSummaryID" }, + { 0x84, 0x30, "Voltage" }, + { 0x84, 0x31, "Current" }, + { 0x84, 0x32, "Frequency" }, + { 0x84, 0x33, "ApparentPower" }, + { 0x84, 0x35, "PercentLoad" }, + { 0x84, 0x40, "ConfigVoltage" }, + { 0x84, 0x41, "ConfigCurrent" }, + { 0x84, 0x43, "ConfigApparentPower" }, + { 0x84, 0x53, "LowVoltageTransfer" }, + { 0x84, 0x54, "HighVoltageTransfer" }, + { 0x84, 0x56, "DelayBeforeStartup" }, + { 0x84, 0x57, "DelayBeforeShutdown" }, + { 0x84, 0x58, "Test" }, + { 0x84, 0x5a, "AudibleAlarmControl" }, + { 0x84, 0x60, "Present" }, + { 0x84, 0x61, "Good" }, + { 0x84, 0x62, "InternalFailure" }, + { 0x84, 0x65, "Overload" }, + { 0x84, 0x66, "OverCharged" }, + { 0x84, 0x67, "OverTemperature" }, + { 0x84, 0x68, "ShutdownRequested" }, + { 0x84, 0x69, "ShutdownImminent" }, + { 0x84, 0x6b, "SwitchOn/Off" }, + { 0x84, 0x6c, "Switchable" }, + { 0x84, 0x6d, "Used" }, + { 0x84, 0x6e, "Boost" }, + { 0x84, 0x73, "CommunicationLost" }, + { 0x84, 0xfd, "iManufacturer" }, + { 0x84, 0xfe, "iProduct" }, + { 0x84, 0xff, "iSerialNumber" }, + { 0x85, 0, "Battery System" }, + { 0x85, 0x01, "SMBBatteryMode" }, + { 0x85, 0x02, "SMBBatteryStatus" }, + { 0x85, 0x03, "SMBAlarmWarning" }, + { 0x85, 0x04, "SMBChargerMode" }, + { 0x85, 0x05, "SMBChargerStatus" }, + { 0x85, 0x06, "SMBChargerSpecInfo" }, + { 0x85, 0x07, "SMBSelectorState" }, + { 0x85, 0x08, "SMBSelectorPresets" }, + { 0x85, 0x09, "SMBSelectorInfo" }, + { 0x85, 0x29, "RemainingCapacityLimit" }, + { 0x85, 0x2c, "CapacityMode" }, + { 0x85, 0x42, "BelowRemainingCapacityLimit" }, + { 0x85, 0x44, "Charging" }, + { 0x85, 0x45, "Discharging" }, + { 0x85, 0x4b, "NeedReplacement" }, + { 0x85, 0x66, "RemainingCapacity" }, + { 0x85, 0x68, "RunTimeToEmpty" }, + { 0x85, 0x6a, "AverageTimeToFull" }, + { 0x85, 0x83, "DesignCapacity" }, + { 0x85, 0x85, "ManufacturerDate" }, + { 0x85, 0x89, "iDeviceChemistry" }, + { 0x85, 0x8b, "Rechargable" }, + { 0x85, 0x8f, "iOEMInformation" }, + { 0x85, 0x8d, "CapacityGranularity1" }, + { 0x85, 0xd0, "ACPresent" }, + /* pages 0xff00 to 0xffff are vendor-specific */ + { 0xffff, 0, "Vendor-specific-FF" }, + { 0, 0, NULL } +}; + +static void resolv_usage_page(unsigned page) { + const struct hid_usage_entry *p; + + for (p = hid_usage_table; p->description; p++) + if (p->page == page) { + printk("%s", p->description); + return; + } + printk("%04x", page); +} + +static void resolv_usage(unsigned usage) { + const struct hid_usage_entry *p; + + resolv_usage_page(usage >> 16); + printk("."); + for (p = hid_usage_table; p->description; p++) + if (p->page == (usage >> 16)) { + for(++p; p->description && p->usage != 0; p++) + if (p->usage == (usage & 0xffff)) { + printk("%s", p->description); + return; + } + break; + } + printk("%04x", usage & 0xffff); +} + +__inline__ static void tab(int n) { + while (n--) printk(" "); +} + +static void hid_dump_field(struct hid_field *field, int n) { + int j; + + if (field->physical) { + tab(n); + printk("Physical("); + resolv_usage(field->physical); printk(")\n"); + } + if (field->logical) { + tab(n); + printk("Logical("); + resolv_usage(field->logical); printk(")\n"); + } + tab(n); printk("Usage(%d)\n", field->maxusage); + for (j = 0; j < field->maxusage; j++) { + tab(n+2);resolv_usage(field->usage[j].hid); printk("\n"); + } + if (field->logical_minimum != field->logical_maximum) { + tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); + tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); + } + if (field->physical_minimum != field->physical_maximum) { + tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); + tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); + } + if (field->unit_exponent) { + tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); + } + if (field->unit) { + char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; + char *units[5][8] = { + { "None", "None", "None", "None", "None", "None", "None", "None" }, + { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, + { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, + { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, + { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } + }; + + int i; + int sys; + __u32 data = field->unit; + + /* First nibble tells us which system we're in. */ + sys = data & 0xf; + data >>= 4; + + if(sys > 4) { + tab(n); printk("Unit(Invalid)\n"); + } + else { + int earlier_unit = 0; + + tab(n); printk("Unit(%s : ", systems[sys]); + + for (i=1 ; i>= 4; + if (nibble != 0) { + if(earlier_unit++ > 0) + printk("*"); + printk("%s", units[sys][i]); + if(nibble != 1) { + /* This is a _signed_ nibble(!) */ + + int val = nibble & 0x7; + if(nibble & 0x08) + val = -((0x7 & ~val) +1); + printk("^%d", val); + } + } + } + printk(")\n"); + } + } + tab(n); printk("Report Size(%u)\n", field->report_size); + tab(n); printk("Report Count(%u)\n", field->report_count); + tab(n); printk("Report Offset(%u)\n", field->report_offset); + + tab(n); printk("Flags( "); + j = field->flags; + printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); + printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); + printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); + printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); + printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); + printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); + printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); + printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); + printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); + printk(")\n"); +} + +static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { + struct hid_report_enum *report_enum; + struct hid_report *report; + struct list_head *list; + unsigned i,k; + static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; + + for (i = 0; i < HID_REPORT_TYPES; i++) { + report_enum = device->report_enum + i; + list = report_enum->report_list.next; + while (list != &report_enum->report_list) { + report = (struct hid_report *) list; + tab(2); + printk("%s", table[i]); + if (report->id) + printk("(%d)", report->id); + printk("[%s]", table[report->type]); + printk("\n"); + for (k = 0; k < report->maxfield; k++) { + tab(4); + printk("Field(%d)\n", k); + hid_dump_field(report->field[k], 6); + } + list = list->next; + } + } +} + +static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) { + printk("hid-debug: input "); + resolv_usage(usage->hid); + printk(" = %d\n", value); +} + + +static char *events[EV_MAX + 1] = { + [EV_SYN] = "Sync", [EV_KEY] = "Key", + [EV_REL] = "Relative", [EV_ABS] = "Absolute", + [EV_MSC] = "Misc", [EV_LED] = "LED", + [EV_SND] = "Sound", [EV_REP] = "Repeat", + [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", + [EV_FF_STATUS] = "ForceFeedbackStatus", +}; + +static char *syncs[2] = { + [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", +}; +static char *keys[KEY_MAX + 1] = { + [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", + [KEY_1] = "1", [KEY_2] = "2", + [KEY_3] = "3", [KEY_4] = "4", + [KEY_5] = "5", [KEY_6] = "6", + [KEY_7] = "7", [KEY_8] = "8", + [KEY_9] = "9", [KEY_0] = "0", + [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", + [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", + [KEY_Q] = "Q", [KEY_W] = "W", + [KEY_E] = "E", [KEY_R] = "R", + [KEY_T] = "T", [KEY_Y] = "Y", + [KEY_U] = "U", [KEY_I] = "I", + [KEY_O] = "O", [KEY_P] = "P", + [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", + [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", + [KEY_A] = "A", [KEY_S] = "S", + [KEY_D] = "D", [KEY_F] = "F", + [KEY_G] = "G", [KEY_H] = "H", + [KEY_J] = "J", [KEY_K] = "K", + [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", + [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", + [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", + [KEY_Z] = "Z", [KEY_X] = "X", + [KEY_C] = "C", [KEY_V] = "V", + [KEY_B] = "B", [KEY_N] = "N", + [KEY_M] = "M", [KEY_COMMA] = "Comma", + [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", + [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", + [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", + [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", + [KEY_F2] = "F2", [KEY_F3] = "F3", + [KEY_F4] = "F4", [KEY_F5] = "F5", + [KEY_F6] = "F6", [KEY_F7] = "F7", + [KEY_F8] = "F8", [KEY_F9] = "F9", + [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", + [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", + [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", + [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", + [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", + [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", + [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", + [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", + [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", + [KEY_F11] = "F11", [KEY_F12] = "F12", + [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", + [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", + [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", + [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", + [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", + [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", + [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", + [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", + [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", + [KEY_END] = "End", [KEY_DOWN] = "Down", + [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", + [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", + [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", + [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", + [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", + [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", + [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", + [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", + [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", + [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", + [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", + [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", + [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", + [KEY_FIND] = "Find", [KEY_CUT] = "Cut", + [KEY_HELP] = "Help", [KEY_MENU] = "Menu", + [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", + [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", + [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", + [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", + [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", + [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", + [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", + [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", + [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", + [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", + [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", + [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", + [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", + [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", + [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", + [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", + [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", + [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", + [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", + [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", + [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New", + [KEY_REDO] = "Redo", [KEY_F13] = "F13", + [KEY_F14] = "F14", [KEY_F15] = "F15", + [KEY_F16] = "F16", [KEY_F17] = "F17", + [KEY_F18] = "F18", [KEY_F19] = "F19", + [KEY_F20] = "F20", [KEY_F21] = "F21", + [KEY_F22] = "F22", [KEY_F23] = "F23", + [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", + [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", + [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", + [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", + [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", + [KEY_PRINT] = "Print", [KEY_HP] = "HP", + [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", + [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", + [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", + [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", + [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", + [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", + [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", + [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", + [BTN_0] = "Btn0", [BTN_1] = "Btn1", + [BTN_2] = "Btn2", [BTN_3] = "Btn3", + [BTN_4] = "Btn4", [BTN_5] = "Btn5", + [BTN_6] = "Btn6", [BTN_7] = "Btn7", + [BTN_8] = "Btn8", [BTN_9] = "Btn9", + [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", + [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", + [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", + [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", + [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", + [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", + [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", + [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", + [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", + [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", + [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", + [BTN_B] = "BtnB", [BTN_C] = "BtnC", + [BTN_X] = "BtnX", [BTN_Y] = "BtnY", + [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", + [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", + [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", + [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", + [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", + [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", + [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", + [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", + [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", + [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", + [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", + [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", + [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", + [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", + [KEY_OPTION] = "Option", [KEY_INFO] = "Info", + [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", + [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", + [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", + [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", + [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", + [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", + [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", + [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", + [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", + [KEY_TV] = "TV", [KEY_TV2] = "TV2", + [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", + [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", + [KEY_CD] = "CD", [KEY_TAPE] = "Tape", + [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", + [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", + [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", + [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", + [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", + [KEY_LIST] = "List", [KEY_MEMO] = "Memo", + [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", + [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", + [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", + [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", + [KEY_LAST] = "Last", [KEY_AB] = "AB", + [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", + [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", + [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", + [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", + [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", + [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", + [KEY_DEL_LINE] = "DeleteLine", + [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", + [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", + [KEY_DOCUMENTS] = "Documents", + [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", + [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", + [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", + [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F", + [KEY_FN_S] = "Fn+S", + [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2", + [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4", + [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6", + [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8", + [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10", + [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12", + [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle", + [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", + [KEY_KBDILLUMUP] = "KbdIlluminationUp", + [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", +}; + +static char *relatives[REL_MAX + 1] = { + [REL_X] = "X", [REL_Y] = "Y", + [REL_Z] = "Z", [REL_RX] = "Rx", + [REL_RY] = "Ry", [REL_RZ] = "Rz", + [REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial", + [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", +}; + +static char *absolutes[ABS_MAX + 1] = { + [ABS_X] = "X", [ABS_Y] = "Y", + [ABS_Z] = "Z", [ABS_RX] = "Rx", + [ABS_RY] = "Ry", [ABS_RZ] = "Rz", + [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", + [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", + [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", + [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", + [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", + [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", + [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", + [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", + [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", + [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", +}; -void hid_dump_input(struct hid_usage *, __s32); -void hid_dump_device(struct hid_device *); -void hid_dump_field(struct hid_field *, int); -void hid_resolv_usage(unsigned); -void hid_resolv_event(__u8, __u16); +static char *misc[MSC_MAX + 1] = { + [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", + [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" +}; -#else +static char *leds[LED_MAX + 1] = { + [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", + [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", + [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", + [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", + [LED_MISC] = "Misc", +}; -#define hid_dump_input(a,b) do { } while (0) -#define hid_dump_device(c) do { } while (0) -#define hid_dump_field(a,b) do { } while (0) -#define hid_resolv_usage(a) do { } while (0) -#define hid_resolv_event(a,b) do { } while (0) +static char *repeats[REP_MAX + 1] = { + [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" +}; -#endif /* CONFIG_HID_DEBUG */ +static char *sounds[SND_MAX + 1] = { + [SND_CLICK] = "Click", [SND_BELL] = "Bell", + [SND_TONE] = "Tone" +}; +static char **names[EV_MAX + 1] = { + [EV_SYN] = syncs, [EV_KEY] = keys, + [EV_REL] = relatives, [EV_ABS] = absolutes, + [EV_MSC] = misc, [EV_LED] = leds, + [EV_SND] = sounds, [EV_REP] = repeats, +}; -#endif +static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) { + printk("%s.%s", events[type] ? events[type] : "?", + names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); +} diff --git a/trunk/include/linux/hid.h b/trunk/include/linux/hid.h index 93173fe45634..342b4e639acb 100644 --- a/trunk/include/linux/hid.h +++ b/trunk/include/linux/hid.h @@ -264,8 +264,6 @@ struct hid_item { #define HID_QUIRK_INVERT_HWHEEL 0x00004000 #define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 #define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 -#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 -#define HID_QUIRK_IGNORE_MOUSE 0x00040000 /* * This is the global environment of the parser. This information is @@ -432,8 +430,8 @@ struct hid_device { /* device report descriptor */ /* device-specific function pointers */ int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int); - int (*hid_open) (struct hid_device *); - void (*hid_close) (struct hid_device *); + int (*hidinput_open) (struct input_dev *); + void (*hidinput_close) (struct input_dev *); /* hiddev event handler */ void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, @@ -473,6 +471,16 @@ struct hid_descriptor { struct hid_class_descriptor desc[1]; } __attribute__ ((packed)); +#ifdef DEBUG +#include "hid-debug.h" +#else +#define hid_dump_input(a,b) do { } while (0) +#define hid_dump_device(c) do { } while (0) +#define hid_dump_field(a,b) do { } while (0) +#define resolv_usage(a) do { } while (0) +#define resolv_event(a,b) do { } while (0) +#endif + /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ /* We ignore a few input applications that are not widely used */ #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) @@ -495,7 +503,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size); int hid_ff_init(struct hid_device *hid); int hid_lgff_init(struct hid_device *hid); -int hid_plff_init(struct hid_device *hid); int hid_tmff_init(struct hid_device *hid); int hid_zpff_init(struct hid_device *hid); #ifdef CONFIG_HID_PID diff --git a/trunk/include/linux/mmc/card.h b/trunk/include/linux/mmc/card.h index e45712acfac5..d0e6a5497614 100644 --- a/trunk/include/linux/mmc/card.h +++ b/trunk/include/linux/mmc/card.h @@ -71,7 +71,6 @@ struct mmc_card { #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ #define MMC_STATE_READONLY (1<<4) /* card is read-only */ #define MMC_STATE_HIGHSPEED (1<<5) /* card is in high speed mode */ -#define MMC_STATE_BLOCKADDR (1<<6) /* card uses block-addressing */ u32 raw_cid[4]; /* raw card CID */ u32 raw_csd[4]; /* raw card CSD */ u32 raw_scr[2]; /* raw card SCR */ @@ -88,7 +87,6 @@ struct mmc_card { #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) -#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) @@ -96,7 +94,6 @@ struct mmc_card { #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) -#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) ((c)->dev.bus_id) diff --git a/trunk/include/linux/mmc/host.h b/trunk/include/linux/mmc/host.h index 913e5752569f..c15ae1986b98 100644 --- a/trunk/include/linux/mmc/host.h +++ b/trunk/include/linux/mmc/host.h @@ -92,10 +92,8 @@ struct mmc_host { unsigned int max_seg_size; /* see blk_queue_max_segment_size */ unsigned short max_hw_segs; /* see blk_queue_max_hw_segments */ unsigned short max_phys_segs; /* see blk_queue_max_phys_segments */ + unsigned short max_sectors; /* see blk_queue_max_sectors */ unsigned short unused; - unsigned int max_req_size; /* maximum number of bytes in one req */ - unsigned int max_blk_size; /* maximum size of one mmc block */ - unsigned int max_blk_count; /* maximum number of blocks in one req */ /* private data */ struct mmc_ios ios; /* current io bus settings */ @@ -108,9 +106,8 @@ struct mmc_host { struct list_head cards; /* devices attached to this host */ wait_queue_head_t wq; - spinlock_t lock; /* claimed lock */ - unsigned int claimed:1; /* host exclusively claimed */ - + spinlock_t lock; /* card_busy lock */ + struct mmc_card *card_busy; /* the MMC card claiming host */ struct mmc_card *card_selected; /* the selected MMC card */ struct delayed_work detect; @@ -129,7 +126,6 @@ static inline void *mmc_priv(struct mmc_host *host) } #define mmc_dev(x) ((x)->parent) -#define mmc_classdev(x) (&(x)->class_dev) #define mmc_hostname(x) ((x)->class_dev.bus_id) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); diff --git a/trunk/include/linux/mmc/mmc.h b/trunk/include/linux/mmc/mmc.h index cdc54be804f1..bcf24909d677 100644 --- a/trunk/include/linux/mmc/mmc.h +++ b/trunk/include/linux/mmc/mmc.h @@ -43,7 +43,6 @@ struct mmc_command { #define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC) #define MMC_RSP_R3 (MMC_RSP_PRESENT) #define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) -#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) #define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE)) diff --git a/trunk/include/linux/mmc/protocol.h b/trunk/include/linux/mmc/protocol.h index c90b6768329d..2dce60c43f4b 100644 --- a/trunk/include/linux/mmc/protocol.h +++ b/trunk/include/linux/mmc/protocol.h @@ -79,12 +79,9 @@ #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ /* SD commands type argument response */ - /* class 0 */ + /* class 8 */ /* This is basically the same command as for MMC with some quirks. */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ -#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ - - /* class 10 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ /* Application commands */ @@ -117,14 +114,6 @@ * [3:0] Function group 1 */ -/* - * SD_SEND_IF_COND argument format: - * - * [31:12] Reserved (0) - * [11:8] Host Voltage Supply Flags - * [7:0] Check Pattern (0xAA) - */ - /* MMC status in R1 Type diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index ccd706f876ec..3d1d21035dec 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -735,11 +735,9 @@ #define PCI_DEVICE_ID_TI_TVP4020 0x3d07 #define PCI_DEVICE_ID_TI_4450 0x8011 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 -#define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033 #define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034 #define PCI_DEVICE_ID_TI_X515 0x8036 #define PCI_DEVICE_ID_TI_XX12 0x8039 -#define PCI_DEVICE_ID_TI_XX12_FM 0x803b #define PCI_DEVICE_ID_TI_1130 0xac12 #define PCI_DEVICE_ID_TI_1031 0xac13 #define PCI_DEVICE_ID_TI_1131 0xac15 @@ -767,7 +765,6 @@ #define PCI_DEVICE_ID_TI_1510 0xac56 #define PCI_DEVICE_ID_TI_X620 0xac8d #define PCI_DEVICE_ID_TI_X420 0xac8e -#define PCI_DEVICE_ID_TI_XX20_FM 0xac8f #define PCI_VENDOR_ID_SONY 0x104d @@ -1974,7 +1971,6 @@ #define PCI_DEVICE_ID_TOPIC_TP560 0x0000 #define PCI_VENDOR_ID_ENE 0x1524 -#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550 #define PCI_DEVICE_ID_ENE_1211 0x1211 #define PCI_DEVICE_ID_ENE_1225 0x1225 #define PCI_DEVICE_ID_ENE_1410 0x1410 diff --git a/trunk/include/linux/tifm.h b/trunk/include/linux/tifm.h index 3deb0a6c1370..dfb8052eee5e 100644 --- a/trunk/include/linux/tifm.h +++ b/trunk/include/linux/tifm.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include /* Host registers (relative to pci base address): */ enum { @@ -62,10 +62,11 @@ enum { #define TIFM_IRQ_ENABLE 0x80000000 -#define TIFM_IRQ_SOCKMASK(x) (x) -#define TIFM_IRQ_CARDMASK(x) ((x) << 8) -#define TIFM_IRQ_FIFOMASK(x) ((x) << 16) +#define TIFM_IRQ_SOCKMASK 0x00000001 +#define TIFM_IRQ_CARDMASK 0x00000100 +#define TIFM_IRQ_FIFOMASK 0x00010000 #define TIFM_IRQ_SETALL 0xffffffff +#define TIFM_IRQ_SETALLSOCK 0x0000000f #define TIFM_CTRL_LED 0x00000040 #define TIFM_CTRL_FAST_CLK 0x00000100 @@ -88,9 +89,10 @@ struct tifm_dev { char __iomem *addr; spinlock_t lock; tifm_media_id media_id; - unsigned int socket_id; + char wq_name[KOBJ_NAME_LEN]; + struct workqueue_struct *wq; - void (*signal_irq)(struct tifm_dev *sock, + unsigned int (*signal_irq)(struct tifm_dev *sock, unsigned int sock_irq_status); struct tifm_driver *drv; @@ -101,23 +103,24 @@ struct tifm_driver { tifm_media_id *id_table; int (*probe)(struct tifm_dev *dev); void (*remove)(struct tifm_dev *dev); - int (*suspend)(struct tifm_dev *dev, - pm_message_t state); - int (*resume)(struct tifm_dev *dev); struct device_driver driver; }; struct tifm_adapter { char __iomem *addr; - spinlock_t lock; unsigned int irq_status; - unsigned int socket_change_set; - wait_queue_head_t change_set_notify; + unsigned int insert_mask; + unsigned int remove_mask; + spinlock_t lock; unsigned int id; - unsigned int num_sockets; + unsigned int max_sockets; + char wq_name[KOBJ_NAME_LEN]; + unsigned int inhibit_new_cards; + struct workqueue_struct *wq; + struct work_struct media_inserter; + struct work_struct media_remover; struct tifm_dev **sockets; - struct task_struct *media_switcher; struct class_device cdev; struct device *dev; @@ -127,9 +130,9 @@ struct tifm_adapter { struct tifm_adapter *tifm_alloc_adapter(void); void tifm_free_device(struct device *dev); void tifm_free_adapter(struct tifm_adapter *fm); -int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data)); +int tifm_add_adapter(struct tifm_adapter *fm); void tifm_remove_adapter(struct tifm_adapter *fm); -struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm); +struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id); int tifm_register_driver(struct tifm_driver *drv); void tifm_unregister_driver(struct tifm_driver *drv); void tifm_eject(struct tifm_dev *sock); diff --git a/trunk/include/linux/video_output.h b/trunk/include/linux/video_output.h deleted file mode 100644 index e63e0c03ee0d..000000000000 --- a/trunk/include/linux/video_output.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Copyright (C) 2006 Luming Yu - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ -#ifndef _LINUX_VIDEO_OUTPUT_H -#define _LINUX_VIDEO_OUTPUT_H -#include -struct output_device; -struct output_properties { - int (*set_state)(struct output_device *); - int (*get_status)(struct output_device *); -}; -struct output_device { - int request_state; - struct output_properties *props; - struct class_device class_dev; -}; -#define to_output_device(obj) container_of(obj, struct output_device, class_dev) -struct output_device *video_output_register(const char *name, - struct device *dev, - void *devdata, - struct output_properties *op); -void video_output_unregister(struct output_device *dev); -#endif diff --git a/trunk/include/rdma/ib_user_mad.h b/trunk/include/rdma/ib_user_mad.h index d66b15ea82c4..44537aa32e62 100644 --- a/trunk/include/rdma/ib_user_mad.h +++ b/trunk/include/rdma/ib_user_mad.h @@ -98,7 +98,7 @@ struct ib_user_mad_hdr { */ struct ib_user_mad { struct ib_user_mad_hdr hdr; - __u64 data[0]; + __u8 data[0]; }; /** diff --git a/trunk/include/rdma/ib_verbs.h b/trunk/include/rdma/ib_verbs.h index 765589f4d166..0bfa3328d686 100644 --- a/trunk/include/rdma/ib_verbs.h +++ b/trunk/include/rdma/ib_verbs.h @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -420,8 +419,8 @@ struct ib_wc { enum ib_wc_opcode opcode; u32 vendor_err; u32 byte_len; - struct ib_qp *qp; __be32 imm_data; + u32 qp_num; u32 src_qp; int wc_flags; u16 pkey_index; diff --git a/trunk/lib/swiotlb.c b/trunk/lib/swiotlb.c index 50a438010182..10625785eefd 100644 --- a/trunk/lib/swiotlb.c +++ b/trunk/lib/swiotlb.c @@ -1,7 +1,7 @@ /* * Dynamic DMA mapping support. * - * This implementation is a fallback for platforms that do not support + * This implementation is for IA-64 and EM64T platforms that do not support * I/O TLBs (aka DMA address translation hardware). * Copyright (C) 2000 Asit Mallick * Copyright (C) 2000 Goutham Rao @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -36,10 +35,8 @@ #define OFFSET(val,align) ((unsigned long) \ ( (val) & ( (align) - 1))) -#ifndef SG_ENT_VIRT_ADDRESS #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) -#define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) -#endif +#define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) /* * Maximum allowable number of contiguous slabs to map, @@ -104,25 +101,13 @@ static unsigned int io_tlb_index; * We need to save away the original address corresponding to a mapped entry * for the sync operations. */ -#ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T -typedef char *io_tlb_addr_t; -#define swiotlb_orig_addr_null(buffer) (!(buffer)) -#define ptr_to_io_tlb_addr(ptr) (ptr) -#define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off)) -#define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg) -#endif -static io_tlb_addr_t *io_tlb_orig_addr; +static unsigned char **io_tlb_orig_addr; /* * Protect the above data structures in the map and unmap calls */ static DEFINE_SPINLOCK(io_tlb_lock); -#ifdef SWIOTLB_EXTRA_VARIABLES -SWIOTLB_EXTRA_VARIABLES; -#endif - -#ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES static int __init setup_io_tlb_npages(char *str) { @@ -137,50 +122,30 @@ setup_io_tlb_npages(char *str) swiotlb_force = 1; return 1; } -#endif __setup("swiotlb=", setup_io_tlb_npages); /* make io_tlb_overflow tunable too? */ -#ifndef swiotlb_adjust_size -#define swiotlb_adjust_size(size) ((void)0) -#endif - -#ifndef swiotlb_adjust_seg -#define swiotlb_adjust_seg(start, size) ((void)0) -#endif - -#ifndef swiotlb_print_info -#define swiotlb_print_info(bytes) \ - printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \ - "0x%lx\n", bytes >> 20, \ - virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)) -#endif - /* * Statically reserve bounce buffer space and initialize bounce buffer data * structures for the software IO TLB used to implement the DMA API. */ -void __init -swiotlb_init_with_default_size(size_t default_size) +void +swiotlb_init_with_default_size (size_t default_size) { - unsigned long i, bytes; + unsigned long i; if (!io_tlb_nslabs) { io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); } - swiotlb_adjust_size(io_tlb_nslabs); - swiotlb_adjust_size(io_tlb_overflow); - - bytes = io_tlb_nslabs << IO_TLB_SHIFT; /* * Get IO TLB memory from the low pages */ - io_tlb_start = alloc_bootmem_low_pages(bytes); + io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); if (!io_tlb_start) panic("Cannot allocate SWIOTLB buffer"); - io_tlb_end = io_tlb_start + bytes; + io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); /* * Allocate and initialize the free list array. This array is used @@ -188,45 +153,34 @@ swiotlb_init_with_default_size(size_t default_size) * between io_tlb_start and io_tlb_end. */ io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int)); - for (i = 0; i < io_tlb_nslabs; i++) { - if ( !(i % IO_TLB_SEGSIZE) ) - swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT), - IO_TLB_SEGSIZE << IO_TLB_SHIFT); + for (i = 0; i < io_tlb_nslabs; i++) io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); - } io_tlb_index = 0; - io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t)); + io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); /* * Get the overflow emergency buffer */ io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); - if (!io_tlb_overflow_buffer) - panic("Cannot allocate SWIOTLB overflow buffer!\n"); - swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow); - - swiotlb_print_info(bytes); + printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", + virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); } -#ifndef __swiotlb_init_with_default_size -#define __swiotlb_init_with_default_size swiotlb_init_with_default_size -#endif -void __init -swiotlb_init(void) +void +swiotlb_init (void) { - __swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ + swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ } -#ifdef SWIOTLB_ARCH_NEED_LATE_INIT /* * Systems with larger DMA zones (those that don't support ISA) can * initialize the swiotlb later using the slab allocator if needed. * This should be just like above, but with some error catching. */ int -swiotlb_late_init_with_default_size(size_t default_size) +swiotlb_late_init_with_default_size (size_t default_size) { - unsigned long i, bytes, req_nslabs = io_tlb_nslabs; + unsigned long i, req_nslabs = io_tlb_nslabs; unsigned int order; if (!io_tlb_nslabs) { @@ -237,9 +191,8 @@ swiotlb_late_init_with_default_size(size_t default_size) /* * Get IO TLB memory from the low pages */ - order = get_order(io_tlb_nslabs << IO_TLB_SHIFT); + order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); io_tlb_nslabs = SLABS_PER_PAGE << order; - bytes = io_tlb_nslabs << IO_TLB_SHIFT; while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN, @@ -252,14 +205,13 @@ swiotlb_late_init_with_default_size(size_t default_size) if (!io_tlb_start) goto cleanup1; - if (order != get_order(bytes)) { + if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) { printk(KERN_WARNING "Warning: only able to allocate %ld MB " "for software IO TLB\n", (PAGE_SIZE << order) >> 20); io_tlb_nslabs = SLABS_PER_PAGE << order; - bytes = io_tlb_nslabs << IO_TLB_SHIFT; } - io_tlb_end = io_tlb_start + bytes; - memset(io_tlb_start, 0, bytes); + io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); + memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT)); /* * Allocate and initialize the free list array. This array is used @@ -275,12 +227,12 @@ swiotlb_late_init_with_default_size(size_t default_size) io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_index = 0; - io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL, - get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); + io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL, + get_order(io_tlb_nslabs * sizeof(char *))); if (!io_tlb_orig_addr) goto cleanup3; - memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t)); + memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *)); /* * Get the overflow emergency buffer @@ -290,29 +242,29 @@ swiotlb_late_init_with_default_size(size_t default_size) if (!io_tlb_overflow_buffer) goto cleanup4; - swiotlb_print_info(bytes); + printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - " + "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20, + virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); return 0; cleanup4: - free_pages((unsigned long)io_tlb_orig_addr, - get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); + free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs * + sizeof(char *))); io_tlb_orig_addr = NULL; cleanup3: - free_pages((unsigned long)io_tlb_list, - get_order(io_tlb_nslabs * sizeof(int))); + free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * + sizeof(int))); io_tlb_list = NULL; -cleanup2: io_tlb_end = NULL; +cleanup2: free_pages((unsigned long)io_tlb_start, order); io_tlb_start = NULL; cleanup1: io_tlb_nslabs = req_nslabs; return -ENOMEM; } -#endif -#ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr) { @@ -323,35 +275,11 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr) return (addr & ~mask) != 0; } -static inline int range_needs_mapping(const void *ptr, size_t size) -{ - return swiotlb_force; -} - -static inline int order_needs_mapping(unsigned int order) -{ - return 0; -} -#endif - -static void -__sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir) -{ -#ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE - if (dir == DMA_TO_DEVICE) - memcpy(dma_addr, buffer, size); - else - memcpy(buffer, dma_addr, size); -#else - __swiotlb_arch_sync_single(buffer, dma_addr, size, dir); -#endif -} - /* * Allocates bounce buffer and returns its kernel virtual address. */ static void * -map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir) +map_single(struct device *hwdev, char *buffer, size_t size, int dir) { unsigned long flags; char *dma_addr; @@ -424,7 +352,7 @@ map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir) */ io_tlb_orig_addr[index] = buffer; if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) - __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); + memcpy(dma_addr, buffer, size); return dma_addr; } @@ -438,18 +366,17 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir) unsigned long flags; int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; - io_tlb_addr_t buffer = io_tlb_orig_addr[index]; + char *buffer = io_tlb_orig_addr[index]; /* * First, sync the memory before unmapping the entry */ - if (!swiotlb_orig_addr_null(buffer) - && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) + if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) /* * bounce... copy the data back into the original buffer * and * delete the bounce buffer. */ - __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); + memcpy(buffer, dma_addr, size); /* * Return the buffer to the free list by setting the corresponding @@ -482,18 +409,18 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir, int target) { int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; - io_tlb_addr_t buffer = io_tlb_orig_addr[index]; + char *buffer = io_tlb_orig_addr[index]; switch (target) { case SYNC_FOR_CPU: if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) - __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); + memcpy(buffer, dma_addr, size); else BUG_ON(dir != DMA_TO_DEVICE); break; case SYNC_FOR_DEVICE: if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) - __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); + memcpy(dma_addr, buffer, size); else BUG_ON(dir != DMA_FROM_DEVICE); break; @@ -502,13 +429,11 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, } } -#ifdef SWIOTLB_ARCH_NEED_ALLOC - void * swiotlb_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flags) { - dma_addr_t dev_addr; + unsigned long dev_addr; void *ret; int order = get_order(size); @@ -519,11 +444,8 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, */ flags |= GFP_DMA; - if (!order_needs_mapping(order)) - ret = (void *)__get_free_pages(flags, order); - else - ret = NULL; - if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) { + ret = (void *)__get_free_pages(flags, order); + if (ret && address_needs_mapping(hwdev, virt_to_phys(ret))) { /* * The allocated memory isn't reachable by the device. * Fall back on swiotlb_map_single(). @@ -543,24 +465,22 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, if (swiotlb_dma_mapping_error(handle)) return NULL; - ret = bus_to_virt(handle); + ret = phys_to_virt(handle); } memset(ret, 0, size); - dev_addr = virt_to_bus(ret); + dev_addr = virt_to_phys(ret); /* Confirm address can be DMA'd by device */ if (address_needs_mapping(hwdev, dev_addr)) { - printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n", - (unsigned long long)*hwdev->dma_mask, - (unsigned long long)dev_addr); + printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016lx\n", + (unsigned long long)*hwdev->dma_mask, dev_addr); panic("swiotlb_alloc_coherent: allocated memory is out of " "range for device"); } *dma_handle = dev_addr; return ret; } -EXPORT_SYMBOL(swiotlb_alloc_coherent); void swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, @@ -573,9 +493,6 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); } -EXPORT_SYMBOL(swiotlb_free_coherent); - -#endif static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) @@ -587,7 +504,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) * When the mapping is small enough return a static buffer to limit * the damage, or panic when the transfer is too big. */ - printk(KERN_ERR "DMA: Out of SW-IOMMU space for %zu bytes at " + printk(KERN_ERR "DMA: Out of SW-IOMMU space for %lu bytes at " "device %s\n", size, dev ? dev->bus_id : "?"); if (size > io_tlb_overflow && do_panic) { @@ -608,7 +525,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) { - dma_addr_t dev_addr = virt_to_bus(ptr); + unsigned long dev_addr = virt_to_phys(ptr); void *map; BUG_ON(dir == DMA_NONE); @@ -617,20 +534,19 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) * we can safely return the device addr and not worry about bounce * buffering it. */ - if (!range_needs_mapping(ptr, size) - && !address_needs_mapping(hwdev, dev_addr)) + if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) return dev_addr; /* * Oh well, have to allocate and map a bounce buffer. */ - map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir); + map = map_single(hwdev, ptr, size, dir); if (!map) { swiotlb_full(hwdev, size, dir, 1); map = io_tlb_overflow_buffer; } - dev_addr = virt_to_bus(map); + dev_addr = virt_to_phys(map); /* * Ensure that the address returned is DMA'ble @@ -641,6 +557,25 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) return dev_addr; } +/* + * Since DMA is i-cache coherent, any (complete) pages that were written via + * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to + * flush them when they get mapped into an executable vm-area. + */ +static void +mark_clean(void *addr, size_t size) +{ + unsigned long pg_addr, end; + + pg_addr = PAGE_ALIGN((unsigned long) addr); + end = (unsigned long) addr + size; + while (pg_addr + PAGE_SIZE <= end) { + struct page *page = virt_to_page(pg_addr); + set_bit(PG_arch_1, &page->flags); + pg_addr += PAGE_SIZE; + } +} + /* * Unmap a single streaming mode DMA translation. The dma_addr and size must * match what was provided for in a previous swiotlb_map_single call. All @@ -653,13 +588,13 @@ void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - char *dma_addr = bus_to_virt(dev_addr); + char *dma_addr = phys_to_virt(dev_addr); BUG_ON(dir == DMA_NONE); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) unmap_single(hwdev, dma_addr, size, dir); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(dma_addr, size); + mark_clean(dma_addr, size); } /* @@ -676,13 +611,13 @@ static inline void swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir, int target) { - char *dma_addr = bus_to_virt(dev_addr); + char *dma_addr = phys_to_virt(dev_addr); BUG_ON(dir == DMA_NONE); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) sync_single(hwdev, dma_addr, size, dir, target); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(dma_addr, size); + mark_clean(dma_addr, size); } void @@ -707,13 +642,13 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr, unsigned long offset, size_t size, int dir, int target) { - char *dma_addr = bus_to_virt(dev_addr) + offset; + char *dma_addr = phys_to_virt(dev_addr) + offset; BUG_ON(dir == DMA_NONE); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) sync_single(hwdev, dma_addr, size, dir, target); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(dma_addr, size); + mark_clean(dma_addr, size); } void @@ -752,16 +687,18 @@ int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { - dma_addr_t dev_addr; + void *addr; + unsigned long dev_addr; int i; BUG_ON(dir == DMA_NONE); for (i = 0; i < nelems; i++, sg++) { - dev_addr = SG_ENT_PHYS_ADDRESS(sg); - if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length) - || address_needs_mapping(hwdev, dev_addr)) { - void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir); + addr = SG_ENT_VIRT_ADDRESS(sg); + dev_addr = virt_to_phys(addr); + if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) { + void *map = map_single(hwdev, addr, sg->length, dir); + sg->dma_address = virt_to_bus(map); if (!map) { /* Don't panic here, we expect map_sg users to do proper error handling. */ @@ -770,7 +707,6 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, sg[0].dma_length = 0; return 0; } - sg->dma_address = virt_to_bus(map); } else sg->dma_address = dev_addr; sg->dma_length = sg->length; @@ -792,10 +728,9 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems, for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - unmap_single(hwdev, bus_to_virt(sg->dma_address), - sg->dma_length, dir); + unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir); else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); + mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); } /* @@ -815,10 +750,8 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - sync_single(hwdev, bus_to_virt(sg->dma_address), + sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir, target); - else if (dir == DMA_FROM_DEVICE) - dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); } void @@ -835,48 +768,10 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); } -#ifdef SWIOTLB_ARCH_NEED_MAP_PAGE - -dma_addr_t -swiotlb_map_page(struct device *hwdev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - dma_addr_t dev_addr; - char *map; - - dev_addr = page_to_bus(page) + offset; - if (address_needs_mapping(hwdev, dev_addr)) { - map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction); - if (!map) { - swiotlb_full(hwdev, size, direction, 1); - map = io_tlb_overflow_buffer; - } - dev_addr = virt_to_bus(map); - } - - return dev_addr; -} - -void -swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, - size_t size, enum dma_data_direction direction) -{ - char *dma_addr = bus_to_virt(dev_addr); - - BUG_ON(direction == DMA_NONE); - if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) - unmap_single(hwdev, dma_addr, size, direction); - else if (direction == DMA_FROM_DEVICE) - dma_mark_clean(dma_addr, size); -} - -#endif - int swiotlb_dma_mapping_error(dma_addr_t dma_addr) { - return (dma_addr == virt_to_bus(io_tlb_overflow_buffer)); + return (dma_addr == virt_to_phys(io_tlb_overflow_buffer)); } /* @@ -885,13 +780,10 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr) * during bus mastering, then you would pass 0x00ffffff as the mask to * this function. */ -#ifndef __swiotlb_dma_supported -#define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask)) -#endif int -swiotlb_dma_supported(struct device *hwdev, u64 mask) +swiotlb_dma_supported (struct device *hwdev, u64 mask) { - return __swiotlb_dma_supported(hwdev, mask); + return (virt_to_phys (io_tlb_end) - 1) <= mask; } EXPORT_SYMBOL(swiotlb_init); @@ -906,4 +798,6 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device); EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); EXPORT_SYMBOL(swiotlb_sync_sg_for_device); EXPORT_SYMBOL(swiotlb_dma_mapping_error); +EXPORT_SYMBOL(swiotlb_alloc_coherent); +EXPORT_SYMBOL(swiotlb_free_coherent); EXPORT_SYMBOL(swiotlb_dma_supported); diff --git a/trunk/scripts/Kbuild.include b/trunk/scripts/Kbuild.include index d65c40331e66..f01f8c072852 100644 --- a/trunk/scripts/Kbuild.include +++ b/trunk/scripts/Kbuild.include @@ -1,7 +1,7 @@ #### # kbuild: Generic definitions -# Convenient constants +# Convinient variables comma := , squote := ' empty := @@ -56,89 +56,76 @@ endef # gcc support functions # See documentation in Documentation/kbuild/makefiles.txt -# checker-shell -# Usage: option = $(call checker-shell,$(CC)...-o $$OUT,option-ok,otherwise) -# Exit code chooses option. $$OUT is safe location for needless output. -define checker-shell - $(shell set -e; \ - DIR=$(KBUILD_EXTMOD); \ - cd $${DIR:-$(objtree)}; \ - OUT=$$PWD/.$$$$.null; \ - \ - ln -s /dev/null $$OUT; \ - if $(1) >/dev/null 2>&1; \ - then echo "$(2)"; \ - else echo "$(3)"; \ - fi; \ - rm -f $$OUT) -endef +# output directory for tests below +TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) # as-option -# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) -as-option = $(call checker-shell,\ - $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o $$OUT,$(1),$(2)) +# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,) + +as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \ + -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \ + else echo "$(2)"; fi ;) # as-instr -# Usage: cflags-y += $(call as-instr,instr,option1,option2) -as-instr = $(call checker-shell,\ - printf "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o $$OUT -,$(2),$(3)) +# Usage: cflags-y += $(call as-instr, instr, option1, option2) + +as-instr = $(shell if echo -e "$(1)" | \ + $(CC) $(AFLAGS) -c -xassembler - \ + -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \ + then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \ + else echo "$(3)"; fi) # cc-option -# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) -cc-option = $(call checker-shell,\ - $(CC) $(CFLAGS) $(if $(3),$(3),$(1)) -S -xc /dev/null -o $$OUT,$(1),$(2)) +# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586) + +cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) # cc-option-yn -# Usage: flag := $(call cc-option-yn,-march=winchip-c6) -cc-option-yn = $(call cc-option,"y","n",$(1)) +# Usage: flag := $(call cc-option-yn, -march=winchip-c6) +cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) # cc-option-align # Prefix align with either -falign or -malign cc-option-align = $(subst -functions=0,,\ - $(call cc-option,-falign-functions=0,-malign-functions=0)) + $(call cc-option,-falign-functions=0,-malign-functions=0)) # cc-version -# Usage gcc-ver := $(call cc-version,$(CC)) +# Usage gcc-ver := $(call cc-version, $(CC)) cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) # cc-ifversion # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) -cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) +cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \ + echo $(3); fi;) # ld-option # Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both) -ld-option = $(call checker-shell,\ - $(CC) $(1) -nostdlib -xc /dev/null -o $$OUT,$(1),$(2)) - -###### +ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \ + -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \ + then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \ + else echo "$(2)"; fi) +### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: # $(Q)$(MAKE) $(build)=dir build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj -# Prefix -I with $(srctree) if it is not an absolute path, -# add original to the end -addtree = $(if \ - $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1) - +# Prefix -I with $(srctree) if it is not an absolute path +addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1) # Find all -I options and call addtree -flags = $(foreach o,$($(1)),\ - $(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) - -# echo command. -# Short version is used, if $(quiet) equals `quiet_', otherwise full one. -echo-cmd = $(if $($(quiet)cmd_$(1)),\ - echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) +flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) -# printing commands +# If quiet is set, only print short version of command cmd = @$(echo-cmd) $(cmd_$(1)) -# Add $(obj)/ for paths that are not absolute +# Add $(obj)/ for paths that is not absolute objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) ### -# if_changed - execute command if any prerequisite is newer than +# if_changed - execute command if any prerequisite is newer than # target, or command line has changed # if_changed_dep - as if_changed, but uses fixdep to reveal dependencies # including used config symbols @@ -146,12 +133,16 @@ objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) # See Documentation/kbuild/makefiles.txt for more info ifneq ($(KBUILD_NOCMDDEP),1) -# Check if both arguments has same arguments. Result is empty string, if equal. +# Check if both arguments has same arguments. Result in empty string if equal # User may override this check using make KBUILD_NOCMDDEP=1 arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ $(filter-out $(cmd_$@), $(cmd_$(1))) ) endif +# echo command. Short version is $(quiet) equals quiet, otherwise full command +echo-cmd = $(if $($(quiet)cmd_$(1)), \ + echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) + # >'< substitution is for echo to work, # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=1;...'] @@ -162,15 +153,15 @@ make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) # PHONY targets skipped in both cases. any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) -# Execute command if command has changed or prerequisite(s) are updated. +# Execute command if command has changed or prerequisitei(s) are updated # if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ @set -e; \ $(echo-cmd) $(cmd_$(1)); \ echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) -# Execute the command and also postprocess generated .d dependencies file. -# +# execute the command and also postprocess generated .d dependencies +# file if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ $(echo-cmd) $(cmd_$(1)); \ @@ -178,10 +169,9 @@ if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd) -# Will check if $(cmd_foo) changed, or any of the prerequisites changed, -# and if so will execute $(rule_foo). # Usage: $(call if_changed_rule,foo) -# +# will check if $(cmd_foo) changed, or any of the prequisites changed, +# and if so will execute $(rule_foo) if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ $(rule_$(1))) diff --git a/trunk/scripts/gen_initramfs_list.sh b/trunk/scripts/gen_initramfs_list.sh index 43f75d6e4d96..4c723fd18648 100644 --- a/trunk/scripts/gen_initramfs_list.sh +++ b/trunk/scripts/gen_initramfs_list.sh @@ -1,6 +1,6 @@ #!/bin/bash # Copyright (C) Martin Schlemmer -# Copyright (C) 2006 Sam Ravnborg +# Copyright (c) 2006 Sam Ravnborg # # Released under the terms of the GNU GPL # @@ -17,15 +17,15 @@ cat << EOF Usage: $0 [-o ] [-u ] [-g ] {-d | } ... -o Create gzipped initramfs file named using - gen_init_cpio and gzip + gen_init_cpio and gzip -u User ID to map to user ID 0 (root). - is only meaningful if - is a directory. + is only meaningful if + is a directory. -g Group ID to map to group ID 0 (root). - is only meaningful if - is a directory. + is only meaningful if + is a directory. File list or directory for cpio archive. - If is a .cpio file it will be used + If is a .cpio file it will be used as direct input to initramfs. -d Output the default cpio list. @@ -36,12 +36,6 @@ to reset the root/group mapping. EOF } -# awk style field access -# $1 - field number; rest is argument string -field() { - shift $1 ; echo $1 -} - list_default_initramfs() { # echo usr/kinit/kinit : @@ -125,17 +119,22 @@ parse() { str="${ftype} ${name} ${location} ${str}" ;; "nod") - local dev=`LC_ALL=C ls -l "${location}"` - local maj=`field 5 ${dev}` - local min=`field 6 ${dev}` - maj=${maj%,} - - [ -b "${location}" ] && dev="b" || dev="c" - - str="${ftype} ${name} ${str} ${dev} ${maj} ${min}" + local dev_type= + local maj=$(LC_ALL=C ls -l "${location}" | \ + gawk '{sub(/,/, "", $5); print $5}') + local min=$(LC_ALL=C ls -l "${location}" | \ + gawk '{print $6}') + + if [ -b "${location}" ]; then + dev_type="b" + else + dev_type="c" + fi + str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}" ;; "slink") - local target=`field 11 $(LC_ALL=C ls -l "${location}")` + local target=$(LC_ALL=C ls -l "${location}" | \ + gawk '{print $11}') str="${ftype} ${name} ${target} ${str}" ;; *) diff --git a/trunk/scripts/makelst b/trunk/scripts/makelst index 4fc80f2b7e19..34bd72391238 100755 --- a/trunk/scripts/makelst +++ b/trunk/scripts/makelst @@ -1,31 +1,31 @@ -#!/bin/sh +#!/bin/bash # A script to dump mixed source code & assembly # with correct relocations from System.map -# Requires the following lines in makefile: +# Requires the following lines in Rules.make. +# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) +# William Stearns #%.lst: %.c # $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $< -# $(srctree)/scripts/makelst $*.o $(objtree)/System.map $(OBJDUMP) +# $(TOPDIR)/scripts/makelst $*.o $(TOPDIR)/System.map $(OBJDUMP) # -# Copyright (C) 2000 IBM Corporation -# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) -# William Stearns +# Copyright (C) 2000 IBM Corporation +# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) # -# awk style field access -field() { - shift $1 ; echo $1 -} - -t1=`$3 --syms $1 | grep .text | grep -m1 " F "` +t1=`$3 --syms $1 | grep .text | grep " F " | head -n 1` if [ -n "$t1" ]; then - t2=`field 6 $t1` + t2=`echo $t1 | gawk '{ print $6 }'` if [ ! -r $2 ]; then echo "No System.map" >&2 + t7=0 else t3=`grep $t2 $2` - t4=`field 1 $t3` - t5=`field 1 $t1` - t6=`printf "%lu" $((0x$t4 - 0x$t5))` + t4=`echo $t3 | gawk '{ print $1 }'` + t5=`echo $t1 | gawk '{ print $1 }'` + t6=`echo $t4 - $t5 | tr a-f A-F` + t7=`( echo ibase=16 ; echo $t6 ) | bc` fi +else + t7=0 fi -$3 -r --source --adjust-vma=${t6:-0} $1 +$3 -r --source --adjust-vma=$t7 $1 diff --git a/trunk/security/keys/key.c b/trunk/security/keys/key.c index 700400d801dc..ac9326c5f1da 100644 --- a/trunk/security/keys/key.c +++ b/trunk/security/keys/key.c @@ -188,7 +188,6 @@ static inline void key_alloc_serial(struct key *key) spin_lock(&key_serial_lock); -attempt_insertion: parent = NULL; p = &key_serial_tree.rb_node; @@ -203,33 +202,39 @@ static inline void key_alloc_serial(struct key *key) else goto serial_exists; } - - /* we've found a suitable hole - arrange for this key to occupy it */ - rb_link_node(&key->serial_node, parent, p); - rb_insert_color(&key->serial_node, &key_serial_tree); - - spin_unlock(&key_serial_lock); - return; + goto insert_here; /* we found a key with the proposed serial number - walk the tree from * that point looking for the next unused serial number */ serial_exists: for (;;) { key->serial++; - if (key->serial < 3) { - key->serial = 3; - goto attempt_insertion; - } + if (key->serial < 2) + key->serial = 2; + + if (!rb_parent(parent)) + p = &key_serial_tree.rb_node; + else if (rb_parent(parent)->rb_left == parent) + p = &(rb_parent(parent)->rb_left); + else + p = &(rb_parent(parent)->rb_right); parent = rb_next(parent); if (!parent) - goto attempt_insertion; + break; xkey = rb_entry(parent, struct key, serial_node); if (key->serial < xkey->serial) - goto attempt_insertion; + goto insert_here; } + /* we've found a suitable hole - arrange for this key to occupy it */ +insert_here: + rb_link_node(&key->serial_node, parent, p); + rb_insert_color(&key->serial_node, &key_serial_tree); + + spin_unlock(&key_serial_lock); + } /* end key_alloc_serial() */ /*****************************************************************************/