Linux – How to know which kernel configuration option enabled the driver

configurationkernel-moduleslinux-kernel

TL;DR:
when I was trying to compile a driver for USB DAQ device I have reconfigured the kernel. The driver refused to compile under the default distro's kernel but everything works with my tweaked kernel.

The driver consists of 2 kernel modules. I know which options I changed but I want to know which particular configuration option enabled my driver. Is there any way how to figure it out without trying (configuring and compiling kernel) every possible combination of the options?

Longer story:
I have an Advantech USB-4702 DAQ device which comes with a driver for various distros, e.g. openSUSE 11.4. It has to be compiled from source and it compiles well on supported distributions (I tried openSUSE 11.4 32bit with kernel 2.6.37.6-24-desktop).

When I was trying to get it work under SLES 11 SP 3 (64bit, kernel 3.0.76-0.11-default) I got compile errors. One of them was caused by this snippet in the source:

#ifndef CONFIG_USB
#  error "This driver needs to have USB support."
#endif

So I took a look at the configuration options of the running kernel (from /proc/config.gz) and found CONFIG_USB to be enabled (I guess I would not be able to use my USB keyboard and mouse if it was disabled). Then I started to play with the kernel configuration and enabled (some as modules) some of them. I compiled the kernel, installed it, rebooted. Then the driver compiled without any errors or warnings and I am able to use the device now.

The question is, how can I find out which particular option "enabled" compilation of the driver? I know which options were changed, but I don't want to enable anything that is not necessary for the driver. And I don't want to go through configuring and compiling the kernel with every possible combination of the options.

Best Answer

I assume, the driver in question is compiled as a module. If you also built the prerequisites as modules, you can easily find them. All modules and their corresponding options are noted in the kernel makefiles. So you can just grep these for the module name.

But first, you need to find out, which modules your driver depends on. So issue a lsmod and search for your driver, especially in the Column Used by. I, for example use the rt2800usb driver.

$ lsmod | grep rt2800usb
rt2800usb  15392   0  
rt2x00usb  8306    1  rt2800usb
rt2800lib  59262   1  rt2800usb
rt2x00lib  34431   3  rt2x00usb,rt2800lib,rt2800usb
usbcore    146570  7  rt2x00usb,rt2800usb

This tells me that my driver needs the modules rt2x00usb, rt2800lib, rt2x00lib and usbcore. Now I search the Makefiles for them. Note the leading space and trailing .o in the search strings

$ fgrep -r --include=Makefile ' usbcore.o'
drivers/usb/core/Makefile:obj-$(CONFIG_USB) += usbcore.o

$ grep -Pr --include=Makefile ' rt2(x|8)00(usb|lib)\.o'
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2800_LIB) += rt2800lib.o
drivers/net/wireless/rt2x00/Makefile:obj-$(CONFIG_RT2800USB) += rt2800usb.o

And there we have the config options needed to build those modules. If you cannot instantly find the culprit, try to go a level deeper and search for the dependencies of the dependencies... If you can guess the name, this may help for built-in objects, too (contrary to modules).

(All command line outputs in this post were slightly condensed and reformatted for better readability.)

Related Question