[ONE Original Android Development] sVenose:
Kernel CPU frequency issue

These past few days I've been writing a custom script packaged in a custom initrd using the 265 CM 12.1 kernel source. I lowered the CPU voltage lower limit from 600mV to 100mV by modifying the clock-krait-8974.c file and changing the CPU_MIN_VDD value. I rebuilt the kernel with selinux disabled and all other configurations kept as default.

My custom script is a boot image that sets the phone usb mode to RNDIS during boot, starts a udhcpd daemon for dynamic IP assignment to the host machine and then starts a telnetd daemon so I can log into the phone and run a busybox shell. It also starts ftpd so I can modify the scripts straight from the device amongst other things since I get full access to the root directory.

I built a static htop binary so I can monitor CPU usage on all the cores. Everything works great. I wanted to use 2 custom scripts to test how low I could undervolt my OnePlus One while still remaining stable. I opened the scripts in the UKM directory to see how you change the voltage on the frequencies and made a script the does that interactively by prompting the user for the frequency and voltage values.

The other script starts 4 dd child processes as so:

dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null &

This puts a full load on all the cores so I can stress test the CPU. I

I was thinking 600mV wasn't a low enough frequency for 69MHz that's why I modified the kernel and changed the lower limit to 100mV. So I started by checking the scripts worked perfectly and they did. Changing voltage or the amount of cores online by changing msm_mpdesicion min/max cores settings worked great.

Then came the real test. How low a voltage could I go for 69Mhz. I decided to start with the previous limit of 600mV just to see if everything worked fine. Script sets min and max cores value to 4 so all cores are online, then proceeds to set scaling_min_freq to 69600 and scaling_governor to powersave on all 4 cores individually.

Then launch the load script to stress the cpu and htop confirms the cpus are all running at 100%.

First off, I found it strange how responsive the phone was at 69Mhz. Everything was almost as smooth and fast as they were when the frequency was 2457MHz except for noticeable delay in htop updates. That's understandable since I don't have android running but it was still suspiciously too....smooth. Even with all the cores running on full load, doing other tasks where still easy.

I decided to just set the voltage for 69MHz to 100mV. I did that and run the load test again fully expecting the phone to hang. But nope, everything still worked fine. At this point I was very suspicious, is the voltage being applied correctly?

I decided I would change to a frequency that would definitely hang on too low a voltage. So I changed the cpus to 1113MHz, and set the voltage to 600mV and ran the load test. Maybe voltage is only applied after a core has been brought down and up again because I had to do that for the phone to hang.

Anyway this confirmed that the voltage was being applied correctly. But 100mv for 69MHz worked?

I rebuilt the kernel and set the lower voltage limit to 10mV by changing CPU_VDD_MIN=10.

I rebooted my phone and ran the test again, this time 69MHz at 10mV. Cycled the cores on and off and reapplied the frequency to 69MHz but nothing. No hangups at all. Phone kept running smooth basically mocking me and asking for more, or less to be precise. I checked htop and all the cores where at 100%. Manually checked each cpu UV_mV_table and each had 69MHz at 10mV.

Something else was bothering me. While scaling_cur_freq reported 69MHz, or 69600 to be precise, cpuinfo_cur_freq reported 268MHz or 268800 to be precise. I remember your previous kernels had this value as lowest frequency possible to set while the device was running.

Maybe cpuinfo was reporting the wrong frequency since in the stats/time_in_state 69MHz was updating properly and 268MHz is no longer in the frequency table. Neither here nor in the under "qcom,speed3-pvs8-bin-v1" for my particular cpu in the msm8974pro.dtsi file in the kernel.

But the cpuinfo_cur_freq updated properly for any frequency above or equal to 300MHz. Anything less than that and it would only return 268MHz . I searched high and low and couldn't find where that value was being applied. And through thorough testing it seems that 268MHz is the lowest frequency being applied no matter what you set below 300MHz, thats why I can't get my device to hang on any frequency lower than 300MHz but at 300MHz and higher setting too low a voltage hangs the device.

This poses two issues.

1) Where is 268MHz coming from? In essence it means that anyone setting their phones to lower than 300MHz is only locking their device to 268MHz, I also tested that while android and synapse was working fine to be sure. IT DOES NOT go lower than 268MHz and 69MHz/146MHz/223MHz is never applied.

2) Where is 268MHz getting its voltage value from? It is not using the ones I set for the lower frequencies because if it was my phone would have hang already as I set them to 10mV. That means that if the unknown voltage for 268MHz is being set too high we could be losing precious battery life if we have our minimum CPU frequency value set lower than 300MHz.

I can't locate the issue at all in the kernel but I'm not too experienced in the inner workings of the msm cpufreq driver.

Hope the devs can fix this issue or as a workaround set the lowest possible frequency to 300MHz and not anything lower than that.

Sorry for wall of text, and if I posted this in the wrong place may the mods let me know. This is my first post here on XDEV.