]> Pileus Git - ~andy/linux/blob - drivers/media/usb/dvb-usb-v2/usb_urb.c
[media] dvb_usb_v2: use ratelimited debugs where appropriate
[~andy/linux] / drivers / media / usb / dvb-usb-v2 / usb_urb.c
1 /* usb-urb.c is part of the DVB USB library.
2  *
3  * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
4  * see dvb-usb-init.c for copyright information.
5  *
6  * This file keeps functions for initializing and handling the
7  * BULK and ISOC USB data transfers in a generic way.
8  * Can be used for DVB-only and also, that's the plan, for
9  * Hybrid USB devices (analog and DVB).
10  */
11 #include "dvb_usb_common.h"
12
13 /* URB stuff for streaming */
14
15 int usb_urb_reconfig(struct usb_data_stream *stream,
16                 struct usb_data_stream_properties *props);
17
18 static void usb_urb_complete(struct urb *urb)
19 {
20         struct usb_data_stream *stream = urb->context;
21         int ptype = usb_pipetype(urb->pipe);
22         int i;
23         u8 *b;
24
25         dev_dbg_ratelimited(&stream->udev->dev, "%s: %s urb completed " \
26                         "status=%d length=%d/%d pack_num=%d errors=%d\n",
27                         __func__, ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
28                         urb->status, urb->actual_length,
29                         urb->transfer_buffer_length,
30                         urb->number_of_packets, urb->error_count);
31
32         switch (urb->status) {
33         case 0:         /* success */
34         case -ETIMEDOUT:    /* NAK */
35                 break;
36         case -ECONNRESET:   /* kill */
37         case -ENOENT:
38         case -ESHUTDOWN:
39                 return;
40         default:        /* error */
41                 dev_dbg_ratelimited(&stream->udev->dev,
42                                 "%s: urb completition failed=%d\n",
43                                 __func__, urb->status);
44                 break;
45         }
46
47         b = (u8 *) urb->transfer_buffer;
48         switch (ptype) {
49         case PIPE_ISOCHRONOUS:
50                 for (i = 0; i < urb->number_of_packets; i++) {
51                         if (urb->iso_frame_desc[i].status != 0)
52                                 dev_dbg(&stream->udev->dev, "%s: iso frame " \
53                                                 "descriptor has an error=%d\n",
54                                                 __func__,
55                                                 urb->iso_frame_desc[i].status);
56                         else if (urb->iso_frame_desc[i].actual_length > 0)
57                                 stream->complete(stream,
58                                         b + urb->iso_frame_desc[i].offset,
59                                         urb->iso_frame_desc[i].actual_length);
60
61                         urb->iso_frame_desc[i].status = 0;
62                         urb->iso_frame_desc[i].actual_length = 0;
63                 }
64                 break;
65         case PIPE_BULK:
66                 if (urb->actual_length > 0)
67                         stream->complete(stream, b, urb->actual_length);
68                 break;
69         default:
70                 dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \
71                                 "completition handler\n", KBUILD_MODNAME);
72                 return;
73         }
74         usb_submit_urb(urb, GFP_ATOMIC);
75 }
76
77 int usb_urb_killv2(struct usb_data_stream *stream)
78 {
79         int i;
80         for (i = 0; i < stream->urbs_submitted; i++) {
81                 dev_dbg(&stream->udev->dev, "%s: kill urb=%d\n", __func__, i);
82                 /* stop the URB */
83                 usb_kill_urb(stream->urb_list[i]);
84         }
85         stream->urbs_submitted = 0;
86         return 0;
87 }
88
89 int usb_urb_submitv2(struct usb_data_stream *stream,
90                 struct usb_data_stream_properties *props)
91 {
92         int i, ret;
93
94         if (props) {
95                 ret = usb_urb_reconfig(stream, props);
96                 if (ret < 0)
97                         return ret;
98         }
99
100         for (i = 0; i < stream->urbs_initialized; i++) {
101                 dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i);
102                 ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC);
103                 if (ret) {
104                         dev_err(&stream->udev->dev, "%s: could not submit " \
105                                         "urb no. %d - get them all back\n",
106                                         KBUILD_MODNAME, i);
107                         usb_urb_killv2(stream);
108                         return ret;
109                 }
110                 stream->urbs_submitted++;
111         }
112         return 0;
113 }
114
115 int usb_urb_free_urbs(struct usb_data_stream *stream)
116 {
117         int i;
118
119         usb_urb_killv2(stream);
120
121         for (i = stream->urbs_initialized - 1; i >= 0; i--) {
122                 if (stream->urb_list[i]) {
123                         dev_dbg(&stream->udev->dev, "%s: free urb=%d\n",
124                                         __func__, i);
125                         /* free the URBs */
126                         usb_free_urb(stream->urb_list[i]);
127                 }
128         }
129         stream->urbs_initialized = 0;
130
131         return 0;
132 }
133
134 static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream)
135 {
136         int i, j;
137
138         /* allocate the URBs */
139         for (i = 0; i < stream->props.count; i++) {
140                 dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i);
141                 stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
142                 if (!stream->urb_list[i]) {
143                         dev_dbg(&stream->udev->dev, "%s: failed\n", __func__);
144                         for (j = 0; j < i; j++)
145                                 usb_free_urb(stream->urb_list[j]);
146                         return -ENOMEM;
147                 }
148                 usb_fill_bulk_urb(stream->urb_list[i],
149                                 stream->udev,
150                                 usb_rcvbulkpipe(stream->udev,
151                                                 stream->props.endpoint),
152                                 stream->buf_list[i],
153                                 stream->props.u.bulk.buffersize,
154                                 usb_urb_complete, stream);
155
156                 stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
157                 stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
158                 stream->urbs_initialized++;
159         }
160         return 0;
161 }
162
163 static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
164 {
165         int i, j;
166
167         /* allocate the URBs */
168         for (i = 0; i < stream->props.count; i++) {
169                 struct urb *urb;
170                 int frame_offset = 0;
171                 dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i);
172                 stream->urb_list[i] = usb_alloc_urb(
173                                 stream->props.u.isoc.framesperurb, GFP_ATOMIC);
174                 if (!stream->urb_list[i]) {
175                         dev_dbg(&stream->udev->dev, "%s: failed\n", __func__);
176                         for (j = 0; j < i; j++)
177                                 usb_free_urb(stream->urb_list[j]);
178                         return -ENOMEM;
179                 }
180
181                 urb = stream->urb_list[i];
182
183                 urb->dev = stream->udev;
184                 urb->context = stream;
185                 urb->complete = usb_urb_complete;
186                 urb->pipe = usb_rcvisocpipe(stream->udev,
187                                 stream->props.endpoint);
188                 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
189                 urb->interval = stream->props.u.isoc.interval;
190                 urb->number_of_packets = stream->props.u.isoc.framesperurb;
191                 urb->transfer_buffer_length = stream->props.u.isoc.framesize *
192                                 stream->props.u.isoc.framesperurb;
193                 urb->transfer_buffer = stream->buf_list[i];
194                 urb->transfer_dma = stream->dma_addr[i];
195
196                 for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
197                         urb->iso_frame_desc[j].offset = frame_offset;
198                         urb->iso_frame_desc[j].length =
199                                         stream->props.u.isoc.framesize;
200                         frame_offset += stream->props.u.isoc.framesize;
201                 }
202
203                 stream->urbs_initialized++;
204         }
205         return 0;
206 }
207
208 int usb_free_stream_buffers(struct usb_data_stream *stream)
209 {
210         if (stream->state & USB_STATE_URB_BUF) {
211                 while (stream->buf_num) {
212                         stream->buf_num--;
213                         dev_dbg(&stream->udev->dev, "%s: free buf=%d\n",
214                                 __func__, stream->buf_num);
215                         usb_free_coherent(stream->udev, stream->buf_size,
216                                           stream->buf_list[stream->buf_num],
217                                           stream->dma_addr[stream->buf_num]);
218                 }
219         }
220
221         stream->state &= ~USB_STATE_URB_BUF;
222
223         return 0;
224 }
225
226 int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
227                 unsigned long size)
228 {
229         stream->buf_num = 0;
230         stream->buf_size = size;
231
232         dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \
233                         "streaming\n", __func__,  num * size);
234
235         for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
236                 stream->buf_list[stream->buf_num] = usb_alloc_coherent(
237                                 stream->udev, size, GFP_ATOMIC,
238                                 &stream->dma_addr[stream->buf_num]);
239                 if (!stream->buf_list[stream->buf_num]) {
240                         dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n",
241                                         __func__, stream->buf_num);
242                         usb_free_stream_buffers(stream);
243                         return -ENOMEM;
244                 }
245
246                 dev_dbg(&stream->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
247                                 __func__, stream->buf_num,
248                                 stream->buf_list[stream->buf_num],
249                                 (long long)stream->dma_addr[stream->buf_num]);
250                 memset(stream->buf_list[stream->buf_num], 0, size);
251                 stream->state |= USB_STATE_URB_BUF;
252         }
253
254         return 0;
255 }
256
257 int usb_urb_reconfig(struct usb_data_stream *stream,
258                 struct usb_data_stream_properties *props)
259 {
260         int buf_size;
261
262         if (!props)
263                 return 0;
264
265         /* check allocated buffers are large enough for the request */
266         if (props->type == USB_BULK) {
267                 buf_size = stream->props.u.bulk.buffersize;
268         } else if (props->type == USB_ISOC) {
269                 buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb;
270         } else {
271                 dev_err(&stream->udev->dev, "%s: invalid endpoint type=%d\n",
272                                 KBUILD_MODNAME, props->type);
273                 return -EINVAL;
274         }
275
276         if (stream->buf_num < props->count || stream->buf_size < buf_size) {
277                 dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \
278                                 "allocated buffers are too small\n",
279                                 KBUILD_MODNAME);
280                 return -EINVAL;
281         }
282
283         /* check if all fields are same */
284         if (stream->props.type == props->type &&
285                         stream->props.count == props->count &&
286                         stream->props.endpoint == props->endpoint) {
287                 if (props->type == USB_BULK &&
288                                 props->u.bulk.buffersize ==
289                                 stream->props.u.bulk.buffersize)
290                         return 0;
291                 else if (props->type == USB_ISOC &&
292                                 props->u.isoc.framesperurb ==
293                                 stream->props.u.isoc.framesperurb &&
294                                 props->u.isoc.framesize ==
295                                 stream->props.u.isoc.framesize &&
296                                 props->u.isoc.interval ==
297                                 stream->props.u.isoc.interval)
298                         return 0;
299         }
300
301         dev_dbg(&stream->udev->dev, "%s: re-alloc urbs\n", __func__);
302
303         usb_urb_free_urbs(stream);
304         memcpy(&stream->props, props, sizeof(*props));
305         if (props->type == USB_BULK)
306                 return usb_urb_alloc_bulk_urbs(stream);
307         else if (props->type == USB_ISOC)
308                 return usb_urb_alloc_isoc_urbs(stream);
309
310         return 0;
311 }
312
313 int usb_urb_initv2(struct usb_data_stream *stream,
314                 const struct usb_data_stream_properties *props)
315 {
316         int ret;
317
318         if (!stream || !props)
319                 return -EINVAL;
320
321         memcpy(&stream->props, props, sizeof(*props));
322
323         if (!stream->complete) {
324                 dev_err(&stream->udev->dev, "%s: there is no data callback - " \
325                                 "this doesn't make sense\n", KBUILD_MODNAME);
326                 return -EINVAL;
327         }
328
329         switch (stream->props.type) {
330         case USB_BULK:
331                 ret = usb_alloc_stream_buffers(stream, stream->props.count,
332                                 stream->props.u.bulk.buffersize);
333                 if (ret < 0)
334                         return ret;
335
336                 return usb_urb_alloc_bulk_urbs(stream);
337         case USB_ISOC:
338                 ret = usb_alloc_stream_buffers(stream, stream->props.count,
339                                 stream->props.u.isoc.framesize *
340                                 stream->props.u.isoc.framesperurb);
341                 if (ret < 0)
342                         return ret;
343
344                 return usb_urb_alloc_isoc_urbs(stream);
345         default:
346                 dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \
347                                 "transfer\n", KBUILD_MODNAME);
348                 return -EINVAL;
349         }
350 }
351
352 int usb_urb_exitv2(struct usb_data_stream *stream)
353 {
354         usb_urb_free_urbs(stream);
355         usb_free_stream_buffers(stream);
356
357         return 0;
358 }