dvb-frontend: Replace timeval with ktime_t
PATCH v2 1/1 dvb-frontend: Replace timeval with ktime_t
struct timeval uses a 32-bit seconds representation which will overflow in the year 2038 and beyond. This patch replaces the usage of struct timeval with ktime_t which is a 64-bit timestamp and is year 2038 safe.
This patch is part of a larger attempt to remove all instances of 32-bit timekeeping variables (timeval, timespec, time_t) which are not year 2038 safe, from the kernel.
The patch is a work-in-progress - correctness of the following changes is unclear:
(a) Usage of timeval_usec_diff - The function seems to subtract usec values without caring about the difference of the seconds field. There may be an implicit assumption in the original code that the time delta is always of the order of microseconds.
The patch replaces the usage of timeval_usec_diff with ktime_to_us(ktime_sub()) which computes the real timestamp difference, not just the difference in the usec field.
(b) printk diffing the tv[i] and tv[i-1] values. The original printk statement seems to get the order wrong. This patch preserves that order.
--
Changes in v2:
- Use the more concise ktime_us_delta
- Preserve the waketime argument in dvb_frontend_sleep_until as a pointer, fixes bug introduced in v1 of the patch where the caller doesn't get its timestamp modified.
--- drivers/media/dvb-core/dvb_frontend.c | 40 +++++++++-------------------------- drivers/media/dvb-core/dvb_frontend.h | 3 +-- drivers/media/dvb-frontends/stv0299.c | 11 +++++----- 3 files changed, 17 insertions(+), 37 deletions(-)
drivers/media/dvb-core/dvb_frontend.c +10 -30
@@ -40,6 +40,7 @@#include <linux/freezer.h> #include <linux/jiffies.h> #include <linux/kthread.h> +#include <linux/ktime.h> #include <asm/processor.h> #include "dvb_frontend.h"
@@ -889,42 +890,21 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) fepriv->thread); } -s32 timeval_usec_diff (struct timeval lasttime,struct timeval curtime) -{ -return ((curtime.tv_usec < lasttime.tv_usec) ? -1000000 - lasttime.tv_usec + curtime.tv_usec : - curtime.tv_usec - lasttime.tv_usec); -} -EXPORT_SYMBOL (timeval_usec_diff); - -static inline void timeval_usec_add (struct timeval *curtime,u32 add_usec) -{ - curtime->tv_usec += add_usec; -if (curtime->tv_usec >=1000000 ) { - curtime->tv_usec -=1000000 ; - curtime->tv_sec++; - } -} -/* * Sleep until gettimeofday() > waketime + add_usec * This needs to be as precise as possible, but as the delay is * usually between 2ms and 32ms, it is done using a scheduled msleep * followed by usleep (normally a busy-wait loop) for the remainder */ -void dvb_frontend_sleep_until (struct timeval *waketime,u32 add_usec) +void dvb_frontend_sleep_until (ktime_t *waketime,u32 add_usec) { -struct timeval lasttime;s32 delta, newdelta; -timeval_usec_add (waketime, add_usec); - -do_gettimeofday (&lasttime); - delta =timeval_usec_diff (lasttime, *waketime); +ktime_add_us (*waketime, add_usec); + delta =ktime_us_delta (ktime_get_real (), *waketime);if (delta >2500 ) {msleep ((delta -1500 ) /1000 ); -do_gettimeofday (&lasttime); - newdelta =timeval_usec_diff (lasttime, *waketime); + newdelta =ktime_us_delta (ktime_get_real (), *waketime); delta = (newdelta > delta) ?0 : newdelta; }if (delta >0 )
@@ -2458,13 +2438,13 @@ static int dvb_frontend_ioctl_legacy(struct file *file,* include the initialization or start bit */ unsigned long swcmd = ((unsigned long ) parg) <<1 ; -struct timeval nexttime; -struct timeval tv[10 ]; +ktime_t nexttime; +ktime_t tv[10 ];int i;u8 last =1 ;if (dvb_frontend_debug)printk ("%s switch command: 0x%04lx\n" , __func__, swcmd); -do_gettimeofday (&nexttime); + nexttime =ktime_get_real ();if (dvb_frontend_debug) tv[0 ] = nexttime;/* before sending a command, initialize by sending
@@ -2475,7 +2455,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,for (i =0 ; i <9 ; i++) {if (dvb_frontend_debug) -do_gettimeofday (&tv[i +1 ]); + tv[i+1 ] =ktime_get_real ();if ((swcmd &0x01 ) != last) {/* set voltage to (last ? 13V : 18V) */ fe->ops.set_voltage (fe, (last) ?SEC_VOLTAGE_13 :SEC_VOLTAGE_18 );
@@ -2489,7 +2469,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,printk ("%s(%d): switch delay (should be 32k followed by all 8k\n" , __func__, fe->dvb->num);for (i =1 ; i <10 ; i++) -printk ("%d: %d\n" , i,timeval_usec_diff (tv[i-1 ] , tv[i])); +printk ("%d: %d\n" , i, (int )ktime_to_us (ktime_sub (tv[i-1 ], tv[i]))); } err =0 ; fepriv->state =FESTATE_DISEQC ;
drivers/media/dvb-core/dvb_frontend.h +1 -2
@@ -439,7 +439,6 @@ extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);extern int dvb_frontend_suspend (struct dvb_frontend *fe);extern int dvb_frontend_resume (struct dvb_frontend *fe); -extern void dvb_frontend_sleep_until (struct timeval *waketime,u32 add_usec); -extern s32 timeval_usec_diff (struct timeval lasttime,struct timeval curtime); +extern void dvb_frontend_sleep_until (ktime_t *waketime,u32 add_usec);#endif
drivers/media/dvb-frontends/stv0299.c +6 -5
@@ -44,6 +44,7 @@#include <linux/init.h> #include <linux/kernel.h> +#include <linux/ktime.h> #include <linux/module.h> #include <linux/string.h> #include <linux/slab.h>
@@ -404,8 +405,8 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned longu8 lv_mask =0x40 ;u8 last =1 ;int i; -struct timeval nexttime; -struct timeval tv[10 ]; +ktime_t nexttime; +ktime_t tv[10 ]; reg0x08 =stv0299_readreg (state,0x08 ); reg0x0c =stv0299_readreg (state,0x0c );
@@ -418,7 +419,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned longif (debug_legacy_dish_switch)printk ("%s switch command: 0x%04lx\n" ,__func__, cmd); -do_gettimeofday (&nexttime); + nexttime =ktime_get_real ();if (debug_legacy_dish_switch) tv[0 ] = nexttime;stv0299_writeregI (state,0x0c , reg0x0c |0x50 );/* set LNB to 18V */
@@ -427,7 +428,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned longfor (i=0 ; i<9 ; i++) {if (debug_legacy_dish_switch) -do_gettimeofday (&tv[i+1 ]); + tv[i+1 ] =ktime_get_real ();if ((cmd &0x01 ) != last) {/* set voltage to (last ? 13V : 18V) */ stv0299_writeregI (state,0x0c , reg0x0c | (last ? lv_mask :0x50 ));
@@ -443,7 +444,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned longprintk ("%s(%d): switch delay (should be 32k followed by all 8k\n" , __func__, fe->dvb->num);for (i =1 ; i <10 ; i++) -printk ("%d: %d\n" , i,timeval_usec_diff (tv[i-1 ] , tv[i])); +printk ("%d: %d\n" , i, (int )ktime_to_us (ktime_sub (tv[i-1 ], tv[i]))); }return 0 ;
Signature · 1 line
2.2.0.rc0.207.ga3a616c