aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx/em28xx-cards.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-05 09:21:07 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-11 05:56:46 -0400
commit47677e51e2a4040c204d7971a5103592600185b1 (patch)
tree58196e42f5ad37ee12333a69593d444f0d1e10de /drivers/media/usb/em28xx/em28xx-cards.c
parent88e4fcda55e07278fcf5f6eea684685ffc0633e2 (diff)
[media] em28xx: Only deallocate struct em28xx after finishing all extensions
We can't free struct em28xx while one of the extensions is still using it. So, add a kref() to control it, freeing it only after the extensions fini calls. Reviewed-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-cards.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 2fb300e882f0..e7ec3b7866f1 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2939,7 +2939,7 @@ static void flush_request_modules(struct em28xx *dev)
2939 * unregisters the v4l2,i2c and usb devices 2939 * unregisters the v4l2,i2c and usb devices
2940 * called when the device gets disconnected or at module unload 2940 * called when the device gets disconnected or at module unload
2941*/ 2941*/
2942void em28xx_release_resources(struct em28xx *dev) 2942static void em28xx_release_resources(struct em28xx *dev)
2943{ 2943{
2944 /*FIXME: I2C IR should be disconnected */ 2944 /*FIXME: I2C IR should be disconnected */
2945 2945
@@ -2956,7 +2956,27 @@ void em28xx_release_resources(struct em28xx *dev)
2956 2956
2957 mutex_unlock(&dev->lock); 2957 mutex_unlock(&dev->lock);
2958}; 2958};
2959EXPORT_SYMBOL_GPL(em28xx_release_resources); 2959
2960/**
2961 * em28xx_free_device() - Free em28xx device
2962 *
2963 * @ref: struct kref for em28xx device
2964 *
2965 * This is called when all extensions and em28xx core unregisters a device
2966 */
2967void em28xx_free_device(struct kref *ref)
2968{
2969 struct em28xx *dev = kref_to_dev(ref);
2970
2971 em28xx_info("Freeing device\n");
2972
2973 if (!dev->disconnected)
2974 em28xx_release_resources(dev);
2975
2976 kfree(dev->alt_max_pkt_size_isoc);
2977 kfree(dev);
2978}
2979EXPORT_SYMBOL_GPL(em28xx_free_device);
2960 2980
2961/* 2981/*
2962 * em28xx_init_dev() 2982 * em28xx_init_dev()
@@ -3409,6 +3429,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
3409 dev->dvb_xfer_bulk ? "bulk" : "isoc"); 3429 dev->dvb_xfer_bulk ? "bulk" : "isoc");
3410 } 3430 }
3411 3431
3432 kref_init(&dev->ref);
3433
3412 request_modules(dev); 3434 request_modules(dev);
3413 3435
3414 /* Should be the last thing to do, to avoid newer udev's to 3436 /* Should be the last thing to do, to avoid newer udev's to
@@ -3453,11 +3475,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
3453 em28xx_close_extension(dev); 3475 em28xx_close_extension(dev);
3454 3476
3455 em28xx_release_resources(dev); 3477 em28xx_release_resources(dev);
3456 3478 kref_put(&dev->ref, em28xx_free_device);
3457 if (!dev->users) {
3458 kfree(dev->alt_max_pkt_size_isoc);
3459 kfree(dev);
3460 }
3461} 3479}
3462 3480
3463static int em28xx_usb_suspend(struct usb_interface *interface, 3481static int em28xx_usb_suspend(struct usb_interface *interface,