Commit a2cb600f authored by Corey Minyard's avatar Corey Minyard
Browse files

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: default avatarCorey Minyard <cminyard@mvista.com>
parent 7e030d6d
Loading
Loading
Loading
Loading
+45 −23
Original line number Original line Diff line number Diff line
@@ -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);
	sysfs_remove_link(&bmc->pdev.dev.kobj, intf->my_dev_name);
	kfree(intf->my_dev_name);
	kfree(intf->my_dev_name);
	intf->my_dev_name = NULL;
	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);
			/*
			goto out_list_del;
			 * Don't go to out_err, you can only do that if
			 * the device is registered already.
			 */
			return rv;
		}
		}


		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:
out:
	ipmi_bmc_unregister(intf);
	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;