Linux Kernel Architecture

(Jacob Rumans) #1

Chapter7:Modules


More important than direct aliases is the inclusion of device databases. The kernel provides the macro
MODULE_DEVICE_TABLEto implement such databases. The device table for the8139toomodule that was
shown above is created by the following code:

drivers/net/8139too.c
static struct pci_device_id rtl8139_pci_tbl[] = {
{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
...
{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 },

{0,}
};

MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);

The macro provides a standardized name in the module binary by which the table can be accessed:

<module.h>
#define MODULE_GENERIC_TABLE(gtype,name) \
extern const struct gtype##_id __mod_##gtype##_table \
__attribute__ ((unused, alias(__stringify(name))))

<module.h>
#define MODULE_DEVICE_TABLE(type,name) \
MODULE_GENERIC_TABLE(type##_device,name)

In the case of PCI, this generates the ELF symbol__mod_pci_device_table, which is an alias for
rtl8139_pci_tbl.

When modules are built, a conversion script (scripts/mod/file2alias.c) parses the device tables for
the different bus systems (PCI, USB, IEEE1394,...) — which have all different formats — and gener-
atesMODULE_ALIASentries for the database entries. This allows treating device databases entries in the
same way as module aliases without having to duplicate the database information. Since the conversion
process basically consists of parsing an ELF file and doing some string rewriting, I will not discuss it in
greater detail here. The output looks as follows for the8139toomodule:

drivers/net/8139too.mod.c
MODULE_ALIAS("pci:v000010ECd00008139sv*sd*bc*sc*i*");
MODULE_ALIAS("pci:v000010ECd00008138sv*sd*bc*sc*i*");
MODULE_ALIAS("pci:v00001113d00001211sv*sd*bc*sc*i*");
...
MODULE_ALIAS("pci:v00001743d00008139sv*sd*bc*sc*i*");
MODULE_ALIAS("pci:v0000021Bd00008139sv*sd*bc*sc*i*");
MODULE_ALIAS("pci:v*d00008139sv000010ECsd00008139bc*sc*i*");
MODULE_ALIAS("pci:v*d00008139sv00001186sd00001300bc*sc*i*");
MODULE_ALIAS("pci:v*d00008139sv000013D1sd0000AB06bc*sc*i*");

Providing module aliases forms the basis to solve the automatic module loading problem, but is not
yet completely sufficient. The kernel needs some support from userspace. After the kernel has noticed
that it needs a module for a device with specific properties, it needs to pass an appropriate request to
Free download pdf