diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index c0875378acc2..dcbab6ad4c26 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -77,23 +77,51 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | |||
77 | /* Get user pages for DMA Xfer */ | 77 | /* Get user pages for DMA Xfer */ |
78 | down_read(¤t->mm->mmap_sem); | 78 | down_read(¤t->mm->mmap_sem); |
79 | y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); | 79 | y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); |
80 | uv_pages = get_user_pages(current, current->mm, uv_dma.uaddr, uv_dma.page_count, 0, 1, &dma->map[y_pages], NULL); | 80 | uv_pages = 0; /* silence gcc. value is set and consumed only if: */ |
81 | if (y_pages == y_dma.page_count) { | ||
82 | uv_pages = get_user_pages(current, current->mm, | ||
83 | uv_dma.uaddr, uv_dma.page_count, 0, 1, | ||
84 | &dma->map[y_pages], NULL); | ||
85 | } | ||
81 | up_read(¤t->mm->mmap_sem); | 86 | up_read(¤t->mm->mmap_sem); |
82 | 87 | ||
83 | dma->page_count = y_dma.page_count + uv_dma.page_count; | 88 | if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { |
84 | 89 | int rc = -EFAULT; | |
85 | if (y_pages + uv_pages != dma->page_count) { | 90 | |
86 | IVTV_DEBUG_WARN | 91 | if (y_pages == y_dma.page_count) { |
87 | ("failed to map user pages, returned %d instead of %d\n", | 92 | IVTV_DEBUG_WARN |
88 | y_pages + uv_pages, dma->page_count); | 93 | ("failed to map uv user pages, returned %d " |
89 | 94 | "expecting %d\n", uv_pages, uv_dma.page_count); | |
90 | for (i = 0; i < dma->page_count; i++) { | 95 | |
91 | put_page(dma->map[i]); | 96 | if (uv_pages >= 0) { |
97 | for (i = 0; i < uv_pages; i++) | ||
98 | put_page(dma->map[y_pages + i]); | ||
99 | rc = -EFAULT; | ||
100 | } else { | ||
101 | rc = uv_pages; | ||
102 | } | ||
103 | } else { | ||
104 | IVTV_DEBUG_WARN | ||
105 | ("failed to map y user pages, returned %d " | ||
106 | "expecting %d\n", y_pages, y_dma.page_count); | ||
92 | } | 107 | } |
93 | dma->page_count = 0; | 108 | if (y_pages >= 0) { |
94 | return -EINVAL; | 109 | for (i = 0; i < y_pages; i++) |
110 | put_page(dma->map[i]); | ||
111 | /* | ||
112 | * Inherit the -EFAULT from rc's | ||
113 | * initialization, but allow it to be | ||
114 | * overriden by uv_pages above if it was an | ||
115 | * actual errno. | ||
116 | */ | ||
117 | } else { | ||
118 | rc = y_pages; | ||
119 | } | ||
120 | return rc; | ||
95 | } | 121 | } |
96 | 122 | ||
123 | dma->page_count = y_pages + uv_pages; | ||
124 | |||
97 | /* Fill & map SG List */ | 125 | /* Fill & map SG List */ |
98 | if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) { | 126 | if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) { |
99 | IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n"); | 127 | IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n"); |