Installing openSUSE 10.2 on a ThinkPad X60

From ThinkWiki
Revision as of 21:07, 8 July 2007 by McCoy-Tyner (Talk | contribs) (Automatic power switching for ipw3495)
Jump to: navigation, search

Lenovo ThinkPad X60 (model 1707-CTO / model 1706-8GG)

Hardware Details

  • Intel Core Duo T2400 (1.83GHz, 2MB L2, 667MHz FSB)
  • 2GB RAM (2 NonParity DDR2 SDRAM SoDIMM PC2-5300)
  • Intel Graphics Media Accelerator 950
  • 12.1 inch XGA (1024x768) (Lenovo LTN121XJ-L07)
  • 80GB, 5400rpm Serial ATA (Hitachi HTS541080G9SA00) / 100GB Serial ATA on 1706GG (Toshiba MK1034GSX)
  • Intel PRO/1000 Gigabit Ethernet
  • Intel PRO/Wireless 3945ABG
  • Bluetooth
  • Firewire
  • SD Card Reader
  • 56K V.92 Modem

Software Details

Installation procedure

Setup

Since I didn't get a dock or usb CDROM with this machine, I started the installation procedure using a USB Stick. I followed these instructions to set up a boot USB key. This contains GRUB and the loader for the installer. The actual installation media was on an NFS share. To set this up, copy the contents of the CDS/DVD into a directory (or mount the DVD iso image loopback) then share the directory containing CD1 via NFS, is the simplest way. Sharing the DVD as a SMB share works from windows, too.

Using the ultra-bay DVD-drive is straightforward as it is detected at startup and can be booted from. Nothing special about this.

Installation

Press F12 during POST to get the boot selector menu up, choose the USB Key. This boots into GRUB. Press F4 here to set the installation source to NFS or SMB as needed, and enter the server details. For example, with SMB, enter the server name, the name of the share, and the directory where the first CD's contents are, eg 'CD1'. Now the installer is loaded from the share and proceeds as a usual SUSE install. No special steps are required during the install, but read the documentation about preserving or moving the ThinkVantage rescue partition before you commit to the installation.

NOTE!
After installing the software, the installer reboots into the installed system to configure it, as usual. Note that because it was booted from a USB key, GRUB has been installed onto the key instead of the hard disk. You can correct this after the configuration is completed, but for now, keep the USB key inserted, boot from that again. The GRUB menu boots the installed system from the hard disk, just like the old days with LILO and a boot floppy. Once the installation and you're logged in, start YaST2, go to System, Bootloader, and change the boot loader location to its proper location (I recommend the boot or root partition with the Generic MBR option). Now the laptop can boot on its own.

What works out of the box

Hardware

  • Ethernet adaptor
  • Intel 3945ABG Wireless ethernet adapter
  • GMA950 graphics with 3D acceleration with integral monitor
  • Sound playback
  • USB
  • Firewire
  • Bluetooth (with kbluetoothd, gets about 55kB/s with OBEXFTP)
  • Trackpoint
  • SD card reader

Power management etc

  • Suspend to disk (Fn+F12)
  • Suspend to RAM (Fn+F4)
  • Turn display dark (Fn+F3)
  • CPU speed stepping (required BIOS update to 2.05 though)
  • LCD Brightness depending on current power scheme, via KPowersave and HAL

Extra keys

  • Volume control, keyboard light and screen brightness control
  • Lid switch (LCD off when lid closed, resume from suspend to RAM when opened)
  • Multimedia keys with KMix and Amarok
  • Browser back/forward keys with Konqueror

What had to be configured by hand

  • Mouse wheel emulation, set "Emulate Mouse wheel with button 2" in SaX2 mouse settings
  • Keyboard dead keys for international characters, set "Right Alt is Compose" in SaX2 keyboard settings, then ralt-shift-2, a => ä
  • Sound recording, using KMix or other mixer, set the mic as capture source, turn it up, enable and turn up 'Capture' channel.
  • FN-F2 initially does nothing. This requires extra tweaking.
  • FN-F7 doesn't work either. Even though ibm-acpi module may be loaded, the video-switch facility does not work.
  • The finger print reader, a working driver is existing.
  • By default the fan runs all the time. If power management on the ipw3945 is enabled, it only runs about 1/3 of the time. Use 'iwpriv eth1 set_power 7' to enable power management - this comes at the cost of increasing latency when using wireless. See the ipw3495 README for details. A description how to do this automatically can be found below.

Accessing the nvram - device

The default permissions of the nvram device prevent the screen sliders for brightness / volume etc. from being displayed for non root users. To circumvent this problem, a modification of an entry should be made within /etc/udev.d/hooks/50-udev-default.rules:

replace

KERNEL=="nvram",               GROUP="kmem", MODE="600"

by

KERNEL=="nvram",               GROUP="users", MODE="640"

and every user is able to read from nvram. This ensures that the sliders are displayed when modifying the brightness or the volume.

Automatic power switching for ipw3495

UNDER CONSTRUCTION

This procedure can be automatized:

Create a script switch_wireless_mode in /usr/lib/powersave/scripts and make it executeable:

#!/bin/bash
###########################################################################
#                                                                         #
#                         Powersave Daemon                                #
#                                                                         #
#          Copyright (C) 2004,2005 SUSE Linux Products GmbH               #
#                                                                         #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the   #
# Free Software Foundation; either version 2 of the License, or (at you   #
# option) any later version.                                              #
#                                                                         #
# This program is distributed in the hope that it will be useful, but     #
# WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       #
# General Public License for more details.                                #
#                                                                         #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., #
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA                  #
#                                                                         #
###########################################################################
#
# change mode for the wireless network card on X60 lenovo laptop
# currently the interface name needs to be set manually.
#
# we call the script ipw3945pwr in order to set the power accordingly
# 

# This is where all the main work is done:
IPW3945PWR=/usr/bin/ipw3945pwr 

