diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-09-09 05:30:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-09-13 16:42:17 -0400 |
commit | 345321dc9c52b774f42c934339f9b3e2f0a39395 (patch) | |
tree | a86e8fde0d50634c467c0c9d75b37776037e27d7 /drivers/media | |
parent | 8c96f0a207bedb6f06089fde9adc7abe8136a087 (diff) |
[media] gspca: Don't set gspca_dev->dev to NULL before stop0
In commit a3d6e8cc0e6ddc8b3cfdeb3c979f07ed1aa528b3 gspca_dev->dev is set
to NULL on disconnect, before calling stop0. The plan was to get rid of
gspca_dev->present and instead simply check for gspca_dev->dev everywhere
where we were checking for present. This should be race free since all users
of gspca_dev->dev hold the usb_lock, or so I thought.
But I was wrong, drivers which use a work-queue + synchronous bulk transfers
to get the video data don't hold the usb_lock while doing so, their stop0
callbacks stop the workqueue, so they won't be using gspca_dev->dev anymore
after the stop0 call, but they might be dereferincing it before, so we should
not set gspca_dev->dev to NULL on disconnect before calling stop0.
This also means that the workqueue functions in these drivers cannot
use gspca_dev->dev to check if they need to stop because of disconnection,
so we will need to keep gspca_dev->present around, and set that to 0 on
disconnect, before calling stop0. Unfortunately as part of the plan to remove
gspca_dev->present, these workqueues where already moved over to checking
for gspca_dev->dev instead of gspca_dev->present as part of commit
254902b01d2acc6aced99ec17caa4c6cd890cdea, so this patch also reverts those
parts of that commit.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/usb/gspca/finepix.c | 6 | ||||
-rw-r--r-- | drivers/media/usb/gspca/gspca.c | 3 | ||||
-rw-r--r-- | drivers/media/usb/gspca/jl2005bcd.c | 6 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sq905.c | 8 | ||||
-rw-r--r-- | drivers/media/usb/gspca/sq905c.c | 6 | ||||
-rw-r--r-- | drivers/media/usb/gspca/vicam.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/gspca/xirlink_cit.c | 4 | ||||
-rw-r--r-- | drivers/media/usb/gspca/zc3xx.c | 4 |
8 files changed, 19 insertions, 22 deletions
diff --git a/drivers/media/usb/gspca/finepix.c b/drivers/media/usb/gspca/finepix.c index c8f2201cc35..04807eee777 100644 --- a/drivers/media/usb/gspca/finepix.c +++ b/drivers/media/usb/gspca/finepix.c | |||
@@ -94,7 +94,7 @@ static void dostream(struct work_struct *work) | |||
94 | 94 | ||
95 | /* loop reading a frame */ | 95 | /* loop reading a frame */ |
96 | again: | 96 | again: |
97 | while (gspca_dev->dev && gspca_dev->streaming) { | 97 | while (gspca_dev->present && gspca_dev->streaming) { |
98 | #ifdef CONFIG_PM | 98 | #ifdef CONFIG_PM |
99 | if (gspca_dev->frozen) | 99 | if (gspca_dev->frozen) |
100 | break; | 100 | break; |
@@ -110,7 +110,7 @@ again: | |||
110 | if (gspca_dev->frozen) | 110 | if (gspca_dev->frozen) |
111 | break; | 111 | break; |
112 | #endif | 112 | #endif |
113 | if (!gspca_dev->dev || !gspca_dev->streaming) | 113 | if (!gspca_dev->present || !gspca_dev->streaming) |
114 | break; | 114 | break; |
115 | 115 | ||
116 | /* the frame comes in parts */ | 116 | /* the frame comes in parts */ |
@@ -129,7 +129,7 @@ again: | |||
129 | if (gspca_dev->frozen) | 129 | if (gspca_dev->frozen) |
130 | goto out; | 130 | goto out; |
131 | #endif | 131 | #endif |
132 | if (!gspca_dev->dev || !gspca_dev->streaming) | 132 | if (!gspca_dev->present || !gspca_dev->streaming) |
133 | goto out; | 133 | goto out; |
134 | if (len < FPIX_MAX_TRANSFER || | 134 | if (len < FPIX_MAX_TRANSFER || |
135 | (data[len - 2] == 0xff && | 135 | (data[len - 2] == 0xff && |
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index d4e8343f5b1..7cce0f201d7 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c | |||
@@ -2358,8 +2358,6 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2358 | 2358 | ||
2359 | mutex_lock(&gspca_dev->usb_lock); | 2359 | mutex_lock(&gspca_dev->usb_lock); |
2360 | 2360 | ||
2361 | usb_set_intfdata(intf, NULL); | ||
2362 | gspca_dev->dev = NULL; | ||
2363 | gspca_dev->present = 0; | 2361 | gspca_dev->present = 0; |
2364 | destroy_urbs(gspca_dev); | 2362 | destroy_urbs(gspca_dev); |
2365 | 2363 | ||
@@ -2375,6 +2373,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2375 | if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming) | 2373 | if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming) |
2376 | gspca_dev->sd_desc->stop0(gspca_dev); | 2374 | gspca_dev->sd_desc->stop0(gspca_dev); |
2377 | gspca_dev->streaming = 0; | 2375 | gspca_dev->streaming = 0; |
2376 | gspca_dev->dev = NULL; | ||
2378 | wake_up_interruptible(&gspca_dev->wq); | 2377 | wake_up_interruptible(&gspca_dev->wq); |
2379 | 2378 | ||
2380 | v4l2_device_disconnect(&gspca_dev->v4l2_dev); | 2379 | v4l2_device_disconnect(&gspca_dev->v4l2_dev); |
diff --git a/drivers/media/usb/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c index 234777116e5..c4b4a9598db 100644 --- a/drivers/media/usb/gspca/jl2005bcd.c +++ b/drivers/media/usb/gspca/jl2005bcd.c | |||
@@ -335,7 +335,7 @@ static void jl2005c_dostream(struct work_struct *work) | |||
335 | goto quit_stream; | 335 | goto quit_stream; |
336 | } | 336 | } |
337 | 337 | ||
338 | while (gspca_dev->dev && gspca_dev->streaming) { | 338 | while (gspca_dev->present && gspca_dev->streaming) { |
339 | #ifdef CONFIG_PM | 339 | #ifdef CONFIG_PM |
340 | if (gspca_dev->frozen) | 340 | if (gspca_dev->frozen) |
341 | break; | 341 | break; |
@@ -371,7 +371,7 @@ static void jl2005c_dostream(struct work_struct *work) | |||
371 | buffer, act_len); | 371 | buffer, act_len); |
372 | header_read = 1; | 372 | header_read = 1; |
373 | } | 373 | } |
374 | while (bytes_left > 0 && gspca_dev->dev) { | 374 | while (bytes_left > 0 && gspca_dev->present) { |
375 | data_len = bytes_left > JL2005C_MAX_TRANSFER ? | 375 | data_len = bytes_left > JL2005C_MAX_TRANSFER ? |
376 | JL2005C_MAX_TRANSFER : bytes_left; | 376 | JL2005C_MAX_TRANSFER : bytes_left; |
377 | ret = usb_bulk_msg(gspca_dev->dev, | 377 | ret = usb_bulk_msg(gspca_dev->dev, |
@@ -394,7 +394,7 @@ static void jl2005c_dostream(struct work_struct *work) | |||
394 | } | 394 | } |
395 | } | 395 | } |
396 | quit_stream: | 396 | quit_stream: |
397 | if (gspca_dev->dev) { | 397 | if (gspca_dev->present) { |
398 | mutex_lock(&gspca_dev->usb_lock); | 398 | mutex_lock(&gspca_dev->usb_lock); |
399 | jl2005c_stop(gspca_dev); | 399 | jl2005c_stop(gspca_dev); |
400 | mutex_unlock(&gspca_dev->usb_lock); | 400 | mutex_unlock(&gspca_dev->usb_lock); |
diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c index a8ac97931ad..2e05acab304 100644 --- a/drivers/media/usb/gspca/sq905.c +++ b/drivers/media/usb/gspca/sq905.c | |||
@@ -232,7 +232,7 @@ static void sq905_dostream(struct work_struct *work) | |||
232 | frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage | 232 | frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage |
233 | + FRAME_HEADER_LEN; | 233 | + FRAME_HEADER_LEN; |
234 | 234 | ||
235 | while (gspca_dev->dev && gspca_dev->streaming) { | 235 | while (gspca_dev->present && gspca_dev->streaming) { |
236 | #ifdef CONFIG_PM | 236 | #ifdef CONFIG_PM |
237 | if (gspca_dev->frozen) | 237 | if (gspca_dev->frozen) |
238 | break; | 238 | break; |
@@ -246,7 +246,7 @@ static void sq905_dostream(struct work_struct *work) | |||
246 | we must finish reading an entire frame, otherwise the | 246 | we must finish reading an entire frame, otherwise the |
247 | next time we stream we start reading in the middle of a | 247 | next time we stream we start reading in the middle of a |
248 | frame. */ | 248 | frame. */ |
249 | while (bytes_left > 0 && gspca_dev->dev) { | 249 | while (bytes_left > 0 && gspca_dev->present) { |
250 | data_len = bytes_left > SQ905_MAX_TRANSFER ? | 250 | data_len = bytes_left > SQ905_MAX_TRANSFER ? |
251 | SQ905_MAX_TRANSFER : bytes_left; | 251 | SQ905_MAX_TRANSFER : bytes_left; |
252 | ret = sq905_read_data(gspca_dev, buffer, data_len, 1); | 252 | ret = sq905_read_data(gspca_dev, buffer, data_len, 1); |
@@ -278,7 +278,7 @@ static void sq905_dostream(struct work_struct *work) | |||
278 | gspca_frame_add(gspca_dev, LAST_PACKET, | 278 | gspca_frame_add(gspca_dev, LAST_PACKET, |
279 | NULL, 0); | 279 | NULL, 0); |
280 | } | 280 | } |
281 | if (gspca_dev->dev) { | 281 | if (gspca_dev->present) { |
282 | /* acknowledge the frame */ | 282 | /* acknowledge the frame */ |
283 | mutex_lock(&gspca_dev->usb_lock); | 283 | mutex_lock(&gspca_dev->usb_lock); |
284 | ret = sq905_ack_frame(gspca_dev); | 284 | ret = sq905_ack_frame(gspca_dev); |
@@ -288,7 +288,7 @@ static void sq905_dostream(struct work_struct *work) | |||
288 | } | 288 | } |
289 | } | 289 | } |
290 | quit_stream: | 290 | quit_stream: |
291 | if (gspca_dev->dev) { | 291 | if (gspca_dev->present) { |
292 | mutex_lock(&gspca_dev->usb_lock); | 292 | mutex_lock(&gspca_dev->usb_lock); |
293 | sq905_command(gspca_dev, SQ905_CLEAR); | 293 | sq905_command(gspca_dev, SQ905_CLEAR); |
294 | mutex_unlock(&gspca_dev->usb_lock); | 294 | mutex_unlock(&gspca_dev->usb_lock); |
diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c index 70fae6982e9..784620c102b 100644 --- a/drivers/media/usb/gspca/sq905c.c +++ b/drivers/media/usb/gspca/sq905c.c | |||
@@ -150,7 +150,7 @@ static void sq905c_dostream(struct work_struct *work) | |||
150 | goto quit_stream; | 150 | goto quit_stream; |
151 | } | 151 | } |
152 | 152 | ||
153 | while (gspca_dev->dev && gspca_dev->streaming) { | 153 | while (gspca_dev->present && gspca_dev->streaming) { |
154 | #ifdef CONFIG_PM | 154 | #ifdef CONFIG_PM |
155 | if (gspca_dev->frozen) | 155 | if (gspca_dev->frozen) |
156 | break; | 156 | break; |
@@ -173,7 +173,7 @@ static void sq905c_dostream(struct work_struct *work) | |||
173 | packet_type = FIRST_PACKET; | 173 | packet_type = FIRST_PACKET; |
174 | gspca_frame_add(gspca_dev, packet_type, | 174 | gspca_frame_add(gspca_dev, packet_type, |
175 | buffer, FRAME_HEADER_LEN); | 175 | buffer, FRAME_HEADER_LEN); |
176 | while (bytes_left > 0 && gspca_dev->dev) { | 176 | while (bytes_left > 0 && gspca_dev->present) { |
177 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? | 177 | data_len = bytes_left > SQ905C_MAX_TRANSFER ? |
178 | SQ905C_MAX_TRANSFER : bytes_left; | 178 | SQ905C_MAX_TRANSFER : bytes_left; |
179 | ret = usb_bulk_msg(gspca_dev->dev, | 179 | ret = usb_bulk_msg(gspca_dev->dev, |
@@ -195,7 +195,7 @@ static void sq905c_dostream(struct work_struct *work) | |||
195 | } | 195 | } |
196 | } | 196 | } |
197 | quit_stream: | 197 | quit_stream: |
198 | if (gspca_dev->dev) { | 198 | if (gspca_dev->present) { |
199 | mutex_lock(&gspca_dev->usb_lock); | 199 | mutex_lock(&gspca_dev->usb_lock); |
200 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); | 200 | sq905c_command(gspca_dev, SQ905C_CLEAR, 0); |
201 | mutex_unlock(&gspca_dev->usb_lock); | 201 | mutex_unlock(&gspca_dev->usb_lock); |
diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c index b1a64b91266..57d88f70c39 100644 --- a/drivers/media/usb/gspca/vicam.c +++ b/drivers/media/usb/gspca/vicam.c | |||
@@ -194,7 +194,7 @@ static void vicam_dostream(struct work_struct *work) | |||
194 | goto exit; | 194 | goto exit; |
195 | } | 195 | } |
196 | 196 | ||
197 | while (gspca_dev->dev && gspca_dev->streaming) { | 197 | while (gspca_dev->present && gspca_dev->streaming) { |
198 | #ifdef CONFIG_PM | 198 | #ifdef CONFIG_PM |
199 | if (gspca_dev->frozen) | 199 | if (gspca_dev->frozen) |
200 | break; | 200 | break; |
@@ -299,7 +299,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
299 | dev->work_thread = NULL; | 299 | dev->work_thread = NULL; |
300 | mutex_lock(&gspca_dev->usb_lock); | 300 | mutex_lock(&gspca_dev->usb_lock); |
301 | 301 | ||
302 | if (gspca_dev->dev) | 302 | if (gspca_dev->present) |
303 | vicam_set_camera_power(gspca_dev, 0); | 303 | vicam_set_camera_power(gspca_dev, 0); |
304 | } | 304 | } |
305 | 305 | ||
diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c index 13b8d395d21..d4b23c9bf90 100644 --- a/drivers/media/usb/gspca/xirlink_cit.c +++ b/drivers/media/usb/gspca/xirlink_cit.c | |||
@@ -2697,9 +2697,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2697 | { | 2697 | { |
2698 | struct sd *sd = (struct sd *) gspca_dev; | 2698 | struct sd *sd = (struct sd *) gspca_dev; |
2699 | 2699 | ||
2700 | /* We cannot use gspca_dev->present here as that is not set when | 2700 | if (!gspca_dev->present) |
2701 | sd_init gets called and we get called from sd_init */ | ||
2702 | if (!gspca_dev->dev) | ||
2703 | return; | 2701 | return; |
2704 | 2702 | ||
2705 | switch (sd->model) { | 2703 | switch (sd->model) { |
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index f0bacee33ef..234d9eaa8ee 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c | |||
@@ -5950,7 +5950,7 @@ static void transfer_update(struct work_struct *work) | |||
5950 | if (gspca_dev->frozen) | 5950 | if (gspca_dev->frozen) |
5951 | goto err; | 5951 | goto err; |
5952 | #endif | 5952 | #endif |
5953 | if (!gspca_dev->dev || !gspca_dev->streaming) | 5953 | if (!gspca_dev->present || !gspca_dev->streaming) |
5954 | goto err; | 5954 | goto err; |
5955 | 5955 | ||
5956 | /* Bit 0 of register 11 indicates FIFO overflow */ | 5956 | /* Bit 0 of register 11 indicates FIFO overflow */ |
@@ -6842,7 +6842,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
6842 | mutex_lock(&gspca_dev->usb_lock); | 6842 | mutex_lock(&gspca_dev->usb_lock); |
6843 | sd->work_thread = NULL; | 6843 | sd->work_thread = NULL; |
6844 | } | 6844 | } |
6845 | if (!gspca_dev->dev) | 6845 | if (!gspca_dev->present) |
6846 | return; | 6846 | return; |
6847 | send_unknown(gspca_dev, sd->sensor); | 6847 | send_unknown(gspca_dev, sd->sensor); |
6848 | } | 6848 | } |