diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2013-11-04 18:19:52 +0100 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2013-11-05 12:37:49 +0100 |
commit | e6423e1597ac838c720d5b9ae64c61506d1d4a5b (patch) | |
tree | 1d67835af9852947a1a211a00ae0122e689bd14d | |
parent | 87af4ef6e63b55de3c34cd20e9ebb54b0e0ded05 (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.c | 38 |
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: |