Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 330574
b: refs/heads/master
c: bce1c02
h: refs/heads/master
v: v3
  • Loading branch information
Antti Palosaari authored and Mauro Carvalho Chehab committed Aug 4, 2012
1 parent 55231ec commit 7bee948
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 75 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 05752890411cee29464f4edc5e2f1bb904679f5b
refs/heads/master: bce1c0290270fbc8c18414de4cbdb035521230d6
3 changes: 2 additions & 1 deletion trunk/drivers/media/dvb/dvb-usb/dvb_usb_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ extern int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff);
extern int usb_urb_init(struct usb_data_stream *stream,
struct usb_data_stream_properties *props);
extern int usb_urb_exit(struct usb_data_stream *stream);
extern int usb_urb_submit(struct usb_data_stream *stream);
extern int usb_urb_submit(struct usb_data_stream *stream,
struct usb_data_stream_properties *props);
extern int usb_urb_kill(struct usb_data_stream *stream);

extern int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/media/dvb/dvb-usb/dvb_usb_dvb.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
*/
if (adap->feedcount == onoff && adap->feedcount > 0) {
deb_ts("submitting all URBs\n");
usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
usb_urb_submit(&adap->fe_adap[adap->active_fe].stream, NULL);

deb_ts("controlling pid parser\n");
if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
Expand Down
220 changes: 148 additions & 72 deletions trunk/drivers/media/dvb/dvb-usb/usb_urb.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include "dvb_usb_common.h"

/* URB stuff for streaming */

int usb_urb_reconfig(struct usb_data_stream *stream,
struct usb_data_stream_properties *props);

static void usb_urb_complete(struct urb *urb)
{
struct usb_data_stream *stream = urb->context;
Expand Down Expand Up @@ -79,9 +83,17 @@ int usb_urb_kill(struct usb_data_stream *stream)
return 0;
}

int usb_urb_submit(struct usb_data_stream *stream)
int usb_urb_submit(struct usb_data_stream *stream,
struct usb_data_stream_properties *props)
{
int i, ret;

if (props) {
ret = usb_urb_reconfig(stream, props);
if (ret < 0)
return ret;
}

for (i = 0; i < stream->urbs_initialized; i++) {
deb_ts("submitting URB no. %d\n", i);
ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC);
Expand All @@ -96,75 +108,43 @@ int usb_urb_submit(struct usb_data_stream *stream)
return 0;
}

static int usb_free_stream_buffers(struct usb_data_stream *stream)
int usb_urb_free_urbs(struct usb_data_stream *stream)
{
if (stream->state & USB_STATE_URB_BUF) {
while (stream->buf_num) {
stream->buf_num--;
deb_mem("freeing buffer %d\n", stream->buf_num);
usb_free_coherent(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num],
stream->dma_addr[stream->buf_num]);
}
}

stream->state &= ~USB_STATE_URB_BUF;

return 0;
}

