Well, I have my remote working, but it wasnt easy. I added a pile of printk statements to the code that was griping, lirc-0.7.1/drivers/lirc_serial/lirc_serial.c. printk statements output to the /var/log/kern.log file where I was seeing the error dump. By seeing which line of code preceeded the dump, I found the problematic statement. And by shit-luck the statement was buried in an #ifdef / #else block. So I forced the compiler to take the other path and joy, joy success.
Tech details:
Top of lirc_serial.c has
Code:
#if defined(rdtsc)
#define USE_RDTSC
#warning "Note: using rdtsc instruction"
#endif
further down
Code:
#ifdef USE_RDTSC
/* This is an overflow/precision juggle, complicated in that we can't
do long long divide in the kernel */
/* When we use the rdtsc instruction to measure clocks, we keep the
* pulse and space widths as clock cycles. As this is CPU speed
* dependent, the widths must be calculated in init_port and ioctl
* time
*/
/* So send_pulse can quickly convert microseconds to clocks */
static unsigned long conv_us_to_clocks = 0;
static inline int init_timing_params(unsigned int new_duty_cycle,
unsigned int new_freq)
{
unsigned long long loops_per_sec,work;
duty_cycle=new_duty_cycle;
freq=new_freq;
loops_per_sec=current_cpu_data.loops_per_jiffy;
loops_per_sec*=HZ;
/* How many clocks in a microsecond?, avoiding long long divide */
work=loops_per_sec;
work*=4295; /* 4295 = 2^32 / 1e6 */
conv_us_to_clocks=(work>>32);
/* Carrier period in clocks, approach good up to 32GHz clock,
gets carrier frequency within 8Hz */
period=loops_per_sec>>3;
period/=(freq>>3);
/* Derive pulse and space from the period */
pulse_width = period*duty_cycle/100;
space_width = period - pulse_width;
dprintk("in init_timing_params, freq=%d, duty_cycle=%d, "
"clk/jiffy=%ld, pulse=%ld, space=%ld, "
"conv_us_to_clocks=%ld\n",
freq, duty_cycle, current_cpu_data.loops_per_jiffy,
pulse_width, space_width, conv_us_to_clocks);
return 0;
}
#else /* ! USE_RDTSC */
static inline int init_timing_params(unsigned int new_duty_cycle,
unsigned int new_freq)
{
/* period, pulse/space width are kept with 8 binary places -
* IE multiplied by 256. */
if(256*1000000L/new_freq*new_duty_cycle/100<=
LIRC_SERIAL_TRANSMITTER_LATENCY) return(-EINVAL);
if(256*1000000L/new_freq*(100-new_duty_cycle)/100<=
LIRC_SERIAL_TRANSMITTER_LATENCY) return(-EINVAL);
duty_cycle=new_duty_cycle;
freq=new_freq;
period=256*1000000L/freq;
pulse_width=period*duty_cycle/100;
space_width=period-pulse_width;
dprintk("in init_timing_params, freq=%d pulse=%ld, "
"space=%ld\n", freq, pulse_width, space_width);
return 0;
}
#endif /* USE_RDTSC */
Somehow rtdsc is defined so the first block is used. However, the line in the first block causes the modprobe failure.
Code:
loops_per_sec=current_cpu_data.loops_per_jiffy;
The first block should provide better timings if functional, but I prefer less-accurate timings that at least load.
STEPS TO FIX - This is a hack, that works for me, Im sure there are better ways.To force the compiler to use the second block, I change
lirc-0.7.1/drivers/lirc_serial/lirc_serial.c line 109
from:
Code:
Old Code:
#define USE_RDTSC
to:
Code:
New Code:
#define DONT_USE_RDTSC
then
Code:
killall lircd
make
make install
rmmod lirc_serial
modprobe lirc_serial
lircd