Commit 3bb8ea40 authored by Corey Minyard's avatar Corey Minyard
Browse files

ipmi_si: Switch hotmod to use a platform device



Don't force the main code to create one for it.

Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
parent 3cd83bac
Loading
Loading
Loading
Loading
+96 −112
Original line number Diff line number Diff line
@@ -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,71 +101,37 @@ static int check_hotmod_int_op(const char *curr, const char *option,
	return 0;
}

static int hotmod_handler(const char *val, const struct kernel_param *kp)
static int parse_hotmod_str(const char *curr, enum hotmod_op *op,
			    struct ipmi_plat_data *h)
{
	char *str = kstrdup(val, GFP_KERNEL);
	char *s, *o;
	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;

	if (!str)
		return -ENOMEM;

	/* Kill any trailing spaces, as we can get a "\n" from echo. */
	len = strlen(str);
	ival = len - 1;
	while ((ival >= 0) && isspace(str[ival])) {
		str[ival] = '\0';
		ival--;
	}

	for (curr = str; curr; curr = next) {
		regspacing = 1;
		regsize = 1;
		regshift = 0;
		irq = 0;
		ipmb = 0; /* Choose the default if not specified */

		next = strchr(curr, ':');
		if (next) {
			*next = '\0';
			next++;
		}
	unsigned int ival;

	rv = parse_str(hotmod_ops, &ival, "operation", &curr);
	if (rv)
			break;
		op = ival;
		return rv;
	*op = ival;

	rv = parse_str(hotmod_si, &ival, "interface type", &curr);
	if (rv)
			break;
		si_type = ival;
		return rv;
	h->type = ival;

	rv = parse_str(hotmod_as, &ival, "address space", &curr);
	if (rv)
			break;
		addr_space = ival;
		return rv;
	h->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;
	rv = kstrtoul(curr, 0, &h->addr);
	if (rv) {
		pr_warn("Invalid hotmod address '%s': %d\n", curr, rv);
		return rv;
	}

	while (s) {
@@ -178,64 +146,80 @@ static int hotmod_handler(const char *val, const struct kernel_param *kp)
			*o = '\0';
			o++;
		}
			rv = check_hotmod_int_op(curr, o, "rsp", &regspacing);
		rv = check_hotmod_int_op(curr, o, "rsp", &h->regspacing);
		if (rv < 0)
				goto out;
			return rv;
		else if (rv)
			continue;
			rv = check_hotmod_int_op(curr, o, "rsi", &regsize);
		rv = check_hotmod_int_op(curr, o, "rsi", &h->regsize);
		if (rv < 0)
				goto out;
			return rv;
		else if (rv)
			continue;
			rv = check_hotmod_int_op(curr, o, "rsh", &regshift);
		rv = check_hotmod_int_op(curr, o, "rsh", &h->regshift);
		if (rv < 0)
				goto out;
			return rv;
		else if (rv)
			continue;
			rv = check_hotmod_int_op(curr, o, "irq", &irq);
		rv = check_hotmod_int_op(curr, o, "irq", &h->irq);
		if (rv < 0)
				goto out;
			return rv;
		else if (rv)
			continue;
			rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb);
		rv = check_hotmod_int_op(curr, o, "ipmb", &h->slave_addr);
		if (rv < 0)
				goto out;
			return rv;
		else if (rv)
			continue;

			rv = -EINVAL;
		pr_warn("Invalid hotmod option '%s'\n", curr);
			goto out;
		return -EINVAL;
	}

		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);
	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), *curr, *next;
	int  rv;
	struct ipmi_plat_data h;
	unsigned int len, ival;

	if (!str)
		return -ENOMEM;

	/* Kill any trailing spaces, as we can get a "\n" from echo. */
	len = strlen(str);
	ival = len - 1;
	while ((ival >= 0) && isspace(str[ival])) {
		str[ival] = '\0';
		ival--;
	}

	for (curr = str; curr; curr = next) {
		enum hotmod_op op;

		next = strchr(curr, ':');
		if (next) {
			*next = '\0';
			next++;
		}

		memset(&h, 0, sizeof(h));
		rv = parse_hotmod_str(curr, &op, &h);
		if (rv)
			goto out;

		if (op == HM_ADD) {
			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;
+1 −1
Original line number Diff line number Diff line
@@ -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");
+1 −0
Original line number Diff line number Diff line
@@ -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 },
	{ }
};