High resolution timer for cx88 remotes
PATCH 1/1 High resolution timer for cx88 remotes
Hi
Some remotes requires short polling interval which in modern kernels is below resolution of standard scheduler (schedule_delayed_work), this causes problem of missed keystrokes. One of the solutions is to raise kernel timer frequency, my proposition is to use high resolution timers which are present in kernel since 2.6.16 (at least API AFAIK). I have encountered this problem on my Winfast 2000XP Expert, but after checking cx88-input.c it seems that following cards can be affected also:WINFAST2000XP_EXPERTWINFAST_DTV1000WINFAST_TV2000_XP_GLOBALPROLINK_PLAYTVPVRPIXELVIEW_PLAYTV_ULTRA_PROPROLINK_PV_8000GTPROLINK_PV_GLOBAL_XTREMEKWORLD_LTV883MSI_TVANYWHERE_MASTER
Patched driver seems to work on my system, with kernel 2.6.28.
I have removed kernel checks for versions below 2.6.20 - they were because of API changes in scheduler.
I have not tested it on older kernels.
Regards
AH
linux/drivers/media/video/cx88/cx88-input.c Sat May 23 14:04:17 2009 +0200 renamed from linux/drivers/media/video/cx88/cx88-input.c Sun May 17 12:28:55 2009 +0000 +0 -0
@@ -23,10 +23,10 @@ */
#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/hrtimer.h>
#include "compat.h"
#include "cx88.h"
@@ -49,7 +49,7 @@
/* poll external decoder */
int polling;
- struct delayed_work work;
+ struct hrtimer timer;
u32 gpio_addr;
u32 last_gpio;
u32 mask_keycode;
@@ -144,31 +144,25 @@
}
}-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void cx88_ir_work(void *data)
-#else
-static void cx88_ir_work(struct work_struct *work) -#endif
+enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
- struct cx88_IR *ir = data;
-#else
- struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work);
-#endif
+ unsigned long missed;
+ struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
cx88_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + missed = hrtimer_forward_now(&ir->timer, ktime_set(0, ir->polling * 1000000)); + if (missed > 1)
+ ir_dprintk("Missed ticks %ld\n", missed - 1);
+
+ return HRTIMER_RESTART;
}
void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
{
if (ir->polling) {-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
- INIT_DELAYED_WORK(&ir->work, cx88_ir_work, ir);
-#else
- INIT_DELAYED_WORK(&ir->work, cx88_ir_work);
-#endif
- schedule_delayed_work(&ir->work, 0);
+ hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ir->timer.function = cx88_ir_work;
+ hrtimer_start(&ir->timer, ktime_set(0, ir->polling * 1000000), HRTIMER_MODE_REL);
}
if (ir->sampling) {
core->pci_irqmask |= PCI_INT_IR_SMPINT;
@@ -185,7 +179,7 @@
}
if (ir->polling)- cancel_delayed_work_sync(&ir->work);
+ hrtimer_cancel(&ir->timer);
}
/* ---------------------------------------------------------------------- */
Em Sat, 23 May 2009 14:06:01 +0200
AH <[email protected]> escreveu:
Quoted 67 lines
Hi
Some remotes requires short polling interval which in modern kernels is below resolution of standard scheduler (
schedule_delayed_work), this causes problem of missed keystrokes. One of the solutions is to raise kernel timer frequency, my proposition is to use high resolution timers which are present in kernel since 2.6.16 (at least API AFAIK). I have encountered this problem on my Winfast 2000XP Expert, but after checkingcx88-input.cit seems that following cards can be affected also:WINFAST2000XP_EXPERTWINFAST_DTV1000WINFAST_TV2000_XP_GLOBALPROLINK_PLAYTVPVRPIXELVIEW_PLAYTV_ULTRA_PROPROLINK_PV_8000GTPROLINK_PV_GLOBAL_XTREMEKWORLD_LTV883MSI_TVANYWHERE_MASTERPatched driver seems to work on my system, with kernel 2.6.28. I have removed kernel checks for versions below 2.6.20 - they were because of API changes in scheduler.
I have not tested it on older kernels.
Regards
AHdiff -r
315bc4b65b4flinux/drivers/media/video/cx88/cx88-input.c
---a/linux/drivers/media/video/cx88/cx88-input.cSun May 17
12:28:55 2009 +0000
+++b/linux/drivers/media/video/cx88/cx88-input.cSat May 23
14:04:17 2009 +0200(quoted diff) +3
-9@@ -23,10 +23,10 @@ */ #include <linux/init.h> -#include <linux/delay.h> #include <linux/input.h> #include <linux/pci.h> #include <linux/module.h> +#include <linux/hrtimer.h> #include "compat.h" #include "cx88.h"@@ -49,7 +49,7 @@ /* poll external decoder */ int polling; - struct delayed_work work; + struct hrtimer timer; u32 gpio_addr; u32 last_gpio; u32 mask_keycode;@@ -144,31 +144,25 @@ } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void cx88_ir_work(void *data) -#else -static void cx88_ir_work(struct work_struct *work) -#endif +enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct cx88_IR *ir = data;
Review line 154
Quoted 10 lines
(quoted diff) +3
-4-#else - struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); -#endif + unsigned long missed; + struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); cx88_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + missed = hrtimer_forward_now(&ir->timer, ktime_set(0, ir->polling * 1000000));
Hmm... this patch got line wrapped. please fix it and re-send.
Quoted 34 lines
(quoted diff) +7
-6+ if (missed > 1) + ir_dprintk("Missed ticks %ld\n", missed - 1); + + return HRTIMER_RESTART; } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_DELAYED_WORK(&ir->work, cx88_ir_work, ir); -#else - INIT_DELAYED_WORK(&ir->work, cx88_ir_work); -#endif - schedule_delayed_work(&ir->work, 0); + hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ir->timer.function = cx88_ir_work; + hrtimer_start(&ir->timer, ktime_set(0, ir->polling * 1000000), HRTIMER_MODE_REL); }if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT;(quoted diff) +1
-3@@ -185,7 +179,7 @@ } if (ir->polling) - cancel_delayed_work_sync(&ir->work); + hrtimer_cancel(&ir->timer); } /* ---------------------------------------------------------------------- */ --
Quoted 3 lines
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Cheers,
Mauro
Quoted 5 lines · Mauro Carvalho Chehab
Em Sat, 23 May 2009 14:06:01 +0200
AH <[email protected]> escreveu:Quoted 3 lines
Patched driver seems to work on my system, with kernel 2.6.28. I have removed kernel checks for versions below 2.6.20 - they were because of API changes in scheduler.
If you are going to break compatibility below 2.6.20 then you should add the driver to versions.txt