diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-11-17 19:05:34 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-12-15 17:35:54 -0500 |
| commit | 9e368fa011d4e0aa050db348d69514900520e40b (patch) | |
| tree | 1b5dfaa305964791a2af6959a47b7bb6c89e471d | |
| parent | 18a3e0bfbcd589599d0affbfd484ba9a97e5f122 (diff) | |
ipmi: add PNP discovery (ACPI namespace via PNPACPI)
This allows ipmi_si_intf.c to claim IPMI devices described in the ACPI
namespace. Using PNP makes it simpler to parse the IRQ/IO/memory resources
of the device.
We look at any SPMI tables before looking for devices in the namespace.
This is based on ipmi_pci_probe().
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Myron Stowe <myron.stowe@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index b58e587d2990..679cd08b80b4 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -64,6 +64,7 @@ | |||
| 64 | #include <linux/dmi.h> | 64 | #include <linux/dmi.h> |
| 65 | #include <linux/string.h> | 65 | #include <linux/string.h> |
| 66 | #include <linux/ctype.h> | 66 | #include <linux/ctype.h> |
| 67 | #include <linux/pnp.h> | ||
| 67 | 68 | ||
| 68 | #ifdef CONFIG_PPC_OF | 69 | #ifdef CONFIG_PPC_OF |
| 69 | #include <linux/of_device.h> | 70 | #include <linux/of_device.h> |
| @@ -2023,6 +2024,103 @@ static __devinit void spmi_find_bmc(void) | |||
| 2023 | try_init_spmi(spmi); | 2024 | try_init_spmi(spmi); |
| 2024 | } | 2025 | } |
| 2025 | } | 2026 | } |
| 2027 | |||
| 2028 | static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | ||
| 2029 | const struct pnp_device_id *dev_id) | ||
| 2030 | { | ||
| 2031 | struct acpi_device *acpi_dev; | ||
| 2032 | struct smi_info *info; | ||
| 2033 | acpi_handle handle; | ||
| 2034 | acpi_status status; | ||
| 2035 | unsigned long long tmp; | ||
| 2036 | |||
| 2037 | acpi_dev = pnp_acpi_device(dev); | ||
| 2038 | if (!acpi_dev) | ||
| 2039 | return -ENODEV; | ||
| 2040 | |||
| 2041 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
| 2042 | if (!info) | ||
| 2043 | return -ENOMEM; | ||
| 2044 | |||
| 2045 | info->addr_source = "ACPI"; | ||
| 2046 | |||
| 2047 | handle = acpi_dev->handle; | ||
| 2048 | |||
| 2049 | /* _IFT tells us the interface type: KCS, BT, etc */ | ||
| 2050 | status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); | ||
| 2051 | if (ACPI_FAILURE(status)) | ||
| 2052 | goto err_free; | ||
| 2053 | |||
| 2054 | switch (tmp) { | ||
| 2055 | case 1: | ||
| 2056 | info->si_type = SI_KCS; | ||
| 2057 | break; | ||
| 2058 | case 2: | ||
| 2059 | info->si_type = SI_SMIC; | ||
| 2060 | break; | ||
| 2061 | case 3: | ||
| 2062 | info->si_type = SI_BT; | ||
| 2063 | break; | ||
| 2064 | default: | ||
| 2065 | dev_info(&dev->dev, "unknown interface type %lld\n", tmp); | ||
| 2066 | goto err_free; | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | if (pnp_port_valid(dev, 0)) { | ||
| 2070 | info->io_setup = port_setup; | ||
| 2071 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | ||
| 2072 | info->io.addr_data = pnp_port_start(dev, 0); | ||
| 2073 | } else if (pnp_mem_valid(dev, 0)) { | ||
| 2074 | info->io_setup = mem_setup; | ||
| 2075 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
| 2076 | info->io.addr_data = pnp_mem_start(dev, 0); | ||
| 2077 | } else { | ||
| 2078 | dev_err(&dev->dev, "no I/O or memory address\n"); | ||
| 2079 | goto err_free; | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | info->io.regspacing = DEFAULT_REGSPACING; | ||
| 2083 | info->io.regsize = DEFAULT_REGSPACING; | ||
| 2084 | info->io.regshift = 0; | ||
| 2085 | |||
| 2086 | /* If _GPE exists, use it; otherwise use standard interrupts */ | ||
| 2087 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); | ||
| 2088 | if (ACPI_SUCCESS(status)) { | ||
| 2089 | info->irq = tmp; | ||
| 2090 | info->irq_setup = acpi_gpe_irq_setup; | ||
| 2091 | } else if (pnp_irq_valid(dev, 0)) { | ||
| 2092 | info->irq = pnp_irq(dev, 0); | ||
| 2093 | info->irq_setup = std_irq_setup; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | info->dev = &acpi_dev->dev; | ||
| 2097 | pnp_set_drvdata(dev, info); | ||
| 2098 | |||
| 2099 | return try_smi_init(info); | ||
| 2100 | |||
| 2101 | err_free: | ||
| 2102 | kfree(info); | ||
| 2103 | return -EINVAL; | ||
| 2104 | } | ||
| 2105 | |||
| 2106 | static void __devexit ipmi_pnp_remove(struct pnp_dev *dev) | ||
| 2107 | { | ||
| 2108 | struct smi_info *info = pnp_get_drvdata(dev); | ||
| 2109 | |||
| 2110 | cleanup_one_si(info); | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | static const struct pnp_device_id pnp_dev_table[] = { | ||
| 2114 | {"IPI0001", 0}, | ||
| 2115 | {"", 0}, | ||
| 2116 | }; | ||
| 2117 | |||
| 2118 | static struct pnp_driver ipmi_pnp_driver = { | ||
| 2119 | .name = DEVICE_NAME, | ||
| 2120 | .probe = ipmi_pnp_probe, | ||
| 2121 | .remove = __devexit_p(ipmi_pnp_remove), | ||
| 2122 | .id_table = pnp_dev_table, | ||
| 2123 | }; | ||
| 2026 | #endif | 2124 | #endif |
| 2027 | 2125 | ||
| 2028 | #ifdef CONFIG_DMI | 2126 | #ifdef CONFIG_DMI |
| @@ -3106,6 +3204,9 @@ static __devinit int init_ipmi_si(void) | |||
| 3106 | #ifdef CONFIG_ACPI | 3204 | #ifdef CONFIG_ACPI |
| 3107 | spmi_find_bmc(); | 3205 | spmi_find_bmc(); |
| 3108 | #endif | 3206 | #endif |
| 3207 | #ifdef CONFIG_PNP | ||
| 3208 | pnp_register_driver(&ipmi_pnp_driver); | ||
| 3209 | #endif | ||
| 3109 | 3210 | ||
| 3110 | #ifdef CONFIG_PCI | 3211 | #ifdef CONFIG_PCI |
| 3111 | rv = pci_register_driver(&ipmi_pci_driver); | 3212 | rv = pci_register_driver(&ipmi_pci_driver); |
| @@ -3229,6 +3330,9 @@ static __exit void cleanup_ipmi_si(void) | |||
| 3229 | #ifdef CONFIG_PCI | 3330 | #ifdef CONFIG_PCI |
| 3230 | pci_unregister_driver(&ipmi_pci_driver); | 3331 | pci_unregister_driver(&ipmi_pci_driver); |
| 3231 | #endif | 3332 | #endif |
| 3333 | #ifdef CONFIG_PNP | ||
| 3334 | pnp_unregister_driver(&ipmi_pnp_driver); | ||
| 3335 | #endif | ||
| 3232 | 3336 | ||
| 3233 | #ifdef CONFIG_PPC_OF | 3337 | #ifdef CONFIG_PPC_OF |
| 3234 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3338 | of_unregister_platform_driver(&ipmi_of_platform_driver); |
