summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2013-11-04 18:19:52 +0100
committerStefan Agner <stefan.agner@toradex.com>2013-11-05 12:37:49 +0100
commite6423e1597ac838c720d5b9ae64c61506d1d4a5b (patch)
tree1d67835af9852947a1a211a00ae0122e689bd14d
parent87af4ef6e63b55de3c34cd20e9ebb54b0e0ded05 (diff)
mvf_adc: Destroy device on remove
When compiled as a module, the driver removes the device entries correctly when the module exits.
-rw-r--r--drivers/misc/mvf_adc.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/misc/mvf_adc.c b/drivers/misc/mvf_adc.c
index 53f99b3c93cb..2c904f57baa8 100644
--- a/drivers/misc/mvf_adc.c
+++ b/drivers/misc/mvf_adc.c
@@ -52,12 +52,12 @@ static DECLARE_COMPLETION(adc_tsi);
struct adc_device {
struct platform_device *pdev;
- struct platform_device *owner;
struct clk *clk;
struct adc_client *cur;
void __iomem *regs;
spinlock_t lock;
+ struct device *dev;
struct cdev cdev;
int irq;
@@ -687,9 +687,9 @@ static int __devinit adc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct adc_device *adc;
struct resource *regs;
+ dev_t devt;
int ret;
-
adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
if (adc == NULL) {
dev_err(dev, "failed to allocate adc_device\n");
@@ -734,30 +734,37 @@ static int __devinit adc_probe(struct platform_device *pdev)
goto err_clk;
}
+ /* clk enable */
+ clk_enable(adc->clk);
+ /* Save device structure by Platform device ID for touch */
+ adc_devices[pdev->id] = adc;
+
+ /* Create character device for ADC */
cdev_init(&adc->cdev, &adc_fops);
adc->cdev.owner = THIS_MODULE;
- ret = cdev_add(&adc->cdev, MKDEV(mvf_adc_major, pdev->id), 1);
+ devt = MKDEV(mvf_adc_major, pdev->id);
+ ret = cdev_add(&adc->cdev, devt, 1);
if (ret < 0)
- return ret;
+ goto err_clk;
- if (IS_ERR(device_create(adc_class, &pdev->dev,
- MKDEV(mvf_adc_major, pdev->id),
- NULL, "mvf-adc.%d", pdev->id)))
+ adc->dev = device_create(adc_class, &pdev->dev, devt,
+ NULL, "mvf-adc.%d", pdev->id);
+ if (IS_ERR(adc->dev)) {
dev_err(dev, "failed to create device\n");
+ goto err_cdev;
+ }
- /* clk enable */
- clk_enable(adc->clk);
/* Associated structures */
platform_set_drvdata(pdev, adc);
- /* Save device structure by Platform device ID for touch */
- adc_devices[pdev->id] = adc;
-
dev_info(dev, "attached adc driver\n");
return 0;
+err_cdev:
+ cdev_del(&adc->cdev);
+
err_clk:
clk_put(adc->clk);
@@ -772,12 +779,18 @@ err_alloc:
static int __devexit adc_remove(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct adc_device *adc = platform_get_drvdata(pdev);
+ dev_info(dev, "remove adc driver\n");
+
+ device_destroy(adc_class, adc->dev->devt);
+ cdev_del(&adc->cdev);
iounmap(adc->regs);
free_irq(adc->irq, adc);
clk_disable(adc->clk);
clk_put(adc->clk);
+ adc_devices[pdev->id] = NULL;
kfree(adc);
return 0;
@@ -818,6 +831,7 @@ static int __init adc_init(void)
if (ret)
printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
+ return 0;
err_class:
class_destroy(adc_class);
err: