Compiling kernel IEGD 10.x module for any Linux distribution

19 Feb 2010

Intel Atom Logo

Intel has put great effort to put complete open-source drivers into recent kernels for its devices. Only device that is clearly missing there is GMA500 (aka Poulsbo, aka US15 chipset, aka Atom Z5xx family). This is understood as it does relay on Imagination Technologies PowerVR core licensed out by Intel to produce GMA500, so most of the driver parts cannot go open-source as it would imply of violation of some agreement between ImgTec and Intel.

Fortunately Intel provides binary driver set called Intel® Embedded Graphics Driver (IEGD) supporting all embedded video chipsets, containing binary form of video driver libraries for latest Xorg, OpenGL and VA.

While most of the work you need to do is to have IEGD_10_3_Linux.tgz file (in case of IEGD 10.3) extracted onto the target box and to copy various .so files in proper places (follow IEGD documentation). Yet there is one more complicated thing extra – IEGD Kernel Module (IKM) iegd_mod.ko that has to be compiled out of the source shipped with IEGD.

Linux Kernel module

IEGD documentation clearly states that only few distributions are supported by this driver, and those are i.e. Fedora 8 & 10, some older Ubuntu 8.x and finally Moblin. But what about others, such as Debian, newer Ubuntu. You think you are unlucky running other distro? You shall understand word “supported” here as “tested”.

Reading the documentation, in all cases your are supposed to enter IKM folder of extracted drivers and launch install.sh script. This script shall compile and install without any hassle IKM on “supported” distributions. Surprisingly trying that on your distribution even it is not supported may work too! With one important exception it produces bogus driver that will crash your kernel.

Finding the proper way for your distribution

This recipe will save some few hours up to few days of struggling with fancy errors trying to compile and run the IKM module on your system :)

Investigating the driver and install.sh first thing to notice is that it checks you Kernel version, it also takes (false) assumption that your are running one of the “supported” distros, so i.e 2.6.27 may mean Fedora version of the 2.6.27 Kernel not any 2.6.27 kernel.

Linux distributions have this fancy characteristic that they usually come with heavily patched kernel, so when you take 2.6.xx driver module from one distro and try to run it on the same version kernel on the other distro it will likely crash your kernel. Why? Incompatible ABI.

What Intel (Tungsten?) did in IKM is prepared IKM/val subfolder with headers extracted from several kernel sources of “supported” distributions. And what install.sh does, it tries to guess which one of DRM and AGP kernel module headers placed in that subfolder are OK for your Kernel.

In case you are running on the “unsupported” distribution the answer in 95% cases is NONE! Even you will be able to compile the iegd_mod.ko using Makefile produced by install.sh the module will crash you kernel as soon you will try to use it. Since your kernel has incompatible ABI (different structures) with the ABI provided inside IKM/val subfolder.

Preparing for compilation of IKM for your own kernel

If you are running “unsupported” distribution you should avoid then using headers in IKM/val subfolder. The right way is to take AGP and DRM headers out of your running kernel sources (you don’t have to compile the whole kernel of course).

So go to IEGD_10_3_Linux folder and launch:

sudo apt-get install linux-headers-x.y.zz
apt-get source linux-image-x.y.zz

Where x.y.zz is your running kernel version. (Use your own distro command to grab kernel source if you don’t run on Debian or Ubuntu)

This will install kernel headers and scripts to build kernel modules and also produce linux-x.y.zz folder containing source code of your running Kernel. The whole trick if to place (replace) Makefile in IKM folder as below:

KERNELVER ?= $(shell uname -r)
KERNELDIR ?= /lib/modules/$(KERNELVER)/build
INSTALLDIR ?= /lib/modules/$(KERNELVER)/kernel/drivers/char/agp
PWD ?= $(realpath .)

EXTRA_CFLAGS += -I$(PWD)/include
EXTRA_CFLAGS += -I$(PWD)/../linux-$(KERNELVER)/drivers/char/agp
EXTRA_CFLAGS += -I/lib/modules/$(KERNELVER)/build/include/drm

all: clean modules

modules:
	@echo $(PWD)
	@$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

install:
	install -o root -g root -m 755 -d $(INSTALLDIR)
	install -o root -g root -m 744 iegd_mod.ko $(INSTALLDIR)
	/sbin/depmod -a

uninstall:
	rm -rf $(INSTALLDIR)/iegd_mod.ko
	/sbin/depmod -a

