Tech Blog - Crushing The Kworker Uprising (or how to fix your Linux Lenovo Ideapad y560p)

Note: This stuff works on Ubuntu 12.04, Precise pangolin. It should be fairly easy to port to other distributions.

There has been a recent kernel bug that has, on certain systems like my wonderful, wonderful Lenovo y560p , lead to the massive uprising of interrupts, which can waste up to 60% of CPU time.

See what’s happening here? For the computer, it’s like when a random friendly sales team member randomly shows up at random times of thethe day to you, the random programmer, to say things like “sup man, hey yo IT pro what’s cookin man, hey, you must be doing some serious thinking and shit, but man, hey, just gotta check you out and ask what’s cookin’, man, so, hey, man, what’s cookin’?” and then look at you with big, brown eyes waiting for an intelligent answer.

This not only wastes aerial brownian motion, but can also suck up to 60% of your brain power (long term effects not counted). No wonder the poor, idle machine can’t get things done any more, because the CPU is clooged with the interrupt controller gone haywire incessantly screamin “SUP, MAN! YEAH!” It’s like Guantanamo for geeks. It’s not torture, bit it is enhanced communication.

The most obvious solution is to fire the sales team.


# /etc/default/grub

# Find GRUB_CMDLINE_LINUX_DEFAULT and add acpi=off to the end, like so:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi=off"

followed by


sudo update-grub
sudo reboot
# Good riddance

This works like a charm. The sales team is gone, the chatter stops, and the CPU is free to work again (not to mention the tremendous emotional satisfaction).

However, it has a big minus. I have found that the sales team, properly kept outside of the IT office (kind of like farmers put wire fence around trees in goat pens), actually gets things of its own done. More specifically, I realized my Indigo IOx Expresscard
was no longer working, which was the reason I bought my beloved Lenovo in the first place. I hate to admit it, but firing the sales team is actually kind of a bad idea. Uh… sup guys, wanna come back, like, uh, would you?

Luckily, a very smart fellow on the linux kernel bug forum found a better solution: Instead of firing the entire sales team, we only fire the team member that does the most interrupting. Sales can still be made, we can work, all is well. First we need to find the culprit:


# Find the chatterbox

grep enabled /sys/firmware/acpi/interrupts/*
# He has the file with the highest number


sudo crontab -e
# now add this line, save, quit
@reboot echo "disable" > /sys/firmware/acpi/interrupts/gpeXX
# Note: for some reason, adding the line to /etc/rc.local doesn't work


#!/bin/bash
# Put this in a new file /etc/pm/sleep.d/30_disable_gpe (XX is the culprit found above)

case "$1" in
thaw|resume)
echo "disable" > /sys/firmware/acpi/interrupts/gpeXX 2>/dev/null
;;
*)
;;
esac
exit $?

This simply clobbers the interrupt that is problematic, while the express card still works great.

Oh, and I’m kidding about the sales team. I love you guys.

10 Comments

  • Carlo,
    I have had this problem with mint 12 and 13. Since I run a Lenovo T400, I felt that your news would be my answer.
    However, my gpe interrupt is still not being disabled.

    I have two rc.local files, one in /etc and the other in /etc/init.d
    Which would be the correct place?

    By revdjenk, March 16, 2013 – 1:33 am
  • aha, I checked both files. the /etc/rc.local is more or less a place-setter.

    but where in /etc/init.d should I put this line?
    First, I know nothing about scripts. and here is my rc.local file, there:

    PATH=/sbin:/usr/sbin:/bin:/usr/bin

    . /lib/init/vars.sh
    . /lib/lsb/init-functions

    do_start() {
    if [ -x /etc/rc.local ]; then
    [ "$VERBOSE" != no ] && log_begin_msg “Running local boot scripts (/etc/rc.local)”
    /etc/rc.local
    ES=$?
    [ "$VERBOSE" != no ] && log_end_msg $ES
    return $ES
    fi
    }

    case “$1″ in
    start)
    do_start
    ;;
    restart|reload|force-reload)
    echo “Error: argument ‘$1′ not supported” >&2
    exit 3
    ;;
    stop)
    ;;
    *)
    echo “Usage: $0 start|stop” >&2
    exit 3
    ;;
    esac

    By revdjenk, March 16, 2013 – 1:45 am
  • Hi revdjenk, you’re right I should have updated my post, I’ll do that now.

    For some reason putting it into /etc/rc.local doesn’t work. What does it work is putting it into root’s crontab. Do:

    sudo crontab -e

    and add the line

    @reboot echo “disable” > /sys/firmware/acpi/interrupts/gpe18

    That should do the trick.

    By carlo, March 16, 2013 – 11:30 am
  • Reporting:

    Well… no more mouse lag…but also no sleep/slumber function and battery indicator is showing 100% when I’ve been unplugged for 30 minutes!

    I will have to undo this. Thanks for the try!

    By revdjenk, March 16, 2013 – 5:46 pm
  • Well, that blows… sure you got the right interrupt?

    By carlo, March 16, 2013 – 5:58 pm
  • Yes, mine was #11, the only one with activity. All the others reported 0.

    By revdjenk, March 16, 2013 – 6:19 pm
  • What is curious: when I notice the lag/stutter top reports two kworker processes, bouncing between 10-25%.

    Often, but not always, starting another program kills the lagging, sometimes for the rest of the day, sometimes for a mere minute, then I repeat opening programs until the lagging disappears.
    The lagging returns after suspending (closing the lid) or after not being used for half an hour.

    I have installed mint on two other lenovos (T60 and 61) and they have none of this issue!

    Another curious occurrence on my machine, I have not seen or heard elsewhere:
    There is a two-second delay on the menu when I put the cursor over a category before it highlights and opens its programs. Clicking on the category does not help, the delay remains.

    By revdjenk, March 16, 2013 – 6:29 pm
  • I’ve also got a Lenovo Y560P and experienced the exact same issue.

    I attempted this solution, but I did not work and the interrupt was still enabled.

    Playing around in the console, I noticed that it does work if issue the command “echo “disable” > /sys/firmware/acpi/interrupts/gpeXX” twice.

    So I simply adapted the original solution to echo to the interrupt twice for restart & resume and now I’m rocking.

    By Hendrik G Louw, November 28, 2013 – 9:06 am
  • I just want to let you know that it works in rc.local if you provide the full path to the program or script you want to execute
    In this case that would be

    /bin/echo “disable” > /sys/firmware/acpi/interrupts/gpeXX

    By Subgirl, May 16, 2014 – 8:48 pm
  • help me

    By jason egle, November 28, 2014 – 8:09 pm

One Trackback

  1. [...] was trying to solve a hardware problem, and one of the many attempts was to upgrade my kernel from 3.2 (standard) to 3.4 (special). It [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*