summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authorAlex Woods <devnull@localhost>2003-07-19 13:54:36 +0000
committerAlex Woods <devnull@localhost>2003-07-19 13:54:36 +0000
commitbece0ee41ada89cb339afdecf7501eec5883d189 (patch)
treeabf5d2213d45e3980b2355f9a45e7ba9cbe4cd43 /linux/drivers/media/dvb
parente3006e1f0c98f42f184647b569819771bb589ae8 (diff)
downloadmediapointer-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.c108
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h16
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