mirror of
https://github.com/torvalds/linux.git
synced 2024-12-08 03:52:16 +00:00
ipmi_si: Switch hotmod to use a platform device
Don't force the main code to create one for it. Signed-off-by: Corey Minyard <cminyard@mvista.com>
This commit is contained in:
parent
3cd83bac48
commit
3bb8ea400c
@ -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);
|
||||
memset(&h, 0, sizeof(h));
|
||||
rv = parse_hotmod_str(curr, &op, &h);
|
||||
if (rv)
|
||||
break;
|
||||
op = ival;
|
||||
|
||||
rv = parse_str(hotmod_si, &ival, "interface type", &curr);
|
||||
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", ®spacing);
|
||||
if (rv < 0)
|
||||
goto out;
|
||||
else if (rv)
|
||||
continue;
|
||||
rv = check_hotmod_int_op(curr, o, "rsi", ®size);
|
||||
if (rv < 0)
|
||||
goto out;
|
||||
else if (rv)
|
||||
continue;
|
||||
rv = check_hotmod_int_op(curr, o, "rsh", ®shift);
|
||||
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;
|
||||
|
@ -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");
|
||||
|
@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user