static int __init ipmi_parisc_probe(struct parisc_device *dev) { struct si_sm_io io; io.si_type = SI_KCS; io.addr_source = SI_DEVICETREE; io.addr_type = IPMI_MEM_ADDR_SPACE; io.addr_data = dev->hpa.start; io.regsize = 1; io.regspacing = 1; io.regshift = 0; io.irq = 0; /* no interrupt */ io.irq_setup = NULL; io.dev = &dev->dev; dev_dbg(&dev->dev, "addr 0x%lx\n", io.addr_data); return ipmi_si_add_smi(&io); }
int ipmi_si_hardcode_find_bmc(void) { int ret = -ENODEV; int i; struct si_sm_io io; char *str; /* Parse out the si_type string into its components. */ str = si_type_str; if (*str != '\0') { for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) { si_type[i] = str; str = strchr(str, ','); if (str) { *str = '\0'; str++; } else { break; } } } memset(&io, 0, sizeof(io)); for (i = 0; i < SI_MAX_PARMS; i++) { if (!ports[i] && !addrs[i]) continue; io.addr_source = SI_HARDCODED; pr_info(PFX "probing via hardcoded address\n"); if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { io.si_type = SI_KCS; } else if (strcmp(si_type[i], "smic") == 0) { io.si_type = SI_SMIC; } else if (strcmp(si_type[i], "bt") == 0) { io.si_type = SI_BT; } else { pr_warn(PFX "Interface type specified for interface %d, was invalid: %s\n", i, si_type[i]); continue; } if (ports[i]) { /* An I/O port */ io.addr_data = ports[i]; io.addr_type = IPMI_IO_ADDR_SPACE; } else if (addrs[i]) { /* A memory port */ io.addr_data = addrs[i]; io.addr_type = IPMI_MEM_ADDR_SPACE; } else { pr_warn(PFX "Interface type specified for interface %d, but port and address were not set or set to zero.\n", i); continue; } io.addr = NULL; io.regspacing = regspacings[i]; if (!io.regspacing) io.regspacing = DEFAULT_REGSPACING; io.regsize = regsizes[i]; if (!io.regsize) io.regsize = DEFAULT_REGSIZE; io.regshift = regshifts[i]; io.irq = irqs[i]; if (io.irq) io.irq_setup = ipmi_std_irq_setup; io.slave_addr = slave_addrs[i]; ret = ipmi_si_add_smi(&io); } return ret; }
static int hotmod_handler(const char *val, const 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; }
static int ipmi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rv; struct si_sm_io io; if (pci_match_id(ipmi_pci_blacklist, pdev)) return -ENODEV; memset(&io, 0, sizeof(io)); io.addr_source = SI_PCI; dev_info(&pdev->dev, "probing via PCI"); switch (pdev->class) { case PCI_CLASS_SERIAL_IPMI_SMIC: io.si_type = SI_SMIC; break; case PCI_CLASS_SERIAL_IPMI_KCS: io.si_type = SI_KCS; break; case PCI_CLASS_SERIAL_IPMI_BT: io.si_type = SI_BT; break; default: dev_info(&pdev->dev, "Unknown IPMI class: %x\n", pdev->class); return -ENOMEM; } rv = pci_enable_device(pdev); if (rv) { dev_err(&pdev->dev, "couldn't enable PCI device\n"); return rv; } io.addr_source_cleanup = ipmi_pci_cleanup; io.addr_source_data = pdev; if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { io.addr_space = IPMI_IO_ADDR_SPACE; io.io_setup = ipmi_si_port_setup; } else { io.addr_space = IPMI_MEM_ADDR_SPACE; io.io_setup = ipmi_si_mem_setup; } io.addr_data = pci_resource_start(pdev, 0); io.dev = &pdev->dev; io.regspacing = ipmi_pci_probe_regspacing(&io); io.regsize = DEFAULT_REGSIZE; io.regshift = 0; io.irq = pdev->irq; if (io.irq) io.irq_setup = ipmi_std_irq_setup; dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", &pdev->resource[0], io.regsize, io.regspacing, io.irq); rv = ipmi_si_add_smi(&io); if (rv) pci_disable_device(pdev); return rv; }