Thursday, July 4, 2013

Improving pm-utils power management scripts for pci devices

By default pm-utils changes power control parameters only for a subset of device classes. The classes id's are hardcoded into the /usr/lib/pm-utils/power.d/pci_devices script. Unfortunately it is not possible for a user to define his own set of classes to be treated by the script.

Using powertop I've found that there are quite a few additional pci devices in the system that could be auto suspended by the kernel. First of all it is necessary to generate a html report file by executing - 'sudo powertop -html'. In the Tuning section of the generated report file there will be pci devices shown that need tuning as well as a proper command to tune it. For example the following is reported for the Nvidia graphics subsystem that is not used:
Runtime PM for PCI Device NVIDIA Corporation GF119M [GeForce 610M]
echo 'auto' > '/sys/bus/pci/devices/0000:01:00.0/power/control';
To get the class id of the device the following should be done:
alex@thinkpad:~$ cat /sys/bus/pci/devices/0000:01:00.0/class
0x030000
The same should be done for all other devices reported by the powertop to get all class id's.

Now to handle the devices the following script should to be added:
alex@thinkpad:~$ cat /etc/pm/power.d/20-pci_devices
#!/bin/sh

#
# This script adjusts the power control of a set of PCI devices that
# are reported by the powertop on my thinkpad edge e330 laptop
#

PCI_DEVICES_PM_ENABLE="${PCI_DEVICES_PM_ENABLE:-true}"
PCI_DEVICES_CLASSES="0x060400 0x030000 0x078000 0x0c0320 0x0c0330 0x0c0500 0x010601 0x060100 0x030000 0xff0000" 

set_pci_device()
{
  for dev in /sys/bus/pci/devices/* ; do
    if [ -e $dev/class -a -e $dev/power/control ]; then
      id=$(basename $dev)
      class=$(cat $dev/class)
      for c in $PCI_DEVICES_CLASSES ; do
        [ "$c" = "$class" ] && {
          echo "Setting device $id to $1"
          echo $1 > $dev/power/control
          break
        }
      done
    fi
  done
}

case "$1" in
  true) # powersaving on
    [ "$PCI_DEVICES_PM_ENABLE" = true ] && set_pci_device "auto"
    ;;
  false) # powersaving off
    [ "$PCI_DEVICES_PM_ENABLE" = true ] && set_pci_device "on"
    ;;
  *)
    exit 254
    ;;
esac

exit 0

PCI_DEVICES_CLASSES contains all device classes that were reported by the  powertop on my system. They should be replaced by device classes for a target host. Ideally the pm-utils script should be patched by the maintainer so that it would be possible to define the device string in the /etc/pm/config.d/defaults

Edit: the script above has been simplified to this:
alex@thinkpad:~$ cat /etc/pm/power.d/20-pci_devices
#!/bin/sh

#
# This script adjusts the power control of all PCI devices
#

PCI_DEVICES_PM_ENABLE="${PCI_DEVICES_PM_ENABLE:-true}"

set_pci_device()
{
  for dev in /sys/bus/pci/devices/*/power/control; do
    echo $1 > $dev
  done
}

case "$1" in
  true) # powersaving on
    [ "$PCI_DEVICES_PM_ENABLE" = true ] && set_pci_device "auto" ;;
  false) # powersaving off
    [ "$PCI_DEVICES_PM_ENABLE" = true ] && set_pci_device "on" ;;
esac

exit 0
 

No comments: