aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2015-06-09 17:51:46 -0400
committerCorey Minyard <cminyard@mvista.com>2015-09-03 16:00:28 -0400
commit0fbcf4af7c8362d4691f9388efa57d0b14b34225 (patch)
tree79e1c4279ab8dccc84bb4e2d056d5e2496451df1
parent92e847212676bb3c5f9f7e317907367dbb8c504b (diff)
ipmi: Convert the IPMI SI ACPI handling to a platform device
The IPMI SI driver was using direct PNP, but that was not really ideal because the IPMI device is a platform device. There was some special handling in the acpi_pnp.c code for making this work, but that was breaking ACPI handling for the IPMI SSIF driver. So without this patch there were significant issues getting the SSIF driver to work with ACPI. So use a platform device for ACPI detection and remove the entry from acpi_pnp.c. Signed-off-by: Corey Minyard <cminyard@mvista.com>
-rw-r--r--drivers/acpi/acpi_pnp.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c320
2 files changed, 157 insertions, 165 deletions
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index fb765524cc3d..c58940b231d6 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -19,8 +19,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
19 {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ 19 {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */
20 /* floppy */ 20 /* floppy */
21 {"PNP0700"}, 21 {"PNP0700"},
22 /* ipmi_si */
23 {"IPI0001"},
24 /* tpm_inf_pnp */ 22 /* tpm_inf_pnp */
25 {"IFX0101"}, /* Infineon TPMs */ 23 {"IFX0101"}, /* Infineon TPMs */
26 {"IFX0102"}, /* Infineon TPMs */ 24 {"IFX0102"}, /* Infineon TPMs */
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 8a45e92ff60c..6443e762b426 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -64,7 +64,6 @@
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>
68#include <linux/of_device.h> 67#include <linux/of_device.h>
69#include <linux/of_platform.h> 68#include <linux/of_platform.h>
70#include <linux/of_address.h> 69#include <linux/of_address.h>
@@ -309,9 +308,6 @@ static int num_force_kipmid;
309#ifdef CONFIG_PCI 308#ifdef CONFIG_PCI
310static bool pci_registered; 309static bool pci_registered;
311#endif 310#endif
312#ifdef CONFIG_ACPI
313static bool pnp_registered;
314#endif
315#ifdef CONFIG_PARISC 311#ifdef CONFIG_PARISC
316static bool parisc_registered; 312static bool parisc_registered;
317#endif 313#endif
@@ -2233,134 +2229,6 @@ static void spmi_find_bmc(void)
2233 try_init_spmi(spmi); 2229 try_init_spmi(spmi);
2234 } 2230 }
2235} 2231}
2236
2237static int ipmi_pnp_probe(struct pnp_dev *dev,
2238 const struct pnp_device_id *dev_id)
2239{
2240 struct acpi_device *acpi_dev;
2241 struct smi_info *info;
2242 struct resource *res, *res_second;
2243 acpi_handle handle;
2244 acpi_status status;
2245 unsigned long long tmp;
2246 int rv = -EINVAL;
2247
2248 acpi_dev = pnp_acpi_device(dev);
2249 if (!acpi_dev)
2250 return -ENODEV;
2251
2252 info = smi_info_alloc();
2253 if (!info)
2254 return -ENOMEM;
2255
2256 info->addr_source = SI_ACPI;
2257 printk(KERN_INFO PFX "probing via ACPI\n");
2258
2259 handle = acpi_dev->handle;
2260 info->addr_info.acpi_info.acpi_handle = handle;
2261
2262 /* _IFT tells us the interface type: KCS, BT, etc */
2263 status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
2264 if (ACPI_FAILURE(status)) {
2265 dev_err(&dev->dev, "Could not find ACPI IPMI interface type\n");
2266 goto err_free;
2267 }
2268
2269 switch (tmp) {
2270 case 1:
2271 info->si_type = SI_KCS;
2272 break;
2273 case 2:
2274 info->si_type = SI_SMIC;
2275 break;
2276 case 3:
2277 info->si_type = SI_BT;
2278 break;
2279 case 4: /* SSIF, just ignore */
2280 rv = -ENODEV;
2281 goto err_free;
2282 default:
2283 dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp);
2284 goto err_free;
2285 }
2286
2287 res = pnp_get_resource(dev, IORESOURCE_IO, 0);
2288 if (res) {
2289 info->io_setup = port_setup;
2290 info->io.addr_type = IPMI_IO_ADDR_SPACE;
2291 } else {
2292 res = pnp_get_resource(dev, IORESOURCE_MEM, 0);
2293 if (res) {
2294 info->io_setup = mem_setup;
2295 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
2296 }
2297 }
2298 if (!res) {
2299 dev_err(&dev->dev, "no I/O or memory address\n");
2300 goto err_free;
2301 }
2302 info->io.addr_data = res->start;
2303
2304 info->io.regspacing = DEFAULT_REGSPACING;
2305 res_second = pnp_get_resource(dev,
2306 (info->io.addr_type == IPMI_IO_ADDR_SPACE) ?
2307 IORESOURCE_IO : IORESOURCE_MEM,
2308 1);
2309 if (res_second) {
2310 if (res_second->start > info->io.addr_data)
2311 info->io.regspacing = res_second->start - info->io.addr_data;
2312 }
2313 info->io.regsize = DEFAULT_REGSPACING;
2314 info->io.regshift = 0;
2315
2316 /* If _GPE exists, use it; otherwise use standard interrupts */
2317 status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
2318 if (ACPI_SUCCESS(status)) {
2319 info->irq = tmp;
2320 info->irq_setup = acpi_gpe_irq_setup;
2321 } else if (pnp_irq_valid(dev, 0)) {
2322 info->irq = pnp_irq(dev, 0);
2323 info->irq_setup = std_irq_setup;
2324 }
2325
2326 info->dev = &dev->dev;
2327 pnp_set_drvdata(dev, info);
2328
2329 dev_info(info->dev, "%pR regsize %d spacing %d irq %d\n",
2330 res, info->io.regsize, info->io.regspacing,
2331 info->irq);
2332
2333 rv = add_smi(info);
2334 if (rv)
2335 kfree(info);
2336
2337 return rv;
2338
2339err_free:
2340 kfree(info);
2341 return rv;
2342}
2343
2344static void ipmi_pnp_remove(struct pnp_dev *dev)
2345{
2346 struct smi_info *info = pnp_get_drvdata(dev);
2347
2348 cleanup_one_si(info);
2349}
2350
2351static const struct pnp_device_id pnp_dev_table[] = {
2352 {"IPI0001", 0},
2353 {"", 0},
2354};
2355
2356static struct pnp_driver ipmi_pnp_driver = {
2357 .name = DEVICE_NAME,
2358 .probe = ipmi_pnp_probe,
2359 .remove = ipmi_pnp_remove,
2360 .id_table = pnp_dev_table,
2361};
2362
2363MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
2364#endif 2232#endif
2365 2233
2366#ifdef CONFIG_DMI 2234#ifdef CONFIG_DMI
@@ -2669,10 +2537,19 @@ static struct pci_driver ipmi_pci_driver = {
2669}; 2537};
2670#endif /* CONFIG_PCI */ 2538#endif /* CONFIG_PCI */
2671 2539
2672static const struct of_device_id ipmi_match[];
2673static int ipmi_probe(struct platform_device *dev)
2674{
2675#ifdef CONFIG_OF 2540#ifdef CONFIG_OF
2541static const struct of_device_id of_ipmi_match[] = {
2542 { .type = "ipmi", .compatible = "ipmi-kcs",
2543 .data = (void *)(unsigned long) SI_KCS },
2544 { .type = "ipmi", .compatible = "ipmi-smic",
2545 .data = (void *)(unsigned long) SI_SMIC },
2546 { .type = "ipmi", .compatible = "ipmi-bt",
2547 .data = (void *)(unsigned long) SI_BT },
2548 {},
2549};
2550
2551static int of_ipmi_probe(struct platform_device *dev)
2552{
2676 const struct of_device_id *match; 2553 const struct of_device_id *match;
2677 struct smi_info *info; 2554 struct smi_info *info;
2678 struct resource resource; 2555 struct resource resource;
@@ -2683,9 +2560,9 @@ static int ipmi_probe(struct platform_device *dev)
2683 2560
2684 dev_info(&dev->dev, "probing via device tree\n"); 2561 dev_info(&dev->dev, "probing via device tree\n");
2685 2562
2686 match = of_match_device(ipmi_match, &dev->dev); 2563 match = of_match_device(of_ipmi_match, &dev->dev);
2687 if (!match) 2564 if (!match)
2688 return -EINVAL; 2565 return -ENODEV;
2689 2566
2690 if (!of_device_is_available(np)) 2567 if (!of_device_is_available(np))
2691 return -EINVAL; 2568 return -EINVAL;
@@ -2754,33 +2631,161 @@ static int ipmi_probe(struct platform_device *dev)
2754 kfree(info); 2631 kfree(info);
2755 return ret; 2632 return ret;
2756 } 2633 }
2757#endif
2758 return 0; 2634 return 0;
2759} 2635}
2636#else
2637#define of_ipmi_match NULL
2638static int of_ipmi_probe(struct platform_device *dev)
2639{
2640 return -ENODEV;
2641}
2642#endif
2760 2643
2761static int ipmi_remove(struct platform_device *dev) 2644#ifdef CONFIG_ACPI
2645static int acpi_ipmi_probe(struct platform_device *dev)
2762{ 2646{
2763#ifdef CONFIG_OF 2647 struct smi_info *info;
2764 cleanup_one_si(dev_get_drvdata(&dev->dev)); 2648 struct resource *res, *res_second;
2649 acpi_handle handle;
2650 acpi_status status;
2651 unsigned long long tmp;
2652 int rv = -EINVAL;
2653
2654 handle = ACPI_HANDLE(&dev->dev);
2655 if (!handle)
2656 return -ENODEV;
2657
2658 info = smi_info_alloc();
2659 if (!info)
2660 return -ENOMEM;
2661
2662 info->addr_source = SI_ACPI;
2663 dev_info(&dev->dev, PFX "probing via ACPI\n");
2664
2665 info->addr_info.acpi_info.acpi_handle = handle;
2666
2667 /* _IFT tells us the interface type: KCS, BT, etc */
2668 status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
2669 if (ACPI_FAILURE(status)) {
2670 dev_err(&dev->dev, "Could not find ACPI IPMI interface type\n");
2671 goto err_free;
2672 }
2673
2674 switch (tmp) {
2675 case 1:
2676 info->si_type = SI_KCS;
2677 break;
2678 case 2:
2679 info->si_type = SI_SMIC;
2680 break;
2681 case 3:
2682 info->si_type = SI_BT;
2683 break;
2684 case 4: /* SSIF, just ignore */
2685 rv = -ENODEV;
2686 goto err_free;
2687 default:
2688 dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp);
2689 goto err_free;
2690 }
2691
2692 res = platform_get_resource(dev, IORESOURCE_IO, 0);
2693 if (res) {
2694 info->io_setup = port_setup;
2695 info->io.addr_type = IPMI_IO_ADDR_SPACE;
2696 } else {
2697 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
2698 if (res) {
2699 info->io_setup = mem_setup;
2700 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
2701 }
2702 }
2703 if (!res) {
2704 dev_err(&dev->dev, "no I/O or memory address\n");
2705 goto err_free;
2706 }
2707 info->io.addr_data = res->start;
2708
2709 info->io.regspacing = DEFAULT_REGSPACING;
2710 res_second = platform_get_resource(dev,
2711 (info->io.addr_type == IPMI_IO_ADDR_SPACE) ?
2712 IORESOURCE_IO : IORESOURCE_MEM,
2713 1);
2714 if (res_second) {
2715 if (res_second->start > info->io.addr_data)
2716 info->io.regspacing =
2717 res_second->start - info->io.addr_data;
2718 }
2719 info->io.regsize = DEFAULT_REGSPACING;
2720 info->io.regshift = 0;
2721
2722 /* If _GPE exists, use it; otherwise use standard interrupts */
2723 status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
2724 if (ACPI_SUCCESS(status)) {
2725 info->irq = tmp;
2726 info->irq_setup = acpi_gpe_irq_setup;
2727 } else {
2728 int irq = platform_get_irq(dev, 0);
2729
2730 if (irq > 0) {
2731 info->irq = irq;
2732 info->irq_setup = std_irq_setup;
2733 }
2734 }
2735
2736 info->dev = &dev->dev;
2737 platform_set_drvdata(dev, info);
2738
2739 dev_info(info->dev, "%pR regsize %d spacing %d irq %d\n",
2740 res, info->io.regsize, info->io.regspacing,
2741 info->irq);
2742
2743 rv = add_smi(info);
2744 if (rv)
2745 kfree(info);
2746
2747 return rv;
2748
2749err_free:
2750 kfree(info);
2751 return rv;
2752}
2753
2754static struct acpi_device_id acpi_ipmi_match[] = {
2755 { "IPI0001", 0 },
2756 { },
2757};
2758MODULE_DEVICE_TABLE(acpi, acpi_ipmi_match);
2759#else
2760static int acpi_ipmi_probe(struct platform_device *dev)
2761{
2762 return -ENODEV;
2763}
2765#endif 2764#endif
2766 return 0; 2765
2766static int ipmi_probe(struct platform_device *dev)
2767{
2768 if (of_ipmi_probe(dev) == 0)
2769 return 0;
2770
2771 return acpi_ipmi_probe(dev);
2767} 2772}
2768 2773
2769static const struct of_device_id ipmi_match[] = 2774static int ipmi_remove(struct platform_device *dev)
2770{ 2775{
2771 { .type = "ipmi", .compatible = "ipmi-kcs", 2776 struct smi_info *info = dev_get_drvdata(&dev->dev);
2772 .data = (void *)(unsigned long) SI_KCS }, 2777
2773 { .type = "ipmi", .compatible = "ipmi-smic", 2778 if (info)
2774 .data = (void *)(unsigned long) SI_SMIC }, 2779 cleanup_one_si(info);
2775 { .type = "ipmi", .compatible = "ipmi-bt", 2780
2776 .data = (void *)(unsigned long) SI_BT }, 2781 return 0;
2777 {}, 2782}
2778};
2779 2783
2780static struct platform_driver ipmi_driver = { 2784static struct platform_driver ipmi_driver = {
2781 .driver = { 2785 .driver = {
2782 .name = DEVICE_NAME, 2786 .name = DEVICE_NAME,
2783 .of_match_table = ipmi_match, 2787 .of_match_table = of_ipmi_match,
2788 .acpi_match_table = ACPI_PTR(acpi_ipmi_match),
2784 }, 2789 },
2785 .probe = ipmi_probe, 2790 .probe = ipmi_probe,
2786 .remove = ipmi_remove, 2791 .remove = ipmi_remove,
@@ -3692,13 +3697,6 @@ static int init_ipmi_si(void)
3692 } 3697 }
3693#endif 3698#endif
3694 3699
3695#ifdef CONFIG_ACPI
3696 if (si_tryacpi) {
3697 pnp_register_driver(&ipmi_pnp_driver);
3698 pnp_registered = true;
3699 }
3700#endif
3701
3702#ifdef CONFIG_DMI 3700#ifdef CONFIG_DMI
3703 if (si_trydmi) 3701 if (si_trydmi)
3704 dmi_find_bmc(); 3702 dmi_find_bmc();
@@ -3850,10 +3848,6 @@ static void cleanup_ipmi_si(void)
3850 if (pci_registered) 3848 if (pci_registered)
3851 pci_unregister_driver(&ipmi_pci_driver); 3849 pci_unregister_driver(&ipmi_pci_driver);
3852#endif 3850#endif
3853#ifdef CONFIG_ACPI
3854 if (pnp_registered)
3855 pnp_unregister_driver(&ipmi_pnp_driver);
3856#endif
3857#ifdef CONFIG_PARISC 3851#ifdef CONFIG_PARISC
3858 if (parisc_registered) 3852 if (parisc_registered)
3859 unregister_parisc_driver(&ipmi_parisc_driver); 3853 unregister_parisc_driver(&ipmi_parisc_driver);