Loading drivers/char/ipmi/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ # Makefile for the ipmi drivers. # ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \ ipmi_si_hotmod.o obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o Loading drivers/char/ipmi/ipmi_si.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,3 +20,5 @@ void ipmi_irq_start_cleanup(struct si_sm_io *io); int ipmi_std_irq_setup(struct si_sm_io *io); void ipmi_irq_finish_setup(struct si_sm_io *io); int ipmi_si_remove_by_dev(struct device *dev); void ipmi_si_remove_by_data(int addr_space, enum si_type si_type, unsigned long addr); drivers/char/ipmi/ipmi_si_hotmod.c 0 → 100644 +242 −0 Original line number Diff line number Diff line /* * ipmi_si_hotmod.c * * Handling for dynamically adding/removing IPMI devices through * a module parameter (and thus sysfs). */ #include <linux/moduleparam.h> #include <linux/ipmi.h> #include "ipmi_si.h" #define PFX "ipmi_hotmod: " 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."); /* * Parms come in as <op1>[:op2[:op3...]]. ops are: * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] * Options are: * rsp=<regspacing> * rsi=<regsize> * rsh=<regshift> * irq=<irq> * ipmb=<ipmb addr> */ 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 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 { ipmi_si_remove_by_data(addr_space, si_type, addr); } } rv = len; out: kfree(str); return rv; } drivers/char/ipmi/ipmi_si_intf.c +18 −243 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -1689,86 +1682,6 @@ static int mem_setup(struct si_sm_io *io) return 0; } /* * Parms come in as <op1>[:op2[:op3...]]. ops are: * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] * Options are: * rsp=<regspacing> * rsi=<regsize> * rsh=<regshift> * irq=<irq> * ipmb=<ipmb addr> */ 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); Loading @@ -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; Loading Loading @@ -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; Loading Loading
drivers/char/ipmi/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ # Makefile for the ipmi drivers. # ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \ ipmi_si_hotmod.o obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o Loading
drivers/char/ipmi/ipmi_si.h +2 −0 Original line number Diff line number Diff line Loading @@ -20,3 +20,5 @@ void ipmi_irq_start_cleanup(struct si_sm_io *io); int ipmi_std_irq_setup(struct si_sm_io *io); void ipmi_irq_finish_setup(struct si_sm_io *io); int ipmi_si_remove_by_dev(struct device *dev); void ipmi_si_remove_by_data(int addr_space, enum si_type si_type, unsigned long addr);
drivers/char/ipmi/ipmi_si_hotmod.c 0 → 100644 +242 −0 Original line number Diff line number Diff line /* * ipmi_si_hotmod.c * * Handling for dynamically adding/removing IPMI devices through * a module parameter (and thus sysfs). */ #include <linux/moduleparam.h> #include <linux/ipmi.h> #include "ipmi_si.h" #define PFX "ipmi_hotmod: " 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."); /* * Parms come in as <op1>[:op2[:op3...]]. ops are: * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] * Options are: * rsp=<regspacing> * rsi=<regsize> * rsh=<regshift> * irq=<irq> * ipmb=<ipmb addr> */ 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 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 { ipmi_si_remove_by_data(addr_space, si_type, addr); } } rv = len; out: kfree(str); return rv; }
drivers/char/ipmi/ipmi_si_intf.c +18 −243 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -1689,86 +1682,6 @@ static int mem_setup(struct si_sm_io *io) return 0; } /* * Parms come in as <op1>[:op2[:op3...]]. ops are: * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] * Options are: * rsp=<regspacing> * rsi=<regsize> * rsh=<regshift> * irq=<irq> * ipmb=<ipmb addr> */ 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); Loading @@ -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; Loading Loading @@ -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; Loading