Getting symbol version mismatch in the cdc_ether driver
I am building a new loadable kernel module similar to usbnet.
i am reusing all the functionality of usbnet and and on top of that will have my own specific features ( for one of the demo project i am working at my organization).
i was able to create the module based on my code changes and was successfully able to run with a ECM based modem( which would use cdc_ether as minidriver).
But recently, i added some new functionality in the usbnet driver and when i load the module ,it loads successfully. However, as soon as i insert my ECM modem device, i start getting the following errors. On further debugging, its found that the below symbol errors are happening only when i include the following linux header files in usbnet.h
i am not sure why the cdc_ether complains about the symbol version mismatch when i include the above two header files in my usbnet driver.
My makefile to build the module use the same kernel version which is installed. Compiler version also remains the same.
Can someone throw me some pointers as why this is happening and what's the solution to this?
[ 8949.900137] usb 2-1: new high speed USB device using ehci_hcd and address 22
[ 8950.084835] cdc_ether: disagrees about version of symbol usbnet_get_ethernet_addr
[ 8950.084845] cdc_ether: Unknown symbol usbnet_get_ethernet_addr (err -22)
[ 8950.085155] cdc_ether: disagrees about version of symbol usbnet_suspend
[ 8950.085162] cdc_ether: Unknown symbol usbnet_suspend (err -22)
[ 8950.085584] cdc_ether: disagrees about version of symbol usbnet_get_endpoints
[ 8950.085591] cdc_ether: Unknown symbol usbnet_get_endpoints (err -22)
[ 8950.086254] cdc_ether: disagrees about version of symbol usbnet_disconnect
[ 8950.086261] cdc_ether: Unknown symbol usbnet_disconnect (err -22)
[ 8950.086477] cdc_ether: disagrees about version of symbol usbnet_probe
[ 8950.086484] cdc_ether: Unknown symbol usbnet_probe (err -22)
[ 8950.086792] cdc_ether: disagrees about version of symbol usbnet_resume
[ 8950.086798] cdc_ether: Unknown symbol usbnet_resume (err -22)
Is everything built with the same kernel headers, glibc version & gcc version?
If so, trace the offending symbols in the header files and see if you can fond what's going on.
thanks business_kid for the reply.
Yes, i was able to figure out the root cause last week after further debugging, but still don't know the solution to this.
gcc and glibc version is same of the kernel as that of my module.
the reason i see those errors is because of difference in symbol versions of usbnet functions ( as imported by cdc_ether) in the generated Module.symvers of my usbnet module and that of /lib/modules/$(shell uname -r)/build/Module.symvers when i include <linux/udp.h> and <linux/tcp.h>
when i include </usr/include/linux/udp.h> in my module, then i DON'T see any errors.
there is BIG difference in code between /usr/include/linux/udp.h and /usr/src/linux-headers-`uname -r`/include/linux/udp.h ( which i downloaded based on current kernel installed). I can't use /usr/include/linux/udp.h since its missing lots of code which i want to use in my module.
to solve this i downloaded the linux source of the current installed kernel and re-compiled the kernel and then installed the kernel image + headers.When i re-compiled the kernel from the src, i checked that udp.h in the src is the latest and included all the functions that i needed.
But even after this i get the same errors as soon as i include <linux/udp.h> which is of course is being taken from linux source that i downloaded.
what's the solution to this?
Just to clarify my question here.
it seems that when i compiled the kernel with the src ( which has the udp.h and tcp.h i wanted), it seems that it built usbnet module based on /usr/include/linux/udp.h( glib) instead of picking up the file from /usr/src/linux-headers-`uname -r`/include/linux/udp.h
my modified(customized) usbnet takes the src from /usr/src/linux-headers-`uname -r`/include/linux/udp.h
this is creating the symbol mismatch when i load cdc_ether with my customised usbnet.
does anyone know how can i compile the kernel and its internal modules purely based on /usr/src/linux-headers-`uname -r`/include/linux/udp.h
and NOT /usr/include/linux/udp.h
I ran into this on lfs and hlfs back in the day.
gcc & glibc are the same - good. That leaves kernel headers. It is not unusual to see a different version of kernel headers from the kernel version in a distro. As the kernel updates, a new set of headers is rarely installed, and with good reason: You are open to this potentially awkward problem
You have traced it to /usr/include/linux/tcp.h. In your kernel source, there is another ~/include/linux/tcp.h. I would at least try that file from whatever kernel sources you have lying around.
Taking a diff of </usr/include/linux/udp.h> and that of /usr/src/linux-headers-`uname -r`/include/linux/udp.h, it was noticed that the functions that I needed are defined under __KERNEL__
When I compiled the kernel with the src, then the new udp.h and tcp.h is not taken into account in generating the usbnet symbols. Does anyone know why? If this because kernel compilation does not take into account ifdef __KERNEL__?
and only use /usr/include/linux/udp.h as its generic to all kernels?
I'm definitely not the kernel expert here, but you have 2 commands to install the kernel headers
make headers_check which nowadays includes the obsolete command 'make headers_install'
This is described as a 'sanity check' on the headers, but actually bangs them in IIRC.
make headersdep some other checks - inclusion cycles?
Before those commands are run, the headers in the kernel are not 'fit for use.' After they are run, the headers are in /usr/include.
I was able to resolve the issue.
What i did is that i included the <linux/tcp.h> and <linux/udp.h> to the usbnet code of the kernel source of installed kernel.
I replaced /usr/include/linux/udp.h and tcp.h with the updated version from the kernel src.
I recompiled the kernel and installed.
Now when i compile my module with <linux/udp.h> and <linux/tcp.h>, i don't see the CRC errors.
One more solution i found was that one can disable the CRC check during "make menuconfig" for the loadable module.
the above two solutions are not the one that i wanted as my original thought was to make changes in usbnet module without re-compiling the kernel. seems like its not the case.
Great! Mark this solved, then. Glad to help.
I always follow a strict procedure:
"make distclean" removes everything, including the kernel config which is why I said save it. Then, everything is recompiled, and in so doing, you know that everything is done correctly.
Of course, I am using Gentoo, which is a source-based distribution, and that's one reason why I do so. You must by some means ensure that everything is compatible.
|All times are GMT -5. The time now is 10:14 AM.|