diff options
author | Corey Minyard <cminyard@mvista.com> | 2017-09-01 14:37:07 -0500 |
---|---|---|
committer | Corey Minyard <cminyard@mvista.com> | 2017-09-27 16:03:45 -0500 |
commit | a2cb600fa22a877df48e1a9372ac5f02680c1ee3 (patch) | |
tree | 205322e64001d3806ebcc046dbdfe6430d59dd6f /drivers/char | |
parent | 7e030d6dff713250c7dcfb543cad2addaf479b0e (diff) |
ipmi: Rework BMC registration
There was a certain error case where the BMC wouldn't be deregistered
like it should be. Rework the BMC registration to make calling
ipmi_bmc_unregister() ok even if it's not registered and to clean up
the error handling for ipmi_bmc_register().
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 42532f296e93..1517f14ee903 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -404,6 +404,7 @@ struct ipmi_smi { wait_queue_head_t waitq; struct bmc_device *bmc; + bool bmc_registered; char *my_dev_name; /* @@ -2524,17 +2525,18 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) { struct bmc_device *bmc = intf->bmc; + if (!intf->bmc_registered) + return; + sysfs_remove_link(&intf->si_dev->kobj, "bmc"); - if (intf->my_dev_name) { - sysfs_remove_link(&bmc->pdev.dev.kobj, intf->my_dev_name); - kfree(intf->my_dev_name); - intf->my_dev_name = NULL; - } + sysfs_remove_link(&bmc->pdev.dev.kobj, intf->my_dev_name); + kfree(intf->my_dev_name); + intf->my_dev_name = NULL; mutex_lock(&ipmidriver_mutex); kref_put(&bmc->usecount, cleanup_bmc_device); mutex_unlock(&ipmidriver_mutex); - intf->bmc = NULL; + intf->bmc_registered = false; } static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) @@ -2600,7 +2602,9 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) if (bmc->id.device_id == orig_dev_id) { printk(KERN_ERR PFX "Out of device ids!\n"); - break; + mutex_unlock(&ipmidriver_mutex); + rv = -EAGAIN; + goto out; } } @@ -2613,16 +2617,11 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) rv = platform_device_register(&bmc->pdev); mutex_unlock(&ipmidriver_mutex); if (rv) { - put_device(&bmc->pdev.dev); printk(KERN_ERR "ipmi_msghandler:" " Unable to register bmc device: %d\n", rv); - /* - * Don't go to out_err, you can only do that if - * the device is registered already. - */ - return rv; + goto out_list_del; } dev_info(intf->si_dev, "Found new BMC (man_id: 0x%6.6x, " @@ -2641,7 +2640,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) printk(KERN_ERR "ipmi_msghandler: Unable to create bmc symlink: %d\n", rv); - goto out_err; + goto out_put_bmc; } intf->my_dev_name = kasprintf(GFP_KERNEL, "ipmi%d", ifnum); @@ -2650,7 +2649,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) printk(KERN_ERR "ipmi_msghandler: allocate link from BMC: %d\n", rv); - goto out_err; + goto out_unlink1; } rv = sysfs_create_link(&bmc->pdev.dev.kobj, &intf->si_dev->kobj, @@ -2662,14 +2661,35 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) "ipmi_msghandler:" " Unable to create symlink to bmc: %d\n", rv); - goto out_err; + goto out_free_my_dev_name; } - return 0; + intf->bmc_registered = true; -out_err: - ipmi_bmc_unregister(intf); +out: return rv; + + +out_free_my_dev_name: + kfree(intf->my_dev_name); + intf->my_dev_name = NULL; + +out_unlink1: + sysfs_remove_link(&intf->si_dev->kobj, "bmc"); + +out_put_bmc: + mutex_lock(&ipmidriver_mutex); + intf->bmc = NULL; + kref_put(&bmc->usecount, cleanup_bmc_device); + mutex_unlock(&ipmidriver_mutex); + goto out; + +out_list_del: + mutex_lock(&ipmidriver_mutex); + intf->bmc = NULL; + mutex_unlock(&ipmidriver_mutex); + put_device(&bmc->pdev.dev); + goto out; } static int @@ -2959,6 +2979,10 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, get_guid(intf); + rv = ipmi_bmc_register(intf, i); + if (rv) + goto out; + if ((intf->ipmi_version_major > 1) || ((intf->ipmi_version_major == 1) && (intf->ipmi_version_minor >= 5))) { @@ -2987,13 +3011,11 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, intf->curr_channel = IPMI_MAX_CHANNELS; } - rv = ipmi_bmc_register(intf, i); - - if (rv == 0) - rv = add_proc_entries(intf, i); + rv = add_proc_entries(intf, i); out: if (rv) { + ipmi_bmc_unregister(intf); if (intf->proc_dir) remove_proc_entries(intf); intf->handlers = NULL; |