Commit dc7c65db authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (72 commits)
  Revert "x86/PCI: ACPI based PCI gap calculation"
  PCI: remove unnecessary volatile in PCIe hotplug struct controller
  x86/PCI: ACPI based PCI gap calculation
  PCI: include linux/pm_wakeup.h for device_set_wakeup_capable
  PCI PM: Fix pci_prepare_to_sleep
  x86/PCI: Fix PCI config space for domains > 0
  Fix acpi_pm_device_sleep_wake() by providing a stub for CONFIG_PM_SLEEP=n
  PCI: Simplify PCI device PM code
  PCI PM: Introduce pci_prepare_to_sleep and pci_back_from_sleep
  PCI ACPI: Rework PCI handling of wake-up
  ACPI: Introduce new device wakeup flag 'prepared'
  ACPI: Introduce acpi_device_sleep_wake function
  PCI: rework pci_set_power_state function to call platform first
  PCI: Introduce platform_pci_power_manageable function
  ACPI: Introduce acpi_bus_power_manageable function
  PCI: make pci_name use dev_name
  PCI: handle pci_name() being const
  PCI: add stub for pci_set_consistent_dma_mask()
  PCI: remove unused arch pcibios_update_resource() functions
  PCI: fix pci_setup_device()'s sprinting into a const buffer
  ...

