summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c118
-rw-r--r--drivers/pnp/pnpacpi/core.c20
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c9
-rw-r--r--include/linux/pnp.h13
4 files changed, 142 insertions, 18 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index d2e698096ace..679cd08b80b4 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -64,6 +64,7 @@
#include <linux/dmi.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <linux/pnp.h>
#ifdef CONFIG_PPC_OF
#include <linux/of_device.h>
@@ -1919,7 +1920,7 @@ struct SPMITable {
s8 spmi_id[1]; /* A '\0' terminated array starts here. */
};
-static __devinit int try_init_acpi(struct SPMITable *spmi)
+static __devinit int try_init_spmi(struct SPMITable *spmi)
{
struct smi_info *info;
u8 addr_space;
@@ -1940,7 +1941,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
return -ENOMEM;
}
- info->addr_source = "ACPI";
+ info->addr_source = "SPMI";
/* Figure out the interface type. */
switch (spmi->InterfaceType) {
@@ -2002,7 +2003,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
return 0;
}
-static __devinit void acpi_find_bmc(void)
+static __devinit void spmi_find_bmc(void)
{
acpi_status status;
struct SPMITable *spmi;
@@ -2020,9 +2021,106 @@ static __devinit void acpi_find_bmc(void)
if (status != AE_OK)
return;
- try_init_acpi(spmi);
+ try_init_spmi(spmi);
}
}
+
+static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
+ const struct pnp_device_id *dev_id)
+{
+ struct acpi_device *acpi_dev;
+ struct smi_info *info;
+ acpi_handle handle;
+ acpi_status status;
+ unsigned long long tmp;
+
+ acpi_dev = pnp_acpi_device(dev);
+ if (!acpi_dev)
+ return -ENODEV;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->addr_source = "ACPI";
+
+ handle = acpi_dev->handle;
+
+ /* _IFT tells us the interface type: KCS, BT, etc */
+ status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ goto err_free;
+
+ switch (tmp) {
+ case 1:
+ info->si_type = SI_KCS;
+ break;
+ case 2:
+ info->si_type = SI_SMIC;
+ break;
+ case 3:
+ info->si_type = SI_BT;
+ break;
+ default:
+ dev_info(&dev->dev, "unknown interface type %lld\n", tmp);
+ goto err_free;
+ }
+
+ if (pnp_port_valid(dev, 0)) {
+ info->io_setup = port_setup;
+ info->io.addr_type = IPMI_IO_ADDR_SPACE;
+ info->io.addr_data = pnp_port_start(dev, 0);
+ } else if (pnp_mem_valid(dev, 0)) {
+ info->io_setup = mem_setup;
+ info->io.addr_type = IPMI_MEM_ADDR_SPACE;
+ info->io.addr_data = pnp_mem_start(dev, 0);
+ } else {
+ dev_err(&dev->dev, "no I/O or memory address\n");
+ goto err_free;
+ }
+
+ info->io.regspacing = DEFAULT_REGSPACING;
+ info->io.regsize = DEFAULT_REGSPACING;
+ info->io.regshift = 0;
+
+ /* If _GPE exists, use it; otherwise use standard interrupts */
+ status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
+ if (ACPI_SUCCESS(status)) {
+ info->irq = tmp;
+ info->irq_setup = acpi_gpe_irq_setup;
+ } else if (pnp_irq_valid(dev, 0)) {
+ info->irq = pnp_irq(dev, 0);
+ info->irq_setup = std_irq_setup;
+ }
+
+ info->dev = &acpi_dev->dev;
+ pnp_set_drvdata(dev, info);
+
+ return try_smi_init(info);
+
+err_free:
+ kfree(info);
+ return -EINVAL;
+}
+
+static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
+{
+ struct smi_info *info = pnp_get_drvdata(dev);
+
+ cleanup_one_si(info);
+}
+
+static const struct pnp_device_id pnp_dev_table[] = {
+ {"IPI0001", 0},
+ {"", 0},
+};
+
+static struct pnp_driver ipmi_pnp_driver = {
+ .name = DEVICE_NAME,
+ .probe = ipmi_pnp_probe,
+ .remove = __devexit_p(ipmi_pnp_remove),
+ .id_table = pnp_dev_table,
+};
#endif
#ifdef CONFIG_DMI
@@ -2202,7 +2300,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
int rv;
int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
struct smi_info *info;
- int first_reg_offset = 0;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
@@ -2241,9 +2338,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
info->addr_source_cleanup = ipmi_pci_cleanup;
info->addr_source_data = pdev;
- if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID)
- first_reg_offset = 1;
-
if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
info->io_setup = port_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE;
@@ -3108,7 +3202,10 @@ static __devinit int init_ipmi_si(void)
#endif
#ifdef CONFIG_ACPI
- acpi_find_bmc();
+ spmi_find_bmc();
+#endif
+#ifdef CONFIG_PNP
+ pnp_register_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PCI
@@ -3233,6 +3330,9 @@ static __exit void cleanup_ipmi_si(void)
#ifdef CONFIG_PCI
pci_unregister_driver(&ipmi_pci_driver);
#endif
+#ifdef CONFIG_PNP
+ pnp_unregister_driver(&ipmi_pnp_driver);
+#endif
#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&ipmi_of_platform_driver);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 83b8b5ac49c9..5314bf630bc4 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -80,7 +80,8 @@ static int pnpacpi_get_resources(struct pnp_dev *dev)
static int pnpacpi_set_resources(struct pnp_dev *dev)
{
- acpi_handle handle = dev->data;
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
struct acpi_buffer buffer;
int ret;
@@ -103,7 +104,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
static int pnpacpi_disable_resources(struct pnp_dev *dev)
{
- acpi_handle handle = dev->data;
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
int ret;
dev_dbg(&dev->dev, "disable resources\n");
@@ -121,6 +123,8 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
#ifdef CONFIG_ACPI_SLEEP
static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
{
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
int power_state;
power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
@@ -128,16 +132,19 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
power_state = (state.event == PM_EVENT_ON) ?
ACPI_STATE_D0 : ACPI_STATE_D3;
- return acpi_bus_set_power((acpi_handle) dev->data, power_state);
+ return acpi_bus_set_power(handle, power_state);
}
static int pnpacpi_resume(struct pnp_dev *dev)
{
- return acpi_bus_set_power((acpi_handle) dev->data, ACPI_STATE_D0);
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
+
+ return acpi_bus_set_power(handle, ACPI_STATE_D0);
}
#endif
-static struct pnp_protocol pnpacpi_protocol = {
+struct pnp_protocol pnpacpi_protocol = {
.name = "Plug and Play ACPI",
.get = pnpacpi_get_resources,
.set = pnpacpi_set_resources,
@@ -147,6 +154,7 @@ static struct pnp_protocol pnpacpi_protocol = {
.resume = pnpacpi_resume,
#endif
};
+EXPORT_SYMBOL(pnpacpi_protocol);
static int __init pnpacpi_add_device(struct acpi_device *device)
{
@@ -168,7 +176,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
if (!dev)
return -ENOMEM;
- dev->data = device->handle;
+ dev->data = device;
/* .enabled means the device can decode the resources */
dev->active = device->status.enabled;
status = acpi_get_handle(device->handle, "_SRS", &temp);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index ef3a2cd3a7a0..5702b2c8691f 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -465,7 +465,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
{
- acpi_handle handle = dev->data;
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
acpi_status status;
pnp_dbg(&dev->dev, "parse allocated resources\n");
@@ -773,7 +774,8 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
{
- acpi_handle handle = dev->data;
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
acpi_status status;
struct acpipnp_parse_option_s parse_data;
@@ -845,7 +847,8 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
int pnpacpi_build_resource_template(struct pnp_dev *dev,
struct acpi_buffer *buffer)
{
- acpi_handle handle = dev->data;
+ struct acpi_device *acpi_dev = dev->data;
+ acpi_handle handle = acpi_dev->handle;
struct acpi_resource *resource;
int res_cnt = 0;
acpi_status status;
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index fddfafaed024..7c4193eb0072 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -334,6 +334,19 @@ extern struct pnp_protocol pnpbios_protocol;
#define pnp_device_is_pnpbios(dev) 0
#endif
+#ifdef CONFIG_PNPACPI
+extern struct pnp_protocol pnpacpi_protocol;
+
+static inline struct acpi_device *pnp_acpi_device(struct pnp_dev *dev)
+{
+ if (dev->protocol == &pnpacpi_protocol)
+ return dev->data;
+ return NULL;
+}
+#else
+#define pnp_acpi_device(dev) 0
+#endif
+
/* status */
#define PNP_READY 0x0000
#define PNP_ATTACHED 0x0001