Jon Cormier
2014-07-29 14:19:36 UTC
Reported issue:
1. Enable I2C1, flash the new kernel and reboot
2. Immediately after reboot, attempt to change the processor clock: "echo
456000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
3. Process blocks
However, if we do the following:
1. Enable I2C1, flash the new kernel and reboot
2. Immediately after reboot, run: "i2cdetect -y 2 0x08 0x08" or just
"i2cdetect -y 2"
3. Then run: "echo 456000 >
/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
4. Command succeeds
Here's the kernel hung task stack trace:
INFO: task sh:1428 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
sh D c026dc74 0 1428 1426 0x00000000
[<c026dc74>] (schedule+0x2a8/0x334) from [<c026e2e0>]
(schedule_timeout+0x1c/0x218)
[<c026e2e0>] (schedule_timeout+0x1c/0x218) from [<c026e164>]
(wait_for_common+0xf0/0x1b8)
[<c026e164>] (wait_for_common+0xf0/0x1b8) from [<c019ca1c>]
(i2c_davinci_cpufreq_transition+0x18/0x50)
[<c019ca1c>] (i2c_davinci_cpufreq_transition+0x18/0x50) from [<c00599a4>]
(notifier_call_chain+0x38/0x68)
[<c00599a4>] (notifier_call_chain+0x38/0x68) from [<c0059a80>]
(__srcu_notifier_call_chain+0x40/0x58)
[<c0059a80>] (__srcu_notifier_call_chain+0x40/0x58) from [<c0059aac>]
(srcu_notifier_call_chain+0x14/0x18)
[<c0059aac>] (srcu_notifier_call_chain+0x14/0x18) from [<c019dd78>]
(cpufreq_notify_transition+0xc8/0xfc)
[<c019dd78>] (cpufreq_notify_transition+0xc8/0xfc) from [<c00373ac>]
(davinci_target+0x144/0x154)
[<c00373ac>] (davinci_target+0x144/0x154) from [<c019d404>]
(__cpufreq_driver_target+0x28/0x38)
[<c019d404>] (__cpufreq_driver_target+0x28/0x38) from [<c019f260>]
(cpufreq_set+0x54/0x70)
[<c019f260>] (cpufreq_set+0x54/0x70) from [<c019d698>]
(store_scaling_setspeed+0x58/0x6c)
[<c019d698>] (store_scaling_setspeed+0x58/0x6c) from [<c019e3d0>]
(store+0x58/0x74)
[<c019e3d0>] (store+0x58/0x74) from [<c00d8854>]
(sysfs_write_file+0x108/0x140)
[<c00d8854>] (sysfs_write_file+0x108/0x140) from [<c009512c>]
(vfs_write+0xb0/0x118)
[<c009512c>] (vfs_write+0xb0/0x118) from [<c0095244>] (sys_write+0x3c/0x68)
[<c0095244>] (sys_write+0x3c/0x68) from [<c002bea0>]
(ret_fast_syscall+0x0/0x28)
Kernel panic - not syncing: hung_task: blocked tasks
[<c003069c>] (unwind_backtrace+0x0/0xd0) from [<c026d810>] (panic+0x44/0xc8)
[<c026d810>] (panic+0x44/0xc8) from [<c006aa7c>] (watchdog+0x1d4/0x21c)
[<c006aa7c>] (watchdog+0x1d4/0x21c) from [<c0054670>] (kthread+0x78/0x80)
[<c0054670>] (kthread+0x78/0x80) from [<c002c8dc>]
(kernel_thread_exit+0x0/0x8)
According to the stack trace the kernel gets stuck in the
"i2c_davinci_cpufreq_transition" function when it calls
"wait_for_completion(&dev->xfr_complete);" The two other places this
xfr_complete variable is referenced is the init_completion in the probe and
the complete at the end of the i2c_davinci_xfer function. My understanding
as to what this was intended for was to ensure that a transfer in progress
completed before changing the clock frequency. But as its currently done
the only thing it does is make sure there has been a completed i2c transfer
on this device ever. Is my understanding correct?
Currently the workaround is to simply disable the wait_for_completion as
seen below. How would you fix this to ensure a transfer in progress
completes before changing clocks without hanging if no transfer was ever
attempted?
diff --git a/drivers/i2c/busses/i2c-davinci.c
b/drivers/i2c/busses/i2c-davinci.c
index a76d85f..564247f 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -596,7 +596,7 @@ static int i2c_davinci_cpufreq_transition(struct
notifier_block *nb,
dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
if (val == CPUFREQ_PRECHANGE) {
- wait_for_completion(&dev->xfr_complete);
+ //wait_for_completion(&dev->xfr_complete);
davinci_i2c_reset_ctrl(dev, 0);
} else if (val == CPUFREQ_POSTCHANGE) {
i2c_davinci_calc_clk_dividers(dev);
Patch were this was introduced:
sha: 82c0de11b734c5acec13c0f6007466da81cd16d9 i2c:davinci:Add cpufreq
support
1. Enable I2C1, flash the new kernel and reboot
2. Immediately after reboot, attempt to change the processor clock: "echo
456000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
3. Process blocks
However, if we do the following:
1. Enable I2C1, flash the new kernel and reboot
2. Immediately after reboot, run: "i2cdetect -y 2 0x08 0x08" or just
"i2cdetect -y 2"
3. Then run: "echo 456000 >
/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
4. Command succeeds
Here's the kernel hung task stack trace:
INFO: task sh:1428 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
sh D c026dc74 0 1428 1426 0x00000000
[<c026dc74>] (schedule+0x2a8/0x334) from [<c026e2e0>]
(schedule_timeout+0x1c/0x218)
[<c026e2e0>] (schedule_timeout+0x1c/0x218) from [<c026e164>]
(wait_for_common+0xf0/0x1b8)
[<c026e164>] (wait_for_common+0xf0/0x1b8) from [<c019ca1c>]
(i2c_davinci_cpufreq_transition+0x18/0x50)
[<c019ca1c>] (i2c_davinci_cpufreq_transition+0x18/0x50) from [<c00599a4>]
(notifier_call_chain+0x38/0x68)
[<c00599a4>] (notifier_call_chain+0x38/0x68) from [<c0059a80>]
(__srcu_notifier_call_chain+0x40/0x58)
[<c0059a80>] (__srcu_notifier_call_chain+0x40/0x58) from [<c0059aac>]
(srcu_notifier_call_chain+0x14/0x18)
[<c0059aac>] (srcu_notifier_call_chain+0x14/0x18) from [<c019dd78>]
(cpufreq_notify_transition+0xc8/0xfc)
[<c019dd78>] (cpufreq_notify_transition+0xc8/0xfc) from [<c00373ac>]
(davinci_target+0x144/0x154)
[<c00373ac>] (davinci_target+0x144/0x154) from [<c019d404>]
(__cpufreq_driver_target+0x28/0x38)
[<c019d404>] (__cpufreq_driver_target+0x28/0x38) from [<c019f260>]
(cpufreq_set+0x54/0x70)
[<c019f260>] (cpufreq_set+0x54/0x70) from [<c019d698>]
(store_scaling_setspeed+0x58/0x6c)
[<c019d698>] (store_scaling_setspeed+0x58/0x6c) from [<c019e3d0>]
(store+0x58/0x74)
[<c019e3d0>] (store+0x58/0x74) from [<c00d8854>]
(sysfs_write_file+0x108/0x140)
[<c00d8854>] (sysfs_write_file+0x108/0x140) from [<c009512c>]
(vfs_write+0xb0/0x118)
[<c009512c>] (vfs_write+0xb0/0x118) from [<c0095244>] (sys_write+0x3c/0x68)
[<c0095244>] (sys_write+0x3c/0x68) from [<c002bea0>]
(ret_fast_syscall+0x0/0x28)
Kernel panic - not syncing: hung_task: blocked tasks
[<c003069c>] (unwind_backtrace+0x0/0xd0) from [<c026d810>] (panic+0x44/0xc8)
[<c026d810>] (panic+0x44/0xc8) from [<c006aa7c>] (watchdog+0x1d4/0x21c)
[<c006aa7c>] (watchdog+0x1d4/0x21c) from [<c0054670>] (kthread+0x78/0x80)
[<c0054670>] (kthread+0x78/0x80) from [<c002c8dc>]
(kernel_thread_exit+0x0/0x8)
According to the stack trace the kernel gets stuck in the
"i2c_davinci_cpufreq_transition" function when it calls
"wait_for_completion(&dev->xfr_complete);" The two other places this
xfr_complete variable is referenced is the init_completion in the probe and
the complete at the end of the i2c_davinci_xfer function. My understanding
as to what this was intended for was to ensure that a transfer in progress
completed before changing the clock frequency. But as its currently done
the only thing it does is make sure there has been a completed i2c transfer
on this device ever. Is my understanding correct?
Currently the workaround is to simply disable the wait_for_completion as
seen below. How would you fix this to ensure a transfer in progress
completes before changing clocks without hanging if no transfer was ever
attempted?
diff --git a/drivers/i2c/busses/i2c-davinci.c
b/drivers/i2c/busses/i2c-davinci.c
index a76d85f..564247f 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -596,7 +596,7 @@ static int i2c_davinci_cpufreq_transition(struct
notifier_block *nb,
dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
if (val == CPUFREQ_PRECHANGE) {
- wait_for_completion(&dev->xfr_complete);
+ //wait_for_completion(&dev->xfr_complete);
davinci_i2c_reset_ctrl(dev, 0);
} else if (val == CPUFREQ_POSTCHANGE) {
i2c_davinci_calc_clk_dividers(dev);
Patch were this was introduced:
sha: 82c0de11b734c5acec13c0f6007466da81cd16d9 i2c:davinci:Add cpufreq
support
--
Jonathan Cormier
CriticalLink
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://linux.davincidsp.com/pipermail/davinci-linux-open-source/attachments/20140729/c120f833/attachment.html>
Jonathan Cormier
CriticalLink
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://linux.davincidsp.com/pipermail/davinci-linux-open-source/attachments/20140729/c120f833/attachment.html>