tags:

views:

31

answers:

1

Hi all,

I've been working with a userland program writeread.c (referred here), utilizing the ftdi_sio Linux driver.

I had worked with the default ftdi_sio that comes with Ubuntu Lucid that I use - and then, as a sanity check, decided to rebuild ftdi_sio from source. I did not want to download the entire kernel source, so I opted for so called "building out-of-tree modules":

... which means you can only have installed linux-headers-* packages (instead of having entire linux-source-* installed) - and the respective kernel module source - in order to build a kernel module.

So, I basically got the following files in a folder:

and ran make - and a ftdi_sio.ko kernel objects compiles, which also can be insmod-ed without a problem.

 

The problem is now here - as long as I work with low speeds (115200 bps), there is no observable difference between: loading the 'vanilla' driver (using sudo modprobe ftdi_sio); and loading the newly built driver (using sudo modprobe usbserial; sudo insmod /path/to/ftdi_sio.ko) - in respect to the performance of the userland program (writeread.c).

However, if I try the same at 2000000 bps, then the 'vanilla' driver works fine - while the build driver causes a segfault of the userland program (writeread.c). In particular, this segfault happened at free()-ing memory resources - because the driver would end up reading more bytes from the loopback connection, than it itself would write! However, that in itself is not that relevant for this discussion, because I finally found a way to get the built ftdi_sio to work (Edit: just noticed that a similar procedure is also given in External Linux kernel module dependencies R#2238581 - Stack Overflow):

$ sudo modprobe -r ftdi_sio # remove 'vanilla' driver from memory 
...
# build the driver
$ cd /path/to/ftdi_sio_2.6.32/
$ make clean && make 

# check vanilla version
$ ls -la /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko
-rw-r--r-- 1 root root 102396 2010-10-17 01:47 /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko

# (re)move the 'vanilla' kernel object
$ sudo mv /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko ~/Desktop/ftdi_sio_orig.ko  

# symlink our built version, as if it is the 'vanilla' one
$ sudo ln -s /path/to/ftdi_sio_2.6.32/ftdi_sio.ko /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/

# check 
$ ls -la /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko
lrwxrwxrwx 1 root root 57 2010-10-26 12:49 /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko -> /path/to/ftdi_sio_2.6.32/ftdi_sio.ko

# call depmod
$ sudo depmod

# !! plug in USB at this point, built driver autoloads;
# however, running `writeread.c` will segfault!

# !! REBOOT at this point

# after reboot:
# !! plug in USB at this point, built driver autoloads;
# and `writeread.c` runs without segfault

So, my question is: can anyone clarify to me, why - even after running depmod - do I still have to reboot, to have the built driver behave properly? In other words: is there any other command I could call (maybe after depmod), so that the driver works properly when it's loaded, without rebooting?

The reason I'm asking, is that I suspect that upon each recompilation of the kernel module, the symbol table will change - so to ensure that it works properly, I'd have to run depmod and reboot after each time the driver is built - which I think would be kind of tedious :) So, it would be nice to be able to rebuild the kernel module, and use it in the same session - without having to reboot.

 

Well, thanks in advance for any answers,

Cheers!!

 

 

Makefile:

CONFIG_MODULE_FORCE_UNLOAD=y
# flags passed to gcc for compilation - -v:verbose, -H:show include files
# KBUILD_CFLAGS += -v
# for debugging make itself, use --debug=i in make command for targets

# debug build:
EXTRA_CFLAGS=-g -O0

KVERSION = $(shell uname -r)

obj-m += ftdi_sio.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+1  A: 

In short, no, I can't see anything wrong with the sequence you're doing, or why it would cause that behaviour.

The fact that the kernel allows the newly built module to be inserted basically means that you've built it properly and it has also inserted correctly, so there are no version mismatches or anything.

I'll guess that when you run the test at 2000000 bps, you first tested the vanilla driver and then the new driver? So my guess is the driver is not cleaning up something correctly, so when you run the test again (with the new driver) you see a segfault. But like I said, that's a guess.

mpe
Thank you, @mpe, for your response! First of all, thanks for evaluating the sequence of steps. Re: "_you first tested the vanilla driver and then the new driver?_" - yes, I did. Also, I haven't thought of it before, but I think "_the driver is not cleaning up something correctly_" makes a lot of sense - I'll try to take a closer look at that, and report back if I find anything interesting. Thanks again - cheers!
sdaau