. ${0%/*}/helper_functions

if [ $EVENT_TYPE != "ACADAPTER" ]; then
    DEBUG "switch_wireless_mode only makes sense for acadapter events ;-)" WARN
else
    # $1 can be acadapter.online or acadapter.offline, see $IPW3945PWR
    # ${IPW3945PWR} "acadapter.test"
    ${IPW3945PWR} "$1"
fi

$SCRIPT_RETURN $EV_ID 0 "switch_wireless_mode finished"
EXIT 0

The script tries to detect your wireless interface automatically. Nevertheless, it is not designed to cope with more than one wireless network interface, if you add another one, unwanted side effects could happen.

Two lines have to be modified "on top" of this to make powersaved aware of it. The file that should be changed is /etc/sysconfig/powersave/events:

## Path:                System/Powermanagement/Powersave/Events
## Type:                string
EVENT_ACADAPTER_ONLINE="reread_cpu_capabilities switch_wireless_mode"
EVENT_ACADAPTER_OFFLINE="reread_cpu_capabilities switch_wireless_mode"

"switch_wireless_mode" should be added to the EVENT_ACADAPTER_ONLINE and EVENT_ACADAPTER_OFFLINE as shown above. Given this, the x60 will switch to low power mode when running on battery and back to high power mode when running on mains automatically.

In addition it refers to another script actually doing the work that is called ipw3945pwr and is located in /usr/bin (in this example) that actually does the switching. The corresponding code is listed here:

#!/bin/sh
IWPRIV="/usr/sbin/iwpriv"
IWCONFIG="/usr/sbin/iwconfig"
AWK="/bin/gawk"
STATEFILE="/proc/acpi/ac_adapter/AC/state"
MODEPARAM="set_power"
MODESHOW="get_power"
POWERSCHEME="6"
BATTERYSCHEME="7" 
NLOOPS="0"

# if we return from suspend and the network settings haven't been adjusted yet,
# we have to wait until it is our turn!
IF=`${IWCONFIG} 2>&1 | ${AWK} '{if(match($0,"ESSID")){print $1}}'`
while [ "${IF}" = "" -a "${NLOOPS}" != "10" ]; do
        sleep 2
        IF=`${IWCONFIG} 2>&1 | ${AWK} '{if(match($0,"ESSID")){print $1}}'`
        NLOOPS=`expr ${NLOOPS} + 1`
done

if [ "${1}" = "acadapter.test" ]; then
        ADAPTERSTATE=`cat $STATEFILE 2>&1 | grep on-line > /dev/null && echo "acadapter.online" || echo "acadapter.offline"`
else
        ADAPTERSTATE=${1}
fi

if [ "${ADAPTERSTATE}" = "acadapter.online" ]; then
        # echo -n "... on Mains ..." 
        ${IWPRIV} ${IF} ${MODEPARAM} ${POWERSCHEME}
elif [ "${ADAPTERSTATE}" = "acadapter.offline" ]; then
        # echo -n "... on Battery ..." 
        ${IWPRIV} ${IF} ${MODEPARAM} ${BATTERYSCHEME}
elif [ "${ADAPTERSTATE}" = "acadapter.show" ]; then
        # echo -n "... Showstats ..." 
        ${IWPRIV} ${IF} ${MODESHOW}
else
        echo ""
        echo "Call ipw3945pwr <param>"
        echo ""
        echo "<param> may be adapter.online or adapter.offline or"
        echo "               adapter.test or acadapter.show"
        echo "In case of acadapter.test the script tries to find out the current"
        echo "state of power supply. In case of acadapter.show the state"
        echo "checked and displayed"
        echo ""
        echo "The ipw3945 operation mode is adapted accordingly."
        echo ""
        exit 1
fi
exit 0

The reason for this is simply explained. There are two other cases when you will need the status checking. Given you perform a suspend2disk or suspend2ram with AC applied and you unplug the power after that, the corresponding event will not be recognized. Therefore it is suggested to enter a reference to /usr/bin/ipw3945pwr in /etc/pm/scripts UNDER CONSTRUCTION

Given that eth0 is the wireless interface, a test

iwpriv eth0 get_power

should make it clear whether everything works as expected, the return values should differ between mains plugged and mains unplugged. This does not work if you suspend your computer when connected to mains, unplug mains and wake it up again. But, I guess that this is not what I would call a characteristic or typical mode of operation.

Activating FN-F2 and FN-F7

Both keys FN-F2 and FN-F7 create acpi events. This can be seen easily by performing a "tail -f /var/log/acpid" and pressing one of those combinations, however, in the initial state of the installation nothing happens afterwards. The following description shows how to make both keys do what you would expect them to.

FN-F2: blocking the screen as soon as FN-F2 is pressed

Firstly I have to point out that this description is referring to kde - users, I am highly convinced that there exists a similar program on gnome for locking the screen but I simply do not know (and did not test). Therefore your mileage may vary.

Locking the screen may be realized by calling: /opt/kde3/bin/kdesktop_lock --forcelock This works from within a kdesktop, however, if you perform this call from a deamon you do not have access to a X11-screen / a kde session. To circumvent this, the call is executed as the user that is currently owning the screen ":0" through sudo. See the patch for "dockhandler" below.

FN-F7: switching video outputs

Every attempt to make

echo "video_switch" > /proc/acpi/ibm/video

work failed. Luckily there is a tool available from Ken Mano at http://www16.plala.or.jp/mano-a-mano/i810switch.html that can be patched to make video switching work on x60.

The chip i945 on the x60 should be treated like a i855, so the patch that needs to be applied is:

--- i810switch-0.6.5/i810switch.c.original	2005-06-12 06:36:36.000000000 +0200
+++ i810switch-0.6.5/i810switch.c	2007-02-28 15:05:49.000000000 +0100
@@ -60,6 +60,7 @@
 #define I855STR			"8086:3582"
 //#define I865STR			"8086:2572"
 #define I915STR			"8086:2592"
+#define I945STR			"8086:27a2"
 #define MEMSTR			"Memory at"
 #define NONPRSTR		"32-bit, non-prefetchable"
 
@@ -272,7 +273,8 @@
 			return p;
 		}
 
-		i = (p = strstr(*buff_ptr, I855STR)) != NULL;
+		i = (p = strstr(*buff_ptr, I855STR)) != NULL ||
+		    (p = strstr(*buff_ptr, I945STR)) != NULL;
 		if (i)
 		{
 			*chiptype = I855;

After this, the tool should be compiled and installed. I can provide RPM's for openSUSE 10.2 on request.

What is missing now is the interfacing between FN-F7 and i810switch and i810rotate. The latter should be used as it rotates from LCD-Only - LCD+CRT - CRT-Only with every new call.

Patching dockhandler

I included this in dockutils (/usr/lib/dockutils from dockutils-01), however, there are several optional ways how to do this. The patch in use is depicted below:

--- dockhandler 2006-11-06 18:22:37.000000000 +0100
+++ dockhandler 2007-03-02 12:44:53.000000000 +0100
@@ -70,6 +70,12 @@
        elif [ "$SER" -eq 4107 ]; then # Fn+F9
            ACTION=dock
        fi
+       if [ "$SER" -eq 4098 ]; then # Fn+F2
+           ACTION=lockscreen
+       fi
+       if [ "$SER" -eq 4103 ]; then # Fn+F7
+           ACTION=videotoggle
+       fi
     elif [ "$EVENT" = "ibm/dock" ]; then
        case $VAL in
            0)  # X32 has strange dock code
@@ -81,7 +87,7 @@
     fi
 fi

-export MODEL=`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key smbios.system.version`
+export MODEL=`hal-get-property --udi /org/freedesktop/Hal/devices/computer --key smbios.system.version | sed "y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/"`

 if [ -n "`echo $MODEL | grep -i thinkpad`" ]; then
     HOOKDIR=thinkpad
--- hooks/thinkpad/60x60        2006-11-05 02:35:17.000000000 +0100
+++ hooks/thinkpad/60x60        2007-03-02 12:18:37.000000000 +0100
@@ -6,10 +6,25 @@
 #
 # This file is released under the GPLv2.
 #
+# Modifications by Dr. Ing. Dieter Jurzitza / enhanced features
+#

 . common_functions

-[ "$MODEL" == "Thinkpad X60" ] && exit 0;
+[ "$MODEL" = "THINKPAD X60" ] || exit 0;
+
+video_toggle(){
+    echo x60 video_toggle
+    /usr/sbin/i810rotate
+}
+
+lock_screen(){
+    echo x60 lock_screen
+    APPLICATION="/opt/kde3/bin/kdesktop_lock"
+    [ -f ${APPLICATION} ] || exit 0
+    USER=`/usr/bin/who -u | /bin/awk '{if(match($2, ":0")){print $1}}'`
+    sudo -u ${USER} /bin/bash -l -c "export DISPLAY=:0.0; ${APPLICATION} --forcelock &"
+}

 if [ "$1" = "dock" ]; then
     echo x60 dock
@@ -18,4 +33,12 @@
 elif [ "$1" = "undock" ]; then
     echo x60 undock
     unregister_cdroms
+
+elif [ "$1" = "videotoggle" ]; then
+    echo x60 video toggle
+    video_toggle
+
+elif [ "$1" = "lockscreen" ]; then
+    echo x60 lock screen
+    lock_screen
fi

This patch does two things: firstly it repairs a bug in dockutils. The former comparison [ "MODEL" == "Thinkpad X60" ] && exit 0; ensures that the file 60x60 is processed for each notebook not named "Thinkpad X60" what is not what was meant here.

Functionally both the FN-F2 and FN-F7 keys are tested in dockhandler. Events are assigned that are called "lockscreen" for FN-F2 and "videotoggle" for FN-F7, correspondingly. The event "lockscreen" in turn triggers the function call "lock_screen()" from within 60x60, the same holds true for the event "videotoggle" and the function call to "video_toggle". Please make sure that the path to i810rotate in "video_toggle()" fits to your system environment.

After this, both keys FN-F2 and FN-F7 should do what you expect them to do. FN-F2 is adapted for the usage of kde, so your mileage may vary if you want to adapt it to gnome or other window managers.

If you do not want to struggle with those patches, let me know. I can provide rpm's for both i810switch and dockhandler that can simply replace the original ones and provide the functionality as described above. Send me an email if you need those.

The following commentary must have been caused due to problems with transferring the code described here to the local system:

The [ "MODEL" = XXX ]; then -line has been confirmed by SuSE (dockhandler author). If you run into issues with your X60 when implementing my suggestions, don't hesitate to contact me.

I have had to revert that change on my X60 /* MODEL = .... */

This is only another way to do it - and I think the elifs aren't appropriate because you'd think all key combinations are related to the Fn+F9 toggle, what is not the case.

I did changed the upper code into

 elif [ "$SER" -eq 4107 ]; then # Fn+F9
           ACTION=dock
 elif [ "$SER" -eq 4098 ]; then # Fn+F2
           ACTION=lockscreen
 elif [ "$SER" -eq 4103 ]; then # Fn+F7
           ACTION=videotoggle
 fi

Activating the internal modem

Choosing the right modem driver

The internal modem can only be used with the hsfmodem-package that is available from http://www.linuxant.com. The current version is hsfmodem-7.60. I recommend *not* to use the "openSUSE" package but to switch to the "generic" package as the latter one rebuilds the module if the kernel version does not match. My experiments with the slmodem package have failed.

Suspend2ram / Suspend2disk issues with the modem driver

Installing this module encorporates issues with suspend2disk / suspend2ram. These are twofold. On one hand you have to make sure that the modules are being unloaded before performing a suspend2ram / suspend2disk process. Otherwise you will observe crashed. On the other hand the unloading of the intel sound module that is replaced by the hsf-package does not work as expected if i. e. kmix is running.

But step by step. First of all it must be ensured that the module is unloaded for sure if a susped2disk / suspend2 ram action should be performed. This can be achieved as follows:

This is done by placing a script in /etc/pm/hooks, I have chosen the name "08softmodem" and made it executable:

#!/bin/bash

. /etc/pm/functions

case "$1" in
        hibernate|suspend)
                /etc/init.d/hsf stop
                ;;
        thaw|resume)
                /etc/init.d/hsf start
                ;;
        *)
                ;;  
