Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2407d77a authored by Matthew Garrett's avatar Matthew Garrett Committed by Linus Torvalds
Browse files

ipmi: split device discovery and registration



The ipmi spec indicates that we should only make use of one si per bmc, so
separate device discovery and registration to make that possible.

[thenzl@redhat.com: fix mutex use]
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5fedc4a2
Loading
Loading
Loading
Loading
+84 −46
Original line number Diff line number Diff line
@@ -308,6 +308,7 @@ static int num_max_busy_us;

static int unload_when_empty = 1;

static int add_smi(struct smi_info *smi);
static int try_smi_init(struct smi_info *smi);
static void cleanup_one_si(struct smi_info *to_clean);

@@ -1785,7 +1786,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
				info->irq_setup = std_irq_setup;
			info->slave_addr = ipmb;

			try_smi_init(info);
			if (!add_smi(info))
				if (try_smi_init(info))
					cleanup_one_si(info);
		} else {
			/* remove */
			struct smi_info *e, *tmp_e;
@@ -1871,7 +1874,9 @@ static __devinit void hardcode_find_bmc(void)
			info->irq_setup = std_irq_setup;
		info->slave_addr = slave_addrs[i];

		try_smi_init(info);
		if (!add_smi(info))
			if (try_smi_init(info))
				cleanup_one_si(info);
	}
}

@@ -2069,7 +2074,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
	}
	info->io.addr_data = spmi->addr.address;

	try_smi_init(info);
	add_smi(info);

	return 0;
}
@@ -2167,7 +2172,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
	info->dev = &acpi_dev->dev;
	pnp_set_drvdata(dev, info);

	return try_smi_init(info);
	return add_smi(info);

err_free:
	kfree(info);
@@ -2326,7 +2331,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
	if (info->irq)
		info->irq_setup = std_irq_setup;

	try_smi_init(info);
	add_smi(info);
}

static void __devinit dmi_find_bmc(void)
@@ -2429,7 +2434,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
	info->dev = &pdev->dev;
	pci_set_drvdata(pdev, info);

	return try_smi_init(info);
	return add_smi(info);
}

static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
@@ -2542,7 +2547,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,

	dev_set_drvdata(&dev->dev, info);

	return try_smi_init(info);
	return add_smi(info);
}

static int __devexit ipmi_of_remove(struct of_device *dev)
@@ -2971,14 +2976,16 @@ static __devinit void default_find_bmc(void)
		info->io.regsize = DEFAULT_REGSPACING;
		info->io.regshift = 0;

		if (try_smi_init(info) == 0) {
		if (add_smi(info) == 0) {
			if ((try_smi_init(info)) == 0) {
				/* Found one... */
			printk(KERN_INFO "ipmi_si: Found default %s state"
			       " machine at %s address 0x%lx\n",
				printk(KERN_INFO "ipmi_si: Found default %s"
				" state machine at %s address 0x%lx\n",
				si_to_str[info->si_type],
				addr_space_to_str[info->io.addr_type],
				info->io.addr_data);
			return;
			} else
				cleanup_one_si(info);
		}
	}
}
@@ -2997,32 +3004,48 @@ static int is_new_interface(struct smi_info *info)
	return 1;
}

static int try_smi_init(struct smi_info *new_smi)
static int add_smi(struct smi_info *new_smi)
{
	int rv;
	int i;
	int rv = 0;

	printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
	       " machine at %s address 0x%lx, slave address 0x%x,"
	       " irq %d\n",
	printk(KERN_INFO "ipmi_si: Adding %s-specified %s state machine",
			ipmi_addr_src_to_str[new_smi->addr_source],
	       si_to_str[new_smi->si_type],
	       addr_space_to_str[new_smi->io.addr_type],
	       new_smi->io.addr_data,
	       new_smi->slave_addr, new_smi->irq);

			si_to_str[new_smi->si_type]);
	mutex_lock(&smi_infos_lock);
	if (!is_new_interface(new_smi)) {
		printk(KERN_WARNING "ipmi_si: duplicate interface\n");
		printk(KERN_CONT ": duplicate interface\n");
		rv = -EBUSY;
		goto out_err;
	}

	printk(KERN_CONT "\n");

	/* So we know not to free it unless we have allocated one. */
	new_smi->intf = NULL;
	new_smi->si_sm = NULL;
	new_smi->handlers = NULL;

	list_add_tail(&new_smi->link, &smi_infos);

