Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 356969
b: refs/heads/master
c: 16427fa
h: refs/heads/master
i:
  356967: 4e23540
v: v3
  • Loading branch information
Julian Scheel authored and Mauro Carvalho Chehab committed Dec 4, 2012
1 parent 240fe55 commit 1d920cb
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 20 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: 6823627b933decf5842fcfc37cc71c549f56c6a2
refs/heads/master: 16427faf28674451a7a0485ab0a929402f355ffd
112 changes: 93 additions & 19 deletions trunk/drivers/media/usb/tm6000/tm6000-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@
#define TM6000_MIN_BUF 4
#define TM6000_DEF_BUF 8

#define TM6000_NUM_URB_BUF 8

#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */

/* Declare static vars that will be used as parameters */
static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */
static int keep_urb; /* keep urb buffers allocated */

/* Debug level */
int tm6000_debug;
Expand Down Expand Up @@ -537,6 +540,71 @@ static void tm6000_irq_callback(struct urb *urb)
urb->status);
}

/*
* Allocate URB buffers
*/
static int tm6000_alloc_urb_buffers(struct tm6000_core *dev)
{
int num_bufs = TM6000_NUM_URB_BUF;
int i;

if (dev->urb_buffer != NULL)
return 0;

dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
if (!dev->urb_buffer) {
tm6000_err("cannot allocate memory for urb buffers\n");
return -ENOMEM;
}

dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL);
if (!dev->urb_dma) {
tm6000_err("cannot allocate memory for urb dma pointers\n");
return -ENOMEM;
}

for (i = 0; i < num_bufs; i++) {
dev->urb_buffer[i] = usb_alloc_coherent(
dev->udev, dev->urb_size,
GFP_KERNEL, &dev->urb_dma[i]);
if (!dev->urb_buffer[i]) {
tm6000_err("unable to allocate %i bytes for transfer buffer %i\n",
dev->urb_size, i);
return -ENOMEM;
}
memset(dev->urb_buffer[i], 0, dev->urb_size);
}

return 0;
}

/*
* Free URB buffers
*/
static int tm6000_free_urb_buffers(struct tm6000_core *dev)
{
int i;

if (dev->urb_buffer == NULL)
return 0;

for (i = 0; i < TM6000_NUM_URB_BUF; i++) {
if (dev->urb_buffer[i]) {
usb_free_coherent(dev->udev,
dev->urb_size,
dev->urb_buffer[i],
dev->urb_dma[i]);
dev->urb_buffer[i] = NULL;
}
}
kfree(dev->urb_buffer);
kfree(dev->urb_dma);
dev->urb_buffer = NULL;
dev->urb_dma = NULL;

return 0;
}

/*
* Stop and Deallocate URBs
*/
Expand All @@ -551,18 +619,15 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
if (urb) {
usb_kill_urb(urb);
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->isoc_ctl.transfer_buffer[i],
urb->transfer_dma);
}
usb_free_urb(urb);
dev->isoc_ctl.urb[i] = NULL;
}
dev->isoc_ctl.transfer_buffer[i] = NULL;
}

if (!keep_urb)
tm6000_free_urb_buffers(dev);

kfree(dev->isoc_ctl.urb);
kfree(dev->isoc_ctl.transfer_buffer);

Expand All @@ -572,12 +637,13 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
}

/*
* Allocate URBs and start IRQ
* Assign URBs and start IRQ
*/
static int tm6000_prepare_isoc(struct tm6000_core *dev)
{
struct tm6000_dmaqueue *dma_q = &dev->vidq;
int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
int i, j, sb_size, pipe, size, max_packets;
int num_bufs = TM6000_NUM_URB_BUF;
struct urb *urb;

/* De-allocates all pending stuff */
Expand Down Expand Up @@ -605,6 +671,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)

max_packets = TM6000_MAX_ISO_PACKETS;
sb_size = max_packets * size;
dev->urb_size = sb_size;

dev->isoc_ctl.num_bufs = num_bufs;

Expand All @@ -627,6 +694,17 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
max_packets, num_bufs, sb_size,
dev->isoc_in.maxsize, size);


if (!dev->urb_buffer && tm6000_alloc_urb_buffers(dev) < 0) {
tm6000_err("cannot allocate memory for urb buffers\n");

/* call free, as some buffers might have been allocated */
tm6000_free_urb_buffers(dev);
kfree(dev->isoc_ctl.urb);
kfree(dev->isoc_ctl.transfer_buffer);
return -ENOMEM;
}

/* allocate urbs and transfer buffers */
for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
urb = usb_alloc_urb(max_packets, GFP_KERNEL);
Expand All @@ -638,17 +716,8 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
}
dev->isoc_ctl.urb[i] = urb;

dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
sb_size, GFP_KERNEL, &urb->transfer_dma);
if (!dev->isoc_ctl.transfer_buffer[i]) {
tm6000_err("unable to allocate %i bytes for transfer"
" buffer %i%s\n",
sb_size, i,
in_interrupt() ? " while in int" : "");
tm6000_uninit_isoc(dev);
return -ENOMEM;
}
memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
urb->transfer_dma = dev->urb_dma[i];
dev->isoc_ctl.transfer_buffer[i] = dev->urb_buffer[i];

usb_fill_bulk_urb(urb, dev->udev, pipe,
dev->isoc_ctl.transfer_buffer[i], sb_size,
Expand Down Expand Up @@ -1826,6 +1895,9 @@ int tm6000_v4l2_unregister(struct tm6000_core *dev)
{
video_unregister_device(dev->vfd);

/* if URB buffers are still allocated free them now */
tm6000_free_urb_buffers(dev);

if (dev->radio_dev) {
if (video_is_registered(dev->radio_dev))
video_unregister_device(dev->radio_dev);
Expand All @@ -1851,3 +1923,5 @@ MODULE_PARM_DESC(debug, "activates debug info");
module_param(vid_limit, int, 0644);
MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");

module_param(keep_urb, bool, 0);
MODULE_PARM_DESC(keep_urb, "Keep urb buffers allocated even when the device is closed by the user");
5 changes: 5 additions & 0 deletions trunk/drivers/media/usb/tm6000/tm6000.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ struct tm6000_core {

spinlock_t slock;

/* urb dma buffers */
char **urb_buffer;
dma_addr_t *urb_dma;
unsigned int urb_size;

unsigned long quirks;
};

Expand Down

0 comments on commit 1d920cb

Please sign in to comment.