Dans le noyau Linux, que fait la méthode probe()
fournie par le pilote? En quoi est-elle différente de la fonction init
du pilote, c’est-à-dire pourquoi les actions de la fonction probe()
ne peuvent-elles pas être effectuées dans la fonction init
du pilote?
Différents types d'appareils peuvent avoir des fonctions probe (). Par exemple, les périphériques PCI et USB ont tous deux des fonctions probe ().
Si vous parlez de périphériques PCI, je vous recommanderais de lire le chapitre 12 de Pilotes de périphérique Linux , qui couvre cette partie de l’initialisation du pilote. L’USB est traité au chapitre 13.
Réponse plus courte, en supposant PCI: La fonction init du pilote appelle pci_register_driver()
qui donne au noyau une liste des périphériques qu’il est en mesure de desservir, ainsi qu’un pointeur sur la fonction probe()
. Le noyau appelle ensuite la fonction probe()
du pilote une fois pour chaque périphérique.
Cette fonction d'analyse lance l'initialisation par périphérique: initialisation matérielle, allocation de ressources et enregistrement du périphérique avec le noyau en tant que bloc, périphérique réseau ou autre.
Cela facilite la tâche des pilotes de périphérique, car ils n'ont jamais besoin de rechercher des périphériques ni de chercher un périphérique branché à chaud. Le noyau gère cette partie et avise le bon pilote quand il a un périphérique à gérer.
@Bandicoot: probe () sera appelé pour vérifier que le périphérique existe et que la fonctionnalité est correcte.Si le périphérique n'est pas hot-plugable, la fonctionnalité de probe () peut être intégrée à la méthode init () réduire l'encombrement de la mémoire lors de l'exécution du pilote. P.S link
Probe () se produit au moment du démarrage du périphérique ou lorsque le périphérique est connecté. Pour un périphérique "plateforme", la fonction de sonde est appelée lorsqu'un périphérique de plateforme est enregistré et que son nom de périphérique correspond au nom spécifié dans le pilote de périphérique. P.S link
La fonction i2c_detect sonde l'adaptateur I2C en recherchant les différentes adresses spécifiées dans la structure addr_data. Si un périphérique est trouvé, la fonction chip_detect est appelée. P.S lien .
Un lien qui effacera sûrement votre doute. P.S link
Dans le noyau 2.4.29, je peux vous montrer comment se fait la détection? Veuillez voir ci-dessous (Nom du fichier: drivers/acorn/char/pcf8583.c)
static struct i2c_driver pcf8583_driver = {
name: "PCF8583",
id: I2C_DRIVERID_PCF8583,
flags: I2C_DF_NOTIFY,
attach_adapter: pcf8583_probe, /* This will be called from i2c-core.c P.S see below function i2c_add_driver()*/
detach_client: pcf8583_detach,
command: pcf8583_command
};
Nom du fichier: drivers/i2c/i2c-core.c
int i2c_add_driver(struct i2c_driver *driver)
{
........................
........................
/* now look for instances of driver on our adapters
*/
if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) {
for (i=0;i<I2C_ADAP_MAX;i++)
if (adapters[i]!=NULL)
/* Ignore errors */
driver->attach_adapter(adapters[i]); /*This is a location from where probe is called. Pointer **driver** is of type **pcf8583_driver** which you have passed into this function*/
}
ADAP_UNLOCK();
return 0;
}
Quelques liens importants:
1) http://www.slideshare.net/varunmahajan06/i2c-subsystem-in-linux2624
2) http://www.programering.com/a/MjNwcTMwATM.html
3) http://www.linuxjournal.com/article/6717
4) http://www.developermemo.com/2943157/
5) http://free-electrons.com/doc/kernel-architecture.pdf
6) http://www.techques.com/question/1-3014627/Probe-problem-when-writing-a-I2C-device-driver
Dans PCI pour kernel-2.4.29, il est appelé lorsque le fournisseur et l'ID de périphérique sont identifiés. Le pilote de bus PCI le fait pour vous. Veuillez voir le code ci-dessous:
Nom du fichier: drivers/pci/pci.c
static int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
{
const struct pci_device_id *id;
int ret = 0;
if (drv->id_table) {
id = pci_match_device(drv->id_table, dev); /* check for device presence*/
if (!id) {
ret = 0;
goto out;
}
} else
id = NULL;
dev_probe_lock();
if (drv->probe(dev, id) >= 0) { /* This is a location from where probe is called*/
dev->driver = drv;
ret = 1;
}
dev_probe_unlock();
out:
return ret;
}
Init (void) // s'exécute une fois lorsque le pilote/module est appelé et configure les éléments pour l'ordinateur du pilote du noyau.
La sonde (* pdev) // est utilisée par la machine du pilote du noyau pour détecter et installer les périphériques réels.
La fonction drivers xxx_init_module()
appelle pci_register_driver(struct pci_driver *drv)
en transmettant une référence à la structure de type pci_driver
. struct pci_driver
est une structure importante que tous les pilotes PCI doivent avoir, et qui est initialisée avec des variables telles que le nom du pilote, la liste des périphériques PCI que le pilote peut prendre en charge, les routines de rappel pour le sous-système PCI principal.
La structure de pilotes pci_driver contient des champs de membres importants énumérés ci-dessous:
name
- Nom du pilote qui est unique parmi tous les pilotes PCI du noyau. Il apparaîtra sous /sys/bus/pci/drivers
.
pci_device_id
- Une table de données d'identification de périphérique comprend le type de puces que ce pilote prend en charge.
probe
- L'adresse de la fonction xxx_probe()
.
remove/suspend/resume/shutdown
- adresse de la fonction que le système central PCI appelle lorsque le périphérique PCI est retiré/suspendu/repris/arrêté, respectivement. Généralement utilisé par les couches supérieures pour la gestion de l'alimentation.
Pour plus d'informations sur la manière dont l'analyse du pilote est exécutée à partir du cœur PCI, reportez-vous à Linux Device Driver Init .
La vérification est effectuée lorsque la méthode probe () est appelée par un pointeur de fonction à l'intérieur d'une structure utilisée pour la liaison de périphérique avec les données de plate-forme par défaut ou personnalisées concernant les pilotes de périphérique . aux pilotes lorsqu'une entrée du champ du nom de id_table correspond au nom du périphérique sera analysée.
Le noyau Linux utilise un processus périphérique matériel correspondant à un processus {pilote de périphérique logiciel}. init
est appelé très tôt et enregistre la fonction probe
et un nom de périphérique matériel tel que "taiko_sound_card" dans le noyau. Ceci indique au noyau que "je suis un pilote sw pour ce périphérique de ce nom". Lorsque le noyau passe en revue les périphériques matériels (arborescence de périphériques ou bus enum) et trouve une correspondance, il appelle votre fonction probe
enregistrée. Maintenant, votre pilote de périphérique sw possède le périphérique hw.
Si aucun appareil correspondant n'est trouvé, votre sonde peut ne jamais être appelée. C'est pourquoi généralement init
est minuscule et probe
fait tout le travail init.
Plusieurs périphériques et hotplug
Vous utilisez un serveur de grande taille avec de nombreux accélérateurs GPU connectés à PICe. À un moment donné, vous décidez d’acheter plus de GPU pour les slots libres.
Si nous utilisions init
, nous devrions alors rmmod
et insmod
le module. Mais cela nécessiterait l’arrêt de tous les GPU connectés, ce qui causerait des temps morts.
Avec probe
, nous connectons simplement les nouveaux GPU pour effectuer une nouvelle analyse.
PCIe hotplug ne serait pas possible autrement: https://electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice
Exemple de périphérique QEMU edu PCI
QEMU possède un périphérique PCI éducatif appelé edu, qui nous permet de tester facilement lorsque probe
est appelé.
Premièrement, nous avons besoin d’un pilote PCI de noyau Linux minimal, que j’ai écrit ici .
Nous pouvons commencer avec le périphérique attaché avec:
-device edu
mais plus intéressant encore, nous pouvons également connecter et supprimer le périphérique du moniteur QEMU, Ctrl + Alt + 2 sur l'interface graphique SDL ou -monitor telnet::45454,server,nowait
sur l'interface de ligne de commande, à l'aide des commandes suivantes:
device_add edu
device_del edu
Si le périphérique est connecté au démarrage:
probe
est appelé dès que nous insmod
le module
dmesg
contient une ligne de type: pci 0000:00:04: [1234:11e8] ...
qui indique que notre périphérique a été interrogé sur BDF 0000:00:04
.
Nous savons qu'il s'agit de notre périphérique, car le fournisseur est 0x1234 et l'ID de périphérique 11e8 dans la source QEMU.
Nous concluons donc que les périphériques PCI sont testés au démarrage et stockés dans une liste quelque part.
Si nous connectons le périphérique après le démarrage à partir du moniteur:
rien ne se passe jusqu'à ce que nous faisons:
echo 1 > /sys/bus/pci/rescan
Voir aussi: Comment obliger le noyau Linux à énumérer le bus PCI-e?
après nouvelle analyse:
si nous avions déjà insmodé, probe
est appelé immédiatement.
Donc, dans ce cas, probe
est passé séparément de insmod
, montrant en quoi elles diffèrent.
si ce n'est pas le cas: probe
est appelé immédiatement après insmod