Here's how I did it:
I was able to make Motorola's binary-only driver work
on my Mandrake 8.1 installation. Motorola basically
says that they've tested it only on RedHat 7.1; out of
the box, the kernel module will *not* work on kernels
> 2.4.6 (?). Insmod'ing it out of the box would give a
segmentation fault with the message
'kernel BUG at slab.c:1097!'
WHAT COULD HAVE BEEN DONE WHAT I DID SYSTEM
Mandrake 8.1 (vitamin) DISCLAIMER:
Your mileage may vary. It works for me, but it might
not work for you.
SOURCE CODE (kmalloc_hack.c)
Online, I found a page that outlined
steps on how to patch the slab memory allocator to
prevent the bug from occuring. However, I couldn't
compile kernel modules (something which I have yet to
figure out why), so that option wasn't available to
me. The next best thing was to kludge the module.
From reading the kernel sources, as well as reading
about it online, the module crashes because of the
different flag format used in kernels 2.4.6 and below.
So, I wrote a small function to translate the module's
kmalloc() and __vmalloc() calls to use the proper flag
format. Then, taking a cue from Mark Spieth's
Fixscript (check out this page as
well as the LinModem HOWTO), I used objcopy to point
the module's kmalloc() and __vmalloc() calls to my
functions. I then linked in my function, and used the
resulting module. Command lines are as follows:
% objcopy --redefine-sym kmalloc=kmalloc_hack --redefine-sym \
__vmalloc=vmalloc_hack sm56.o sm56_h.o
% gcc -D__KERNEL__ -DMODULE -Wall -O -fomit-frame-pointer -o \
kmhack.o -c kmalloc_hack.c
% ld -r -o sm56_hh.o sm56_h.o kmhack.o
I then cp'd the kludged driver in place of the
installed driver.
Kernel 2.4.8-26mdk
32MB RAM
Motorola SM56 PCI II Modem
/* kmalloc_hack.c
* Hack to make the SM56 binary-only module work
* on >2.4.8 kernels
*
* AUTHOR: Jan Michael Ibanez
* v 0.1
*
* NOTE :
* This is only a hack. Your mileage may vary.
*/
#include <linux/slab.h>
#include <linux/vmalloc.h>
void * kmalloc_hack(size_t size, int flags)
{
/* perform a kmalloc() call on behalf
* of the module, but with the right
* flags
*/
void * retval;
int newflags = GFP_USER | GFP_DMA;
/*
* FIXME : function should translate flags,
* instead of assuming GFP_USER | GFP_DMA
*/
retval = kmalloc(size, newflags);
return retval;
}
void * vmalloc_hack(unsigned long size, int gfp_mask, pgprot_t prot)
{
/* perform a __vmalloc() call on behalf
* of the module.
*/
int new_gfp_mask = GFP_USER | GFP_DMA
/* FIXME : function should translate
* gfp_mask instead of assuming
* GFP_USER | GFP_DMA
*/
void * retval = __vmalloc(size, new_gfp_mask, prot);
return retval;
}
Previously: Disturbed