diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-12-18 07:50:43 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-01-19 08:28:12 -0500 |
commit | d2db8fee0d77f43f64e4e97ccc1558a9f59fab41 (patch) | |
tree | 4c4a65bb628b94ce7df210cef85b7fa218f9b592 | |
parent | 9af39713feb53da96ba23fa94a73ffd0de50a815 (diff) |
[media] cpia2: convert .ioctl to .unlocked_ioctl
Implement core-assisted locking in cpia2.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/cpia2/cpia2.h | 2 | ||||
-rw-r--r-- | drivers/media/video/cpia2/cpia2_core.c | 65 | ||||
-rw-r--r-- | drivers/media/video/cpia2/cpia2_v4l.c | 104 |
3 files changed, 50 insertions, 121 deletions
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 916c13d5cf7d..6d6d1843791c 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h | |||
@@ -378,7 +378,7 @@ struct cpia2_fh { | |||
378 | 378 | ||
379 | struct camera_data { | 379 | struct camera_data { |
380 | /* locks */ | 380 | /* locks */ |
381 | struct mutex busy_lock; /* guard against SMP multithreading */ | 381 | struct mutex v4l2_lock; /* serialize file operations */ |
382 | struct v4l2_prio_state prio; | 382 | struct v4l2_prio_state prio; |
383 | 383 | ||
384 | /* camera status */ | 384 | /* camera status */ |
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index 9606bc01b803..aaffca8e13fd 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c | |||
@@ -2247,7 +2247,7 @@ struct camera_data *cpia2_init_camera_struct(void) | |||
2247 | 2247 | ||
2248 | 2248 | ||
2249 | cam->present = 1; | 2249 | cam->present = 1; |
2250 | mutex_init(&cam->busy_lock); | 2250 | mutex_init(&cam->v4l2_lock); |
2251 | init_waitqueue_head(&cam->wq_stream); | 2251 | init_waitqueue_head(&cam->wq_stream); |
2252 | 2252 | ||
2253 | return cam; | 2253 | return cam; |
@@ -2365,9 +2365,9 @@ long cpia2_read(struct camera_data *cam, | |||
2365 | char __user *buf, unsigned long count, int noblock) | 2365 | char __user *buf, unsigned long count, int noblock) |
2366 | { | 2366 | { |
2367 | struct framebuf *frame; | 2367 | struct framebuf *frame; |
2368 | if (!count) { | 2368 | |
2369 | if (!count) | ||
2369 | return 0; | 2370 | return 0; |
2370 | } | ||
2371 | 2371 | ||
2372 | if (!buf) { | 2372 | if (!buf) { |
2373 | ERR("%s: buffer NULL\n",__func__); | 2373 | ERR("%s: buffer NULL\n",__func__); |
@@ -2379,17 +2379,12 @@ long cpia2_read(struct camera_data *cam, | |||
2379 | return -EINVAL; | 2379 | return -EINVAL; |
2380 | } | 2380 | } |
2381 | 2381 | ||
2382 | /* make this _really_ smp and multithread-safe */ | ||
2383 | if (mutex_lock_interruptible(&cam->busy_lock)) | ||
2384 | return -ERESTARTSYS; | ||
2385 | |||
2386 | if (!cam->present) { | 2382 | if (!cam->present) { |
2387 | LOG("%s: camera removed\n",__func__); | 2383 | LOG("%s: camera removed\n",__func__); |
2388 | mutex_unlock(&cam->busy_lock); | ||
2389 | return 0; /* EOF */ | 2384 | return 0; /* EOF */ |
2390 | } | 2385 | } |
2391 | 2386 | ||
2392 | if(!cam->streaming) { | 2387 | if (!cam->streaming) { |
2393 | /* Start streaming */ | 2388 | /* Start streaming */ |
2394 | cpia2_usb_stream_start(cam, | 2389 | cpia2_usb_stream_start(cam, |
2395 | cam->params.camera_state.stream_mode); | 2390 | cam->params.camera_state.stream_mode); |
@@ -2398,42 +2393,31 @@ long cpia2_read(struct camera_data *cam, | |||
2398 | /* Copy cam->curbuff in case it changes while we're processing */ | 2393 | /* Copy cam->curbuff in case it changes while we're processing */ |
2399 | frame = cam->curbuff; | 2394 | frame = cam->curbuff; |
2400 | if (noblock && frame->status != FRAME_READY) { | 2395 | if (noblock && frame->status != FRAME_READY) { |
2401 | mutex_unlock(&cam->busy_lock); | ||
2402 | return -EAGAIN; | 2396 | return -EAGAIN; |
2403 | } | 2397 | } |
2404 | 2398 | ||
2405 | if(frame->status != FRAME_READY) { | 2399 | if (frame->status != FRAME_READY) { |
2406 | mutex_unlock(&cam->busy_lock); | 2400 | mutex_unlock(&cam->v4l2_lock); |
2407 | wait_event_interruptible(cam->wq_stream, | 2401 | wait_event_interruptible(cam->wq_stream, |
2408 | !cam->present || | 2402 | !cam->present || |
2409 | (frame = cam->curbuff)->status == FRAME_READY); | 2403 | (frame = cam->curbuff)->status == FRAME_READY); |
2404 | mutex_lock(&cam->v4l2_lock); | ||
2410 | if (signal_pending(current)) | 2405 | if (signal_pending(current)) |
2411 | return -ERESTARTSYS; | 2406 | return -ERESTARTSYS; |
2412 | /* make this _really_ smp and multithread-safe */ | 2407 | if (!cam->present) |
2413 | if (mutex_lock_interruptible(&cam->busy_lock)) { | ||
2414 | return -ERESTARTSYS; | ||
2415 | } | ||
2416 | if(!cam->present) { | ||
2417 | mutex_unlock(&cam->busy_lock); | ||
2418 | return 0; | 2408 | return 0; |
2419 | } | ||
2420 | } | 2409 | } |
2421 | 2410 | ||
2422 | /* copy data to user space */ | 2411 | /* copy data to user space */ |
2423 | if (frame->length > count) { | 2412 | if (frame->length > count) |
2424 | mutex_unlock(&cam->busy_lock); | ||
2425 | return -EFAULT; | 2413 | return -EFAULT; |
2426 | } | 2414 | if (copy_to_user(buf, frame->data, frame->length)) |
2427 | if (copy_to_user(buf, frame->data, frame->length)) { | ||
2428 | mutex_unlock(&cam->busy_lock); | ||
2429 | return -EFAULT; | 2415 | return -EFAULT; |
2430 | } | ||
2431 | 2416 | ||
2432 | count = frame->length; | 2417 | count = frame->length; |
2433 | 2418 | ||
2434 | frame->status = FRAME_EMPTY; | 2419 | frame->status = FRAME_EMPTY; |
2435 | 2420 | ||
2436 | mutex_unlock(&cam->busy_lock); | ||
2437 | return count; | 2421 | return count; |
2438 | } | 2422 | } |
2439 | 2423 | ||
@@ -2447,17 +2431,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, | |||
2447 | { | 2431 | { |
2448 | unsigned int status=0; | 2432 | unsigned int status=0; |
2449 | 2433 | ||
2450 | if(!cam) { | 2434 | if (!cam) { |
2451 | ERR("%s: Internal error, camera_data not found!\n",__func__); | 2435 | ERR("%s: Internal error, camera_data not found!\n",__func__); |
2452 | return POLLERR; | 2436 | return POLLERR; |
2453 | } | 2437 | } |
2454 | 2438 | ||
2455 | mutex_lock(&cam->busy_lock); | 2439 | if (!cam->present) |
2456 | |||
2457 | if(!cam->present) { | ||
2458 | mutex_unlock(&cam->busy_lock); | ||
2459 | return POLLHUP; | 2440 | return POLLHUP; |
2460 | } | ||
2461 | 2441 | ||
2462 | if(!cam->streaming) { | 2442 | if(!cam->streaming) { |
2463 | /* Start streaming */ | 2443 | /* Start streaming */ |
@@ -2465,16 +2445,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, | |||
2465 | cam->params.camera_state.stream_mode); | 2445 | cam->params.camera_state.stream_mode); |
2466 | } | 2446 | } |
2467 | 2447 | ||
2468 | mutex_unlock(&cam->busy_lock); | ||
2469 | poll_wait(filp, &cam->wq_stream, wait); | 2448 | poll_wait(filp, &cam->wq_stream, wait); |
2470 | mutex_lock(&cam->busy_lock); | ||
2471 | 2449 | ||
2472 | if(!cam->present) | 2450 | if(!cam->present) |
2473 | status = POLLHUP; | 2451 | status = POLLHUP; |
2474 | else if(cam->curbuff->status == FRAME_READY) | 2452 | else if(cam->curbuff->status == FRAME_READY) |
2475 | status = POLLIN | POLLRDNORM; | 2453 | status = POLLIN | POLLRDNORM; |
2476 | 2454 | ||
2477 | mutex_unlock(&cam->busy_lock); | ||
2478 | return status; | 2455 | return status; |
2479 | } | 2456 | } |
2480 | 2457 | ||
@@ -2496,29 +2473,19 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) | |||
2496 | 2473 | ||
2497 | DBG("mmap offset:%ld size:%ld\n", start_offset, size); | 2474 | DBG("mmap offset:%ld size:%ld\n", start_offset, size); |
2498 | 2475 | ||
2499 | /* make this _really_ smp-safe */ | 2476 | if (!cam->present) |
2500 | if (mutex_lock_interruptible(&cam->busy_lock)) | ||
2501 | return -ERESTARTSYS; | ||
2502 | |||
2503 | if (!cam->present) { | ||
2504 | mutex_unlock(&cam->busy_lock); | ||
2505 | return -ENODEV; | 2477 | return -ENODEV; |
2506 | } | ||
2507 | 2478 | ||
2508 | if (size > cam->frame_size*cam->num_frames || | 2479 | if (size > cam->frame_size*cam->num_frames || |
2509 | (start_offset % cam->frame_size) != 0 || | 2480 | (start_offset % cam->frame_size) != 0 || |
2510 | (start_offset+size > cam->frame_size*cam->num_frames)) { | 2481 | (start_offset+size > cam->frame_size*cam->num_frames)) |
2511 | mutex_unlock(&cam->busy_lock); | ||
2512 | return -EINVAL; | 2482 | return -EINVAL; |
2513 | } | ||
2514 | 2483 | ||
2515 | pos = ((unsigned long) (cam->frame_buffer)) + start_offset; | 2484 | pos = ((unsigned long) (cam->frame_buffer)) + start_offset; |
2516 | while (size > 0) { | 2485 | while (size > 0) { |
2517 | page = kvirt_to_pa(pos); | 2486 | page = kvirt_to_pa(pos); |
2518 | if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) { | 2487 | if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) |
2519 | mutex_unlock(&cam->busy_lock); | ||
2520 | return -EAGAIN; | 2488 | return -EAGAIN; |
2521 | } | ||
2522 | start += PAGE_SIZE; | 2489 | start += PAGE_SIZE; |
2523 | pos += PAGE_SIZE; | 2490 | pos += PAGE_SIZE; |
2524 | if (size > PAGE_SIZE) | 2491 | if (size > PAGE_SIZE) |
@@ -2528,7 +2495,5 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) | |||
2528 | } | 2495 | } |
2529 | 2496 | ||
2530 | cam->mmapped = true; | 2497 | cam->mmapped = true; |
2531 | mutex_unlock(&cam->busy_lock); | ||
2532 | return 0; | 2498 | return 0; |
2533 | } | 2499 | } |
2534 | |||
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 7edf80b0d01a..9bad39842936 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -238,59 +238,40 @@ static struct v4l2_queryctrl controls[] = { | |||
238 | static int cpia2_open(struct file *file) | 238 | static int cpia2_open(struct file *file) |
239 | { | 239 | { |
240 | struct camera_data *cam = video_drvdata(file); | 240 | struct camera_data *cam = video_drvdata(file); |
241 | int retval = 0; | 241 | struct cpia2_fh *fh; |
242 | 242 | ||
243 | if (!cam) { | 243 | if (!cam) { |
244 | ERR("Internal error, camera_data not found!\n"); | 244 | ERR("Internal error, camera_data not found!\n"); |
245 | return -ENODEV; | 245 | return -ENODEV; |
246 | } | 246 | } |
247 | 247 | ||
248 | if(mutex_lock_interruptible(&cam->busy_lock)) | 248 | if (!cam->present) |
249 | return -ERESTARTSYS; | 249 | return -ENODEV; |
250 | |||
251 | if(!cam->present) { | ||
252 | retval = -ENODEV; | ||
253 | goto err_return; | ||
254 | } | ||
255 | 250 | ||
256 | if (cam->open_count > 0) { | 251 | if (cam->open_count == 0) { |
257 | goto skip_init; | 252 | if (cpia2_allocate_buffers(cam)) |
258 | } | 253 | return -ENOMEM; |
259 | 254 | ||
260 | if (cpia2_allocate_buffers(cam)) { | 255 | /* reset the camera */ |
261 | retval = -ENOMEM; | 256 | if (cpia2_reset_camera(cam) < 0) |
262 | goto err_return; | 257 | return -EIO; |
263 | } | ||
264 | 258 | ||
265 | /* reset the camera */ | 259 | cam->APP_len = 0; |
266 | if (cpia2_reset_camera(cam) < 0) { | 260 | cam->COM_len = 0; |
267 | retval = -EIO; | ||
268 | goto err_return; | ||
269 | } | 261 | } |
270 | 262 | ||
271 | cam->APP_len = 0; | 263 | fh = kmalloc(sizeof(*fh), GFP_KERNEL); |
272 | cam->COM_len = 0; | 264 | if (!fh) |
273 | 265 | return -ENOMEM; | |
274 | skip_init: | 266 | file->private_data = fh; |
275 | { | 267 | fh->prio = V4L2_PRIORITY_UNSET; |
276 | struct cpia2_fh *fh = kmalloc(sizeof(*fh),GFP_KERNEL); | 268 | v4l2_prio_open(&cam->prio, &fh->prio); |
277 | if(!fh) { | 269 | fh->mmapped = 0; |
278 | retval = -ENOMEM; | ||
279 | goto err_return; | ||
280 | } | ||
281 | file->private_data = fh; | ||
282 | fh->prio = V4L2_PRIORITY_UNSET; | ||
283 | v4l2_prio_open(&cam->prio, &fh->prio); | ||
284 | fh->mmapped = 0; | ||
285 | } | ||
286 | 270 | ||
287 | ++cam->open_count; | 271 | ++cam->open_count; |
288 | 272 | ||
289 | cpia2_dbg_dump_registers(cam); | 273 | cpia2_dbg_dump_registers(cam); |
290 | 274 | return 0; | |
291 | err_return: | ||
292 | mutex_unlock(&cam->busy_lock); | ||
293 | return retval; | ||
294 | } | 275 | } |
295 | 276 | ||
296 | /****************************************************************************** | 277 | /****************************************************************************** |
@@ -304,15 +285,11 @@ static int cpia2_close(struct file *file) | |||
304 | struct camera_data *cam = video_get_drvdata(dev); | 285 | struct camera_data *cam = video_get_drvdata(dev); |
305 | struct cpia2_fh *fh = file->private_data; | 286 | struct cpia2_fh *fh = file->private_data; |
306 | 287 | ||
307 | mutex_lock(&cam->busy_lock); | ||
308 | |||
309 | if (cam->present && | 288 | if (cam->present && |
310 | (cam->open_count == 1 | 289 | (cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) { |
311 | || fh->prio == V4L2_PRIORITY_RECORD | ||
312 | )) { | ||
313 | cpia2_usb_stream_stop(cam); | 290 | cpia2_usb_stream_stop(cam); |
314 | 291 | ||
315 | if(cam->open_count == 1) { | 292 | if (cam->open_count == 1) { |
316 | /* save camera state for later open */ | 293 | /* save camera state for later open */ |
317 | cpia2_save_camera_state(cam); | 294 | cpia2_save_camera_state(cam); |
318 | 295 | ||
@@ -321,26 +298,21 @@ static int cpia2_close(struct file *file) | |||
321 | } | 298 | } |
322 | } | 299 | } |
323 | 300 | ||
324 | { | 301 | if (fh->mmapped) |
325 | if(fh->mmapped) | 302 | cam->mmapped = 0; |
326 | cam->mmapped = 0; | 303 | v4l2_prio_close(&cam->prio, fh->prio); |
327 | v4l2_prio_close(&cam->prio, fh->prio); | 304 | file->private_data = NULL; |
328 | file->private_data = NULL; | 305 | kfree(fh); |
329 | kfree(fh); | ||
330 | } | ||
331 | 306 | ||
332 | if (--cam->open_count == 0) { | 307 | if (--cam->open_count == 0) { |
333 | cpia2_free_buffers(cam); | 308 | cpia2_free_buffers(cam); |
334 | if (!cam->present) { | 309 | if (!cam->present) { |
335 | video_unregister_device(dev); | 310 | video_unregister_device(dev); |
336 | mutex_unlock(&cam->busy_lock); | ||
337 | kfree(cam); | 311 | kfree(cam); |
338 | return 0; | 312 | return 0; |
339 | } | 313 | } |
340 | } | 314 | } |
341 | 315 | ||
342 | mutex_unlock(&cam->busy_lock); | ||
343 | |||
344 | return 0; | 316 | return 0; |
345 | } | 317 | } |
346 | 318 | ||
@@ -405,11 +377,11 @@ static int sync(struct camera_data *cam, int frame_nr) | |||
405 | return 0; | 377 | return 0; |
406 | } | 378 | } |
407 | 379 | ||
408 | mutex_unlock(&cam->busy_lock); | 380 | mutex_unlock(&cam->v4l2_lock); |
409 | wait_event_interruptible(cam->wq_stream, | 381 | wait_event_interruptible(cam->wq_stream, |
410 | !cam->streaming || | 382 | !cam->streaming || |
411 | frame->status == FRAME_READY); | 383 | frame->status == FRAME_READY); |
412 | mutex_lock(&cam->busy_lock); | 384 | mutex_lock(&cam->v4l2_lock); |
413 | if (signal_pending(current)) | 385 | if (signal_pending(current)) |
414 | return -ERESTARTSYS; | 386 | return -ERESTARTSYS; |
415 | if(!cam->present) | 387 | if(!cam->present) |
@@ -1293,11 +1265,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) | |||
1293 | if(frame < 0) { | 1265 | if(frame < 0) { |
1294 | /* Wait for a frame to become available */ | 1266 | /* Wait for a frame to become available */ |
1295 | struct framebuf *cb=cam->curbuff; | 1267 | struct framebuf *cb=cam->curbuff; |
1296 | mutex_unlock(&cam->busy_lock); | 1268 | mutex_unlock(&cam->v4l2_lock); |
1297 | wait_event_interruptible(cam->wq_stream, | 1269 | wait_event_interruptible(cam->wq_stream, |
1298 | !cam->present || | 1270 | !cam->present || |
1299 | (cb=cam->curbuff)->status == FRAME_READY); | 1271 | (cb=cam->curbuff)->status == FRAME_READY); |
1300 | mutex_lock(&cam->busy_lock); | 1272 | mutex_lock(&cam->v4l2_lock); |
1301 | if (signal_pending(current)) | 1273 | if (signal_pending(current)) |
1302 | return -ERESTARTSYS; | 1274 | return -ERESTARTSYS; |
1303 | if(!cam->present) | 1275 | if(!cam->present) |
@@ -1337,14 +1309,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
1337 | if (!cam) | 1309 | if (!cam) |
1338 | return -ENOTTY; | 1310 | return -ENOTTY; |
1339 | 1311 | ||
1340 | /* make this _really_ smp-safe */ | 1312 | if (!cam->present) |
1341 | if (mutex_lock_interruptible(&cam->busy_lock)) | ||
1342 | return -ERESTARTSYS; | ||
1343 | |||
1344 | if (!cam->present) { | ||
1345 | mutex_unlock(&cam->busy_lock); | ||
1346 | return -ENODEV; | 1313 | return -ENODEV; |
1347 | } | ||
1348 | 1314 | ||
1349 | /* Priority check */ | 1315 | /* Priority check */ |
1350 | switch (cmd) { | 1316 | switch (cmd) { |
@@ -1352,10 +1318,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
1352 | { | 1318 | { |
1353 | struct cpia2_fh *fh = file->private_data; | 1319 | struct cpia2_fh *fh = file->private_data; |
1354 | retval = v4l2_prio_check(&cam->prio, fh->prio); | 1320 | retval = v4l2_prio_check(&cam->prio, fh->prio); |
1355 | if(retval) { | 1321 | if (retval) |
1356 | mutex_unlock(&cam->busy_lock); | ||
1357 | return retval; | 1322 | return retval; |
1358 | } | ||
1359 | break; | 1323 | break; |
1360 | } | 1324 | } |
1361 | default: | 1325 | default: |
@@ -1529,7 +1493,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
1529 | break; | 1493 | break; |
1530 | } | 1494 | } |
1531 | 1495 | ||
1532 | mutex_unlock(&cam->busy_lock); | ||
1533 | return retval; | 1496 | return retval; |
1534 | } | 1497 | } |
1535 | 1498 | ||
@@ -1596,7 +1559,7 @@ static const struct v4l2_file_operations cpia2_fops = { | |||
1596 | .release = cpia2_close, | 1559 | .release = cpia2_close, |
1597 | .read = cpia2_v4l_read, | 1560 | .read = cpia2_v4l_read, |
1598 | .poll = cpia2_v4l_poll, | 1561 | .poll = cpia2_v4l_poll, |
1599 | .ioctl = cpia2_ioctl, | 1562 | .unlocked_ioctl = cpia2_ioctl, |
1600 | .mmap = cpia2_mmap, | 1563 | .mmap = cpia2_mmap, |
1601 | }; | 1564 | }; |
1602 | 1565 | ||
@@ -1620,6 +1583,7 @@ int cpia2_register_camera(struct camera_data *cam) | |||
1620 | 1583 | ||
1621 | memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template)); | 1584 | memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template)); |
1622 | video_set_drvdata(cam->vdev, cam); | 1585 | video_set_drvdata(cam->vdev, cam); |
1586 | cam->vdev->lock = &cam->v4l2_lock; | ||
1623 | 1587 | ||
1624 | reset_camera_struct_v4l(cam); | 1588 | reset_camera_struct_v4l(cam); |
1625 | 1589 | ||