カスタム PCIe デバイス用の Linux カーネル デバイス ドライバーを作成しています。ユーザー空間アプリケーションはこのデバイスにマップされ、頻繁にそのメモリにアクセスします (読み取りと書き込み)。PCIe デバイスは、ランタイム中にオフになる可能性がある外部電源によって駆動されます。
デバイスがリセットされるたびに、ユーザー アプリケーションのすべてのメモリ読み取りが返され0xFFFFFFFF
ます。カーネルドライバにデバイスのリセットをいち早く検知したいので、https://www.kernel.org/doc/html/latest/PCI/pci-error-recovery.htmlerror_detected
に合わせてコールバック関数を実装しました。
static pci_ers_result_t mydevice_error_detected(struct pci_dev* dev, pci_channel_state_t state) {
printk(KERN_ALERT "mydevice PCI error detected");
return PCI_ERS_RESULT_DISCONNECT;
}
static struct pci_error_handlers mydevice_error_handlers = {
.error_detected = mydevice_error_detected,
.slot_reset = mydevice_slot_reset,
.resume = mydevice_resume
};
static struct pci_driver mydevice_driver = {
.name = "mydevice",
.id_table = mydevice_ids,
.probe = mydevice_probe,
.remove = mydevice_remove,
.suspend = mydevice_suspend,
.resume = mydevice_resume,
.err_handler = &mydevice_error_handlers
};
ただし、mydevice_error_detected
デバイスのリセット中に呼び出されることはありません。これは、ユーザー空間アプリケーションが継続的にデバイス メモリの読み取りに失敗し (結果として取得しよう0xFFFFFFFF
として) いる場合であってもです。
また、lspci
電源がオフになっていても、PCI 再スキャン後にデバイスが一覧表示されます。
01:00.0 Unassigned class [ff00]: MyVendorId Device 5a00 (rev ff)
唯一の違いはrev ff
、デバイスがオフ状態のときに行末に " " が発生することです。それ以外の場合lspci
は戻ります
01:00.0 Unassigned class [ff00]: MyVendorId Device 5a00
リセット中は構成スペースにアクセスできないため、デバイスが完全にオフになっていると確信しています。デバイスへの最初のメモリ読み取り要求が失敗/タイムアウトするたびに、カーネルがエラー検出コールバックを呼び出すことを期待しています。私の仮定は正しいですか?