Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7f3ea72 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Linus Torvalds
Browse files

[PATCH] dcdbas: convert to the new platform device interface



Do not use platform_device_register_simple() as it is going away, define
dcdbas_driver and implement ->probe() and ->remove() functions so manual
binding and unbinding will work with this driver.

Also switch to using attribute_group when creating sysfs attributes and
make sure to check and handle errors; explicitely remove attributes when
detaching driver.

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d0497614
Loading
Loading
Loading
Loading
+88 −22
Original line number Diff line number Diff line
@@ -530,30 +530,27 @@ static DCDBAS_DEV_ATTR_RW(host_control_action);
static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);

static struct device_attribute *dcdbas_dev_attrs[] = {
	&dev_attr_smi_data_buf_size,
	&dev_attr_smi_data_buf_phys_addr,
	&dev_attr_smi_request,
	&dev_attr_host_control_action,
	&dev_attr_host_control_smi_type,
	&dev_attr_host_control_on_shutdown,
static struct attribute *dcdbas_dev_attrs[] = {
	&dev_attr_smi_data_buf_size.attr,
	&dev_attr_smi_data_buf_phys_addr.attr,
	&dev_attr_smi_request.attr,
	&dev_attr_host_control_action.attr,
	&dev_attr_host_control_smi_type.attr,
	&dev_attr_host_control_on_shutdown.attr,
	NULL
};

/**
 * dcdbas_init: initialize driver
 */
static int __init dcdbas_init(void)
static struct attribute_group dcdbas_attr_group = {
	.attrs = dcdbas_dev_attrs,
};

static int __devinit dcdbas_probe(struct platform_device *dev)
{
	int i;
	int i, error;

	host_control_action = HC_ACTION_NONE;
	host_control_smi_type = HC_SMITYPE_NONE;

	dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
	if (IS_ERR(dcdbas_pdev))
		return PTR_ERR(dcdbas_pdev);

	/*
	 * BIOS SMI calls require buffer addresses be in 32-bit address space.
	 * This is done by setting the DMA mask below.
@@ -561,21 +558,81 @@ static int __init dcdbas_init(void)
	dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
	dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;

	register_reboot_notifier(&dcdbas_reboot_nb);
	error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
	if (error)
		return error;

	for (i = 0; dcdbas_bin_attrs[i]; i++)
		sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
	for (i = 0; dcdbas_bin_attrs[i]; i++) {
		error = sysfs_create_bin_file(&dev->dev.kobj,
					      dcdbas_bin_attrs[i]);
		if (error) {
			while (--i >= 0)
				sysfs_remove_bin_file(&dev->dev.kobj,
						      dcdbas_bin_attrs[i]);
			sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
			return error;
		}
	}

	for (i = 0; dcdbas_dev_attrs[i]; i++)
		device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
	register_reboot_notifier(&dcdbas_reboot_nb);

	dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
	dev_info(&dev->dev, "%s (version %s)\n",
		 DRIVER_DESCRIPTION, DRIVER_VERSION);

	return 0;
}

static int __devexit dcdbas_remove(struct platform_device *dev)
{
	int i;

	unregister_reboot_notifier(&dcdbas_reboot_nb);
	for (i = 0; dcdbas_bin_attrs[i]; i++)
		sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]);
	sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);

	return 0;
}

static struct platform_driver dcdbas_driver = {
	.driver		= {
		.name	= DRIVER_NAME,
		.owner	= THIS_MODULE,
	},
	.probe		= dcdbas_probe,
	.remove		= __devexit_p(dcdbas_remove),
};

/**
 * dcdbas_init: initialize driver
 */
static int __init dcdbas_init(void)
{
	int error;

	error = platform_driver_register(&dcdbas_driver);
	if (error)
		return error;

	dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1);
	if (!dcdbas_pdev) {
		error = -ENOMEM;
		goto err_unregister_driver;
	}

	error = platform_device_add(dcdbas_pdev);
	if (error)
		goto err_free_device;

	return 0;

 err_free_device:
	platform_device_put(dcdbas_pdev);
 err_unregister_driver:
	platform_driver_unregister(&dcdbas_driver);
	return error;
}

/**
 * dcdbas_exit: perform driver cleanup
 */
@@ -588,6 +645,15 @@ static void __exit dcdbas_exit(void)
	unregister_reboot_notifier(&dcdbas_reboot_nb);
	smi_data_buf_free();
	platform_device_unregister(dcdbas_pdev);
	platform_driver_unregister(&dcdbas_driver);

	/*
	 * We have to free the buffer here instead of dcdbas_remove
	 * because only in module exit function we can be sure that
	 * all sysfs attributes belonging to this module have been
	 * released.
	 */
	smi_data_buf_free();
}

module_init(dcdbas_init);