]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipmi: Consolidate the adding of platform devices
authorCorey Minyard <cminyard@mvista.com>
Thu, 21 Feb 2019 20:21:17 +0000 (14:21 -0600)
committerCorey Minyard <cminyard@mvista.com>
Fri, 22 Feb 2019 13:12:41 +0000 (07:12 -0600)
It was being done in two different places now that hard-coded devices
use platform devices, and it's about to be three with hotmod switching
to platform devices.  So put the code in one place.

This required some rework on some interfaces to make the type space
clean.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
drivers/char/ipmi/Kconfig
drivers/char/ipmi/Makefile
drivers/char/ipmi/ipmi_dmi.c
drivers/char/ipmi/ipmi_dmi.h
drivers/char/ipmi/ipmi_plat_data.c [new file with mode: 0644]
drivers/char/ipmi/ipmi_plat_data.h [new file with mode: 0644]
drivers/char/ipmi/ipmi_si.h
drivers/char/ipmi/ipmi_si_hardcode.c
drivers/char/ipmi/ipmi_si_platform.c

index c108441882ccde34311729361afc7f2876e5f182..94719fc6ff9d3dc2a9c1cc0fc4d399c08128683f 100644 (file)
@@ -18,6 +18,10 @@ menuconfig IPMI_HANDLER
         If unsure, say N.
 
 config IPMI_DMI_DECODE
+       select IPMI_PLAT_DATA
+       bool
+
+config IPMI_PLAT_DATA
        bool
 
 if IPMI_HANDLER
@@ -56,6 +60,7 @@ config IPMI_DEVICE_INTERFACE
 
 config IPMI_SI
        tristate 'IPMI System Interface handler'
+       select IPMI_PLAT_DATA
        help
          Provides a driver for System Interfaces (KCS, SMIC, BT).
         Currently, only KCS and SMIC are supported.  If
index 7a3baf301a8f7a15ff442fe84ba045dd209c0d84..3f06b206247516e23cbe2065ec77289855201a55 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
 obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
 obj-$(CONFIG_IPMI_SI) += ipmi_si.o
 obj-$(CONFIG_IPMI_DMI_DECODE) += ipmi_dmi.o
+obj-$(CONFIG_IPMI_PLAT_DATA) += ipmi_plat_data.o
 obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o
 obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
index 249880457b17798a091b218fe4e33469f62f1144..ff0b199be4729757743bbd72bff2fc61a842d291 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/property.h>
 #include "ipmi_si_sm.h"
 #include "ipmi_dmi.h"
+#include "ipmi_plat_data.h"
 
 #define IPMI_DMI_TYPE_KCS      0x01
 #define IPMI_DMI_TYPE_SMIC     0x02
