diff options
author | Alex Woods <devnull@localhost> | 2003-07-19 13:54:36 +0000 |
---|---|---|
committer | Alex Woods <devnull@localhost> | 2003-07-19 13:54:36 +0000 |
commit | bece0ee41ada89cb339afdecf7501eec5883d189 (patch) | |
tree | abf5d2213d45e3980b2355f9a45e7ba9cbe4cd43 /linux/drivers/media/dvb | |
parent | e3006e1f0c98f42f184647b569819771bb589ae8 (diff) | |
download | mediapointer-dvb-s2-bece0ee41ada89cb339afdecf7501eec5883d189.tar.gz mediapointer-dvb-s2-bece0ee41ada89cb339afdecf7501eec5883d189.tar.bz2 |
Hand off all processing of urb data to a tasklet
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c | 108 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h | 16 |
2 files changed, 92 insertions, 32 deletions
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c index dd3b5fc27..8759bf263 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -125,14 +125,10 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL); - if (!down_interruptible(&dec->pes2ts_sem)) { - dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], - ttusb_dec_av_pes2ts_cb, dec->demux.feed); - dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO], - ttusb_dec_av_pes2ts_cb, dec->demux.feed); - - up(&dec->pes2ts_sem); - } + dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], + ttusb_dec_av_pes2ts_cb, dec->demux.feed); + dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO], + ttusb_dec_av_pes2ts_cb, dec->demux.feed); } static int ttusb_dec_i2c_master_xfer(struct dvb_i2c_bus *i2c, @@ -151,7 +147,7 @@ static int ttusb_dec_i2c_master_xfer(struct dvb_i2c_bus *i2c, return 0; } -static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes, +static void ttusb_dec_process_av_pes(struct ttusb_dec *dec, u8 *av_pes, int length) { int i; @@ -197,14 +193,8 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes, memcpy(&dec->v_pes[dec->v_pes_length], &av_pes[12], prebytes); - if (!down_interruptible(&dec->pes2ts_sem)) { - dvb_filter_pes2ts(&dec->v_pes2ts, - dec->v_pes, - dec->v_pes_length + - prebytes); - - up(&dec->pes2ts_sem); - } + dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, + dec->v_pes_length + prebytes); } if (av_pes[5] & 0x10) { @@ -247,15 +237,9 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes, postbytes); memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); - if (postbytes == 0) { - if (!down_interruptible(&dec->pes2ts_sem)) { - dvb_filter_pes2ts(&dec->v_pes2ts, - dec->v_pes, - dec->v_pes_length); - - up(&dec->pes2ts_sem); - } - } + if (postbytes == 0) + dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, + dec->v_pes_length); break; } @@ -272,7 +256,7 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes, } } -static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b, +static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, int length) { while (length) { @@ -358,6 +342,31 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b, } } +static void ttusb_dec_process_urb_frame_list(unsigned long data) +{ + struct ttusb_dec *dec = (struct ttusb_dec *)data; + struct list_head *item; + struct urb_frame *frame; + unsigned long flags; + + while (1) { + spin_lock_irqsave(&dec->urb_frame_list_lock, flags); + if ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { + frame = list_entry(item, struct urb_frame, + urb_frame_list); + list_del(&frame->urb_frame_list); + } else { + spin_unlock_irqrestore(&dec->urb_frame_list_lock, + flags); + return; + } + spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags); + + ttusb_dec_process_urb_frame(dec, frame->data, frame->length); + kfree(frame); + } +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static void ttusb_dec_process_urb(struct urb *urb) #else @@ -373,12 +382,28 @@ static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs) struct usb_iso_packet_descriptor *d; u8 *b; int length; + struct urb_frame *frame; d = &urb->iso_frame_desc[i]; b = urb->transfer_buffer + d->offset; length = d->actual_length; - ttusb_dec_process_urb_frame(dec, b, length); + if ((frame = kmalloc(sizeof(struct urb_frame), + GFP_ATOMIC))) { + unsigned long flags; + + memcpy(frame->data, b, length); + frame->length = length; + + spin_lock_irqsave(&dec->urb_frame_list_lock, + flags); + list_add_tail(&frame->urb_frame_list, + &dec->urb_frame_list); + spin_unlock_irqrestore(&dec->urb_frame_list_lock, + flags); + + tasklet_schedule(&dec->urb_tasklet); + } } } else { /* -ENOENT is expected when unlinking urbs */ @@ -654,6 +679,14 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) return 0; } +static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) +{ + dec->urb_frame_list_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&dec->urb_frame_list); + tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list, + (unsigned long)dec); +} + static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) { dprintk("%s\n", __FUNCTION__); @@ -835,8 +868,6 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec) return result; } - sema_init(&dec->pes2ts_sem, 1); - dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx); return 0; @@ -869,6 +900,20 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec) ttusb_dec_free_iso_urbs(dec); } +static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec) +{ + struct list_head *item; + struct urb_frame *frame; + + tasklet_kill(&dec->urb_tasklet); + + while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { + frame = list_entry(item, struct urb_frame, urb_frame_list); + list_del(&frame->urb_frame_list); + kfree(frame); + } +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) @@ -893,6 +938,7 @@ static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum, ttusb_dec_init_stb(dec); ttusb_dec_init_dvb(dec); ttusb_dec_init_v_pes(dec); + ttusb_dec_init_tasklet(dec); return (void *)dec; } @@ -920,6 +966,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, ttusb_dec_init_stb(dec); ttusb_dec_init_dvb(dec); ttusb_dec_init_v_pes(dec); + ttusb_dec_init_tasklet(dec); usb_set_intfdata(intf, (void *)dec); ttusb_dec_set_streaming_interface(dec); @@ -942,6 +989,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) dprintk("%s\n", __FUNCTION__); + ttusb_dec_exit_tasklet(dec); ttusb_dec_exit_usb(dec); ttusb_dec_exit_dvb(dec); diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h index 7268803d2..db1c13f5e 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h +++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h @@ -22,7 +22,10 @@ #ifndef _TTUSB_DEC_H #define _TTUSB_DEC_H -#include "asm/semaphore.h" +#include <asm/semaphore.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/spinlock.h> #include "dmxdev.h" #include "dvb_demux.h" #include "dvb_filter.h" @@ -77,11 +80,20 @@ struct ttusb_dec { struct dvb_filter_pes2ts a_pes2ts; struct dvb_filter_pes2ts v_pes2ts; - struct semaphore pes2ts_sem; u8 v_pes[16 + MAX_AV_PES_LENGTH]; int v_pes_length; int v_pes_postbytes; + + struct list_head urb_frame_list; + struct tasklet_struct urb_tasklet; + spinlock_t urb_frame_list_lock; +}; + +struct urb_frame { + u8 data[ISO_FRAME_SIZE]; + int length; + struct list_head urb_frame_list; }; #endif |