esac

exit $?

Secondly, given you want to unload this you have to make sure that the soundmodule is not bound to kmix any more. Therefore I created a second script called 06kmix located in the same directory to make sure that it is processed before the unloading of the modules is actually being processed:

#!/bin/bash

. /etc/pm/functions

KMIXPID=`ps ax | awk '{if (match($5, "kmix")){print $1}}'`

case "$1" in
        hibernate|suspend)
                kill -SIGHUP $KMIXPID
                ;;
        thaw|resume)
                ;;
        *)
                ;;
esac

exit $?

If both scripts are in place, suspending and resuming should work, however, kmix will be halted when you get out of the suspend and it will not restart automatically. I had received a suggestion to restard it using an event of kpowersaved did not work for me. But I realized it using a different technique. I created a script called /home/<username>/.kde/Autostart/restartkmix with the following contents. It should be executeable as well:

#!/bin/sh
SLEEP=10
while [ 1 ]; do
        PROCNUM=`ps ax | awk '{if(match($0," kmix")&&(!match($0,"awk"))){print $1}}'`
        if [ "${PROCNUM}" = "" ]; then
                kmix -autostart
        fi
        sleep $SLEEP
done

This generates a small amount of system load every 10 seconds but I think this is neglible. If kmix is not running it is restarted. This works perfectly for me.

Activating the fingerprint reader

There is a description of the fingerprint reader project at another location in this wiki (http://www.thinkwiki.org/wiki/Integrated_Fingerprint_Reader). The package (currently thinkfinger-0.2.2.tar.gz) should be downloaded, untared, built and installed. After that, you will have to do three things in addition:

1.) you need to modify /etc/pam.d/common-auth:

#%PAM-1.0
#
# This file is autogenerated by pam-config. All changes
# will be overwritten.
#
# Authentication-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
#
auth    required        pam_env.so
auth    sufficient      pam_thinkfinger.so
auth    required        pam_unix2.so

the line containing pam_thinkfinger.so needs to be added.

2.) you have to add a fingerprint from you. This is precisely described in the documentation of the thinkfinger package.

3.) you should change your default displaymanager to gdm, otherwise you will be able to use the fingerprint-reader only in console applications. This can be achieved by setting

DISPLAYMANAGER=gdm

in /etc/sysconfig/displaymanager.

Eject / reinsert the ULTRA-Bay

Though there are code elements in dockhandler intended to make docking / undocking of the ULTRA-Bay work it initially didn't (for me) After ejecting the Bay I never got it back working again. An important thing to realize is that you have to press FN-F9 to eject the Bay and FN-F11 to reinsert (given you installed dockhandler).

Following some hints from the thinkpad mailing list I noticed that unloading ata_piix before ejecting and reloading it after reinserting the Bay made the Bay be recognized. This implies that you switch the harddisk mode in the setup of your notebook from COMPATIBILITY to AHCI. Before you do so you have to ensure that the AHCI-Module is included in the list of modules that are loaded at boot time and it should be loaded prior to the ata_piix module.

To do this, you have to modify /etc/sysconfig/kernel accordingly from:

INITRD_MODULES="processor thermal ata_piix fan jbd ext3 edd"

to INITRD_MODULES="processor thermal ahci ata_piix fan jbd ext3 edd"

and rebuild the initrd. If you don't do this, the laptop will not boot in AHCI-mode of the harddisk.

The corresponding modifications in /usr/lib/dockutils/common_functions are simple:

--- common_functions.original   2007-04-13 20:29:18.000000000 +0200
+++ common_functions    2007-06-24 16:04:53.000000000 +0200
@@ -6,8 +6,11 @@
 #
 # This file is released under the GPLv2.
 #
+MODPROBE="/sbin/modprobe"
+MODULE="ata_piix"

 scan_scsi_hosts() {
+    ${MODPROBE} ${MODULE}
     DEVS=`hal-find-by-property --key linux.subsystem --string scsi_host`

     for I in $DEVS; do
@@ -35,4 +38,6 @@
        echo "unregistered $SYS_PATH"
        echo 1 > $SYS_PATH/device/delete
     done
+    sleep 2
+    ${MODPROBE} -r ${MODULE}
 }

Based on this change the eject / reinsert process works smoothly on my laptop.

Kernel upgrade to 2.6.21 and solving suspend2ram / suspend2disk stability issues

Stability issues

I had been facing suspend event related stability issues with the stock distribution system from the very begin. There were consistent freezes (see "Suspend2ram / Suspend2disk issues with the modem driver") I managed to solve. On top of this I experienced repetitive crashes from both suspend2ram / suspend2disk events and had no clue how to solve them. Those events were not deterministic, say every fourth or fifth suspend event there was a crash, the behaviour of suspend2ram was worse than that of suspend2disk, but both of them weren't reliable.

Stable suspend2ram / suspend2disk

Recently I decided to upgrade from stock kernel 2.6.18.8 to kernel 2.6.21-185 because the more recent kernels are said to be more robust with regard to suspend2disk / suspend2ram. However, initially I had no luck, apparently the very same behaviour appeared. But this time I got "oopses" from the e1000 module - though there was an entry in /etc/pm/config listing it as module that should be unloaded during suspend2ram / suspend2disk since the very begin:

