diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-03-05 09:21:07 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-03-11 05:56:46 -0400 |
commit | 47677e51e2a4040c204d7971a5103592600185b1 (patch) | |
tree | 58196e42f5ad37ee12333a69593d444f0d1e10de /drivers/media/usb/em28xx/em28xx-cards.c | |
parent | 88e4fcda55e07278fcf5f6eea684685ffc0633e2 (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.c | 32 |
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 | */ |
2942 | void em28xx_release_resources(struct em28xx *dev) | 2942 | static 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 | }; |
2959 | EXPORT_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 | */ | ||
2967 | void 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 | } | ||
2979 | EXPORT_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 | ||
3463 | static int em28xx_usb_suspend(struct usb_interface *interface, | 3481 | static int em28xx_usb_suspend(struct usb_interface *interface, |