aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-12-18 07:50:43 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:28:12 -0500
commitd2db8fee0d77f43f64e4e97ccc1558a9f59fab41 (patch)
tree4c4a65bb628b94ce7df210cef85b7fa218f9b592
parent9af39713feb53da96ba23fa94a73ffd0de50a815 (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.h2
-rw-r--r--drivers/media/video/cpia2/cpia2_core.c65
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c104
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
379struct camera_data { 379struct 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[] = {
238static int cpia2_open(struct file *file) 238static 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;
274skip_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;
291err_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