[3-11] update dvb subsystem core
PATCH 1/1 [3-11] update dvb subsystem core
Hello,
this patch updates the dvb subsystem core.
Fixed problems:
- partly reintroduced the DVB_DEVFS_ONLY switch, which was previously wiped out by Alan Cox: if enabled, some really obscure code is not compiled into the kernel that is necessary to xxx
- switched from user-land types like __u8 to u8 and uint16_t to u16 this makes the patch rather large.
- updated the dvr (digital videorecording) facility
- renamed some structures, like "struct dmxdev_s" to "struct dmxdev"
- introduced dvb_functions.[ch], where some linux-kernel specific functions are encapsulated. by this, the dvb subsystem stays quite independent from deeper linux kernel functions.
- moved dvb_usercopy() to dvb_functions.c -- this is essentially video_usercopy() which should be generic_usercopy() instead... ;-)
- Made the dvb-core in dvbdev.c work with devfs again. I had to introduce some #if KERNELVERSION magic again here, sorry. I'll fix it up with the next patchset.
Please review and apply.
Thanks
Michael Hunold.
drivers/media/dvb/Makefile +1 -1
@@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ # ttusb-budget/ +obj-y := dvb-core/ frontends/ ttpci/ # ttusb-dec/ ttusb-budget/
drivers/media/dvb/dvb-core/Kconfig +10 -0
@@ -5,3 +5,13 @@ DVB core utility functions for device handling, software fallbacks etc. Say Y when you have a DVB card and want to use it. If unsure say N. + +config DVB_DEVFS_ONLY + bool "devfs only" + depends on DVB_CORE=y && DEVFS_FS + help + If you rely completly on devfs, you can drop support for the old + major/minor device scheme. This omits some really awkward lines of + code and saves some space in your kernel image. + + But as always: If unsure say N.
drivers/media/dvb/dvb-core/Makefile +1 -1
@@ -3,6 +3,6 @@ # dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o + dvb_functions.o dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o
drivers/media/dvb/dvb-core/demux.h +16 -28
100 lines not on this page · raw message
drivers/media/dvb/dvb-core/dmxdev.c +17 -19
@@ -21,22 +21,20 @@* */ +#include <asm/uaccess.h> +#include <asm/system.h> +#include <linux/spinlock.h> +#include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/module.h> +#include <linux/sched.h> #include <linux/poll.h> -#include <asm/uaccess.h> +#include <linux/ioctl.h> +#include <linux/wait.h> #include "dmxdev.h" +#include "dvb_functions.h" -#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,5 ,51 ) -#include "compat.h" -#endif - -//MODULE_DESCRIPTION(""); -//MODULE_AUTHOR("Ralph Metzler, Marcus Metzler"); -//#ifdef MODULE_LICENSE -//MODULE_LICENSE("GPL"); -//#endif MODULE_PARM (debug,"i" );static int debug =0 ;
@@ -483,7 +481,7 @@ {int i;dmxdev_t *dmxdev = filter->dev; -uint16_t pid = filter->params.sec.pid; +u16 pid = filter->params.sec.pid;for (i=0 ; i<dmxdev->filternum; i++) if (dmxdev->filter[i].state>=DMXDEV_STATE_GO &&
@@ -959,7 +957,7 @@ ret=-EINVAL ;break ; } - dmxdev->demux->get_pes_pids (dmxdev->demux, (uint16_t *)parg); + dmxdev->demux->get_pes_pids (dmxdev->demux, (u16 *)parg);break ;case DMX_GET_STC :
@@ -999,7 +997,8 @@poll_wait (file, &dmxdevfilter->buffer.queue, wait);if (dmxdevfilter->state !=DMXDEV_STATE_GO && - dmxdevfilter->state !=DMXDEV_STATE_DONE ) + dmxdevfilter->state !=DMXDEV_STATE_DONE && + dmxdevfilter->state !=DMXDEV_STATE_TIMEDOUT )return 0 ;if (dmxdevfilter->buffer.error)
@@ -1103,7 +1106,8 @@ .poll = dvb_dvr_poll, }; -static struct dvb_device dvbdev_dvr = { +static +struct dvb_device dvbdev_dvr = { .priv =0 , .users =1 , .writers =1 ,
@@ -1125,9 +1129,10 @@ dmxdev->dvr=vmalloc (dmxdev->filternum*sizeof (dmxdev_dvr_t));if (!dmxdev->dvr) {vfree (dmxdev->filter); - dmxdev->filter=0 ; + dmxdev->filter =NULL ;return -ENOMEM ; } +sema_init (&dmxdev->mutex,1 );spin_lock_init (&dmxdev->lock);for (i=0 ; i<dmxdev->filternum; i++) {
@@ -1143,8 +1149,7 @@dvb_register_device (dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev,DVB_DEVICE_DVR );dvb_dmxdev_buffer_init (&dmxdev->dvr_buffer); -/* fixme: is this correct? */ -try_module_get (THIS_MODULE ); +return 0 ; }
@@ -1162,8 +1169,6 @@ dmxdev->dvr=0 ; } dmxdev->demux->close (dmxdev->demux); -/* fixme: is this correct? */ -module_put (THIS_MODULE ); }
drivers/media/dvb/dvb-core/dmxdev.h +19 -19
@@ -24,16 +24,16 @@#ifndef _DMXDEV_H_#define _DMXDEV_H_ -#ifndef __KERNEL__ -#define __KERNEL__ -#endif - -#include <linux/dvb/dmx.h> - -#include <linux/version.h> +#include <asm/types.h> +#include <asm/semaphore.h> +#include <linux/spinlock.h> +#include <linux/kernel.h> +#include <linux/timer.h> #include <linux/wait.h> -#include <linux/types.h> #include <linux/fs.h> +#include <linux/string.h> + +#include <linux/dvb/dmx.h> #include "dvbdev.h" #include "demux.h"
@@ -53,17 +53,17 @@DMXDEV_STATE_TIMEDOUT } dmxdev_state_t; -typedef struct dmxdev_buffer_s { -uint8_t *data; -uint32_t size; -int32_t pread; -int32_t pwrite; +typedef struct dmxdev_buffer { +u8 *data; +int size; +int pread; +int pwrite;wait_queue_head_t queue;int error; }dmxdev_buffer_t ; -typedef struct dmxdev_filter_s { +typedef struct dmxdev_filter { struct dvb_device *dvbdev; union {
@@ -82,7 +82,7 @@int type;dmxdev_state_t state; -struct dmxdev_s *dev; +struct dmxdev *dev;dmxdev_buffer_t buffer;struct semaphore mutex;
@@ -90,20 +90,20 @@// only for sections struct timer_list timer;int todo; -uint8_t secheader[3 ]; +u8 secheader[3 ];u16 pid; } dmxdev_filter_t; -typedef struct dmxdev_dvr_s { +typedef struct dmxdev_dvr {int state; -struct dmxdev_s *dev; +struct dmxdev *dev;dmxdev_buffer_t buffer; }dmxdev_dvr_t ; -typedef struct dmxdev_s { +typedef struct dmxdev { struct dvb_device *dvbdev; struct dvb_device *dvr_dvbdev;
drivers/media/dvb/dvb-core/dvb_demux.c +46 -70
284 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_demux.h +6 -0
@@ -26,7 +26,9 @@#define _DVB_DEMUX_H_#include <asm/semaphore.h> +#include <linux/time.h> #include <linux/timer.h> +#include <linux/spinlock.h> #include "demux.h"
@@ -140,4 +142,8 @@void dvb_dmx_swfilter_packets (struct dvb_demux *dvbdmx,const u8 *buf,size_t count);void dvb_dmx_swfilter (struct dvb_demux *demux,const u8 *buf,size_t count); +int dvbdmx_connect_frontend (dmx_demux_t *demux,dmx_frontend_t *frontend); +int dvbdmx_disconnect_frontend (dmx_demux_t *demux); +#endif /* _DVB_DEMUX_H_ */ +
drivers/media/dvb/dvb-core/dvb_filter.c +27 -25
149 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_filter.h +39 -40
139 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_frontend.c +16 -28
98 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_functions.c +99 -0
99 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_functions.h +29 -0
@@ -0,0 +1,29 @@ +#ifndef __DVB_FUNCTIONS_H__ +#define __DVB_FUNCTIONS_H__ + +/** +* a sleeping delay function, waits i ms +* +*/ +static inline +void dvb_delay (int i) +{ + current->state=TASK_INTERRUPTIBLE ; +schedule_timeout ((HZ *i)/1000 ); +} + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefull become +generic_usercopy() someday... */ + +extern int dvb_usercopy (struct inode *inode,struct file *file, +unsigned int cmd,unsigned long arg, +int (*func)(struct inode *inode,struct file *file, +unsigned int cmd,void *arg)); + +extern void dvb_kernel_thread_setup (const char *thread_name); + +#include "dvb_compat.h" + +#endif +
drivers/media/dvb/dvb-core/dvb_i2c.c +4 -5
@@ -19,16 +19,15 @@* Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +#include <asm/semaphore.h> +#include <asm/errno.h> #include <linux/slab.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/version.h> - -#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,5 ,51 ) -#include "compat.h" -#endif #include "dvb_i2c.h" +#include "dvb_functions.h" +struct dvb_i2c_device {struct list_head list_head;
drivers/media/dvb/dvb-core/dvb_ksyms.c +9 -68
91 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvb_net.c +7 -4
@@ -24,15 +24,18 @@* */ +#include <asm/errno.h> #include <asm/uaccess.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/ioctl.h> +#include <linux/slab.h> #include <linux/dvb/net.h> +#include "dvb_demux.h" #include "dvb_net.h" - -#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,5 ,51 ) -#include "compat.h" -#endif +#include "dvb_functions.h" #define DVB_NET_MULTICAST_MAX 10
drivers/media/dvb/dvb-core/dvb_ringbuffer.c +4 -3
@@ -32,10 +32,12 @@#define __KERNEL_SYSCALLS__ +#include <asm/uaccess.h> +#include <asm/errno.h> #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/module.h> -#include <asm/uaccess.h> +#include <linux/sched.h> +#include <linux/string.h> #include "dvb_ringbuffer.h"
@@ -50,7 +52,6 @@init_waitqueue_head (&rbuf->queue);spin_lock_init (&(rbuf->lock)); - rbuf->lock=SPIN_LOCK_UNLOCKED ; }
drivers/media/dvb/dvb-core/dvb_ringbuffer.h +3 -0
@@ -32,6 +32,9 @@ #ifndef _DVB_RINGBUFFER_H_ #define _DVB_RINGBUFFER_H_ +#include <linux/spinlock.h> +#include <linux/wait.h> + typedef struct dvb_ringbuffer { u8 *data;
drivers/media/dvb/dvb-core/dvbdev.c +76 -32
198 lines not on this page · raw message
drivers/media/dvb/dvb-core/dvbdev.h +4 -6
@@ -24,9 +24,9 @@#ifndef _DVBDEV_H_#define _DVBDEV_H_ -#include <linux/types.h> -#include <linux/version.h> +#include <asm/types.h> #include <linux/poll.h> +#include <linux/fs.h> #include <linux/devfs_fs_kernel.h> #include <linux/list.h>
@@ -45,6 +45,7 @@struct dvb_adapter {int num; +devfs_handle_t devfs_handle;struct list_head list_head;struct list_head device_list;const char *name;
@@ -54,6 +55,7 @@struct dvb_device {struct list_head list_head;struct file_operations *fops; +devfs_handle_t devfs_handle;struct dvb_adapter *adapter;int type;u32 id;
@@ -84,9 +86,5 @@extern int dvb_generic_release (struct inode *inode,struct file *file);extern int dvb_generic_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg); -int dvb_usercopy (struct inode *inode,struct file *file, -unsigned int cmd,unsigned long arg, -int (*func)(struct inode *inode,struct file *file, -unsigned int cmd,void *arg));#endif /* #ifndef _DVBDEV_H_ */
Quoted 8 lines · Michael Hunold
Hello,
this patch updates the dvb subsystem core.
Fixed problems:
- partly reintroduced theDVB_DEVFS_ONLYswitch, which was previously wiped out by Alan Cox: if enabled, some really obscure code is not compiled into the kernel that is necessary to xxx
No, this is wrong. I did remove it not Alan Cox and I removed it because kernel 2.5/2.6 should not behave differently whether devfs is used or not except nodes showing up in devfs.
drivers/media/dvb/dvb-core/dmxdev.c line 1152
Quoted 3 lines
drivers/media/dvb/dvb-core/dmxdev.c +1
-2-/* fixme: is this correct? */ -try_module_get (THIS_MODULE ); +
Just removing this makes the code even more incorrect. You need to add a ->owner member and call try_module_get on it before calling into the module (and handle the return value..)
drivers/media/dvb/dvb-core/dmxdev.h line 103
Quoted 7 lines
drivers/media/dvb/dvb-core/dmxdev.h +2
-2-typedef struct dmxdev_dvr_s { +typedef struct dmxdev_dvr {int state; -struct dmxdev_s *dev; +struct dmxdev *dev;dmxdev_buffer_t buffer; }dmxdev_dvr_t ;
Once you rename everything you can nuke the typedef crap aswel..
and your devfs stuff is a mess. I already told one of the DVB folks (it wasn't you IIRC) that I'll publish a 2.5 devfs API on 2.4 header. But first I have to fix the devfs API on 2.5 and randomly bringing back old crap and lots of ifdefs in those changing areas won't help.
What the problem with 2.5, dvb and devfs?
Hello Christoph,
Quoted 1 line
What the problem with 2.5, dvb and devfs?
The main problem is that our development "dvb-kernel" CVS tree *should* compile under 2.4 aswell, because most of the dvb-users don't want to participate in kernel development in general, but only on the development of the dvb subsystem. So work is done on the "dvb-kernel" tree, which should be synced with the 2.5 kernel frequently.
So, regarding devfs, I introduced #ifdefs around the functions that have changed recently. That's not nice, I know. But in my eyes it's important to keep the CVS and the kernel version more in sync.
IIRC Gerd Knorr has the same problems with his driver packages (regarding the i2c subsystem mainly), but he has written some perl scripts to remove the #ifdef stuff before submitting his patches...
Quoted 2 lines
I already told one of the DVB folks
(it wasn't you IIRC) that I'll publish a 2.5 devfs API on 2.4 header.
No, you spoke to Holger I think, who has maintained the dvb-core kernel submissions before me.
Quoted 2 lines
But first I have to fix the devfs API on 2.5 and randomly bringing back old crap and lots of ifdefs in those changing areas won't help.
I understand. But delaying the dvb updates just because a few calls to the devfs subsystem (which are now separated by #ifdefs and can easily be found) is not a good option either, or is it?
CU
Michael.
Hello Christoph,
Quoted 8 lines
Quoted 3 lines
- partly reintroduced the
DVB_DEVFS_ONLYswitch, which was previously wiped out by Alan Cox: if enabled, some really obscure code is not compiled into the kernel that is necessary to xxxNo, this is wrong. I did remove it not Alan Cox and I removed it because kernel 2.5/2.6 should not behave differently whether devfs is used or not except nodes showing up in devfs.
The code does not behave differently. If DVB_DEVFS_ONLY is set, then the old chardev register interface is omitted.
We use the dvb subsystem on set-top-boxes where devfs is present only. The DVB_DEVFS_ONLY switch then lets us save some bytes and skips the "map-minor-to-actual-device" function stuff.
Quoted 8 lines
drivers/media/dvb/dvb-core/dmxdev.c line 1152
Quoted 3 lines
drivers/media/dvb/dvb-core/dmxdev.c +1
-2-/* fixme: is this correct? */ -try_module_get (THIS_MODULE ); +Just removing this makes the code even more incorrect. You need to add a ->owner member and call
try_module_geton it before calling into the module (and handle the return value..)
There is a functional dependency between the dvb-core and the actual dvb driver. So there is no need to increase the module count of the dvb-core if a new adapter is registered IMHO, because you cannot unload the dvb-core before the driver anyway.
Quoted 10 lines
Quoted 7 lines
drivers/media/dvb/dvb-core/dmxdev.h +2
-2-typedef struct dmxdev_dvr_s { +typedef struct dmxdev_dvr { int state; - struct dmxdev_s *dev; + struct dmxdev *dev; dmxdev_buffer_t buffer;}
dmxdev_dvr_t;Once you rename everything you can nuke the typedef crap aswel..
Thanks, added to the TODO list.
CU
Michael.
Quoted 9 lines · Michael Hunold
Hello Christoph,
Quoted 1 line
What the problem with 2.5, dvb and devfs?
The main problem is that our development "dvb-kernel" CVS tree *should* compile under 2.4 aswell, because most of the dvb-users don't want to participate in kernel development in general, but only on the development of the dvb subsystem. So work is done on the "dvb-kernel" tree, which should be synced with the 2.5 kernel frequently.
That okay in principle, but I'd like to ask you nicely to not touch any devfs-related stuff currently. I'ts in flux and any external change makes my life in cleaning up the mess a lot harder.
Quoted 6 lines
Quoted 2 lines
But first I have to fix the devfs API on 2.5 and randomly bringing back old crap and lots of ifdefs in those changing areas won't help.
I understand. But delaying the dvb updates just because a few calls to the devfs subsystem (which are now separated by #ifdefs and can easily be found) is not a good option either, or is it?
I think it is :) Esepcially as you don't just add ifdefs (which give me lots of rejects and you much uglier code than just using the compat header I'll send to lkml once I'm done with the API changes) but you also change the code that's ifdefed for 2.5 to reverse change I did. There is a reason why I removed every occurance of devfs_handle_t from all drivers and the particular reason is that it will go away in the next series of patches.
Quoted 2 lines · Michael Hunold
The code does not behave differently. If
DVB_DEVFS_ONLYis set, then the old chardev register interface is omitted.
Which is a different behaviour, now you can't create a device node manually anymor. Also note that the feature you rely on here (devfs presetting file->private_data) will go away in the next round of patches, see Al Viro's patchit for a generic replacement that works with or without devfs.
Quoted 8 lines
Quoted 3 lines
Just removing this makes the code even more incorrect. You need to add a ->owner member and call
try_module_geton it before calling into the module (and handle the return value..)There is a functional dependency between the dvb-core and the actual dvb driver. So there is no need to increase the module count of the dvb-core if a new adapter is registered IMHO, because you cannot unload the dvb-core before the driver anyway.
Okay, you're right I should have read more of the code to get the global picture. You still wan't an owner field for at least struct dvb_device device, though - but the try_module_get must go into dvb_generic_open and maybe in more other places where you use the "backend" modules.
Hello Christoph,
Quoted 3 lines
That okay in principle, but I'd like to ask you nicely to not touch any devfs-related stuff currently. I'ts in flux and any external change makes my life in cleaning up the mess a lot harder.
The problem was that the devices disappeared. I did not realize that you did a typo and they were created at another place, though.
So I rewrote the code for both 2.4 and 2.5 and it worked again.
Quoted 9 lines
Quoted 1 line
I understand. But delaying the dvb updates just because a few calls to the devfs subsystem (which are now separated by #ifdefs and can easily be found) is not a good option either, or is it?
I think it is :) Esepcially as you don't just add ifdefs (which give me lots of rejects and you much uglier code than just using the compat header I'll send to lkml once I'm done with the API changes) but you also change the code that's ifdefed for 2.5 to reverse change I did. There is a reason why I removed every occurance of
devfs_handle_tfrom all drivers and the particular reason is that it will go away in the next series of patches.
Ok, I understand.
I promise that I don't touch the devfs related code anymore. But, how do we proceed in general?
Will the other patches be applied and who does that for which tree? Shall I resend the patches where you had objections?
CU
Michael.
Hello Christoph, Linus,
Quoted 4 lines
Quoted 1 line
The code does not behave differently. If
DVB_DEVFS_ONLYis set, then the old chardev register interface is omitted.Which is a different behaviour, now you can't create a device node manually anymor.
I won't insist on keeping code that I haven't written. My only point is that we use the code in set-top-boxes, where every byte is valuable. But
I suspect that there are numerous other places where we could safe
bytes... 8-)
Quoted 5 lines
Also note that the feature you rely on here (devfs
presettingfile->private_data) will go away in the next round of patches,
see Al Viro's patchit for a generic replacement that works with or without devfs.
Ok.
Quoted 6 lines
Quoted 1 line
There is a functional dependency between the dvb-core and the actual dvb driver. So there is no need to increase the module count of the dvb-core if a new adapter is registered IMHO, because you cannot unload the dvb-core before the driver anyway.
Okay, you're right I should have read more of the code to get the global picture. You still wan't an owner field for at least struct
dvb_devicedevice, though - but thetry_module_getmust go intodvb_generic_openand maybe in more other places where you use the "backend" modules.
I don't get that, sorry. The backend modules have functional dependencies and register/deregister upon loading/unloading. There is never a call from the dvb-core to the backend modules. Do I really need an owner field then?
CU
Michael.
Quoted 1 line · Michael Hunold
I promise that I don't touch the devfs related code anymore.
Oh, you can of course touch it again in future, I just want to finish the API transition first, I hope I'll be done by the end of this week.
Quoted 5 lines
But, how do
we proceed in general?Will the other patches be applied and who does that for which tree? Shall I resend the patches where you had objections?
As nothing got in yet I'd suggest resending everything, with Linus you sometimes may have to resend quite often anyway :)
Quoted 4 lines · Michael Hunold
I won't insist on keeping code that I haven't written. My only point is that we use the code in set-top-boxes, where every byte is valuable. But
I suspect that there are numerous other places where we could safe
bytes... 8-)
This code will go away soon for both the devfs and non-devfs case..
Quoted 9 lines
Quoted 4 lines
Okay, you're right I should have read more of the code to get the global picture. You still wan't an owner field for at least struct
dvb_devicedevice, though - but thetry_module_getmust go intodvb_generic_openand maybe in more other places where you use the "backend" modules.I don't get that, sorry. The backend modules have functional dependencies and register/deregister upon loading/unloading. There is never a call from the dvb-core to the backend modules. Do I really need an owner field then?
It doesn't have to be a call. Unless I completely misread the code your dvb core references struct dvb_adapter in certain cases. But struct dvb_adapter is allocated in the actual drivers so these could be unloaded and give you scrambled memory even when it's still in use.
So you need to acquire a reference on those backends whenever you touch any object that logically belongs to them.
Hello Christoph,
Quoted 3 lines
Oh, you can of course touch it again in future, I just want to finish the API transition first, I hope I'll be done by the end of this week.
Ok. (see below)
Quoted 5 lines
Quoted 2 lines
Will the other patches be applied and who does that for which tree? Shall I resend the patches where you had objections?
As nothing got in yet I'd suggest resending everything, with Linus you sometimes may have to resend quite often anyway :)
No problem. I'll change the stuff you suggested and resend it.
Last time I sent the patches through Alan Cox, who feeded them to Linus. It this better? Alan?
CU
Michael.
Quoted 4 lines · Michael Hunold
No problem. I'll change the stuff you suggested and resend it.
Last time I sent the patches through Alan Cox, who feeded them to Linus. It this better? Alan?
Well, if it worked I'd try it again..
Quoted 4 lines · Michael Hunold
No problem. I'll change the stuff you suggested and resend it.
Last time I sent the patches through Alan Cox, who feeded them to Linus. It this better? Alan?
Up to you.