diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-06-26 12:57:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:44 -0400 |
commit | 04613c5e600e64840e4f753bd881cd5ab96ae403 (patch) | |
tree | d253b03b6d2afc47ba795bf24aed8db44b713506 /drivers/media/video/pwc | |
parent | 4fba471e405f8f983085fd9f2fd9637bfc275f8f (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.c | 76 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 11 |
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 | ||
516 | static void pwc_isoc_cleanup(struct pwc_device *pdev) | 506 | static 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? :-) */ | ||
132 | struct 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 */ |
141 | struct pwc_frame_buf | 132 | struct 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 */ |