regression in ktime.h circa 3.16.0-rc5+ breaks lirc irsend, bad commit 166afb64511

From: Trevor Cordes
Date: Mon Mar 23 2015 - 13:07:09 EST


Hello everyone, this is my first attempt at bisecting a kernel to solve a
bug. Please bear with me.

I have successfully bisected and located a commit that is causing my
problem. Look at commit 166afb64511.

ktime_to_us returns s64, but the commit changes it so ktime_to_us just
returns what ktime_divns returns, and ktime_divns returns a u64! If the
u64 is big enough, wouldn't it wrap s64 around to a negative number? Or,
perhaps if some caller is passing in negative ktime_t to begin with it
will trigger without having to hit big numbers. With my limited knowledge
of C, I am stabbing in the dark here.

That's just my guess as to why this commit causes my problem. My bug
symptom is my previously working MythTV lirc blaster no longer reliably
sends IR signals. Using irsend to test I can see irsend is just timing
out (and only sometimes blasts, usually the first attempt). On good
kernels it returns immediately after blasting.

This little patch (at bottom of email) that puts the code back in place
and gets rid of the function call fixes the problem for me. I applied
this patch to the very latest FC21 kernel-PAE-3.19.1-201.fc21.i686 src.rpm
and rpmbuilded and the bug is gone! I can once again MythTV. Hooray.

I suspect no one else is seeing this because less people are running
32-bit now, and perhaps in most code paths the value of the u64 never gets
above 2^63. I suspect something in drivers/media (possibly) is passing
very high or negative values (possibly another bug) to these calls.

Obviously my patch isn't the real solution, the real solution is to make
the new function calls use a consistent 64-bit type, or figure out what in
my code path is calling these functions and check it for value sanity.

I've documented the whole process / details of this bug in RHBZ:
https://bugzilla.redhat.com/show_bug.cgi?id=1200353

Thanks!

diff -uNr a/include/linux/ktime.h b/include/linux/ktime.h
--- a/include/linux/ktime.h 2015-02-08 20:54:22.000000000 -0600
+++ b/include/linux/ktime.h 2015-03-23 01:09:43.000000000 -0500
@@ -173,12 +173,16 @@

static inline s64 ktime_to_us(const ktime_t kt)
{
- return ktime_divns(kt, NSEC_PER_USEC);
+/* return ktime_divns(kt, NSEC_PER_USEC); */
+ struct timeval tv = ktime_to_timeval(kt);
+ return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
}

static inline s64 ktime_to_ms(const ktime_t kt)
{
- return ktime_divns(kt, NSEC_PER_MSEC);
+/* return ktime_divns(kt, NSEC_PER_MSEC); */
+ struct timeval tv = ktime_to_timeval(kt);
+ return (s64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
}

static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/