aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/media/usb/em28xx/em28xx-audio.c7
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c32
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c5
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c8
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c15
-rw-r--r--drivers/media/usb/em28xx/em28xx.h8
6 files changed, 56 insertions, 19 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 0f5b6f3e7a3f..f75c0a5494d6 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -301,6 +301,7 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
301 goto err; 301 goto err;
302 } 302 }
303 303
304 kref_get(&dev->ref);
304 dev->adev.users++; 305 dev->adev.users++;
305 mutex_unlock(&dev->lock); 306 mutex_unlock(&dev->lock);
306 307
@@ -341,6 +342,7 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
341 substream->runtime->dma_area = NULL; 342 substream->runtime->dma_area = NULL;
342 } 343 }
343 mutex_unlock(&dev->lock); 344 mutex_unlock(&dev->lock);
345 kref_put(&dev->ref, em28xx_free_device);
344 346
345 return 0; 347 return 0;
346} 348}
@@ -895,6 +897,8 @@ static int em28xx_audio_init(struct em28xx *dev)
895 897
896 em28xx_info("Binding audio extension\n"); 898 em28xx_info("Binding audio extension\n");
897 899
900 kref_get(&dev->ref);
901
898 printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " 902 printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
899 "Rechberger\n"); 903 "Rechberger\n");
900 printk(KERN_INFO 904 printk(KERN_INFO
@@ -967,7 +971,7 @@ static int em28xx_audio_fini(struct em28xx *dev)
967 if (dev == NULL) 971 if (dev == NULL)
968 return 0; 972 return 0;
969 973
970 if (dev->has_alsa_audio != 1) { 974 if (!dev->has_alsa_audio) {
971 /* This device does not support the extension (in this case 975 /* This device does not support the extension (in this case
972 the device is expecting the snd-usb-audio module or 976 the device is expecting the snd-usb-audio module or
973 doesn't have analog audio support at all) */ 977 doesn't have analog audio support at all) */
@@ -986,6 +990,7 @@ static int em28xx_audio_fini(struct em28xx *dev)
986 dev->adev.sndcard = NULL; 990 dev->adev.sndcard = NULL;
987 } 991 }
988 992
993 kref_put(&dev->ref, em28xx_free_device);
989 return 0; 994 return 0;
990} 995}
991 996
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,
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index d4986bdfbdc3..cacdca3a3412 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1043,7 +1043,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
1043 em28xx_info("Binding DVB extension\n"); 1043 em28xx_info("Binding DVB extension\n");
1044 1044
1045 dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); 1045 dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
1046
1047 if (dvb == NULL) { 1046 if (dvb == NULL) {
1048 em28xx_info("em28xx_dvb: memory allocation failed\n"); 1047 em28xx_info("em28xx_dvb: memory allocation failed\n");
1049 return -ENOMEM; 1048 return -ENOMEM;
@@ -1521,6 +1520,9 @@ static int em28xx_dvb_init(struct em28xx *dev)
1521 dvb->adapter.mfe_shared = mfe_shared; 1520 dvb->adapter.mfe_shared = mfe_shared;
1522 1521
1523 em28xx_info("DVB extension successfully initialized\n"); 1522 em28xx_info("DVB extension successfully initialized\n");
1523
1524 kref_get(&dev->ref);
1525
1524ret: 1526ret:
1525 em28xx_set_mode(dev, EM28XX_SUSPEND); 1527 em28xx_set_mode(dev, EM28XX_SUSPEND);
1526 mutex_unlock(&dev->lock); 1528 mutex_unlock(&dev->lock);
@@ -1577,6 +1579,7 @@ static int em28xx_dvb_fini(struct em28xx *dev)
1577 em28xx_unregister_dvb(dvb); 1579 em28xx_unregister_dvb(dvb);
1578 kfree(dvb); 1580 kfree(dvb);
1579 dev->dvb = NULL; 1581 dev->dvb = NULL;
1582 kref_put(&dev->ref, em28xx_free_device);
1580 } 1583 }
1581 1584
1582 return 0; 1585 return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 47a2c1dcccbf..2a9bf667f208 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -676,6 +676,8 @@ static int em28xx_ir_init(struct em28xx *dev)
676 return 0; 676 return 0;
677 } 677 }
678 678
679 kref_get(&dev->ref);
680
679 if (dev->board.buttons) 681 if (dev->board.buttons)
680 em28xx_init_buttons(dev); 682 em28xx_init_buttons(dev);
681 683
@@ -816,7 +818,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
816 818
817 /* skip detach on non attached boards */ 819 /* skip detach on non attached boards */
818 if (!ir) 820 if (!ir)
819 return 0; 821 goto ref_put;
820 822
821 if (ir->rc) 823 if (ir->rc)
822 rc_unregister_device(ir->rc); 824 rc_unregister_device(ir->rc);
@@ -824,6 +826,10 @@ static int em28xx_ir_fini(struct em28xx *dev)
824 /* done */ 826 /* done */
825 kfree(ir); 827 kfree(ir);
826 dev->ir = NULL; 828 dev->ir = NULL;
829
830ref_put:
831 kref_put(&dev->ref, em28xx_free_device);
832
827 return 0; 833 return 0;
828} 834}
829 835
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 13466c47023c..0856e5d367b6 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1837,7 +1837,6 @@ static int em28xx_v4l2_open(struct file *filp)
1837 video_device_node_name(vdev), v4l2_type_names[fh_type], 1837 video_device_node_name(vdev), v4l2_type_names[fh_type],
1838 dev->users); 1838 dev->users);
1839 1839
1840
1841 if (mutex_lock_interruptible(&dev->lock)) 1840 if (mutex_lock_interruptible(&dev->lock))
1842 return -ERESTARTSYS; 1841 return -ERESTARTSYS;
1843 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); 1842 fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
@@ -1869,6 +1868,7 @@ static int em28xx_v4l2_open(struct file *filp)
1869 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); 1868 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
1870 } 1869 }
1871 1870
1871 kref_get(&dev->ref);
1872 dev->users++; 1872 dev->users++;
1873 1873
1874 mutex_unlock(&dev->lock); 1874 mutex_unlock(&dev->lock);
@@ -1926,9 +1926,8 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
1926 dev->clk = NULL; 1926 dev->clk = NULL;
1927 } 1927 }
1928 1928
1929 if (dev->users)
1930 em28xx_warn("Device is open ! Memory deallocation is deferred on last close.\n");
1931 mutex_unlock(&dev->lock); 1929 mutex_unlock(&dev->lock);
1930 kref_put(&dev->ref, em28xx_free_device);
1932 1931
1933 return 0; 1932 return 0;
1934} 1933}
@@ -1976,11 +1975,9 @@ static int em28xx_v4l2_close(struct file *filp)
1976 mutex_lock(&dev->lock); 1975 mutex_lock(&dev->lock);
1977 1976
1978 if (dev->users == 1) { 1977 if (dev->users == 1) {
1979 /* free the remaining resources if device is disconnected */ 1978 /* No sense to try to write to the device */
1980 if (dev->disconnected) { 1979 if (dev->disconnected)
1981 kfree(dev->alt_max_pkt_size_isoc);
1982 goto exit; 1980 goto exit;
1983 }
1984 1981
1985 /* Save some power by putting tuner to sleep */ 1982 /* Save some power by putting tuner to sleep */
1986 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); 1983 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
@@ -2001,6 +1998,8 @@ static int em28xx_v4l2_close(struct file *filp)
2001exit: 1998exit:
2002 dev->users--; 1999 dev->users--;
2003 mutex_unlock(&dev->lock); 2000 mutex_unlock(&dev->lock);
2001 kref_put(&dev->ref, em28xx_free_device);
2002
2004 return 0; 2003 return 0;
2005} 2004}
2006 2005
@@ -2515,6 +2514,8 @@ static int em28xx_v4l2_init(struct em28xx *dev)
2515 2514
2516 em28xx_info("V4L2 extension successfully initialized\n"); 2515 em28xx_info("V4L2 extension successfully initialized\n");
2517 2516
2517 kref_get(&dev->ref);
2518
2518 mutex_unlock(&dev->lock); 2519 mutex_unlock(&dev->lock);
2519 return 0; 2520 return 0;
2520 2521
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 9e44f5bfc48b..2051fc9fb932 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -32,6 +32,7 @@
32#include <linux/workqueue.h> 32#include <linux/workqueue.h>
33#include <linux/i2c.h> 33#include <linux/i2c.h>
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35#include <linux/kref.h>
35#include <linux/videodev2.h> 36#include <linux/videodev2.h>
36 37
37#include <media/videobuf2-vmalloc.h> 38#include <media/videobuf2-vmalloc.h>
@@ -536,9 +537,10 @@ struct em28xx_i2c_bus {
536 enum em28xx_i2c_algo_type algo_type; 537 enum em28xx_i2c_algo_type algo_type;
537}; 538};
538 539
539
540/* main device struct */ 540/* main device struct */
541struct em28xx { 541struct em28xx {
542 struct kref ref;
543
542 /* generic device properties */ 544 /* generic device properties */
543 char name[30]; /* name (including minor) of the device */ 545 char name[30]; /* name (including minor) of the device */
544 int model; /* index in the device_data struct */ 546 int model; /* index in the device_data struct */
@@ -710,6 +712,8 @@ struct em28xx {
710 struct em28xx_dvb *dvb; 712 struct em28xx_dvb *dvb;
711}; 713};
712 714
715#define kref_to_dev(d) container_of(d, struct em28xx, ref)
716
713struct em28xx_ops { 717struct em28xx_ops {
714 struct list_head next; 718 struct list_head next;
715 char *name; 719 char *name;
@@ -771,7 +775,7 @@ extern struct em28xx_board em28xx_boards[];
771extern struct usb_device_id em28xx_id_table[]; 775extern struct usb_device_id em28xx_id_table[];
772int em28xx_tuner_callback(void *ptr, int component, int command, int arg); 776int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
773void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl); 777void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl);
774void em28xx_release_resources(struct em28xx *dev); 778void em28xx_free_device(struct kref *ref);
775 779
776/* Provided by em28xx-camera.c */ 780/* Provided by em28xx-camera.c */
777int em28xx_detect_sensor(struct em28xx *dev); 781int em28xx_detect_sensor(struct em28xx *dev);