@@ -22,7 +23,7 @@
 
 struct ipmi_dmi_info {
        enum si_type si_type;
-       u32 flags;
+       unsigned int space; /* addr space for si, intf# for ssif */
        unsigned long addr;
        u8 slave_addr;
        struct ipmi_dmi_info *next;
@@ -33,133 +34,60 @@ static struct ipmi_dmi_info *ipmi_dmi_infos;
 static int ipmi_dmi_nr __initdata;
 
 static void __init dmi_add_platform_ipmi(unsigned long base_addr,
-                                        u32 flags,
+                                        unsigned int space,
                                         u8 slave_addr,
                                         int irq,
                                         int offset,
                                         int type)
 {
-       struct platform_device *pdev;
-       struct resource r[4];
-       unsigned int num_r = 1, size;
-       struct property_entry p[5];
-       unsigned int pidx = 0;
-       char *name;
-       int rv;
-       enum si_type si_type;
+       const char *name;
        struct ipmi_dmi_info *info;
+       struct ipmi_plat_data p;
 
-       memset(p, 0, sizeof(p));
+       memset(&p, 0, sizeof(p));
 
        name = "dmi-ipmi-si";
        switch (type) {
        case IPMI_DMI_TYPE_SSIF:
                name = "dmi-ipmi-ssif";
-               offset = 1;
-               size = 1;
-               si_type = SI_TYPE_INVALID;
+               p.type = SI_TYPE_INVALID;
                break;
        case IPMI_DMI_TYPE_BT:
-               size = 3;
-               si_type = SI_BT;
+               p.type = SI_BT;
                break;
        case IPMI_DMI_TYPE_KCS:
-               size = 2;
-               si_type = SI_KCS;
+               p.type = SI_KCS;
                break;
        case IPMI_DMI_TYPE_SMIC:
-               size = 2;
-               si_type = SI_SMIC;
+               p.type = SI_SMIC;
                break;
        default:
                pr_err("Invalid IPMI type: %d\n", type);
                return;
        }
 
-       if (si_type != SI_TYPE_INVALID)
-               p[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", si_type);
-
-       p[pidx++] = PROPERTY_ENTRY_U8("slave-addr", slave_addr);
-       p[pidx++] = PROPERTY_ENTRY_U8("addr-source", SI_SMBIOS);
+       memset(&p, 0, sizeof(p));
+       p.addr = base_addr;
+       p.space = space;
+       p.regspacing = offset;
+       p.irq = irq;
+       p.slave_addr = slave_addr;
+       p.addr_source = SI_SMBIOS;
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info) {
                pr_warn("Could not allocate dmi info\n");
        } else {
-               info->si_type = si_type;
-               info->flags = flags;
+               info->si_type = p.type;
+               info->space = space;
                info->addr = base_addr;
                info->slave_addr = slave_addr;
                info->next = ipmi_dmi_infos;
                ipmi_dmi_infos = info;
        }
 
-       pdev = platform_device_alloc(name, ipmi_dmi_nr);
-       if (!pdev) {
-               pr_err("Error allocation IPMI platform device\n");
-               return;
-       }
-
-       if (type == IPMI_DMI_TYPE_SSIF) {
-               p[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", base_addr);
-               goto add_properties;
-       }
-
-       memset(r, 0, sizeof(r));
-
-       r[0].start = base_addr;
-       r[0].end = r[0].start + offset - 1;
-       r[0].name = "IPMI Address 1";
-       r[0].flags = flags;
-
-       if (size > 1) {
-               r[1].start = r[0].start + offset;
-               r[1].end = r[1].start + offset - 1;
-               r[1].name = "IPMI Address 2";
-               r[1].flags = flags;
-               num_r++;
-       }
-
-       if (size > 2) {
-               r[2].start = r[1].start + offset;
-               r[2].end = r[2].start + offset - 1;
-               r[2].name = "IPMI Address 3";
-               r[2].flags = flags;
-               num_r++;
-       }
-
-       if (irq) {
-               r[num_r].start = irq;
-               r[num_r].end = irq;
-               r[num_r].name = "IPMI IRQ";
-               r[num_r].flags = IORESOURCE_IRQ;
-               num_r++;
-       }
-
-       rv = platform_device_add_resources(pdev, r, num_r);
-       if (rv) {
-               dev_err(&pdev->dev, "Unable to add resources: %d\n", rv);
-               goto err;
-       }
-
-add_properties:
-       rv = platform_device_add_properties(pdev, p);
-       if (rv) {
-               dev_err(&pdev->dev, "Unable to add properties: %d\n", rv);
-               goto err;
-       }
-
-       rv = platform_device_add(pdev);
-       if (rv) {
-               dev_err(&pdev->dev, "Unable to add device: %d\n", rv);
-               goto err;
-       }
-
-       ipmi_dmi_nr++;
-       return;
-
-err:
-       platform_device_put(pdev);
+       if (ipmi_platform_add(name, ipmi_dmi_nr, &p))
+               ipmi_dmi_nr++;
 }
 
 /*
@@ -169,14 +97,14 @@ err:
  * This function allows an ACPI-specified IPMI device to look up the
  * slave address from the DMI table.
  */
-int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags,
+int ipmi_dmi_get_slave_addr(enum si_type si_type, unsigned int space,
                            unsigned long base_addr)
 {
        struct ipmi_dmi_info *info = ipmi_dmi_infos;
 
        while (info) {
                if (info->si_type == si_type &&
-                   info->flags == flags &&
+                   info->space == space &&
                    info->addr == base_addr)
                        return info->slave_addr;
                info = info->next;
@@ -197,13 +125,13 @@ EXPORT_SYMBOL(ipmi_dmi_get_slave_addr);
 
 static void __init dmi_decode_ipmi(const struct dmi_header *dm)
 {
-       const u8        *data = (const u8 *) dm;
-       u32             flags = IORESOURCE_IO;
-       unsigned long   base_addr;
-       u8              len = dm->length;
-       u8              slave_addr;
-       int             irq = 0, offset;
-       int             type;
+       const u8 *data = (const u8 *) dm;
+       int space = IPMI_IO_ADDR_SPACE;
+       unsigned long base_addr;
+       u8 len = dm->length;
+       u8 slave_addr;
+       int irq = 0, offset = 0;
+       int type;
 
        if (len < DMI_IPMI_MIN_LENGTH)
                return;
@@ -218,8 +146,7 @@ static void __init dmi_decode_ipmi(const struct dmi_header *dm)
        }
        if (len >= DMI_IPMI_VER2_LENGTH) {
                if (type == IPMI_DMI_TYPE_SSIF) {
-                       offset = 0;
-                       flags = 0;
+                       space = 0; /* Match I2C interface 0. */
                        base_addr = data[DMI_IPMI_ADDR] >> 1;
                        if (base_addr == 0) {
                                /*
@@ -236,7 +163,7 @@ static void __init dmi_decode_ipmi(const struct dmi_header *dm)
                                base_addr &= DMI_IPMI_IO_MASK;
                        } else {
                                /* Memory */
-                               flags = IORESOURCE_MEM;
+                               space = IPMI_MEM_ADDR_SPACE;
                        }
 
                        /*
@@ -280,7 +207,7 @@ static void __init dmi_decode_ipmi(const struct dmi_header *dm)
                offset = 1;
        }
 
-       dmi_add_platform_ipmi(base_addr, flags, slave_addr, irq,
+       dmi_add_platform_ipmi(base_addr, space, slave_addr, irq,
                              offset, type);
 }
 
index 8d2b094db8e63b1fb6f090315bd278ffa5d870e8..2dbec0461d0c4373b52531792ab8e1162ab95e2e 100644 (file)
@@ -4,6 +4,6 @@
  */
 
 #ifdef CONFIG_IPMI_DMI_DECODE
-int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags,
+int ipmi_dmi_get_slave_addr(enum si_type si_type, unsigned int space,
                            unsigned long base_addr);
 #endif
diff --git a/drivers/char/ipmi/ipmi_plat_data.c b/drivers/char/ipmi/ipmi_plat_data.c
new file mode 100644 (file)
index 0000000..8f0ca2a
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Add an IPMI platform device.
+ */
+
+#include <linux/platform_device.h>
+#include "ipmi_plat_data.h"
+#include "ipmi_si.h"
+
+struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,
+                                         struct ipmi_plat_data *p)
+{
+       struct platform_device *pdev;
+       unsigned int num_r = 1, size, pidx = 0;
+       struct resource r[4];
+       struct property_entry pr[6];
+       u32 flags;
+       int rv;
+
+       memset(pr, 0, sizeof(pr));
+       memset(r, 0, sizeof(r));
+
+       if (p->type == SI_BT)
+               size = 3;
+       else if (p->type == SI_TYPE_INVALID)
+               size = 0;
+       else
+               size = 2;
+
+       if (p->regsize == 0)
+               p->regsize = DEFAULT_REGSIZE;
+       if (p->regspacing == 0)
+               p->regspacing = p->regsize;
+
+       pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);
+       if (p->slave_addr)
+               pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);
+       pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);
+       if (p->regshift)
+               pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift);
+       pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize);
+       /* Last entry must be left NULL to terminate it. */
+
+       pdev = platform_device_alloc(name, inst);
+       if (!pdev) {
+               pr_err("Error allocating IPMI platform device %s.%d\n",
+                      name, inst);
+               return NULL;
+       }
+
+       if (size == 0)
+               /* An invalid or SSIF interface, no resources. */
+               goto add_properties;
+
+       /*
+        * Register spacing is derived from the resources in
+        * the IPMI platform code.
+        */
+
+       if (p->space == IPMI_IO_ADDR_SPACE)
+               flags = IORESOURCE_IO;
+       else
+               flags = IORESOURCE_MEM;
+
+       r[0].start = p->addr;
+       r[0].end = r[0].start + p->regsize - 1;
+       r[0].name = "IPMI Address 1";
+       r[0].flags = flags;
+
+       if (size > 1) {
+               r[1].start = r[0].start + p->regspacing;
+               r[1].end = r[1].start + p->regsize - 1;
+               r[1].name = "IPMI Address 2";
+               r[1].flags = flags;
+               num_r++;
+       }
+
+       if (size > 2) {
+               r[2].start = r[1].start + p->regspacing;
+               r[2].end = r[2].start + p->regsize - 1;
+               r[2].name = "IPMI Address 3";
+               r[2].flags = flags;
+               num_r++;
+       }
+
+       if (p->irq) {
+               r[num_r].start = p->irq;
+               r[num_r].end = p->irq;
+               r[num_r].name = "IPMI IRQ";
+               r[num_r].flags = IORESOURCE_IRQ;
+               num_r++;
+       }
+
+       rv = platform_device_add_resources(pdev, r, num_r);
+       if (rv) {
+               dev_err(&pdev->dev,
+                       "Unable to add hard-code resources: %d\n", rv);
+               goto err;
+       }
+ add_properties:
+       rv = platform_device_add_properties(pdev, pr);
+       if (rv) {
+               dev_err(&pdev->dev,
+                       "Unable to add hard-code properties: %d\n", rv);
+               goto err;
+       }
+
+       rv = platform_device_add(pdev);
+       if (rv) {
+               dev_err(&pdev->dev,
+                       "Unable to add hard-code device: %d\n", rv);
+               goto err;
+       }
+       return pdev;
+
+err:
+       platform_device_put(pdev);
+       return NULL;
+}
+EXPORT_SYMBOL(ipmi_platform_add);
diff --git a/drivers/char/ipmi/ipmi_plat_data.h b/drivers/char/ipmi/ipmi_plat_data.h
new file mode 100644 (file)
index 0000000..567cfce
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Generic code to add IPMI platform devices.
+ */
+
+#include <linux/ipmi.h>
+
+struct ipmi_plat_data {
+       unsigned int type; /* si_type for si, SI_INVALID for others */
+       unsigned int space; /* addr_space for si, intf# for ssif. */
+       unsigned long addr;
+       unsigned int regspacing;
+       unsigned int regsize;
+       unsigned int regshift;
+       unsigned int irq;
+       unsigned int slave_addr;
+       enum ipmi_addr_src addr_source;
+};
+
+struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,
+                                         struct ipmi_plat_data *p);
index 3efc8a71aab4ec59fbd17af19547cdc5720c542a..49b211bf9ad769c3d8a45e154f9f7496737835a5 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 #include "ipmi_si_sm.h"
 
 #define DEFAULT_REGSPACING     1
