diff options
Diffstat (limited to 'drivers/usb/gadget/uvc_video.c')
-rw-r--r-- | drivers/usb/gadget/uvc_video.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index b0e53a8ea4f7..71e896d4c5ae 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c | |||
@@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf, | |||
32 | data[0] = 2; | 32 | data[0] = 2; |
33 | data[1] = UVC_STREAM_EOH | video->fid; | 33 | data[1] = UVC_STREAM_EOH | video->fid; |
34 | 34 | ||
35 | if (buf->buf.bytesused - video->queue.buf_used <= len - 2) | 35 | if (buf->bytesused - video->queue.buf_used <= len - 2) |
36 | data[1] |= UVC_STREAM_EOF; | 36 | data[1] |= UVC_STREAM_EOF; |
37 | 37 | ||
38 | return 2; | 38 | return 2; |
@@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf, | |||
47 | void *mem; | 47 | void *mem; |
48 | 48 | ||
49 | /* Copy video data to the USB buffer. */ | 49 | /* Copy video data to the USB buffer. */ |
50 | mem = queue->mem + buf->buf.m.offset + queue->buf_used; | 50 | mem = buf->mem + queue->buf_used; |
51 | nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); | 51 | nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used); |
52 | 52 | ||
53 | memcpy(data, mem, nbytes); | 53 | memcpy(data, mem, nbytes); |
54 | queue->buf_used += nbytes; | 54 | queue->buf_used += nbytes; |
@@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, | |||
82 | req->length = video->req_size - len; | 82 | req->length = video->req_size - len; |
83 | req->zero = video->payload_size == video->max_payload_size; | 83 | req->zero = video->payload_size == video->max_payload_size; |
84 | 84 | ||
85 | if (buf->buf.bytesused == video->queue.buf_used) { | 85 | if (buf->bytesused == video->queue.buf_used) { |
86 | video->queue.buf_used = 0; | 86 | video->queue.buf_used = 0; |
87 | buf->state = UVC_BUF_STATE_DONE; | 87 | buf->state = UVC_BUF_STATE_DONE; |
88 | uvc_queue_next_buffer(&video->queue, buf); | 88 | uvc_queue_next_buffer(&video->queue, buf); |
@@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, | |||
92 | } | 92 | } |
93 | 93 | ||
94 | if (video->payload_size == video->max_payload_size || | 94 | if (video->payload_size == video->max_payload_size || |
95 | buf->buf.bytesused == video->queue.buf_used) | 95 | buf->bytesused == video->queue.buf_used) |
96 | video->payload_size = 0; | 96 | video->payload_size = 0; |
97 | } | 97 | } |
98 | 98 | ||
@@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, | |||
115 | 115 | ||
116 | req->length = video->req_size - len; | 116 | req->length = video->req_size - len; |
117 | 117 | ||
118 | if (buf->buf.bytesused == video->queue.buf_used) { | 118 | if (buf->bytesused == video->queue.buf_used) { |
119 | video->queue.buf_used = 0; | 119 | video->queue.buf_used = 0; |
120 | buf->state = UVC_BUF_STATE_DONE; | 120 | buf->state = UVC_BUF_STATE_DONE; |
121 | uvc_queue_next_buffer(&video->queue, buf); | 121 | uvc_queue_next_buffer(&video->queue, buf); |
@@ -161,6 +161,7 @@ static void | |||
161 | uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | 161 | uvc_video_complete(struct usb_ep *ep, struct usb_request *req) |
162 | { | 162 | { |
163 | struct uvc_video *video = req->context; | 163 | struct uvc_video *video = req->context; |
164 | struct uvc_video_queue *queue = &video->queue; | ||
164 | struct uvc_buffer *buf; | 165 | struct uvc_buffer *buf; |
165 | unsigned long flags; | 166 | unsigned long flags; |
166 | int ret; | 167 | int ret; |
@@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) | |||
169 | case 0: | 170 | case 0: |
170 | break; | 171 | break; |
171 | 172 | ||
172 | case -ESHUTDOWN: | 173 | case -ESHUTDOWN: /* disconnect from host. */ |
173 | printk(KERN_INFO "VS request cancelled.\n"); | 174 | printk(KERN_INFO "VS request cancelled.\n"); |
175 | uvc_queue_cancel(queue, 1); | ||
174 | goto requeue; | 176 | goto requeue; |
175 | 177 | ||
176 | default: | 178 | default: |
177 | printk(KERN_INFO "VS request completed with status %d.\n", | 179 | printk(KERN_INFO "VS request completed with status %d.\n", |
178 | req->status); | 180 | req->status); |
181 | uvc_queue_cancel(queue, 0); | ||
179 | goto requeue; | 182 | goto requeue; |
180 | } | 183 | } |
181 | 184 | ||
@@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video) | |||
229 | static int | 232 | static int |
230 | uvc_video_alloc_requests(struct uvc_video *video) | 233 | uvc_video_alloc_requests(struct uvc_video *video) |
231 | { | 234 | { |
235 | unsigned int req_size; | ||
232 | unsigned int i; | 236 | unsigned int i; |
233 | int ret = -ENOMEM; | 237 | int ret = -ENOMEM; |
234 | 238 | ||
235 | BUG_ON(video->req_size); | 239 | BUG_ON(video->req_size); |
236 | 240 | ||
241 | req_size = video->ep->maxpacket | ||
242 | * max_t(unsigned int, video->ep->maxburst, 1) | ||
243 | * (video->ep->mult + 1); | ||
244 | |||
237 | for (i = 0; i < UVC_NUM_REQUESTS; ++i) { | 245 | for (i = 0; i < UVC_NUM_REQUESTS; ++i) { |
238 | video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL); | 246 | video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); |
239 | if (video->req_buffer[i] == NULL) | 247 | if (video->req_buffer[i] == NULL) |
240 | goto error; | 248 | goto error; |
241 | 249 | ||
@@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video) | |||
245 | 253 | ||
246 | video->req[i]->buf = video->req_buffer[i]; | 254 | video->req[i]->buf = video->req_buffer[i]; |
247 | video->req[i]->length = 0; | 255 | video->req[i]->length = 0; |
248 | video->req[i]->dma = DMA_ADDR_INVALID; | ||
249 | video->req[i]->complete = uvc_video_complete; | 256 | video->req[i]->complete = uvc_video_complete; |
250 | video->req[i]->context = video; | 257 | video->req[i]->context = video; |
251 | 258 | ||
252 | list_add_tail(&video->req[i]->list, &video->req_free); | 259 | list_add_tail(&video->req[i]->list, &video->req_free); |
253 | } | 260 | } |
254 | 261 | ||
255 | video->req_size = video->ep->maxpacket; | 262 | video->req_size = req_size; |
263 | |||
256 | return 0; | 264 | return 0; |
257 | 265 | ||
258 | error: | 266 | error: |
@@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video) | |||
309 | video->encode(req, video, buf); | 317 | video->encode(req, video, buf); |
310 | 318 | ||
311 | /* Queue the USB request */ | 319 | /* Queue the USB request */ |
312 | if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) { | 320 | ret = usb_ep_queue(video->ep, req, GFP_ATOMIC); |
321 | if (ret < 0) { | ||
313 | printk(KERN_INFO "Failed to queue request (%d)\n", ret); | 322 | printk(KERN_INFO "Failed to queue request (%d)\n", ret); |
314 | usb_ep_set_halt(video->ep); | 323 | usb_ep_set_halt(video->ep); |
315 | spin_unlock_irqrestore(&video->queue.irqlock, flags); | 324 | spin_unlock_irqrestore(&video->queue.irqlock, flags); |