SUSPEND_MODULES="button e1000"

Looking into /etc/pm/hooks I found that there is a file called 50modules, meant for unloading modules specified in SUSPEND_MODULES from /etc/pm/config, However, even moving 50modules to 04modules (to process this early) did not fix the problems, the crashes remained.

I started experimenting by stopping the interface and unloading the module by hand, and now: success! Say the wire bound ethernet interface is eth0 in your case, an

ifdown eth0
rmmod e1000

immediatly before suspend2ram / suspend2disk solved my issues. After restart, I had to add a

modprobe e1000
ifup eth0

to get the interface back into life. Either the script 50modules does not do what it is meant to do or the interface must be shut down prior to unloading the module. I thought it makes sense to add a small script to let this happen automatically. Call this file i. e. 04e1000 and put it into /etc/pm/hooks, do not forget to make it executable!

#!/bin/bash

. /etc/pm/functions

case "$1" in
        hibernate|suspend)
                ifdown eth0
                rmmod e1000
                ;;
        thaw|resume)
                modprobe e1000
                ifup eth0
                ;;
        *)
                ;;
esac

exit $?

I was unable to cross check with the old kernel due to prior "experiments", so before following my path and upgrading the kernel, I strongly recommend to verify whether the manual procedure / the scriptlett alone probably solves everything and you can leave the kernel "as is". If you are not successful, you really might want to consider upgrading the kernel, too.


Generic solution / multiple network interfaces

After plugging another network interface into my X60 the name of the e1000-related network interface changed. I noticed this after new crashes with suspend2ram / suspend2disk. I decided that I didn't want to care about this any more and created a new script that unloads every network interface listed by ifconfig automatically. If you like this to happen, please consider the following script, I called it 04netmgnt.

#!/bin/bash
#
# This file makes sure that all netinterfaces and all corresponding modules
# are being shutdown at shutdown and restarted at reboot.
#
# Dr. Ing. Dieter Jurzitza, Karlsruhe, 2007
# 

LS="/bin/ls"
SED="/bin/sed"
DEBUGFILE="/etc/pm/04unloadnet.dbg"
IFNAMEFILE="/etc/pm/ifnames-tmp"
IFCONFIG="/sbin/ifconfig"
IFUP="/sbin/ifup"
IFDOWN="/sbin/ifdown"
MODPROBE="/sbin/modprobe"
RMMOD="/sbin/rmmod"

SYS="/sys/class/net/"
SPATH="/device/driver/module/drivers/"

function getnetifnames(){
	# call ifconfig, remove everything but interface-names!
	# and remove "lo" since there is nothing to unload!
	INTERFACES=(`${IFCONFIG} | ${SED} 's/[[:space:]].*//g;/^lo$/d;/^$/d'`)
	# now we know all network interface names

	# save those temporarily to $IFNAMEFILE, we need this at next restart.
	# $INTERFACES is an array of the names we find.
	i=0
	echo -n "declare INTERFACES=(" > ${IFNAMEFILE}
	while [ "${INTERFACES[$i]}" != "" ]; do
		echo -n "${INTERFACES[$i]}" >> ${IFNAMEFILE}
		i=`expr ${i} + 1`
		if [ "${INTERFACES[$i]}" != "" ]; then
			echo -n " " >> ${IFNAMEFILE}
		fi
	done
	echo ")" >> ${IFNAMEFILE}

	# now find the modules that belong to those interfaces!
	# Same as before, now $MODULES is an array of modules corresponding
	# to $INTERFACES
	i=0
	while [ "${INTERFACES[$i]}" != "" ]; do
		MODULES[$i]=`${LS} ${SYS}${INTERFACES[$i]}${SPATH} | ${SED} 's/.*://g'`
		i=`expr $i + 1`
	done 

	# and write them to $IFNAMEFILE to store for the next reboot!
	# Just like before.
	i=0
	echo -n "declare MODULES=(" >> ${IFNAMEFILE}
	while [ "${MODULES[$i]}" != "" ]; do
		echo -n "${MODULES[$i]}" >> ${IFNAMEFILE}
		i=`expr ${i} + 1`
		if [ "${MODULES[$i]}" != "" ]; then
			echo -n " " >> ${IFNAMEFILE}
		fi
	done	
	echo ")" >> ${IFNAMEFILE}
} 

function restartnetif () {
	if [ -f ${IFNAMEFILE} ]; then
		. ${IFNAMEFILE}
		i=0
		# ok. On startup, load each module and start the corresponding
		# interface
		while [ "${MODULES[$i]}" != "" ]; do
			# just in case we'd like to see what happens.
			# echo "${MODPROBE} ${MODULES[i]}" >> ${DEBUGFILE}
			# echo "${IFUP} ${INTERFACES[i]}" >> ${DEBUGFILE}
			${MODPROBE}  ${MODULES[$i]}
			${IFUP} ${INTERFACES[$i]}
			i=`expr ${i} + 1`
		done
		rm -f ${IFNAMEFILE} > /dev/null 2>&1
	fi
} 

function shutdownnetif () {
	declare -a INTERFACES
	declare -a MODULES
	getnetifnames
	i=0
	# ok. On shutdown, shut each interface down and unload the corresponding
	# module.
	while [ "${MODULES[$i]}" != "" ]; do
		${IFDOWN} ${INTERFACES[$i]}
		${RMMOD}  ${MODULES[$i]}
		i=`expr ${i} + 1`
	done
} 

case "$1" in
	hibernate|suspend)
	shutdownnetif
	;;
	thaw|resume)
	restartnetif
	# and finally restart the entire network!
	/etc/init.d/network restart
	;;
	*)
	;;
esac
exit $?

The script tries to detect each network interface automatically and determins the corresponding module. At suspend2ram / suspend2disk the interface is shut down and the module is unloaded. At resume the inverse process occurs. In order to "save state" the modules names / interface names are written into a temporary file that is removed after the next restart.