clean:
	@rm -f *.o iegd*.ko iegd*.mod.c iegd*.o agp/*.o drm/*.o Module.symvers
	@rm -fr .intel* .tmp* .*.cmd agp/.*.cmd drm/.*.cmd

obj-m := iegd_mod.o
iegd_mod-objs := agp/pci.o agp/global.o agp/drv_alm.o agp/drv_nap.o \
                 agp/drv_plb.o agp/drv_cmn.o agp/drv_gn4.o drm/iegd_drv.o \
                 drm/iegd_interface.o drm/iegd_interface_265.o \
                 drm/iegd_interface_2611.o drm/iegd_interface_2615.o \
                 drm/iegd_interface_2624.o drm/psb_irq.o

You don’t need to launch install.sh at all. Just paste the file as above.

As you see now, this Makefile references to ../linux-$(KERNELVER) for your running Kernel source AGP & DRM headers. Yet however you may still need to do few tweaks in your Makefile, see notes below:

Note (1) In case you are running older kernel, /lib/modules/$(KERNELVER)/build/include/drm may not exist, then $(PWD)/../linux-$(KERNELVER)/drivers/char/drm should be right path to put in the Makefile instead.

Note (2) The Kernel source code folder you downloaded (i.e. via apt-get source) may not actually match exactly linux-$(KERNELVER), so you may change that EXTRA_CFLAGS setting manually:

In case of Ubuntu uname -r is 2.6.31-19-generic while the extracted source folder name has no -generic suffix and it is just linux-2.6.31-19. In case of Debian uname -r is 2.6.26-21 while the extracted source folder name is linux-2.6-2.6.26-21. Weird huh? Final fixes before compilation

There is a file still missing if you try now to make. It is file that exists in IKM/val/agp but does not exist in your $(PWD)/../linux-$(KERNELVER)/drivers/char/agp. It is called interface_abs.h.

Wonder why the heck it is NOT in IKM/include!? This is a little lack of consequence from Intel here.

Anyway just copy interface_abs.h into IKM/include out of IKM/val/agp/agpm0vmob2 if you are running on >= 2.6.30 Kernel or from IKM/val/agp/agpm0v103 otherwise. The only difference between interface_abs.h from agpm0vmob2 and agpm0v103 is one macro definition.

Finally we need two little extra fixes:

  1. Trying to compile on Debian Lenny we will get many nasty errors from kernel headers for IKM/drm/iegd_interface.c. Moving igd_abs.h inclusion in this source file little down fixes the issue. Edit IKM/drm/iegd_interface.c as below:

     #include "iegd.h"
    -#include "igd_abs.h"
     #include "drmP.h"
     #include "drm.h"
       
    +#include "igd_abs.h"
     #include "iegd_drm.h"
     #include "iegd_drv.h"
     #include "psb_intregs.h"
    
  2. IKM/drm/iegd_drv.c tries to include linux/config.h at the very beginning of the file. This is not actually necessary, and anyway does not exist, so you may comment that out:

    -#include <linux/config.h>
    +/* #include <linux/config.h> */
    

Compiling at last

Now you are ready to so make and sudo make install. This time iegd_mod.ko should be ABI compatible with your kernel.

I have tested this method on Debian 5.0 Lenny and Ubuntu 9.10 Karmic Koala.

To ensure everything works fine after driver installation try:

sudo modprobe iegd_mod

And try to go into IKM/agp and compile and run agp_test.c:

gcc -o agp_test agp_test.c
sudo ./agp_test

Next try the same with IKM/drm compiling and running drm_test.c.

If those two test won’t fail and won’t blow your kernel it means you have fully working IEGD module on your own Linux distro.

Notes for users of old psb-modules or psb-kernel-source Ubuntu package

Older psb-modules and psb-kernel-source Ubuntu packages install their own incompatible drm.ko module at ~~~/lib/modules/uname -r/updates/char/drm~~~.

Check find ~~~/lib/modules/uname -r -type f -name ‘drm*’~~~ you should have only one: ~~~/lib/modules/uname -r/kernel/drivers/gpu/drm/drm.ko~~~

In case if you find other drm.ko, probably in updates/char/drm delete it. That one came from psb-kernel-source and is causing you a trouble. You may ensure you got only valid drm.ko reinstalling your kernel image with:

apt-get install --reinstall linux-image-`uname -r`

Notes for curious

The difference of Makefile of mine and Makefile produced of install.sh is the beginning:

KERNELVER ?= $(shell uname -r)
KERNELDIR ?= /lib/modules/$(KERNELVER)/build
INSTALLDIR ?= /lib/modules/$(KERNELVER)/kernel/drivers/char/agp
PWD ?= $(realpath .)

EXTRA_CFLAGS += -I$(PWD)/include
EXTRA_CFLAGS += -I$(PWD)/../linux-$(KERNELVER)/drivers/char/agp
EXTRA_CFLAGS += -I/lib/modules/$(KERNELVER)/build/include/drm

If you try to run install.sh EXTRA_CFLAGS will include two of IKM/val folders which contain some Kernel source extracted header definitions that are likely not compatible with your Kernel.

I use also PWD ?= $(realpath .) here instead of PWD ?= $(shell pwd) because with some Linux headers versions $(shell pwd) resolves to /lib/modules path not the path where IKM sources are.

Notes for Intel

It would be nice for next IEGD release if IKM source tree would be made for readable and clear:

  1. IKM/val should be renamed to IKM/kernel-headers (what the heck “val” means here ?!) and this should be noted somewhere in docs that files here are NOT made by Intel but extracted of “supported” Linux distributions Kernel sources

  2. interface_abs.h should moved away from IKM/val (IKM/kernel-headers) to avoid confusion (with point 1) and placed into IKM/includes (and there should be #ifdef for this one macro that makes it different for across 2.6.30)

  3. IKM/drm/iegd_interface.c should be fixed as described above (moving iegd_abs.h inclusion little bit down).

  4. IKM/drm/iegd_drv.c inclusion of <include/config.h> is not necessary, may be removed.

  5. Finally install.sh should contain case when running on “unsupported” distribution.

    So it shall make SURE if running on “supported” distributions and then and only then use files from IKM/kernel-headers, OTHERWISE ask for a path for your own Linux distribution Kernel source’s to find a path for your own kernel/drivers/char/agp and kernel/drivers/char/drm (include/drm) i.e. by showing:

     Your Linux distribution and Kernel version was untested, however you
     may try to compile and run driver on your own risk. Please provide your
     running kernel sources extracted i.e. on Debian or Ubuntu using apt-get
     source linux-image-2.6-686: [path to your kernel]:
    

Fell free to post your comments and problems with method presented here below using comment form!

Posted in Linux