Slackware Linux on a Lenovo ThinkPad X121e

Last updated: January 23 2014

Some notes on installing Slackware Linux 13.37 on my shiny new Lenovo ThinkPad X121e. This machine is my first Thinkpad; it replaces my previous Netbook (a Samsung NC10) that was stolen from a hostel. I chose the X121e as a replacement because it was tweakers.net's Best Buy Netbook for April 2012, and I'd heard a lot of positive things about Thinkpads' build quality and Linux compatibility. I don't particularly care about multimedia chops or ultralightness, but I do care about battery life, build quality and keyboard kinetics, and on those fronts, this machine delivers.

The body is less rigid than I'd like it to be (the case flexes noticeably if you apply torque), but the construction itself appears to be robust, including the screen hinges, which feel appropriately sturdy. The flexibility of the case is not necessarily a bad thing, because it lets the body absorb some force where a more rigid laptop would crack or shatter. The keyboard is quite large and nice to type on. The machine may be slightly larger than the average netbook, but it pays back in keyboard width. The core keys have a pleasant spacing. The function keys are, as usual in this category, a bit cramped, but usable. The keys have a fair amount of travel and a clear pressure point, and typing on them is no curse.

This guide is written for the "red top" ThinkPad X121e with the AMD E-450 APU and slow harddisk, model code NWS66MH. Hardware varies considerably between the different X121 models, so your mileage with these instructions may vary.

The red lid: how bad is it?

The X121e has a garish red lid. Judging from online product shots, there seemed to be a chance of it being a tacky, plastic Ferrari-like piece of trim. Placing my order, I was a bit unsure about how it would turn out, but fortunately things went fine. To my pleasant surprise the finish is a dark deep metallic red with a dull lustre that is miles from being cheesy. The red coating is slightly rubbery and has a satiny quality that pleases the touch. Honestly I'd still prefer black, but the red finish is very elegantly executed and has to be seen in real life to be appreciated.

Snapshotting the factory install

My X121e came with a copy of Windows 7 Home Professional. I wouldn't have minded a version without an OS, but since I couldn't find a domestic online shop that offered one, I settled for the Microsoft tax. Perhaps it might come in handy to have a copy of Windows 7 around somewhere in case I need it, and it could serve as a reference to the Linux install.

After switching on the X121e for the first time, I made a copy of all partitions by network booting the PING Live CD. Having a bit copy of these install partitions allows me to return the laptop to factory new state at any time. The way the Win7 install is set up, you have to choose an installation language at setup time, which becomes a permanent setting as the installer throws away the other available languages. You can opt to make a "factory restore disk" after Windows finishes installing, but this method is superior.

Repartitioning the disk

After playing with my shiny new toy in Windows for a few days and being amazed at the amount of crapware that manufacturers install by default (yes, Norton is there, and yes, there are a ton of Thinkpad utilities that run at startup), it was time to partition the disk and install Slackware Linux. I did this by booting the GParted Live distro over the network (PXE) and cutting up the main Windows partition (some 250GB) into a part for Windows and a part for Linux. I decided on 100GB for Windows (because who knows when I might need it), and 150GB for Slackware. Since I try not to keep any data on my mobile devices that I can't afford to lose, that should be more than enough. GParted successfully split the Windows partition off into a Linux partition, and turned this Linux partition into an extended partition containing a tiny boot and a large main partition. The tiny boot partition will hold the kernel and the initrd, and the large main partition will become my encrypted root.

Full harddisk encryption

The Slackware install will be fully encrypted at the partition level, underneath the filesystem level even, using LUKS and LVM. This is the Linux version of full disk encryption. Anything less on a mobile device seems unwise to me. My previous netbook, the one that was stolen from a hostel, was also encrypted this way, and I got tremendous peace of mind after the fact from being certain that the thief may have the aging hardware, but never the data. (Obviously, the little data that was on there was also backed up externally.) Why not take the extra steps? Theoretically there is some overhead to encrypting everything that goes to disk, but when you have 4GB of memory for the Linux kernel to cache files in, and a decent writeback delay to minimize the commits to disk (I use 15 seconds, also for power saving reasons), you'll never notice it.

For instructions about the actual creation of the LVM partition and encrypting it, I defer to the README_CRYPT.TXT file on the Slackware installation CD. The process is pretty involved, but not hard to follow if you've ever worked with LVM and/or LUKS. It boils down to: create an encrypted partition, open it by entering your password, then turn the opened partition into an LVM volume. The rest of the instructions are the same as installing Slackware on LVM. Finish up by installing the proper initrd. When the kernel boots from the tiny unencrypted boot partition, it needs a small environment with LUKS support to be able to mount its encrypted. This tiny environment is the initrd. The README explains all of this, and more, in a step by step fashion.

After installing the OS, writing the LILO bootloader to the MBR worked without a hitch. In the rest of this article I'll focus on how to get all the hardware working. For this we need to compile our own kernel, because the stock kernel from Slackware 13.37 is too old. Compiling a vanilla kernel for a distro as simple and modular as Slackware is not as difficult as it sounds, but the instructions on how to do it are widely out of scope here. I used the newest kernel at the time of writing, the 3.3.3 release.

Network card

lspci reports the ethernet card is an "Atheros Communications Device 1083 (rev c0)". The 3.3.3 kernel supports it with the atl1c module. The 2.6.37 Slackware install kernel did have the atl1c module, but did not recognize the card. Annoying when you're trying to pull all your packages off a webserver. This tip from the Debian wiki saved the day. Go to a second terminal with Alt-F2 while you're in the installer and type:

modprobe atl1c
echo "1969 1083" > /sys/bus/pci/drivers/atl1c/new_id
ifconfig eth0 up

And we have a card. This should not be necessary in any recent kernel.

Integrated camera

The integrated camera is an UVC (USB Video Class) device, supported by the uvcvideo kernel module. I chose to compile uvcvideo as a separate module so that I can unload it to save power. My old Netbook had a similar camera that was always-on and sapped power, but that's probably not an issue on the X121e, because the camera knows when to switch itself on and off. (It has a little green LED that comes on when the camera is active).

Checking the camera with mplayer -v tv:// shows that everything is working fine.

Wifi card