As always, if you consider playing with this and you think that errors can happen to easily while typing, I'd be pleased to provide the script if you like to try.

If you get the impression that there is something going wrong, you might want to try to keep the configuration files over a reboot. Just put a pound sign in front of the line

rm -f ${IFNAMEFILE} > /dev/null 2>&1

and you should be able to see what is written into /etc/pm/ifnames-tmp. Here it looks like:

declare INTERFACES=(eth0 eth1)
declare MODULES=(ipw3945 e1000)

These are two arrays apparently ok - this might vary as you put different network interfaces into your pcmcia slots or into one of the usb ports. Keep me informed if you experience something going wrong.

Kernel upgrade procedure

I downloaded the latest kernel from ftp.gwdg.de/pub/opensuse/repositories/Kernel:/HEAD/openSUSE_10.2. However I found that this branch has vanished in the meantime. So I suggest that if you are brave and you still want to install a kernel from the 2.6.21 series (as I did) you should use the one from the SL-OSS-factory tree:

ftp.gwdg.de/pub/opensuse/distribution/SL-OSS-factory/inst-source/suse/i586/kernel-default-2.6.21-12.i586.rpm

but be aware, I did not test it on my own until now (but this is on my todo list. I will test as soon as openSUSE 10.3 is released). Nevertheless I do not expect big differences to the kernel-default-2.6.21-185.i586.rpm I used from the path mentioned first in this chapter.

Between kernel 2.6.18 and 2.6.21 there were significant changes in the wlan interface. Due to this you should download and rebuild the following packages:

- the ipw3945 kernel module (ipw3945-kmp-default-1.2.0_2.6.21_12-3.i586.rpm), otherwise wlan won't work. 
  ipw3945d-1.7.18-31.i586.rpm can remain as-is, it need not be changed. The same is valid for ipw-firmware-7-31.i586.rpm.
- wpa_supplicant should be downloaded as source - rpm, recompiled and reinstalled. I used wpa_supplicant-0.5.7-21.src.rpm.
- madwifi should be upgraded, too. Download the source - rpm (madwifi-0.9.3-18.src.rpm), install it, rebuild the i586-rpm and install it.

After this you will still face the problem that wlan does not work - though the drivers are being loaded, you will get no connection to the wlan. This is caused by getcfg not returning the appropriate values. To circumvent this problems, you have to write

WIRELESS='yes'

into /etc/sysconfig/network/ifcfg-wlan-bus-pci-0000:03:00.0. Be aware that this is required every time you modify the wlan configuration. The only alternative would be to patch getcfg.

Getcfg is part of the package sysconfig, so you will have to get the sources for sysconfig and patch there. The required patch is shown here:

--- tools/get_config_lib.c.original	2007-05-24 22:19:33.000000000 +0200
+++ tools/get_config_lib.c	2007-05-24 22:19:25.000000000 +0200
@@ -31,6 +31,7 @@
 int syslog_verbosity = LOG_EMERG;
 char syslog_name [MAX_HWDESC_PART_LEN] = {'\0'};
 const char *hwdesc_type_names[] = { HWDESC_TYPE_NAMES };
+const char *hwdesc_interface_names[] = { HWDESC_INTERFACE_NAMES };
 const char *hwdesc_bus_names[] = { HWDESC_BUS_NAMES };
 
 void error_log(int level, const char* message, ...) {
@@ -87,6 +88,11 @@
 		   hwdesc->interfacepath[i]);
 	    sprintf(varname, " %s_INTERFACEPATH_%d", prefix, i);
 	    strcat(varlist, varname);
+	    if (!strcmp(hwdesc->interfacetype[i], hwdesc_interface_names[4])){
+		   adjust_network_type(hwdesc, i);
+		   strcpy(hwdesc->interfacetype[i], 
+				get_interface_name(hwdesc->interfaceclass[i]));
+	    }
 	    printf("%s_INTERFACETYPE_%d=\"%s\";\n", prefix, i, 
 		   hwdesc->interfacetype[i]);
 	    sprintf(varname, " %s_INTERFACETYPE_%d", prefix, i);

This is nothing but a plaster, however, this works for me.

Power consumption when running on battery

The stock openSUSE kernels seem not to be optimized for low power consumption of the notebook. After the upgrade to 2.6.21 experimenting was started with a very interesting tool that can provide a lot of information regarding the power consumption of the laptop. It is called powertop and may be downloaded from http://www.linuxpowertop.org.

