web-dev-qa-db-ja.com

Linuxデバイスドライバーでは、initに加えてプローブ方法が必要なのはなぜですか?

Linuxカーネルでは、ドライバーが提供するprobe()メソッドは何をしますか?ドライバーのinit関数とはどの程度違いますか、つまり、ドライバーのinit関数でprobe()関数アクションを実行できないのはなぜですか?

44
Bandicoot

さまざまなデバイスタイプにprobe()関数を含めることができます。たとえば、PCIデバイスとUSBデバイスの両方にprobe()関数があります。

PCIデバイスについて話している場合は、 Linux Device Drivers の第12章を読むことをお勧めします。この章では、ドライバーの初期化のこの部分について説明しています。 USBについては、第13章で説明しています。

PCIを想定した短い答え:ドライバーのinit関数はpci_register_driver()を呼び出し、probe()関数へのポインターとともに、カーネルがサービス可能なデバイスのリストを提供します。次に、カーネルは、デバイスごとにドライバーのprobe()関数を1回呼び出します。

このプローブ機能は、デバイスごとの初期化を開始します。ハードウェアの初期化、リソースの割り当て、およびデバイスをカーネルにブロックデバイスまたはネットワークデバイスなどとして登録します。

デバイスを検索したり、ホットプラグされたデバイスを見つけることを心配する必要がないため、デバイスドライバーは簡単になります。カーネルはその部分を処理し、適切なドライバーにユーザーが処理するデバイスがある場合に通知します。

70
Eric Seppanen

@ Bandicoot:probe()が呼び出され、デバイスが存在し、機能が正常であることを確認します。デバイスがホットプラグ対応でない場合、機能はprobe()はinit()メソッド内に配置できます。これにより、ドライバーの実行時のメモリフットプリントが削減されます。 P.S リンク

Probe()は、デバイスのブート時またはデバイスの接続時に発生します。「プラットフォーム」デバイスの場合、プラットフォームデバイスが登録され、そのデバイス名がデバイスドライバーで指定された名前と一致すると、プローブ機能が呼び出されます。 P.S リンク

I2c_detect関数はI2Cアダプターをプローブし、addr_data構造体で指定されたさまざまなアドレスを探します。デバイスが見つかった場合、chip_detect関数が呼び出されます。 P.S リンク

あなたの疑いを確実にクリアするリンク。 P.S リンク

カーネル2.4.29では、プローブがどのように発生するかを示すことができますか?以下を参照してください(ファイル名: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

};

ファイル名: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;
}

いくつかの重要なリンク:

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

Kernel-2.4.29のPCIでは、ベンダーとデバイスIDが識別されると呼び出されます。 PCIバスドライバーがこれを行います。以下のコードをご覧ください:

ファイル名: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)//ドライバー/モジュールが呼び出されたときに1回実行され、カーネルドライバーマシン用に設定します。

Probe(* pdev)//実際のデバイスを検出してインストールするために、必要に応じてカーネルドライバーマシンによって使用されます

8
fbp

ドライバxxx_init_module()関数は、_pci_driver_型の構造体への参照を渡すことにより、pci_register_driver(struct pci_driver *drv)を呼び出します。 _struct pci_driver_はすべてのPCIドライバーが持つべき重要な構造であり、ドライバー名、ドライバーがサポートできるPCIデバイスのテーブルリスト、PCIコアサブシステムのコールバックルーチンなどの変数で初期化されます。

ドライバーのpci_driver構造には、以下にリストする重要なメンバーフィールドがあります。

  1. name –カーネル内のすべてのPCIドライバーの中で一意のドライバーの名前。 _/sys/bus/pci/drivers_の下に表示されます。

  2. _pci_device_id_ –デバイス識別データのテーブルは、このドライバーがサポートするチップのタイプで構成されます。

  3. probexxx_probe()関数のアドレス。

  4. _remove/suspend/resume/shutdown_ – PCIデバイスがそれぞれ削除/一時停止/再開/シャットダウンされたときにPCIコアシステムが呼び出す関数のアドレス。通常、電力管理のために上位層で使用されます。

PCIコアから実行されるドライバーのプローブ方法の詳細については、 Linux Device Driver Init を参照してください。

1

プローブは、デバイスに関するデフォルトまたはカスタムプラットフォームデータでデバイスバインディングに使用される構造内の関数ポインターによってprobe()メソッドが呼び出されたときに行われます。ドライバは、デバイスに関する多くの情報を使用するため、id_table nameフィールドのエントリがデバイス名と一致する場合、プロービングはそのような情報をドライバに提供します。

0

Linuxカーネルは、ハードウェアデバイスプロセスと一致するソフトウェアデバイスドライバーを使用します。 initは非常に早く呼び出され、probe関数と「taiko_sound_card」などのハードウェアデバイス名をカーネルに登録します。これは、「この名前のこのデバイスのswドライバーです」とカーネルに伝えるためです。カーネルがhwデバイス(デバイスツリーまたはバス列挙)を通過し、一致するものを見つけると、登録されたprobe関数を呼び出します。 これでswデバイスドライバーownsハードウェアデバイス

一致するデバイスが見つからない場合、プローブが呼び出されることはありません。これが通常initが小さく、probeがすべての初期化作業を行う理由です。

0
Liyong Zhou

複数のデバイスとホットプラグ

  1. 多くのPICe接続GPUアクセラレータを備えた大規模なサーバーを実行しています。ある時点で、空きスロット用にGPUを追加購入することにします。

    initを使用した場合、rmmodおよびinsmodモジュールを使用する必要があります。ただし、接続されているすべてのGPUを停止する必要があるため、ダウンタイムが発生します。

    probeを使用すると、新しいGPUを接続するだけで再スキャンが実行されます。

  2. そうしないと、PCIeホットプラグはできません。 https://electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice

QEMU edu PCIデバイスの例

QEMUにはeduと呼ばれる教育用PCIデバイスがあり、probeが呼び出されたときに簡単にテストできます。

まず、そのための最小限のLinuxカーネルPCIドライバーが必要です これはここに書いた

以下を添付したデバイスから開始できます。

-device edu

さらに興味深いことに、SDL GUIでCtrl + Alt + 2または-monitor telnet::45454,server,nowaitのCLIで、次のコマンドを使用します。

device_add edu
device_del edu

起動時にデバイスが接続されている場合:

  • probeは、モジュールをinsmodするとすぐに呼び出されます

  • dmesgには次のタイプの行が含まれます:pci 0000:00:04: [1234:11e8] ...これは、デバイスがBDFにプローブされたことを示しています0000:00:04

    ベンダーは0x1234であり、QEMUソースのデバイスIDは11e8であるため、これがデバイスであることがわかります。

    したがって、PCIデバイスはブート時にプローブされ、どこかにリストに保存されると結論付けます。

モニターからの起動後にデバイスを接続する場合:

  • するまで何も起こりません:

    echo 1 > /sys/bus/pci/rescan
    

    参照: LinuxカーネルにPCI-eバスを列挙させるにはどうすればよいですか?

  • 再スキャン後:

    • すでにinsmoddedされている場合、probeがすぐに呼び出されます。

      したがって、この場合、probeinsmodとは別に発生し、それらの違いを示しています。

    • 持っていない場合:probeinsmodの直後に呼び出されます