UE のハング検出: 手順 1 から 14
UE のハング検出の手順 1 から 14 を以下に説明します。 この手順は、「UE のハング検出および回復フロー」に示されている図に対応しています。
この例では、OID_SET_POWER を使用します。
NDIS がシステム電源 IRP を受信するか、NIC のアクティブな参照が 0 になります。
NDIS は、WDI ドライバーに対して OID_SET_POWER D3 を生成します。
WDI は、WDI OID を LE に送信する前のタスクなど、WDI コマンド (M1) のタイマーを設定します。 コマンドがタスクの場合は、そのタスクの追加タイマーも設定されます。 どちらのタイマーもタイムアウトする可能性がありますが、リセット回復をトリガーできるのは最大で 1 つだけです。
WDI は、LE に WDI コマンドを送信します。 LE では、OID を完了するためにファームウェア コマンドが必要な場合、アダプター構造体に WDI OID を記憶しておくことが推奨されます。 ファームウェアが WDI OID のジョブを完了すると、LE は OID を完了し、アダプター構造体から削除します。 WDI は OID を LE にシリアル化するため、LE が保留中の WDI OID を記憶するために必要なスロットは 1 つだけです。 ファームウェア コマンドがハングした場合、LE はいつでも OID を返すことができますが、ファームウェアが無効になっている場合は手順 17 の予期しない削除までに返すことができます (予期しない削除のコンテキストで可能)。 それ以外の場合は、診断コールバックの前か後かに関係なく、ファームウェアが対応するジョブを完了したときに、LE は WDI OID を完了します。 LE が診断後に WDI OID を記憶する必要がある場合は、それを記憶するための別のスロットが必要となります。 ただし、診断後に OID を受信した場合は、連鎖的なハングを回避するために、LE はファームウェアに触れないようにする必要があります。
LE はファームウェアにコマンドを送信します。
ファームウェア コマンドがタイムアウトした場合、ファームウェアがハングしているか、時間がかかりすぎていることが原因である可能性があります。
- ファームウェアがタイムアウト後にコマンドを完了するのに時間がかかりすぎているだけである場合、LE は WDI コマンドを完了できます。 UE がそれを適切に処理します。
- ファームウェアがハングしている場合、WDI コマンドはすぐには完了しません。 ハードウェアがリセットされている場合、LE は手順 16 の予期しない削除でコマンドを完了する必要があるため、潜在的な競合状態に対する特別な処理を行わなくても安全に完了できます。
WDI タイマーが起動して WDI 診断コマンドが生成されます。 この WDI コマンドは、WDI OID ではなく、LE ドライバー MiniportWdiAdapterHangDiagnose の呼び出しです。
LE はハードウェア制御レジスタの状態と、必要に応じてファームウェア全体の状態を収集します。
- IHV ドライバーは、1 KB に制限されたハードウェア レジスタの内容を収集し、関数から制御が戻るときにそれを返す必要があります。 さらに、実稼働前環境では、IHV が事後デバッグを徹底的に行えるように、LE はファームウェア コンテキストのファイルへのダンプを試みる必要があります。 ハードウェア レジスタとファームウェア イメージの収集を制御するレジストリ キーとしてスイッチを実装できます。
- LE は、キャンセルのために現在のコマンドをマークします。 コマンドの完了が診断と競合する場合は、LE がこのコマンドに対して何も行わなくても許容されます。
- このコマンドが保留中の場合、UE はリセットの結果としてさらに WDI コマンドを送信する可能性があります。 これらは、インフライト コマンドまたはクリーンアップ コマンドです。 診断呼び出しの後、LE はファームウェアに触れることなくそれらを処理する必要があります。
WDI は制御レジスタの状態を受け取ります。
WDI はハングした WDI コマンドをマークして、後で LE によって示されるようにします。
WDI は、WDI の完了なしで NDIS コマンドを返します (完了します)。 WDI は NDIS コマンドをダブルバッファー処理するため、これは安全です。
WDI はリセットのために NDIS を呼び出し、エラー コードNDIS_ERROR_CODE_HARDWARE_FAILURE (0xc000138a) で NdisWriteErrorLogEntry を呼び出します。 これにより、LE のモジュール名と共にイベントがシステム イベント ログに記録されます。 エラー イベント ID は、(0xc000138a | 0xffff) – 0n5002 として自動的に表示されます。 LE も同じエラー コードを使用してエラー ログを書き込む場合、LE によるイベントを簡単に区別するために、データの最初の DWORD に上位ビット セット (0x80000000) が含まれている必要があります。 WDI では、最初の DWORD データに 0x00000000 から 0x7fffffff を使用します。
呼び出しから制御が戻されます。
NDIS は IRP を完了します。
この後、NDIS はバスを呼び出して、予期しない削除と再列挙を実行します。 WDI は、NDIS コマンドを完了するために、WDI コマンドから制御が戻るのを待たなくて済むように、NDIS コマンドをダブルバッファー処理することに注意してください。 これにより、LE がキャンセル ロジックを実行する必要がなくなります (キャンセル ロジックは実行が複雑であることで知られています)。
PnP 操作のデッドロックを回避するために、NDIS OID_SET_POWER を完了する必要があります。 PnP イベントと電源状態変更イベントはすべてシリアル化されます。 つまり、Set power OID から制御が戻らない場合、NDIS は Set power IRP を返すことができないので、リセット回復は予期しない削除 IRP によってロックされます。