On 05/11/2015 04:37 AM, Tina Ruchandani wrote:
> 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.
>
> Signed-off-by: Tina Ruchandani <[email protected]>
Hi Tina!
Please CC patches for anything under drivers/media and/or include/media to the
linux-media mailinglist. That's where the experts on these drivers are and
they will be able to tell you if it is OK or not.
I suspect that in both cases it may well be a bug.
Regards,
Hans
> ---
> drivers/media/dvb-core/dvb_frontend.c | 46
> ++++++++++++-----------------------
> drivers/media/dvb-core/dvb_frontend.h | 3 +--
> drivers/media/dvb-frontends/stv0299.c | 15 ++++++------
> 3 files changed, 24 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/media/dvb-core/dvb_frontend.c
> b/drivers/media/dvb-core/dvb_frontend.c
> index 882ca41..48c3daf 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -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,25 @@ 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;
> + ktime_t lasttime;
> s32 delta, newdelta;
>
> - timeval_usec_add(waketime, add_usec);
> + ktime_add_us(waketime, add_usec);
>
> - do_gettimeofday(&lasttime);
> - delta = timeval_usec_diff(lasttime, *waketime);
> + lasttime = ktime_get_real();
> + delta = ktime_to_us(ktime_sub(lasttime, waketime));
> if (delta > 2500) {
> msleep((delta - 1500) / 1000);
> - do_gettimeofday(&lasttime);
> - newdelta = timeval_usec_diff(lasttime, *waketime);
> + lasttime = ktime_get_real();
> + newdelta = ktime_to_us(ktime_sub(lasttime, waketime));
> delta = (newdelta > delta) ? 0 : newdelta;
> }
> if (delta > 0)
> @@ -2458,24 +2442,24 @@ 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
> * a 32ms 18V to the switch
> */
> fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
> - dvb_frontend_sleep_until(&nexttime, 32000);
> + dvb_frontend_sleep_until(nexttime, 32000);
>
> 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);
> @@ -2483,13 +2467,13 @@ static int dvb_frontend_ioctl_legacy(struct file
> *file,
> }
> swcmd = swcmd >> 1;
> if (i != 8)
> - dvb_frontend_sleep_until(&nexttime,
> 8000);
> + dvb_frontend_sleep_until(nexttime,
> 8000);
> }
> if (dvb_frontend_debug) {
> 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;
> diff --git a/drivers/media/dvb-core/dvb_frontend.h
> b/drivers/media/dvb-core/dvb_frontend.h
> index 816269e..5ddd55f 100644
> --- a/drivers/media/dvb-core/dvb_frontend.h
> +++ b/drivers/media/dvb-core/dvb_frontend.h
> @@ -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
> diff --git a/drivers/media/dvb-frontends/stv0299.c
> b/drivers/media/dvb-frontends/stv0299.c
> index b57ecf4..8d30865 100644
> --- a/drivers/media/dvb-frontends/stv0299.c
> +++ b/drivers/media/dvb-frontends/stv0299.c
> @@ -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 long
> u8 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,16 +419,16 @@ static int stv0299_send_legacy_dish_cmd (struct
> dvb_frontend* fe, unsigned long
> if (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 */
>
> - dvb_frontend_sleep_until(&nexttime, 32000);
> + dvb_frontend_sleep_until(nexttime, 32000);
>
> for (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));
> @@ -437,13 +438,13 @@ static int stv0299_send_legacy_dish_cmd (struct
> dvb_frontend* fe, unsigned long
> cmd = cmd >> 1;
>
> if (i != 8)
> - dvb_frontend_sleep_until(&nexttime, 8000);
> + dvb_frontend_sleep_until(nexttime, 8000);
> }
> if (debug_legacy_dish_switch) {
> 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])));
> }
>
> return 0;
>
_______________________________________________
Y2038 mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/y2038