Commit 6ddd89d0 authored by Frank Schaefer's avatar Frank Schaefer Committed by Mauro Carvalho Chehab

[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: default avatarFrank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent afb177e0
...@@ -3322,10 +3322,10 @@ static int em28xx_usb_probe(struct usb_interface *interface, ...@@ -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 @@ ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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); ...@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment