Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usb_urb.c
Go to the documentation of this file.
1 /* usb-urb.c is part of the DVB USB library.
2  *
3  * Copyright (C) 2004-6 Patrick Boettcher ([email protected])
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  }
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,
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 
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 
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 
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 }