Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}