To efficiently use it (and anticipate some of it's findings) modifications of the kernel configuration are shown here that helped to reduce the power consumtpion and in turn prolong the operating time when running from battery. Please note that this information refers to kernel 2.6.21 and may need adaptations for other kernel releases:

CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_USB_SUSPEND=y
CONFIG_TIMER_STATS=y /* openSUSE default */
CONFIG_HPET_TIMER=y /* openSUSE default */
CONFIG_HPET=y /* openSUSE default */
CONFIG_CPU_FREQ_GOV_ONDEMAND=m  /* openSUSE default */
CONFIG_CPU_FREQ_STAT=m /* openSUSE default */
CONFIG_SND_AC97_POWER_SAVE=y /* openSUSE default */
CONFIG_ACPI_BATTERY=m /* openSUSE default */

The list of relevant kernel options is available in the powertop's faq. All those options are activated on the standard Fedora 7 and Ubuntu Gutsy kernels.

It is hard to tell the impact of one single of those modifications with respect to power consumption. The "CONFIG_TIMER_STATS" option is mainly meant to make powertop work at it's best, HPET, USB_SUSPEND, NO_HZ and AC97_POWER_SAVE helps in saving power. A part of these options are enabled by default in the openSUSE kernel config (see notes in the list above). Others are compiled in as modules and can stay that way.

When running on mains the X60 draws about 15 W power. In contrast, given the above mentioned modifications were implemented and the device is only running calmly about 10 W power consumption from battery can be reached. It is important to dim the display as much as anyhow acceptable because the display consumes a decent amount of the total power.

To keep the power consumption low it is a good idea to uninstall the hsf-modem driver as it generates many wakeup events and hence a decent amount of power consumption. Moreover though zen is disabled there is one zen-updater Process creating regular wakeup events, killing it may also be beneficial with regard to the total power consumption of the device. Even if you disable novell-zmd in the system configuration this process keeps being started. You will recognize a red square with a cross in it after each and every restart of the desktop - wether you finalize it and store the session or you don't. This is something suse should consider fixing, this behaviour is annoying.

To get rid of this one can uninstall the related rpm: rpm -e zen-updater will make opensuseupdater to take it's place. Apparently it is less power consuming, but one may simply uninstall this program, too. rpm -e opensuse-updater (the dash is neccessary) will remove this.

Emacs is a bad boy in this regard, too. It creates wakeup-events for the CPU. Therefore if you do not use it constantly it may be a good idea to turn it off.

If it is not intended to send the device to sleep but even more power should be saved instantaneously it may be helpful to use FN-F7 (configuration can be found at another location in this document) to really turn the LCD off. This saves another 2 Watts approximately, so one may come down to about 8W power consumption when the device is idle.

PCMCIA - slot

There is nothing special to say about the PCMCIA-slot. It just works (for me).

Integrating an (old) SIEMENS IGATE 11M PCMCIA-wlan card

I own an old IGATE 11M card (still fine for just surfing) I wanted to test on openSUSE 10.2. Unfortunately it did not work out of the box, so I describe here what I did to get it going. This issue is an openSUSE 10.2 problem and not specific to this wlan card.

The card is based on a prism chipset for which several linux drivers are available (hostap, orinoco ..). When I used to work with SUSE 9.3 I had had success with the hostap driver so I had planned to use it here, too.

Yast2 nicely detects the card and allows to configure everything including the appropriate encryption settings (wpa psk in this case). In /etc/sysconfig/hardware/hwcfg-bus-pcmcia-0.0 the hostap driver is entered so initially everything seemed to be alright.

However, the card was not working and I found that the orinoco driver had had been loaded - this was astonishing as YaST2 wrote "hostap_cs" into /etc/sysconfig/hardware/hwcfg-bus-pcmcia-0.0. This problem is caused by an error in /etc/modprobe.d/prism2. It causes the orinoco driver to always be loaded what messes up the entire configuration. Even worse, "hostap" was not loaded at all.

In order to circumvent this problem, the file /etc/modprobe.d/prism2 should be modified. It basically contains a list of keys that ought to assign each individual (pcmcia-) card to a specific driver. Unfortunately there is an aliasing phenomenon so there are two matches for the SIEMENS IGATE 11m card - one for the orinoco driver, one for the prism2 driver (and none for hostap!). The orinoco driver does not work with the card, the prism driver is not installed. A pointer to hostap is missing in the file.

To fix this, the following patch should be applied:

--- prism2.original     2006-11-25 16:50:35.000000000 +0100
+++ prism2      2007-05-28 10:36:46.000000000 +0200
@@ -58,7 +58,7 @@
 alias pcmcia:m*c*f*fn*pfn*pa71B18589pbB6F1B0ABpc4B74BAA0pd* hostap_cs
 alias pcmcia:m*c*f*fn*pfn*pa71B18589pbF144E3ACpc*pd* orinoco_cs
 alias pcmcia:m*c*f*fn*pfn*pa71B18589pbF144E3ACpc4B74BAA0pd00000000* prism2_cs
-alias pcmcia:m*c*f*fn*pfn*pa74C5E40Dpb8304FF77pc4B74BAA0pd* prism2_cs
+alias pcmcia:m*c*f*fn*pfn*pa74C5E40Dpb8304FF77pc4B74BAA0pd* hostap_cs
 alias pcmcia:m*c*f*fn*pfn*pa74C5E40DpbDB472A18pc*pd* hostap_cs
 alias pcmcia:m*c*f*fn*pfn*pa78FC06EEpb45A50C1Epc*pd* prism2_cs
 alias pcmcia:m*c*f*fn*pfn*pa78FC06EEpbDB9AA842pc*pd* prism2_cs
@@ -84,7 +84,6 @@
 alias pcmcia:m0101c0777f*fn*pfn*pa*pb*pc*pd* hostap_cs
 alias pcmcia:m0126c8000f*fn*pfn*pa*pb*pc*pd* hostap_cs
 alias pcmcia:m0138c0002f*fn*pfn*pa*pb*pc*pd* hostap_cs
-alias pcmcia:m0156c0002f*fn*pfn*pa*pb*pc*pd* orinoco_cs
 alias pcmcia:m01EBc080Af*fn*pfn*pa*pb*pc*pd* orinoco_cs
 alias pcmcia:m01FFc0008f*fn*pfn*pa*pb*pc*pd* prism2_cs
 alias pcmcia:m0250c0002f*fn*pfn*pa*pb*pc*pd* hostap_cs

This basically removes the reference to the orinoco driver and adds one to the hostap driver. This makes the card work (for me). However, it should be denoted that this may or may not work for other wlan cards that might rely on orinoco / prism2. But probably this is an useful hint where to search for potential issues.

openSUSE specific issues

Make irqbalancer work

If you installed the "irqbalancer" package you probably realized that it is not running. Calling "/etc/init.d/irq_balancer status" will return "unused". Doing a "cat /proc/interrupts" will show all interrupts on CPU 0, CPU 1 will not process any interrupt. To solve this problem you should edit /etc/init.d/irq_balancer manually. Change the line

start)
        echo -n "Starting irqbalance "
        if [ $PHYS -gt 1 ] || [ $PROC -gt 1 -a $PHYS -eq 0 ] ; then

