[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: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
d0497614e0
commit
a7f3ea728b
1 changed files with 90 additions and 24 deletions
|
@ -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;
|
||||
|
||||
error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
register_reboot_notifier(&dcdbas_reboot_nb);
|
||||
|
||||
for (i = 0; dcdbas_bin_attrs[i]; i++)
|
||||
sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
|
||||
dcdbas_bin_attrs[i]);
|
||||
|
||||
for (i = 0; dcdbas_dev_attrs[i]; i++)
|
||||
device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue