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 Drivers
→ Network device support
→
Wireless LAN
→ Realtek 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 Drivers
→ Multifunction device drivers
→
Realtek PCI-E card reader
) and CONFIG_MMC_REALTEK_PCI
(in
Device Drivers
→ MMC/SD/SDIO card support
→
Realtek 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:
#!/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.