summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2017-09-01 14:37:07 -0500
committerCorey Minyard <cminyard@mvista.com>2017-09-27 16:03:45 -0500
commita2cb600fa22a877df48e1a9372ac5f02680c1ee3 (patch)
tree205322e64001d3806ebcc046dbdfe6430d59dd6f /drivers/char
parent7e030d6dff713250c7dcfb543cad2addaf479b0e (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.c68
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;