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
default: 0
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.
s3_beep is for debugging; it makes the PC's speaker beep
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
Format: { level | edge | high | low }
......@@ -1537,6 +1541,9 @@ 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
......
......@@ -248,7 +248,7 @@ S: Supported
ACPI PCI HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
ACPI THERMAL DRIVER
......@@ -1145,21 +1145,21 @@ COMPACTPCI HOTPLUG CORE
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
COMPACTPCI HOTPLUG GENERIC DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
COMPAL LAPTOP SUPPORT
......@@ -3219,7 +3219,7 @@ S: Supported
PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
PCMCIA SUBSYSTEM
......@@ -3865,7 +3865,7 @@ S: Maintained
SHPC HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
L: pcihpd-discuss@lists.sourceforge.net
L: linux-pci@vger.kernel.org
S: Supported
SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
......
......@@ -19,36 +19,6 @@
#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
* and other strange ISA hardware, so we always want the
......
......@@ -373,15 +373,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
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)
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,
resource_size_t size, resource_size_t align)
{
......
......@@ -76,38 +76,6 @@ void __devinit __weak pcibios_fixup_bus(struct pci_bus *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,
resource_size_t size, resource_size_t align)
__attribute__ ((weak));
......
......@@ -408,7 +408,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->class = class >> 8;
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));
if (ofpci_verbose)
......
......@@ -158,6 +158,8 @@ static int __init acpi_sleep_setup(char *str)
acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4;
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
......
......@@ -1213,9 +1213,9 @@ static int suspend(int vetoable)
if (err != APM_SUCCESS)
apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO;
device_power_up();
device_power_up(PMSG_RESUME);
local_irq_enable();
device_resume();
device_resume(PMSG_RESUME);
queue_event(APM_NORMAL_RESUME, NULL);
spin_lock(&user_list_lock);
for (as = user_list; as != NULL; as = as->next) {
......@@ -1240,7 +1240,7 @@ static void standby(void)
apm_error("standby", err);
local_irq_disable();
device_power_up();
device_power_up(PMSG_RESUME);
local_irq_enable();
}
......@@ -1326,7 +1326,7 @@ static void check_events(void)
ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
device_resume();
device_resume(PMSG_RESUME);
queue_event(event, NULL);
}
ignore_normal_resume = 0;
......
......@@ -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 vendor;
......@@ -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);
if (class == 0xffff)
return;
return -1; /* no class, treat as single function */
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)
type = read_pci_config_byte(num, slot, func,
PCI_HEADER_TYPE);
if (!(type & 0x80))
return;
return -1;
return 0;
}
void __init early_quirks(void)
......@@ -167,6 +180,9 @@ void __init early_quirks(void)
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++)
for (slot = 0; slot < 32; slot++)
for (func = 0; func < 8; func++)
check_dev_quirk(num, slot, func);
for (func = 0; func < 8; 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)
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();
#ifdef CONFIG_X86_32
......
......@@ -20,6 +20,7 @@
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;
......@@ -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 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);
if (raw_pci_ext_ops)
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,
int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
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);
if (raw_pci_ext_ops)
return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
......@@ -121,6 +122,21 @@ 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.
......@@ -128,7 +144,11 @@ void __init dmi_check_skip_isa_align(void)
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);
}
/*
......@@ -481,12 +501,18 @@ 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;
......
......@@ -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);
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)
......@@ -57,3 +64,54 @@ 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;
}
}
}
}
This diff is collapsed.
......@@ -28,6 +28,7 @@
#define PCI_USE__CRS 0x10000
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
#define PCI_HAS_IO_ECS 0x40000
#define PCI_NOASSIGN_ROMS 0x80000
extern unsigned int pci_probe;
extern unsigned long pirq_table_addr;
......
......@@ -336,6 +336,15 @@ 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
......
......@@ -48,6 +48,7 @@ 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
......
......@@ -295,6 +295,28 @@ int acpi_bus_set_power(acpi_handle handle, int state)
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
-------------------------------------------------------------------------- */
......
......@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
"firmware_node");
ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
"physical_node");
if (acpi_dev->wakeup.flags.valid)
device_set_wakeup_capable(dev, true);
}
return 0;
......
This diff is collapsed.
......@@ -292,69 +292,135 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
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):
* 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 };
struct acpi_object_list arg_list = { 1, &arg };
acpi_status status = AE_OK;
int i;
int ret = 0;
int i, err;
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 */
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) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
return -1;
return -ENODEV;
}
}
/* Execute PSW */
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
printk(KERN_ERR PREFIX "Evaluate _PSW\n");
dev->wakeup.flags.valid = 0;
ret = -1;
}
/*
* Passing 3 as the third argument below means the device may be placed
* in arbitrary power state afterwards.
*/
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
if (!err)
dev->wakeup.flags.prepared = 1;
return ret;
return err;
}
/*
* 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
*/
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
union acpi_object arg = { ACPI_TYPE_INTEGER };
struct acpi_object_list arg_list = { 1, &arg };
acpi_status status = AE_OK;
int i;
int ret = 0;
int i, ret;
if (!dev || !dev->wakeup.flags.valid)
return -1;
return -EINVAL;
arg.integer.value = 0;
/* Execute PSW */
status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
printk(KERN_ERR PREFIX "Evaluate _PSW\n");
dev->wakeup.flags.valid = 0;
return -1;
}
/*
* Do not execute the code below twice in a row without calling
* acpi_enable_wakeup_device_power() in between for the same device
*/
if (!dev->wakeup.flags.prepared)
return 0;
dev->wakeup.flags.prepared = 0;
ret = acpi_device_sleep_wake(dev, 0, 0, 0);
if (ret)
return ret;
/* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
......@@ -362,7 +428,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
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)
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *package = NULL;
union acpi_object in_arg[3];
struct acpi_object_list arg_list = { 3, in_arg };
acpi_status psw_status = AE_OK;
int psw_error;
struct acpi_device_id button_device_ids[] = {
{"PNP0C0D", 0},
......@@ -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
* present will the _PSW object used.
*/
/*
* Three agruments are needed for the _DSW object.
* Argument 0: enable/disable the wake capabilities
* When _DSW object is called to disable the wake capabilities, maybe
* 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"));
}
psw_error = acpi_device_sleep_wake(device, 0, 0, 0);
if (psw_error)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"error in _DSW or _PSW evaluation\n"));
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids))
device->wakeup.flags.run_wake = 1;
......
This diff is collapsed.
......@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
continue;
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_unlock(&acpi_device_lock);
......@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state)
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
/* If users want to disable run-wake GPE,
* we only disable it for wake and leave it for runtime
*/
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) {
spin_unlock(&acpi_device_lock);
/* set_gpe_type will disable GPE, leave it like that */
......@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state)
if (!dev->wakeup.flags.valid)
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) {
spin_unlock(&acpi_device_lock);
acpi_set_gpe_type(dev->wakeup.gpe_device,
......
......@@ -453,6 +453,8 @@ 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);
......@@ -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);
}
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;
......@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
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_device *pdev;
......@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
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_device *pdev;
......@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev)
return ret;
}
static int platform_resume(struct device *dev)
static int platform_legacy_resume(struct device *dev)
{
int ret = 0;
......@@ -606,15 +610,291 @@ static int platform_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,
.suspend = platform_suspend,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
.pm = PLATFORM_PM_OPS_PTR,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
......
This diff is collapsed.
......@@ -4,7 +4,7 @@
* 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)
{
......
......@@ -6,9 +6,6 @@
#include <linux/string.h>
#include "power.h"
int (*platform_enable_wakeup)(struct device *dev, int is_on);
/*
* wakeup - Report/change current wakeup option for device
*
......
......@@ -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_active.prev;
struct list_head *entry = dpm_list.prev;
while (entry != &dpm_active) {
while (entry != &dpm_list) {
struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
if (hash == value) {
......
......@@ -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 \
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
obj-$(CONFIG_PROC_FS) += proc.o
......
......@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/pci-acpi.h>
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
......@@ -299,7 +300,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
*
* @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;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
......@@ -322,9 +323,6 @@ 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
*
......@@ -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);
/**
* 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
*
......
......@@ -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_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;
......
......@@ -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 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);
......@@ -83,7 +82,6 @@ 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,
};
......@@ -274,23 +272,6 @@ 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;
......@@ -357,7 +338,11 @@ 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);
retval = pci_hp_register(slot->hotplug_slot,
acpiphp_slot->bridge->pci_bus,
acpiphp_slot->device);
if (retval == -EBUSY)
goto error_hpslot;
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
goto error_hpslot;
......
......@@ -258,7 +258,12 @@ 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) {
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;
}
}
......@@ -1878,19 +1883,3 @@ 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;
}
......@@ -33,8 +33,10 @@
#include <linux/kobject.h>
#include <asm/uaccess.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include "acpiphp.h"
#include "../pci.h"
#define DRIVER_VERSION "1.0.1"
#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)
int retval = 0;
acpi_status status;
struct acpi_device *device;
struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
struct kobject *sysdir = &pci_slots_kset->kobj;
dbg("%s\n", __func__);
......@@ -477,7 +479,7 @@ static int __init ibm_acpiphp_init(void)
static void __exit ibm_acpiphp_exit(void)
{
acpi_status status;
struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
struct kobject *sysdir = &pci_slots_kset->kobj;
dbg("%s\n", __func__);
......
......@@ -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);
status = pci_hp_register(slot->hotplug_slot, bus, i);
if (status) {
err("pci_hp_register failed with error %d", status);
goto error_name;
......
......@@ -434,7 +434,9 @@ 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);
result = pci_hp_register(hotplug_slot,
ctrl->pci_dev->subordinate,
slot->device);
if (result) {
err("pci_hp_register failed with error %d\n", result);
goto error_name;
......
......@@ -66,6 +66,7 @@ struct dummy_slot {
struct pci_dev *dev;
struct work_struct remove_work;
unsigned long removed;
char name[8];
};
static int debug;
......@@ -100,6 +101,7 @@ 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)
......@@ -113,18 +115,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);
retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
goto error_dslot;
......@@ -148,17 +150,17 @@ static int add_slot(struct pci_dev *dev)
static int __init pci_scan_buses(void)
{
struct pci_dev *dev = NULL;
int retval = 0;
int lastslot = 0;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
retval = add_slot(dev);
if (retval) {
pci_dev_put(dev);
break;
}
if (PCI_FUNC(dev->devfn) > 0 &&
lastslot == PCI_SLOT(dev->devfn))
continue;
lastslot = PCI_SLOT(dev->devfn);
add_slot(dev);
}
return retval;
return 0;
}
static void remove_slot(struct dummy_slot *dslot)
......@@ -296,23 +298,9 @@ 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;
......@@ -322,41 +310,27 @@ static int disable_slot(struct hotplug_slot *slot)
dbg("%s - physical_slot = %s\n", __func__, slot->name);
/* 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;
}
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;
}
/* 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 */
pci_remove_bus_device(dslot->dev);
/* queue work item to blow away this sysfs entry and other parts. */
/* 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);
/* blow away this sysfs entry and other parts. */
remove_slot(dslot);
pci_dev_put(dev);
}
return 0;
}
......
......@@ -1001,7 +1001,8 @@ 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_hp_register(tmp_slot->hotplug_slot,
pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
}
print_ebda_hpc ();
......
This diff is collapsed.
......@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
extern int pciehp_force;
extern int pciehp_slot_with_bus;
extern struct workqueue_struct *pciehp_wq;
#define dbg(format, arg...) \
......@@ -96,7 +97,7 @@ struct controller {
u32 slot_cap;
u8 cap_base;
struct timer_list poll_timer;
volatile int cmd_busy;
int cmd_busy;
unsigned int no_cmd_complete:1;
};
......@@ -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_unconfigure_device(struct slot *p_slot);
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_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)
{
......@@ -202,8 +203,13 @@ struct hpc_ops {
#include <acpi/actypes.h>
#include <linux/pci-acpi.h>
#define pciehp_get_hp_hw_control_from_firmware(dev) \
pciehp_acpi_get_hp_hw_control_from_firmware(dev)
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);
}
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp)
{
......
......@@ -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_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);
......@@ -85,7 +84,6 @@ 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,
};
......@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
*/
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);
kfree(slot->hotplug_slot->info);
kfree(slot->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);
kfree(hotplug_slot->info);
kfree(hotplug_slot);
}
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_info *info;
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);
if (!hotplug_slot)
goto error_slot;
slot->hotplug_slot = hotplug_slot;
goto error;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
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 */
hotplug_slot->info = info;
hotplug_slot->name = slot->name;
hotplug_slot->private = slot;
hotplug_slot->release = &release_slot;
make_slot_name(slot);
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
get_power_status(hotplug_slot, &info->power_status);
get_attention_status(hotplug_slot, &info->attention_status);
get_latch_status(hotplug_slot, &info->latch_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 "
"slot_device_offset=%x\n", slot->bus, slot->device,
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) {
err("pci_hp_register failed with error %d\n", retval);
if (retval == -EEXIST)
......@@ -263,7 +233,7 @@ static int init_slots(struct controller *ctrl)
}
/* create additional sysfs entries */
if (EMI(ctrl)) {
retval = sysfs_create_file(&hotplug_slot->kobj,
retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
if (retval) {
pci_hp_deregister(hotplug_slot);
......@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl)
goto error_info;
}
}
list_add(&slot->slot_list, &ctrl->slot_list);
}
return 0;
......@@ -280,27 +248,18 @@ static int init_slots(struct controller *ctrl)
kfree(info);
error_hpslot:
kfree(hotplug_slot);
error_slot:
kfree(slot);
error:
return retval;
}
static void cleanup_slots(struct controller *ctrl)
{
struct list_head *tmp;
struct list_head *next;
struct slot *slot;
list_for_each_safe(tmp, next, &ctrl->slot_list) {
slot = list_entry(tmp, struct slot, slot_list);
list_del(&slot->slot_list);
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (EMI(ctrl))
sysfs_remove_file(&slot->hotplug_slot->kobj,
sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
&hotplug_slot_attr_lock.attr);
cancel_delayed_work(&slot->work);
flush_scheduled_work();
flush_workqueue(pciehp_wq);
pci_hp_deregister(slot->hotplug_slot);
}
}
......@@ -398,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
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)
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
enum pci_bus_speed *value)
{
struct slot *slot = hotplug_slot->private;
int retval;
......@@ -444,34 +392,30 @@ 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;
struct pci_dev *pdev = dev->port;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __func__);
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;
}
INIT_LIST_HEAD(&ctrl->slot_list);
pdev = dev->port;
ctrl->pci_dev = pdev;
rc = pcie_init(ctrl, dev);
if (rc) {
ctrl = pcie_init(dev);
if (!ctrl) {
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
goto err_out_free_ctrl;
goto err_out_none;
}
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);
set_service_data(dev, ctrl);
/* Setup the slot information structures */
rc = init_slots(ctrl);
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;
}
......@@ -495,20 +439,16 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
cleanup_slots(ctrl);
err_out_release_ctlr:
ctrl->hpc_ops->release_ctlr(ctrl);
err_out_free_ctrl:
kfree(ctrl);
err_out_none:
return -ENODEV;
}
static void pciehp_remove (struct pcie_device *dev)
{
struct pci_dev *pdev = dev->port;
struct controller *ctrl = pci_get_drvdata(pdev);
struct controller *ctrl = get_service_data(dev);
cleanup_slots(ctrl);
ctrl->hpc_ops->release_ctlr(ctrl);
kfree(ctrl);
}
#ifdef CONFIG_PM
......@@ -522,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev)
{
printk("%s ENTRY\n", __func__);
if (pciehp_force) {
struct pci_dev *pdev = dev->port;
struct controller *ctrl = pci_get_drvdata(pdev);
struct controller *ctrl = get_service_data(dev);
struct slot *t_slot;
u8 status;
/* 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);
......
This diff is collapsed.
......@@ -14,8 +14,10 @@
*/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include "rpadlpar.h"
#include "../pci.h"
#define DLPAR_KOBJ_NAME "control"
......@@ -27,7 +29,6 @@
#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)
{
......@@ -112,7 +113,7 @@ int dlpar_sysfs_init(void)
int error;
dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
&pci_hotplug_slots_kset->kobj);
&pci_slots_kset->kobj);
if (!dlpar_kobj)
return -EINVAL;
......
......@@ -33,33 +33,6 @@
#include <asm/rtas.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 */
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
{
......@@ -135,9 +108,6 @@ 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);
......@@ -151,6 +121,7 @@ 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,
......@@ -162,19 +133,16 @@ int rpaphp_register_slot(struct slot *slot)
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) {
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);
......
......@@ -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)
{
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(&bss_hotplug_slot->kobj,
sysfs_remove_file(&pci_slot->kobj,
&sn_slot_path_attr.attr);
break;
}
......@@ -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)
{
int device;
struct pci_slot *pci_slot;
struct hotplug_slot *bss_hotplug_slot;
int rc = 0;
......@@ -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->release = &sn_release_slot;
rc = pci_hp_register(bss_hotplug_slot);
rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
if (rc)
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);
if (rc)
goto register_err;
......
......@@ -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);
#ifdef CONFIG_ACPI
#include <linux/pci-acpi.h>
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp)
{
......@@ -177,14 +178,15 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev,
return -ENODEV;
return 0;
}
#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)
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);
}
#else
#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
struct ctrl_reg {
......
......@@ -39,7 +39,7 @@
int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
int shpchp_slot_with_bus;
static int shpchp_slot_with_bus;
struct workqueue_struct *shpchp_wq;
#define DRIVER_VERSION "0.4"
......@@ -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_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);
......@@ -81,7 +80,6 @@ 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,
};
......@@ -159,7 +157,8 @@ 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);
retval = pci_hp_register(slot->hotplug_slot,
ctrl->pci_dev->subordinate, slot->device);
if (retval) {
err("pci_hp_register failed with error %d\n", retval);
if (retval == -EEXIST)
......@@ -288,19 +287,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
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)
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;
......@@ -333,10 +321,11 @@ 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 1;
if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
return 0;
if (get_hp_hw_control_from_firmware(dev))
return 0;
return 1;
}
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)
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,
......
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