Loading drivers/char/ipmi/ipmi_si_hotmod.c +96 −112 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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", ®spacing); 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", ®size); 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", ®shift); 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; Loading drivers/char/ipmi/ipmi_si_intf.c +1 −1 Original line number Diff line number Diff line Loading @@ -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"); Loading drivers/char/ipmi/ipmi_si_platform.c +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/char/ipmi/ipmi_si_hotmod.c +96 −112 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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", ®spacing); 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", ®size); 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", ®shift); 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; Loading
drivers/char/ipmi/ipmi_si_intf.c +1 −1 Original line number Diff line number Diff line Loading @@ -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"); Loading
drivers/char/ipmi/ipmi_si_platform.c +1 −0 Original line number Diff line number Diff line Loading @@ -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