wake-up-neo.net

Warum wird die Prüfmethode zusätzlich zu init in Linux-Gerätetreibern benötigt?

Was macht die probe()-Methode, die der Treiber anbietet, im Linux-Kernel? Wie unterscheidet es sich von der init-Funktion des Treibers, d. H. Warum können die probe()-Funktionen nicht in der init-Funktion des Treibers ausgeführt werden?

44
Bandicoot

Verschiedene Gerätetypen können probe () - Funktionen haben. Zum Beispiel verfügen sowohl PCI- als auch USB-Geräte über Probe () - Funktionen.

Wenn Sie über PCI-Geräte sprechen, würde ich Ihnen empfehlen, Kapitel 12 von Linux Device Drivers zu lesen, das diesen Teil der Treiberinitialisierung abdeckt. USB wird in Kapitel 13 behandelt.

Kürzere Antwort unter der Annahme von PCI: Die init-Funktion des Treibers ruft pci_register_driver() auf, die dem Kernel eine Liste der Geräte gibt, die er bedienen kann, zusammen mit einem Zeiger auf die probe()-Funktion. Der Kernel ruft dann einmal für jedes Gerät die probe()-Funktion des Treibers auf.

Diese Testfunktion startet die Initialisierung pro Gerät: Initialisieren der Hardware, Zuweisen von Ressourcen und Registrieren des Geräts beim Kernel als Block- oder Netzwerkgerät oder was auch immer es ist.

Dies macht es für Gerätetreiber einfacher, da sie nie nach Geräten suchen müssen oder sich Gedanken darüber machen müssen, ob ein Gerät Hot-Plug-fähig ist. Der Kernel behandelt diesen Teil und benachrichtigt den richtigen Treiber, wenn ihm ein Gerät zur Verfügung steht.

68
Eric Seppanen

@Bandicoot: probe () wird aufgerufen, um sicherzustellen, dass das Gerät vorhanden ist und die Funktionalität einwandfrei ist. Wenn das Gerät nicht Hot-Plug-fähig ist, kann die Funktion von probe () in die Methode init () gestellt werden Reduzieren Sie den Speicherbedarf des Treibers zur Laufzeit. P.S Link

Probe () geschieht zum Zeitpunkt des Gerätestarts oder wenn das Gerät angeschlossen ist. Bei einem "Plattform" -Gerät wird die Probe-Funktion aufgerufen, wenn ein Plattformgerät registriert wird und dessen Gerätename mit dem im Gerätetreiber angegebenen Namen übereinstimmt. P.S Link

Die Funktion i2c_detect prüft den I2C-Adapter und sucht nach den verschiedenen Adressen, die in der Struktur addr_data angegeben sind. Wird ein Gerät gefunden, wird die Funktion chip_detect aufgerufen. P.S link .

Ein Link, der sicherlich Ihre Zweifel klären wird. P.S Link

In Kernel 2.4.29 kann ich Ihnen zeigen, wie die Untersuchung geschieht. Bitte sehen Sie unten (Dateiname: 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

};

Dateiname: 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;
}

Einige wichtige Links:

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-geraetreiber

In PCI für Kernel-2.4.29 wird es aufgerufen, wenn Hersteller- und Geräte-ID identifiziert werden. PCI-Bustreiber tun dies für Sie. Bitte sehen Sie den Code unten:

Dateiname: 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;
}
9
Manish

Init (void) // wird einmal ausgeführt, wenn der Treiber/das Modul aufgerufen wird, und konfiguriert die Einstellungen für die Kernel-Treibermaschine.

Probe (* pdev) // wird vom Kernel-Treibercomputer bei Bedarf zum Erkennen und Installieren von tatsächlichen Geräten verwendet

8
fbp

Die Funktion xxx_init_module() des Treibers ruft pci_register_driver(struct pci_driver *drv) auf, indem sie eine Referenz auf die Struktur des Typs pci_driver übergeben. struct pci_driver ist eine wichtige Struktur, die alle PCI-Treiber haben sollten. Sie wird mit Variablen wie Treibername, Tabellenliste der PCI-Geräte, die der Treiber unterstützen kann, und Callback-Routinen für das PCI-Core-Subsystem initialisiert.

