From 44814ec982d2905d50fe4d0cdaf693b76afe7f64 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 12 Sep 2017 22:28:49 -0500 Subject: ipmi_si: Move the hotmod handling to another file. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_intf.c | 261 +++------------------------------------ 1 file changed, 18 insertions(+), 243 deletions(-) (limited to 'drivers/char/ipmi/ipmi_si_intf.c') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 6c2e14af8321..02e263b2152a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1310,13 +1310,6 @@ static unsigned int num_slave_addrs; static const char * const addr_space_to_str[] = { "i/o", "mem" }; -static int hotmod_handler(const char *val, struct kernel_param *kp); - -module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200); -MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" - " Documentation/IPMI.txt in the kernel sources for the" - " gory details."); - #ifdef CONFIG_ACPI module_param_named(tryacpi, si_tryacpi, bool, 0); MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" @@ -1689,86 +1682,6 @@ static int mem_setup(struct si_sm_io *io) return 0; } -/* - * Parms come in as [:op2[:op3...]]. ops are: - * add|remove,kcs|bt|smic,mem|i/o,
[,[,[,...]]] - * Options are: - * rsp= - * rsi= - * rsh= - * irq= - * ipmb= - */ -enum hotmod_op { HM_ADD, HM_REMOVE }; -struct hotmod_vals { - const char *name; - const int val; -}; - -static const struct hotmod_vals hotmod_ops[] = { - { "add", HM_ADD }, - { "remove", HM_REMOVE }, - { NULL } -}; - -static const struct hotmod_vals hotmod_si[] = { - { "kcs", SI_KCS }, - { "smic", SI_SMIC }, - { "bt", SI_BT }, - { NULL } -}; - -static const struct hotmod_vals hotmod_as[] = { - { "mem", IPMI_MEM_ADDR_SPACE }, - { "i/o", IPMI_IO_ADDR_SPACE }, - { NULL } -}; - -static int parse_str(const struct hotmod_vals *v, int *val, char *name, - char **curr) -{ - char *s; - int i; - - s = strchr(*curr, ','); - if (!s) { - pr_warn(PFX "No hotmod %s given.\n", name); - return -EINVAL; - } - *s = '\0'; - s++; - for (i = 0; v[i].name; i++) { - if (strcmp(*curr, v[i].name) == 0) { - *val = v[i].val; - *curr = s; - return 0; - } - } - - pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr); - return -EINVAL; -} - -static int check_hotmod_int_op(const char *curr, const char *option, - const char *name, int *val) -{ - char *n; - - if (strcmp(curr, name) == 0) { - if (!option) { - pr_warn(PFX "No option given for '%s'\n", curr); - return -EINVAL; - } - *val = simple_strtoul(option, &n, 0); - if ((*n != '\0') || (*option == '\0')) { - pr_warn(PFX "Bad option given for '%s'\n", curr); - return -EINVAL; - } - return 1; - } - return 0; -} - static struct smi_info *smi_info_alloc(void) { struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -1778,162 +1691,6 @@ static struct smi_info *smi_info_alloc(void) return info; } -static int hotmod_handler(const char *val, struct kernel_param *kp) -{ - char *str = kstrdup(val, GFP_KERNEL); - int rv; - char *next, *curr, *s, *n, *o; - enum hotmod_op op; - enum si_type si_type; - int 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++; - } - - rv = parse_str(hotmod_ops, &ival, "operation", &curr); - 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, &addr_space, "address space", &curr); - if (rv) - break; - - s = strchr(curr, ','); - if (s) { - *s = '\0'; - s++; - } - addr = simple_strtoul(curr, &n, 0); - if ((*n != '\0') || (*curr == '\0')) { - pr_warn(PFX "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(PFX "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_type = 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; - } else { - /* remove */ - struct smi_info *e, *tmp_e; - - mutex_lock(&smi_infos_lock); - list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { - if (e->io.addr_type != addr_space) - continue; - if (e->io.si_type != si_type) - continue; - if (e->io.addr_data == addr) - cleanup_one_si(e); - } - mutex_unlock(&smi_infos_lock); - } - } - rv = len; -out: - kfree(str); - return rv; -} - static int hardcode_find_bmc(void) { int ret = -ENODEV; @@ -3779,6 +3536,24 @@ int ipmi_si_remove_by_dev(struct device *dev) return rv; } +void ipmi_si_remove_by_data(int addr_space, enum si_type si_type, + unsigned long addr) +{ + /* remove */ + struct smi_info *e, *tmp_e; + + mutex_lock(&smi_infos_lock); + list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { + if (e->io.addr_type != addr_space) + continue; + if (e->io.si_type != si_type) + continue; + if (e->io.addr_data == addr) + cleanup_one_si(e); + } + mutex_unlock(&smi_infos_lock); +} + static void cleanup_ipmi_si(void) { struct smi_info *e, *tmp_e; -- cgit