[media] em28xx: create a common function for isoc and bulk URB allocation and setup
Rename the existing function for isoc transfers em28xx_init_isoc to em28xx_init_usb_xfer and extend it. URB allocation and setup is now done depending on the USB transfer type, which is selected with a new function parameter. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
afb177e065
commit
6ddd89d0c9
3 changed files with 60 additions and 49 deletions
|
@ -3322,10 +3322,10 @@ static int em28xx_usb_probe(struct usb_interface *interface,
|
||||||
|
|
||||||
if (has_dvb) {
|
if (has_dvb) {
|
||||||
/* pre-allocate DVB isoc transfer buffers */
|
/* pre-allocate DVB isoc transfer buffers */
|
||||||
retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE,
|
retval = em28xx_alloc_urbs(dev, EM28XX_DIGITAL_MODE, 0,
|
||||||
EM28XX_DVB_NUM_ISOC_PACKETS,
|
|
||||||
EM28XX_DVB_NUM_BUFS,
|
EM28XX_DVB_NUM_BUFS,
|
||||||
dev->dvb_max_pkt_size);
|
dev->dvb_max_pkt_size,
|
||||||
|
EM28XX_DVB_NUM_ISOC_PACKETS);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
goto unlock_and_free;
|
goto unlock_and_free;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
Markus Rechberger <mrechberger@gmail.com>
|
Markus Rechberger <mrechberger@gmail.com>
|
||||||
Mauro Carvalho Chehab <mchehab@infradead.org>
|
Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
Sascha Sommer <saschasommer@freenet.de>
|
Sascha Sommer <saschasommer@freenet.de>
|
||||||
|
Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -1035,10 +1036,10 @@ EXPORT_SYMBOL_GPL(em28xx_stop_urbs);
|
||||||
/*
|
/*
|
||||||
* Allocate URBs
|
* Allocate URBs
|
||||||
*/
|
*/
|
||||||
int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
|
||||||
int num_packets, int num_bufs, int max_pkt_size)
|
int num_bufs, int max_pkt_size, int packet_multiplier)
|
||||||
{
|
{
|
||||||
struct em28xx_usb_bufs *isoc_bufs;
|
struct em28xx_usb_bufs *usb_bufs;
|
||||||
int i;
|
int i;
|
||||||
int sb_size, pipe;
|
int sb_size, pipe;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
|
@ -1047,49 +1048,52 @@ int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
||||||
em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
|
em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
|
||||||
|
|
||||||
if (mode == EM28XX_DIGITAL_MODE)
|
if (mode == EM28XX_DIGITAL_MODE)
|
||||||
isoc_bufs = &dev->usb_ctl.digital_bufs;
|
usb_bufs = &dev->usb_ctl.digital_bufs;
|
||||||
else
|
else
|
||||||
isoc_bufs = &dev->usb_ctl.analog_bufs;
|
usb_bufs = &dev->usb_ctl.analog_bufs;
|
||||||
|
|
||||||
/* De-allocates all pending stuff */
|
/* De-allocates all pending stuff */
|
||||||
em28xx_uninit_usb_xfer(dev, mode);
|
em28xx_uninit_usb_xfer(dev, mode);
|
||||||
|
|
||||||
isoc_bufs->num_bufs = num_bufs;
|
usb_bufs->num_bufs = num_bufs;
|
||||||
|
|
||||||
isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
|
usb_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
|
||||||
if (!isoc_bufs->urb) {
|
if (!usb_bufs->urb) {
|
||||||
em28xx_errdev("cannot alloc memory for usb buffers\n");
|
em28xx_errdev("cannot alloc memory for usb buffers\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
|
usb_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!isoc_bufs->transfer_buffer) {
|
if (!usb_bufs->transfer_buffer) {
|
||||||
em28xx_errdev("cannot allocate memory for usb transfer\n");
|
em28xx_errdev("cannot allocate memory for usb transfer\n");
|
||||||
kfree(isoc_bufs->urb);
|
kfree(usb_bufs->urb);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
isoc_bufs->max_pkt_size = max_pkt_size;
|
usb_bufs->max_pkt_size = max_pkt_size;
|
||||||
isoc_bufs->num_packets = num_packets;
|
if (xfer_bulk)
|
||||||
|
usb_bufs->num_packets = 0;
|
||||||
|
else
|
||||||
|
usb_bufs->num_packets = packet_multiplier;
|
||||||
dev->usb_ctl.vid_buf = NULL;
|
dev->usb_ctl.vid_buf = NULL;
|
||||||
dev->usb_ctl.vbi_buf = NULL;
|
dev->usb_ctl.vbi_buf = NULL;
|
||||||
|
|
||||||
sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size;
|
sb_size = packet_multiplier * usb_bufs->max_pkt_size;
|
||||||
|
|
||||||
/* allocate urbs and transfer buffers */
|
/* allocate urbs and transfer buffers */
|
||||||
for (i = 0; i < isoc_bufs->num_bufs; i++) {
|
for (i = 0; i < usb_bufs->num_bufs; i++) {
|
||||||
urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL);
|
urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL);
|
||||||
if (!urb) {
|
if (!urb) {
|
||||||
em28xx_err("cannot alloc usb_ctl.urb %i\n", i);
|
em28xx_err("cannot alloc usb_ctl.urb %i\n", i);
|
||||||
em28xx_uninit_usb_xfer(dev, mode);
|
em28xx_uninit_usb_xfer(dev, mode);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
isoc_bufs->urb[i] = urb;
|
usb_bufs->urb[i] = urb;
|
||||||
|
|
||||||
isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
|
usb_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
|
||||||
sb_size, GFP_KERNEL, &urb->transfer_dma);
|
sb_size, GFP_KERNEL, &urb->transfer_dma);
|
||||||
if (!isoc_bufs->transfer_buffer[i]) {
|
if (!usb_bufs->transfer_buffer[i]) {
|
||||||
em28xx_err("unable to allocate %i bytes for transfer"
|
em28xx_err("unable to allocate %i bytes for transfer"
|
||||||
" buffer %i%s\n",
|
" buffer %i%s\n",
|
||||||
sb_size, i,
|
sb_size, i,
|
||||||
|
@ -1097,35 +1101,42 @@ int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
||||||
em28xx_uninit_usb_xfer(dev, mode);
|
em28xx_uninit_usb_xfer(dev, mode);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memset(isoc_bufs->transfer_buffer[i], 0, sb_size);
|
memset(usb_bufs->transfer_buffer[i], 0, sb_size);
|
||||||
|
|
||||||
/* FIXME: this is a hack - should be
|
if (xfer_bulk) { /* bulk */
|
||||||
'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
|
pipe = usb_rcvbulkpipe(dev->udev,
|
||||||
should also be using 'desc.bInterval'
|
mode == EM28XX_ANALOG_MODE ?
|
||||||
*/
|
EM28XX_EP_ANALOG :
|
||||||
|
EM28XX_EP_DIGITAL);
|
||||||
|
usb_fill_bulk_urb(urb, dev->udev, pipe,
|
||||||
|
usb_bufs->transfer_buffer[i], sb_size,
|
||||||
|
em28xx_irq_callback, dev);
|
||||||
|
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
|
||||||
|
} else { /* isoc */
|
||||||
pipe = usb_rcvisocpipe(dev->udev,
|
pipe = usb_rcvisocpipe(dev->udev,
|
||||||
mode == EM28XX_ANALOG_MODE ?
|
mode == EM28XX_ANALOG_MODE ?
|
||||||
EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
|
EM28XX_EP_ANALOG :
|
||||||
|
EM28XX_EP_DIGITAL);
|
||||||
usb_fill_int_urb(urb, dev->udev, pipe,
|
usb_fill_int_urb(urb, dev->udev, pipe,
|
||||||
isoc_bufs->transfer_buffer[i], sb_size,
|
usb_bufs->transfer_buffer[i], sb_size,
|
||||||
em28xx_irq_callback, dev, 1);
|
em28xx_irq_callback, dev, 1);
|
||||||
|
urb->transfer_flags = URB_ISO_ASAP |
|
||||||
urb->number_of_packets = isoc_bufs->num_packets;
|
URB_NO_TRANSFER_DMA_MAP;
|
||||||
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
|
|
||||||
|
|
||||||
k = 0;
|
k = 0;
|
||||||
for (j = 0; j < isoc_bufs->num_packets; j++) {
|
for (j = 0; j < usb_bufs->num_packets; j++) {
|
||||||
urb->iso_frame_desc[j].offset = k;
|
urb->iso_frame_desc[j].offset = k;
|
||||||
urb->iso_frame_desc[j].length =
|
urb->iso_frame_desc[j].length =
|
||||||
isoc_bufs->max_pkt_size;
|
usb_bufs->max_pkt_size;
|
||||||
k += isoc_bufs->max_pkt_size;
|
k += usb_bufs->max_pkt_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
urb->number_of_packets = usb_bufs->num_packets;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(em28xx_alloc_isoc);
|
EXPORT_SYMBOL_GPL(em28xx_alloc_urbs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate URBs and start IRQ
|
* Allocate URBs and start IRQ
|
||||||
|
@ -1155,8 +1166,8 @@ int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alloc) {
|
if (alloc) {
|
||||||
rc = em28xx_alloc_isoc(dev, mode, num_packets,
|
rc = em28xx_alloc_urbs(dev, mode, 0, num_bufs,
|
||||||
num_bufs, max_pkt_size);
|
max_pkt_size, num_packets);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -662,8 +662,8 @@ int em28xx_vbi_supported(struct em28xx *dev);
|
||||||
int em28xx_set_outfmt(struct em28xx *dev);
|
int em28xx_set_outfmt(struct em28xx *dev);
|
||||||
int em28xx_resolution_set(struct em28xx *dev);
|
int em28xx_resolution_set(struct em28xx *dev);
|
||||||
int em28xx_set_alternate(struct em28xx *dev);
|
int em28xx_set_alternate(struct em28xx *dev);
|
||||||
int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
|
||||||
int num_packets, int num_bufs, int max_pkt_size);
|
int num_bufs, int max_pkt_size, int packet_multiplier);
|
||||||
int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
|
||||||
int num_packets, int num_bufs, int max_pkt_size,
|
int num_packets, int num_bufs, int max_pkt_size,
|
||||||
int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
|
int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
|
||||||
|
|
Loading…
Add table
Reference in a new issue