I am learning linux network driver recently, and I wonder that if I have many network cards in same type on my board, how does the kernel drive them? Does the kernel need to load the same driver many times? I think it's not possible, insmod won't do that, so how can I make all same kind cards work at same time?
regards
The state of every card (I/O addresses, IRQs, ...) is stored into a driver-specific structure that is passed (directly or indirectly) to every entry point of the driver which can this way differenciate the cards. That way the very same code can control different cards (which means that yes, the kernel only keeps one instance of a driver's module no matter the number of devices it controls).
For instance, have a look at drivers/video/backlight/platform_lcd.c
, which is a very simple LCD power driver. It contains a structure called platform_lcd
that is private to this file and stores the state of the LCD (whether it is powered, and whether it is suspended). One instance of this structure is allocated in the probe
function of the driver through kzalloc
- that is, one per LCD device - and stored into the platform device representing the LCD using platform_set_drvdata
. The instance that has been allocated for this device is then fetched back at the beginning of all other driver functions so that it knows which instance it is working on:
struct platform_lcd *plcd = to_our_lcd(lcd);
to_our_lcd
expands to lcd_get_data
which itself expands to dev_get_drvdata
(a counterpart of platform_set_drvdata) if you look at include/linux/lcd.h
. The function can then know the state of the device is has been invoked for.
This is a very simple example, and the platform_lcd
driver does not directly control any device (this is deferred to a function pointer in the platform data), but add hardware-specific parameters (IRQ, I/O base, etc.) and you get how 99% of the drivers in Linux work.
The driver code is only loaded once, but it allocates a separate context structure for each card. Typically you will see a struct pci_driver
with a .probe
function pointer. The probe function is called once for each card by the PCI support code, and it calls alloc_etherdev
to allocate a network interface with space for whatever private context it needs.