Optimus laptop issues


#121

if your search for 01:00.0 (find /sys -name "*01:00.0*") ?

edit:
/sys/bus/devices/… are “just” symlinks, maybe if you check realpath

mv@mv-pc:~$ ls -l /sys/bus/pci/devices/
insgesamt 0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:01.0 -> ../../../devices/pci0000:00/0000:00:01.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:02.0 -> ../../../devices/pci0000:00/0000:00:02.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:16.0 -> ../../../devices/pci0000:00/0000:00:16.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1a.0 -> ../../../devices/pci0000:00/0000:00:1a.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1b.0 -> ../../../devices/pci0000:00/0000:00:1b.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1c.0 -> ../../../devices/pci0000:00/0000:00:1c.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1c.1 -> ../../../devices/pci0000:00/0000:00:1c.1
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1c.3 -> ../../../devices/pci0000:00/0000:00:1c.3
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1d.0 -> ../../../devices/pci0000:00/0000:00:1d.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1f.0 -> ../../../devices/pci0000:00/0000:00:1f.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1f.2 -> ../../../devices/pci0000:00/0000:00:1f.2
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:00:1f.3 -> ../../../devices/pci0000:00/0000:00:1f.3
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:01:00.0 -> ../../../devices/pci0000:00/0000:00:01.0/0000:01:00.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:02:00.0 -> ../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:02:00.1 -> ../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.1
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:02:00.2 -> ../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.2
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:02:00.3 -> ../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.3
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:03:00.0 -> ../../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0
lrwxrwxrwx 1 root root 0  1. Feb 07:43 0000:05:00.0 -> ../../../devices/pci0000:00/0000:00:1c.3/0000:05:00.0

mv@mv-pc:~$ cat /sys/devices/pci0000\:00/0000\:00\:01.0/0000\:01\:00.0/uevent 
DRIVER=nvidia
PCI_CLASS=30000
PCI_ID=10DE:0DE9
PCI_SUBSYS_ID=1025:0505
PCI_SLOT_NAME=0000:01:00.0
MODALIAS=pci:v000010DEd00000DE9sv00001025sd00000505bc03sc00i00

#122

Sorry for delay, I’ve been quite busy last few days. I’ve got it to work, but it’s a bit “hacky” solution. When I add the call to autostart as explained in https://wiki.archlinux.org/index.php/Hybrid_graphics#Fully_Power_Down_Discrete_GPU
I need to add acpi_osi= options to boot, or I get hard freeze right after login. The same goes if I add script as systemd service as explained here
https://wiki.archlinux.org/index.php/Systemd/User
or here
https://bbs.archlinux.org/viewtopic.php?id=86815
But everything works fine if script is executed after boot is finished. As workaround I’ve added

sleep 60

to the script, so it is waiting 60 seconds before executing. It works just fine, as expected after one minute battery life goes up to correct value, and touchpad works fine.
So basically the goal is achieved although I don’t think this is very “elegant” solution to the problem. If anyone has better idea I’m all ears :slight_smile:


#123

You haven’t posted the script. Is there a reason?


#124

It’s the same test script from
https://wiki.archlinux.org/index.php/Hybrid_graphics#Fully_Power_Down_Discrete_GPU
I’ve just removed all unnecessary calls and left the one that is working for me. No other changes.


#125

I went to the link and I can’t find what you describe. If I go into your mind, I might understand.
The point is, will a new inexperienced user be benefited if you post more detail?

  • Filename and path of new file
  • Contents of file
  • Permissions changes if any.
  • Kernel parameters
  • Any other change (after more than 120 posts troubleshooting experience) that was needed

#126

Ok then, I wanted to double check if anyone has better idea before posting this as final solution, but so be it.

There is big chance something will go wrong - make Timeshift snapshot before starting!
Even though I try to be as thorough as possible, I’m just a human being, so use common sense and check everything you are typing in scripts / services described below.

Steps to achieve the goal:

  • after fresh installation install desired graphics drivers - in my case video-linux (it was actually installed by default)
  • install acpi_call by using pacman -S acpi_call (select proper package for your kernel - in my case linux420-acpi_call)
  • load kernel module
modprobe acpi_call
  • add it to boot by creating file /etc/modules-load.d/acpi_call.conf
    contents:
acpi_call
  • run (with sudo!) test-script of acpi_call located in /usr/share/linux420-acpi_call/examples/turn_off_gpu.sh (linux420- part will match kernel version you chose when installing acpi_call)
  • copy the script to /usr/bin/
sudo cp /usr/share/linux420-acpi_call/examples/turn_off_gpu.sh /usr/bin/
  • edit the script - add sleep 20 after #!/bin/bash like so:
#!/bin/bash
sleep 20
  • remove all calls that failed when you ran the test script
  • make second copy of the script you have just edited, name it turn_on_gpu.sh
sudo cp /usr/bin/turn_off_gpu.sh /usr/bin/turn_on_gpu.sh
  • edit turn_on_gpu.sh - change the call from OFF to ON and remove sleep 20
#!/bin/bash

if lsmod | grep -q acpi_call; then
methods="
\_SB.PCI0.PEG0.PEGP._ON
"
  • create a new file in /etc/systemd/system/ eg. gpu-off.service with following content:
[Unit]
Description=Nvidia gpu off

[Service]
ExecStart=/usr/bin/turn_off_gpu.sh


[Install]
WantedBy=multi-user.target 
  • create new file in /etc/systemd/system/ eg. gpu-on-off-sleep.service with following content:
[Unit]
Description=nvidia gpu on/off hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/turn_on_gpu.sh 
ExecStop=/usr/bin/turn_off_gpu.sh

[Install]
WantedBy=sleep.target
  • double check if scripts are executable with
sudo chmod 755 /usr/bin/turn_off_gpu.sh
sudo chmod 755 /usr/bin/turn_on_gpu.sh
  • and enable the services with
sudo systemctl enable gpu-off.service
sudo systemctl enable gpu-on-off-sleep.service
  • reboot

After login the script will sleep for 20 seconds (you can adjust the value if you still have problems at login), and then turn off the discrete gpu. When you put your system to sleep the gpu is being turned on, and after waking it turned off again. Without these changes inducing suspend will freeze your system. Bear in mind that if you want to hibernate the system you are going to have to write separate service for that, similar to gpu-on-off-sleep.service

If you have Elan1200 touchpad like me you will probably also need to restart it’s kernel module after waking the system up. You can do it by adding another script:

  • create file /usr/bin/touchpad_reset.sh with content:
#!/bin/bash
modprobe -r i2c-hid
modprobe i2c-hid
echo "Touchpad restarted"
  • make it executable:
sudo chmod 755 /usr/bin/touchpad_reset.sh
  • edit /etc/systemd/system/gpu-on-off-sleep.service by making the script run at wake:
[Unit]
Description=nvidia gpu on/off hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/turn_on_gpu.sh 
ExecStop=/usr/bin/touchpad_reset.sh 
ExecStop=/usr/bin/turn_off_gpu.sh


[Install]
WantedBy=sleep.target
  • reset the gpu-on-off-sleep.service:
sudo systemctl disable gpu-on-off-sleep.service
sudo systemctl enable gpu-on-off-sleep.service
  • reboot

It will restart touchpad kernel module after waking the system so it should work properly.

My turn_off_gpu.sh script for reference:

#!/bin/bash
sleep 40

if lsmod | grep -q acpi_call; then
methods="
\_SB.PCI0.PEG0.PEGP._OFF
"

for m in $methods; do
    echo -n "Trying $m: "
    echo $m > /proc/acpi/call
    result=$(cat /proc/acpi/call)
    case "$result" in
        Error*)
            echo "failed"
        ;;
        *)
            echo "works!"
            # break # try out outher methods too
        ;;
    esac
done

else
    echo "The acpi_call module is not loaded, try running 'modprobe acpi_call' or 'insmod acpi_call.ko' as root"
    exit 1
fi

Huge Thank You to everyone who got involved in solving my issue - especially @dglt and @petsam. I couldn’t have done it without your help and patience :wink:


#127

your welcome, glad to see it work out in the end. good job on the explanation and overall for not giving up when most others would. :+1:


#128

Excellent work! You deserve a special badge :medal_military:

I bookmarked the solution. Will add in video troubleshooting tutorial when possible.


#129

