|
@@ -404,6 +404,7 @@ struct ipmi_smi {
|
|
wait_queue_head_t waitq;
|
|
wait_queue_head_t waitq;
|
|
|
|
|
|
struct bmc_device *bmc;
|
|
struct bmc_device *bmc;
|
|
|
|
+ bool bmc_registered;
|
|
char *my_dev_name;
|
|
char *my_dev_name;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2524,17 +2525,18 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf)
|
|
{
|
|
{
|
|
struct bmc_device *bmc = intf->bmc;
|
|
struct bmc_device *bmc = intf->bmc;
|
|
|
|
|
|
|
|
+ if (!intf->bmc_registered)
|
|
|
|
+ return;
|
|
|
|
+
|
|
sysfs_remove_link(&intf->si_dev->kobj, "bmc");
|
|
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);
|
|
mutex_lock(&ipmidriver_mutex);
|
|
kref_put(&bmc->usecount, cleanup_bmc_device);
|
|
kref_put(&bmc->usecount, cleanup_bmc_device);
|
|
mutex_unlock(&ipmidriver_mutex);
|
|
mutex_unlock(&ipmidriver_mutex);
|
|
- intf->bmc = NULL;
|
|
|
|
|
|
+ intf->bmc_registered = false;
|
|
}
|
|
}
|
|
|
|
|
|
static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
|
|
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) {
|
|
if (bmc->id.device_id == orig_dev_id) {
|
|
printk(KERN_ERR PFX
|
|
printk(KERN_ERR PFX
|
|
"Out of device ids!\n");
|
|
"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);
|
|
rv = platform_device_register(&bmc->pdev);
|
|
mutex_unlock(&ipmidriver_mutex);
|
|
mutex_unlock(&ipmidriver_mutex);
|
|
if (rv) {
|
|
if (rv) {
|
|
- put_device(&bmc->pdev.dev);
|
|
|
|
printk(KERN_ERR
|
|
printk(KERN_ERR
|
|
"ipmi_msghandler:"
|
|
"ipmi_msghandler:"
|
|
" Unable to register bmc device: %d\n",
|
|
" Unable to register bmc device: %d\n",
|
|
rv);
|
|
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, "
|
|
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
|
|
printk(KERN_ERR
|
|
"ipmi_msghandler: Unable to create bmc symlink: %d\n",
|
|
"ipmi_msghandler: Unable to create bmc symlink: %d\n",
|
|
rv);
|
|
rv);
|
|
- goto out_err;
|
|
|
|
|
|
+ goto out_put_bmc;
|
|
}
|
|
}
|
|
|
|
|
|
intf->my_dev_name = kasprintf(GFP_KERNEL, "ipmi%d", ifnum);
|
|
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
|
|
printk(KERN_ERR
|
|
"ipmi_msghandler: allocate link from BMC: %d\n",
|
|
"ipmi_msghandler: allocate link from BMC: %d\n",
|
|
rv);
|
|
rv);
|
|
- goto out_err;
|
|
|
|
|
|
+ goto out_unlink1;
|
|
}
|
|
}
|
|
|
|
|
|
rv = sysfs_create_link(&bmc->pdev.dev.kobj, &intf->si_dev->kobj,
|
|
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:"
|
|
"ipmi_msghandler:"
|
|
" Unable to create symlink to bmc: %d\n",
|
|
" Unable to create symlink to bmc: %d\n",
|
|
rv);
|
|
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;
|
|
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
|
|
static int
|
|
@@ -2959,6 +2979,10 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
|
|
|
|
|
|
get_guid(intf);
|
|
get_guid(intf);
|
|
|
|
|
|
|
|
+ rv = ipmi_bmc_register(intf, i);
|
|
|
|
+ if (rv)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
if ((intf->ipmi_version_major > 1)
|
|
if ((intf->ipmi_version_major > 1)
|
|
|| ((intf->ipmi_version_major == 1)
|
|
|| ((intf->ipmi_version_major == 1)
|
|
&& (intf->ipmi_version_minor >= 5))) {
|
|
&& (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;
|
|
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:
|
|
out:
|
|
if (rv) {
|
|
if (rv) {
|
|
|
|
+ ipmi_bmc_unregister(intf);
|
|
if (intf->proc_dir)
|
|
if (intf->proc_dir)
|
|
remove_proc_entries(intf);
|
|
remove_proc_entries(intf);
|
|
intf->handlers = NULL;
|
|
intf->handlers = NULL;
|