diff options
author | Chris Rankin <rankincj@yahoo.com> | 2011-09-24 10:02:32 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-24 11:12:48 -0400 |
commit | d7222e7d6fb06ca3e7aa7a1ab07f8e6c6adb1d22 (patch) | |
tree | 733646ed67e9d39e4cdec59f4ed1ee08d46fc63a /drivers/media/video/em28xx/em28xx-core.c | |
parent | bd829e9d1d7de3178d67d94043f43527213a63a0 (diff) |
[media] em28xx: fix race on disconnect
This patch closes the race on the device and extension lists at USB disconnect
time. Previously, the device was removed from the device list during
em28xx_release_resources(), and then passed to the em28xx_close_extension()
function so that all extensions could run their fini() operations. However, this
left a (brief, theoretical, highly unlikely ;-)) window between these two calls
during which a new module could call em28xx_register_extension(). The result
would have been that the em28xx_usb_disconnect() function would also have passed
the device to the new extension's fini() function, despite never having called
the extension's init() function.
This patch also restores em28xx_close_extension()'s symmetry with
em28xx_init_extension(), and establishes the property that every device in the
device list must have been initialised for every extension in the extension list.
Signed-off-by: Chris Rankin <rankincj@yahoo.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-core.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 23 |
1 files changed, 5 insertions, 18 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index bd481ab65f29..804a4ab47ac6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -1184,18 +1184,6 @@ static LIST_HEAD(em28xx_devlist); | |||
1184 | static DEFINE_MUTEX(em28xx_devlist_mutex); | 1184 | static DEFINE_MUTEX(em28xx_devlist_mutex); |
1185 | 1185 | ||
1186 | /* | 1186 | /* |
1187 | * em28xx_realease_resources() | ||
1188 | * unregisters the v4l2,i2c and usb devices | ||
1189 | * called when the device gets disconected or at module unload | ||
1190 | */ | ||
1191 | void em28xx_remove_from_devlist(struct em28xx *dev) | ||
1192 | { | ||
1193 | mutex_lock(&em28xx_devlist_mutex); | ||
1194 | list_del(&dev->devlist); | ||
1195 | mutex_unlock(&em28xx_devlist_mutex); | ||
1196 | }; | ||
1197 | |||
1198 | /* | ||
1199 | * Extension interface | 1187 | * Extension interface |
1200 | */ | 1188 | */ |
1201 | 1189 | ||
@@ -1245,14 +1233,13 @@ void em28xx_init_extension(struct em28xx *dev) | |||
1245 | 1233 | ||
1246 | void em28xx_close_extension(struct em28xx *dev) | 1234 | void em28xx_close_extension(struct em28xx *dev) |
1247 | { | 1235 | { |
1248 | struct em28xx_ops *ops = NULL; | 1236 | const struct em28xx_ops *ops = NULL; |
1249 | 1237 | ||
1250 | mutex_lock(&em28xx_devlist_mutex); | 1238 | mutex_lock(&em28xx_devlist_mutex); |
1251 | if (!list_empty(&em28xx_extension_devlist)) { | 1239 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { |
1252 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { | 1240 | if (ops->fini) |
1253 | if (ops->fini) | 1241 | ops->fini(dev); |
1254 | ops->fini(dev); | ||
1255 | } | ||
1256 | } | 1242 | } |
1243 | list_del(&dev->devlist); | ||
1257 | mutex_unlock(&em28xx_devlist_mutex); | 1244 | mutex_unlock(&em28xx_devlist_mutex); |
1258 | } | 1245 | } |