I’m sorry everyone, it looks like I’ve done goofed. Using explained method is workaround but only partially - sleep and hibernation is not working… Unless I put acpi_osi options back in grub ;-( I think that’s it - every working solution to turning off gpu requires acpi_osi to boot and work properly. I’m really sorry for fake news :confused: I didn’t try suspending the machine when testing this.


#130

you can try setting different sleep states, and/or having a script run on sleep and wake .targets.
also you can try some alternative sleep commands and then edit the .desktop files related to sleep in the menu bar to run that command given it works.

for now, i think you should look at the power management arch wiki. i think you should be able to make it work without acpi_osi=! . one way to find out.
https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate

try adding mem_sleep_default=deep to your grub kernel parameters to change the default sleep mode to deep


#131
mem_sleep_default=deep

= no change. I’m reading the article now. The issue is it is not going to sleep properly (it looks like it hangs on trying to suspend, fans start to spin at higher speed and screen stays black but with backlight on). Most of the troubleshooting I see is about waking issues, not actually suspending. I’m messing with acpi_sleep to try different options.


#132

sounds like your nvidia gpu is getting turned on while trying to suspend, i thought this may be an issue. continue trying different ways of making it suspend properly, and if none are successful maybe try using a systemd service or modifying the existing sleep/suspend one to activate the card before suspend, maybe add sleep 5 and use whatever acpi_call you use to turn off the card to also turn it on before entering sleep/suspend. the same could be done to disable the card again after wake.
before doing that i would test to see if your able to turn the card on with acpi_call without causing any issues/lockups, also to see if your able to properly sleep/wake once the card is turned back on.

something like this:
for sleep/suspend: turn on gpu & sleep 5 > suspend
on wake: sleep 20 > turn off gpu


#133

Ok, I’ve tried all acpi_sleep options from
https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt
and so far no change.
I’m going to have to do some research to do what you are talking about, any advice to where to look for that?
Edit
I’ve created turn_on_gpu.sh script and it works without issues, gpu get’s turned on just fine, and suspend works.


Manjaro KDE and Nvidia
#134

look up :point_up_2:, youve already done this to make the gpu turn off 60 seconds after graphical.target

now you can do the same that triggers on sleep.target or suspend.target instead (try each one)

but before that, try manually using acpi_call to turn the gpu back on and see if your able to sleep/suspend normally
im guessing it’s somthing like changing
\_SB.PCI0.P0P1.PEGP._OFF
to
\_SB.PCI0.P0P1.PEGP._ON ??? (change call to match your gpu)


#135

That’s not what I mean, I mean how to actually trigger that on sleep / suspend,but nvm I will look for that. I’ve tried turning on gpu and it works fine, and suspend works after turning it on. So that’s probably right way to go :wink:


#136

create a turn_on_gpu.sh with the “on” acpi_call. then.

  • create a new file in /etc/systemd/system/ eg. gpuon.service with following content
[Unit]
Description=gpuon
Before=sleep.target

[Service]
ExecStart=/usr/bin/turn_on_gpu.sh && sleep 5


[Install]
WantedBy=sleep.target 
  • double check if script is executable with
sudo chmod 755 /usr/bin/turn_on_gpu.sh
  • and enable the service with
sudo systemctl enable gpuon.service

on sleep/suspend gpu gets turned on , waits 5 seconds and then sleeps

My script for reference:

#!/bin/bash

#insert the gpu on acpi_call command here


exit

you can do the same to turn off the card 60 seconds (or maybe less) after wake from sleep


#137

Ok, I’ve got it to work, thanks again :slight_smile: Instructions at https://wiki.archlinux.org/index.php/Power_management#Sleep_hooks are a bit confusing to someone without experience with using services. I’m going to update “solution post” now.


#138

fine, do it your way then :unamused:. [joking]
i edited the turn on gpu .sh to make it much simpler, if what you have now works already, use it. :+1:


#139

I actually did it your way :wink: Post your edited script please, I actually wanted to ask if someone with proper knowledge can optimize this. Solution post is updated.


#140

Well I appreciated the quick rendering of the systemd unit for him. Your getting pretty good at writing those services.

Great job on all the Video support threads lately.

Congrats to both of you on a nice solution.