Die Treiberstruktur pci_driver enthält wichtige Mitgliederfelder, die unten aufgeführt sind:

  1. name - Name des Treibers, der unter allen PCI-Treibern im Kernel eindeutig ist. Es erscheint unter /sys/bus/pci/drivers.

  2. pci_device_id - Eine Tabelle mit Geräteidentifikationsdaten besteht aus der Art von Chips, die dieser Treiber unterstützt.

  3. probe - Die Adresse der xxx_probe()-Funktion.

  4. remove/suspend/resume/shutdown - Adresse der Funktion, die das PCI-Kernsystem aufruft, wenn das PCI-Gerät entfernt/ausgesetzt/wieder aufgenommen/heruntergefahren wird. Wird normalerweise von oberen Schichten für die Energieverwaltung verwendet.

Weitere Informationen dazu, wie das Testen des Treibers vom PCI-Core aus ausgeführt wird, finden Sie unter Linux Device Driver Init

1

Das Testen wird durchgeführt, wenn die probe () -Methode über einen Funktionszeiger in einer Struktur aufgerufen wird, die für die Gerätebindung mit Standard- oder benutzerdefinierten Plattformdaten für das Gerät verwendet wird. Treiber verwenden viele Informationen über das Gerät, sodass das Testen diese Informationen liefert an die Treiber, wenn ein Eintrag im Feld id_table name mit dem Gerätenamen übereinstimmt, wird der Probe geprüft.

0

Der Linux-Kernel verwendet einen Hardwaregerät, der mit einem Software-Gerätetreiber -Prozess übereinstimmt. init wird sehr früh aufgerufen und registriert die probe-Funktion und einen Hardware-Gerätenamen wie "taiko_sound_card" beim Kernel. Dies ist, um dem Kernel zu sagen, dass "Ich bin ein sw-Treiber für dieses Gerät mit diesem Namen". Wenn der Kernel durch hw-Geräte (Gerätebaum oder Busauflistung) geht und eine Übereinstimmung findet, ruft er Ihre registrierte probe-Funktion auf. Jetzt besitzt Ihr sw-Gerätetreiber besitzt das hw-Gerät.

Wenn kein passendes Gerät gefunden wird, wird Ihre Sonde möglicherweise nie aufgerufen. Aus diesem Grund ist normalerweise init klein und probe erledigt die gesamte Init-Funktion.

0
Liyong Zhou

Mehrere Geräte und Hotplug

  1. Sie betreiben einen großen Server mit vielen mit PICe verbundenen GPUs-Beschleunigern. Irgendwann beschließen Sie, mehr GPUs für die freien Steckplätze zu kaufen.

    Wenn wir init verwendet haben, müssten wir rmmod und insmod das Modul verwenden. Dafür müssten jedoch alle verbundenen GPUs angehalten werden, was zu Ausfallzeiten führt. 

    Mit probe schließen wir einfach die neuen GPUs an, um einen neuen Scan durchzuführen.

  2. Ein PCIe-Hotplug wäre sonst nicht möglich: https://electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice

QEMU edu PCI-Gerätebeispiel

QEMU hat ein pädagogisches PCI-Gerät namens edu, mit dem wir leicht testen können, wann probe aufgerufen wird.

Zuerst benötigen wir einen minimalen Linux-Kernel-PCI-Treiber, den ich hier geschrieben habe

Wir können mit dem angeschlossenen Gerät beginnen mit:

-device edu

aber noch interessanter ist, dass wir das Gerät auch an den QEMU-Monitor anschließen und entfernen können, Strg + Alt + 2 in der SDL-GUI oder -monitor telnet::45454,server,nowait in der CLI, mit den Befehlen:

device_add edu
device_del edu

Wenn das Gerät beim Booten angeschlossen ist:

  • probe wird aufgerufen, sobald das Modul insmod ist

  • dmesg enthält eine Zeile vom Typ: pci 0000:00:04: [1234:11e8] ..., die anzeigt, dass unser Gerät auf BDF 0000:00:04 geprüft wurde.

    Wir wissen, dass dies unser Gerät ist, da der Hersteller 0x1234 und die Geräte-ID 11e8 in der QEMU-Quelle ist.

    Wir schließen daraus, dass PCI-Geräte beim Booten getestet und irgendwo in einer Liste gespeichert werden.

Wenn wir das Gerät nach dem Booten vom Monitor anschließen:

  • nichts passiert, bis wir es tun:

    echo 1 > /sys/bus/pci/rescan
    

    Siehe auch: Wie kann der Linux-Kernel gezwungen werden, den PCI-e-Bus aufzulisten?

  • nach erneutem Scannen:

    • wenn wir bereits eingebettet waren, wird probe sofort aufgerufen.

      In diesem Fall passierte probe getrennt von insmod und zeigte, wie sie sich unterscheiden. 

    • wenn wir nicht haben: probe wird unmittelbar nach insmod aufgerufen.