ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
Sparc OVM プラットフォームでの SR-IOV 構成
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
次の各セクションでは、SR-IOV ドライバのインタフェースについて説明します。
SR-IOV ドライバで現在構成されているパラメータのリストを取得するには、pci_param_get(9F) インタフェースを使用する必要があります。このインタフェースの呼び出しは、ドライバの接続時やほかの適切なタイミングで行われます。返されるデータはパラメータリストへのポインタになりますが、これには、PF デバイスと対応する VF デバイスの両方の名前-値情報が含まれています。
int pci_param_get(dev_info_t *dip, pci_param_t *php)
各表記の意味は次のとおりです。
dev_info 構造体へのポインタ
param ハンドル pci_param_t へのポインタ
デバイスドライバは、pci_param_get インタフェースを呼び出したあと、次の手順を実行して PF と VF のパラメータのリストを取得すべきです。
pci_plist_get(9F) インタフェースを呼び出して PF デバイスのパラメータのリストを取得し、pci_plist_getvf(9F) インタフェースを呼び出して構成対象 VF のパラメータのリストを取得します。
pci_plist_lookup(9F) インタフェースを呼び出してデバイスパラメータを取得します。
すべての PF および VF パラメータを検証します
パラメータが現在の構成と一致しない場合、ドライバはデバイスの接続を失敗させるべきです。
pci_param_free(9F) インタフェースを呼び出すことで、PF デバイスと構成対象 VF デバイスのパラメータを取得するパラメータハンドルへのポインタを解放します。例 21-2 を参照してください
注 - VF を構成する前に、パラメータの検証を完了するようにしてください。
名前-値ペアはデバイスごとに定義します。名前-値ペアは、PF 用に 1 セット、構成対象 VF ごとに 1 セットずつ存在します。名前-値ペアはオプションであり、デバイスの一部またはすべてで存在していない可能性があります。
例 21-2 SR-IOV pci_param_get(9F) ルーチン
pci_param_t my_params; pci_plist_t pf_plist; pci_plist_t vf_plist[8]; labelp = NULL; rval = pci_param_get(dip,&my_params); if (rval || (my_params == NULL)) { cmn_err(CE_NOTE, "No params available\n"); goto continue_with_attach; } rval = pci_plist_get(my_params, &pf_list); if (rval || (pf_plist == NULL)) { cmn_err(CE_NOTE, "No params for PF \n"); goto continue_with_attach; } for (i = 0; i < 8; i++) { rval = pci_plist_getvf(my_params, i, &vf_plist[i]); if (rval || (vf_plist[i] == NULL)) { cmn_err(CE_WARN, "No params for VF %d\n", i); continue; } } pci_param_free(my_params); /* * Validate the PF and VF params lists. * Fail the attach if the params are incompatible or exceed the * resources available. */ continue_with_attach:
SR-IOV デバイスドライバは、IOV_VALIDATE_PARAM ioctl を実装している場合、 pci_param_get_ioctl(9F) インタフェースを使用して、arg 引数から PF および VF デバイスのパラメータを抽出できます。
int pci_param_get_ioctl(dev_info_t *dip, intptr_t arg, int mode,pci_param_t *php)
各表記の意味は次のとおりです。
dev_info 構造体へのポインタ
ドライバの ioctl コールから取得された引数
ドライバの ioctl コールから取得された引数
pci_param_get() または pci_param_get_ioctl() インタフェースを呼び出すことで取得されたハンドルである param ハンドル pci_param_t へのポインタ
ドライバは、パラメータを取得したあと、pci_param_free() インタフェースを呼び出すことで、この呼び出しで返された param ハンドルを解放すべきです。
pci_plist_get(9F) インタフェースは、pci_param_get(9F) 呼び出しとpci_param_get_ioctl(9F) 呼び出しのいずれかから取得された param ハンドルからパラメータリストを取得するために使用します。
int pci_plist_get(pci_param_t param, pci_plist_t *plist_p)
各表記の意味は次のとおりです。
pci_param_get() または pci_param_get_ioctl() インタフェースから取得されたハンドル。
pci_plist_t へのポインタ (成功時には NULL 以外の plist が返される)。
pci_plist_get() 呼び出しから返される plist は、PF 機能専用です。構造体 pci_plist_t では、次のデータ型の配列がサポートされます。
int8_t
uint8
int16_t
uint16_t
int32_t
uint32_t
int64_t
uint64_t
char *
pci_plist_getvf(9F) インタフェースは、VF デバイスの名前-値ペアリストを取得するために使用します。
int pciv_plist_getvf (pci_param_t param, uint16_t vf_index, pci_plist_t *vfplist_p )
各表記の意味は次のとおりです。
pci_param_get() または pci_param_get_ioctl() インタフェースから取得されたハンドル。
0 から #VFS - 1 までの値。
pci_plist_t 構造体へのポインタ。
pciv_vf_config(9F) インタフェースは SR-IOV ドライバで、VF に関する構成情報を取得するために使用されるほか、ドライバの接続時に VF を構成するためにも使用されます。
#include <sys/sunddi.h> int pciv_vf_config(dev_info_t *dip, pciv_config_vf_t *vfcfg_p)
各表記の意味は次のとおりです。
dev_info 構造体へのポインタ。
pciv_config_vf 構造体へのポインタ。
typedef enum { PCIV_VFCFG_PARAM, PCIV_VF_ENABLE, PCIV_VF_DISABLE PCIV_EVT_VFENABLE_PRE, PCIV_EVT_VFENABLE_POST, PCIV_EVT_VFDISABLE_PRE, PCIV_EVT_VFDISABLE_POST } pciv_vf_config_cmd_t;
pciv_config_vf 構造体には次のフィールドが含まれます。
typedef struct pciv_config_vf { int version; pciv_vf_config_cmd_t cmd; uint16_t num_vf; uint16_t first_vf_offset; uint16_t vf_stride; boolean_t ari_cap; uint32_t page_size; } pciv_config_vf_t;
各表記の意味は次のとおりです。
バージョン番号。
このインタフェースを構成情報の取得のために呼び出すのか、VF の接続のために呼び出すのかを示すために使用されます。
PCIV_VFCFG_PARAM – 構成情報を取得します
PCIV_VF_ENABLE – VF を有効にします
PCIV_EVT_VFENABLE_PRE
PCIV_EVT_VFDISABLE_PRE
PCIV_EVT_VFENABLE_POST
PCIV_EVT_VFDISABLE_POST
バックエンドで定義される VF の数。
各 VF 間の距離。
最初の VF と PF とのオフセット。
ARI 可能な階層。
システムのページサイズを指定します。
ドライバはまず、構成情報を取得するために、cmd フィールドを PCIV_VFCFG_PARAM に設定して pciv_vfconfig() インタフェースを呼び出すべきです。ドライバは次に、VF を構成するために、cmd フィールドを PCIV_VF_ENABLE に設定してこのインタフェースを再度呼び出すべきです。
ドライバは次のいずれかのエラーコードを返すことができます。
DDI_SUCCESS
DDI_FAILURE
PCIV_REQRESET
PCIV_REQREATTACH
ドライバは、pciv_vf_config() インタフェースを呼び出して VF を有効化する前に、DDI_CB_FLAG_SRIOV ビットを設定してコールバックを登録しておく必要はありません。しかし、SR-IOV フレームワークによって VF が構成解除されたときに通知を受け取るためには、ドライバは、VF の有効化後に DDI_CB_FLAG_SRIOV ビットを設定してコールバックを登録する必要があります。追加情報については、「ドライバのコールバック」を参照してください。
VF をサポートできる PF ドライバはすべて、その機能を PCIe フレームワークに知らせるために、flags 引数に DDI_CB_FLAG_SRIOV フラグを設定して ddi_cb_register(9F) を呼び出すべきです。ddi_cb_register() 関数は、ドライバの接続ルーチン内で呼び出す必要があります。PF デバイスドライバがその接続ルーチン内で pciv_vf_config() 関数を呼び出して VF を有効化する場合、PF ドライバは VF の有効化後に ddi_cb_register() 関数を呼び出すべきです。
フレームワークは、次のアクションを実行する際に DDI_CB_FLAG_SRIOV フラグを必要とします。
VF をサポートできるデバイスドライバが存在することを Sparc OVM エージェントに示します。すると、Sparc OVM エージェントは VF デバイスの作成を許可します。この機能がないと、ユーザーは SPARC プラットフォーム上で VF を作成できません。
フレームワークは、VF を無効にする前とあとで、PF ドライバに対してコールバックを発行します。これにより、PF ドライバは VF サポートのための内部管理作業を容易に行えるようになります。
ドライバで pci_plist_lookup(9F) インタフェースを使用すると、サポートされているさまざまなデータ型の名前-値ペアを検索できます。この関数は、名前とインタフェース名で示された型に一致する nvpair (名前-値ペア) を検索します。見つかった場合、nelem と val が変更され、値の要素数とデータの開始アドレスがそれぞれ格納されます。
pci_plist_lookup() インタフェースでは次のデータ型がサポートされています。
int pci_plist_lookup_int8(pci_plist_t plist , const char *name,int8_t * val)
int pci_plist_lookup_uint8(pci_plist_t plist , const char *name,uint8_t * val)
int pci_plist_lookup_int16(pci_plist_t plist , const char *name,int16_t * val)
int pci_plist_lookup_uint16(pci_plist_t plist , const char *name, uint16_t * val)
int pci_plist_lookup_int32(pci_plist_t plist , const char *name,int32_t * val)
int pci_plist_lookup_uint32(pci_plist_t plist , const char *name, uint32_t * val)
int pci_plist_lookup_int64(pci_plist_t plist , const char *name,int64_t * val)
int pci_plist_lookup_uint64(pci_plist_t plist , const char *name, uint64_t * val)
int pci_plist_lookup_string(pci_plist_t plist , const char *name, char ** val)
int pci_plist_lookup_plist(pci_plist_t plist , const char *name, pci_plist_t ** val)
int pci_plist_lookup_int8_array(pci_plist_t plist, const char *name,int8_t * val, uint_t *nelem)
int pci_plist_lookup_uint8_array(pci_plist_t plist, const char *name, int8_t * val, uint_t *nelem)
int pci_plist_lookup_int16_array(pci_plist_t plist, const char *name,int16_t * val, uint_t *nelem)
int pci_plist_lookup_uint16_array(pci_plist_t plist, const char *name, uint16_t *val, uint_t *nelem)
int pci_plist_lookup_int32_array(pci_plist_t plist, const char *name,int32_t * val, uint_t *nelem)
int pci_plist_lookup_uint32_array(pci_plist_t plist, const char *name,uint32_t *val, uint_t *nelem)
int pci_plist_lookup_int64_array(pci_plist_t plist, const char *name, int64_t *val, uint_t *nelem)
int pci_plist_lookup_uint64_array(pci_plist_t plist,const char *name,uint64_t * val, uint_t *nelem)
int pci_plist_lookup_string_array(pci_plist_t plist, const char *name,char ** val, uint_t *nelem)
各表記の意味は次のとおりです。
処理対象となる pci_plist_t 構造体へのポインタ。
検索する名前-値ペアの名前。
値の要素数を格納するアドレス。
データの開始アドレス。
pci_plist_lookup() 関数は、成功時は 0 を返し、失敗時はエラー値を返します。次のエラー値がサポートされています。
無効な引数
一致する名前-値ペアが見つかりません
エンコードまたはデコードの方式がサポートされていません
param ハンドルを使ってデバイスパラメータを取得したあと、ドライバによって pci_param_free(9F) インタフェースが呼び出される必要があります。この呼び出しにより、pci_param_get() および pci_param_get_ioctl() インタフェースによって割り当てられたリソースが解放されます。
int pci_param_free (pci_param_t param)
ここで param は、pci_param_get() または pci_param_get_ioctl() インタフェースから取得されたハンドルです。
pciv_send(9F) インタフェースは、SR-IOV に対応した PF および VF ドライバが互いに通信を行うために使用されます。PF ドライバはいずれの VF ドライバとも通信できますが、VF ドライバはそれ自身の PF ドライバとしか通信できません。
int pciv_send(dev_info_t *dip, pciv_pvp_req_t *req
各表記の意味は次のとおりです。
dev_info 構造体へのポインタ。
pciv_pvp_req_t 構造体へのポインタ。
pciv_pvp_req_t の構造:
typedef struct pciv_pvp_req { int pvp_dstfunc; caddr_t pvp_buf; size_t pvp_nbyte; buf_cb_t pvp_cb; caddr_t pvp_cb_arg; uint_t pvp_flag; } pciv_pvp_req_t;
各表記の意味は次のとおりです。
PF ドライバから呼び出された場合、VF インデックスの範囲は 1 から num_vf になります。呼び出し元が VF ドライバの場合、これは常に PCIV_PF にすべきです。
送信対象となる呼び出し元のバッファーのバッファーアドレス。
送信されるバイトの数 (8K 未満でなければならない)。
pvp_flag が PCIV_NOWAIT として設定された場合のコールバック関数のポインタ。
pvp_flag を PCIV_NOWAIT に設定した場合、呼び出しがすぐに戻り、pvp_buf のデータが宛先に送信される前に pvp_cb のコールバックルーチンが呼び出されます。呼び出し元はその後、コールバックルーチン内でバッファーを解放することを許可されます。
typedef void (*buf_cb_t)(int rc, caddr_t buf, size_t size, caddr_t cb_arg);
各表記の意味は次のとおりです。
送信用の DDI リターンコード。
送信対象となる呼び出し元のバッファーのバッファーアドレス。
送信されるバイトの数。
呼び出し元がルーチンの呼び出し時に設定した入力引数。
pvp_flag が PCIV_NOWAIT として設定された場合の、pvp_cb のコールバック入力引数。
PCIV_NOWAIT – 受信側の応答を待ちません。
PCIV_WAIT – これがデフォルトの状態です。受信側から送信の確認を受け取るまで待ちます。
pciv_send() インタフェースは次のいずれかの戻り値を返します。
バッファーの送信が成功しました。
デバイスドライバがこの処理をサポートしていません。呼び出し元はハードウェアメールボックスなど、その他のメカニズムを使用できます。
pvp_nbyte または pvp_dstfunc が無効です。
リソース不足により処理が失敗しました。
着信した送信を処理するためのコールバックが、リモート側で登録されませんでした。
不明な理由により失敗しました。