out_err:
	mutex_unlock(&smi_infos_lock);
	return rv;
}

static int try_smi_init(struct smi_info *new_smi)
{
	int rv = 0;
	int i;

	printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
	       " machine at %s address 0x%lx, slave address 0x%x,"
	       " irq %d\n",
	       ipmi_addr_src_to_str[new_smi->addr_source],
	       si_to_str[new_smi->si_type],
	       addr_space_to_str[new_smi->io.addr_type],
	       new_smi->io.addr_data,
	       new_smi->slave_addr, new_smi->irq);

	switch (new_smi->si_type) {
	case SI_KCS:
		new_smi->handlers = &kcs_smi_handlers;
@@ -3183,10 +3206,6 @@ static int try_smi_init(struct smi_info *new_smi)
		goto out_err_stop_timer;
	}

	list_add_tail(&new_smi->link, &smi_infos);

	mutex_unlock(&smi_infos_lock);

	printk(KERN_INFO "IPMI %s interface initialized\n",
	       si_to_str[new_smi->si_type]);

@@ -3197,11 +3216,17 @@ static int try_smi_init(struct smi_info *new_smi)
	wait_for_timer_and_thread(new_smi);

 out_err:
	if (new_smi->intf)
	new_smi->interrupt_disabled = 1;

	if (new_smi->intf) {
		ipmi_unregister_smi(new_smi->intf);
		new_smi->intf = NULL;
	}

	if (new_smi->irq_cleanup)
	if (new_smi->irq_cleanup) {
		new_smi->irq_cleanup(new_smi);
		new_smi->irq_cleanup = NULL;
	}

	/*
	 * Wait until we know that we are out of any interrupt
@@ -3214,18 +3239,21 @@ static int try_smi_init(struct smi_info *new_smi)
		if (new_smi->handlers)
			new_smi->handlers->cleanup(new_smi->si_sm);
		kfree(new_smi->si_sm);
		new_smi->si_sm = NULL;
	}
	if (new_smi->addr_source_cleanup)
	if (new_smi->addr_source_cleanup) {
		new_smi->addr_source_cleanup(new_smi);
	if (new_smi->io_cleanup)
		new_smi->addr_source_cleanup = NULL;
	}
	if (new_smi->io_cleanup) {
		new_smi->io_cleanup(new_smi);
		new_smi->io_cleanup = NULL;
	}

	if (new_smi->dev_registered)
	if (new_smi->dev_registered) {
		platform_device_unregister(new_smi->pdev);

	kfree(new_smi);

	mutex_unlock(&smi_infos_lock);
		new_smi->dev_registered = 0;
	}

	return rv;
}
@@ -3235,6 +3263,7 @@ static __devinit int init_ipmi_si(void)
	int  i;
	char *str;
	int  rv;
	struct smi_info *e;

	if (initialized)
		return 0;
@@ -3292,16 +3321,22 @@ static __devinit int init_ipmi_si(void)
	of_register_platform_driver(&ipmi_of_platform_driver);
#endif

	mutex_lock(&smi_infos_lock);
	list_for_each_entry(e, &smi_infos, link) {
		if (!e->si_sm)
			try_smi_init(e);
	}
	mutex_unlock(&smi_infos_lock);

	if (si_trydefaults) {
		mutex_lock(&smi_infos_lock);
		if (list_empty(&smi_infos)) {
			/* No BMC was found, try defaults. */
			mutex_unlock(&smi_infos_lock);
			default_find_bmc();
		} else {
		} else
			mutex_unlock(&smi_infos_lock);
	}
	}

	mutex_lock(&smi_infos_lock);
	if (unload_when_empty && list_empty(&smi_infos)) {
@@ -3326,7 +3361,7 @@ module_init(init_ipmi_si);

static void cleanup_one_si(struct smi_info *to_clean)
{
	int           rv;
	int           rv = 0;
	unsigned long flags;

	if (!to_clean)
@@ -3370,13 +3405,16 @@ static void cleanup_one_si(struct smi_info *to_clean)
		schedule_timeout_uninterruptible(1);
	}

	if (to_clean->intf)
		rv = ipmi_unregister_smi(to_clean->intf);

	if (rv) {
		printk(KERN_ERR
		       "ipmi_si: Unable to unregister device: errno=%d\n",
		       rv);
	}

	if (to_clean->handlers)
		to_clean->handlers->cleanup(to_clean->si_sm);

	kfree(to_clean->si_sm);