Skip to content

Commit

Permalink
ipmi: split device discovery and registration
Browse files Browse the repository at this point in the history
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: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Signed-off-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Matthew Garrett authored and Linus Torvalds committed May 27, 2010
1 parent 5fedc4a commit 2407d77
Showing 1 changed file with 84 additions and 46 deletions.
130 changes: 84 additions & 46 deletions drivers/char/ipmi/ipmi_si_intf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
/* Found one... */
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;
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",
si_to_str[info->si_type],
addr_space_to_str[info->io.addr_type],
info->io.addr_data);
} else
cleanup_one_si(info);
}
}
}
Expand All @@ -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;

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);
int rv = 0;

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]);
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;
Expand Down Expand Up @@ -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]);

Expand All @@ -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
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -3292,15 +3321,21 @@ 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);
Expand All @@ -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)
Expand Down Expand Up @@ -3370,14 +3405,17 @@ static void cleanup_one_si(struct smi_info *to_clean)
schedule_timeout_uninterruptible(1);
}

rv = ipmi_unregister_smi(to_clean->intf);
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);
}

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

kfree(to_clean->si_sm);

Expand Down

0 comments on commit 2407d77

Please sign in to comment.