/* Returns 0 if initialized, or negative on an error. */ static int init_one_kcs(int kcs_port, int irq, unsigned long kcs_physaddr, struct kcs_info **kcs) { int rv; struct kcs_info *new_kcs; /* Did anything get passed in at all? Both == zero disables the driver. */ if (!(kcs_port || kcs_physaddr)) return -ENODEV; /* Only initialize a port OR a physical address on this call. Also, IRQs can go with either ports or addresses. */ if (kcs_port && kcs_physaddr) return -EINVAL; new_kcs = kmalloc(sizeof(*new_kcs), GFP_KERNEL); if (!new_kcs) { printk(KERN_ERR "ipmi_kcs: out of memory\n"); return -ENOMEM; } /* So we know not to free it unless we have allocated one. */ new_kcs->kcs_sm = NULL; new_kcs->addr = NULL; new_kcs->physaddr = kcs_physaddr; new_kcs->port = kcs_port; if (kcs_port) { if (request_region(kcs_port, 2, DEVICE_NAME) == NULL) { kfree(new_kcs); printk(KERN_ERR "ipmi_kcs: can't reserve port @ 0x%4.4x\n", kcs_port); return -EIO; } } else { if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) { kfree(new_kcs); printk(KERN_ERR "ipmi_kcs: can't reserve memory @ 0x%lx\n", kcs_physaddr); return -EIO; } if ((new_kcs->addr = ioremap(kcs_physaddr, 2)) == NULL) { kfree(new_kcs); printk(KERN_ERR "ipmi_kcs: can't remap memory at 0x%lx\n", kcs_physaddr); return -EIO; } } new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL); if (!new_kcs->kcs_sm) { printk(KERN_ERR "ipmi_kcs: out of memory\n"); rv = -ENOMEM; goto out_err; } init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr); spin_lock_init(&(new_kcs->kcs_lock)); spin_lock_init(&(new_kcs->msg_lock)); rv = ipmi_kcs_detect_hardware(kcs_port, new_kcs->addr, new_kcs->kcs_sm); if (rv) { if (kcs_port) printk(KERN_ERR "ipmi_kcs: No KCS @ port 0x%4.4x\n", kcs_port); else printk(KERN_ERR "ipmi_kcs: No KCS @ addr 0x%lx\n", kcs_physaddr); goto out_err; } if (irq != 0) { rv = request_irq(irq, kcs_irq_handler, SA_INTERRUPT, DEVICE_NAME, new_kcs); if (rv) { printk(KERN_WARNING "ipmi_kcs: %s unable to claim interrupt %d," " running polled\n", DEVICE_NAME, irq); irq = 0; } } new_kcs->irq = irq; INIT_LIST_HEAD(&(new_kcs->xmit_msgs)); INIT_LIST_HEAD(&(new_kcs->hp_xmit_msgs)); new_kcs->curr_msg = NULL; atomic_set(&new_kcs->req_events, 0); new_kcs->run_to_completion = 0; start_clear_flags(new_kcs); if (irq) { new_kcs->kcs_state = KCS_CLEARING_FLAGS_THEN_SET_IRQ; printk(KERN_INFO "ipmi_kcs: Acquiring BMC @ port=0x%x irq=%d\n", kcs_port, irq); } else { if (kcs_port) printk(KERN_INFO "ipmi_kcs: Acquiring BMC @ port=0x%x\n", kcs_port); else printk(KERN_INFO "ipmi_kcs: Acquiring BMC @ addr=0x%lx\n", kcs_physaddr); } rv = ipmi_register_smi(&handlers, new_kcs, ipmi_version_major, ipmi_version_minor, &(new_kcs->intf)); if (rv) { free_irq(irq, new_kcs); printk(KERN_ERR "ipmi_kcs: Unable to register device: error %d\n", rv); goto out_err; } new_kcs->interrupt_disabled = 0; new_kcs->timer_stopped = 0; new_kcs->stop_operation = 0; init_timer(&(new_kcs->kcs_timer)); new_kcs->kcs_timer.data = (long) new_kcs; new_kcs->kcs_timer.function = kcs_timeout; new_kcs->last_timeout_jiffies = jiffies; new_kcs->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES; add_timer(&(new_kcs->kcs_timer)); *kcs = new_kcs; return 0; out_err: if (kcs_port) release_region (kcs_port, 2); if (new_kcs->addr) iounmap(new_kcs->addr); if (kcs_physaddr) release_mem_region(kcs_physaddr, 2); if (new_kcs->kcs_sm) kfree(new_kcs->kcs_sm); kfree(new_kcs); return rv; }
static int ipmi_powernv_probe(struct platform_device *pdev) { struct ipmi_smi_powernv *ipmi; struct device *dev; u32 prop; int rc; if (!pdev || !pdev->dev.of_node) return -ENODEV; dev = &pdev->dev; ipmi = devm_kzalloc(dev, sizeof(*ipmi), GFP_KERNEL); if (!ipmi) return -ENOMEM; spin_lock_init(&ipmi->msg_lock); rc = of_property_read_u32(dev->of_node, "ibm,ipmi-interface-id", &prop); if (rc) { dev_warn(dev, "No interface ID property\n"); goto err_free; } ipmi->interface_id = prop; rc = of_property_read_u32(dev->of_node, "interrupts", &prop); if (rc) { dev_warn(dev, "No interrupts property\n"); goto err_free; } ipmi->event = 1ull << prop; ipmi->event_nb.notifier_call = ipmi_opal_event; rc = opal_notifier_register(&ipmi->event_nb); if (rc) { dev_warn(dev, "OPAL notifier registration failed (%d)\n", rc); goto err_free; } ipmi->opal_msg = devm_kmalloc(dev, sizeof(*ipmi->opal_msg) + IPMI_MAX_MSG_LENGTH, GFP_KERNEL); if (!ipmi->opal_msg) { rc = -ENOMEM; goto err_unregister; } /* todo: query actual ipmi_device_id */ rc = ipmi_register_smi(&ipmi_powernv_smi_handlers, ipmi, &ipmi->ipmi_id, dev, 0); if (rc) { dev_warn(dev, "IPMI SMI registration failed (%d)\n", rc); goto err_free_msg; } dev_set_drvdata(dev, ipmi); return 0; err_free_msg: devm_kfree(dev, ipmi->opal_msg); err_unregister: opal_notifier_unregister(&ipmi->event_nb); err_free: devm_kfree(dev, ipmi); return rc; }
static int ipmi_powernv_probe(struct platform_device *pdev) { struct ipmi_smi_powernv *ipmi; struct device *dev; u32 prop; int rc; if (!pdev || !pdev->dev.of_node) return -ENODEV; dev = &pdev->dev; ipmi = devm_kzalloc(dev, sizeof(*ipmi), GFP_KERNEL); if (!ipmi) return -ENOMEM; spin_lock_init(&ipmi->msg_lock); rc = of_property_read_u32(dev->of_node, "ibm,ipmi-interface-id", &prop); if (rc) { dev_warn(dev, "No interface ID property\n"); goto err_free; } ipmi->interface_id = prop; rc = of_property_read_u32(dev->of_node, "interrupts", &prop); if (rc) { dev_warn(dev, "No interrupts property\n"); goto err_free; } ipmi->irq = irq_of_parse_and_map(dev->of_node, 0); if (!ipmi->irq) { dev_info(dev, "Unable to map irq from device tree\n"); ipmi->irq = opal_event_request(prop); } if (request_irq(ipmi->irq, ipmi_opal_event, IRQ_TYPE_LEVEL_HIGH, "opal-ipmi", ipmi)) { dev_warn(dev, "Unable to request irq\n"); goto err_dispose; } ipmi->opal_msg = devm_kmalloc(dev, sizeof(*ipmi->opal_msg) + IPMI_MAX_MSG_LENGTH, GFP_KERNEL); if (!ipmi->opal_msg) { rc = -ENOMEM; goto err_unregister; } /* todo: query actual ipmi_device_id */ rc = ipmi_register_smi(&ipmi_powernv_smi_handlers, ipmi, &ipmi->ipmi_id, dev, 0); if (rc) { dev_warn(dev, "IPMI SMI registration failed (%d)\n", rc); goto err_free_msg; } dev_set_drvdata(dev, ipmi); return 0; err_free_msg: devm_kfree(dev, ipmi->opal_msg); err_unregister: free_irq(ipmi->irq, ipmi); err_dispose: irq_dispose_mapping(ipmi->irq); err_free: devm_kfree(dev, ipmi); return rc; }