index 86ac9b8a3219af54810874d30d299ac660b0b070..cb58298d80f59aa12d14feaf2b38b41dc8dd476a 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 #include "ipmi_si.h"
+#include "ipmi_plat_data.h"
 
 /*
  * There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
@@ -78,121 +79,39 @@ static struct platform_device *ipmi_hc_pdevs[SI_MAX_PARMS];
 static void __init ipmi_hardcode_init_one(const char *si_type_str,
                                          unsigned int i,
                                          unsigned long addr,
-                                         unsigned int flags)
+                                         enum ipmi_addr_space addr_space)
 {
-       struct platform_device *pdev;
-       unsigned int num_r = 1, size;
-       struct resource r[4];
-       struct property_entry p[6];
-       enum si_type si_type;
-       unsigned int regspacing, regsize;
-       int rv;
+       struct ipmi_plat_data p;
 
-       memset(p, 0, sizeof(p));
-       memset(r, 0, sizeof(r));
+       memset(&p, 0, sizeof(p));
 
        if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) {
-               size = 2;
-               si_type = SI_KCS;
+               p.type = SI_KCS;
        } else if (strcmp(si_type_str, "smic") == 0) {
-               size = 2;
-               si_type = SI_SMIC;
+               p.type = SI_SMIC;
        } else if (strcmp(si_type_str, "bt") == 0) {
-               size = 3;
-               si_type = SI_BT;
+               p.type = SI_BT;
        } else if (strcmp(si_type_str, "invalid") == 0) {
                /*
                 * Allow a firmware-specified interface to be
                 * disabled.
                 */