static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num,
unsigned long size)
{
stream->buf_num = 0;
stream->buf_size = size;
int i;

deb_mem("all in all I will use %lu bytes for streaming\n", num * size);
usb_urb_kill(stream);

for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
deb_mem("allocating buffer %d\n", stream->buf_num);
stream->buf_list[stream->buf_num] = usb_alloc_coherent(
stream->udev, size, GFP_ATOMIC,
&stream->dma_addr[stream->buf_num]);
if (stream->buf_list[stream->buf_num] == NULL) {
deb_mem("not enough memory for urb-buffer" \
" allocation.\n");
usb_free_stream_buffers(stream);
return -ENOMEM;
for (i = 0; i < stream->urbs_initialized; i++) {
if (stream->urb_list[i] != NULL) {
deb_mem("freeing URB no. %d.\n", i);
pr_debug("%s: free URB=%d\n", __func__, i);
/* free the URBs */
usb_free_urb(stream->urb_list[i]);
}
deb_mem("buffer %d: %p (dma: %llu)\n",
stream->buf_num,
stream->buf_list[stream->buf_num],
(long long)stream->dma_addr[stream->buf_num]);
memset(stream->buf_list[stream->buf_num], 0, size);
stream->state |= USB_STATE_URB_BUF;
}
deb_mem("allocation successful\n");
stream->urbs_initialized = 0;

return 0;
}

static int usb_bulk_urb_init(struct usb_data_stream *stream)
static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream)
{
int i, j;

i = usb_allocate_stream_buffers(stream, stream->props.count,
stream->props.u.bulk.buffersize);
if (i < 0)
return i;

/* allocate the URBs */
for (i = 0; i < stream->props.count; i++) {
pr_debug("%s: alloc URB=%d\n", __func__, i);
stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
if (!stream->urb_list[i]) {
deb_mem("not enough memory for urb_alloc_urb!.\n");
for (j = 0; j < i; j++)
usb_free_urb(stream->urb_list[j]);
return -ENOMEM;
}
usb_fill_bulk_urb(stream->urb_list[i], stream->udev,
usb_fill_bulk_urb(stream->urb_list[i],
stream->udev,
usb_rcvbulkpipe(stream->udev,
stream->props.endpoint),
stream->props.endpoint),
stream->buf_list[i],
stream->props.u.bulk.buffersize,
usb_urb_complete, stream);
Expand All @@ -176,21 +156,15 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
return 0;
}

static int usb_isoc_urb_init(struct usb_data_stream *stream)
static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
{
int i, j;

i = usb_allocate_stream_buffers(stream, stream->props.count,
stream->props.u.isoc.framesize *
stream->props.u.isoc.framesperurb);
if (i < 0)
return i;

/* allocate the URBs */
for (i = 0; i < stream->props.count; i++) {
struct urb *urb;
int frame_offset = 0;

pr_debug("%s: alloc URB=%d\n", __func__, i);
stream->urb_list[i] = usb_alloc_urb(
stream->props.u.isoc.framesperurb, GFP_ATOMIC);
if (!stream->urb_list[i]) {
Expand All @@ -210,7 +184,8 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->interval = stream->props.u.isoc.interval;
urb->number_of_packets = stream->props.u.isoc.framesperurb;
urb->transfer_buffer_length = stream->buf_size;
urb->transfer_buffer_length = stream->props.u.isoc.framesize *
stream->props.u.isoc.framesperurb;
urb->transfer_buffer = stream->buf_list[i];
urb->transfer_dma = stream->dma_addr[i];

Expand All @@ -226,9 +201,110 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
return 0;
}

int usb_free_stream_buffers(struct usb_data_stream *stream)
{
if (stream->state & USB_STATE_URB_BUF) {
while (stream->buf_num) {
stream->buf_num--;
deb_mem("freeing buffer %d\n", stream->buf_num);
usb_free_coherent(stream->udev, stream->buf_size,
stream->buf_list[stream->buf_num],
stream->dma_addr[stream->buf_num]);
}
}

stream->state &= ~USB_STATE_URB_BUF;

return 0;
}

int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
unsigned long size)
{
stream->buf_num = 0;
stream->buf_size = size;

deb_mem("all in all I will use %lu bytes for streaming\n", num * size);

for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
deb_mem("allocating buffer %d\n", stream->buf_num);
stream->buf_list[stream->buf_num] = usb_alloc_coherent(
stream->udev, size, GFP_ATOMIC,
&stream->dma_addr[stream->buf_num]);
if (stream->buf_list[stream->buf_num] == NULL) {
deb_mem("not enough memory for urb-buffer" \
" allocation.\n");
usb_free_stream_buffers(stream);
return -ENOMEM;
}
deb_mem("buffer %d: %p (dma: %llu)\n",
stream->buf_num,
stream->buf_list[stream->buf_num],
(long long)stream->dma_addr[stream->buf_num]);
memset(stream->buf_list[stream->buf_num], 0, size);
stream->state |= USB_STATE_URB_BUF;
}
deb_mem("allocation successful\n");

return 0;
}

int usb_urb_reconfig(struct usb_data_stream *stream,
struct usb_data_stream_properties *props)
{
int buf_size;

if (props == NULL)
return 0;

/* check allocated buffers are large enough for the request */
if (props->type == USB_BULK)
buf_size = stream->props.u.bulk.buffersize;
else if (props->type == USB_ISOC)
buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb;
else
return -EINVAL;

if (stream->buf_num < props->count || stream->buf_size < buf_size) {
err("cannot reconfigure as allocated buffers are too small");
return -EINVAL;
}

/* check if all fields are same */
if (stream->props.type == props->type &&
stream->props.count == props->count &&
stream->props.endpoint == props->endpoint) {
if (props->type == USB_BULK &&
props->u.bulk.buffersize ==
stream->props.u.bulk.buffersize)
return 0;
else if (props->type == USB_ISOC &&
props->u.isoc.framesperurb ==
stream->props.u.isoc.framesperurb &&
props->u.isoc.framesize ==
stream->props.u.isoc.framesize &&
props->u.isoc.interval ==
stream->props.u.isoc.interval)
return 0;
}

pr_debug("%s: re-alloc URBs\n", __func__);

usb_urb_free_urbs(stream);
memcpy(&stream->props, props, sizeof(*props));
if (props->type == USB_BULK)
return usb_urb_alloc_bulk_urbs(stream);
else if (props->type == USB_ISOC)
return usb_urb_alloc_isoc_urbs(stream);

return 0;
}

int usb_urb_init(struct usb_data_stream *stream,
struct usb_data_stream_properties *props)
{
int ret;

if (stream == NULL || props == NULL)
return -EINVAL;

Expand All @@ -244,9 +320,20 @@ int usb_urb_init(struct usb_data_stream *stream,

switch (stream->props.type) {
case USB_BULK:
return usb_bulk_urb_init(stream);
ret = usb_alloc_stream_buffers(stream, stream->props.count,
stream->props.u.bulk.buffersize);
if (ret < 0)
return ret;

return usb_urb_alloc_bulk_urbs(stream);
case USB_ISOC:
return usb_isoc_urb_init(stream);
ret = usb_alloc_stream_buffers(stream, stream->props.count,
stream->props.u.isoc.framesize *
stream->props.u.isoc.framesperurb);
if (ret < 0)
return ret;

return usb_urb_alloc_isoc_urbs(stream);
default:
err("unknown URB-type for data transfer.");
return -EINVAL;
Expand All @@ -255,19 +342,8 @@ int usb_urb_init(struct usb_data_stream *stream,

int usb_urb_exit(struct usb_data_stream *stream)
{
int i;

usb_urb_kill(stream);

for (i = 0; i < stream->urbs_initialized; i++) {
if (stream->urb_list[i] != NULL) {
deb_mem("freeing URB no. %d.\n", i);
/* free the URBs */
usb_free_urb(stream->urb_list[i]);
}
}
stream->urbs_initialized = 0;

usb_urb_free_urbs(stream);
usb_free_stream_buffers(stream);

return 0;
}

0 comments on commit 7bee948

Please sign in to comment.