aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-06-26 12:57:15 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:44 -0400
commit04613c5e600e64840e4f753bd881cd5ab96ae403 (patch)
treed253b03b6d2afc47ba795bf24aed8db44b713506 /drivers/media/video/pwc
parent4fba471e405f8f983085fd9f2fd9637bfc275f8f (diff)
[media] pwc: properly allocate dma-able memory for ISO buffers
Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r--drivers/media/video/pwc/pwc-if.c76
-rw-r--r--drivers/media/video/pwc/pwc.h11
2 files changed, 28 insertions, 59 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index a6b5fde5c3ad..4c1c056ffdf4 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -376,7 +376,6 @@ static int pwc_isoc_init(struct pwc_device *pdev)
376 int i, j, ret; 376 int i, j, ret;
377 struct usb_interface *intf; 377 struct usb_interface *intf;
378 struct usb_host_interface *idesc = NULL; 378 struct usb_host_interface *idesc = NULL;
379 void *kbuf;
380 379
381 if (pdev->iso_init) 380 if (pdev->iso_init)
382 return 0; 381 return 0;
@@ -416,20 +415,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
416 if (ret < 0) 415 if (ret < 0)
417 return ret; 416 return ret;
418 417
419 /* Allocate Isochronuous pipe buffers */ 418 /* Allocate and init Isochronuous urbs */
420 for (i = 0; i < MAX_ISO_BUFS; i++) {
421 kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
422 if (kbuf == NULL) {
423 PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
424 pdev->iso_init = 1;
425 pwc_isoc_cleanup(pdev);
426 return -ENOMEM;
427 }
428 PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
429 pdev->sbuf[i].data = kbuf;
430 }
431
432 /* Allocate Isochronuous urbs */
433 for (i = 0; i < MAX_ISO_BUFS; i++) { 419 for (i = 0; i < MAX_ISO_BUFS; i++) {
434 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); 420 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
435 if (urb == NULL) { 421 if (urb == NULL) {
@@ -438,19 +424,23 @@ static int pwc_isoc_init(struct pwc_device *pdev)
438 pwc_isoc_cleanup(pdev); 424 pwc_isoc_cleanup(pdev);
439 return -ENOMEM; 425 return -ENOMEM;
440 } 426 }
441 pdev->sbuf[i].urb = urb; 427 pdev->urbs[i] = urb;
442 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb); 428 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
443 }
444
445 /* init URB structure */
446 for (i = 0; i < MAX_ISO_BUFS; i++) {
447 urb = pdev->sbuf[i].urb;
448 429
449 urb->interval = 1; // devik 430 urb->interval = 1; // devik
450 urb->dev = udev; 431 urb->dev = udev;
451 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); 432 urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
452 urb->transfer_flags = URB_ISO_ASAP; 433 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
453 urb->transfer_buffer = pdev->sbuf[i].data; 434 urb->transfer_buffer = usb_alloc_coherent(udev,
435 ISO_BUFFER_SIZE,
436 GFP_KERNEL,
437 &urb->transfer_dma);
438 if (urb->transfer_buffer == NULL) {
439 PWC_ERROR("Failed to allocate urb buffer %d\n", i);
440 pdev->iso_init = 1;
441 pwc_isoc_cleanup(pdev);
442 return -ENOMEM;
443 }
454 urb->transfer_buffer_length = ISO_BUFFER_SIZE; 444 urb->transfer_buffer_length = ISO_BUFFER_SIZE;
455 urb->complete = pwc_isoc_handler; 445 urb->complete = pwc_isoc_handler;
456 urb->context = pdev; 446 urb->context = pdev;
@@ -464,14 +454,14 @@ static int pwc_isoc_init(struct pwc_device *pdev)
464 454
465 /* link */ 455 /* link */
466 for (i = 0; i < MAX_ISO_BUFS; i++) { 456 for (i = 0; i < MAX_ISO_BUFS; i++) {
467 ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); 457 ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
468 if (ret) { 458 if (ret) {
469 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); 459 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
470 pdev->iso_init = 1; 460 pdev->iso_init = 1;
471 pwc_isoc_cleanup(pdev); 461 pwc_isoc_cleanup(pdev);
472 return ret; 462 return ret;
473 } 463 }
474 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); 464 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
475 } 465 }
476 466
477 /* All is done... */ 467 /* All is done... */
@@ -486,12 +476,9 @@ static void pwc_iso_stop(struct pwc_device *pdev)
486 476
487 /* Unlinking ISOC buffers one by one */ 477 /* Unlinking ISOC buffers one by one */
488 for (i = 0; i < MAX_ISO_BUFS; i++) { 478 for (i = 0; i < MAX_ISO_BUFS; i++) {
489 struct urb *urb; 479 if (pdev->urbs[i]) {
490 480 PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
491 urb = pdev->sbuf[i].urb; 481 usb_kill_urb(pdev->urbs[i]);
492 if (urb) {
493 PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
494 usb_kill_urb(urb);
495 } 482 }
496 } 483 }
497} 484}
@@ -502,21 +489,22 @@ static void pwc_iso_free(struct pwc_device *pdev)
502 489
503 /* Freeing ISOC buffers one by one */ 490 /* Freeing ISOC buffers one by one */
504 for (i = 0; i < MAX_ISO_BUFS; i++) { 491 for (i = 0; i < MAX_ISO_BUFS; i++) {
505 struct urb *urb; 492 if (pdev->urbs[i]) {
506
507 urb = pdev->sbuf[i].urb;
508 if (urb) {
509 PWC_DEBUG_MEMORY("Freeing URB\n"); 493 PWC_DEBUG_MEMORY("Freeing URB\n");
510 usb_free_urb(urb); 494 if (pdev->urbs[i]->transfer_buffer) {
511 pdev->sbuf[i].urb = NULL; 495 usb_free_coherent(pdev->udev,
496 pdev->urbs[i]->transfer_buffer_length,
497 pdev->urbs[i]->transfer_buffer,
498 pdev->urbs[i]->transfer_dma);
499 }
500 usb_free_urb(pdev->urbs[i]);
501 pdev->urbs[i] = NULL;
512 } 502 }
513 } 503 }
514} 504}
515 505
516static void pwc_isoc_cleanup(struct pwc_device *pdev) 506static void pwc_isoc_cleanup(struct pwc_device *pdev)
517{ 507{
518 int i;
519
520 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); 508 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
521 509
522 if (pdev->iso_init == 0) 510 if (pdev->iso_init == 0)
@@ -526,16 +514,6 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
526 pwc_iso_free(pdev); 514 pwc_iso_free(pdev);
527 usb_set_interface(pdev->udev, 0, 0); 515 usb_set_interface(pdev->udev, 0, 0);
528 516
529 /* Release Iso-pipe buffers */
530 for (i = 0; i < MAX_ISO_BUFS; i++) {
531 if (pdev->sbuf[i].data != NULL) {
532 PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n",
533 pdev->sbuf[i].data);
534 kfree(pdev->sbuf[i].data);
535 pdev->sbuf[i].data = NULL;
536 }
537 }
538
539 pdev->iso_init = 0; 517 pdev->iso_init = 0;
540 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); 518 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
541} 519}
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index d65cd14ef9f2..1cfb8b475a3f 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -128,15 +128,6 @@
128#define DEVICE_USE_CODEC3(x) ((x)>=700) 128#define DEVICE_USE_CODEC3(x) ((x)>=700)
129#define DEVICE_USE_CODEC23(x) ((x)>=675) 129#define DEVICE_USE_CODEC23(x) ((x)>=675)
130 130
131/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
132struct pwc_iso_buf
133{
134 void *data;
135 int length;
136 int read;
137 struct urb *urb;
138};
139
140/* intermediate buffers with raw data from the USB cam */ 131/* intermediate buffers with raw data from the USB cam */
141struct pwc_frame_buf 132struct pwc_frame_buf
142{ 133{
@@ -180,7 +171,7 @@ struct pwc_device
180 int cmd_len; 171 int cmd_len;
181 unsigned char cmd_buf[13]; 172 unsigned char cmd_buf[13];
182 173
183 struct pwc_iso_buf sbuf[MAX_ISO_BUFS]; 174 struct urb *urbs[MAX_ISO_BUFS];
184 char iso_init; 175 char iso_init;
185 176
186 /* videobuf2 queue and queued buffers list */ 177 /* videobuf2 queue and queued buffers list */