-               size = 1;
-               si_type = SI_TYPE_INVALID;
+               p.type = SI_TYPE_INVALID;
        } else {
                pr_warn("Interface type specified for interface %d, was invalid: %s\n",
                        i, si_type_str);
                return;
        }
 
-       regsize = regsizes[i];
-       if (regsize == 0)
-               regsize = DEFAULT_REGSIZE;
+       p.regsize = regsizes[i];
+       p.slave_addr = slave_addrs[i];
+       p.addr_source = SI_HARDCODED;
+       p.regshift = regshifts[i];
+       p.regsize = regsizes[i];
+       p.addr = addr;
+       p.space = addr_space;
 
-       p[0] = PROPERTY_ENTRY_U8("ipmi-type", si_type);
-       p[1] = PROPERTY_ENTRY_U8("slave-addr", slave_addrs[i]);
-       p[2] = PROPERTY_ENTRY_U8("addr-source", SI_HARDCODED);
-       p[3] = PROPERTY_ENTRY_U8("reg-shift", regshifts[i]);
-       p[4] = PROPERTY_ENTRY_U8("reg-size", regsize);
-       /* Last entry must be left NULL to terminate it. */
-
-       /*
-        * Register spacing is derived from the resources in
-        * the IPMI platform code.
-        */
-       regspacing = regspacings[i];
-       if (regspacing == 0)
-               regspacing = regsize;
-
-       r[0].start = addr;
-       r[0].end = r[0].start + regsize - 1;
-       r[0].name = "IPMI Address 1";
-       r[0].flags = flags;
-
-       if (size > 1) {
-               r[1].start = r[0].start + regspacing;
-               r[1].end = r[1].start + regsize - 1;
-               r[1].name = "IPMI Address 2";
-               r[1].flags = flags;
-               num_r++;
-       }
-
-       if (size > 2) {
-               r[2].start = r[1].start + regspacing;
-               r[2].end = r[2].start + regsize - 1;
-               r[2].name = "IPMI Address 3";
-               r[2].flags = flags;
-               num_r++;
-       }
-
-       if (irqs[i]) {
-               r[num_r].start = irqs[i];
-               r[num_r].end = irqs[i];
-               r[num_r].name = "IPMI IRQ";
-               r[num_r].flags = IORESOURCE_IRQ;
-               num_r++;
-       }
-
-       pdev = platform_device_alloc("hardcode-ipmi-si", i);
-       if (!pdev) {
-               pr_err("Error allocating IPMI platform device %d\n", i);
-               return;
-       }
-
-       rv = platform_device_add_resources(pdev, r, num_r);
-       if (rv) {
-               dev_err(&pdev->dev,
-                       "Unable to add hard-code resources: %d\n", rv);
-               goto err;
-       }
-
-       rv = platform_device_add_properties(pdev, p);
-       if (rv) {
-               dev_err(&pdev->dev,
-                       "Unable to add hard-code properties: %d\n", rv);
-               goto err;
-       }
-
-       rv = platform_device_add(pdev);
-       if (rv) {
-               dev_err(&pdev->dev,
-                       "Unable to add hard-code device: %d\n", rv);
-               goto err;
-       }
-
-       ipmi_hc_pdevs[i] = pdev;
-       return;
-
-err:
-       platform_device_put(pdev);
+       ipmi_hc_pdevs[i] = ipmi_platform_add("hardcode-ipmi-si", i, &p);
 }
 
 void __init ipmi_hardcode_init(void)
@@ -219,10 +138,10 @@ void __init ipmi_hardcode_init(void)
        for (i = 0; i < SI_MAX_PARMS; i++) {
                if (i < num_ports && ports[i])
                        ipmi_hardcode_init_one(si_type[i], i, ports[i],
-                                              IORESOURCE_IO);
+                                              IPMI_IO_ADDR_SPACE);
                if (i < num_addrs && addrs[i])
                        ipmi_hardcode_init_one(si_type[i], i, addrs[i],
-                                              IORESOURCE_MEM);
+                                              IPMI_MEM_ADDR_SPACE);
        }
 }
 
index f690e9edb08c1aec97daf64f92ef4424c1010bc9..f2b5ac0986f257aebb3ca9495f5e52bff5d589b7 100644 (file)
@@ -307,15 +307,10 @@ static int of_ipmi_probe(struct platform_device *dev)
 static int find_slave_address(struct si_sm_io *io, int slave_addr)
 {
 #ifdef CONFIG_IPMI_DMI_DECODE
-       if (!slave_addr) {
-               u32 flags = IORESOURCE_IO;
-
-               if (io->addr_space == IPMI_MEM_ADDR_SPACE)
-                       flags = IORESOURCE_MEM;
-
-               slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags,
+       if (!slave_addr)
+               slave_addr = ipmi_dmi_get_slave_addr(io->si_type,
+                                                    io->addr_space,
                                                     io->addr_data);
-       }
 #endif
 
        return slave_addr;