diff options
author | Mike Isely <isely@pobox.com> | 2008-04-07 01:22:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:48 -0400 |
commit | e5be15c63804e05b5a94197524023702a259e308 (patch) | |
tree | 4223cab8016088a06d0423e1e41eacb646867c46 /drivers/media/video/pvrusb2/pvrusb2-main.c | |
parent | d913d6303072ca194919d851e6743ad8c3a7563d (diff) |
V4L/DVB (7711): pvrusb2: Fix race on module unload
The pvrusb2 driver - for basically forever - was not enforcing a
proper module tear-down. Kernel threads are used inside the driver
and all must be gone before the module can be safely removed. This
changeset reimplements a chunk of pvrusb2-context.c to enforce this
correctly. Unfortunately this is not a simple fix. The new
implementation also cuts back on kernel thread usage; instead of there
being 1 control thread per instance now it's just 1 control thread
shared by all instances. (By dropping to a single thread then the
module exit function can block on its shutdown and the thread itself
can monitor and cleanly shut down all of the other instances first.)
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-main.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-main.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 54d9f168d7ad..332aced8a5a1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c | |||
@@ -125,6 +125,12 @@ static int __init pvr_init(void) | |||
125 | 125 | ||
126 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init"); | 126 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init"); |
127 | 127 | ||
128 | ret = pvr2_context_global_init(); | ||
129 | if (ret != 0) { | ||
130 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
128 | #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS | 134 | #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS |
129 | class_ptr = pvr2_sysfs_class_create(); | 135 | class_ptr = pvr2_sysfs_class_create(); |
130 | #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ | 136 | #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ |
@@ -136,6 +142,8 @@ static int __init pvr_init(void) | |||
136 | if (pvrusb2_debug) info("Debug mask is %d (0x%x)", | 142 | if (pvrusb2_debug) info("Debug mask is %d (0x%x)", |
137 | pvrusb2_debug,pvrusb2_debug); | 143 | pvrusb2_debug,pvrusb2_debug); |
138 | 144 | ||
145 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); | ||
146 | |||
139 | return ret; | 147 | return ret; |
140 | } | 148 | } |
141 | 149 | ||
@@ -148,6 +156,10 @@ static void __exit pvr_exit(void) | |||
148 | #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS | 156 | #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS |
149 | pvr2_sysfs_class_destroy(class_ptr); | 157 | pvr2_sysfs_class_destroy(class_ptr); |
150 | #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ | 158 | #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ |
159 | |||
160 | pvr2_context_global_done(); | ||
161 | |||
162 | pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete"); | ||
151 | } | 163 | } |
152 | 164 | ||
153 | module_init(pvr_init); | 165 | module_init(pvr_init); |