into

start)
        echo -n "Starting irqbalance "
        if [ $PHYS -gt 1 ] || [ $PROC -gt 1 -a $PHYS -eq 1 ] ; then

$PHYS should be compared to 1, not to 0. After restarting irq_balancer, the interrupts should be shared between cpu 0 and cpu 1 now. The important point is the change from $PHYS -eq 0 to $PHYS -eq 1.

This issue has been fixed recently, you can download irqbalance-0.55-12.src.rpm from OSS-factory tree, build and install (or you live with the small change as shown above!)

Avoiding duplicate s2ram / s2disk events

To provide certain functionality openSUSE 10.2 still keeps both pm-utils and powersave active. In future versions powersave shall vanish. For thinkpads the file /usr/lib/powersave/thinkpad_acpi_events takes care of those events. Unfortunately the s2ram and s2disk events are treated both in pm-utils and in powersave. This can have unwanted side effects; depending on the speed of action the powersave actions may be faster than the pm-util actions, thereby certain modules that should be removed might not be appropriately.

To get out of these problems it is highly recommended to modify the file /usr/lib/powersave/thinkpad_acpi_events accordingly. The following patch provides all neccessary changes to ensure this. This patch is against the source package of powersave.

--- scripts/thinkpad_acpi_events        2006-11-24 15:33:11.000000000 +0100
+++ scripts/thinkpad_acpi_events        2007-04-16 11:10:07.000000000 +0200
@@ -91,11 +91,7 @@
                     ACTION="blank screen"
                 fi
                 ;;
-            4100)   HOTKEY="Fn+F4"
-                ACTION="suspend-to-ram"
-                . $SYSCONF_DIR/sleep
-                [ "$DISABLE_USER_SUSPEND2RAM" != "yes" ] && powersave "--$ACTION"
-                ;;
+            4100)   HOTKEY="Fn+F4" ;;
             4101)   HOTKEY="Fn+F5" # Wireles LAN
                 if [ -x /opt/thinkpad/ac/onscreen_ac.sh ] ; then
                     run_on_xserver "/opt/thinkpad/ac/onscreen_ac.sh start" &
@@ -109,29 +105,16 @@
                 fi
                 ;;
             4102)   HOTKEY="Fn+F6" ;;
-            4103)   HOTKEY="Fn+F7"
-                ACTION="swap monitors"
-                echo video_switch > /proc/acpi/ibm/video
-                ;;
+            4103)   HOTKEY="Fn+F7" ;;
             4104)   HOTKEY="Fn+F8" ;;
-                # ACTION="expand screen"
-                # echo expand_toggle > /proc/acpi/ibm/video
-            4105)   HOTKEY="Fn+F9"
-                # ACTION="undock"
-               # handled by dockutils
-                ;;
+            4105)   HOTKEY="Fn+F9" ;;
             4106)   HOTKEY="Fn+F10" ;;
             4107)   HOTKEY="Fn+F11" ;;
-            4108)   HOTKEY="Fn+F12"
-                ACTION="suspend-to-disk"
-                . $SYSCONF_DIR/sleep
-                [ "$DISABLE_USER_SUSPEND2DISK" != "yes" ] && powersave "--$ACTION"
-                ;;
+            4108)   HOTKEY="Fn+F12" ;;
             4109)   HOTKEY="Fn+Backspace" ;;
             4110)   HOTKEY="Fn+Insert" ;;
             4111)   HOTKEY="Fn+Delete" ;;
-            4112)   HOTKEY="Fn+Home"
-                    ACTION="brighter display" ;;
+            4112)   HOTKEY="Fn+Home" ;;
             *)      HOTKEY="Unidentified" ;;
         esac
     else



What doesn't work yet

  • Xinerama with external LCD
  • Dual head with external LCD

What I haven't tested yet

  • Embedded Security Subsystem (TCPA)
  • Active Protection System (HDAPS)
  • Maximum battery life

lscpi

> lspci
00:00.0 Host bridge: Intel Corporation Mobile 945GM/PM/GMS/940GML and 945GT Express Memory Controller Hub (rev 03)
00:02.0 VGA compatible controller: Intel Corporation Mobile 945GM/GMS/940GML Express Integrated Graphics Controller (rev 03)
00:02.1 Display controller: Intel Corporation Mobile 945GM/GMS/940GML Express Integrated Graphics Controller (rev 03)
00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller (rev 02)
00:1c.0 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 1 (rev 02)
00:1c.1 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 2 (rev 02)
00:1c.2 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 3 (rev 02)
00:1c.3 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 4 (rev 02)
00:1d.0 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI #1 (rev 02)
00:1d.1 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI #2 (rev 02)
00:1d.2 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI #3 (rev 02)
00:1d.3 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI #4 (rev 02)
00:1d.7 USB Controller: Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller (rev 02)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev e2)
00:1f.0 ISA bridge: Intel Corporation 82801GBM (ICH7-M) LPC Interface Bridge (rev 02)
00:1f.1 IDE interface: Intel Corporation 82801G (ICH7 Family) IDE Controller (rev 02)
00:1f.2 SATA controller: Intel Corporation 82801GBM/GHM (ICH7 Family) Serial ATA Storage Controller AHCI (rev 02)
00:1f.3 SMBus: Intel Corporation 82801G (ICH7 Family) SMBus Controller (rev 02)
02:00.0 Ethernet controller: Intel Corporation 82573L Gigabit Ethernet Controller
03:00.0 Network controller: Intel Corporation PRO/Wireless 3945ABG Network Connection (rev 02)
15:00.0 CardBus bridge: Ricoh Co Ltd RL5c476 II (rev b4)
15:00.1 FireWire (IEEE 1394): Ricoh Co Ltd R5C552 IEEE 1394 Controller (rev 09)
15:00.2 Generic system peripheral [Class 0805]: Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (rev 18)