If you believe lsusb, the wifi card is a Realtek RTL8188CE, but it's probably actually a RTL8192CE since it's supported by kernel module rtl8192ce. It loads a firmware file called rtl8192cfw.bin which is not supplied with kernel 3.3.3 (or perhaps I'm not building the firmware correctly), but which is available from the kernel firmware repository; copy it to /lib/firmware/rtlwifi/rtl8192cfw.bin.

Kernel 3.13 introduces a new config variable, CONFIG_RTL_CARD, which enables support for the various rtl8192* drivers. You can find this option in Device DriversNetwork device supportWireless LANRealtek rtlwifi family of devices. Also enable the proper modules for your card, for me it's CONFIG_RTL8192CE. The firmware blob is not shipped with the vanilla kernel, so you will still need to install it manually.

Card reader

A Realtek "Device 5209". So new that the driver is in staging. Kernel 3.3.3 supports it with Realtek's rts_pstor module, turned on by the CONFIG_RTS_PSTOR config option.

As of kernel 3.10 or so, the rts_pstor module is no longer included in the kernel, and the old code will not compile. There is a patch floating around to make it compile on 3.10, but a native driver has also become available. To get support for the Realtek 5209 in later kernels, you have to enable CONFIG_MFD_RTSX_PCI (in Device DriversMultifunction device driversRealtek PCI-E card reader) and CONFIG_MMC_REALTEK_PCI (in Device DriversMMC/SD/SDIO card supportRealtek PCI-E SD/MMC Card Interface Driver). Due to the driver change, your card will no longer show up as /dev/sdb1, but as something funky like /dev/mmcblk0p1.

Video card

Getting the Radeon HD 6320 graphics card up and running at full speed took some work. The kernel supports the HD 6320 through the radeon module, which loads some firmware blobs at startup. It took me a long time to figure out which firmware files to supply, but the output of dmesg will tell you which files the kernel tries to locate. For me, it's the SUMO* collection, which the kernel expects to find in the /lib/firmware/radeon directory. These files are not in the kernel tree at the time of writing, but you can download them from the kernel firmware repository. I decided to include them directly in the kernel blob since they're small enough and so I don't have to include them in my initrd:

CONFIG_EXTRA_FIRMWARE="radeon/SUMO_me.bin radeon/SUMO_pfp.bin radeon/SUMO_rlc.bin radeon/SUMO_uvd.bin"
CONFIG_EXTRA_FIRMWARE_DIR="firmware"

Radeon power management for the PALM/SUMO family was added in kernel 3.11 "Linux for Workgroups", but disabled by default and hidden behind a tuning option. Kernel 3.13 enables it by default.

I wanted a nice full-resolution console at bootup because I do real work on the console and not everything justifies booting into X when you're running on battery, so I enabled kernel modesetting on the radeon driver. There's also a kernel option that makes it default to always-on. However, I was still getting the usual vga console. The trick is, and this cost me a lot of trial and error, to remove all vga= parameter lines from lilo.conf and to remove all framebuffer console drivers from the kernel configuration, except for fbcon. If you don't specify anything and let the kernel figure things out, the initial boot will be the 80×25 console, but as soon as the radeon module loads, fbcon and the radeondrmfb framebuffer take over and produces a gorgeous native 1366×768 pixel console.

To use the Radeon HD 6320 in X.org, you need a really recent copy of the xf86-video-ati driver. Really recent means that you have to check the latest version out of the git repository and build it yourself. The 6.10.0 version included with Slackware 13.37 was definitely too old, and even the 6.14.0 release didn't detect the card. With the self-built version, everything almost works under X, were it not for the fact that with the stock X server from Slackware 13.37, once the card has been taken over by X, it could never revert to framebuffer mode. Log out of the graphic desktop and the screen would freeze and melts into whiteness, which was weird and unsettling, not to mention impractical. This was fixed in the latest X server build from slackware-current.

Sound card

The card is an ATI "device 1314", or an ATI Technologies Inc SBx00 Azalia (Intel HDA). The audio chip is a Conexant CX20590. The card is supported in ALSA by the snd_hda_intel driver. Somewhere between kernel 3.3.3 and 3.5.2, the control interface (the switches in alsamixer) grew from just a volume slider to a full set of sliders for master, headphones and speaker. You also need the HDMI and Conexant codec modules, namely snd_hda_codec_hdmi and snd_hda_codec_conexant.

In ALSA, three sound cards show up:

#0: HD-Audio Generic
#1: HDA ATI SB
#29: ThinkPad Console Audio Control

The ThinkPad Console Audio Control is provided by the thinkpad_acpi module. I think it's a phantom device that reflects a piece of hardware that only more expensive "real" Thinkpads have, because no matter with which parameters I load the thinkpad_acpi module, or how I hack /etc/asound.conf, I cannot make the control do anything. Likewise, the HD Audio Generic device appears to be a placeholder and not a device that can play sounds. To make our real sound card the default sound sink, we have to create or edit /etc/asound.conf:

# Make sound card #1 the default audio device:
pcm.!default {
	type hw
	card 1
}
ctl.!default {
	type hw
	card 1
}

You can apparently also pass the index=0 argument to the snd-hda-intel module to force the card to be #0, but that didn't work for me. After getting sound working, I noticed that the headphone jack did not work (did not recognize plug events). I added the following line to /etc/modprobe.d/alsa-base.conf:

options snd-hda-intel model=thinkpad

I also recompiled the kernel and turned on some hopeful options like jack hotplugging notification. I don't know what exactly solved the problem, but when the new kernel booted with the new option line, jack hotplugging worked.

HDAPS

HDAPS is a safety system that monitors accelerometers to figure out when the laptop is in free fall, so that the harddisk heads can be parked before the laptop hits the ground. Awesome, and running the Active Protection System diagnostic program under Windows shows that the X121e does in fact have the accelerometers built in.

The HDAPS driver in the 3.3.3 kernel does not recognize the X121e because it doesn't know about the X121e's particular BIOS identifier string (vendor "LENOVO", model "ThinkPad X121e"). I patched hdaps.c to recognize the identifier string and recompiled. Now the driver did load and created the device files, but reading from the device files produced nothing but i/o errors. I conclude that the X121e is not supported by the in-kernel hdaps module at the current time.

tp_smapi

What about tp_smapi? This out-of-mainline kernel module exposes system settings through sysfs, and patches the mainline hdaps driver. I downloaded the latest version (0.41) from Github and built it into the kernel. This gives us /sys/devices/platform/hdaps and /sys/devices/platform/smapi. Now can we read some HDAPS info?

root@thinkbook:/sys/devices/platform/hdaps# cat *
(0,0)
0
cat: keyboard_activity: Device or resource busy
platform:hdaps
cat: mouse_activity: Device or resource busy
cat: oversampling_ratio: Device or resource busy
cat: position: Device or resource busy
cat: power: Is a directory
cat: running_avg_filter_order: Device or resource busy
50
cat: subsystem: Is a directory
cat: temp1: Device or resource busy
MODALIAS=platform:hdaps

That's a no. The '50' is from sampling_rate, which is probably just a property of the driver. What about the smapi directory, does it contain anything interesting?

root@thinkbook:/sys/devices/platform/smapi# cat *
cat: BAT0: Is a directory
cat: BAT1: Is a directory
cat: ac_connected: Device or resource busy
cat: driver: Is a directory
platform:smapi
cat: power: Is a directory
cat: subsystem: Is a directory
DRIVER=smapi
MODALIAS=platform:smapi

root@thinkbook:/sys/devices/platform/smapi# cd BAT0
root@thinkbook:/sys/devices/platform/smapi/BAT0# cat *
cat: barcoding: No such device or address
cat: charging_max_current: No such device or address
cat: charging_max_voltage: No such device or address
cat: chemistry: No such device or address
cat: current_avg: No such device or address
cat: current_now: No such device or address
cat: cycle_count: No such device or address
cat: design_capacity: No such device or address
cat: design_voltage: No such device or address
cat: dump: Device or resource busy
cat: first_use_date: No such device or address
cat: force_discharge: Operation not supported
cat: group0_voltage: No such device or address
cat: group1_voltage: No such device or address
cat: group2_voltage: No such device or address
cat: group3_voltage: No such device or address
0
cat: installed: Device or resource busy
cat: last_full_capacity: No such device or address
cat: manufacture_date: No such device or address
cat: manufacturer: No such device or address
cat: model: No such device or address
cat: power_avg: No such device or address
cat: power_now: No such device or address
cat: remaining_capacity: No such device or address
cat: remaining_charging_time: No such device or address
cat: remaining_percent: No such device or address
cat: remaining_percent_error: No such device or address
cat: remaining_running_time: No such device or address
cat: remaining_running_time_now: No such device or address
cat: serial: No such device or address
cat: start_charge_thresh: Operation not supported
none
100
cat: temperature: No such device or address
cat: voltage: No such device or address

So far, nothing. I conclude that tp_smapi and hdaps do currently not support the X121e, so that HDAPS does currently not work.

thinkpad_acpi

This kernel module promises to deliver extras to ThinkPad users. It gives us the /sys/devices/platform/thinkpad_acpi directory, and the ALSA device #29, the Thinkpad Console Audio Control, which as far as I can tell does nothing. The most interesting information to me is the power directory, but like with tp_smapi, the files in there are useless (show zero on a laptop running on battery). The value of this module is primarily that it enables the hotkeys. Build this as a module, so that you can play with its many load-time parameters, flags and options.

thinkpad_hwmon

Can this module get information from the hardware? The fan readout works:

root@thinkbook:~# cat /sys/devices/platform/thinkpad_hwmon/fan1_input
567

This readout is also available through cat /proc/acpi/ibm/thermal. The temperature sensors work and give values in milli-degrees, as confirmed by doing cat /proc/acpi/ibm/thermal. The other temp* files in that directory all read zero. Reading the power settings does not work.

root@thinkbook:~# cat /sys/devices/platform/thinkpad_hwmon/temp1_input
49000
root@thinkbook:~# cat /sys/devices/platform/thinkpad_hwmon/temp3_input
49000
root@thinkbook:~# cat /sys/devices/platform/thinkpad_hwmon/temp3_input
30000

Reading the battery state

Despite not being able to find the power readings among the thinkpad module outputs, I noticed that somehow the XFCE power manager did report the correct charge on the battery. I investigated this and found that the battery status is available on the system in the very depths of sysfs. On my system:

root@thinkbook:~# cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/energy_full
63710000
root@thinkbook:~# cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/energy_now
54690000
root@thinkbook:~# cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/power_now
18873000

There's more in that directory. I assume that power_now is in microwatts, in which case my machine would be consuming 18.87 watts of power. If the energy_full output is in micro-watt-hours, I could run my laptop for 3.38 hours at the current power level. That's while working on AC without CPU frequency scaling and so on. When I unplug the laptop, power usage drops to around 12W, which comes to around 5.3 hours of usage. And that's before I've made some power saving tweaks.

Here's a small script I use to summarize the battery status:

battery.sh

#!/bin/sh

ENERGY_FULL=`cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/energy_full`
ENERGY_NOW=`cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/energy_now`
POWER_NOW=`cat /sys/bus/acpi/drivers/battery/PNP0C0A\:00/power_supply/BAT1/power_now`

echo "Battery left: $((ENERGY_NOW * 100 / ENERGY_FULL))%"
echo "Current usage: `echo $POWER_NOW | awk '{ printf("%.2f", $1/1000000) }'` watt"
echo "Time left: `echo $ENERGY_NOW $POWER_NOW | awk '{ printf("%.2f", $1/$2) }'` hours"

TouchPad

The touchpad is a Synaptics device. Support under X comes from the xf86-input-synaptics module. At first I didn't have that module installed, and some generic mouse module was taking over. The touchpad did work, but really poorly and jittery. Installing the Synaptics module fixed all that. The synaptics module has quite some options that you can pass to X, so you can tweak the behavior of the touchpad to your liking. I'm personally very fond of the two-fingered scroll gesture.

Bluetooth

The Broadcom USB bluetooth device is supported by the btusb module. I know some Arch users have had problems with this device in combination with rfkill, but on my machine everything works out of the box. (Slack does not use rfkill.) I can enable the device with hciconfig hci0 up, scan the airwaves with hcitool scan, and so on.

Sensors

Running sensors-detect shows that the X121e has an ITE IT8518 sensor chip, but unfortunately as of kernel 3.3.3, there is no module that supports it.

Other modules

The "SBx00 SMBus Controller" uses the module i2c_piix4. The PCI bridge uses shpchp. The USB controller uses ohci-hcd and ehci-hcd. The k10temp module reads the thermal sensor on the CPU and reports its values like so:

root@thinkbook:~# cat /sys/devices/pci0000:00/0000:00:18.3/temp1_input
54250
root@thinkbook:~# cat /sys/devices/pci0000:00/0000:00:18.3/temp1_max
70000
root@thinkbook:~# cat /sys/devices/pci0000:00/0000:00:18.3/temp1_crit
100000

I intend to update this page as I go along.