From a7e394f0cae5bf95e65441ab3651347be589da98 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 5 Jun 2008 01:15:40 +0200 Subject: [PATCH] --- yaml --- r: 102253 b: refs/heads/master c: 06166780eb53685e72b589814d535d1f9948e761 h: refs/heads/master i: 102251: 351ea41c153e0f7708c326f74ca762c219cc51bd v: v3 --- [refs] | 2 +- trunk/Documentation/kernel-parameters.txt | 3 - trunk/MAINTAINERS | 19 +- trunk/arch/s390/Kconfig | 1 + trunk/arch/s390/kernel/smp.c | 2 +- trunk/arch/s390/mm/vmem.c | 2 +- trunk/arch/x86/kernel/apm_32.c | 8 +- trunk/arch/x86/kernel/setup_64.c | 5 - trunk/arch/x86/pci/common.c | 26 - trunk/arch/x86/pci/early.c | 60 +- trunk/arch/x86/pci/irq.c | 511 ++++++------- trunk/arch/x86/pci/pci.h | 1 - trunk/drivers/acpi/Kconfig | 9 - trunk/drivers/acpi/Makefile | 1 - trunk/drivers/acpi/pci_slot.c | 368 ---------- trunk/drivers/acpi/sleep/main.c | 8 +- trunk/drivers/base/platform.c | 296 +------- trunk/drivers/base/power/main.c | 675 ++++-------------- trunk/drivers/base/power/power.h | 2 +- trunk/drivers/base/power/trace.c | 4 +- trunk/drivers/ide/Kconfig | 1 + trunk/drivers/ide/arm/bast-ide.c | 1 + trunk/drivers/ide/arm/ide_arm.c | 1 + trunk/drivers/ide/arm/palm_bk3710.c | 3 - trunk/drivers/ide/ide-generic.c | 1 + trunk/drivers/ide/ide-pnp.c | 1 + trunk/drivers/ide/ide-probe.c | 6 +- trunk/drivers/ide/ide-proc.c | 1 - trunk/drivers/ide/legacy/buddha.c | 2 + trunk/drivers/ide/legacy/falconide.c | 2 + trunk/drivers/ide/legacy/gayle.c | 6 + trunk/drivers/ide/legacy/macide.c | 2 + trunk/drivers/ide/legacy/q40ide.c | 2 + trunk/drivers/ide/pci/cmd640.c | 2 + trunk/drivers/ide/pci/delkin_cb.c | 28 +- trunk/drivers/ide/pci/sis5513.c | 5 + trunk/drivers/ide/ppc/mpc8xx.c | 4 + trunk/drivers/pci/Makefile | 2 +- trunk/drivers/pci/hotplug/acpi_pcihp.c | 85 +-- trunk/drivers/pci/hotplug/acpiphp.h | 1 + trunk/drivers/pci/hotplug/acpiphp_core.c | 25 +- trunk/drivers/pci/hotplug/acpiphp_glue.c | 23 +- trunk/drivers/pci/hotplug/acpiphp_ibm.c | 6 +- trunk/drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- trunk/drivers/pci/hotplug/cpqphp_core.c | 4 +- trunk/drivers/pci/hotplug/fakephp.c | 86 ++- trunk/drivers/pci/hotplug/ibmphp_ebda.c | 3 +- trunk/drivers/pci/hotplug/pci_hotplug_core.c | 274 ++++--- trunk/drivers/pci/hotplug/pciehp.h | 9 +- trunk/drivers/pci/hotplug/pciehp_core.c | 45 +- trunk/drivers/pci/hotplug/pciehp_hpc.c | 104 ++- trunk/drivers/pci/hotplug/rpadlpar_sysfs.c | 5 +- trunk/drivers/pci/hotplug/rpaphp_slot.c | 44 +- trunk/drivers/pci/hotplug/sgi_hotplug.c | 12 +- trunk/drivers/pci/hotplug/shpchp.h | 14 +- trunk/drivers/pci/hotplug/shpchp_core.c | 37 +- trunk/drivers/pci/hotplug/shpchp_hpc.c | 1 + trunk/drivers/pci/intel-iommu.c | 1 + trunk/drivers/pci/msi.c | 12 +- trunk/drivers/pci/pci-acpi.c | 219 +++--- trunk/drivers/pci/pci-driver.c | 388 ++-------- trunk/drivers/pci/pci.c | 2 + trunk/drivers/pci/pci.h | 13 - trunk/drivers/pci/pcie/aer/aerdrv.c | 1 - trunk/drivers/pci/pcie/portdrv_bus.c | 1 - trunk/drivers/pci/probe.c | 45 -- trunk/drivers/pci/proc.c | 4 +- trunk/drivers/pci/quirks.c | 134 +--- trunk/drivers/pci/slot.c | 233 ------ trunk/drivers/pnp/pnpacpi/core.c | 4 +- trunk/drivers/s390/char/sclp_vt220.c | 1 + trunk/drivers/s390/char/tape_3590.c | 2 +- trunk/drivers/s390/cio/blacklist.c | 6 +- trunk/drivers/s390/cio/cio.c | 20 +- trunk/include/acpi/acpi_bus.h | 4 +- trunk/include/asm-generic/vmlinux.lds.h | 6 - trunk/include/asm-s390/system.h | 8 +- trunk/include/asm-x86/pci-direct.h | 4 - trunk/include/linux/device.h | 9 - trunk/include/linux/ide.h | 2 +- trunk/include/linux/pci.h | 36 +- trunk/include/linux/pci_hotplug.h | 14 +- trunk/include/linux/platform_device.h | 1 - trunk/include/linux/pm.h | 314 +------- trunk/ipc/shm.c | 2 - trunk/kernel/power/disk.c | 22 +- trunk/kernel/power/main.c | 6 +- trunk/lib/kobject.c | 1 - 88 files changed, 1204 insertions(+), 3164 deletions(-) delete mode 100644 trunk/drivers/acpi/pci_slot.c delete mode 100644 trunk/drivers/pci/slot.c diff --git a/[refs] b/[refs] index d0f79232f985..695d35496134 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8344b568f5bdc7ee1bba909de3294c6348c36056 +refs/heads/master: 06166780eb53685e72b589814d535d1f9948e761 diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 9cf7b34f2db0..e07c432c731f 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -1496,9 +1496,6 @@ and is between 256 and 4096 characters. It is defined in the file Use with caution as certain devices share address decoders between ROMs and other resources. - norom [X86-32,X86_64] Do not assign address space to - expansion ROMs that do not already have - BIOS assigned address ranges. irqmask=0xMMMM [X86-32] Set a bit mask of IRQs allowed to be assigned automatically to PCI devices. You can make the kernel exclude IRQs of your ISA cards diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 89db949bcd80..e3560df4608e 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -248,7 +248,7 @@ S: Supported ACPI PCI HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported ACPI THERMAL DRIVER @@ -1134,21 +1134,21 @@ COMPACTPCI HOTPLUG CORE P: Scott Murray M: scottm@somanetworks.com M: scott@spiteful.org -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER P: Scott Murray M: scottm@somanetworks.com M: scott@spiteful.org -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported COMPACTPCI HOTPLUG GENERIC DRIVER P: Scott Murray M: scottm@somanetworks.com M: scott@spiteful.org -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported COMPUTONE INTELLIPORT MULTIPORT CARD @@ -3177,7 +3177,7 @@ S: Supported PCIE HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported PCMCIA SUBSYSTEM @@ -3658,13 +3658,6 @@ M: romieu@fr.zoreil.com L: netdev@vger.kernel.org S: Maintained -SIS 5513 IDE CONTROLLER DRIVER -P: Lionel Bouton -M: Lionel.Bouton@inet6.fr -W: http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html -W: http://gyver.homeip.net/sis5513/index.html -S: Maintained - SIS 900/7016 FAST ETHERNET DRIVER P: Daniele Venzano M: venza@brownhat.org @@ -3815,7 +3808,7 @@ S: Maintained SHPC HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com -L: linux-pci@vger.kernel.org +L: pcihpd-discuss@lists.sourceforge.net S: Supported SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 93acb3c1859d..107e492cb47e 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -304,6 +304,7 @@ config ARCH_SPARSEMEM_ENABLE def_bool y select SPARSEMEM_VMEMMAP_ENABLE select SPARSEMEM_VMEMMAP + select SPARSEMEM_STATIC if !64BIT config ARCH_SPARSEMEM_DEFAULT def_bool y diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 42b1d12ebb10..5d4fa4b1c74c 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -711,7 +711,7 @@ int __cpuinit __cpu_up(unsigned int cpu) memset(sf, 0, sizeof(struct stack_frame)); sf->gprs[9] = (unsigned long) sf; cpu_lowcore->save_area[15] = (unsigned long) sf; - __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15); + __ctl_store(cpu_lowcore->cregs_save_area, 0, 15); asm volatile( " stam 0,15,0(%0)" : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); diff --git a/trunk/arch/s390/mm/vmem.c b/trunk/arch/s390/mm/vmem.c index f591188fa2c0..e4868bfc672f 100644 --- a/trunk/arch/s390/mm/vmem.c +++ b/trunk/arch/s390/mm/vmem.c @@ -236,7 +236,7 @@ static int insert_memory_segment(struct memory_segment *seg) { struct memory_segment *tmp; - if (seg->start + seg->size >= VMEM_MAX_PHYS || + if (seg->start + seg->size > VMEM_MAX_PHYS || seg->start + seg->size < seg->start) return -ERANGE; diff --git a/trunk/arch/x86/kernel/apm_32.c b/trunk/arch/x86/kernel/apm_32.c index c1735f61a2c0..bf9290e29013 100644 --- a/trunk/arch/x86/kernel/apm_32.c +++ b/trunk/arch/x86/kernel/apm_32.c @@ -1211,9 +1211,9 @@ static int suspend(int vetoable) if (err != APM_SUCCESS) apm_error("suspend", err); err = (err == APM_SUCCESS) ? 0 : -EIO; - device_power_up(PMSG_RESUME); + device_power_up(); local_irq_enable(); - device_resume(PMSG_RESUME); + device_resume(); queue_event(APM_NORMAL_RESUME, NULL); spin_lock(&user_list_lock); for (as = user_list; as != NULL; as = as->next) { @@ -1238,7 +1238,7 @@ static void standby(void) apm_error("standby", err); local_irq_disable(); - device_power_up(PMSG_RESUME); + device_power_up(); local_irq_enable(); } @@ -1324,7 +1324,7 @@ static void check_events(void) ignore_bounce = 1; if ((event != APM_NORMAL_RESUME) || (ignore_normal_resume == 0)) { - device_resume(PMSG_RESUME); + device_resume(); queue_event(event, NULL); } ignore_normal_resume = 0; diff --git a/trunk/arch/x86/kernel/setup_64.c b/trunk/arch/x86/kernel/setup_64.c index 524b6850b2c0..6dff1286ad8a 100644 --- a/trunk/arch/x86/kernel/setup_64.c +++ b/trunk/arch/x86/kernel/setup_64.c @@ -361,11 +361,6 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); -#ifdef CONFIG_PCI - if (pci_early_dump_regs) - early_dump_pci_devices(); -#endif - #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT if (init_ohci1394_dma_early) init_ohci1394_dma_on_all_controllers(); diff --git a/trunk/arch/x86/pci/common.c b/trunk/arch/x86/pci/common.c index d19fd07bafd6..6e64aaf00d1d 100644 --- a/trunk/arch/x86/pci/common.c +++ b/trunk/arch/x86/pci/common.c @@ -20,7 +20,6 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; -unsigned int pci_early_dump_regs; static int pci_bf_sort; int pci_routeirq; int pcibios_last_bus = -1; @@ -122,21 +121,6 @@ void __init dmi_check_skip_isa_align(void) dmi_check_system(can_skip_pciprobe_dmi_table); } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) -{ - struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE]; - - if (pci_probe & PCI_NOASSIGN_ROMS) { - if (rom_r->parent) - return; - if (rom_r->start) { - /* we deal with BIOS assigned ROM later */ - return; - } - rom_r->start = rom_r->end = rom_r->flags = 0; - } -} - /* * Called after each bus is probed, but before its children * are examined. @@ -144,11 +128,7 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) void __devinit pcibios_fixup_bus(struct pci_bus *b) { - struct pci_dev *dev; - pci_read_bridge_bases(b); - list_for_each_entry(dev, &b->devices, bus_list) - pcibios_fixup_device_resources(dev); } /* @@ -503,18 +483,12 @@ char * __devinit pcibios_setup(char *str) else if (!strcmp(str, "rom")) { pci_probe |= PCI_ASSIGN_ROMS; return NULL; - } else if (!strcmp(str, "norom")) { - pci_probe |= PCI_NOASSIGN_ROMS; - return NULL; } else if (!strcmp(str, "assign-busses")) { pci_probe |= PCI_ASSIGN_ALL_BUSSES; return NULL; } else if (!strcmp(str, "use_crs")) { pci_probe |= PCI_USE__CRS; return NULL; - } else if (!strcmp(str, "earlydump")) { - pci_early_dump_regs = 1; - return NULL; } else if (!strcmp(str, "routeirq")) { pci_routeirq = 1; return NULL; diff --git a/trunk/arch/x86/pci/early.c b/trunk/arch/x86/pci/early.c index 858dbe3399f9..42df4b6606df 100644 --- a/trunk/arch/x86/pci/early.c +++ b/trunk/arch/x86/pci/early.c @@ -49,14 +49,7 @@ void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) { PDprintk("%x writing to %x: %x\n", slot, offset, val); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - outb(val, 0xcfc + (offset&3)); -} - -void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val) -{ - PDprintk("%x writing to %x: %x\n", slot, offset, val); - outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); - outw(val, 0xcfc + (offset&2)); + outb(val, 0xcfc); } int early_pci_allowed(void) @@ -64,54 +57,3 @@ int early_pci_allowed(void) return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) == PCI_PROBE_CONF1; } - -void early_dump_pci_device(u8 bus, u8 slot, u8 func) -{ - int i; - int j; - u32 val; - - printk("PCI: %02x:%02x:%02x", bus, slot, func); - - for (i = 0; i < 256; i += 4) { - if (!(i & 0x0f)) - printk("\n%04x:",i); - - val = read_pci_config(bus, slot, func, i); - for (j = 0; j < 4; j++) { - printk(" %02x", val & 0xff); - val >>= 8; - } - } - printk("\n"); -} - -void early_dump_pci_devices(void) -{ - unsigned bus, slot, func; - - if (!early_pci_allowed()) - return; - - for (bus = 0; bus < 256; bus++) { - for (slot = 0; slot < 32; slot++) { - for (func = 0; func < 8; func++) { - u32 class; - u8 type; - class = read_pci_config(bus, slot, func, - PCI_CLASS_REVISION); - if (class == 0xffffffff) - break; - - early_dump_pci_device(bus, slot, func); - - /* No multi-function device? */ - type = read_pci_config_byte(bus, slot, func, - PCI_HEADER_TYPE); - if (!(type & 0x80)) - break; - } - } - } -} - diff --git a/trunk/arch/x86/pci/irq.c b/trunk/arch/x86/pci/irq.c index c422e10337be..ca8df9c260bc 100644 --- a/trunk/arch/x86/pci/irq.c +++ b/trunk/arch/x86/pci/irq.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -45,8 +45,7 @@ struct irq_router { char *name; u16 vendor, device; int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq); - int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, - int new); + int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); }; struct irq_router_handler { @@ -62,7 +61,7 @@ void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; * and perform checksum verification. */ -static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr) +static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr) { struct irq_routing_table *rt; int i; @@ -75,11 +74,10 @@ static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr) rt->size < sizeof(struct irq_routing_table)) return NULL; sum = 0; - for (i = 0; i < rt->size; i++) + for (i=0; i < rt->size; i++) sum += addr[i]; if (!sum) { - DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", - rt); + DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt); return rt; } return NULL; @@ -102,8 +100,7 @@ static struct irq_routing_table * __init pirq_find_routing_table(void) return rt; printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); } - for (addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); - addr += 16) { + for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { rt = pirq_check_routing_table(addr); if (rt) return rt; @@ -125,23 +122,20 @@ static void __init pirq_peer_trick(void) struct irq_info *e; memset(busmap, 0, sizeof(busmap)); - for (i = 0; i < (rt->size - sizeof(struct irq_routing_table)) / - sizeof(struct irq_info); i++) { + for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) { e = &rt->slots[i]; #ifdef DEBUG { int j; - DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, - e->devfn/8, e->slot); - for (j = 0; j < 4; j++) - DBG(" %d:%02x/%04x", j, e->irq[j].link, - e->irq[j].bitmap); + DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot); + for(j=0; j<4; j++) + DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap); DBG("\n"); } #endif busmap[e->bus] = 1; } - for (i = 1; i < 256; i++) { + for(i = 1; i < 256; i++) { int node; if (!busmap[i] || pci_find_bus(0, i)) continue; @@ -180,8 +174,7 @@ void eisa_set_level_irq(unsigned int irq) * Common IRQ routing practice: nibbles in config space, * offset by some magic constant. */ -static unsigned int -read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr) +static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr) { u8 x; unsigned reg = offset + (nr >> 1); @@ -190,8 +183,7 @@ read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr) return (nr & 1) ? (x >> 4) : (x & 0xf); } -static void write_config_nybble(struct pci_dev *router, unsigned offset, - unsigned nr, unsigned int val) +static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val) { u8 x; unsigned reg = offset + (nr >> 1); @@ -208,18 +200,15 @@ static void write_config_nybble(struct pci_dev *router, unsigned offset, */ static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, - 11, 0, 12, 0, 14, 0, 15 }; + static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; WARN_ON_ONCE(pirq > 16); return irqmap[read_config_nybble(router, 0x48, pirq-1)]; } -static int -pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, - 3, 9, 11, 0, 13, 15 }; + static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; unsigned int val = irqmap[irq]; WARN_ON_ONCE(pirq > 16); @@ -242,8 +231,7 @@ static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return (x < 16) ? x : 0; } -static int -pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { pci_write_config_byte(router, pirq, irq); return 1; @@ -259,8 +247,7 @@ static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq); } -static int -pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq); return 1; @@ -271,8 +258,7 @@ pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) * but without the ugly irq number munging. * However, for 82C586, nibble map is different . */ -static int -pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 }; @@ -280,8 +266,7 @@ pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return read_config_nybble(router, 0x55, pirqmap[pirq-1]); } -static int -pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 }; @@ -300,11 +285,10 @@ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq) static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; WARN_ON_ONCE(pirq > 4); - return read_config_nybble(router, 0x43, pirqmap[pirq-1]); + return read_config_nybble(router,0x43, pirqmap[pirq-1]); } -static int -pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; @@ -322,8 +306,7 @@ static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return read_config_nybble(router, 0xb8, pirq >> 4); } -static int -pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { write_config_nybble(router, 0xb8, pirq >> 4, irq); return 1; @@ -331,7 +314,7 @@ pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) /* * Cyrix: nibble offset 0x5C - * 0x5C bits 7:4 is INTB bits 3:0 is INTA + * 0x5C bits 7:4 is INTB bits 3:0 is INTA * 0x5D bits 7:4 is INTD bits 3:0 is INTC */ static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) @@ -339,8 +322,7 @@ static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return read_config_nybble(router, 0x5C, (pirq-1)^1); } -static int -pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { write_config_nybble(router, 0x5C, (pirq-1)^1, irq); return 1; @@ -368,7 +350,7 @@ pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) * Apparently there are systems implementing PCI routing table using * link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D. * We try our best to handle both link mappings. - * + * * Currently (2003-05-21) it appears most SiS chipsets follow the * definition of routing registers from the SiS-5595 southbridge. * According to the SiS 5595 datasheets the revision id's of the @@ -388,7 +370,7 @@ pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) * * 0x62: USBIRQ: * bit 6 OHCI function disabled (0), enabled (1) - * + * * 0x6a: ACPI/SCI IRQ: bits 4-6 reserved * * 0x7e: Data Acq. Module IRQ - bits 4-6 reserved @@ -423,8 +405,7 @@ static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK); } -static int -pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { u8 x; int reg; @@ -458,8 +439,7 @@ static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq) return read_config_nybble(router, 0x74, pirq-1); } -static int -pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { WARN_ON_ONCE(pirq >= 9); if (pirq > 8) { @@ -481,15 +461,13 @@ pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1, * and 0x03 for SMBus. */ -static int -pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { outb(pirq, 0xc00); return inb(0xc01) & 0xf; } -static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, - int pirq, int irq) +static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { outb(pirq, 0xc00); outb(irq, 0xc01); @@ -504,27 +482,27 @@ static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, * offset 0x56 0-3 PIRQA 4-7 PIRQB * offset 0x57 0-3 PIRQC 4-7 PIRQD */ -static int -pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { u8 irq; irq = 0; if (pirq <= 4) + { irq = read_config_nybble(router, 0x56, pirq - 1); - printk(KERN_INFO - "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", + } + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", dev->vendor, dev->device, pirq, irq); return irq; } -static int -pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - printk(KERN_INFO - "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", dev->vendor, dev->device, pirq, irq); if (pirq <= 4) + { write_config_nybble(router, 0x56, pirq - 1, irq); + } return 1; } @@ -550,8 +528,7 @@ static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq, #ifdef CONFIG_PCI_BIOS -static int -pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { struct pci_dev *bridge; int pin = pci_get_interrupt_pin(dev, &bridge); @@ -560,14 +537,11 @@ pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) #endif -static __init int -intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { static struct pci_device_id __initdata pirq_440gx[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_0) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, { }, }; @@ -575,49 +549,50 @@ intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) if (pci_dev_present(pirq_440gx)) return 0; - switch (device) { - case PCI_DEVICE_ID_INTEL_82371FB_0: - case PCI_DEVICE_ID_INTEL_82371SB_0: - case PCI_DEVICE_ID_INTEL_82371AB_0: - case PCI_DEVICE_ID_INTEL_82371MX: - case PCI_DEVICE_ID_INTEL_82443MX_0: - case PCI_DEVICE_ID_INTEL_82801AA_0: - case PCI_DEVICE_ID_INTEL_82801AB_0: - case PCI_DEVICE_ID_INTEL_82801BA_0: - case PCI_DEVICE_ID_INTEL_82801BA_10: - case PCI_DEVICE_ID_INTEL_82801CA_0: - case PCI_DEVICE_ID_INTEL_82801CA_12: - case PCI_DEVICE_ID_INTEL_82801DB_0: - case PCI_DEVICE_ID_INTEL_82801E_0: - case PCI_DEVICE_ID_INTEL_82801EB_0: - case PCI_DEVICE_ID_INTEL_ESB_1: - case PCI_DEVICE_ID_INTEL_ICH6_0: - case PCI_DEVICE_ID_INTEL_ICH6_1: - case PCI_DEVICE_ID_INTEL_ICH7_0: - case PCI_DEVICE_ID_INTEL_ICH7_1: - case PCI_DEVICE_ID_INTEL_ICH7_30: - case PCI_DEVICE_ID_INTEL_ICH7_31: - case PCI_DEVICE_ID_INTEL_ESB2_0: - case PCI_DEVICE_ID_INTEL_ICH8_0: - case PCI_DEVICE_ID_INTEL_ICH8_1: - case PCI_DEVICE_ID_INTEL_ICH8_2: - case PCI_DEVICE_ID_INTEL_ICH8_3: - case PCI_DEVICE_ID_INTEL_ICH8_4: - case PCI_DEVICE_ID_INTEL_ICH9_0: - case PCI_DEVICE_ID_INTEL_ICH9_1: - case PCI_DEVICE_ID_INTEL_ICH9_2: - case PCI_DEVICE_ID_INTEL_ICH9_3: - case PCI_DEVICE_ID_INTEL_ICH9_4: - case PCI_DEVICE_ID_INTEL_ICH9_5: - case PCI_DEVICE_ID_INTEL_TOLAPAI_0: - case PCI_DEVICE_ID_INTEL_ICH10_0: - case PCI_DEVICE_ID_INTEL_ICH10_1: - case PCI_DEVICE_ID_INTEL_ICH10_2: - case PCI_DEVICE_ID_INTEL_ICH10_3: - r->name = "PIIX/ICH"; - r->get = pirq_piix_get; - r->set = pirq_piix_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371SB_0: + case PCI_DEVICE_ID_INTEL_82371AB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + case PCI_DEVICE_ID_INTEL_82443MX_0: + case PCI_DEVICE_ID_INTEL_82801AA_0: + case PCI_DEVICE_ID_INTEL_82801AB_0: + case PCI_DEVICE_ID_INTEL_82801BA_0: + case PCI_DEVICE_ID_INTEL_82801BA_10: + case PCI_DEVICE_ID_INTEL_82801CA_0: + case PCI_DEVICE_ID_INTEL_82801CA_12: + case PCI_DEVICE_ID_INTEL_82801DB_0: + case PCI_DEVICE_ID_INTEL_82801E_0: + case PCI_DEVICE_ID_INTEL_82801EB_0: + case PCI_DEVICE_ID_INTEL_ESB_1: + case PCI_DEVICE_ID_INTEL_ICH6_0: + case PCI_DEVICE_ID_INTEL_ICH6_1: + case PCI_DEVICE_ID_INTEL_ICH7_0: + case PCI_DEVICE_ID_INTEL_ICH7_1: + case PCI_DEVICE_ID_INTEL_ICH7_30: + case PCI_DEVICE_ID_INTEL_ICH7_31: + case PCI_DEVICE_ID_INTEL_ESB2_0: + case PCI_DEVICE_ID_INTEL_ICH8_0: + case PCI_DEVICE_ID_INTEL_ICH8_1: + case PCI_DEVICE_ID_INTEL_ICH8_2: + case PCI_DEVICE_ID_INTEL_ICH8_3: + case PCI_DEVICE_ID_INTEL_ICH8_4: + case PCI_DEVICE_ID_INTEL_ICH9_0: + case PCI_DEVICE_ID_INTEL_ICH9_1: + case PCI_DEVICE_ID_INTEL_ICH9_2: + case PCI_DEVICE_ID_INTEL_ICH9_3: + case PCI_DEVICE_ID_INTEL_ICH9_4: + case PCI_DEVICE_ID_INTEL_ICH9_5: + case PCI_DEVICE_ID_INTEL_TOLAPAI_0: + case PCI_DEVICE_ID_INTEL_ICH10_0: + case PCI_DEVICE_ID_INTEL_ICH10_1: + case PCI_DEVICE_ID_INTEL_ICH10_2: + case PCI_DEVICE_ID_INTEL_ICH10_3: + r->name = "PIIX/ICH"; + r->get = pirq_piix_get; + r->set = pirq_piix_set; + return 1; } return 0; } @@ -631,7 +606,7 @@ static __init int via_router_probe(struct irq_router *r, * workarounds for some buggy BIOSes */ if (device == PCI_DEVICE_ID_VIA_82C586_0) { - switch (router->device) { + switch(router->device) { case PCI_DEVICE_ID_VIA_82C686: /* * Asus k7m bios wrongly reports 82C686A @@ -656,7 +631,7 @@ static __init int via_router_probe(struct irq_router *r, } } - switch (device) { + switch(device) { case PCI_DEVICE_ID_VIA_82C586_0: r->name = "VIA"; r->get = pirq_via586_get; @@ -677,89 +652,88 @@ static __init int via_router_probe(struct irq_router *r, return 0; } -static __init int -vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_VLSI_82C534: - r->name = "VLSI 82C534"; - r->get = pirq_vlsi_get; - r->set = pirq_vlsi_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_VLSI_82C534: + r->name = "VLSI 82C534"; + r->get = pirq_vlsi_get; + r->set = pirq_vlsi_set; + return 1; } return 0; } -static __init int serverworks_router_probe(struct irq_router *r, - struct pci_dev *router, u16 device) +static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_SERVERWORKS_OSB4: - case PCI_DEVICE_ID_SERVERWORKS_CSB5: - r->name = "ServerWorks"; - r->get = pirq_serverworks_get; - r->set = pirq_serverworks_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_SERVERWORKS_OSB4: + case PCI_DEVICE_ID_SERVERWORKS_CSB5: + r->name = "ServerWorks"; + r->get = pirq_serverworks_get; + r->set = pirq_serverworks_set; + return 1; } return 0; } -static __init int -sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { if (device != PCI_DEVICE_ID_SI_503) return 0; - + r->name = "SIS"; r->get = pirq_sis_get; r->set = pirq_sis_set; return 1; } -static __init int -cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_CYRIX_5520: - r->name = "NatSemi"; - r->get = pirq_cyrix_get; - r->set = pirq_cyrix_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_CYRIX_5520: + r->name = "NatSemi"; + r->get = pirq_cyrix_get; + r->set = pirq_cyrix_set; + return 1; } return 0; } -static __init int -opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_OPTI_82C700: - r->name = "OPTI"; - r->get = pirq_opti_get; - r->set = pirq_opti_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_OPTI_82C700: + r->name = "OPTI"; + r->get = pirq_opti_get; + r->set = pirq_opti_set; + return 1; } return 0; } -static __init int -ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_ITE_IT8330G_0: - r->name = "ITE"; - r->get = pirq_ite_get; - r->set = pirq_ite_set; - return 1; + switch(device) + { + case PCI_DEVICE_ID_ITE_IT8330G_0: + r->name = "ITE"; + r->get = pirq_ite_get; + r->set = pirq_ite_set; + return 1; } return 0; } -static __init int -ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { + switch(device) + { case PCI_DEVICE_ID_AL_M1533: case PCI_DEVICE_ID_AL_M1563: printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n"); @@ -771,29 +745,28 @@ ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) return 0; } -static __init int -amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) +static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - switch (device) { - case PCI_DEVICE_ID_AMD_VIPER_740B: - r->name = "AMD756"; - break; - case PCI_DEVICE_ID_AMD_VIPER_7413: - r->name = "AMD766"; - break; - case PCI_DEVICE_ID_AMD_VIPER_7443: - r->name = "AMD768"; - break; - default: - return 0; + switch(device) + { + case PCI_DEVICE_ID_AMD_VIPER_740B: + r->name = "AMD756"; + break; + case PCI_DEVICE_ID_AMD_VIPER_7413: + r->name = "AMD766"; + break; + case PCI_DEVICE_ID_AMD_VIPER_7443: + r->name = "AMD768"; + break; + default: + return 0; } r->get = pirq_amd756_get; r->set = pirq_amd756_set; return 1; } - -static __init int -pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) + +static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { switch (device) { case PCI_DEVICE_ID_PICOPOWER_PT86C523: @@ -834,7 +807,7 @@ static struct pci_dev *pirq_router_dev; * FIXME: should we have an option to say "generic for * chipset" ? */ - + static void __init pirq_find_router(struct irq_router *r) { struct irq_routing_table *rt = pirq_table; @@ -853,7 +826,7 @@ static void __init pirq_find_router(struct irq_router *r) r->name = "default"; r->get = NULL; r->set = NULL; - + DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n", rt->rtr_vendor, rt->rtr_device); @@ -864,14 +837,12 @@ static void __init pirq_find_router(struct irq_router *r) return; } - for (h = pirq_routers; h->vendor; h++) { + for( h = pirq_routers; h->vendor; h++) { /* First look for a router match */ - if (rt->rtr_vendor == h->vendor && - h->probe(r, pirq_router_dev, rt->rtr_device)) + if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device)) break; /* Fall back to a device match */ - if (pirq_router_dev->vendor == h->vendor && - h->probe(r, pirq_router_dev, pirq_router_dev->device)) + if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device)) break; } printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", @@ -886,13 +857,11 @@ static void __init pirq_find_router(struct irq_router *r) static struct irq_info *pirq_get_info(struct pci_dev *dev) { struct irq_routing_table *rt = pirq_table; - int entries = (rt->size - sizeof(struct irq_routing_table)) / - sizeof(struct irq_info); + int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); struct irq_info *info; for (info = rt->slots; entries--; info++) - if (info->bus == dev->bus->number && - PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) + if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) return info; return NULL; } @@ -920,7 +889,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) if (!pirq_table) return 0; - + DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin); info = pirq_get_info(dev); if (!info) { @@ -933,8 +902,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) DBG(" -> not routed\n" KERN_DEBUG); return 0; } - DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, - pirq_table->exclusive_irqs); + DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); mask &= pcibios_irq_mask; /* Work around broken HP Pavilion Notebooks which assign USB to @@ -947,8 +915,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) } /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */ - if (acer_tm360_irqrouting && dev->irq == 11 && - dev->vendor == PCI_VENDOR_ID_O2) { + if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) { pirq = 0x68; mask = 0x400; dev->irq = r->get(pirq_router_dev, dev, pirq); @@ -961,20 +928,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) */ newirq = dev->irq; if (newirq && !((1 << newirq) & mask)) { - if (pci_probe & PCI_USE_PIRQ_MASK) - newirq = 0; - else - printk("\n" KERN_WARNING - "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n" - KERN_DEBUG, newirq, - pci_name(dev)); + if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0; + else printk("\n" KERN_WARNING + "PCI: IRQ %i for device %s doesn't match PIRQ mask " + "- try pci=usepirqmask\n" KERN_DEBUG, newirq, + pci_name(dev)); } if (!newirq && assign) { for (i = 0; i < 16; i++) { if (!(mask & (1 << i))) continue; - if (pirq_penalty[i] < pirq_penalty[newirq] && - can_request_irq(i, IRQF_SHARED)) + if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED)) newirq = i; } } @@ -985,13 +949,12 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) irq = pirq & 0xf; DBG(" -> hardcoded IRQ %d\n", irq); msg = "Hardcoded"; - } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ - ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) { + } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ + ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) { DBG(" -> got IRQ %d\n", irq); msg = "Found"; eisa_set_level_irq(irq); - } else if (newirq && r->set && - (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { + } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { DBG(" -> assigning IRQ %d", newirq); if (r->set(pirq_router_dev, dev, pirq, newirq)) { eisa_set_level_irq(newirq); @@ -1009,8 +972,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) } else return 0; } - printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, - pci_name(dev)); + printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev)); /* Update IRQ for all devices with the same pirq value */ while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { @@ -1022,26 +984,20 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) if (!info) continue; if (info->irq[pin].link == pirq) { - /* - * We refuse to override the dev->irq - * information. Give a warning! - */ - if (dev2->irq && dev2->irq != irq && \ + /* We refuse to override the dev->irq information. Give a warning! */ + if ( dev2->irq && dev2->irq != irq && \ (!(pci_probe & PCI_USE_PIRQ_MASK) || \ - ((1 << dev2->irq) & mask))) { + ((1 << dev2->irq) & mask)) ) { #ifndef CONFIG_PCI_MSI - printk(KERN_INFO - "IRQ routing conflict for %s, have irq %d, want irq %d\n", - pci_name(dev2), dev2->irq, irq); + printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", + pci_name(dev2), dev2->irq, irq); #endif - continue; - } + continue; + } dev2->irq = irq; pirq_penalty[irq]++; if (dev != dev2) - printk(KERN_INFO - "PCI: Sharing IRQ %d with %s\n", - irq, pci_name(dev2)); + printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2)); } } return 1; @@ -1055,21 +1011,15 @@ static void __init pcibios_fixup_irqs(void) DBG(KERN_DEBUG "PCI: IRQ fixup\n"); while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { /* - * If the BIOS has set an out of range IRQ number, just - * ignore it. Also keep track of which IRQ's are - * already in use. + * If the BIOS has set an out of range IRQ number, just ignore it. + * Also keep track of which IRQ's are already in use. */ if (dev->irq >= 16) { - DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", - pci_name(dev), dev->irq); + DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq); dev->irq = 0; } - /* - * If the IRQ is already assigned to a PCI device, - * ignore its ISA use penalty - */ - if (pirq_penalty[dev->irq] >= 100 && - pirq_penalty[dev->irq] < 100000) + /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */ + if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000) pirq_penalty[dev->irq] = 0; pirq_penalty[dev->irq]++; } @@ -1081,40 +1031,31 @@ static void __init pcibios_fixup_irqs(void) /* * Recalculate IRQ numbers if we use the I/O APIC. */ - if (io_apic_assign_pci_irqs) { + if (io_apic_assign_pci_irqs) + { int irq; if (pin) { - /* - * interrupt pins are numbered starting - * from 1 - */ - pin--; - irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, - PCI_SLOT(dev->devfn), pin); + pin--; /* interrupt pins are numbered starting from 1 */ + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); /* * Busses behind bridges are typically not listed in the MP-table. * In this case we have to look up the IRQ based on the parent bus, * parent slot, and pin number. The SMP code detects such bridged * busses itself so we should get into this branch reliably. */ - if (irq < 0 && dev->bus->parent) { - /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; + if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ + struct pci_dev * bridge = dev->bus->self; pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), - pin); + irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, + PCI_SLOT(bridge->devfn), pin); if (irq >= 0) - printk(KERN_WARNING - "PCI: using PPB %s[%c] to get irq %d\n", - pci_name(bridge), - 'A' + pin, irq); + printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n", + pci_name(bridge), 'A' + pin, irq); } if (irq >= 0) { - printk(KERN_INFO - "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", + printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", pci_name(dev), 'A' + pin, irq); dev->irq = irq; } @@ -1137,8 +1078,7 @@ static int __init fix_broken_hp_bios_irq9(const struct dmi_system_id *d) { if (!broken_hp_bios_irq9) { broken_hp_bios_irq9 = 1; - printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", - d->ident); + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); } return 0; } @@ -1151,8 +1091,7 @@ static int __init fix_acer_tm360_irqrouting(const struct dmi_system_id *d) { if (!acer_tm360_irqrouting) { acer_tm360_irqrouting = 1; - printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", - d->ident); + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); } return 0; } @@ -1164,8 +1103,7 @@ static struct dmi_system_id __initdata pciirq_dmi_table[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"), - DMI_MATCH(DMI_PRODUCT_VERSION, - "HP Pavilion Notebook Model GE"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), }, }, @@ -1200,14 +1138,11 @@ static int __init pcibios_irq_init(void) pirq_find_router(&pirq_router); if (pirq_table->exclusive_irqs) { int i; - for (i = 0; i < 16; i++) + for (i=0; i<16; i++) if (!(pirq_table->exclusive_irqs & (1 << i))) pirq_penalty[i] += 100; } - /* - * If we're using the I/O APIC, avoid using the PCI IRQ - * routing table - */ + /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */ if (io_apic_assign_pci_irqs) pirq_table = NULL; } @@ -1254,40 +1189,33 @@ static int pirq_enable_irq(struct pci_dev *dev) if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg = ""; - pin--; /* interrupt pins are numbered starting from 1 */ + pin--; /* interrupt pins are numbered starting from 1 */ if (io_apic_assign_pci_irqs) { int irq; - irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, - PCI_SLOT(dev->devfn), pin); + irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); /* - * Busses behind bridges are typically not - * listed in the MP-table. In this case we have - * to look up the IRQ based on the parent bus, - * parent slot, and pin number. The SMP code - * detects such bridged busses itself so we - * should get into this branch reliably. + * Busses behind bridges are typically not listed in the MP-table. + * In this case we have to look up the IRQ based on the parent bus, + * parent slot, and pin number. The SMP code detects such bridged + * busses itself so we should get into this branch reliably. */ temp_dev = dev; - while (irq < 0 && dev->bus->parent) { - /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; + while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ + struct pci_dev * bridge = dev->bus->self; pin = (pin + PCI_SLOT(dev->devfn)) % 4; - irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, + irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, PCI_SLOT(bridge->devfn), pin); if (irq >= 0) - printk(KERN_WARNING - "PCI: using PPB %s[%c] to get irq %d\n", - pci_name(bridge), - 'A' + pin, irq); + printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n", + pci_name(bridge), 'A' + pin, irq); dev = bridge; } dev = temp_dev; if (irq >= 0) { - printk(KERN_INFO - "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", + printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", pci_name(dev), 'A' + pin, irq); dev->irq = irq; return 0; @@ -1298,17 +1226,12 @@ static int pirq_enable_irq(struct pci_dev *dev) else msg = " Please try using pci=biosirq."; - /* - * With IDE legacy devices the IRQ lookup failure is not - * a problem.. - */ - if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && - !(dev->class & 0x5)) + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) return 0; - printk(KERN_WARNING - "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", - 'A' + pin, pci_name(dev), msg); + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", + 'A' + pin, pci_name(dev), msg); } return 0; } diff --git a/trunk/arch/x86/pci/pci.h b/trunk/arch/x86/pci/pci.h index 291dafec07b7..720c4c554534 100644 --- a/trunk/arch/x86/pci/pci.h +++ b/trunk/arch/x86/pci/pci.h @@ -27,7 +27,6 @@ #define PCI_CAN_SKIP_ISA_ALIGN 0x8000 #define PCI_USE__CRS 0x10000 #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 -#define PCI_NOASSIGN_ROMS 0x40000 extern unsigned int pci_probe; extern unsigned long pirq_table_addr; diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 250d41a24f78..c52fca833268 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -338,15 +338,6 @@ config ACPI_EC the battery and thermal drivers. If you are compiling for a mobile system, say Y. -config ACPI_PCI_SLOT - tristate "PCI slot detection driver" - default n - help - This driver will attempt to discover all PCI slots in your system, - and creates entries in /sys/bus/pci/slots/. This feature can - help you correlate PCI bus addresses with the physical geography - of your slots. If you are unsure, say N. - config ACPI_POWER bool default y diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index 579c29c0665f..40b0fcae4c78 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_VIDEO) += video.o obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o -obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o diff --git a/trunk/drivers/acpi/pci_slot.c b/trunk/drivers/acpi/pci_slot.c deleted file mode 100644 index b9ab030a52d5..000000000000 --- a/trunk/drivers/acpi/pci_slot.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * pci_slot.c - ACPI PCI Slot Driver - * - * The code here is heavily leveraged from the acpiphp module. - * Thanks to Matthew Wilcox for much guidance. - * Thanks to Kenji Kaneshige for code - * review and fixes. - * - * Copyright (C) 2007 Alex Chiang - * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int debug; -static int check_sta_before_sun; - -#define DRIVER_VERSION "0.1" -#define DRIVER_AUTHOR "Alex Chiang " -#define DRIVER_DESC "ACPI PCI Slot Detection Driver" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(debug, bool, 0644); - -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_slot"); - -#define MY_NAME "pci_slot" -#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) -#define dbg(format, arg...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG "%s: " format, \ - MY_NAME , ## arg); \ - } while (0) - -#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */ - -struct acpi_pci_slot { - acpi_handle root_handle; /* handle of the root bridge */ - struct pci_slot *pci_slot; /* corresponding pci_slot */ - struct list_head list; /* node in the list of slots */ -}; - -static int acpi_pci_slot_add(acpi_handle handle); -static void acpi_pci_slot_remove(acpi_handle handle); - -static LIST_HEAD(slot_list); -static DEFINE_MUTEX(slot_list_lock); -static struct acpi_pci_driver acpi_pci_slot_driver = { - .add = acpi_pci_slot_add, - .remove = acpi_pci_slot_remove, -}; - -static int -check_slot(acpi_handle handle, int *device, unsigned long *sun) -{ - int retval = 0; - unsigned long adr, sta; - acpi_status status; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - dbg("Checking slot on path: %s\n", (char *)buffer.pointer); - - if (check_sta_before_sun) { - /* If SxFy doesn't have _STA, we just assume it's there */ - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT)) { - retval = -1; - goto out; - } - } - - status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - if (ACPI_FAILURE(status)) { - dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer); - retval = -1; - goto out; - } - - *device = (adr >> 16) & 0xffff; - - /* No _SUN == not a slot == bail */ - status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); - if (ACPI_FAILURE(status)) { - dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer); - retval = -1; - goto out; - } - -out: - kfree(buffer.pointer); - return retval; -} - -struct callback_args { - acpi_walk_callback user_function; /* only for walk_p2p_bridge */ - struct pci_bus *pci_bus; - acpi_handle root_handle; -}; - -/* - * register_slot - * - * Called once for each SxFy object in the namespace. Don't worry about - * calling pci_create_slot multiple times for the same pci_bus:device, - * since each subsequent call simply bumps the refcount on the pci_slot. - * - * The number of calls to pci_destroy_slot from unregister_slot is - * symmetrical. - */ -static acpi_status -register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int device; - unsigned long sun; - char name[SLOT_NAME_SIZE]; - struct acpi_pci_slot *slot; - struct pci_slot *pci_slot; - struct callback_args *parent_context = context; - struct pci_bus *pci_bus = parent_context->pci_bus; - - if (check_slot(handle, &device, &sun)) - return AE_OK; - - slot = kmalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) { - err("%s: cannot allocate memory\n", __func__); - return AE_OK; - } - - snprintf(name, sizeof(name), "%u", (u32)sun); - pci_slot = pci_create_slot(pci_bus, device, name); - if (IS_ERR(pci_slot)) { - err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); - kfree(slot); - } - - slot->root_handle = parent_context->root_handle; - slot->pci_slot = pci_slot; - INIT_LIST_HEAD(&slot->list); - mutex_lock(&slot_list_lock); - list_add(&slot->list, &slot_list); - mutex_unlock(&slot_list_lock); - - dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n", - pci_slot, pci_bus->number, device, name); - - return AE_OK; -} - -/* - * walk_p2p_bridge - discover and walk p2p bridges - * @handle: points to an acpi_pci_root - * @context: p2p_bridge_context pointer - * - * Note that when we call ourselves recursively, we pass a different - * value of pci_bus in the child_context. - */ -static acpi_status -walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int device, function; - unsigned long adr; - acpi_status status; - acpi_handle dummy_handle; - acpi_walk_callback user_function; - - struct pci_dev *dev; - struct pci_bus *pci_bus; - struct callback_args child_context; - struct callback_args *parent_context = context; - - pci_bus = parent_context->pci_bus; - user_function = parent_context->user_function; - - status = acpi_get_handle(handle, "_ADR", &dummy_handle); - if (ACPI_FAILURE(status)) - return AE_OK; - - status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - if (ACPI_FAILURE(status)) - return AE_OK; - - device = (adr >> 16) & 0xffff; - function = adr & 0xffff; - - dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); - if (!dev || !dev->subordinate) - goto out; - - child_context.pci_bus = dev->subordinate; - child_context.user_function = user_function; - child_context.root_handle = parent_context->root_handle; - - dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number); - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - user_function, &child_context, NULL); - if (ACPI_FAILURE(status)) - goto out; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - walk_p2p_bridge, &child_context, NULL); -out: - pci_dev_put(dev); - return AE_OK; -} - -/* - * walk_root_bridge - generic root bridge walker - * @handle: points to an acpi_pci_root - * @user_function: user callback for slot objects - * - * Call user_function for all objects underneath this root bridge. - * Walk p2p bridges underneath us and call user_function on those too. - */ -static int -walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) -{ - int seg, bus; - unsigned long tmp; - acpi_status status; - acpi_handle dummy_handle; - struct pci_bus *pci_bus; - struct callback_args context; - - /* If the bridge doesn't have _STA, we assume it is always there */ - status = acpi_get_handle(handle, "_STA", &dummy_handle); - if (ACPI_SUCCESS(status)) { - status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); - if (ACPI_FAILURE(status)) { - info("%s: _STA evaluation failure\n", __func__); - return 0; - } - if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0) - /* don't register this object */ - return 0; - } - - status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); - seg = ACPI_SUCCESS(status) ? tmp : 0; - - status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); - bus = ACPI_SUCCESS(status) ? tmp : 0; - - pci_bus = pci_find_bus(seg, bus); - if (!pci_bus) - return 0; - - context.pci_bus = pci_bus; - context.user_function = user_function; - context.root_handle = handle; - - dbg("root bridge walk, pci_bus = %x\n", pci_bus->number); - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - user_function, &context, NULL); - if (ACPI_FAILURE(status)) - return status; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - walk_p2p_bridge, &context, NULL); - if (ACPI_FAILURE(status)) - err("%s: walk_p2p_bridge failure - %d\n", __func__, status); - - return status; -} - -/* - * acpi_pci_slot_add - * @handle: points to an acpi_pci_root - */ -static int -acpi_pci_slot_add(acpi_handle handle) -{ - acpi_status status; - - status = walk_root_bridge(handle, register_slot); - if (ACPI_FAILURE(status)) - err("%s: register_slot failure - %d\n", __func__, status); - - return status; -} - -/* - * acpi_pci_slot_remove - * @handle: points to an acpi_pci_root - */ -static void -acpi_pci_slot_remove(acpi_handle handle) -{ - struct acpi_pci_slot *slot, *tmp; - - mutex_lock(&slot_list_lock); - list_for_each_entry_safe(slot, tmp, &slot_list, list) { - if (slot->root_handle == handle) { - list_del(&slot->list); - pci_destroy_slot(slot->pci_slot); - kfree(slot); - } - } - mutex_unlock(&slot_list_lock); -} - -static int do_sta_before_sun(const struct dmi_system_id *d) -{ - info("%s detected: will evaluate _STA before calling _SUN\n", d->ident); - check_sta_before_sun = 1; - return 0; -} - -static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { - /* - * Fujitsu Primequest machines will return 1023 to indicate an - * error if the _SUN method is evaluated on SxFy objects that - * are not present (as indicated by _STA), so for those machines, - * we want to check _STA before evaluating _SUN. - */ - { - .callback = do_sta_before_sun, - .ident = "Fujitsu PRIMEQUEST", - .matches = { - DMI_MATCH(DMI_BIOS_VENDOR, "FUJITSU LIMITED"), - DMI_MATCH(DMI_BIOS_VERSION, "PRIMEQUEST"), - }, - }, - {} -}; - -static int __init -acpi_pci_slot_init(void) -{ - dmi_check_system(acpi_pci_slot_dmi_table); - acpi_pci_register_driver(&acpi_pci_slot_driver); - return 0; -} - -static void __exit -acpi_pci_slot_exit(void) -{ - acpi_pci_unregister_driver(&acpi_pci_slot_driver); -} - -module_init(acpi_pci_slot_init); -module_exit(acpi_pci_slot_exit); diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index c3b0cd88d09f..fbd40e96ed14 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -369,8 +369,8 @@ int acpi_suspend(u32 acpi_state) /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state - * @dev: device to examine - * @wake: if set, the device should be able to wake up the system + * @dev: device to examine; its driver model wakeup flags control + * whether it should be able to wake up the system * @d_min_p: used to store the upper limit of allowed states range * Return value: preferred power state of the device on success, -ENODEV on * failure (ie. if there's no 'struct acpi_device' for @dev) @@ -388,7 +388,7 @@ int acpi_suspend(u32 acpi_state) * via @wake. */ -int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) +int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; @@ -427,7 +427,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (wake && adev->wakeup.state.enabled && + (device_may_wakeup(dev) && adev->wakeup.state.enabled && adev->wakeup.sleep_state <= acpi_target_sleep_state)) { acpi_status status; diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index 3f940393d6c7..911ec600fe71 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -453,8 +453,6 @@ int platform_driver_register(struct platform_driver *drv) drv->driver.suspend = platform_drv_suspend; if (drv->resume) drv->driver.resume = platform_drv_resume; - if (drv->pm) - drv->driver.pm = &drv->pm->base; return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(platform_driver_register); @@ -562,9 +560,7 @@ static int platform_match(struct device *dev, struct device_driver *drv) return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } -#ifdef CONFIG_PM_SLEEP - -static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) +static int platform_suspend(struct device *dev, pm_message_t mesg) { int ret = 0; @@ -574,7 +570,7 @@ static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) return ret; } -static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) +static int platform_suspend_late(struct device *dev, pm_message_t mesg) { struct platform_driver *drv = to_platform_driver(dev->driver); struct platform_device *pdev; @@ -587,7 +583,7 @@ static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) return ret; } -static int platform_legacy_resume_early(struct device *dev) +static int platform_resume_early(struct device *dev) { struct platform_driver *drv = to_platform_driver(dev->driver); struct platform_device *pdev; @@ -600,7 +596,7 @@ static int platform_legacy_resume_early(struct device *dev) return ret; } -static int platform_legacy_resume(struct device *dev) +static int platform_resume(struct device *dev) { int ret = 0; @@ -610,291 +606,15 @@ static int platform_legacy_resume(struct device *dev) return ret; } -static int platform_pm_prepare(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm && drv->pm->prepare) - ret = drv->pm->prepare(dev); - - return ret; -} - -static void platform_pm_complete(struct device *dev) -{ - struct device_driver *drv = dev->driver; - - if (drv && drv->pm && drv->pm->complete) - drv->pm->complete(dev); -} - -#ifdef CONFIG_SUSPEND - -static int platform_pm_suspend(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm) { - if (drv->pm->suspend) - ret = drv->pm->suspend(dev); - } else { - ret = platform_legacy_suspend(dev, PMSG_SUSPEND); - } - - return ret; -} - -static int platform_pm_suspend_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->suspend_noirq) - ret = pdrv->pm->suspend_noirq(dev); - } else { - ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND); - } - - return ret; -} - -static int platform_pm_resume(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm) { - if (drv->pm->resume) - ret = drv->pm->resume(dev); - } else { - ret = platform_legacy_resume(dev); - } - - return ret; -} - -static int platform_pm_resume_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->resume_noirq) - ret = pdrv->pm->resume_noirq(dev); - } else { - ret = platform_legacy_resume_early(dev); - } - - return ret; -} - -#else /* !CONFIG_SUSPEND */ - -#define platform_pm_suspend NULL -#define platform_pm_resume NULL -#define platform_pm_suspend_noirq NULL -#define platform_pm_resume_noirq NULL - -#endif /* !CONFIG_SUSPEND */ - -#ifdef CONFIG_HIBERNATION - -static int platform_pm_freeze(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->freeze) - ret = drv->pm->freeze(dev); - } else { - ret = platform_legacy_suspend(dev, PMSG_FREEZE); - } - - return ret; -} - -static int platform_pm_freeze_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->freeze_noirq) - ret = pdrv->pm->freeze_noirq(dev); - } else { - ret = platform_legacy_suspend_late(dev, PMSG_FREEZE); - } - - return ret; -} - -static int platform_pm_thaw(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm) { - if (drv->pm->thaw) - ret = drv->pm->thaw(dev); - } else { - ret = platform_legacy_resume(dev); - } - - return ret; -} - -static int platform_pm_thaw_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->thaw_noirq) - ret = pdrv->pm->thaw_noirq(dev); - } else { - ret = platform_legacy_resume_early(dev); - } - - return ret; -} - -static int platform_pm_poweroff(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm) { - if (drv->pm->poweroff) - ret = drv->pm->poweroff(dev); - } else { - ret = platform_legacy_suspend(dev, PMSG_HIBERNATE); - } - - return ret; -} - -static int platform_pm_poweroff_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->poweroff_noirq) - ret = pdrv->pm->poweroff_noirq(dev); - } else { - ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE); - } - - return ret; -} - -static int platform_pm_restore(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (drv && drv->pm) { - if (drv->pm->restore) - ret = drv->pm->restore(dev); - } else { - ret = platform_legacy_resume(dev); - } - - return ret; -} - -static int platform_pm_restore_noirq(struct device *dev) -{ - struct platform_driver *pdrv; - int ret = 0; - - if (!dev->driver) - return 0; - - pdrv = to_platform_driver(dev->driver); - if (pdrv->pm) { - if (pdrv->pm->restore_noirq) - ret = pdrv->pm->restore_noirq(dev); - } else { - ret = platform_legacy_resume_early(dev); - } - - return ret; -} - -#else /* !CONFIG_HIBERNATION */ - -#define platform_pm_freeze NULL -#define platform_pm_thaw NULL -#define platform_pm_poweroff NULL -#define platform_pm_restore NULL -#define platform_pm_freeze_noirq NULL -#define platform_pm_thaw_noirq NULL -#define platform_pm_poweroff_noirq NULL -#define platform_pm_restore_noirq NULL - -#endif /* !CONFIG_HIBERNATION */ - -struct pm_ext_ops platform_pm_ops = { - .base = { - .prepare = platform_pm_prepare, - .complete = platform_pm_complete, - .suspend = platform_pm_suspend, - .resume = platform_pm_resume, - .freeze = platform_pm_freeze, - .thaw = platform_pm_thaw, - .poweroff = platform_pm_poweroff, - .restore = platform_pm_restore, - }, - .suspend_noirq = platform_pm_suspend_noirq, - .resume_noirq = platform_pm_resume_noirq, - .freeze_noirq = platform_pm_freeze_noirq, - .thaw_noirq = platform_pm_thaw_noirq, - .poweroff_noirq = platform_pm_poweroff_noirq, - .restore_noirq = platform_pm_restore_noirq, -}; - -#define PLATFORM_PM_OPS_PTR &platform_pm_ops - -#else /* !CONFIG_PM_SLEEP */ - -#define PLATFORM_PM_OPS_PTR NULL - -#endif /* !CONFIG_PM_SLEEP */ - struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, - .pm = PLATFORM_PM_OPS_PTR, + .suspend = platform_suspend, + .suspend_late = platform_suspend_late, + .resume_early = platform_resume_early, + .resume = platform_resume, }; EXPORT_SYMBOL_GPL(platform_bus_type); diff --git a/trunk/drivers/base/power/main.c b/trunk/drivers/base/power/main.c index d571204aaff7..45cc3d9eacb8 100644 --- a/trunk/drivers/base/power/main.c +++ b/trunk/drivers/base/power/main.c @@ -12,9 +12,11 @@ * and add it to the list of power-controlled devices. sysfs entries for * controlling device power management will also be added. * - * A separate list is used for keeping track of power info, because the power - * domain dependencies may differ from the ancestral dependencies that the - * subsystem list maintains. + * A different set of lists than the global subsystem list are used to + * keep track of power info because we use different lists to hold + * devices based on what stage of the power management process they + * are in. The power domain dependencies may also differ from the + * ancestral dependencies that the subsystem list maintains. */ #include @@ -28,40 +30,31 @@ #include "power.h" /* - * The entries in the dpm_list list are in a depth first order, simply + * The entries in the dpm_active list are in a depth first order, simply * because children are guaranteed to be discovered after parents, and * are inserted at the back of the list on discovery. * + * All the other lists are kept in the same order, for consistency. + * However the lists aren't always traversed in the same order. + * Semaphores must be acquired from the top (i.e., front) down + * and released in the opposite order. Devices must be suspended + * from the bottom (i.e., end) up and resumed in the opposite order. + * That way no parent will be suspended while it still has an active + * child. + * * Since device_pm_add() may be called with a device semaphore held, * we must never try to acquire a device semaphore while holding * dpm_list_mutex. */ -LIST_HEAD(dpm_list); +LIST_HEAD(dpm_active); +static LIST_HEAD(dpm_off); +static LIST_HEAD(dpm_off_irq); static DEFINE_MUTEX(dpm_list_mtx); -/* - * Set once the preparation of devices for a PM transition has started, reset - * before starting to resume devices. Protected by dpm_list_mtx. - */ -static bool transition_started; - -/** - * device_pm_lock - lock the list of active devices used by the PM core - */ -void device_pm_lock(void) -{ - mutex_lock(&dpm_list_mtx); -} - -/** - * device_pm_unlock - unlock the list of active devices used by the PM core - */ -void device_pm_unlock(void) -{ - mutex_unlock(&dpm_list_mtx); -} +/* 'true' if all devices have been suspended, protected by dpm_list_mtx */ +static bool all_sleeping; /** * device_pm_add - add a device to the list of active devices @@ -75,25 +68,17 @@ int device_pm_add(struct device *dev) dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - if (dev->parent) { - if (dev->parent->power.status >= DPM_SUSPENDING) { - dev_warn(dev, "parent %s is sleeping, will not add\n", + if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { + if (dev->parent->power.sleeping) + dev_warn(dev, "parent %s is sleeping\n", dev->parent->bus_id); - WARN_ON(true); - } - } else if (transition_started) { - /* - * We refuse to register parentless devices while a PM - * transition is in progress in order to avoid leaving them - * unhandled down the road - */ + else + dev_warn(dev, "all devices are sleeping\n"); WARN_ON(true); } error = dpm_sysfs_add(dev); - if (!error) { - dev->power.status = DPM_ON; - list_add_tail(&dev->power.entry, &dpm_list); - } + if (!error) + list_add_tail(&dev->power.entry, &dpm_active); mutex_unlock(&dpm_list_mtx); return error; } @@ -115,243 +100,73 @@ void device_pm_remove(struct device *dev) mutex_unlock(&dpm_list_mtx); } -/** - * pm_op - execute the PM operation appropiate for given PM event - * @dev: Device. - * @ops: PM operations to choose from. - * @state: PM transition of the system being carried out. - */ -static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state) -{ - int error = 0; - - switch (state.event) { -#ifdef CONFIG_SUSPEND - case PM_EVENT_SUSPEND: - if (ops->suspend) { - error = ops->suspend(dev); - suspend_report_result(ops->suspend, error); - } - break; - case PM_EVENT_RESUME: - if (ops->resume) { - error = ops->resume(dev); - suspend_report_result(ops->resume, error); - } - break; -#endif /* CONFIG_SUSPEND */ -#ifdef CONFIG_HIBERNATION - case PM_EVENT_FREEZE: - case PM_EVENT_QUIESCE: - if (ops->freeze) { - error = ops->freeze(dev); - suspend_report_result(ops->freeze, error); - } - break; - case PM_EVENT_HIBERNATE: - if (ops->poweroff) { - error = ops->poweroff(dev); - suspend_report_result(ops->poweroff, error); - } - break; - case PM_EVENT_THAW: - case PM_EVENT_RECOVER: - if (ops->thaw) { - error = ops->thaw(dev); - suspend_report_result(ops->thaw, error); - } - break; - case PM_EVENT_RESTORE: - if (ops->restore) { - error = ops->restore(dev); - suspend_report_result(ops->restore, error); - } - break; -#endif /* CONFIG_HIBERNATION */ - default: - error = -EINVAL; - } - return error; -} - -/** - * pm_noirq_op - execute the PM operation appropiate for given PM event - * @dev: Device. - * @ops: PM operations to choose from. - * @state: PM transition of the system being carried out. - * - * The operation is executed with interrupts disabled by the only remaining - * functional CPU in the system. - */ -static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops, - pm_message_t state) -{ - int error = 0; - - switch (state.event) { -#ifdef CONFIG_SUSPEND - case PM_EVENT_SUSPEND: - if (ops->suspend_noirq) { - error = ops->suspend_noirq(dev); - suspend_report_result(ops->suspend_noirq, error); - } - break; - case PM_EVENT_RESUME: - if (ops->resume_noirq) { - error = ops->resume_noirq(dev); - suspend_report_result(ops->resume_noirq, error); - } - break; -#endif /* CONFIG_SUSPEND */ -#ifdef CONFIG_HIBERNATION - case PM_EVENT_FREEZE: - case PM_EVENT_QUIESCE: - if (ops->freeze_noirq) { - error = ops->freeze_noirq(dev); - suspend_report_result(ops->freeze_noirq, error); - } - break; - case PM_EVENT_HIBERNATE: - if (ops->poweroff_noirq) { - error = ops->poweroff_noirq(dev); - suspend_report_result(ops->poweroff_noirq, error); - } - break; - case PM_EVENT_THAW: - case PM_EVENT_RECOVER: - if (ops->thaw_noirq) { - error = ops->thaw_noirq(dev); - suspend_report_result(ops->thaw_noirq, error); - } - break; - case PM_EVENT_RESTORE: - if (ops->restore_noirq) { - error = ops->restore_noirq(dev); - suspend_report_result(ops->restore_noirq, error); - } - break; -#endif /* CONFIG_HIBERNATION */ - default: - error = -EINVAL; - } - return error; -} - -static char *pm_verb(int event) -{ - switch (event) { - case PM_EVENT_SUSPEND: - return "suspend"; - case PM_EVENT_RESUME: - return "resume"; - case PM_EVENT_FREEZE: - return "freeze"; - case PM_EVENT_QUIESCE: - return "quiesce"; - case PM_EVENT_HIBERNATE: - return "hibernate"; - case PM_EVENT_THAW: - return "thaw"; - case PM_EVENT_RESTORE: - return "restore"; - case PM_EVENT_RECOVER: - return "recover"; - default: - return "(unknown PM event)"; - } -} - -static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info) -{ - dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), - ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ? - ", may wakeup" : ""); -} - -static void pm_dev_err(struct device *dev, pm_message_t state, char *info, - int error) -{ - printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n", - kobject_name(&dev->kobj), pm_verb(state.event), info, error); -} - /*------------------------- Resume routines -------------------------*/ /** - * resume_device_noirq - Power on one device (early resume). + * resume_device_early - Power on one device (early resume). * @dev: Device. - * @state: PM transition of the system being carried out. * * Must be called with interrupts disabled. */ -static int resume_device_noirq(struct device *dev, pm_message_t state) +static int resume_device_early(struct device *dev) { int error = 0; TRACE_DEVICE(dev); TRACE_RESUME(0); - if (!dev->bus) - goto End; - - if (dev->bus->pm) { - pm_dev_dbg(dev, state, "EARLY "); - error = pm_noirq_op(dev, dev->bus->pm, state); - } else if (dev->bus->resume_early) { - pm_dev_dbg(dev, state, "legacy EARLY "); + if (dev->bus && dev->bus->resume_early) { + dev_dbg(dev, "EARLY resume\n"); error = dev->bus->resume_early(dev); } - End: + TRACE_RESUME(error); return error; } /** * dpm_power_up - Power on all regular (non-sysdev) devices. - * @state: PM transition of the system being carried out. * - * Execute the appropriate "noirq resume" callback for all devices marked - * as DPM_OFF_IRQ. + * Walk the dpm_off_irq list and power each device up. This + * is used for devices that required they be powered down with + * interrupts disabled. As devices are powered on, they are moved + * to the dpm_off list. * * Must be called with interrupts disabled and only one CPU running. */ -static void dpm_power_up(pm_message_t state) +static void dpm_power_up(void) { - struct device *dev; - list_for_each_entry(dev, &dpm_list, power.entry) - if (dev->power.status > DPM_OFF) { - int error; + while (!list_empty(&dpm_off_irq)) { + struct list_head *entry = dpm_off_irq.next; + struct device *dev = to_device(entry); - dev->power.status = DPM_OFF; - error = resume_device_noirq(dev, state); - if (error) - pm_dev_err(dev, state, " early", error); - } + list_move_tail(entry, &dpm_off); + resume_device_early(dev); + } } /** * device_power_up - Turn on all devices that need special attention. - * @state: PM transition of the system being carried out. * * Power on system devices, then devices that required we shut them down * with interrupts disabled. * * Must be called with interrupts disabled. */ -void device_power_up(pm_message_t state) +void device_power_up(void) { sysdev_resume(); - dpm_power_up(state); + dpm_power_up(); } EXPORT_SYMBOL_GPL(device_power_up); /** * resume_device - Restore state for one device. * @dev: Device. - * @state: PM transition of the system being carried out. + * */ -static int resume_device(struct device *dev, pm_message_t state) +static int resume_device(struct device *dev) { int error = 0; @@ -360,40 +175,21 @@ static int resume_device(struct device *dev, pm_message_t state) down(&dev->sem); - if (dev->bus) { - if (dev->bus->pm) { - pm_dev_dbg(dev, state, ""); - error = pm_op(dev, &dev->bus->pm->base, state); - } else if (dev->bus->resume) { - pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->resume(dev); - } - if (error) - goto End; + if (dev->bus && dev->bus->resume) { + dev_dbg(dev,"resuming\n"); + error = dev->bus->resume(dev); } - if (dev->type) { - if (dev->type->pm) { - pm_dev_dbg(dev, state, "type "); - error = pm_op(dev, dev->type->pm, state); - } else if (dev->type->resume) { - pm_dev_dbg(dev, state, "legacy type "); - error = dev->type->resume(dev); - } - if (error) - goto End; + if (!error && dev->type && dev->type->resume) { + dev_dbg(dev,"resuming\n"); + error = dev->type->resume(dev); } - if (dev->class) { - if (dev->class->pm) { - pm_dev_dbg(dev, state, "class "); - error = pm_op(dev, dev->class->pm, state); - } else if (dev->class->resume) { - pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->resume(dev); - } + if (!error && dev->class && dev->class->resume) { + dev_dbg(dev,"class resume\n"); + error = dev->class->resume(dev); } - End: + up(&dev->sem); TRACE_RESUME(error); @@ -402,161 +198,78 @@ static int resume_device(struct device *dev, pm_message_t state) /** * dpm_resume - Resume every device. - * @state: PM transition of the system being carried out. * - * Execute the appropriate "resume" callback for all devices the status of - * which indicates that they are inactive. - */ -static void dpm_resume(pm_message_t state) -{ - struct list_head list; - - INIT_LIST_HEAD(&list); - mutex_lock(&dpm_list_mtx); - transition_started = false; - while (!list_empty(&dpm_list)) { - struct device *dev = to_device(dpm_list.next); - - get_device(dev); - if (dev->power.status >= DPM_OFF) { - int error; - - dev->power.status = DPM_RESUMING; - mutex_unlock(&dpm_list_mtx); - - error = resume_device(dev, state); - - mutex_lock(&dpm_list_mtx); - if (error) - pm_dev_err(dev, state, "", error); - } else if (dev->power.status == DPM_SUSPENDING) { - /* Allow new children of the device to be registered */ - dev->power.status = DPM_RESUMING; - } - if (!list_empty(&dev->power.entry)) - list_move_tail(&dev->power.entry, &list); - put_device(dev); - } - list_splice(&list, &dpm_list); - mutex_unlock(&dpm_list_mtx); -} - -/** - * complete_device - Complete a PM transition for given device - * @dev: Device. - * @state: PM transition of the system being carried out. - */ -static void complete_device(struct device *dev, pm_message_t state) -{ - down(&dev->sem); - - if (dev->class && dev->class->pm && dev->class->pm->complete) { - pm_dev_dbg(dev, state, "completing class "); - dev->class->pm->complete(dev); - } - - if (dev->type && dev->type->pm && dev->type->pm->complete) { - pm_dev_dbg(dev, state, "completing type "); - dev->type->pm->complete(dev); - } - - if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) { - pm_dev_dbg(dev, state, "completing "); - dev->bus->pm->base.complete(dev); - } - - up(&dev->sem); -} - -/** - * dpm_complete - Complete a PM transition for all devices. - * @state: PM transition of the system being carried out. + * Resume the devices that have either not gone through + * the late suspend, or that did go through it but also + * went through the early resume. * - * Execute the ->complete() callbacks for all devices that are not marked - * as DPM_ON. + * Take devices from the dpm_off_list, resume them, + * and put them on the dpm_locked list. */ -static void dpm_complete(pm_message_t state) +static void dpm_resume(void) { - struct list_head list; - - INIT_LIST_HEAD(&list); mutex_lock(&dpm_list_mtx); - while (!list_empty(&dpm_list)) { - struct device *dev = to_device(dpm_list.prev); - - get_device(dev); - if (dev->power.status > DPM_ON) { - dev->power.status = DPM_ON; - mutex_unlock(&dpm_list_mtx); - - complete_device(dev, state); + all_sleeping = false; + while(!list_empty(&dpm_off)) { + struct list_head *entry = dpm_off.next; + struct device *dev = to_device(entry); - mutex_lock(&dpm_list_mtx); - } - if (!list_empty(&dev->power.entry)) - list_move(&dev->power.entry, &list); - put_device(dev); + list_move_tail(entry, &dpm_active); + dev->power.sleeping = false; + mutex_unlock(&dpm_list_mtx); + resume_device(dev); + mutex_lock(&dpm_list_mtx); } - list_splice(&list, &dpm_list); mutex_unlock(&dpm_list_mtx); } /** * device_resume - Restore state of each device in system. - * @state: PM transition of the system being carried out. * * Resume all the devices, unlock them all, and allow new * devices to be registered once again. */ -void device_resume(pm_message_t state) +void device_resume(void) { might_sleep(); - dpm_resume(state); - dpm_complete(state); + dpm_resume(); } EXPORT_SYMBOL_GPL(device_resume); /*------------------------- Suspend routines -------------------------*/ -/** - * resume_event - return a PM message representing the resume event - * corresponding to given sleep state. - * @sleep_state: PM message representing a sleep state. - */ -static pm_message_t resume_event(pm_message_t sleep_state) +static inline char *suspend_verb(u32 event) { - switch (sleep_state.event) { - case PM_EVENT_SUSPEND: - return PMSG_RESUME; - case PM_EVENT_FREEZE: - case PM_EVENT_QUIESCE: - return PMSG_RECOVER; - case PM_EVENT_HIBERNATE: - return PMSG_RESTORE; + switch (event) { + case PM_EVENT_SUSPEND: return "suspend"; + case PM_EVENT_FREEZE: return "freeze"; + case PM_EVENT_PRETHAW: return "prethaw"; + default: return "(unknown suspend event)"; } - return PMSG_ON; +} + +static void +suspend_device_dbg(struct device *dev, pm_message_t state, char *info) +{ + dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), + ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? + ", may wakeup" : ""); } /** - * suspend_device_noirq - Shut down one device (late suspend). + * suspend_device_late - Shut down one device (late suspend). * @dev: Device. - * @state: PM transition of the system being carried out. + * @state: Power state device is entering. * * This is called with interrupts off and only a single CPU running. */ -static int suspend_device_noirq(struct device *dev, pm_message_t state) +static int suspend_device_late(struct device *dev, pm_message_t state) { int error = 0; - if (!dev->bus) - return 0; - - if (dev->bus->pm) { - pm_dev_dbg(dev, state, "LATE "); - error = pm_noirq_op(dev, dev->bus->pm, state); - } else if (dev->bus->suspend_late) { - pm_dev_dbg(dev, state, "legacy LATE "); + if (dev->bus && dev->bus->suspend_late) { + suspend_device_dbg(dev, state, "LATE "); error = dev->bus->suspend_late(dev, state); suspend_report_result(dev->bus->suspend_late, error); } @@ -565,30 +278,37 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state) /** * device_power_down - Shut down special devices. - * @state: PM transition of the system being carried out. + * @state: Power state to enter. * - * Power down devices that require interrupts to be disabled. + * Power down devices that require interrupts to be disabled + * and move them from the dpm_off list to the dpm_off_irq list. * Then power down system devices. * * Must be called with interrupts disabled and only one CPU running. */ int device_power_down(pm_message_t state) { - struct device *dev; int error = 0; - list_for_each_entry_reverse(dev, &dpm_list, power.entry) { - error = suspend_device_noirq(dev, state); + while (!list_empty(&dpm_off)) { + struct list_head *entry = dpm_off.prev; + struct device *dev = to_device(entry); + + error = suspend_device_late(dev, state); if (error) { - pm_dev_err(dev, state, " late", error); + printk(KERN_ERR "Could not power down device %s: " + "error %d\n", + kobject_name(&dev->kobj), error); break; } - dev->power.status = DPM_OFF_IRQ; + if (!list_empty(&dev->power.entry)) + list_move(&dev->power.entry, &dpm_off_irq); } + if (!error) error = sysdev_suspend(state); if (error) - dpm_power_up(resume_event(state)); + dpm_power_up(); return error; } EXPORT_SYMBOL_GPL(device_power_down); @@ -596,7 +316,7 @@ EXPORT_SYMBOL_GPL(device_power_down); /** * suspend_device - Save state of one device. * @dev: Device. - * @state: PM transition of the system being carried out. + * @state: Power state device is entering. */ static int suspend_device(struct device *dev, pm_message_t state) { @@ -604,43 +324,24 @@ static int suspend_device(struct device *dev, pm_message_t state) down(&dev->sem); - if (dev->class) { - if (dev->class->pm) { - pm_dev_dbg(dev, state, "class "); - error = pm_op(dev, dev->class->pm, state); - } else if (dev->class->suspend) { - pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->suspend(dev, state); - suspend_report_result(dev->class->suspend, error); - } - if (error) - goto End; + if (dev->class && dev->class->suspend) { + suspend_device_dbg(dev, state, "class "); + error = dev->class->suspend(dev, state); + suspend_report_result(dev->class->suspend, error); } - if (dev->type) { - if (dev->type->pm) { - pm_dev_dbg(dev, state, "type "); - error = pm_op(dev, dev->type->pm, state); - } else if (dev->type->suspend) { - pm_dev_dbg(dev, state, "legacy type "); - error = dev->type->suspend(dev, state); - suspend_report_result(dev->type->suspend, error); - } - if (error) - goto End; + if (!error && dev->type && dev->type->suspend) { + suspend_device_dbg(dev, state, "type "); + error = dev->type->suspend(dev, state); + suspend_report_result(dev->type->suspend, error); } - if (dev->bus) { - if (dev->bus->pm) { - pm_dev_dbg(dev, state, ""); - error = pm_op(dev, &dev->bus->pm->base, state); - } else if (dev->bus->suspend) { - pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->suspend(dev, state); - suspend_report_result(dev->bus->suspend, error); - } + if (!error && dev->bus && dev->bus->suspend) { + suspend_device_dbg(dev, state, ""); + error = dev->bus->suspend(dev, state); + suspend_report_result(dev->bus->suspend, error); } - End: + up(&dev->sem); return error; @@ -648,141 +349,67 @@ static int suspend_device(struct device *dev, pm_message_t state) /** * dpm_suspend - Suspend every device. - * @state: PM transition of the system being carried out. + * @state: Power state to put each device in. * - * Execute the appropriate "suspend" callbacks for all devices. + * Walk the dpm_locked list. Suspend each device and move it + * to the dpm_off list. + * + * (For historical reasons, if it returns -EAGAIN, that used to mean + * that the device would be called again with interrupts disabled. + * These days, we use the "suspend_late()" callback for that, so we + * print a warning and consider it an error). */ static int dpm_suspend(pm_message_t state) { - struct list_head list; int error = 0; - INIT_LIST_HEAD(&list); mutex_lock(&dpm_list_mtx); - while (!list_empty(&dpm_list)) { - struct device *dev = to_device(dpm_list.prev); + while (!list_empty(&dpm_active)) { + struct list_head *entry = dpm_active.prev; + struct device *dev = to_device(entry); - get_device(dev); - mutex_unlock(&dpm_list_mtx); + WARN_ON(dev->parent && dev->parent->power.sleeping); + dev->power.sleeping = true; + mutex_unlock(&dpm_list_mtx); error = suspend_device(dev, state); - mutex_lock(&dpm_list_mtx); if (error) { - pm_dev_err(dev, state, "", error); - put_device(dev); + printk(KERN_ERR "Could not suspend device %s: " + "error %d%s\n", + kobject_name(&dev->kobj), + error, + (error == -EAGAIN ? + " (please convert to suspend_late)" : + "")); + dev->power.sleeping = false; break; } - dev->power.status = DPM_OFF; if (!list_empty(&dev->power.entry)) - list_move(&dev->power.entry, &list); - put_device(dev); + list_move(&dev->power.entry, &dpm_off); } - list_splice(&list, dpm_list.prev); + if (!error) + all_sleeping = true; mutex_unlock(&dpm_list_mtx); - return error; -} - -/** - * prepare_device - Execute the ->prepare() callback(s) for given device. - * @dev: Device. - * @state: PM transition of the system being carried out. - */ -static int prepare_device(struct device *dev, pm_message_t state) -{ - int error = 0; - - down(&dev->sem); - - if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) { - pm_dev_dbg(dev, state, "preparing "); - error = dev->bus->pm->base.prepare(dev); - suspend_report_result(dev->bus->pm->base.prepare, error); - if (error) - goto End; - } - - if (dev->type && dev->type->pm && dev->type->pm->prepare) { - pm_dev_dbg(dev, state, "preparing type "); - error = dev->type->pm->prepare(dev); - suspend_report_result(dev->type->pm->prepare, error); - if (error) - goto End; - } - - if (dev->class && dev->class->pm && dev->class->pm->prepare) { - pm_dev_dbg(dev, state, "preparing class "); - error = dev->class->pm->prepare(dev); - suspend_report_result(dev->class->pm->prepare, error); - } - End: - up(&dev->sem); - - return error; -} -/** - * dpm_prepare - Prepare all devices for a PM transition. - * @state: PM transition of the system being carried out. - * - * Execute the ->prepare() callback for all devices. - */ -static int dpm_prepare(pm_message_t state) -{ - struct list_head list; - int error = 0; - - INIT_LIST_HEAD(&list); - mutex_lock(&dpm_list_mtx); - transition_started = true; - while (!list_empty(&dpm_list)) { - struct device *dev = to_device(dpm_list.next); - - get_device(dev); - dev->power.status = DPM_PREPARING; - mutex_unlock(&dpm_list_mtx); - - error = prepare_device(dev, state); - - mutex_lock(&dpm_list_mtx); - if (error) { - dev->power.status = DPM_ON; - if (error == -EAGAIN) { - put_device(dev); - continue; - } - printk(KERN_ERR "PM: Failed to prepare device %s " - "for power transition: error %d\n", - kobject_name(&dev->kobj), error); - put_device(dev); - break; - } - dev->power.status = DPM_SUSPENDING; - if (!list_empty(&dev->power.entry)) - list_move_tail(&dev->power.entry, &list); - put_device(dev); - } - list_splice(&list, &dpm_list); - mutex_unlock(&dpm_list_mtx); return error; } /** * device_suspend - Save state and stop all devices in system. - * @state: PM transition of the system being carried out. + * @state: new power management state * - * Prepare and suspend all devices. + * Prevent new devices from being registered, then lock all devices + * and suspend them. */ int device_suspend(pm_message_t state) { int error; might_sleep(); - error = dpm_prepare(state); - if (!error) - error = dpm_suspend(state); + error = dpm_suspend(state); if (error) - device_resume(resume_event(state)); + device_resume(); return error; } EXPORT_SYMBOL_GPL(device_suspend); diff --git a/trunk/drivers/base/power/power.h b/trunk/drivers/base/power/power.h index a3252c0e2887..a6894f2a4b99 100644 --- a/trunk/drivers/base/power/power.h +++ b/trunk/drivers/base/power/power.h @@ -4,7 +4,7 @@ * main.c */ -extern struct list_head dpm_list; /* The active device list */ +extern struct list_head dpm_active; /* The active device list */ static inline struct device *to_device(struct list_head *entry) { diff --git a/trunk/drivers/base/power/trace.c b/trunk/drivers/base/power/trace.c index 8c1e656b5f8b..2b4b392dcbc1 100644 --- a/trunk/drivers/base/power/trace.c +++ b/trunk/drivers/base/power/trace.c @@ -188,9 +188,9 @@ static int show_file_hash(unsigned int value) static int show_dev_hash(unsigned int value) { int match = 0; - struct list_head *entry = dpm_list.prev; + struct list_head * entry = dpm_active.prev; - while (entry != &dpm_list) { + while (entry != &dpm_active) { struct device * dev = to_device(entry); unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); if (hash == value) { diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index b4f3aefa12b6..1607536ff5fb 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -1028,6 +1028,7 @@ endif config BLK_DEV_HD_ONLY bool "Old hard disk (MFM/RLL/IDE) driver" + depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN help There are two drivers for MFM/RLL/IDE hard disks. Most people use the newer enhanced driver, but this old one is still around for two diff --git a/trunk/drivers/ide/arm/bast-ide.c b/trunk/drivers/ide/arm/bast-ide.c index 713cef20622e..8e8c28104b45 100644 --- a/trunk/drivers/ide/arm/bast-ide.c +++ b/trunk/drivers/ide/arm/bast-ide.c @@ -42,6 +42,7 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq) hw.io_ports.ctl_addr = aux + (6 * 0x20); hw.irq = irq; + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif == NULL) diff --git a/trunk/drivers/ide/arm/ide_arm.c b/trunk/drivers/ide/arm/ide_arm.c index 4263ffd4ab20..2f311da4c963 100644 --- a/trunk/drivers/ide/arm/ide_arm.c +++ b/trunk/drivers/ide/arm/ide_arm.c @@ -49,6 +49,7 @@ static int __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = IDE_ARM_IRQ; + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif) { diff --git a/trunk/drivers/ide/arm/palm_bk3710.c b/trunk/drivers/ide/arm/palm_bk3710.c index 96378ebfb31f..d024ac8fad14 100644 --- a/trunk/drivers/ide/arm/palm_bk3710.c +++ b/trunk/drivers/ide/arm/palm_bk3710.c @@ -409,9 +409,6 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev) ide_device_add(idx, &palm_bk3710_port_info); - if (!hwif->present) - goto out; - return 0; out: printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c index a6073e248f45..9134488ac043 100644 --- a/trunk/drivers/ide/ide-generic.c +++ b/trunk/drivers/ide/ide-generic.c @@ -125,6 +125,7 @@ static int __init ide_generic_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io_addr, io_addr + 0x206); hw.irq = ide_default_irq(io_addr); + hw.chipset = ide_generic; ide_init_port_hw(hwif, &hw); idx[i] = i; diff --git a/trunk/drivers/ide/ide-pnp.c b/trunk/drivers/ide/ide-pnp.c index 6a8953f68e9f..adbd01784162 100644 --- a/trunk/drivers/ide/ide-pnp.c +++ b/trunk/drivers/ide/ide-pnp.c @@ -55,6 +55,7 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = pnp_irq(dev, 0); + hw.chipset = ide_generic; hwif = ide_find_port(); if (hwif) { diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 655ec7ef568a..380fa0c8cc84 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1333,8 +1333,7 @@ static void ide_port_init_devices(ide_hwif_t *hwif) static void ide_init_port(ide_hwif_t *hwif, unsigned int port, const struct ide_port_info *d) { - if (d->chipset != ide_etrax100) - hwif->channel = port; + hwif->channel = port; if (d->chipset) hwif->chipset = d->chipset; @@ -1519,7 +1518,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) continue; } - if (d->chipset != ide_etrax100 && (i & 1) && mate) { + if ((i & 1) && mate) { hwif->mate = mate; mate->mate = hwif; } @@ -1665,6 +1664,7 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, ide_std_init_ports(hw, base, ctl); hw->irq = irq; + hw->chipset = d->chipset; hwif = ide_find_port_slot(d); if (hwif) { diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c index 8d6ad812a014..55ec7f798772 100644 --- a/trunk/drivers/ide/ide-proc.c +++ b/trunk/drivers/ide/ide-proc.c @@ -63,7 +63,6 @@ static int proc_ide_read_imodel case ide_pmac: name = "mac-io"; break; case ide_au1xxx: name = "au1xxx"; break; case ide_palm3710: name = "palm3710"; break; - case ide_etrax100: name = "etrax100"; break; case ide_acorn: name = "acorn"; break; default: name = "(unknown)"; break; } diff --git a/trunk/drivers/ide/legacy/buddha.c b/trunk/drivers/ide/legacy/buddha.c index 5c730e4dd735..9a1d27ef3f8a 100644 --- a/trunk/drivers/ide/legacy/buddha.c +++ b/trunk/drivers/ide/legacy/buddha.c @@ -138,6 +138,8 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } /* diff --git a/trunk/drivers/ide/legacy/falconide.c b/trunk/drivers/ide/legacy/falconide.c index 9e449a0c623f..af11028b4794 100644 --- a/trunk/drivers/ide/legacy/falconide.c +++ b/trunk/drivers/ide/legacy/falconide.c @@ -81,6 +81,8 @@ static void __init falconide_setup_ports(hw_regs_t *hw) hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; + + hw->chipset = ide_generic; } /* diff --git a/trunk/drivers/ide/legacy/gayle.c b/trunk/drivers/ide/legacy/gayle.c index a9c2593a898c..fed7d812761c 100644 --- a/trunk/drivers/ide/legacy/gayle.c +++ b/trunk/drivers/ide/legacy/gayle.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,10 @@ GAYLE_NUM_HWIFS-1) #define GAYLE_HAS_CONTROL_REG (!ide_doubler) #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) + int ide_doubler = 0; /* support IDE doublers? */ +EXPORT_SYMBOL_GPL(ide_doubler); + module_param_named(doubler, ide_doubler, bool, 0); MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ @@ -112,6 +116,8 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } /* diff --git a/trunk/drivers/ide/legacy/macide.c b/trunk/drivers/ide/legacy/macide.c index caa2632dd08e..2e84290d0bcc 100644 --- a/trunk/drivers/ide/legacy/macide.c +++ b/trunk/drivers/ide/legacy/macide.c @@ -78,6 +78,8 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const char *mac_ide_name[] = diff --git a/trunk/drivers/ide/legacy/q40ide.c b/trunk/drivers/ide/legacy/q40ide.c index 6f535d00e638..8ff6e2d20834 100644 --- a/trunk/drivers/ide/legacy/q40ide.c +++ b/trunk/drivers/ide/legacy/q40ide.c @@ -70,6 +70,8 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static void q40ide_input_data(ide_drive_t *drive, struct request *rq, diff --git a/trunk/drivers/ide/pci/cmd640.c b/trunk/drivers/ide/pci/cmd640.c index aaf38109eaec..b38a1980dcd5 100644 --- a/trunk/drivers/ide/pci/cmd640.c +++ b/trunk/drivers/ide/pci/cmd640.c @@ -747,9 +747,11 @@ static int __init cmd640x_init(void) ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; + hw[0].chipset = ide_cmd640; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; + hw[1].chipset = ide_cmd640; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); diff --git a/trunk/drivers/ide/pci/delkin_cb.c b/trunk/drivers/ide/pci/delkin_cb.c index b9e457996d0e..af0f30051d5a 100644 --- a/trunk/drivers/ide/pci/delkin_cb.c +++ b/trunk/drivers/ide/pci/delkin_cb.c @@ -47,13 +47,18 @@ static const struct ide_port_ops delkin_cb_port_ops = { .quirkproc = ide_undecoded_slave, }; +static const struct ide_port_info delkin_cb_port_info = { + .port_ops = &delkin_cb_port_ops, + .host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS | + IDE_HFLAG_NO_DMA, +}; + static int __devinit delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) { unsigned long base; hw_regs_t hw; ide_hwif_t *hwif = NULL; - ide_drive_t *drive; int i, rc; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; @@ -79,6 +84,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base + 0x10, base + 0x1e); hw.irq = dev->irq; + hw.dev = &dev->dev; hw.chipset = ide_pci; /* this enables IRQ sharing */ hwif = ide_find_port(); @@ -89,26 +95,16 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); - hwif->port_ops = &delkin_cb_port_ops; idx[0] = i; - ide_device_add(idx, NULL); - - if (!hwif->present) - goto out_disable; + ide_device_add(idx, &delkin_cb_port_info); pci_set_drvdata(dev, hwif); - hwif->dev = &dev->dev; - drive = &hwif->drives[0]; - if (drive->present) { - drive->io_32bit = 1; - drive->unmask = 1; - } + return 0; out_disable: - printk(KERN_ERR "delkin_cb: no IDE devices found\n"); pci_release_regions(dev); pci_disable_device(dev); return -ENODEV; @@ -139,14 +135,12 @@ static struct pci_driver driver = { .remove = delkin_cb_remove, }; -static int -delkin_cb_init (void) +static int __init delkin_cb_init(void) { return pci_register_driver(&driver); } -static void -delkin_cb_exit (void) +static void __exit delkin_cb_exit(void) { pci_unregister_driver(&driver); } diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index 4b0b85d8faf5..e127eb25ab63 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -569,6 +569,11 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi { struct ide_port_info d = sis5513_chipset; u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + int rc; + + rc = pci_enable_device(dev); + if (rc) + return rc; if (sis_find_family(dev) == 0) return -ENOTSUPP; diff --git a/trunk/drivers/ide/ppc/mpc8xx.c b/trunk/drivers/ide/ppc/mpc8xx.c index f0e638dcc3ab..236f9c38e519 100644 --- a/trunk/drivers/ide/ppc/mpc8xx.c +++ b/trunk/drivers/ide/ppc/mpc8xx.c @@ -303,6 +303,8 @@ static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) pcmp->pcmc_per = 0x100000 >> (16 * _slot_); #endif /* CONFIG_IDE_8xx_PCCARD */ + hw->chipset = ide_generic; + return 0; } #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ @@ -377,6 +379,8 @@ static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= (0x80000000 >> ioport_dsc[data_port].irq); + hw->chipset = ide_generic; + return 0; } #endif /* CONFIG_IDE_8xx_DIRECT */ diff --git a/trunk/drivers/pci/Makefile b/trunk/drivers/pci/Makefile index 7d63f8ced24b..4d1ce2e7361e 100644 --- a/trunk/drivers/pci/Makefile +++ b/trunk/drivers/pci/Makefile @@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \ +obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o obj-$(CONFIG_PROC_FS) += proc.o diff --git a/trunk/drivers/pci/hotplug/acpi_pcihp.c b/trunk/drivers/pci/hotplug/acpi_pcihp.c index 93e37f0666ab..f8c187a763bd 100644 --- a/trunk/drivers/pci/hotplug/acpi_pcihp.c +++ b/trunk/drivers/pci/hotplug/acpi_pcihp.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -300,7 +299,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) * * @handle - the handle of the hotplug controller. */ -static acpi_status acpi_run_oshp(acpi_handle handle) +acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -323,6 +322,9 @@ static acpi_status acpi_run_oshp(acpi_handle handle) kfree(string.pointer); return status; } +EXPORT_SYMBOL_GPL(acpi_run_oshp); + + /* acpi_get_hp_params_from_firmware * @@ -372,85 +374,6 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, } EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); -/** - * acpi_get_hp_hw_control_from_firmware - * @dev: the pci_dev of the bridge that has a hotplug controller - * @flags: requested control bits for _OSC - * - * Attempt to take hotplug control from firmware. - */ -int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) -{ - acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); - struct pci_dev *pdev = dev; - struct pci_bus *parent; - struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; - - flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_SHPC_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - if (!flags) { - err("Invalid flags %u specified!\n", flags); - return -EINVAL; - } - - /* - * Per PCI firmware specification, we should run the ACPI _OSC - * method to get control of hotplug hardware before using it. If - * an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, - * upto the host bridge under which this controller exists. - */ - while (!handle) { - /* - * This hotplug controller was not listed in the ACPI name - * space at all. Try to get acpi handle of parent pci bus. - */ - if (!pdev || !pdev->bus->parent) - break; - parent = pdev->bus->parent; - dbg("Could not find %s in acpi namespace, trying parent\n", - pci_name(pdev)); - if (!parent->self) - /* Parent must be a host bridge */ - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(parent), - parent->number); - else - handle = DEVICE_ACPI_HANDLE(&(parent->self->dev)); - pdev = parent->self; - } - - while (handle) { - acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); - dbg("Trying to get hotplug control for %s \n", - (char *)string.pointer); - status = pci_osc_control_set(handle, flags); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), (char *)string.pointer); - kfree(string.pointer); - return 0; - } - if (acpi_root_bridge(handle)) - break; - chandle = handle; - status = acpi_get_parent(chandle, &handle); - if (ACPI_FAILURE(status)) - break; - } - - dbg("Cannot get control of hotplug hardware for pci %s\n", - pci_name(dev)); - - kfree(string.pointer); - return -ENODEV; -} -EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); /* acpi_root_bridge - check to see if this acpi object is a root bridge * diff --git a/trunk/drivers/pci/hotplug/acpiphp.h b/trunk/drivers/pci/hotplug/acpiphp.h index eecf7cbf4139..7a29164d4b32 100644 --- a/trunk/drivers/pci/hotplug/acpiphp.h +++ b/trunk/drivers/pci/hotplug/acpiphp.h @@ -215,6 +215,7 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); +extern u32 acpiphp_get_address (struct acpiphp_slot *slot); /* variables */ extern int acpiphp_debug; diff --git a/trunk/drivers/pci/hotplug/acpiphp_core.c b/trunk/drivers/pci/hotplug/acpiphp_core.c index 0e496e866a84..7af68ba27903 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_core.c +++ b/trunk/drivers/pci/hotplug/acpiphp_core.c @@ -70,6 +70,7 @@ static int disable_slot (struct hotplug_slot *slot); static int set_attention_status (struct hotplug_slot *slot, u8 value); static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); @@ -82,6 +83,7 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, }; @@ -272,6 +274,23 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) return 0; } + +/** + * get_address - get pci address of a slot + * @hotplug_slot: slot to get status + * @value: pointer to struct pci_busdev (seg, bus, dev) + */ +static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = hotplug_slot->private; + + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + + *value = acpiphp_get_address(slot->acpi_slot); + + return 0; +} + static int __init init_acpi(void) { int retval; @@ -338,11 +357,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) acpiphp_slot->slot = slot; snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun); - retval = pci_hp_register(slot->hotplug_slot, - acpiphp_slot->bridge->pci_bus, - acpiphp_slot->device); - if (retval == -EBUSY) - goto error_hpslot; + retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); goto error_hpslot; diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index 9342c848db29..648596d469f6 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -258,12 +258,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) bridge->pci_bus->number, slot->device); retval = acpiphp_register_hotplug_slot(slot); if (retval) { - if (retval == -EBUSY) - warn("Slot %d already registered by another " - "hotplug driver\n", slot->sun); - else - warn("acpiphp_register_hotplug_slot failed " - "(err code = 0x%x)\n", retval); + warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); goto err_exit; } } @@ -1872,3 +1867,19 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) return (sta == 0) ? 0 : 1; } + + +/* + * pci address (seg/bus/dev) + */ +u32 acpiphp_get_address(struct acpiphp_slot *slot) +{ + u32 address; + struct pci_bus *pci_bus = slot->bridge->pci_bus; + + address = (pci_domain_nr(pci_bus) << 16) | + (pci_bus->number << 8) | + slot->device; + + return address; +} diff --git a/trunk/drivers/pci/hotplug/acpiphp_ibm.c b/trunk/drivers/pci/hotplug/acpiphp_ibm.c index 2b7c45e39370..ede9051fdb5d 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_ibm.c +++ b/trunk/drivers/pci/hotplug/acpiphp_ibm.c @@ -33,10 +33,8 @@ #include #include #include -#include #include "acpiphp.h" -#include "../pci.h" #define DRIVER_VERSION "1.0.1" #define DRIVER_AUTHOR "Irene Zubarev , Vernon Mauery " @@ -432,7 +430,7 @@ static int __init ibm_acpiphp_init(void) int retval = 0; acpi_status status; struct acpi_device *device; - struct kobject *sysdir = &pci_slots_kset->kobj; + struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; dbg("%s\n", __func__); @@ -479,7 +477,7 @@ static int __init ibm_acpiphp_init(void) static void __exit ibm_acpiphp_exit(void) { acpi_status status; - struct kobject *sysdir = &pci_slots_kset->kobj; + struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; dbg("%s\n", __func__); diff --git a/trunk/drivers/pci/hotplug/cpci_hotplug_core.c b/trunk/drivers/pci/hotplug/cpci_hotplug_core.c index 935947991dc9..d8a6b80ab42a 100644 --- a/trunk/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/trunk/drivers/pci/hotplug/cpci_hotplug_core.c @@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) info->attention_status = cpci_get_attention_status(slot); dbg("registering slot %s", slot->hotplug_slot->name); - status = pci_hp_register(slot->hotplug_slot, bus, i); + status = pci_hp_register(slot->hotplug_slot); if (status) { err("pci_hp_register failed with error %d", status); goto error_name; diff --git a/trunk/drivers/pci/hotplug/cpqphp_core.c b/trunk/drivers/pci/hotplug/cpqphp_core.c index 54defec51d08..36b115b27b0b 100644 --- a/trunk/drivers/pci/hotplug/cpqphp_core.c +++ b/trunk/drivers/pci/hotplug/cpqphp_core.c @@ -434,9 +434,7 @@ static int ctrl_slot_setup(struct controller *ctrl, slot->bus, slot->device, slot->number, ctrl->slot_device_offset, slot_number); - result = pci_hp_register(hotplug_slot, - ctrl->pci_dev->subordinate, - slot->device); + result = pci_hp_register(hotplug_slot); if (result) { err("pci_hp_register failed with error %d\n", result); goto error_name; diff --git a/trunk/drivers/pci/hotplug/fakephp.c b/trunk/drivers/pci/hotplug/fakephp.c index 40337a06c18a..7e9a827c2687 100644 --- a/trunk/drivers/pci/hotplug/fakephp.c +++ b/trunk/drivers/pci/hotplug/fakephp.c @@ -66,7 +66,6 @@ struct dummy_slot { struct pci_dev *dev; struct work_struct remove_work; unsigned long removed; - char name[8]; }; static int debug; @@ -101,7 +100,6 @@ static int add_slot(struct pci_dev *dev) struct dummy_slot *dslot; struct hotplug_slot *slot; int retval = -ENOMEM; - static int count = 1; slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); if (!slot) @@ -115,18 +113,18 @@ static int add_slot(struct pci_dev *dev) slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + slot->name = &dev->dev.bus_id[0]; + dbg("slot->name = %s\n", slot->name); + dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL); if (!dslot) goto error_info; - slot->name = dslot->name; - snprintf(slot->name, sizeof(dslot->name), "fake%d", count++); - dbg("slot->name = %s\n", slot->name); slot->ops = &dummy_hotplug_slot_ops; slot->release = &dummy_release; slot->private = dslot; - retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn)); + retval = pci_hp_register(slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); goto error_dslot; @@ -150,17 +148,17 @@ static int add_slot(struct pci_dev *dev) static int __init pci_scan_buses(void) { struct pci_dev *dev = NULL; - int lastslot = 0; + int retval = 0; while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (PCI_FUNC(dev->devfn) > 0 && - lastslot == PCI_SLOT(dev->devfn)) - continue; - lastslot = PCI_SLOT(dev->devfn); - add_slot(dev); + retval = add_slot(dev); + if (retval) { + pci_dev_put(dev); + break; + } } - return 0; + return retval; } static void remove_slot(struct dummy_slot *dslot) @@ -298,9 +296,23 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) return 0; } +/* find the hotplug_slot for the pci_dev */ +static struct hotplug_slot *get_slot_from_dev(struct pci_dev *dev) +{ + struct dummy_slot *dslot; + + list_for_each_entry(dslot, &slot_list, node) { + if (dslot->dev == dev) + return dslot->slot; + } + return NULL; +} + + static int disable_slot(struct hotplug_slot *slot) { struct dummy_slot *dslot; + struct hotplug_slot *hslot; struct pci_dev *dev; int func; @@ -310,27 +322,41 @@ static int disable_slot(struct hotplug_slot *slot) dbg("%s - physical_slot = %s\n", __func__, slot->name); - for (func = 7; func >= 0; func--) { - dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func); - if (!dev) - continue; - - if (test_and_set_bit(0, &dslot->removed)) { - dbg("Slot already scheduled for removal\n"); - return -ENODEV; + /* don't disable bridged devices just yet, we can't handle them easily... */ + if (dslot->dev->subordinate) { + err("Can't remove PCI devices with other PCI devices behind it yet.\n"); + return -ENODEV; + } + if (test_and_set_bit(0, &dslot->removed)) { + dbg("Slot already scheduled for removal\n"); + return -ENODEV; + } + /* search for subfunctions and disable them first */ + if (!(dslot->dev->devfn & 7)) { + for (func = 1; func < 8; func++) { + dev = pci_get_slot(dslot->dev->bus, + dslot->dev->devfn + func); + if (dev) { + hslot = get_slot_from_dev(dev); + if (hslot) + disable_slot(hslot); + else { + err("Hotplug slot not found for subfunction of PCI device\n"); + return -ENODEV; + } + pci_dev_put(dev); + } else + dbg("No device in slot found\n"); } + } - /* queue work item to blow away this sysfs entry and other - * parts. - */ - INIT_WORK(&dslot->remove_work, remove_slot_worker); - queue_work(dummyphp_wq, &dslot->remove_work); + /* remove the device from the pci core */ + pci_remove_bus_device(dslot->dev); - /* blow away this sysfs entry and other parts. */ - remove_slot(dslot); + /* queue work item to blow away this sysfs entry and other parts. */ + INIT_WORK(&dslot->remove_work, remove_slot_worker); + queue_work(dummyphp_wq, &dslot->remove_work); - pci_dev_put(dev); - } return 0; } diff --git a/trunk/drivers/pci/hotplug/ibmphp_ebda.c b/trunk/drivers/pci/hotplug/ibmphp_ebda.c index 8467d0287325..dca7efc14be2 100644 --- a/trunk/drivers/pci/hotplug/ibmphp_ebda.c +++ b/trunk/drivers/pci/hotplug/ibmphp_ebda.c @@ -1001,8 +1001,7 @@ static int __init ebda_rsrc_controller (void) tmp_slot = list_entry (list, struct slot, ibm_slot_list); snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot)); - pci_hp_register(tmp_slot->hotplug_slot, - pci_find_bus(0, tmp_slot->bus), tmp_slot->device); + pci_hp_register (tmp_slot->hotplug_slot); } print_ebda_hpc (); diff --git a/trunk/drivers/pci/hotplug/pci_hotplug_core.c b/trunk/drivers/pci/hotplug/pci_hotplug_core.c index b3b2d8cf4370..a11021e8ce37 100644 --- a/trunk/drivers/pci/hotplug/pci_hotplug_core.c +++ b/trunk/drivers/pci/hotplug/pci_hotplug_core.c @@ -40,7 +40,6 @@ #include #include #include -#include "../pci.h" #define MY_NAME "pci_hotplug" @@ -61,7 +60,41 @@ static int debug; ////////////////////////////////////////////////////////////////// static LIST_HEAD(pci_hotplug_slot_list); -static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock); + +struct kset *pci_hotplug_slots_kset; + +static ssize_t hotplug_slot_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct hotplug_slot *slot = to_hotplug_slot(kobj); + struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); + return attribute->show ? attribute->show(slot, buf) : -EIO; +} + +static ssize_t hotplug_slot_attr_store(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t len) +{ + struct hotplug_slot *slot = to_hotplug_slot(kobj); + struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); + return attribute->store ? attribute->store(slot, buf, len) : -EIO; +} + +static struct sysfs_ops hotplug_slot_sysfs_ops = { + .show = hotplug_slot_attr_show, + .store = hotplug_slot_attr_store, +}; + +static void hotplug_slot_release(struct kobject *kobj) +{ + struct hotplug_slot *slot = to_hotplug_slot(kobj); + if (slot->release) + slot->release(slot); +} + +static struct kobj_type hotplug_slot_ktype = { + .sysfs_ops = &hotplug_slot_sysfs_ops, + .release = &hotplug_slot_release, +}; /* these strings match up with the values in pci_bus_speed */ static char *pci_bus_speed_strings[] = { @@ -116,15 +149,16 @@ GET_STATUS(power_status, u8) GET_STATUS(attention_status, u8) GET_STATUS(latch_status, u8) GET_STATUS(adapter_status, u8) +GET_STATUS(address, u32) GET_STATUS(max_bus_speed, enum pci_bus_speed) GET_STATUS(cur_bus_speed, enum pci_bus_speed) -static ssize_t power_read_file(struct pci_slot *slot, char *buf) +static ssize_t power_read_file (struct hotplug_slot *slot, char *buf) { int retval; u8 value; - retval = get_power_status(slot->hotplug, &value); + retval = get_power_status (slot, &value); if (retval) goto exit; retval = sprintf (buf, "%d\n", value); @@ -132,10 +166,9 @@ static ssize_t power_read_file(struct pci_slot *slot, char *buf) return retval; } -static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, +static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf, size_t count) { - struct hotplug_slot *slot = pci_slot->hotplug; unsigned long lpower; u8 power; int retval = 0; @@ -171,30 +204,29 @@ static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, return count; } -static struct pci_slot_attribute hotplug_slot_attr_power = { +static struct hotplug_slot_attribute hotplug_slot_attr_power = { .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR}, .show = power_read_file, .store = power_write_file }; -static ssize_t attention_read_file(struct pci_slot *slot, char *buf) +static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf) { int retval; u8 value; - retval = get_attention_status(slot->hotplug, &value); + retval = get_attention_status (slot, &value); if (retval) goto exit; - retval = sprintf(buf, "%d\n", value); + retval = sprintf (buf, "%d\n", value); exit: return retval; } -static ssize_t attention_write_file(struct pci_slot *slot, const char *buf, +static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf, size_t count) { - struct hotplug_slot_ops *ops = slot->hotplug->ops; unsigned long lattention; u8 attention; int retval = 0; @@ -203,13 +235,13 @@ static ssize_t attention_write_file(struct pci_slot *slot, const char *buf, attention = (u8)(lattention & 0xff); dbg (" - attention = %d\n", attention); - if (!try_module_get(ops->owner)) { + if (!try_module_get(slot->ops->owner)) { retval = -ENODEV; goto exit; } - if (ops->set_attention_status) - retval = ops->set_attention_status(slot->hotplug, attention); - module_put(ops->owner); + if (slot->ops->set_attention_status) + retval = slot->ops->set_attention_status(slot, attention); + module_put(slot->ops->owner); exit: if (retval) @@ -217,18 +249,18 @@ static ssize_t attention_write_file(struct pci_slot *slot, const char *buf, return count; } -static struct pci_slot_attribute hotplug_slot_attr_attention = { +static struct hotplug_slot_attribute hotplug_slot_attr_attention = { .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR}, .show = attention_read_file, .store = attention_write_file }; -static ssize_t latch_read_file(struct pci_slot *slot, char *buf) +static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf) { int retval; u8 value; - retval = get_latch_status(slot->hotplug, &value); + retval = get_latch_status (slot, &value); if (retval) goto exit; retval = sprintf (buf, "%d\n", value); @@ -237,17 +269,17 @@ static ssize_t latch_read_file(struct pci_slot *slot, char *buf) return retval; } -static struct pci_slot_attribute hotplug_slot_attr_latch = { +static struct hotplug_slot_attribute hotplug_slot_attr_latch = { .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, .show = latch_read_file, }; -static ssize_t presence_read_file(struct pci_slot *slot, char *buf) +static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf) { int retval; u8 value; - retval = get_adapter_status(slot->hotplug, &value); + retval = get_adapter_status (slot, &value); if (retval) goto exit; retval = sprintf (buf, "%d\n", value); @@ -256,20 +288,42 @@ static ssize_t presence_read_file(struct pci_slot *slot, char *buf) return retval; } -static struct pci_slot_attribute hotplug_slot_attr_presence = { +static struct hotplug_slot_attribute hotplug_slot_attr_presence = { .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, .show = presence_read_file, }; +static ssize_t address_read_file (struct hotplug_slot *slot, char *buf) +{ + int retval; + u32 address; + + retval = get_address (slot, &address); + if (retval) + goto exit; + retval = sprintf (buf, "%04x:%02x:%02x\n", + (address >> 16) & 0xffff, + (address >> 8) & 0xff, + address & 0xff); + +exit: + return retval; +} + +static struct hotplug_slot_attribute hotplug_slot_attr_address = { + .attr = {.name = "address", .mode = S_IFREG | S_IRUGO}, + .show = address_read_file, +}; + static char *unknown_speed = "Unknown bus speed"; -static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf) +static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf) { char *speed_string; int retval; enum pci_bus_speed value; - retval = get_max_bus_speed(slot->hotplug, &value); + retval = get_max_bus_speed (slot, &value); if (retval) goto exit; @@ -284,18 +338,18 @@ static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf) return retval; } -static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = { +static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = { .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = max_bus_speed_read_file, }; -static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf) +static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf) { char *speed_string; int retval; enum pci_bus_speed value; - retval = get_cur_bus_speed(slot->hotplug, &value); + retval = get_cur_bus_speed (slot, &value); if (retval) goto exit; @@ -310,15 +364,14 @@ static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf) return retval; } -static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = { +static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = { .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = cur_bus_speed_read_file, }; -static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, +static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf, size_t count) { - struct hotplug_slot *slot = pci_slot->hotplug; unsigned long ltest; u32 test; int retval = 0; @@ -341,14 +394,13 @@ static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, return count; } -static struct pci_slot_attribute hotplug_slot_attr_test = { +static struct hotplug_slot_attribute hotplug_slot_attr_test = { .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR}, .store = test_write_file }; -static int has_power_file(struct pci_slot *pci_slot) +static int has_power_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if ((slot->ops->enable_slot) || @@ -358,9 +410,8 @@ static int has_power_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_attention_file(struct pci_slot *pci_slot) +static int has_attention_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if ((slot->ops->set_attention_status) || @@ -369,9 +420,8 @@ static int has_attention_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_latch_file(struct pci_slot *pci_slot) +static int has_latch_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if (slot->ops->get_latch_status) @@ -379,9 +429,8 @@ static int has_latch_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_adapter_file(struct pci_slot *pci_slot) +static int has_adapter_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if (slot->ops->get_adapter_status) @@ -389,9 +438,17 @@ static int has_adapter_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_max_bus_speed_file(struct pci_slot *pci_slot) +static int has_address_file (struct hotplug_slot *slot) +{ + if ((!slot) || (!slot->ops)) + return -ENODEV; + if (slot->ops->get_address) + return 0; + return -ENOENT; +} + +static int has_max_bus_speed_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if (slot->ops->get_max_bus_speed) @@ -399,9 +456,8 @@ static int has_max_bus_speed_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_cur_bus_speed_file(struct pci_slot *pci_slot) +static int has_cur_bus_speed_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if (slot->ops->get_cur_bus_speed) @@ -409,9 +465,8 @@ static int has_cur_bus_speed_file(struct pci_slot *pci_slot) return -ENOENT; } -static int has_test_file(struct pci_slot *pci_slot) +static int has_test_file (struct hotplug_slot *slot) { - struct hotplug_slot *slot = pci_slot->hotplug; if ((!slot) || (!slot->ops)) return -ENODEV; if (slot->ops->hardware_test) @@ -419,7 +474,7 @@ static int has_test_file(struct pci_slot *pci_slot) return -ENOENT; } -static int fs_add_slot(struct pci_slot *slot) +static int fs_add_slot (struct hotplug_slot *slot) { int retval = 0; @@ -450,6 +505,13 @@ static int fs_add_slot(struct pci_slot *slot) goto exit_adapter; } + if (has_address_file(slot) == 0) { + retval = sysfs_create_file(&slot->kobj, + &hotplug_slot_attr_address.attr); + if (retval) + goto exit_address; + } + if (has_max_bus_speed_file(slot) == 0) { retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -482,6 +544,10 @@ static int fs_add_slot(struct pci_slot *slot) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); exit_max_speed: + if (has_address_file(slot) == 0) + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr); + +exit_address: if (has_adapter_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); @@ -501,7 +567,7 @@ static int fs_add_slot(struct pci_slot *slot) return retval; } -static void fs_remove_slot(struct pci_slot *slot) +static void fs_remove_slot (struct hotplug_slot *slot) { if (has_power_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); @@ -515,6 +581,9 @@ static void fs_remove_slot(struct pci_slot *slot) if (has_adapter_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); + if (has_address_file(slot) == 0) + sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr); + if (has_max_bus_speed_file(slot) == 0) sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); @@ -530,16 +599,12 @@ static struct hotplug_slot *get_slot_from_name (const char *name) struct hotplug_slot *slot; struct list_head *tmp; - spin_lock(&pci_hotplug_slot_list_lock); list_for_each (tmp, &pci_hotplug_slot_list) { slot = list_entry (tmp, struct hotplug_slot, slot_list); if (strcmp(slot->name, name) == 0) - goto out; + return slot; } - slot = NULL; -out: - spin_unlock(&pci_hotplug_slot_list_lock); - return slot; + return NULL; } /** @@ -551,10 +616,9 @@ static struct hotplug_slot *get_slot_from_name (const char *name) * * Returns 0 if successful, anything else for an error. */ -int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) +int pci_hp_register (struct hotplug_slot *slot) { int result; - struct pci_slot *pci_slot; struct hotplug_slot *tmp; if (slot == NULL) @@ -572,44 +636,19 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) if (tmp) return -EEXIST; - /* - * No problems if we call this interface from both ACPI_PCI_SLOT - * driver and call it here again. If we've already created the - * pci_slot, the interface will simply bump the refcount. - */ - pci_slot = pci_create_slot(bus, slot_nr, slot->name); - if (IS_ERR(pci_slot)) - return PTR_ERR(pci_slot); - - if (pci_slot->hotplug) { - dbg("%s: already claimed\n", __func__); - pci_destroy_slot(pci_slot); - return -EBUSY; - } - - slot->pci_slot = pci_slot; - pci_slot->hotplug = slot; - - /* - * Allow pcihp drivers to override the ACPI_PCI_SLOT name. - */ - if (strcmp(kobject_name(&pci_slot->kobj), slot->name)) { - result = kobject_rename(&pci_slot->kobj, slot->name); - if (result) { - pci_destroy_slot(pci_slot); - return result; - } + slot->kobj.kset = pci_hotplug_slots_kset; + result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL, + "%s", slot->name); + if (result) { + err("Unable to register kobject '%s'", slot->name); + return -EINVAL; } - spin_lock(&pci_hotplug_slot_list_lock); - list_add(&slot->slot_list, &pci_hotplug_slot_list); - spin_unlock(&pci_hotplug_slot_list_lock); - - result = fs_add_slot(pci_slot); - kobject_uevent(&pci_slot->kobj, KOBJ_ADD); - dbg("Added slot %s to the list\n", slot->name); - + list_add (&slot->slot_list, &pci_hotplug_slot_list); + result = fs_add_slot (slot); + kobject_uevent(&slot->kobj, KOBJ_ADD); + dbg ("Added slot %s to the list\n", slot->name); return result; } @@ -622,30 +661,22 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr) * * Returns 0 if successful, anything else for an error. */ -int pci_hp_deregister(struct hotplug_slot *hotplug) +int pci_hp_deregister (struct hotplug_slot *slot) { struct hotplug_slot *temp; - struct pci_slot *slot; - if (!hotplug) + if (slot == NULL) return -ENODEV; - temp = get_slot_from_name(hotplug->name); - if (temp != hotplug) + temp = get_slot_from_name (slot->name); + if (temp != slot) { return -ENODEV; + } + list_del (&slot->slot_list); - spin_lock(&pci_hotplug_slot_list_lock); - list_del(&hotplug->slot_list); - spin_unlock(&pci_hotplug_slot_list_lock); - - slot = hotplug->pci_slot; - fs_remove_slot(slot); - dbg("Removed slot %s from the list\n", hotplug->name); - - hotplug->release(hotplug); - slot->hotplug = NULL; - pci_destroy_slot(slot); - + fs_remove_slot (slot); + dbg ("Removed slot %s from the list\n", slot->name); + kobject_put(&slot->kobj); return 0; } @@ -659,15 +690,13 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) * * Returns 0 if successful, anything else for an error. */ -int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug, +int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, struct hotplug_slot_info *info) { - struct pci_slot *slot; - if (!hotplug || !info) + if ((slot == NULL) || (info == NULL)) return -ENODEV; - slot = hotplug->pci_slot; - memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info)); + memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); return 0; } @@ -675,22 +704,36 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug, static int __init pci_hotplug_init (void) { int result; + struct kset *pci_bus_kset; + pci_bus_kset = bus_get_kset(&pci_bus_type); + + pci_hotplug_slots_kset = kset_create_and_add("slots", NULL, + &pci_bus_kset->kobj); + if (!pci_hotplug_slots_kset) { + result = -ENOMEM; + err("Register subsys error\n"); + goto exit; + } result = cpci_hotplug_init(debug); if (result) { err ("cpci_hotplug_init with error %d\n", result); - goto err_cpci; + goto err_subsys; } info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); + goto exit; -err_cpci: +err_subsys: + kset_unregister(pci_hotplug_slots_kset); +exit: return result; } static void __exit pci_hotplug_exit (void) { cpci_hotplug_exit(); + kset_unregister(pci_hotplug_slots_kset); } module_init(pci_hotplug_init); @@ -702,6 +745,7 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); +EXPORT_SYMBOL_GPL(pci_hotplug_slots_kset); EXPORT_SYMBOL_GPL(pci_hp_register); EXPORT_SYMBOL_GPL(pci_hp_deregister); EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); diff --git a/trunk/drivers/pci/hotplug/pciehp.h b/trunk/drivers/pci/hotplug/pciehp.h index 8492fab800cc..79c9ddaad3fb 100644 --- a/trunk/drivers/pci/hotplug/pciehp.h +++ b/trunk/drivers/pci/hotplug/pciehp.h @@ -202,13 +202,8 @@ struct hpc_ops { #include #include -static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - return acpi_get_hp_hw_control_from_firmware(dev, flags); -} - +#define pciehp_get_hp_hw_control_from_firmware(dev) \ + pciehp_acpi_get_hp_hw_control_from_firmware(dev) static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { diff --git a/trunk/drivers/pci/hotplug/pciehp_core.c b/trunk/drivers/pci/hotplug/pciehp_core.c index 7b21c86e4bff..48a2ed378914 100644 --- a/trunk/drivers/pci/hotplug/pciehp_core.c +++ b/trunk/drivers/pci/hotplug/pciehp_core.c @@ -41,7 +41,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; -static int pciehp_slot_with_bus; +int pciehp_slot_with_bus; struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" @@ -72,6 +72,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); @@ -84,6 +85,7 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -250,9 +252,7 @@ static int init_slots(struct controller *ctrl) dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n", slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval = pci_hp_register(hotplug_slot, - ctrl->pci_dev->subordinate, - slot->device); + retval = pci_hp_register(hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); if (retval == -EEXIST) @@ -263,7 +263,7 @@ static int init_slots(struct controller *ctrl) } /* create additional sysfs entries */ if (EMI(ctrl)) { - retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj, + retval = sysfs_create_file(&hotplug_slot->kobj, &hotplug_slot_attr_lock.attr); if (retval) { pci_hp_deregister(hotplug_slot); @@ -296,7 +296,7 @@ static void cleanup_slots(struct controller *ctrl) slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); if (EMI(ctrl)) - sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, + sysfs_remove_file(&slot->hotplug_slot->kobj, &hotplug_slot_attr_lock.attr); cancel_delayed_work(&slot->work); flush_scheduled_work(); @@ -398,8 +398,19 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) return 0; } -static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, - enum pci_bus_speed *value) +static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = hotplug_slot->private; + struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; + + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + + *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; + + return 0; +} + +static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = hotplug_slot->private; int retval; @@ -433,13 +444,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ struct controller *ctrl; struct slot *t_slot; u8 value; - struct pci_dev *pdev = dev->port; - - if (pciehp_force) - dbg("Bypassing BIOS check for pciehp use on %s\n", - pci_name(pdev)); - else if (pciehp_get_hp_hw_control_from_firmware(pdev)) - goto err_out_none; + struct pci_dev *pdev; ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { @@ -448,6 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } INIT_LIST_HEAD(&ctrl->slot_list); + pdev = dev->port; + ctrl->pci_dev = pdev; + rc = pcie_init(ctrl, dev); if (rc) { dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); @@ -463,12 +471,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { - if (rc == -EBUSY) - warn("%s: slot already registered by another " - "hotplug driver\n", PCIE_MODULE_NAME); - else - err("%s: slot initialization failed\n", - PCIE_MODULE_NAME); + err("%s: slot initialization failed\n", PCIE_MODULE_NAME); goto err_out_release_ctlr; } diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index 0cfaedf2edca..79f104963166 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -268,8 +268,9 @@ static inline int pcie_poll_cmd(struct controller *ctrl) return timeout; } -static inline void pcie_wait_cmd(struct controller *ctrl, int poll) +static inline int pcie_wait_cmd(struct controller *ctrl, int poll) { + int retval = 0; unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; unsigned long timeout = msecs_to_jiffies(msecs); int rc; @@ -277,9 +278,16 @@ static inline void pcie_wait_cmd(struct controller *ctrl, int poll) if (poll) rc = pcie_poll_cmd(ctrl); else - rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); + rc = wait_event_interruptible_timeout(ctrl->queue, + !ctrl->cmd_busy, timeout); if (!rc) dbg("Command not completed in 1000 msec\n"); + else if (rc < 0) { + retval = -EINTR; + info("Command was interrupted by a signal\n"); + } + + return retval; } /** @@ -357,7 +365,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) if (!(slot_ctrl & HP_INTR_ENABLE) || !(slot_ctrl & CMD_CMPL_INTR_ENABLE)) poll = 1; - pcie_wait_cmd(ctrl, poll); + retval = pcie_wait_cmd(ctrl, poll); } out: mutex_unlock(&ctrl->ctrl_lock); @@ -777,7 +785,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) intr_loc |= detected; if (!intr_loc) return IRQ_NONE; - if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) { + if (pciehp_writew(ctrl, SLOTSTATUS, detected)) { err("%s: Cannot write to SLOTSTATUS\n", __func__); return IRQ_NONE; } @@ -789,7 +797,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) if (intr_loc & CMD_COMPLETED) { ctrl->cmd_busy = 0; smp_mb(); - wake_up(&ctrl->queue); + wake_up_interruptible(&ctrl->queue); } if (!(intr_loc & ~CMD_COMPLETED)) @@ -1009,6 +1017,75 @@ static struct hpc_ops pciehp_hpc_ops = { .check_lnk_status = hpc_check_lnk_status, }; +#ifdef CONFIG_ACPI +static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) +{ + acpi_status status; + acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + struct pci_dev *pdev = dev; + struct pci_bus *parent; + struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; + + /* + * Per PCI firmware specification, we should run the ACPI _OSC + * method to get control of hotplug hardware before using it. + * If an _OSC is missing, we look for an OSHP to do the same thing. + * To handle different BIOS behavior, we look for _OSC and OSHP + * within the scope of the hotplug controller and its parents, upto + * the host bridge under which this controller exists. + */ + while (!handle) { + /* + * This hotplug controller was not listed in the ACPI name + * space at all. Try to get acpi handle of parent pci bus. + */ + if (!pdev || !pdev->bus->parent) + break; + parent = pdev->bus->parent; + dbg("Could not find %s in acpi namespace, trying parent\n", + pci_name(pdev)); + if (!parent->self) + /* Parent must be a host bridge */ + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(parent), + parent->number); + else + handle = DEVICE_ACPI_HANDLE( + &(parent->self->dev)); + pdev = parent->self; + } + + while (handle) { + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s \n", + (char *)string.pointer); + status = pci_osc_control_set(handle, + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | + OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (status == AE_NOT_FOUND) + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) { + dbg("Gained control for hotplug HW for pci %s (%s)\n", + pci_name(dev), (char *)string.pointer); + kfree(string.pointer); + return 0; + } + if (acpi_root_bridge(handle)) + break; + chandle = handle; + status = acpi_get_parent(chandle, &handle); + if (ACPI_FAILURE(status)) + break; + } + + dbg("Cannot get control of hotplug hardware for pci %s\n", + pci_name(dev)); + + kfree(string.pointer); + return -1; +} +#endif + static int pcie_init_hardware_part1(struct controller *ctrl, struct pcie_device *dev) { @@ -1045,10 +1122,23 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) if (pcie_write_cmd(ctrl, cmd, mask)) { err("%s: Cannot enable software notification\n", __func__); - return -1; + goto abort; } + if (pciehp_force) + dbg("Bypassing BIOS check for pciehp use on %s\n", + pci_name(ctrl->pci_dev)); + else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev)) + goto abort_disable_intr; + return 0; + + /* We end up here for the many possible ways to fail this API. */ +abort_disable_intr: + if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE)) + err("%s : disabling interrupts failed\n", __func__); +abort: + return -1; } static inline void dbg_ctrl(struct controller *ctrl) @@ -1086,7 +1176,7 @@ static inline void dbg_ctrl(struct controller *ctrl) dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); pciehp_readw(ctrl, SLOTSTATUS, ®16); dbg("Slot Status : 0x%04x\n", reg16); - pciehp_readw(ctrl, SLOTCTRL, ®16); + pciehp_readw(ctrl, SLOTSTATUS, ®16); dbg("Slot Control : 0x%04x\n", reg16); } diff --git a/trunk/drivers/pci/hotplug/rpadlpar_sysfs.c b/trunk/drivers/pci/hotplug/rpadlpar_sysfs.c index a796301ea03f..779c5db71be4 100644 --- a/trunk/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/trunk/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -14,10 +14,8 @@ */ #include #include -#include #include #include "rpadlpar.h" -#include "../pci.h" #define DLPAR_KOBJ_NAME "control" @@ -29,6 +27,7 @@ #define MAX_DRC_NAME_LEN 64 + static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t nbytes) { @@ -113,7 +112,7 @@ int dlpar_sysfs_init(void) int error; dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME, - &pci_slots_kset->kobj); + &pci_hotplug_slots_kset->kobj); if (!dlpar_kobj) return -EINVAL; diff --git a/trunk/drivers/pci/hotplug/rpaphp_slot.c b/trunk/drivers/pci/hotplug/rpaphp_slot.c index 9b714ea93d20..56197b600d36 100644 --- a/trunk/drivers/pci/hotplug/rpaphp_slot.c +++ b/trunk/drivers/pci/hotplug/rpaphp_slot.c @@ -33,6 +33,33 @@ #include #include "rpaphp.h" +static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf) +{ + int retval; + struct slot *slot = (struct slot *)php_slot->private; + struct pci_bus *bus; + + if (!slot) + return -ENOENT; + + bus = slot->bus; + if (!bus) + return -ENOENT; + + if (bus->self) + retval = sprintf(buf, pci_name(bus->self)); + else + retval = sprintf(buf, "%04x:%02x:00.0", + pci_domain_nr(bus), bus->number); + + return retval; +} + +static struct hotplug_slot_attribute php_attr_address = { + .attr = {.name = "address", .mode = S_IFREG | S_IRUGO}, + .show = address_read_file, +}; + /* free up the memory used by a slot */ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) { @@ -108,6 +135,9 @@ int rpaphp_deregister_slot(struct slot *slot) list_del(&slot->rpaphp_slot_list); + /* remove "address" file */ + sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr); + retval = pci_hp_deregister(php_slot); if (retval) err("Problem unregistering a slot %s\n", slot->name); @@ -121,7 +151,6 @@ int rpaphp_register_slot(struct slot *slot) { struct hotplug_slot *php_slot = slot->hotplug_slot; int retval; - int slotno; dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", __func__, slot->dn->full_name, slot->index, slot->name, @@ -133,16 +162,19 @@ int rpaphp_register_slot(struct slot *slot) return -EAGAIN; } - if (slot->dn->child) - slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn); - else - slotno = -1; - retval = pci_hp_register(php_slot, slot->bus, slotno); + retval = pci_hp_register(php_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); return retval; } + /* create "address" file */ + retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr); + if (retval) { + err("sysfs_create_file failed with error %d\n", retval); + goto sysfs_fail; + } + /* add slot to our internal list */ list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); info("Slot [%s] registered\n", slot->name); diff --git a/trunk/drivers/pci/hotplug/sgi_hotplug.c b/trunk/drivers/pci/hotplug/sgi_hotplug.c index 410fe0394a8e..2fe37cd85b69 100644 --- a/trunk/drivers/pci/hotplug/sgi_hotplug.c +++ b/trunk/drivers/pci/hotplug/sgi_hotplug.c @@ -197,15 +197,13 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, static struct hotplug_slot * sn_hp_destroy(void) { struct slot *slot; - struct pci_slot *pci_slot; struct hotplug_slot *bss_hotplug_slot = NULL; list_for_each_entry(slot, &sn_hp_list, hp_list) { bss_hotplug_slot = slot->hotplug_slot; - pci_slot = bss_hotplug_slot->pci_slot; list_del(&((struct slot *)bss_hotplug_slot->private)-> hp_list); - sysfs_remove_file(&pci_slot->kobj, + sysfs_remove_file(&bss_hotplug_slot->kobj, &sn_slot_path_attr.attr); break; } @@ -616,7 +614,6 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot) static int sn_hotplug_slot_register(struct pci_bus *pci_bus) { int device; - struct pci_slot *pci_slot; struct hotplug_slot *bss_hotplug_slot; int rc = 0; @@ -653,12 +650,11 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) bss_hotplug_slot->ops = &sn_hotplug_slot_ops; bss_hotplug_slot->release = &sn_release_slot; - rc = pci_hp_register(bss_hotplug_slot, pci_bus, device); + rc = pci_hp_register(bss_hotplug_slot); if (rc) goto register_err; - pci_slot = bss_hotplug_slot->pci_slot; - rc = sysfs_create_file(&pci_slot->kobj, + rc = sysfs_create_file(&bss_hotplug_slot->kobj, &sn_slot_path_attr.attr); if (rc) goto register_err; @@ -668,7 +664,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) register_err: dev_dbg(&pci_bus->self->dev, "bus failed to register with err = %d\n", - rc); + rc); alloc_err: if (rc == -ENOMEM) diff --git a/trunk/drivers/pci/hotplug/shpchp.h b/trunk/drivers/pci/hotplug/shpchp.h index 8a026f750deb..f66e8d6315ab 100644 --- a/trunk/drivers/pci/hotplug/shpchp.h +++ b/trunk/drivers/pci/hotplug/shpchp.h @@ -170,7 +170,6 @@ extern void shpchp_queue_pushbutton_work(struct work_struct *work); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); #ifdef CONFIG_ACPI -#include static inline int get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { @@ -178,15 +177,14 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev, return -ENODEV; return 0; } - -static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; - return acpi_get_hp_hw_control_from_firmware(dev, flags); -} +#define get_hp_hw_control_from_firmware(pdev) \ + do { \ + if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ + acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\ + } while (0) #else #define get_hp_params_from_firmware(dev, hpp) (-ENODEV) -#define get_hp_hw_control_from_firmware(dev) (0) +#define get_hp_hw_control_from_firmware(dev) do { } while (0) #endif struct ctrl_reg { diff --git a/trunk/drivers/pci/hotplug/shpchp_core.c b/trunk/drivers/pci/hotplug/shpchp_core.c index a8cbd039b85b..97848654652a 100644 --- a/trunk/drivers/pci/hotplug/shpchp_core.c +++ b/trunk/drivers/pci/hotplug/shpchp_core.c @@ -39,7 +39,7 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -static int shpchp_slot_with_bus; +int shpchp_slot_with_bus; struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" @@ -68,6 +68,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); @@ -80,6 +81,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -157,8 +159,7 @@ static int init_slots(struct controller *ctrl) dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n", slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval = pci_hp_register(slot->hotplug_slot, - ctrl->pci_dev->subordinate, slot->device); + retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); if (retval == -EEXIST) @@ -287,8 +288,19 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) return 0; } -static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, - enum pci_bus_speed *value) +static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = get_slot(hotplug_slot); + struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; + + dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); + + *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; + + return 0; +} + +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = get_slot(hotplug_slot); int retval; @@ -318,14 +330,13 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp static int is_shpc_capable(struct pci_dev *dev) { - if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == - PCI_DEVICE_ID_AMD_GOLAM_7450)) - return 1; - if (!pci_find_capability(dev, PCI_CAP_ID_SHPC)) - return 0; - if (get_hp_hw_control_from_firmware(dev)) - return 0; - return 1; + if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == + PCI_DEVICE_ID_AMD_GOLAM_7450)) + return 1; + if (pci_find_capability(dev, PCI_CAP_ID_SHPC)) + return 1; + + return 0; } static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/trunk/drivers/pci/hotplug/shpchp_hpc.c b/trunk/drivers/pci/hotplug/shpchp_hpc.c index 7a0bff364cd4..7d770b2cd889 100644 --- a/trunk/drivers/pci/hotplug/shpchp_hpc.c +++ b/trunk/drivers/pci/hotplug/shpchp_hpc.c @@ -1084,6 +1084,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq); + get_hp_hw_control_from_firmware(pdev); /* * If this is the first controller to be initialized, diff --git a/trunk/drivers/pci/intel-iommu.c b/trunk/drivers/pci/intel-iommu.c index 4f05d91a0fd8..66c0fd21894b 100644 --- a/trunk/drivers/pci/intel-iommu.c +++ b/trunk/drivers/pci/intel-iommu.c @@ -1725,6 +1725,7 @@ int __init init_dmars(void) deferred_flush = kzalloc(g_num_of_iommus * sizeof(struct deferred_flush_tables), GFP_KERNEL); if (!deferred_flush) { + kfree(g_iommus); ret = -ENOMEM; goto error; } diff --git a/trunk/drivers/pci/msi.c b/trunk/drivers/pci/msi.c index ccb1974464fb..8c61304cbb37 100644 --- a/trunk/drivers/pci/msi.c +++ b/trunk/drivers/pci/msi.c @@ -70,10 +70,12 @@ arch_teardown_msi_irqs(struct pci_dev *dev) } } -static void __msi_set_enable(struct pci_dev *dev, int pos, int enable) +static void msi_set_enable(struct pci_dev *dev, int enable) { + int pos; u16 control; + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (pos) { pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); control &= ~PCI_MSI_FLAGS_ENABLE; @@ -83,11 +85,6 @@ static void __msi_set_enable(struct pci_dev *dev, int pos, int enable) } } -static void msi_set_enable(struct pci_dev *dev, int enable) -{ - __msi_set_enable(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), enable); -} - static void msix_set_enable(struct pci_dev *dev, int enable) { int pos; @@ -144,8 +141,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) mask_bits |= flag & mask; pci_write_config_dword(entry->dev, pos, mask_bits); } else { - __msi_set_enable(entry->dev, entry->msi_attrib.pos, - !flag); + msi_set_enable(entry->dev, !flag); } break; case PCI_CAP_ID_MSIX: diff --git a/trunk/drivers/pci/pci-acpi.c b/trunk/drivers/pci/pci-acpi.c index 5f96b869a566..caabf0573c3d 100644 --- a/trunk/drivers/pci/pci-acpi.c +++ b/trunk/drivers/pci/pci-acpi.c @@ -21,19 +21,12 @@ struct acpi_osc_data { acpi_handle handle; - u32 support_set; - u32 control_set; - int is_queried; - u32 query_result; + u32 ctrlset_buf[3]; + u32 global_ctrlsets; struct list_head sibiling; }; static LIST_HEAD(acpi_osc_data_list); -struct acpi_osc_args { - u32 capbuf[3]; - u32 query_result; -}; - static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) { struct acpi_osc_data *data; @@ -51,18 +44,42 @@ static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) return data; } -static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, - 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; +static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; -static acpi_status acpi_run_osc(acpi_handle handle, - struct acpi_osc_args *osc_args) +static acpi_status +acpi_query_osc ( + acpi_handle handle, + u32 level, + void *context, + void **retval ) { - acpi_status status; - struct acpi_object_list input; - union acpi_object in_params[4]; - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *out_obj; - u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE]; + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; + u32 osc_dw0; + acpi_status *ret_status = (acpi_status *)retval; + struct acpi_osc_data *osc_data; + u32 flags = (unsigned long)context, temp; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + + osc_data = acpi_get_osc_data(handle); + if (!osc_data) { + printk(KERN_ERR "acpi osc data array is full\n"); + return AE_ERROR; + } + + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); + + /* do _OSC query for all possible controls */ + temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; /* Setting up input parameters */ input.count = 4; @@ -76,19 +93,20 @@ static acpi_status acpi_run_osc(acpi_handle handle, in_params[2].integer.value = 3; in_params[3].type = ACPI_TYPE_BUFFER; in_params[3].buffer.length = 12; - in_params[3].buffer.pointer = (u8 *)osc_args->capbuf; + in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; status = acpi_evaluate_object(handle, "_OSC", &input, &output); if (ACPI_FAILURE(status)) - return status; - + goto out_nofree; out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { - printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); + printk(KERN_DEBUG + "Evaluate _OSC returns wrong type\n"); status = AE_TYPE; - goto out_kfree; + goto query_osc_out; } - osc_dw0 = *((u32 *)out_obj->buffer.pointer); + osc_dw0 = *((u32 *) out_obj->buffer.pointer); if (osc_dw0) { if (osc_dw0 & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); @@ -97,58 +115,93 @@ static acpi_status acpi_run_osc(acpi_handle handle, if (osc_dw0 & OSC_INVALID_REVISION_ERROR) printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { - if (flags & OSC_QUERY_ENABLE) - goto out_success; - printk(KERN_DEBUG "_OSC FW not grant req. control\n"); - status = AE_SUPPORT; - goto out_kfree; + /* Update Global Control Set */ + osc_data->global_ctrlsets = + *((u32 *)(out_obj->buffer.pointer + 8)); + status = AE_OK; + goto query_osc_out; } status = AE_ERROR; - goto out_kfree; + goto query_osc_out; } -out_success: - if (flags & OSC_QUERY_ENABLE) - osc_args->query_result = - *((u32 *)(out_obj->buffer.pointer + 8)); + + /* Update Global Control Set */ + osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); status = AE_OK; -out_kfree: +query_osc_out: kfree(output.pointer); +out_nofree: + *ret_status = status; + + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; + if (ACPI_FAILURE(status)) { + /* no osc support at all */ + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; + } + return status; } -static acpi_status acpi_query_osc(acpi_handle handle, - u32 level, void *context, void **retval) + +static acpi_status +acpi_run_osc ( + acpi_handle handle, + void *context) { - acpi_status status; - struct acpi_osc_data *osc_data; - u32 flags = (unsigned long)context, support_set; - acpi_handle tmp; - struct acpi_osc_args osc_args; + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; + u32 osc_dw0; - status = acpi_get_handle(handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) + /* Setting up input parameters */ + input.count = 4; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = 16; + in_params[0].buffer.pointer = OSC_UUID; + in_params[1].type = ACPI_TYPE_INTEGER; + in_params[1].integer.value = 1; + in_params[2].type = ACPI_TYPE_INTEGER; + in_params[2].integer.value = 3; + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = 12; + in_params[3].buffer.pointer = (u8 *)context; + + status = acpi_evaluate_object(handle, "_OSC", &input, &output); + if (ACPI_FAILURE (status)) return status; - osc_data = acpi_get_osc_data(handle); - if (!osc_data) { - printk(KERN_ERR "acpi osc data array is full\n"); - return AE_ERROR; + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG + "Evaluate _OSC returns wrong type\n"); + status = AE_TYPE; + goto run_osc_out; } - - /* do _OSC query for all possible controls */ - support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS); - osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; - osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; - - status = acpi_run_osc(handle, &osc_args); - if (ACPI_SUCCESS(status)) { - osc_data->support_set = support_set; - osc_data->query_result = osc_args.query_result; - osc_data->is_queried = 1; + osc_dw0 = *((u32 *) out_obj->buffer.pointer); + if (osc_dw0) { + if (osc_dw0 & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request fails\n"); + if (osc_dw0 & OSC_INVALID_UUID_ERROR) + printk(KERN_DEBUG "_OSC invalid UUID\n"); + if (osc_dw0 & OSC_INVALID_REVISION_ERROR) + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + printk(KERN_DEBUG "_OSC FW not grant req. control\n"); + status = AE_SUPPORT; + goto run_osc_out; + } + status = AE_ERROR; + goto run_osc_out; } + status = AE_OK; +run_osc_out: + kfree(output.pointer); return status; } @@ -162,11 +215,15 @@ static acpi_status acpi_query_osc(acpi_handle handle, **/ acpi_status __pci_osc_support_set(u32 flags, const char *hid) { - if (!(flags & OSC_SUPPORT_MASKS)) - return AE_TYPE; + acpi_status retval = AE_NOT_FOUND; - acpi_get_devices(hid, acpi_query_osc, - (void *)(unsigned long)flags, NULL); + if (!(flags & OSC_SUPPORT_MASKS)) { + return AE_TYPE; + } + acpi_get_devices(hid, + acpi_query_osc, + (void *)(unsigned long)flags, + (void **) &retval ); return AE_OK; } @@ -179,11 +236,10 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid) **/ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) { - acpi_status status; - u32 ctrlset, control_set; + acpi_status status; + u32 ctrlset; acpi_handle tmp; struct acpi_osc_data *osc_data; - struct acpi_osc_args osc_args; status = acpi_get_handle(handle, "_OSC", &tmp); if (ACPI_FAILURE(status)) @@ -196,21 +252,19 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) } ctrlset = (flags & OSC_CONTROL_MASKS); - if (!ctrlset) + if (!ctrlset) { return AE_TYPE; - - if (osc_data->is_queried && - ((osc_data->query_result & ctrlset) != ctrlset)) + } + if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && + ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { return AE_SUPPORT; - - control_set = osc_data->control_set | ctrlset; - osc_args.capbuf[OSC_QUERY_TYPE] = 0; - osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; - osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; - status = acpi_run_osc(handle, &osc_args); - if (ACPI_SUCCESS(status)) - osc_data->control_set = control_set; - + } + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; + status = acpi_run_osc(handle, osc_data->ctrlset_buf); + if (ACPI_FAILURE (status)) { + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; + } + return status; } EXPORT_SYMBOL(pci_osc_control_set); @@ -244,8 +298,7 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev, { int acpi_state; - acpi_state = acpi_pm_device_sleep_state(&pdev->dev, - device_may_wakeup(&pdev->dev), NULL); + acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL); if (acpi_state < 0) return PCI_POWER_ERROR; diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 8eb8a3091dc7..72cf61ed8f96 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -274,57 +274,7 @@ static int pci_device_remove(struct device * dev) return 0; } -static void pci_device_shutdown(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - - if (drv && drv->shutdown) - drv->shutdown(pci_dev); - pci_msi_shutdown(pci_dev); - pci_msix_shutdown(pci_dev); -} - -#ifdef CONFIG_PM_SLEEP - -/* - * Default "suspend" method for devices that have no driver provided suspend, - * or not even a driver at all. - */ -static void pci_default_pm_suspend(struct pci_dev *pci_dev) -{ - pci_save_state(pci_dev); - /* - * mark its power state as "unknown", since we don't know if - * e.g. the BIOS will change its device state when we suspend. - */ - if (pci_dev->current_state == PCI_D0) - pci_dev->current_state = PCI_UNKNOWN; -} - -/* - * Default "resume" method for devices that have no driver provided resume, - * or not even a driver at all. - */ -static int pci_default_pm_resume(struct pci_dev *pci_dev) -{ - int retval = 0; - - /* restore the PCI config space */ - pci_restore_state(pci_dev); - /* if the device was enabled before suspend, reenable */ - retval = pci_reenable_device(pci_dev); - /* - * if the device was busmaster before the suspend, make it busmaster - * again - */ - if (pci_dev->is_busmaster) - pci_set_master(pci_dev); - - return retval; -} - -static int pci_legacy_suspend(struct device *dev, pm_message_t state) +static int pci_device_suspend(struct device * dev, pm_message_t state) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; @@ -334,12 +284,18 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) i = drv->suspend(pci_dev, state); suspend_report_result(drv->suspend, i); } else { - pci_default_pm_suspend(pci_dev); + pci_save_state(pci_dev); + /* + * mark its power state as "unknown", since we don't know if + * e.g. the BIOS will change its device state when we suspend. + */ + if (pci_dev->current_state == PCI_D0) + pci_dev->current_state = PCI_UNKNOWN; } return i; } -static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) +static int pci_device_suspend_late(struct device * dev, pm_message_t state) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; @@ -352,7 +308,26 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) return i; } -static int pci_legacy_resume(struct device *dev) +/* + * Default resume method for devices that have no driver provided resume, + * or not even a driver at all. + */ +static int pci_default_resume(struct pci_dev *pci_dev) +{ + int retval = 0; + + /* restore the PCI config space */ + pci_restore_state(pci_dev); + /* if the device was enabled before suspend, reenable */ + retval = pci_reenable_device(pci_dev); + /* if the device was busmaster before the suspend, make it busmaster again */ + if (pci_dev->is_busmaster) + pci_set_master(pci_dev); + + return retval; +} + +static int pci_device_resume(struct device * dev) { int error; struct pci_dev * pci_dev = to_pci_dev(dev); @@ -361,313 +336,34 @@ static int pci_legacy_resume(struct device *dev) if (drv && drv->resume) error = drv->resume(pci_dev); else - error = pci_default_pm_resume(pci_dev); + error = pci_default_resume(pci_dev); return error; } -static int pci_legacy_resume_early(struct device *dev) +static int pci_device_resume_early(struct device * dev) { int error = 0; struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; - if (drv && drv->resume_early) - error = drv->resume_early(pci_dev); - return error; -} - -static int pci_pm_prepare(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int error = 0; - - if (drv && drv->pm && drv->pm->prepare) - error = drv->pm->prepare(dev); - - return error; -} - -static void pci_pm_complete(struct device *dev) -{ - struct device_driver *drv = dev->driver; - - if (drv && drv->pm && drv->pm->complete) - drv->pm->complete(dev); -} - -#ifdef CONFIG_SUSPEND - -static int pci_pm_suspend(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->suspend) { - error = drv->pm->suspend(dev); - suspend_report_result(drv->pm->suspend, error); - } else { - pci_default_pm_suspend(pci_dev); - } - } else { - error = pci_legacy_suspend(dev, PMSG_SUSPEND); - } - pci_fixup_device(pci_fixup_suspend, pci_dev); - - return error; -} - -static int pci_pm_suspend_noirq(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->suspend_noirq) { - error = drv->pm->suspend_noirq(dev); - suspend_report_result(drv->pm->suspend_noirq, error); - } - } else { - error = pci_legacy_suspend_late(dev, PMSG_SUSPEND); - } - - return error; -} - -static int pci_pm_resume(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error; - - pci_fixup_device(pci_fixup_resume, pci_dev); - - if (drv && drv->pm) { - error = drv->pm->resume ? drv->pm->resume(dev) : - pci_default_pm_resume(pci_dev); - } else { - error = pci_legacy_resume(dev); - } - - return error; -} - -static int pci_pm_resume_noirq(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - int error = 0; - - pci_fixup_device(pci_fixup_resume_early, pci_dev); - - if (drv && drv->pm) { - if (drv->pm->resume_noirq) - error = drv->pm->resume_noirq(dev); - } else { - error = pci_legacy_resume_early(dev); - } - - return error; -} - -#else /* !CONFIG_SUSPEND */ - -#define pci_pm_suspend NULL -#define pci_pm_suspend_noirq NULL -#define pci_pm_resume NULL -#define pci_pm_resume_noirq NULL - -#endif /* !CONFIG_SUSPEND */ - -#ifdef CONFIG_HIBERNATION - -static int pci_pm_freeze(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->freeze) { - error = drv->pm->freeze(dev); - suspend_report_result(drv->pm->freeze, error); - } else { - pci_default_pm_suspend(pci_dev); - } - } else { - error = pci_legacy_suspend(dev, PMSG_FREEZE); - pci_fixup_device(pci_fixup_suspend, pci_dev); - } - - return error; -} - -static int pci_pm_freeze_noirq(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->freeze_noirq) { - error = drv->pm->freeze_noirq(dev); - suspend_report_result(drv->pm->freeze_noirq, error); - } - } else { - error = pci_legacy_suspend_late(dev, PMSG_FREEZE); - } - - return error; -} - -static int pci_pm_thaw(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->thaw) - error = drv->pm->thaw(dev); - } else { - pci_fixup_device(pci_fixup_resume, to_pci_dev(dev)); - error = pci_legacy_resume(dev); - } - - return error; -} - -static int pci_pm_thaw_noirq(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->thaw_noirq) - error = drv->pm->thaw_noirq(dev); - } else { - pci_fixup_device(pci_fixup_resume_early, pci_dev); - error = pci_legacy_resume_early(dev); - } - - return error; -} - -static int pci_pm_poweroff(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int error = 0; - - pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); - - if (drv && drv->pm) { - if (drv->pm->poweroff) { - error = drv->pm->poweroff(dev); - suspend_report_result(drv->pm->poweroff, error); - } - } else { - error = pci_legacy_suspend(dev, PMSG_HIBERNATE); - } - - return error; -} - -static int pci_pm_poweroff_noirq(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - int error = 0; - - if (drv && drv->pm) { - if (drv->pm->poweroff_noirq) { - error = drv->pm->poweroff_noirq(dev); - suspend_report_result(drv->pm->poweroff_noirq, error); - } - } else { - error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE); - } - - return error; -} - -static int pci_pm_restore(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error; - - if (drv && drv->pm) { - error = drv->pm->restore ? drv->pm->restore(dev) : - pci_default_pm_resume(pci_dev); - } else { - error = pci_legacy_resume(dev); - } pci_fixup_device(pci_fixup_resume, pci_dev); + if (drv && drv->resume_early) + error = drv->resume_early(pci_dev); return error; } -static int pci_pm_restore_noirq(struct device *dev) +static void pci_device_shutdown(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; - int error = 0; - pci_fixup_device(pci_fixup_resume, pci_dev); - - if (drv && drv->pm) { - if (drv->pm->restore_noirq) - error = drv->pm->restore_noirq(dev); - } else { - error = pci_legacy_resume_early(dev); - } - pci_fixup_device(pci_fixup_resume_early, pci_dev); - - return error; + if (drv && drv->shutdown) + drv->shutdown(pci_dev); + pci_msi_shutdown(pci_dev); + pci_msix_shutdown(pci_dev); } -#else /* !CONFIG_HIBERNATION */ - -#define pci_pm_freeze NULL -#define pci_pm_freeze_noirq NULL -#define pci_pm_thaw NULL -#define pci_pm_thaw_noirq NULL -#define pci_pm_poweroff NULL -#define pci_pm_poweroff_noirq NULL -#define pci_pm_restore NULL -#define pci_pm_restore_noirq NULL - -#endif /* !CONFIG_HIBERNATION */ - -struct pm_ext_ops pci_pm_ops = { - .base = { - .prepare = pci_pm_prepare, - .complete = pci_pm_complete, - .suspend = pci_pm_suspend, - .resume = pci_pm_resume, - .freeze = pci_pm_freeze, - .thaw = pci_pm_thaw, - .poweroff = pci_pm_poweroff, - .restore = pci_pm_restore, - }, - .suspend_noirq = pci_pm_suspend_noirq, - .resume_noirq = pci_pm_resume_noirq, - .freeze_noirq = pci_pm_freeze_noirq, - .thaw_noirq = pci_pm_thaw_noirq, - .poweroff_noirq = pci_pm_poweroff_noirq, - .restore_noirq = pci_pm_restore_noirq, -}; - -#define PCI_PM_OPS_PTR &pci_pm_ops - -#else /* !CONFIG_PM_SLEEP */ - -#define PCI_PM_OPS_PTR NULL - -#endif /* !CONFIG_PM_SLEEP */ - /** * __pci_register_driver - register a new pci driver * @drv: the driver structure to register @@ -690,9 +386,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, drv->driver.owner = owner; drv->driver.mod_name = mod_name; - if (drv->pm) - drv->driver.pm = &drv->pm->base; - spin_lock_init(&drv->dynids.lock); INIT_LIST_HEAD(&drv->dynids.list); @@ -818,9 +511,12 @@ struct bus_type pci_bus_type = { .uevent = pci_uevent, .probe = pci_device_probe, .remove = pci_device_remove, + .suspend = pci_device_suspend, + .suspend_late = pci_device_suspend_late, + .resume_early = pci_device_resume_early, + .resume = pci_device_resume, .shutdown = pci_device_shutdown, .dev_attrs = pci_dev_attrs, - .pm = PCI_PM_OPS_PTR, }; static int __init pci_driver_init(void) diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 15beaf48407f..e4548ab2a93c 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -1,4 +1,6 @@ /* + * $Id: pci.c,v 1.91 1999/01/21 13:34:01 davem Exp $ + * * PCI Bus Services, see include/linux/pci.h for further explanation. * * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index e1d7bbf079b4..0a497c1b4227 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -106,16 +106,3 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) } struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev); - -/* PCI slot sysfs helper code */ -#define to_pci_slot(s) container_of(s, struct pci_slot, kobj) - -extern struct kset *pci_slots_kset; - -struct pci_slot_attribute { - struct attribute attr; - ssize_t (*show)(struct pci_slot *, char *); - ssize_t (*store)(struct pci_slot *, const char *, size_t); -}; -#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr) - diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.c b/trunk/drivers/pci/pcie/aer/aerdrv.c index b7a3aa602d40..07c3bdb6edc2 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv.c @@ -26,7 +26,6 @@ #include #include "aerdrv.h" -#include "../../pci.h" /* * Version Information diff --git a/trunk/drivers/pci/pcie/portdrv_bus.c b/trunk/drivers/pci/pcie/portdrv_bus.c index 359fe5568df1..3f0976868eda 100644 --- a/trunk/drivers/pci/pcie/portdrv_bus.c +++ b/trunk/drivers/pci/pcie/portdrv_bus.c @@ -13,7 +13,6 @@ #include #include -#include "portdrv.h" static int pcie_port_bus_match(struct device *dev, struct device_driver *drv); static int pcie_port_bus_suspend(struct device *dev, pm_message_t state); diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 4562827b7e22..3706ce7972dd 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -414,7 +414,6 @@ static struct pci_bus * pci_alloc_bus(void) INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); - INIT_LIST_HEAD(&b->slots); } return b; } @@ -858,49 +857,6 @@ int pci_cfg_space_size_ext(struct pci_dev *dev) return PCI_CFG_SPACE_SIZE; } -/** - * pci_disable_pme - Disable the PME function of PCI device - * @dev: PCI device affected - * -EINVAL is returned if PCI device doesn't support PME. - * Zero is returned if the PME is supported and can be disabled. - */ -static int pci_disable_pme(struct pci_dev *dev) -{ - int pm; - u16 value; - - /* find PCI PM capability in list */ - pm = pci_find_capability(dev, PCI_CAP_ID_PM); - - /* If device doesn't support PM Capabilities, it means that PME is - * not supported. - */ - if (!pm) - return -EINVAL; - /* Check device's ability to generate PME# */ - pci_read_config_word(dev, pm + PCI_PM_PMC, &value); - - value &= PCI_PM_CAP_PME_MASK; - /* Check if it can generate PME# */ - if (!value) { - /* - * If it is zero, it means that PME is still unsupported - * although there exists the PM capability. - */ - return -EINVAL; - } - - pci_read_config_word(dev, pm + PCI_PM_CTRL, &value); - - /* Clear PME_Status by writing 1 to it */ - value |= PCI_PM_CTRL_PME_STATUS ; - /* Disable PME enable bit */ - value &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(dev, pm + PCI_PM_CTRL, value); - - return 0; -} - int pci_cfg_space_size(struct pci_dev *dev) { int pos; @@ -1008,7 +964,6 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) } pci_vpd_pci22_init(dev); - pci_disable_pme(dev); return dev; } diff --git a/trunk/drivers/pci/proc.c b/trunk/drivers/pci/proc.c index 4400dffbd93a..963a97642ae9 100644 --- a/trunk/drivers/pci/proc.c +++ b/trunk/drivers/pci/proc.c @@ -1,4 +1,6 @@ /* + * $Id: proc.c,v 1.13 1998/05/12 07:36:07 mj Exp $ + * * Procfs interface for the PCI bus. * * Copyright (c) 1997--1999 Martin Mares @@ -480,5 +482,5 @@ static int __init pci_proc_init(void) return 0; } -device_initcall(pci_proc_init); +__initcall(pci_proc_init); diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 92b52ebd0eb6..dabb563f51d9 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -556,7 +556,7 @@ static void quirk_via_ioapic(struct pci_dev *dev) pci_write_config_byte (dev, 0x58, tmp); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic); /* * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit. @@ -576,7 +576,7 @@ static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert); /* * The AMD io apic can hang the box when an apic irq is masked. @@ -622,7 +622,7 @@ static void quirk_amd_8131_ioapic(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); #endif /* CONFIG_X86_IO_APIC */ /* @@ -774,7 +774,7 @@ static void quirk_cardbus_legacy(struct pci_dev *dev) pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0); } DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); +DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); /* * Following the PCI ordering rules is optional on the AMD762. I'm not @@ -797,7 +797,7 @@ static void quirk_amd_ordering(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering); /* * DreamWorks provided workaround for Dunord I-3000 problem @@ -865,7 +865,7 @@ static void quirk_disable_pxb(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb); static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev) { @@ -885,9 +885,9 @@ static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_amd_ide_mode); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_amd_ide_mode); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_amd_ide_mode); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode); /* * Serverworks CSB5 IDE does not fully support native mode @@ -1054,20 +1054,6 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) * its on-board VGA controller */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_IG) - switch(dev->subsystem_device) { - case 0x00b8: /* Compaq Evo D510 CMT */ - case 0x00b9: /* Compaq Evo D510 SFF */ - asus_hides_smbus = 1; - } - else if (dev->device == PCI_DEVICE_ID_INTEL_82815_CGC) - switch (dev->subsystem_device) { - case 0x001A: /* Compaq Deskpro EN SSF P667 815E */ - /* Motherboard doesn't have host bridge - * subvendor/subdevice IDs, therefore checking - * its on-board VGA controller */ - asus_hides_smbus = 1; - } } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge); @@ -1082,8 +1068,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, as DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG, asus_hides_smbus_hostbridge); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, asus_hides_smbus_hostbridge); static void asus_hides_smbus_lpc(struct pci_dev *dev) { @@ -1109,61 +1093,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc); -/* It appears we just have one such device. If not, we have a warning */ -static void __iomem *asus_rcba_base; -static void asus_hides_smbus_lpc_ich6_suspend(struct pci_dev *dev) +static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev) { - u32 rcba; + u32 val, rcba; + void __iomem *base; if (likely(!asus_hides_smbus)) return; - WARN_ON(asus_rcba_base); - pci_read_config_dword(dev, 0xF0, &rcba); - /* use bits 31:14, 16 kB aligned */ - asus_rcba_base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); - if (asus_rcba_base == NULL) - return; -} - -static void asus_hides_smbus_lpc_ich6_resume_early(struct pci_dev *dev) -{ - u32 val; - - if (likely(!asus_hides_smbus || !asus_rcba_base)) - return; - /* read the Function Disable register, dword mode only */ - val = readl(asus_rcba_base + 0x3418); - writel(val & 0xFFFFFFF7, asus_rcba_base + 0x3418); /* enable the SMBus device */ -} - -static void asus_hides_smbus_lpc_ich6_resume(struct pci_dev *dev) -{ - if (likely(!asus_hides_smbus || !asus_rcba_base)) - return; - iounmap(asus_rcba_base); - asus_rcba_base = NULL; + base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); /* use bits 31:14, 16 kB aligned */ + if (base == NULL) return; + val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */ + writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */ + iounmap(base); dev_info(&dev->dev, "Enabled ICH6/i801 SMBus device\n"); } - -static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev) -{ - asus_hides_smbus_lpc_ich6_suspend(dev); - asus_hides_smbus_lpc_ich6_resume_early(dev); - asus_hides_smbus_lpc_ich6_resume(dev); -} DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6); -DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6_suspend); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6_resume); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6_resume_early); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6); /* * SiS 96x south bridge: BIOS typically hides SMBus device... @@ -1181,10 +1135,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus); /* * ... This is further complicated by the fact that some SiS96x south @@ -1218,7 +1172,7 @@ static void quirk_sis_503(struct pci_dev *dev) quirk_sis_96x_smbus(dev); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503); /* @@ -1251,7 +1205,7 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc); #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) @@ -1316,12 +1270,12 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, qui DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); #endif @@ -1567,10 +1521,6 @@ extern struct pci_fixup __start_pci_fixups_enable[]; extern struct pci_fixup __end_pci_fixups_enable[]; extern struct pci_fixup __start_pci_fixups_resume[]; extern struct pci_fixup __end_pci_fixups_resume[]; -extern struct pci_fixup __start_pci_fixups_resume_early[]; -extern struct pci_fixup __end_pci_fixups_resume_early[]; -extern struct pci_fixup __start_pci_fixups_suspend[]; -extern struct pci_fixup __end_pci_fixups_suspend[]; void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) @@ -1603,16 +1553,6 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) end = __end_pci_fixups_resume; break; - case pci_fixup_resume_early: - start = __start_pci_fixups_resume_early; - end = __end_pci_fixups_resume_early; - break; - - case pci_fixup_suspend: - start = __start_pci_fixups_suspend; - end = __end_pci_fixups_suspend; - break; - default: /* stupid compiler warning, you would think with an enum... */ return; @@ -1689,7 +1629,7 @@ static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap); static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev) diff --git a/trunk/drivers/pci/slot.c b/trunk/drivers/pci/slot.c deleted file mode 100644 index 7e5b85cbd948..000000000000 --- a/trunk/drivers/pci/slot.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * drivers/pci/slot.c - * Copyright (C) 2006 Matthew Wilcox - * Copyright (C) 2006-2008 Hewlett-Packard Development Company, L.P. - * Alex Chiang - */ - -#include -#include -#include -#include "pci.h" - -struct kset *pci_slots_kset; -EXPORT_SYMBOL_GPL(pci_slots_kset); - -static ssize_t pci_slot_attr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct pci_slot *slot = to_pci_slot(kobj); - struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); - return attribute->show ? attribute->show(slot, buf) : -EIO; -} - -static ssize_t pci_slot_attr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t len) -{ - struct pci_slot *slot = to_pci_slot(kobj); - struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); - return attribute->store ? attribute->store(slot, buf, len) : -EIO; -} - -static struct sysfs_ops pci_slot_sysfs_ops = { - .show = pci_slot_attr_show, - .store = pci_slot_attr_store, -}; - -static ssize_t address_read_file(struct pci_slot *slot, char *buf) -{ - if (slot->number == 0xff) - return sprintf(buf, "%04x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number); - else - return sprintf(buf, "%04x:%02x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number, - slot->number); -} - -static void pci_slot_release(struct kobject *kobj) -{ - struct pci_slot *slot = to_pci_slot(kobj); - - pr_debug("%s: releasing pci_slot on %x:%d\n", __func__, - slot->bus->number, slot->number); - - list_del(&slot->list); - - kfree(slot); -} - -static struct pci_slot_attribute pci_slot_attr_address = - __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); - -static struct attribute *pci_slot_default_attrs[] = { - &pci_slot_attr_address.attr, - NULL, -}; - -static struct kobj_type pci_slot_ktype = { - .sysfs_ops = &pci_slot_sysfs_ops, - .release = &pci_slot_release, - .default_attrs = pci_slot_default_attrs, -}; - -/** - * pci_create_slot - create or increment refcount for physical PCI slot - * @parent: struct pci_bus of parent bridge - * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder - * @name: user visible string presented in /sys/bus/pci/slots/ - * - * PCI slots have first class attributes such as address, speed, width, - * and a &struct pci_slot is used to manage them. This interface will - * either return a new &struct pci_slot to the caller, or if the pci_slot - * already exists, its refcount will be incremented. - * - * Slots are uniquely identified by a @pci_bus, @slot_nr, @name tuple. - * - * Placeholder slots: - * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify - * a slot. There is one notable exception - pSeries (rpaphp), where the - * @slot_nr cannot be determined until a device is actually inserted into - * the slot. In this scenario, the caller may pass -1 for @slot_nr. - * - * The following semantics are imposed when the caller passes @slot_nr == - * -1. First, the check for existing %struct pci_slot is skipped, as the - * caller may know about several unpopulated slots on a given %struct - * pci_bus, and each slot would have a @slot_nr of -1. Uniqueness for - * these slots is then determined by the @name parameter. We expect - * kobject_init_and_add() to warn us if the caller attempts to create - * multiple slots with the same name. The other change in semantics is - * user-visible, which is the 'address' parameter presented in sysfs will - * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the - * %struct pci_bus and bb is the bus number. In other words, the devfn of - * the 'placeholder' slot will not be displayed. - */ - -struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, - const char *name) -{ - struct pci_slot *slot; - int err; - - down_write(&pci_bus_sem); - - if (slot_nr == -1) - goto placeholder; - - /* If we've already created this slot, bump refcount and return. */ - list_for_each_entry(slot, &parent->slots, list) { - if (slot->number == slot_nr) { - kobject_get(&slot->kobj); - pr_debug("%s: inc refcount to %d on %04x:%02x:%02x\n", - __func__, - atomic_read(&slot->kobj.kref.refcount), - pci_domain_nr(parent), parent->number, - slot_nr); - goto out; - } - } - -placeholder: - slot = kzalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) { - slot = ERR_PTR(-ENOMEM); - goto out; - } - - slot->bus = parent; - slot->number = slot_nr; - - slot->kobj.kset = pci_slots_kset; - err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, - "%s", name); - if (err) { - printk(KERN_ERR "Unable to register kobject %s\n", name); - goto err; - } - - INIT_LIST_HEAD(&slot->list); - list_add(&slot->list, &parent->slots); - - /* Don't care if debug printk has a -1 for slot_nr */ - pr_debug("%s: created pci_slot on %04x:%02x:%02x\n", - __func__, pci_domain_nr(parent), parent->number, slot_nr); - - out: - up_write(&pci_bus_sem); - return slot; - err: - kfree(slot); - slot = ERR_PTR(err); - goto out; -} -EXPORT_SYMBOL_GPL(pci_create_slot); - -/** - * pci_update_slot_number - update %struct pci_slot -> number - * @slot - %struct pci_slot to update - * @slot_nr - new number for slot - * - * The primary purpose of this interface is to allow callers who earlier - * created a placeholder slot in pci_create_slot() by passing a -1 as - * slot_nr, to update their %struct pci_slot with the correct @slot_nr. - */ - -void pci_update_slot_number(struct pci_slot *slot, int slot_nr) -{ - int name_count = 0; - struct pci_slot *tmp; - - down_write(&pci_bus_sem); - - list_for_each_entry(tmp, &slot->bus->slots, list) { - WARN_ON(tmp->number == slot_nr); - if (!strcmp(kobject_name(&tmp->kobj), kobject_name(&slot->kobj))) - name_count++; - } - - if (name_count > 1) - printk(KERN_WARNING "pci_update_slot_number found %d slots with the same name: %s\n", name_count, kobject_name(&slot->kobj)); - - slot->number = slot_nr; - up_write(&pci_bus_sem); -} -EXPORT_SYMBOL_GPL(pci_update_slot_number); - -/** - * pci_destroy_slot - decrement refcount for physical PCI slot - * @slot: struct pci_slot to decrement - * - * %struct pci_slot is refcounted, so destroying them is really easy; we - * just call kobject_put on its kobj and let our release methods do the - * rest. - */ - -void pci_destroy_slot(struct pci_slot *slot) -{ - pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__, - atomic_read(&slot->kobj.kref.refcount) - 1, - pci_domain_nr(slot->bus), slot->bus->number, slot->number); - - down_write(&pci_bus_sem); - kobject_put(&slot->kobj); - up_write(&pci_bus_sem); -} -EXPORT_SYMBOL_GPL(pci_destroy_slot); - -static int pci_slot_init(void) -{ - struct kset *pci_bus_kset; - - pci_bus_kset = bus_get_kset(&pci_bus_type); - pci_slots_kset = kset_create_and_add("slots", NULL, - &pci_bus_kset->kobj); - if (!pci_slots_kset) { - printk(KERN_ERR "PCI: Slot initialization failure\n"); - return -ENOMEM; - } - return 0; -} - -subsys_initcall(pci_slot_init); diff --git a/trunk/drivers/pnp/pnpacpi/core.c b/trunk/drivers/pnp/pnpacpi/core.c index 50902773beaf..c1b9ea34977b 100644 --- a/trunk/drivers/pnp/pnpacpi/core.c +++ b/trunk/drivers/pnp/pnpacpi/core.c @@ -117,9 +117,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) { int power_state; - power_state = acpi_pm_device_sleep_state(&dev->dev, - device_may_wakeup(&dev->dev), - NULL); + power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); if (power_state < 0) power_state = (state.event == PM_EVENT_ON) ? ACPI_STATE_D0 : ACPI_STATE_D3; diff --git a/trunk/drivers/s390/char/sclp_vt220.c b/trunk/drivers/s390/char/sclp_vt220.c index 62576af36f47..3e577f655b18 100644 --- a/trunk/drivers/s390/char/sclp_vt220.c +++ b/trunk/drivers/s390/char/sclp_vt220.c @@ -773,6 +773,7 @@ sclp_vt220_con_init(void) { int rc; + INIT_LIST_HEAD(&sclp_vt220_register.list); if (!CONSOLE_IS_SCLP) return 0; rc = __sclp_vt220_init(); diff --git a/trunk/drivers/s390/char/tape_3590.c b/trunk/drivers/s390/char/tape_3590.c index 8246ef3ab095..42ce7915fc5d 100644 --- a/trunk/drivers/s390/char/tape_3590.c +++ b/trunk/drivers/s390/char/tape_3590.c @@ -1598,7 +1598,7 @@ tape_3590_setup_device(struct tape_device *device) rc = tape_3590_read_dev_chars(device, rdc_data); if (rc) { DBF_LH(3, "Read device characteristics failed!\n"); - goto fail_kmalloc; + goto fail_rdc_data; } rc = tape_std_assign(device); if (rc) diff --git a/trunk/drivers/s390/cio/blacklist.c b/trunk/drivers/s390/cio/blacklist.c index a4a5f2efea48..0bfcbbe375c4 100644 --- a/trunk/drivers/s390/cio/blacklist.c +++ b/trunk/drivers/s390/cio/blacklist.c @@ -97,8 +97,8 @@ static int pure_hex(char **cp, unsigned int *val, int min_digit, return 0; } -static int parse_busid(char *str, int *cssid, int *ssid, int *devno, - int msgtrigger) +static int parse_busid(char *str, unsigned int *cssid, unsigned int *ssid, + unsigned int *devno, int msgtrigger) { char *str_work; int val, rc, ret; @@ -148,7 +148,7 @@ static int parse_busid(char *str, int *cssid, int *ssid, int *devno, static int blacklist_parse_parameters(char *str, range_action action, int msgtrigger) { - int from_cssid, to_cssid, from_ssid, to_ssid, from, to; + unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to; int rc, totalrc; char *parm; range_action ra; diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 82c6a2d45128..b32d7eb3d81a 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -576,12 +576,14 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) err = -ENODEV; goto out; } - if (cio_is_console(sch->schid)) + if (cio_is_console(sch->schid)) { sch->opm = 0xff; - else + sch->isc = 1; + } else { sch->opm = chp_get_sch_opm(sch); + sch->isc = 3; + } sch->lpm = sch->schib.pmcw.pam & sch->opm; - sch->isc = 3; CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X " "- PIM = %02X, PAM = %02X, POM = %02X\n", @@ -704,9 +706,9 @@ void wait_cons_dev(void) if (!console_subchannel_in_use) return; - /* disable all but isc 7 (console device) */ + /* disable all but isc 1 (console device) */ __ctl_store (save_cr6, 6, 6); - cr6 = 0x01000000; + cr6 = 0x40000000; __ctl_load (cr6, 6, 6); do { @@ -788,11 +790,11 @@ cio_probe_console(void) } /* - * enable console I/O-interrupt subclass 7 + * enable console I/O-interrupt subclass 1 */ - ctl_set_bit(6, 24); - console_subchannel.isc = 7; - console_subchannel.schib.pmcw.isc = 7; + ctl_set_bit(6, 30); + console_subchannel.isc = 1; + console_subchannel.schib.pmcw.isc = 1; console_subchannel.schib.pmcw.intparm = (u32)(addr_t)&console_subchannel; ret = cio_modify(&console_subchannel); diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 2f1c68c7a727..db90a74f8714 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -376,9 +376,9 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) #ifdef CONFIG_PM_SLEEP -int acpi_pm_device_sleep_state(struct device *, int, int *); +int acpi_pm_device_sleep_state(struct device *, int *); #else /* !CONFIG_PM_SLEEP */ -static inline int acpi_pm_device_sleep_state(struct device *d, int w, int *p) +static inline int acpi_pm_device_sleep_state(struct device *d, int *p) { if (p) *p = ACPI_STATE_D0; diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index cf108a3c7f59..f054778e916c 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -84,12 +84,6 @@ VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \ *(.pci_fixup_resume) \ VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_resume_early) = .; \ - *(.pci_fixup_resume_early) \ - VMLINUX_SYMBOL(__end_pci_fixups_resume_early) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \ - *(.pci_fixup_suspend) \ - VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \ } \ \ /* RapidIO route ops */ \ diff --git a/trunk/include/asm-s390/system.h b/trunk/include/asm-s390/system.h index e0d4500d5f95..819e7d99ca0c 100644 --- a/trunk/include/asm-s390/system.h +++ b/trunk/include/asm-s390/system.h @@ -315,14 +315,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) asm volatile( \ " lctlg %1,%2,0(%0)\n" \ : : "a" (&array), "i" (low), "i" (high), \ - "m" (*(addrtype *)(array))); \ + "m" (*(addrtype *)(&array))); \ }) #define __ctl_store(array, low, high) ({ \ typedef struct { char _[sizeof(array)]; } addrtype; \ asm volatile( \ " stctg %2,%3,0(%1)\n" \ - : "=m" (*(addrtype *)(array)) \ + : "=m" (*(addrtype *)(&array)) \ : "a" (&array), "i" (low), "i" (high)); \ }) @@ -333,14 +333,14 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) asm volatile( \ " lctl %1,%2,0(%0)\n" \ : : "a" (&array), "i" (low), "i" (high), \ - "m" (*(addrtype *)(array))); \ + "m" (*(addrtype *)(&array))); \ }) #define __ctl_store(array, low, high) ({ \ typedef struct { char _[sizeof(array)]; } addrtype; \ asm volatile( \ " stctl %2,%3,0(%1)\n" \ - : "=m" (*(addrtype *)(array)) \ + : "=m" (*(addrtype *)(&array)) \ : "a" (&array), "i" (low), "i" (high)); \ }) diff --git a/trunk/include/asm-x86/pci-direct.h b/trunk/include/asm-x86/pci-direct.h index 80c775d9fe20..5b21485be573 100644 --- a/trunk/include/asm-x86/pci-direct.h +++ b/trunk/include/asm-x86/pci-direct.h @@ -11,11 +11,7 @@ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset); extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset); extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val); extern void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val); -extern void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val); extern int early_pci_allowed(void); -extern unsigned int pci_early_dump_regs; -extern void early_dump_pci_device(u8 bus, u8 slot, u8 func); -extern void early_dump_pci_devices(void); #endif diff --git a/trunk/include/linux/device.h b/trunk/include/linux/device.h index f71a78d123ae..6a2d04c011bc 100644 --- a/trunk/include/linux/device.h +++ b/trunk/include/linux/device.h @@ -68,8 +68,6 @@ struct bus_type { int (*resume_early)(struct device *dev); int (*resume)(struct device *dev); - struct pm_ext_ops *pm; - struct bus_type_private *p; }; @@ -133,8 +131,6 @@ struct device_driver { int (*resume) (struct device *dev); struct attribute_group **groups; - struct pm_ops *pm; - struct driver_private *p; }; @@ -201,8 +197,6 @@ struct class { int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); - - struct pm_ops *pm; }; extern int __must_check class_register(struct class *class); @@ -254,11 +248,8 @@ struct device_type { struct attribute_group **groups; int (*uevent)(struct device *dev, struct kobj_uevent_env *env); void (*release)(struct device *dev); - int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); - - struct pm_ops *pm; }; /* interface for exporting device attributes */ diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index f8f195c20da2..9918772bf274 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -153,7 +153,7 @@ enum { ide_unknown, ide_generic, ide_pci, ide_qd65xx, ide_umc8672, ide_ht6560b, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, - ide_pmac, ide_etrax100, ide_acorn, + ide_pmac, ide_acorn, ide_au1xxx, ide_palm3710 }; diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index f1f73f79a180..509159bcd4e7 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -17,7 +17,8 @@ #ifndef LINUX_PCI_H #define LINUX_PCI_H -#include /* The pci register defines */ +/* Include the pci register defines */ +#include /* * The PCI interface treats multi-function devices as independent @@ -48,22 +49,12 @@ #include #include #include -#include #include #include /* Include the ID list */ #include -/* pci_slot represents a physical slot */ -struct pci_slot { - struct pci_bus *bus; /* The bus this slot is on */ - struct list_head list; /* node in list of slots on this bus */ - struct hotplug_slot *hotplug; /* Hotplug info (migrate over time) */ - unsigned char number; /* PCI_SLOT(pci_dev->devfn) */ - struct kobject kobj; -}; - /* File state for mmap()s on /proc/bus/pci/X/Y */ enum pci_mmap_state { pci_mmap_io, @@ -151,7 +142,6 @@ struct pci_dev { void *sysdata; /* hook for sys-specific extension */ struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */ - struct pci_slot *slot; /* Physical slot this device is in */ unsigned int devfn; /* encoded device & function index */ unsigned short vendor; @@ -276,7 +266,6 @@ struct pci_bus { struct list_head children; /* list of child buses */ struct list_head devices; /* list of devices on this bus */ struct pci_dev *self; /* bridge device as seen by parent */ - struct list_head slots; /* list of slots on this bus */ struct resource *resource[PCI_BUS_NUM_RESOURCES]; /* address space routed to this bus */ @@ -400,7 +389,7 @@ struct pci_driver { int (*resume_early) (struct pci_dev *dev); int (*resume) (struct pci_dev *dev); /* Device woken up */ void (*shutdown) (struct pci_dev *dev); - struct pm_ext_ops *pm; + struct pci_error_handlers *err_handler; struct device_driver driver; struct pci_dynids dynids; @@ -499,10 +488,6 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata); struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); -struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, - const char *name); -void pci_destroy_slot(struct pci_slot *slot); -void pci_update_slot_number(struct pci_slot *slot, int slot_nr); int pci_scan_slot(struct pci_bus *bus, int devfn); struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn); void pci_device_add(struct pci_dev *dev, struct pci_bus *bus); @@ -1028,9 +1013,7 @@ enum pci_fixup_pass { pci_fixup_header, /* After reading configuration header */ pci_fixup_final, /* Final phase of device fixups */ pci_fixup_enable, /* pci_enable_device() time */ - pci_fixup_resume, /* pci_device_resume() */ - pci_fixup_suspend, /* pci_device_suspend */ - pci_fixup_resume_early, /* pci_device_resume_early() */ + pci_fixup_resume, /* pci_enable_device() time */ }; /* Anonymous variables would be nice... */ @@ -1052,12 +1035,6 @@ enum pci_fixup_pass { #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook) \ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume, \ resume##vendor##device##hook, vendor, device, hook) -#define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook) \ - DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early, \ - resume_early##vendor##device##hook, vendor, device, hook) -#define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook) \ - DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend, \ - suspend##vendor##device##hook, vendor, device, hook) void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); @@ -1082,10 +1059,7 @@ extern int pci_pci_problems; extern unsigned long pci_cardbus_io_size; extern unsigned long pci_cardbus_mem_size; -int pcibios_add_platform_entries(struct pci_dev *dev); -void pcibios_disable_device(struct pci_dev *dev); -int pcibios_set_pcie_reset_state(struct pci_dev *dev, - enum pcie_reset_state state); +extern int pcibios_add_platform_entries(struct pci_dev *dev); #ifdef CONFIG_PCI_MMCONFIG extern void __init pci_mmcfg_early_init(void); diff --git a/trunk/include/linux/pci_hotplug.h b/trunk/include/linux/pci_hotplug.h index a08cd06b541a..8f67e8f2a3cc 100644 --- a/trunk/include/linux/pci_hotplug.h +++ b/trunk/include/linux/pci_hotplug.h @@ -95,6 +95,9 @@ struct hotplug_slot_attribute { * @get_adapter_status: Called to get see if an adapter is present in the slot or not. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. + * @get_address: Called to get pci address of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. * @get_max_bus_speed: Called to get the max bus speed for a slot. * If this field is NULL, the value passed in the struct hotplug_slot_info * will be used when this value is requested by a user. @@ -117,6 +120,7 @@ struct hotplug_slot_ops { int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); + int (*get_address) (struct hotplug_slot *slot, u32 *value); int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); }; @@ -136,6 +140,7 @@ struct hotplug_slot_info { u8 attention_status; u8 latch_status; u8 adapter_status; + u32 address; enum pci_bus_speed max_bus_speed; enum pci_bus_speed cur_bus_speed; }; @@ -161,14 +166,15 @@ struct hotplug_slot { /* Variables below this are for use only by the hotplug pci core. */ struct list_head slot_list; - struct pci_slot *pci_slot; + struct kobject kobj; }; #define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) -extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr); -extern int pci_hp_deregister(struct hotplug_slot *slot); +extern int pci_hp_register (struct hotplug_slot *slot); +extern int pci_hp_deregister (struct hotplug_slot *slot); extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info); +extern struct kset *pci_hotplug_slots_kset; /* PCI Setting Record (Type 0) */ struct hpp_type0 { @@ -221,9 +227,9 @@ struct hotplug_params { #include #include #include +extern acpi_status acpi_run_oshp(acpi_handle handle); extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp); -int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); int acpi_root_bridge(acpi_handle handle); #endif #endif diff --git a/trunk/include/linux/platform_device.h b/trunk/include/linux/platform_device.h index 95ac21ab3a09..3261681c82a4 100644 --- a/trunk/include/linux/platform_device.h +++ b/trunk/include/linux/platform_device.h @@ -53,7 +53,6 @@ struct platform_driver { int (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); - struct pm_ext_ops *pm; struct device_driver driver; }; diff --git a/trunk/include/linux/pm.h b/trunk/include/linux/pm.h index 4ad9de94449a..39a7ee859b67 100644 --- a/trunk/include/linux/pm.h +++ b/trunk/include/linux/pm.h @@ -112,9 +112,7 @@ typedef struct pm_message { int event; } pm_message_t; -/** - * struct pm_ops - device PM callbacks - * +/* * Several driver power state transitions are externally visible, affecting * the state of pending I/O queues and (for drivers that touch hardware) * interrupts, wakeups, DMA, and other hardware state. There may also be @@ -122,284 +120,6 @@ typedef struct pm_message { * to the rest of the driver stack (such as a driver that's ON gating off * clocks which are not in active use). * - * The externally visible transitions are handled with the help of the following - * callbacks included in this structure: - * - * @prepare: Prepare the device for the upcoming transition, but do NOT change - * its hardware state. Prevent new children of the device from being - * registered after @prepare() returns (the driver's subsystem and - * generally the rest of the kernel is supposed to prevent new calls to the - * probe method from being made too once @prepare() has succeeded). If - * @prepare() detects a situation it cannot handle (e.g. registration of a - * child already in progress), it may return -EAGAIN, so that the PM core - * can execute it once again (e.g. after the new child has been registered) - * to recover from the race condition. This method is executed for all - * kinds of suspend transitions and is followed by one of the suspend - * callbacks: @suspend(), @freeze(), or @poweroff(). - * The PM core executes @prepare() for all devices before starting to - * execute suspend callbacks for any of them, so drivers may assume all of - * the other devices to be present and functional while @prepare() is being - * executed. In particular, it is safe to make GFP_KERNEL memory - * allocations from within @prepare(). However, drivers may NOT assume - * anything about the availability of the user space at that time and it - * is not correct to request firmware from within @prepare() (it's too - * late to do that). [To work around this limitation, drivers may - * register suspend and hibernation notifiers that are executed before the - * freezing of tasks.] - * - * @complete: Undo the changes made by @prepare(). This method is executed for - * all kinds of resume transitions, following one of the resume callbacks: - * @resume(), @thaw(), @restore(). Also called if the state transition - * fails before the driver's suspend callback (@suspend(), @freeze(), - * @poweroff()) can be executed (e.g. if the suspend callback fails for one - * of the other devices that the PM core has unsuccessfully attempted to - * suspend earlier). - * The PM core executes @complete() after it has executed the appropriate - * resume callback for all devices. - * - * @suspend: Executed before putting the system into a sleep state in which the - * contents of main memory are preserved. Quiesce the device, put it into - * a low power state appropriate for the upcoming system state (such as - * PCI_D3hot), and enable wakeup events as appropriate. - * - * @resume: Executed after waking the system up from a sleep state in which the - * contents of main memory were preserved. Put the device into the - * appropriate state, according to the information saved in memory by the - * preceding @suspend(). The driver starts working again, responding to - * hardware events and software requests. The hardware may have gone - * through a power-off reset, or it may have maintained state from the - * previous suspend() which the driver may rely on while resuming. On most - * platforms, there are no restrictions on availability of resources like - * clocks during @resume(). - * - * @freeze: Hibernation-specific, executed before creating a hibernation image. - * Quiesce operations so that a consistent image can be created, but do NOT - * otherwise put the device into a low power device state and do NOT emit - * system wakeup events. Save in main memory the device settings to be - * used by @restore() during the subsequent resume from hibernation or by - * the subsequent @thaw(), if the creation of the image or the restoration - * of main memory contents from it fails. - * - * @thaw: Hibernation-specific, executed after creating a hibernation image OR - * if the creation of the image fails. Also executed after a failing - * attempt to restore the contents of main memory from such an image. - * Undo the changes made by the preceding @freeze(), so the device can be - * operated in the same way as immediately before the call to @freeze(). - * - * @poweroff: Hibernation-specific, executed after saving a hibernation image. - * Quiesce the device, put it into a low power state appropriate for the - * upcoming system state (such as PCI_D3hot), and enable wakeup events as - * appropriate. - * - * @restore: Hibernation-specific, executed after restoring the contents of main - * memory from a hibernation image. Driver starts working again, - * responding to hardware events and software requests. Drivers may NOT - * make ANY assumptions about the hardware state right prior to @restore(). - * On most platforms, there are no restrictions on availability of - * resources like clocks during @restore(). - * - * All of the above callbacks, except for @complete(), return error codes. - * However, the error codes returned by the resume operations, @resume(), - * @thaw(), and @restore(), do not cause the PM core to abort the resume - * transition during which they are returned. The error codes returned in - * that cases are only printed by the PM core to the system logs for debugging - * purposes. Still, it is recommended that drivers only return error codes - * from their resume methods in case of an unrecoverable failure (i.e. when the - * device being handled refuses to resume and becomes unusable) to allow us to - * modify the PM core in the future, so that it can avoid attempting to handle - * devices that failed to resume and their children. - * - * It is allowed to unregister devices while the above callbacks are being - * executed. However, it is not allowed to unregister a device from within any - * of its own callbacks. - */ - -struct pm_ops { - int (*prepare)(struct device *dev); - void (*complete)(struct device *dev); - int (*suspend)(struct device *dev); - int (*resume)(struct device *dev); - int (*freeze)(struct device *dev); - int (*thaw)(struct device *dev); - int (*poweroff)(struct device *dev); - int (*restore)(struct device *dev); -}; - -/** - * struct pm_ext_ops - extended device PM callbacks - * - * Some devices require certain operations related to suspend and hibernation - * to be carried out with interrupts disabled. Thus, 'struct pm_ext_ops' below - * is defined, adding callbacks to be executed with interrupts disabled to - * 'struct pm_ops'. - * - * The following callbacks included in 'struct pm_ext_ops' are executed with - * the nonboot CPUs switched off and with interrupts disabled on the only - * functional CPU. They also are executed with the PM core list of devices - * locked, so they must NOT unregister any devices. - * - * @suspend_noirq: Complete the operations of ->suspend() by carrying out any - * actions required for suspending the device that need interrupts to be - * disabled - * - * @resume_noirq: Prepare for the execution of ->resume() by carrying out any - * actions required for resuming the device that need interrupts to be - * disabled - * - * @freeze_noirq: Complete the operations of ->freeze() by carrying out any - * actions required for freezing the device that need interrupts to be - * disabled - * - * @thaw_noirq: Prepare for the execution of ->thaw() by carrying out any - * actions required for thawing the device that need interrupts to be - * disabled - * - * @poweroff_noirq: Complete the operations of ->poweroff() by carrying out any - * actions required for handling the device that need interrupts to be - * disabled - * - * @restore_noirq: Prepare for the execution of ->restore() by carrying out any - * actions required for restoring the operations of the device that need - * interrupts to be disabled - * - * All of the above callbacks return error codes, but the error codes returned - * by the resume operations, @resume_noirq(), @thaw_noirq(), and - * @restore_noirq(), do not cause the PM core to abort the resume transition - * during which they are returned. The error codes returned in that cases are - * only printed by the PM core to the system logs for debugging purposes. - * Still, as stated above, it is recommended that drivers only return error - * codes from their resume methods if the device being handled fails to resume - * and is not usable any more. - */ - -struct pm_ext_ops { - struct pm_ops base; - int (*suspend_noirq)(struct device *dev); - int (*resume_noirq)(struct device *dev); - int (*freeze_noirq)(struct device *dev); - int (*thaw_noirq)(struct device *dev); - int (*poweroff_noirq)(struct device *dev); - int (*restore_noirq)(struct device *dev); -}; - -/** - * PM_EVENT_ messages - * - * The following PM_EVENT_ messages are defined for the internal use of the PM - * core, in order to provide a mechanism allowing the high level suspend and - * hibernation code to convey the necessary information to the device PM core - * code: - * - * ON No transition. - * - * FREEZE System is going to hibernate, call ->prepare() and ->freeze() - * for all devices. - * - * SUSPEND System is going to suspend, call ->prepare() and ->suspend() - * for all devices. - * - * HIBERNATE Hibernation image has been saved, call ->prepare() and - * ->poweroff() for all devices. - * - * QUIESCE Contents of main memory are going to be restored from a (loaded) - * hibernation image, call ->prepare() and ->freeze() for all - * devices. - * - * RESUME System is resuming, call ->resume() and ->complete() for all - * devices. - * - * THAW Hibernation image has been created, call ->thaw() and - * ->complete() for all devices. - * - * RESTORE Contents of main memory have been restored from a hibernation - * image, call ->restore() and ->complete() for all devices. - * - * RECOVER Creation of a hibernation image or restoration of the main - * memory contents from a hibernation image has failed, call - * ->thaw() and ->complete() for all devices. - */ - -#define PM_EVENT_ON 0x0000 -#define PM_EVENT_FREEZE 0x0001 -#define PM_EVENT_SUSPEND 0x0002 -#define PM_EVENT_HIBERNATE 0x0004 -#define PM_EVENT_QUIESCE 0x0008 -#define PM_EVENT_RESUME 0x0010 -#define PM_EVENT_THAW 0x0020 -#define PM_EVENT_RESTORE 0x0040 -#define PM_EVENT_RECOVER 0x0080 - -#define PM_EVENT_SLEEP (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE) - -#define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, }) -#define PMSG_QUIESCE ((struct pm_message){ .event = PM_EVENT_QUIESCE, }) -#define PMSG_SUSPEND ((struct pm_message){ .event = PM_EVENT_SUSPEND, }) -#define PMSG_HIBERNATE ((struct pm_message){ .event = PM_EVENT_HIBERNATE, }) -#define PMSG_RESUME ((struct pm_message){ .event = PM_EVENT_RESUME, }) -#define PMSG_THAW ((struct pm_message){ .event = PM_EVENT_THAW, }) -#define PMSG_RESTORE ((struct pm_message){ .event = PM_EVENT_RESTORE, }) -#define PMSG_RECOVER ((struct pm_message){ .event = PM_EVENT_RECOVER, }) -#define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, }) - -/** - * Device power management states - * - * These state labels are used internally by the PM core to indicate the current - * status of a device with respect to the PM core operations. - * - * DPM_ON Device is regarded as operational. Set this way - * initially and when ->complete() is about to be called. - * Also set when ->prepare() fails. - * - * DPM_PREPARING Device is going to be prepared for a PM transition. Set - * when ->prepare() is about to be called. - * - * DPM_RESUMING Device is going to be resumed. Set when ->resume(), - * ->thaw(), or ->restore() is about to be called. - * - * DPM_SUSPENDING Device has been prepared for a power transition. Set - * when ->prepare() has just succeeded. - * - * DPM_OFF Device is regarded as inactive. Set immediately after - * ->suspend(), ->freeze(), or ->poweroff() has succeeded. - * Also set when ->resume()_noirq, ->thaw_noirq(), or - * ->restore_noirq() is about to be called. - * - * DPM_OFF_IRQ Device is in a "deep sleep". Set immediately after - * ->suspend_noirq(), ->freeze_noirq(), or - * ->poweroff_noirq() has just succeeded. - */ - -enum dpm_state { - DPM_INVALID, - DPM_ON, - DPM_PREPARING, - DPM_RESUMING, - DPM_SUSPENDING, - DPM_OFF, - DPM_OFF_IRQ, -}; - -struct dev_pm_info { - pm_message_t power_state; - unsigned can_wakeup:1; - unsigned should_wakeup:1; - enum dpm_state status; /* Owned by the PM core */ -#ifdef CONFIG_PM_SLEEP - struct list_head entry; -#endif -}; - -/* - * The PM_EVENT_ messages are also used by drivers implementing the legacy - * suspend framework, based on the ->suspend() and ->resume() callbacks common - * for suspend and hibernation transitions, according to the rules below. - */ - -/* Necessary, because several drivers use PM_EVENT_PRETHAW */ -#define PM_EVENT_PRETHAW PM_EVENT_QUIESCE - -/* * One transition is triggered by resume(), after a suspend() call; the * message is implicit: * @@ -444,13 +164,35 @@ struct dev_pm_info { * or from system low-power states such as standby or suspend-to-RAM. */ -#ifdef CONFIG_PM_SLEEP -extern void device_pm_lock(void); -extern void device_power_up(pm_message_t state); -extern void device_resume(pm_message_t state); +#define PM_EVENT_ON 0 +#define PM_EVENT_FREEZE 1 +#define PM_EVENT_SUSPEND 2 +#define PM_EVENT_HIBERNATE 4 +#define PM_EVENT_PRETHAW 8 + +#define PM_EVENT_SLEEP (PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE) + +#define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, }) +#define PMSG_PRETHAW ((struct pm_message){ .event = PM_EVENT_PRETHAW, }) +#define PMSG_SUSPEND ((struct pm_message){ .event = PM_EVENT_SUSPEND, }) +#define PMSG_HIBERNATE ((struct pm_message){ .event = PM_EVENT_HIBERNATE, }) +#define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, }) + +struct dev_pm_info { + pm_message_t power_state; + unsigned can_wakeup:1; + unsigned should_wakeup:1; + bool sleeping:1; /* Owned by the PM core */ +#ifdef CONFIG_PM_SLEEP + struct list_head entry; +#endif +}; -extern void device_pm_unlock(void); extern int device_power_down(pm_message_t state); +extern void device_power_up(void); +extern void device_resume(void); + +#ifdef CONFIG_PM_SLEEP extern int device_suspend(pm_message_t state); extern int device_prepare_suspend(pm_message_t state); diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index 554429ade079..d05f6b564998 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -894,8 +894,6 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) if (!sfd) goto out_put_dentry; - err = -ENOMEM; - file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); if (!file) goto out_free; diff --git a/trunk/kernel/power/disk.c b/trunk/kernel/power/disk.c index d416be0efa8a..14a656cdc652 100644 --- a/trunk/kernel/power/disk.c +++ b/trunk/kernel/power/disk.c @@ -193,7 +193,6 @@ static int create_image(int platform_mode) if (error) return error; - device_pm_lock(); local_irq_disable(); /* At this point, device_suspend() has been called, but *not* * device_power_down(). We *must* call device_power_down() now. @@ -225,11 +224,9 @@ static int create_image(int platform_mode) /* NOTE: device_power_up() is just a resume() for devices * that suspended with irqs off ... no overall powerup. */ - device_power_up(in_suspend ? - (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); + device_power_up(); Enable_irqs: local_irq_enable(); - device_pm_unlock(); return error; } @@ -283,8 +280,7 @@ int hibernation_snapshot(int platform_mode) Finish: platform_finish(platform_mode); Resume_devices: - device_resume(in_suspend ? - (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); + device_resume(); Resume_console: resume_console(); Close: @@ -304,9 +300,8 @@ static int resume_target_kernel(void) { int error; - device_pm_lock(); local_irq_disable(); - error = device_power_down(PMSG_QUIESCE); + error = device_power_down(PMSG_PRETHAW); if (error) { printk(KERN_ERR "PM: Some devices failed to power down, " "aborting resume\n"); @@ -334,10 +329,9 @@ static int resume_target_kernel(void) swsusp_free(); restore_processor_state(); touch_softlockup_watchdog(); - device_power_up(PMSG_RECOVER); + device_power_up(); Enable_irqs: local_irq_enable(); - device_pm_unlock(); return error; } @@ -356,7 +350,7 @@ int hibernation_restore(int platform_mode) pm_prepare_console(); suspend_console(); - error = device_suspend(PMSG_QUIESCE); + error = device_suspend(PMSG_PRETHAW); if (error) goto Finish; @@ -368,7 +362,7 @@ int hibernation_restore(int platform_mode) enable_nonboot_cpus(); } platform_restore_cleanup(platform_mode); - device_resume(PMSG_RECOVER); + device_resume(); Finish: resume_console(); pm_restore_console(); @@ -409,7 +403,6 @@ int hibernation_platform_enter(void) if (error) goto Finish; - device_pm_lock(); local_irq_disable(); error = device_power_down(PMSG_HIBERNATE); if (!error) { @@ -418,7 +411,6 @@ int hibernation_platform_enter(void) while (1); } local_irq_enable(); - device_pm_unlock(); /* * We don't need to reenable the nonboot CPUs or resume consoles, since @@ -427,7 +419,7 @@ int hibernation_platform_enter(void) Finish: hibernation_ops->finish(); Resume_devices: - device_resume(PMSG_RESTORE); + device_resume(); Resume_console: resume_console(); Close: diff --git a/trunk/kernel/power/main.c b/trunk/kernel/power/main.c index d023b6b584e5..6a6d5eb3524e 100644 --- a/trunk/kernel/power/main.c +++ b/trunk/kernel/power/main.c @@ -228,7 +228,6 @@ static int suspend_enter(suspend_state_t state) { int error = 0; - device_pm_lock(); arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); @@ -240,11 +239,10 @@ static int suspend_enter(suspend_state_t state) if (!suspend_test(TEST_CORE)) error = suspend_ops->enter(state); - device_power_up(PMSG_RESUME); + device_power_up(); Done: arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); - device_pm_unlock(); return error; } @@ -293,7 +291,7 @@ int suspend_devices_and_enter(suspend_state_t state) if (suspend_ops->finish) suspend_ops->finish(); Resume_devices: - device_resume(PMSG_RESUME); + device_resume(); Resume_console: resume_console(); Close: diff --git a/trunk/lib/kobject.c b/trunk/lib/kobject.c index dcade0543bd2..718e5101c263 100644 --- a/trunk/lib/kobject.c +++ b/trunk/lib/kobject.c @@ -439,7 +439,6 @@ int kobject_rename(struct kobject *kobj, const char *new_name) return error; } -EXPORT_SYMBOL_GPL(kobject_rename); /** * kobject_move - move object to another parent