root/drivers/media/usb/dvb-usb-v2/usb_urb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usb_urb_complete
  2. usb_urb_killv2
  3. usb_urb_submitv2
  4. usb_urb_free_urbs
  5. usb_urb_alloc_bulk_urbs
  6. usb_urb_alloc_isoc_urbs
  7. usb_free_stream_buffers
  8. usb_alloc_stream_buffers
  9. usb_urb_reconfig
  10. usb_urb_initv2
  11. usb_urb_exitv2

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

/* [<][>][^][v][top][bottom][index][help] */