Fixed up conflicts in various files (arch/x86/kernel/setup_64.c,
arch/x86/pci/irq.c, arch/x86/pci/pci.h, drivers/acpi/sleep/main.c,
drivers/pci/pci.c, drivers/pci/pci.h, include/acpi/acpi_bus.h) from x86
and ACPI updates manually.
parents 8a0ca91e 58b6e553
...@@ -147,10 +147,14 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -147,10 +147,14 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0 default: 0
acpi_sleep= [HW,ACPI] Sleep options acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode, s3_beep } Format: { s3_bios, s3_mode, s3_beep, old_ordering }
See Documentation/power/video.txt for s3_bios and s3_mode. See Documentation/power/video.txt for s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called. as soon as the kernel's real-mode entry point is called.
old_ordering causes the ACPI 1.0 ordering of the _PTS
control method, wrt putting devices into low power
states, to be enforced (the ACPI 2.0 ordering of _PTS is
used by default).
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low } Format: { level | edge | high | low }
...@@ -1537,6 +1541,9 @@ and is between 256 and 4096 characters. It is defined in the file ...@@ -1537,6 +1541,9 @@ and is between 256 and 4096 characters. It is defined in the file
Use with caution as certain devices share Use with caution as certain devices share
address decoders between ROMs and other address decoders between ROMs and other
resources. 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 irqmask=0xMMMM [X86-32] Set a bit mask of IRQs allowed to be
assigned automatically to PCI devices. You can assigned automatically to PCI devices. You can
make the kernel exclude IRQs of your ISA cards make the kernel exclude IRQs of your ISA cards
......
...@@ -248,7 +248,7 @@ S: Supported ...@@ -248,7 +248,7 @@ S: Supported
ACPI PCI HOTPLUG DRIVER ACPI PCI HOTPLUG DRIVER
P: Kristen Carlson Accardi P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
ACPI THERMAL DRIVER ACPI THERMAL DRIVER
...@@ -1145,21 +1145,21 @@ COMPACTPCI HOTPLUG CORE ...@@ -1145,21 +1145,21 @@ COMPACTPCI HOTPLUG CORE
P: Scott Murray P: Scott Murray
M: scottm@somanetworks.com M: scottm@somanetworks.com
M: scott@spiteful.org M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
P: Scott Murray P: Scott Murray
M: scottm@somanetworks.com M: scottm@somanetworks.com
M: scott@spiteful.org M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
COMPACTPCI HOTPLUG GENERIC DRIVER COMPACTPCI HOTPLUG GENERIC DRIVER
P: Scott Murray P: Scott Murray
M: scottm@somanetworks.com M: scottm@somanetworks.com
M: scott@spiteful.org M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
COMPAL LAPTOP SUPPORT COMPAL LAPTOP SUPPORT
...@@ -3219,7 +3219,7 @@ S: Supported ...@@ -3219,7 +3219,7 @@ S: Supported
PCIE HOTPLUG DRIVER PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
PCMCIA SUBSYSTEM PCMCIA SUBSYSTEM
...@@ -3865,7 +3865,7 @@ S: Maintained ...@@ -3865,7 +3865,7 @@ S: Maintained
SHPC HOTPLUG DRIVER SHPC HOTPLUG DRIVER
P: Kristen Carlson Accardi P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net L: linux-pci@vger.kernel.org
S: Supported S: Supported
SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
......
...@@ -19,36 +19,6 @@ ...@@ -19,36 +19,6 @@
#include "pci-frv.h" #include "pci-frv.h"
#if 0
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
u32 new, check;
int reg;
new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
if (resource < 6) {
reg = PCI_BASE_ADDRESS_0 + 4*resource;
} else if (resource == PCI_ROM_RESOURCE) {
res->flags |= IORESOURCE_ROM_ENABLE;
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
return;
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
#endif
/* /*
* We need to avoid collisions with `mirrored' VGA ports * We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the * and other strange ISA hardware, so we always want the
......
...@@ -373,15 +373,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) ...@@ -373,15 +373,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return(0); return(0);
} }
/*****************************************************************************/
void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource)
{
printk(KERN_WARNING "%s(%d): no support for changing PCI resources...\n",
__FILE__, __LINE__);
}
/*****************************************************************************/ /*****************************************************************************/
/* /*
......
...@@ -345,42 +345,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) ...@@ -345,42 +345,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pcibios_enable_resources(dev); return pcibios_enable_resources(dev);
} }
void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
u32 new, check;
int reg;
return;
new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
if (resource < 6) {
reg = PCI_BASE_ADDRESS_0 + 4 * resource;
} else if (resource == PCI_ROM_RESOURCE) {
res->flags |= IORESOURCE_ROM_ENABLE;
reg = dev->rom_base_reg;
} else {
/*
* Somebody might have asked allocation of a non-standard
* resource
*/
return;
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) &
((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
void pcibios_align_resource(void *data, struct resource *res, void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align) resource_size_t size, resource_size_t align)
{ {
......
...@@ -76,38 +76,6 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) ...@@ -76,38 +76,6 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus)
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
} }
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
u32 new, check;
int reg;
new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
if (resource < 6) {
reg = PCI_BASE_ADDRESS_0 + 4*resource;
} else if (resource == PCI_ROM_RESOURCE) {
res->flags |= IORESOURCE_ROM_ENABLE;
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
/*
* Somebody might have asked allocation of a non-standard
* resource
*/
return;
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
void pcibios_align_resource(void *data, struct resource *res, void pcibios_align_resource(void *data, struct resource *res,
resource_size_t size, resource_size_t align) resource_size_t size, resource_size_t align)
__attribute__ ((weak)); __attribute__ ((weak));
......
...@@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, ...@@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->class = class >> 8; dev->class = class >> 8;
dev->revision = class & 0xff; dev->revision = class & 0xff;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), sprintf(dev->dev.bus_id, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
if (ofpci_verbose) if (ofpci_verbose)
......
...@@ -158,6 +158,8 @@ static int __init acpi_sleep_setup(char *str) ...@@ -158,6 +158,8 @@ static int __init acpi_sleep_setup(char *str)
acpi_realmode_flags |= 2; acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0) if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4; acpi_realmode_flags |= 4;
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ','); str = strchr(str, ',');
if (str != NULL) if (str != NULL)
str += strspn(str, ", \t"); str += strspn(str, ", \t");
......
...@@ -1213,9 +1213,9 @@ static int suspend(int vetoable) ...@@ -1213,9 +1213,9 @@ static int suspend(int vetoable)
if (err != APM_SUCCESS) if (err != APM_SUCCESS)
apm_error("suspend", err); apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO; err = (err == APM_SUCCESS) ? 0 : -EIO;
device_power_up(); device_power_up(PMSG_RESUME);
local_irq_enable(); local_irq_enable();
device_resume(); device_resume(PMSG_RESUME);
queue_event(APM_NORMAL_RESUME, NULL); queue_event(APM_NORMAL_RESUME, NULL);
spin_lock(&user_list_lock); spin_lock(&user_list_lock);
for (as = user_list; as != NULL; as = as->next) { for (as = user_list; as != NULL; as = as->next) {
...@@ -1240,7 +1240,7 @@ static void standby(void) ...@@ -1240,7 +1240,7 @@ static void standby(void)
apm_error("standby", err); apm_error("standby", err);
local_irq_disable(); local_irq_disable();
device_power_up(); device_power_up(PMSG_RESUME);
local_irq_enable(); local_irq_enable();
} }
...@@ -1326,7 +1326,7 @@ static void check_events(void) ...@@ -1326,7 +1326,7 @@ static void check_events(void)
ignore_bounce = 1; ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME) if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) { || (ignore_normal_resume == 0)) {
device_resume(); device_resume(PMSG_RESUME);
queue_event(event, NULL); queue_event(event, NULL);
} }
ignore_normal_resume = 0; ignore_normal_resume = 0;
......
...@@ -120,7 +120,18 @@ static struct chipset early_qrk[] __initdata = { ...@@ -120,7 +120,18 @@ static struct chipset early_qrk[] __initdata = {
{} {}
}; };
static void __init check_dev_quirk(int num, int slot, int func) /**
* check_dev_quirk - apply early quirks to a given PCI device
* @num: bus number
* @slot: slot number
* @func: PCI function
*
* Check the vendor & device ID against the early quirks table.
*
* If the device is single function, let early_quirks() know so we don't
* poke at this device again.
*/
static int __init check_dev_quirk(int num, int slot, int func)
{ {
u16 class; u16 class;
u16 vendor; u16 vendor;
...@@ -131,7 +142,7 @@ static void __init check_dev_quirk(int num, int slot, int func) ...@@ -131,7 +142,7 @@ static void __init check_dev_quirk(int num, int slot, int func)
class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE); class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE);
if (class == 0xffff) if (class == 0xffff)
return; return -1; /* no class, treat as single function */
vendor = read_pci_config_16(num, slot, func, PCI_VENDOR_ID); vendor = read_pci_config_16(num, slot, func, PCI_VENDOR_ID);
...@@ -154,7 +165,9 @@ static void __init check_dev_quirk(int num, int slot, int func) ...@@ -154,7 +165,9 @@ static void __init check_dev_quirk(int num, int slot, int func)
type = read_pci_config_byte(num, slot, func, type = read_pci_config_byte(num, slot, func,
PCI_HEADER_TYPE); PCI_HEADER_TYPE);
if (!(type & 0x80)) if (!(type & 0x80))
return; return -1;
return 0;
} }
void __init early_quirks(void) void __init early_quirks(void)
...@@ -167,6 +180,9 @@ void __init early_quirks(void) ...@@ -167,6 +180,9 @@ void __init early_quirks(void)
/* Poor man's PCI discovery */ /* Poor man's PCI discovery */
for (num = 0; num < 32; num++) for (num = 0; num < 32; num++)
for (slot = 0; slot < 32; slot++) for (slot = 0; slot < 32; slot++)
for (func = 0; func < 8; func++) for (func = 0; func < 8; func++) {
check_dev_quirk(num, slot, func); /* Only probe function 0 on single fn devices */
if (check_dev_quirk(num, slot, func))
break;
}
} }
...@@ -684,6 +684,11 @@ void __init setup_arch(char **cmdline_p) ...@@ -684,6 +684,11 @@ void __init setup_arch(char **cmdline_p)
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
} }
#ifdef CONFIG_PCI
if (pci_early_dump_regs)
early_dump_pci_devices();
#endif
finish_e820_parsing(); finish_e820_parsing();
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF; PCI_PROBE_MMCONF;
unsigned int pci_early_dump_regs;
static int pci_bf_sort; static int pci_bf_sort;
int pci_routeirq; int pci_routeirq;
int pcibios_last_bus = -1; int pcibios_last_bus = -1;
...@@ -31,7 +32,7 @@ struct pci_raw_ops *raw_pci_ext_ops; ...@@ -31,7 +32,7 @@ struct pci_raw_ops *raw_pci_ext_ops;
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val) int reg, int len, u32 *val)
{ {
if (reg < 256 && raw_pci_ops) if (domain == 0 && reg < 256 && raw_pci_ops)
return raw_pci_ops->read(domain, bus, devfn, reg, len, val); return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
if (raw_pci_ext_ops) if (raw_pci_ext_ops)
return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val); return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
...@@ -41,7 +42,7 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, ...@@ -41,7 +42,7 @@ int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 val) int reg, int len, u32 val)
{ {
if (reg < 256 && raw_pci_ops) if (domain == 0 && reg < 256 && raw_pci_ops)
return raw_pci_ops->write(domain, bus, devfn, reg, len, val); return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
if (raw_pci_ext_ops) if (raw_pci_ext_ops)
return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val); return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
...@@ -121,6 +122,21 @@ void __init dmi_check_skip_isa_align(void) ...@@ -121,6 +122,21 @@ void __init dmi_check_skip_isa_align(void)
dmi_check_system(can_skip_pciprobe_dmi_table); 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 * Called after each bus is probed, but before its children
* are examined. * are examined.
...@@ -128,7 +144,11 @@ void __init dmi_check_skip_isa_align(void) ...@@ -128,7 +144,11 @@ void __init dmi_check_skip_isa_align(void)
void __devinit pcibios_fixup_bus(struct pci_bus *b) void __devinit pcibios_fixup_bus(struct pci_bus *b)
{ {
struct pci_dev *dev;
pci_read_bridge_bases(b); pci_read_bridge_bases(b);
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
} }
/* /*
...@@ -481,12 +501,18 @@ char * __devinit pcibios_setup(char *str) ...@@ -481,12 +501,18 @@ char * __devinit pcibios_setup(char *str)
else if (!strcmp(str, "rom")) { else if (!strcmp(str, "rom")) {
pci_probe |= PCI_ASSIGN_ROMS; pci_probe |= PCI_ASSIGN_ROMS;
return NULL; return NULL;
} else if (!strcmp(str, "norom")) {
pci_probe |= PCI_NOASSIGN_ROMS;
return NULL;
} else if (!strcmp(str, "assign-busses")) { } else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES; pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL; return NULL;
} else if (!strcmp(str, "use_crs")) { } else if (!strcmp(str, "use_crs")) {
pci_probe |= PCI_USE__CRS; pci_probe |= PCI_USE__CRS;
return NULL; return NULL;
} else if (!strcmp(str, "earlydump")) {
pci_early_dump_regs = 1;
return NULL;
} else if (!strcmp(str, "routeirq")) { } else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1; pci_routeirq = 1;
return NULL; return NULL;
......
...@@ -49,7 +49,14 @@ void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) ...@@ -49,7 +49,14 @@ 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); PDprintk("%x writing to %x: %x\n", slot, offset, val);
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
outb(val, 0xcfc); 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));
} }
int early_pci_allowed(void) int early_pci_allowed(void)
...@@ -57,3 +64,54 @@ int early_pci_allowed(void) ...@@ -57,3 +64,54 @@ int early_pci_allowed(void)
return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) == return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
PCI_PROBE_CONF1; 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;
}
}
}
}
This diff is collapsed.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define PCI_USE__CRS 0x10000 #define PCI_USE__CRS 0x10000
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
#define PCI_HAS_IO_ECS 0x40000 #define PCI_HAS_IO_ECS 0x40000
#define PCI_NOASSIGN_ROMS 0x80000
extern unsigned int pci_probe; extern unsigned int pci_probe;
extern unsigned long pirq_table_addr; extern unsigned long pirq_table_addr;
......
...@@ -336,6 +336,15 @@ config ACPI_EC ...@@ -336,6 +336,15 @@ config ACPI_EC
the battery and thermal drivers. If you are compiling for a the battery and thermal drivers. If you are compiling for a
mobile system, say Y. 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 config ACPI_POWER
bool bool
default y default y
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o ...@@ -48,6 +48,7 @@ obj-$(CONFIG_ACPI_DOCK) += dock.o
obj-$(CONFIG_ACPI_BAY) += bay.o obj-$(CONFIG_ACPI_BAY) += bay.o
obj-$(CONFIG_ACPI_VIDEO) += video.o obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.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_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_CONTAINER) += container.o
......
...@@ -295,6 +295,28 @@ int acpi_bus_set_power(acpi_handle handle, int state) ...@@ -295,6 +295,28 @@ int acpi_bus_set_power(acpi_handle handle, int state)
EXPORT_SYMBOL(acpi_bus_set_power); EXPORT_SYMBOL(acpi_bus_set_power);
bool acpi_bus_power_manageable(acpi_handle handle)
{
struct acpi_device *device;
int result;
result = acpi_bus_get_device(handle, &device);
return result ? false : device->flags.power_manageable;
}
EXPORT_SYMBOL(acpi_bus_power_manageable);
bool acpi_bus_can_wakeup(acpi_handle handle)
{
struct acpi_device *device;
int result;
result = acpi_bus_get_device(handle, &device);
return result ? false : device->wakeup.flags.valid;
}
EXPORT_SYMBOL(acpi_bus_can_wakeup);
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Event Management Event Management
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
......
...@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) ...@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
"firmware_node"); "firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node"); "physical_node");
if (acpi_dev->wakeup.flags.valid)
device_set_wakeup_capable(dev, true);
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -292,69 +292,135 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) ...@@ -292,69 +292,135 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
return 0; return 0;
} }
/**
* acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
* ACPI 3.0) _PSW (Power State Wake)
* @dev: Device to handle.
* @enable: 0 - disable, 1 - enable the wake capabilities of the device.
* @sleep_state: Target sleep state of the system.
* @dev_state: Target power state of the device.
*
* Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
* State Wake) for the device, if present. On failure reset the device's
* wakeup.flags.valid flag.
*
* RETURN VALUE:
* 0 if either _DSW or _PSW has been successfully executed
* 0 if neither _DSW nor _PSW has been found
* -ENODEV if the execution of either _DSW or _PSW has failed
*/
int acpi_device_sleep_wake(struct acpi_device *dev,
int enable, int sleep_state, int dev_state)
{
union acpi_object in_arg[3];
struct acpi_object_list arg_list = { 3, in_arg };
acpi_status status = AE_OK;
/*
* Try to execute _DSW first.
*
* Three agruments are needed for the _DSW object:
* Argument 0: enable/disable the wake capabilities
* Argument 1: target system state
* Argument 2: target device state
* When _DSW object is called to disable the wake capabilities, maybe
* the first argument is filled. The values of the other two agruments
* are meaningless.
*/
in_arg[0].type = ACPI_TYPE_INTEGER;
in_arg[0].integer.value = enable;
in_arg[1].type = ACPI_TYPE_INTEGER;
in_arg[1].integer.value = sleep_state;
in_arg[2].type = ACPI_TYPE_INTEGER;
in_arg[2].integer.value = dev_state;
status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL);
if (ACPI_SUCCESS(status)) {
return 0;
} else if (status != AE_NOT_FOUND) {
printk(KERN_ERR PREFIX "_DSW execution failed\n");
dev->wakeup.flags.valid = 0;
return -ENODEV;
}
/* Execute _PSW */
arg_list.count = 1;
in_arg[0].integer.value = enable;
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
printk(KERN_ERR PREFIX "_PSW execution failed\n");
dev->wakeup.flags.valid = 0;
return -ENODEV;
}
return 0;
}
/* /*
* Prepare a wakeup device, two steps (Ref ACPI 2.0:P229): * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
* 1. Power on the power resources required for the wakeup device * 1. Power on the power resources required for the wakeup device
* 2. Enable _PSW (power state wake) for the device if present * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
* State Wake) for the device, if present
*/ */
int acpi_enable_wakeup_device_power(struct acpi_device *dev) int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{ {
union acpi_object arg = { ACPI_TYPE_INTEGER }; int i, err;
struct acpi_object_list arg_list = { 1, &arg };
acpi_status status = AE_OK;
int i;
int ret = 0;
if (!dev || !dev->wakeup.flags.valid) if (!dev || !dev->wakeup.flags.valid)
return -1; return -EINVAL;
/*
* Do not execute the code below twice in a row without calling
* acpi_disable_wakeup_device_power() in between for the same device
*/
if (dev->wakeup.flags.prepared)
return 0;
arg.integer.value = 1;
/* Open power resource */ /* Open power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) { for (i = 0; i < dev->wakeup.resources.count; i++) {
ret = acpi_power_on(dev->wakeup.resources.handles[i], dev); int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
if (ret) { if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n"); printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0; dev->wakeup.flags.valid = 0;
return -1; return -ENODEV;
} }
} }
/* Execute PSW */ /*
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); * Passing 3 as the third argument below means the device may be placed
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { * in arbitrary power state afterwards.
printk(KERN_ERR PREFIX "Evaluate _PSW\n"); */
dev->wakeup.flags.valid = 0; err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
ret = -1; if (!err)
} dev->wakeup.flags.prepared = 1;
return ret; return err;
} }
/* /*
* Shutdown a wakeup device, counterpart of above method * Shutdown a wakeup device, counterpart of above method
* 1. Disable _PSW (power state wake) * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power
* State Wake) for the device, if present
* 2. Shutdown down the power resources * 2. Shutdown down the power resources
*/ */
int acpi_disable_wakeup_device_power(struct acpi_device *dev) int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{ {
union acpi_object arg = { ACPI_TYPE_INTEGER }; int i, ret;
struct acpi_object_list arg_list = { 1, &arg };
acpi_status status = AE_OK;
int i;
int ret = 0;
if (!dev || !dev->wakeup.flags.valid) if (!dev || !dev->wakeup.flags.valid)
return -1; return -EINVAL;
arg.integer.value = 0; /*
/* Execute PSW */ * Do not execute the code below twice in a row without calling
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); * acpi_enable_wakeup_device_power() in between for the same device
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { */
printk(KERN_ERR PREFIX "Evaluate _PSW\n"); if (!dev->wakeup.flags.prepared)
dev->wakeup.flags.valid = 0; return 0;
return -1;
} dev->wakeup.flags.prepared = 0;
ret = acpi_device_sleep_wake(dev, 0, 0, 0);
if (ret)
return ret;
/* Close power resource */ /* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) { for (i = 0; i < dev->wakeup.resources.count; i++) {
...@@ -362,7 +428,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) ...@@ -362,7 +428,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
if (ret) { if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n"); printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0; dev->wakeup.flags.valid = 0;
return -1; return -ENODEV;
} }
} }
......
...@@ -703,9 +703,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) ...@@ -703,9 +703,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
acpi_status status = 0; acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *package = NULL; union acpi_object *package = NULL;
union acpi_object in_arg[3]; int psw_error;
struct acpi_object_list arg_list = { 3, in_arg };
acpi_status psw_status = AE_OK;
struct acpi_device_id button_device_ids[] = { struct acpi_device_id button_device_ids[] = {
{"PNP0C0D", 0}, {"PNP0C0D", 0},
...@@ -737,39 +735,11 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) ...@@ -737,39 +735,11 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
* So it is necessary to call _DSW object first. Only when it is not * So it is necessary to call _DSW object first. Only when it is not
* present will the _PSW object used. * present will the _PSW object used.
*/ */
/* psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
* Three agruments are needed for the _DSW object. if (psw_error)
* Argument 0: enable/disable the wake capabilities ACPI_DEBUG_PRINT((ACPI_DB_INFO,
* When _DSW object is called to disable the wake capabilities, maybe "error in _DSW or _PSW evaluation\n"));
* the first argument is filled. The value of the other two agruments
* is meaningless.
*/
in_arg[0].type = ACPI_TYPE_INTEGER;
in_arg[0].integer.value = 0;
in_arg[1].type = ACPI_TYPE_INTEGER;
in_arg[1].integer.value = 0;
in_arg[2].type = ACPI_TYPE_INTEGER;
in_arg[2].integer.value = 0;
psw_status = acpi_evaluate_object(device->handle, "_DSW",
&arg_list, NULL);
if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n"));
/*
* When the _DSW object is not present, OSPM will call _PSW object.
*/
if (psw_status == AE_NOT_FOUND) {
/*
* Only one agruments is required for the _PSW object.
* agrument 0: enable/disable the wake capabilities
*/
arg_list.count = 1;
in_arg[0].integer.value = 0;
psw_status = acpi_evaluate_object(device->handle, "_PSW",
&arg_list, NULL);
if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND))
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in "
"evaluate _PSW\n"));
}
/* Power button, Lid switch always enable wakeup */ /* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids)) if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1; device->wakeup.flags.run_wake = 1;
......
This diff is collapsed.
...@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) ...@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
continue; continue;
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
acpi_enable_wakeup_device_power(dev); acpi_enable_wakeup_device_power(dev, sleep_state);
spin_lock(&acpi_device_lock); spin_lock(&acpi_device_lock);
} }
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
...@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state) ...@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state)
list_for_each_safe(node, next, &acpi_wakeup_device_list) { list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev = struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list); container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid) if (!dev->wakeup.flags.valid)
continue; continue;
/* If users want to disable run-wake GPE, /* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime * we only disable it for wake and leave it for runtime
*/ */
if (!dev->wakeup.state.enabled || if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
sleep_state > (u32) dev->wakeup.sleep_state) { || sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) { if (dev->wakeup.flags.run_wake) {
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
/* set_gpe_type will disable GPE, leave it like that */ /* set_gpe_type will disable GPE, leave it like that */
...@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state) ...@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state)
if (!dev->wakeup.flags.valid) if (!dev->wakeup.flags.valid)
continue; continue;
if (!dev->wakeup.state.enabled ||
sleep_state > (u32) dev->wakeup.sleep_state) { if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
|| sleep_state > (u32) dev->wakeup.sleep_state) {
if (dev->wakeup.flags.run_wake) { if (dev->wakeup.flags.run_wake) {
spin_unlock(&acpi_device_lock); spin_unlock(&acpi_device_lock);
acpi_set_gpe_type(dev->wakeup.gpe_device, acpi_set_gpe_type(dev->wakeup.gpe_device,
......
...@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv) ...@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv)
drv->driver.suspend = platform_drv_suspend; drv->driver.suspend = platform_drv_suspend;
if (drv->resume) if (drv->resume)
drv->driver.resume = platform_drv_resume; drv->driver.resume = platform_drv_resume;
if (drv->pm)
drv->driver.pm = &drv->pm->base;
return driver_register(&drv->driver); return driver_register(&drv->driver);
} }
EXPORT_SYMBOL_GPL(platform_driver_register); EXPORT_SYMBOL_GPL(platform_driver_register);
...@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv) ...@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv)
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
} }
static int platform_suspend(struct device *dev, pm_message_t mesg) #ifdef CONFIG_PM_SLEEP
static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
{ {
int ret = 0; int ret = 0;
...@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg) ...@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
return ret; return ret;
} }
static int platform_suspend_late(struct device *dev, pm_message_t mesg) static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
{ {
struct platform_driver *drv = to_platform_driver(dev->driver); struct platform_driver *drv = to_platform_driver(dev->driver);
struct platform_device *pdev; struct platform_device *pdev;
...@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg) ...@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
return ret; return ret;
} }
static int platform_resume_early(struct device *dev) static int platform_legacy_resume_early(struct device *dev)
{ {
struct platform_driver *drv = to_platform_driver(dev->driver); struct platform_driver *drv = to_platform_driver(dev->driver);
struct platform_device *pdev; struct platform_device *pdev;
...@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev) ...@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev)
return ret; return ret;
} }
static int platform_resume(struct device *dev) static int platform_legacy_resume(struct device *dev)
{ {
int ret = 0; int ret = 0;
...@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev) ...@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev)
return ret; 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 = { struct bus_type platform_bus_type = {
.name = "platform", .name = "platform",
.dev_attrs = platform_dev_attrs, .dev_attrs = platform_dev_attrs,
.match = platform_match, .match = platform_match,
.uevent = platform_uevent, .uevent = platform_uevent,
.suspend = platform_suspend, .pm = PLATFORM_PM_OPS_PTR,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
}; };
EXPORT_SYMBOL_GPL(platform_bus_type); EXPORT_SYMBOL_GPL(platform_bus_type);
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* main.c * main.c
*/ */
extern struct list_head dpm_active; /* The active device list */ extern struct list_head dpm_list; /* The active device list */
static inline struct device *to_device(struct list_head *entry) static inline struct device *to_device(struct list_head *entry)
{ {
......
...@@ -6,9 +6,6 @@ ...@@ -6,9 +6,6 @@
#include <linux/string.h> #include <linux/string.h>
#include "power.h" #include "power.h"
int (*platform_enable_wakeup)(struct device *dev, int is_on);
/* /*
* wakeup - Report/change current wakeup option for device * wakeup - Report/change current wakeup option for device
* *
......
...@@ -188,9 +188,9 @@ static int show_file_hash(unsigned int value) ...@@ -188,9 +188,9 @@ static int show_file_hash(unsigned int value)
static int show_dev_hash(unsigned int value) static int show_dev_hash(unsigned int value)
{ {
int match = 0; int match = 0;
struct list_head * entry = dpm_active.prev; struct list_head *entry = dpm_list.prev;
while (entry != &dpm_active) { while (entry != &dpm_list) {
struct device * dev = to_device(entry); struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
if (hash == value) { if (hash == value) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the PCI bus specific drivers. # Makefile for the PCI bus specific drivers.
# #
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_hotplug.h> #include <linux/pci_hotplug.h>
#include <linux/pci-acpi.h>
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/actypes.h> #include <acpi/actypes.h>
...@@ -299,7 +300,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) ...@@ -299,7 +300,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
* *
* @handle - the handle of the hotplug controller. * @handle - the handle of the hotplug controller.
*/ */
acpi_status acpi_run_oshp(acpi_handle handle) static acpi_status acpi_run_oshp(acpi_handle handle)
{ {
acpi_status status; acpi_status status;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
...@@ -322,9 +323,6 @@ acpi_status acpi_run_oshp(acpi_handle handle) ...@@ -322,9 +323,6 @@ acpi_status acpi_run_oshp(acpi_handle handle)
kfree(string.pointer); kfree(string.pointer);
return status; return status;
} }
EXPORT_SYMBOL_GPL(acpi_run_oshp);
/* acpi_get_hp_params_from_firmware /* acpi_get_hp_params_from_firmware
* *
...@@ -374,6 +372,85 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, ...@@ -374,6 +372,85 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
} }
EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); 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 /* acpi_root_bridge - check to see if this acpi object is a root bridge
* *
......
...@@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); ...@@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_attention_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_latch_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_adapter_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 */ /* variables */
extern int acpiphp_debug; extern int acpiphp_debug;
......
...@@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot); ...@@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot);
static int set_attention_status (struct hotplug_slot *slot, u8 value); 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_power_status (struct hotplug_slot *slot, u8 *value);
static int get_attention_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_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
...@@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { ...@@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
.get_attention_status = get_attention_status, .get_attention_status = get_attention_status,
.get_latch_status = get_latch_status, .get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status, .get_adapter_status = get_adapter_status,
.get_address = get_address,
}; };
...@@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0; 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) static int __init init_acpi(void)
{ {
int retval; int retval;
...@@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) ...@@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
acpiphp_slot->slot = slot; acpiphp_slot->slot = slot;
snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun); snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
retval = pci_hp_register(slot->hotplug_slot); retval = pci_hp_register(slot->hotplug_slot,
acpiphp_slot->bridge->pci_bus,
acpiphp_slot->device);
if (retval == -EBUSY)
goto error_hpslot;
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
goto error_hpslot; goto error_hpslot;
......
...@@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
bridge->pci_bus->number, slot->device); bridge->pci_bus->number, slot->device);
retval = acpiphp_register_hotplug_slot(slot); retval = acpiphp_register_hotplug_slot(slot);
if (retval) { if (retval) {
warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", 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);
goto err_exit; goto err_exit;
} }
} }
...@@ -1878,19 +1883,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) ...@@ -1878,19 +1883,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
return (sta == 0) ? 0 : 1; 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;
}
...@@ -33,8 +33,10 @@ ...@@ -33,8 +33,10 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/pci.h>
#include "acpiphp.h" #include "acpiphp.h"
#include "../pci.h"
#define DRIVER_VERSION "1.0.1" #define DRIVER_VERSION "1.0.1"
#define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" #define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
...@@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void) ...@@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void)
int retval = 0; int retval = 0;
acpi_status status; acpi_status status;
struct acpi_device *device; struct acpi_device *device;
struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; struct kobject *sysdir = &pci_slots_kset->kobj;
dbg("%s\n", __func__); dbg("%s\n", __func__);
...@@ -477,7 +479,7 @@ static int __init ibm_acpiphp_init(void) ...@@ -477,7 +479,7 @@ static int __init ibm_acpiphp_init(void)
static void __exit ibm_acpiphp_exit(void) static void __exit ibm_acpiphp_exit(void)
{ {
acpi_status status; acpi_status status;
struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; struct kobject *sysdir = &pci_slots_kset->kobj;
dbg("%s\n", __func__); dbg("%s\n", __func__);
......
...@@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) ...@@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
info->attention_status = cpci_get_attention_status(slot); info->attention_status = cpci_get_attention_status(slot);
dbg("registering slot %s", slot->hotplug_slot->name); dbg("registering slot %s", slot->hotplug_slot->name);
status = pci_hp_register(slot->hotplug_slot); status = pci_hp_register(slot->hotplug_slot, bus, i);
if (status) { if (status) {
err("pci_hp_register failed with error %d", status); err("pci_hp_register failed with error %d", status);
goto error_name; goto error_name;
......
...@@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl, ...@@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
slot->bus, slot->device, slot->bus, slot->device,
slot->number, ctrl->slot_device_offset, slot->number, ctrl->slot_device_offset,
slot_number); slot_number);
result = pci_hp_register(hotplug_slot); result = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
slot->device);
if (result) { if (result) {
err("pci_hp_register failed with error %d\n", result); err("pci_hp_register failed with error %d\n", result);
goto error_name; goto error_name;
......
...@@ -66,6 +66,7 @@ struct dummy_slot { ...@@ -66,6 +66,7 @@ struct dummy_slot {
struct pci_dev *dev; struct pci_dev *dev;
struct work_struct remove_work; struct work_struct remove_work;
unsigned long removed; unsigned long removed;
char name[8];
}; };
static int debug; static int debug;
...@@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev) ...@@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev)
struct dummy_slot *dslot; struct dummy_slot *dslot;
struct hotplug_slot *slot; struct hotplug_slot *slot;
int retval = -ENOMEM; int retval = -ENOMEM;
static int count = 1;
slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
if (!slot) if (!slot)
...@@ -113,18 +115,18 @@ static int add_slot(struct pci_dev *dev) ...@@ -113,18 +115,18 @@ static int add_slot(struct pci_dev *dev)
slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
slot->info->cur_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); dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
if (!dslot) if (!dslot)
goto error_info; 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->ops = &dummy_hotplug_slot_ops;
slot->release = &dummy_release; slot->release = &dummy_release;
slot->private = dslot; slot->private = dslot;
retval = pci_hp_register(slot); retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
goto error_dslot; goto error_dslot;
...@@ -148,17 +150,17 @@ static int add_slot(struct pci_dev *dev) ...@@ -148,17 +150,17 @@ static int add_slot(struct pci_dev *dev)
static int __init pci_scan_buses(void) static int __init pci_scan_buses(void)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
int retval = 0; int lastslot = 0;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
retval = add_slot(dev); if (PCI_FUNC(dev->devfn) > 0 &&
if (retval) { lastslot == PCI_SLOT(dev->devfn))
pci_dev_put(dev); continue;
break; lastslot = PCI_SLOT(dev->devfn);
} add_slot(dev);
} }
return retval; return 0;
} }
static void remove_slot(struct dummy_slot *dslot) static void remove_slot(struct dummy_slot *dslot)
...@@ -296,23 +298,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) ...@@ -296,23 +298,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
return 0; 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) static int disable_slot(struct hotplug_slot *slot)
{ {
struct dummy_slot *dslot; struct dummy_slot *dslot;
struct hotplug_slot *hslot;
struct pci_dev *dev; struct pci_dev *dev;
int func; int func;
...@@ -322,41 +310,27 @@ static int disable_slot(struct hotplug_slot *slot) ...@@ -322,41 +310,27 @@ static int disable_slot(struct hotplug_slot *slot)
dbg("%s - physical_slot = %s\n", __func__, slot->name); dbg("%s - physical_slot = %s\n", __func__, slot->name);
/* don't disable bridged devices just yet, we can't handle them easily... */ for (func = 7; func >= 0; func--) {
if (dslot->dev->subordinate) { dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func);
err("Can't remove PCI devices with other PCI devices behind it yet.\n"); if (!dev)
return -ENODEV; continue;
}
if (test_and_set_bit(0, &dslot->removed)) { if (test_and_set_bit(0, &dslot->removed)) {
dbg("Slot already scheduled for removal\n"); dbg("Slot already scheduled for removal\n");
return -ENODEV; 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");
}
}
/* remove the device from the pci core */ /* queue work item to blow away this sysfs entry and other
pci_remove_bus_device(dslot->dev); * parts.
*/
/* queue work item to blow away this sysfs entry and other parts. */
INIT_WORK(&dslot->remove_work, remove_slot_worker); INIT_WORK(&dslot->remove_work, remove_slot_worker);
queue_work(dummyphp_wq, &dslot->remove_work); queue_work(dummyphp_wq, &dslot->remove_work);
/* blow away this sysfs entry and other parts. */
remove_slot(dslot);
pci_dev_put(dev);
}
return 0; return 0;
} }
......
...@@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void) ...@@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void)
tmp_slot = list_entry (list, struct slot, ibm_slot_list); tmp_slot = list_entry (list, struct slot, ibm_slot_list);
snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot)); snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
pci_hp_register (tmp_slot->hotplug_slot); pci_hp_register(tmp_slot->hotplug_slot,
pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
} }
print_ebda_hpc (); print_ebda_hpc ();
......
This diff is collapsed.
...@@ -43,6 +43,7 @@ extern int pciehp_poll_mode; ...@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
extern int pciehp_poll_time; extern int pciehp_poll_time;
extern int pciehp_debug; extern int pciehp_debug;
extern int pciehp_force; extern int pciehp_force;
extern int pciehp_slot_with_bus;
extern struct workqueue_struct *pciehp_wq; extern struct workqueue_struct *pciehp_wq;
#define dbg(format, arg...) \ #define dbg(format, arg...) \
...@@ -96,7 +97,7 @@ struct controller { ...@@ -96,7 +97,7 @@ struct controller {
u32 slot_cap; u32 slot_cap;
u8 cap_base; u8 cap_base;
struct timer_list poll_timer; struct timer_list poll_timer;
volatile int cmd_busy; int cmd_busy;
unsigned int no_cmd_complete:1; unsigned int no_cmd_complete:1;
}; };
...@@ -156,10 +157,10 @@ extern u8 pciehp_handle_power_fault(struct slot *p_slot); ...@@ -156,10 +157,10 @@ extern u8 pciehp_handle_power_fault(struct slot *p_slot);
extern int pciehp_configure_device(struct slot *p_slot); extern int pciehp_configure_device(struct slot *p_slot);
extern int pciehp_unconfigure_device(struct slot *p_slot); extern int pciehp_unconfigure_device(struct slot *p_slot);
extern void pciehp_queue_pushbutton_work(struct work_struct *work); extern void pciehp_queue_pushbutton_work(struct work_struct *work);
int pcie_init(struct controller *ctrl, struct pcie_device *dev); struct controller *pcie_init(struct pcie_device *dev);
int pciehp_enable_slot(struct slot *p_slot); int pciehp_enable_slot(struct slot *p_slot);
int pciehp_disable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot);
int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev); int pcie_enable_notification(struct controller *ctrl);
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{ {
...@@ -202,8 +203,13 @@ struct hpc_ops { ...@@ -202,8 +203,13 @@ struct hpc_ops {
#include <acpi/actypes.h> #include <acpi/actypes.h>
#include <linux/pci-acpi.h> #include <linux/pci-acpi.h>
#define pciehp_get_hp_hw_control_from_firmware(dev) \ static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
pciehp_acpi_get_hp_hw_control_from_firmware(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);
}
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp) struct hotplug_params *hpp)
{ {
......
...@@ -72,7 +72,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); ...@@ -72,7 +72,6 @@ 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_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_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_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_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); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
...@@ -85,7 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { ...@@ -85,7 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
.get_attention_status = get_attention_status, .get_attention_status = get_attention_status,
.get_latch_status = get_latch_status, .get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status, .get_adapter_status = get_adapter_status,
.get_address = get_address,
.get_max_bus_speed = get_max_bus_speed, .get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed, .get_cur_bus_speed = get_cur_bus_speed,
}; };
...@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = { ...@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
*/ */
static void release_slot(struct hotplug_slot *hotplug_slot) static void release_slot(struct hotplug_slot *hotplug_slot)
{ {
struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
kfree(slot->hotplug_slot->info); kfree(hotplug_slot->info);
kfree(slot->hotplug_slot); kfree(hotplug_slot);
kfree(slot);
}
static void make_slot_name(struct slot *slot)
{
if (pciehp_slot_with_bus)
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
slot->bus, slot->number);
else
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
slot->number);
} }
static int init_slots(struct controller *ctrl) static int init_slots(struct controller *ctrl)
...@@ -210,49 +195,34 @@ static int init_slots(struct controller *ctrl) ...@@ -210,49 +195,34 @@ static int init_slots(struct controller *ctrl)
struct hotplug_slot *hotplug_slot; struct hotplug_slot *hotplug_slot;
struct hotplug_slot_info *info; struct hotplug_slot_info *info;
int retval = -ENOMEM; int retval = -ENOMEM;
int i;
for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
goto error;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
if (!hotplug_slot) if (!hotplug_slot)
goto error_slot; goto error;
slot->hotplug_slot = hotplug_slot;
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
goto error_hpslot; goto error_hpslot;
hotplug_slot->info = info;
hotplug_slot->name = slot->name;
slot->hp_slot = i;
slot->ctrl = ctrl;
slot->bus = ctrl->pci_dev->subordinate->number;
slot->device = ctrl->slot_device_offset + i;
slot->hpc_ops = ctrl->hpc_ops;
slot->number = ctrl->first_slot;
mutex_init(&slot->lock);
INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
/* register this slot with the hotplug pci core */ /* register this slot with the hotplug pci core */
hotplug_slot->info = info;
hotplug_slot->name = slot->name;
hotplug_slot->private = slot; hotplug_slot->private = slot;
hotplug_slot->release = &release_slot; hotplug_slot->release = &release_slot;
make_slot_name(slot);
hotplug_slot->ops = &pciehp_hotplug_slot_ops; hotplug_slot->ops = &pciehp_hotplug_slot_ops;
get_power_status(hotplug_slot, &info->power_status); get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status); get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_status); get_latch_status(hotplug_slot, &info->latch_status);
get_adapter_status(hotplug_slot, &info->adapter_status); get_adapter_status(hotplug_slot, &info->adapter_status);
slot->hotplug_slot = hotplug_slot;
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device, "slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset); slot->hp_slot, slot->number, ctrl->slot_device_offset);
retval = pci_hp_register(hotplug_slot); retval = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
slot->device);
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
if (retval == -EEXIST) if (retval == -EEXIST)
...@@ -263,7 +233,7 @@ static int init_slots(struct controller *ctrl) ...@@ -263,7 +233,7 @@ static int init_slots(struct controller *ctrl)
} }
/* create additional sysfs entries */ /* create additional sysfs entries */
if (EMI(ctrl)) { if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->kobj, retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr); &hotplug_slot_attr_lock.attr);
if (retval) { if (retval) {
pci_hp_deregister(hotplug_slot); pci_hp_deregister(hotplug_slot);
...@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl) ...@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl)
goto error_info; goto error_info;
} }
} }
list_add(&slot->slot_list, &ctrl->slot_list);
} }
return 0; return 0;
...@@ -280,27 +248,18 @@ static int init_slots(struct controller *ctrl) ...@@ -280,27 +248,18 @@ static int init_slots(struct controller *ctrl)
kfree(info); kfree(info);
error_hpslot: error_hpslot:
kfree(hotplug_slot); kfree(hotplug_slot);
error_slot:
kfree(slot);
error: error:
return retval; return retval;
} }
static void cleanup_slots(struct controller *ctrl) static void cleanup_slots(struct controller *ctrl)
{ {
struct list_head *tmp;
struct list_head *next;
struct slot *slot; struct slot *slot;
list_for_each_safe(tmp, next, &ctrl->slot_list) { list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
slot = list_entry(tmp, struct slot, slot_list);
list_del(&slot->slot_list);
if (EMI(ctrl)) if (EMI(ctrl))
sysfs_remove_file(&slot->hotplug_slot->kobj, sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr); &hotplug_slot_attr_lock.attr);
cancel_delayed_work(&slot->work);
flush_scheduled_work();
flush_workqueue(pciehp_wq);
pci_hp_deregister(slot->hotplug_slot); pci_hp_deregister(slot->hotplug_slot);
} }
} }
...@@ -398,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -398,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0; return 0;
} }
static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
{ enum pci_bus_speed *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; struct slot *slot = hotplug_slot->private;
int retval; int retval;
...@@ -444,34 +392,30 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -444,34 +392,30 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
struct controller *ctrl; struct controller *ctrl;
struct slot *t_slot; struct slot *t_slot;
u8 value; u8 value;
struct pci_dev *pdev; struct pci_dev *pdev = dev->port;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (pciehp_force)
if (!ctrl) { dbg("Bypassing BIOS check for pciehp use on %s\n",
err("%s : out of memory\n", __func__); pci_name(pdev));
else if (pciehp_get_hp_hw_control_from_firmware(pdev))
goto err_out_none; goto err_out_none;
}
INIT_LIST_HEAD(&ctrl->slot_list);
pdev = dev->port;
ctrl->pci_dev = pdev;
rc = pcie_init(ctrl, dev); ctrl = pcie_init(dev);
if (rc) { if (!ctrl) {
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
goto err_out_free_ctrl; goto err_out_none;
} }
set_service_data(dev, ctrl);
pci_set_drvdata(pdev, ctrl);
dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
__func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn), pdev->irq);
/* Setup the slot information structures */ /* Setup the slot information structures */
rc = init_slots(ctrl); rc = init_slots(ctrl);
if (rc) { if (rc) {
err("%s: slot initialization failed\n", PCIE_MODULE_NAME); 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);
goto err_out_release_ctlr; goto err_out_release_ctlr;
} }
...@@ -495,20 +439,16 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ ...@@ -495,20 +439,16 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
cleanup_slots(ctrl); cleanup_slots(ctrl);
err_out_release_ctlr: err_out_release_ctlr:
ctrl->hpc_ops->release_ctlr(ctrl); ctrl->hpc_ops->release_ctlr(ctrl);
err_out_free_ctrl:
kfree(ctrl);
err_out_none: err_out_none:
return -ENODEV; return -ENODEV;
} }
static void pciehp_remove (struct pcie_device *dev) static void pciehp_remove (struct pcie_device *dev)
{ {
struct pci_dev *pdev = dev->port; struct controller *ctrl = get_service_data(dev);
struct controller *ctrl = pci_get_drvdata(pdev);
cleanup_slots(ctrl); cleanup_slots(ctrl);
ctrl->hpc_ops->release_ctlr(ctrl); ctrl->hpc_ops->release_ctlr(ctrl);
kfree(ctrl);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -522,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev) ...@@ -522,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev)
{ {
printk("%s ENTRY\n", __func__); printk("%s ENTRY\n", __func__);
if (pciehp_force) { if (pciehp_force) {
struct pci_dev *pdev = dev->port; struct controller *ctrl = get_service_data(dev);
struct controller *ctrl = pci_get_drvdata(pdev);
struct slot *t_slot; struct slot *t_slot;
u8 status; u8 status;
/* reinitialize the chipset's event detection logic */ /* reinitialize the chipset's event detection logic */
pcie_init_hardware_part2(ctrl, dev); pcie_enable_notification(ctrl);
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
......
This diff is collapsed.
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
*/ */
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h> #include <linux/pci_hotplug.h>
#include "rpadlpar.h" #include "rpadlpar.h"
#include "../pci.h"
#define DLPAR_KOBJ_NAME "control" #define DLPAR_KOBJ_NAME "control"
...@@ -27,7 +29,6 @@ ...@@ -27,7 +29,6 @@
#define MAX_DRC_NAME_LEN 64 #define MAX_DRC_NAME_LEN 64
static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
...@@ -112,7 +113,7 @@ int dlpar_sysfs_init(void) ...@@ -112,7 +113,7 @@ int dlpar_sysfs_init(void)
int error; int error;
dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME, dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
&pci_hotplug_slots_kset->kobj); &pci_slots_kset->kobj);
if (!dlpar_kobj) if (!dlpar_kobj)
return -EINVAL; return -EINVAL;
......
...@@ -33,33 +33,6 @@ ...@@ -33,33 +33,6 @@
#include <asm/rtas.h> #include <asm/rtas.h>
#include "rpaphp.h" #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 */ /* free up the memory used by a slot */
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
{ {
...@@ -135,9 +108,6 @@ int rpaphp_deregister_slot(struct slot *slot) ...@@ -135,9 +108,6 @@ int rpaphp_deregister_slot(struct slot *slot)
list_del(&slot->rpaphp_slot_list); 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); retval = pci_hp_deregister(php_slot);
if (retval) if (retval)
err("Problem unregistering a slot %s\n", slot->name); err("Problem unregistering a slot %s\n", slot->name);
...@@ -151,6 +121,7 @@ int rpaphp_register_slot(struct slot *slot) ...@@ -151,6 +121,7 @@ int rpaphp_register_slot(struct slot *slot)
{ {
struct hotplug_slot *php_slot = slot->hotplug_slot; struct hotplug_slot *php_slot = slot->hotplug_slot;
int retval; int retval;
int slotno;
dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
__func__, slot->dn->full_name, slot->index, slot->name, __func__, slot->dn->full_name, slot->index, slot->name,
...@@ -162,19 +133,16 @@ int rpaphp_register_slot(struct slot *slot) ...@@ -162,19 +133,16 @@ int rpaphp_register_slot(struct slot *slot)
return -EAGAIN; return -EAGAIN;
} }
retval = pci_hp_register(php_slot); 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);
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
return 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 */ /* add slot to our internal list */
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
info("Slot [%s] registered\n", slot->name); info("Slot [%s] registered\n", slot->name);
......
...@@ -197,13 +197,15 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, ...@@ -197,13 +197,15 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
static struct hotplug_slot * sn_hp_destroy(void) static struct hotplug_slot * sn_hp_destroy(void)
{ {
struct slot *slot; struct slot *slot;
struct pci_slot *pci_slot;
struct hotplug_slot *bss_hotplug_slot = NULL; struct hotplug_slot *bss_hotplug_slot = NULL;
list_for_each_entry(slot, &sn_hp_list, hp_list) { list_for_each_entry(slot, &sn_hp_list, hp_list) {
bss_hotplug_slot = slot->hotplug_slot; bss_hotplug_slot = slot->hotplug_slot;
pci_slot = bss_hotplug_slot->pci_slot;
list_del(&((struct slot *)bss_hotplug_slot->private)-> list_del(&((struct slot *)bss_hotplug_slot->private)->
hp_list); hp_list);
sysfs_remove_file(&bss_hotplug_slot->kobj, sysfs_remove_file(&pci_slot->kobj,
&sn_slot_path_attr.attr); &sn_slot_path_attr.attr);
break; break;
} }
...@@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot) ...@@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
static int sn_hotplug_slot_register(struct pci_bus *pci_bus) static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
{ {
int device; int device;
struct pci_slot *pci_slot;
struct hotplug_slot *bss_hotplug_slot; struct hotplug_slot *bss_hotplug_slot;
int rc = 0; int rc = 0;
...@@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) ...@@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
bss_hotplug_slot->ops = &sn_hotplug_slot_ops; bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
bss_hotplug_slot->release = &sn_release_slot; bss_hotplug_slot->release = &sn_release_slot;
rc = pci_hp_register(bss_hotplug_slot); rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
if (rc) if (rc)
goto register_err; goto register_err;
rc = sysfs_create_file(&bss_hotplug_slot->kobj, pci_slot = bss_hotplug_slot->pci_slot;
rc = sysfs_create_file(&pci_slot->kobj,
&sn_slot_path_attr.attr); &sn_slot_path_attr.attr);
if (rc) if (rc)
goto register_err; goto register_err;
......
...@@ -170,6 +170,7 @@ extern void shpchp_queue_pushbutton_work(struct work_struct *work); ...@@ -170,6 +170,7 @@ extern void shpchp_queue_pushbutton_work(struct work_struct *work);
extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <linux/pci-acpi.h>
static inline int get_hp_params_from_firmware(struct pci_dev *dev, static inline int get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp) struct hotplug_params *hpp)
{ {
...@@ -177,14 +178,15 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev, ...@@ -177,14 +178,15 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev,
return -ENODEV; return -ENODEV;
return 0; return 0;
} }
#define get_hp_hw_control_from_firmware(pdev) \
do { \ static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ {
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\ u32 flags = OSC_SHPC_NATIVE_HP_CONTROL;
} while (0) return acpi_get_hp_hw_control_from_firmware(dev, flags);
}
#else #else
#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) #define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
#define get_hp_hw_control_from_firmware(dev) do { } while (0) #define get_hp_hw_control_from_firmware(dev) (0)
#endif #endif
struct ctrl_reg { struct ctrl_reg {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
int shpchp_debug; int shpchp_debug;
int shpchp_poll_mode; int shpchp_poll_mode;
int shpchp_poll_time; int shpchp_poll_time;
int shpchp_slot_with_bus; static int shpchp_slot_with_bus;
struct workqueue_struct *shpchp_wq; struct workqueue_struct *shpchp_wq;
#define DRIVER_VERSION "0.4" #define DRIVER_VERSION "0.4"
...@@ -68,7 +68,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value); ...@@ -68,7 +68,6 @@ 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_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_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_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_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); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
...@@ -81,7 +80,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { ...@@ -81,7 +80,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
.get_attention_status = get_attention_status, .get_attention_status = get_attention_status,
.get_latch_status = get_latch_status, .get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status, .get_adapter_status = get_adapter_status,
.get_address = get_address,
.get_max_bus_speed = get_max_bus_speed, .get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed, .get_cur_bus_speed = get_cur_bus_speed,
}; };
...@@ -159,7 +157,8 @@ static int init_slots(struct controller *ctrl) ...@@ -159,7 +157,8 @@ static int init_slots(struct controller *ctrl)
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
"slot_device_offset=%x\n", slot->bus, slot->device, "slot_device_offset=%x\n", slot->bus, slot->device,
slot->hp_slot, slot->number, ctrl->slot_device_offset); slot->hp_slot, slot->number, ctrl->slot_device_offset);
retval = pci_hp_register(slot->hotplug_slot); retval = pci_hp_register(slot->hotplug_slot,
ctrl->pci_dev->subordinate, slot->device);
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
if (retval == -EEXIST) if (retval == -EEXIST)
...@@ -288,19 +287,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -288,19 +287,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
return 0; return 0;
} }
static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
{ enum pci_bus_speed *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); struct slot *slot = get_slot(hotplug_slot);
int retval; int retval;
...@@ -333,10 +321,11 @@ static int is_shpc_capable(struct pci_dev *dev) ...@@ -333,10 +321,11 @@ static int is_shpc_capable(struct pci_dev *dev)
if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) PCI_DEVICE_ID_AMD_GOLAM_7450))
return 1; return 1;
if (pci_find_capability(dev, PCI_CAP_ID_SHPC)) if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
return 1; return 0;
if (get_hp_hw_control_from_firmware(dev))
return 0; return 0;
return 1;
} }
static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
......
...@@ -1084,7 +1084,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) ...@@ -1084,7 +1084,6 @@ 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__, dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn), pdev->irq); PCI_FUNC(pdev->devfn), pdev->irq);
get_hp_hw_control_from_firmware(pdev);
/* /*
* If this is the first controller to be initialized, * If this is the first controller to be initialized,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment