ipmi_si: Switch hotmod to use a platform device
authorCorey Minyard <cminyard@mvista.com>
Thu, 21 Feb 2019 20:23:07 +0000 (14:23 -0600)
committerCorey Minyard <cminyard@mvista.com>
Fri, 22 Feb 2019 13:12:41 +0000 (07:12 -0600)
Don't force the main code to create one for it.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
drivers/char/ipmi/ipmi_si_hotmod.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_si_platform.c

index f3d455bbf3ccdfaface913f93e1e6ac55df10e8e..f0728be00bd2bb863b83d3d7ab5f8f0e784cd8ef 100644 (file)
@@ -10,7 +10,9 @@
 
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
+#include <linux/atomic.h>
 #include "ipmi_si.h"
+#include "ipmi_plat_data.h"
 
 static int hotmod_handler(const char *val, const struct kernel_param *kp);
 
@@ -54,8 +56,8 @@ static const struct hotmod_vals hotmod_as[] = {
        { NULL }
 };
 
-static int parse_str(const struct hotmod_vals *v, int *val, char *name,
-                    char **curr)
+static int parse_str(const struct hotmod_vals *v, unsigned int *val, char *name,
+                    const char **curr)
 {
        char *s;
        int  i;
@@ -80,7 +82,7 @@ static int parse_str(const struct hotmod_vals *v, int *val, char *name,
 }
 
 static int check_hotmod_int_op(const char *curr, const char *option,
-                              const char *name, int *val)
+                              const char *name, unsigned int *val)
 {
        char *n;
 
@@ -99,22 +101,93 @@ static int check_hotmod_int_op(const char *curr, const char *option,
        return 0;
 }
 
+static int parse_hotmod_str(const char *curr, enum hotmod_op *op,
+                           struct ipmi_plat_data *h)
+{
+       char *s, *o;
+       int rv;
+       unsigned int ival;
+
+       rv = parse_str(hotmod_ops, &ival, "operation", &curr);
+       if (rv)
+               return rv;
+       *op = ival;
+
+       rv = parse_str(hotmod_si, &ival, "interface type", &curr);
+       if (rv)
+               return rv;
+       h->type = ival;
+
+       rv = parse_str(hotmod_as, &ival, "address space", &curr);
+       if (rv)
+               return rv;
+       h->space = ival;
+
+       s = strchr(curr, ',');
+       if (s) {
+               *s = '\0';
+               s++;
+       }
+       rv = kstrtoul(curr, 0, &h->addr);
+       if (rv) {
+               pr_warn("Invalid hotmod address '%s': %d\n", curr, rv);
+               return rv;
+       }
+
+       while (s) {
+               curr = s;
+               s = strchr(curr, ',');
+               if (s) {
+                       *s = '\0';
+                       s++;
+               }
+               o = strchr(curr, '=');
+               if (o) {
+                       *o = '\0';
+                       o++;
+               }
+               rv = check_hotmod_int_op(curr, o, "rsp", &h->regspacing);
+               if (rv < 0)
+                       return rv;
+               else if (rv)
+                       continue;
+               rv = check_hotmod_int_op(curr, o, "rsi", &h->regsize);
+               if (rv < 0)
+                       return rv;
+               else if (rv)
+                       continue;
+               rv = check_hotmod_int_op(curr, o, "rsh", &h->regshift);
+               if (rv < 0)
+                       return rv;
+               else if (rv)
+                       continue;
+               rv = check_hotmod_int_op(curr, o, "irq", &h->irq);
+               if (rv < 0)
+                       return rv;
+               else if (rv)
+                       continue;
+               rv = check_hotmod_int_op(curr, o, "ipmb", &h->slave_addr);
+               if (rv < 0)
+                       return rv;
+               else if (rv)
+                       continue;
+
+               pr_warn("Invalid hotmod option '%s'\n", curr);
+               return -EINVAL;
+       }
+
+       h->addr_source = SI_HOTMOD;
+       return 0;
+}
+
+static atomic_t hotmod_nr;
+
 static int hotmod_handler(const char *val, const struct kernel_param *kp)
 {
-       char *str = kstrdup(val, GFP_KERNEL);
+       char *str = kstrdup(val, GFP_KERNEL), *curr, *next;
        int  rv;
-       char *next, *curr, *s, *n, *o;
-       enum hotmod_op op;
-       enum si_type si_type;
-       enum ipmi_addr_space addr_space;
-       unsigned long addr;
-       int regspacing;
-       int regsize;
-       int regshift;
-       int irq;
-       int ipmb;
-       int ival;
-       int len;
+       struct ipmi_plat_data h;
+       unsigned int len, ival;
 
        if (!str)
                return -ENOMEM;
@@ -128,11 +201,7 @@ static int hotmod_handler(const char *val, const struct kernel_param *kp)
        }
 
        for (curr = str; curr; curr = next) {
-               regspacing = 1;
-               regsize = 1;
-               regshift = 0;
-               irq = 0;
-               ipmb = 0; /* Choose the default if not specified */
+               enum hotmod_op op;
 
                next = strchr(curr, ':');
                if (next) {
@@ -140,102 +209,17 @@ static int hotmod_handler(const char *val, const struct kernel_param *kp)
                        next++;
                }
 
-               rv = parse_str(hotmod_ops, &ival, "operation", &curr);
-               if (rv)
-                       break;
-               op = ival;
-
-               rv = parse_str(hotmod_si, &ival, "interface type", &curr);
+               memset(&h, 0, sizeof(h));
+               rv = parse_hotmod_str(curr, &op, &h);
                if (rv)
-                       break;
-               si_type = ival;
-
-               rv = parse_str(hotmod_as, &ival, "address space", &curr);
-               if (rv)
-                       break;
-               addr_space = ival;
-
-               s = strchr(curr, ',');
-               if (s) {
-                       *s = '\0';
-                       s++;
-               }
-               addr = simple_strtoul(curr, &n, 0);
-               if ((*n != '\0') || (*curr == '\0')) {
-                       pr_warn("Invalid hotmod address '%s'\n", curr);
-                       break;
-               }
-
-               while (s) {
-                       curr = s;
-                       s = strchr(curr, ',');
-                       if (s) {
-                               *s = '\0';
-                               s++;
-                       }
-                       o = strchr(curr, '=');
-                       if (o) {
-                               *o = '\0';
-                               o++;
-                       }
-                       rv = check_hotmod_int_op(curr, o, "rsp", &regspacing);
-                       if (rv < 0)
-                               goto out;
-                       else if (rv)
-                               continue;
-                       rv = check_hotmod_int_op(curr, o, "rsi", &regsize);
-                       if (rv < 0)
-                               goto out;
-                       else if (rv)
-                               continue;
-                       rv = check_hotmod_int_op(curr, o, "rsh", &regshift);
-                       if (rv < 0)
-                               goto out;
-                       else if (rv)
-                               continue;
-                       rv = check_hotmod_int_op(curr, o, "irq", &irq);
-                       if (rv < 0)
-                               goto out;
-                       else if (rv)
-                               continue;
-                       rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb);
-                       if (rv < 0)
-                               goto out;
-                       else if (rv)
-                               continue;
-
-                       rv = -EINVAL;
-                       pr_warn("Invalid hotmod option '%s'\n", curr);
                        goto out;
-               }
 
                if (op == HM_ADD) {
-                       struct si_sm_io io;
-
-                       memset(&io, 0, sizeof(io));
-                       io.addr_source = SI_HOTMOD;
-                       io.si_type = si_type;
-                       io.addr_data = addr;
-                       io.addr_space = addr_space;
-
-                       io.addr = NULL;
-                       io.regspacing = regspacing;
-                       if (!io.regspacing)
-                               io.regspacing = DEFAULT_REGSPACING;
-                       io.regsize = regsize;
-                       if (!io.regsize)
-                               io.regsize = DEFAULT_REGSIZE;
-                       io.regshift = regshift;
-                       io.irq = irq;
-                       if (io.irq)
-                               io.irq_setup = ipmi_std_irq_setup;
-                       io.slave_addr = ipmb;
-
-                       rv = ipmi_si_add_smi(&io);
-                       if (rv)
-                               goto out;
+                       ipmi_platform_add("hotmod-ipmi-si",
+                                         atomic_inc_return(&hotmod_nr),
+                                         &h);
                } else {
-                       ipmi_si_remove_by_data(addr_space, si_type, addr);
+                       ipmi_si_remove_by_data(h.space, h.type, h.addr);
                }
        }
        rv = len;
index 54e3b4f2c02485f7561942caa65452342c457628..c8af06dfa24456804b389dd91e79ba5387d20b56 100644 (file)
@@ -1870,7 +1870,7 @@ int ipmi_si_add_smi(struct si_sm_io *io)
         * address, they presumably want us to use it and not what is
         * in the firmware.
         */
-       if (io->addr_source != SI_HARDCODED &&
+       if (io->addr_source != SI_HARDCODED && io->addr_source != SI_HOTMOD &&
            ipmi_si_hardcode_match(io->addr_space, io->addr_data)) {
                dev_info(io->dev,
                         "Hard-coded device at this address already exists");
index f2b5ac0986f257aebb3ca9495f5e52bff5d589b7..0f493fe8370179c22416301f7f6661090a9da15d 100644 (file)
@@ -431,6 +431,7 @@ static int ipmi_remove(struct platform_device *pdev)
 static const struct platform_device_id si_plat_ids[] = {
        { "dmi-ipmi-si", 0 },
        { "hardcode-ipmi-si", 0 },
+       { "hotmod-ipmi-si", 0 },
        { }
 };