ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
デバイスドライバの記述 Oracle Solaris 11.1 Information Library (日本語) |
パート I Oracle Solaris プラットフォーム用デバイスドライバの設計
2. Oracle Solaris カーネルとデバイスツリー
Sparc OVM プラットフォームでの SR-IOV 構成
22. ドライバのコンパイル、ロード、パッケージ化、およびテスト
23. デバイスドライバのデバッグ、テスト、およびチューニング
SR-IOV ドライバの ioctl は、管理者が構成できるデバイス固有のパラメータを特定したり、特定の構成を適用する前にその構成を検証したりする場合に使用されます。次の各セクションでは、ioctl のデータ構造体やインタフェースについて説明します。
次の各セクションでは、ioctl を実装する前に PF ドライバで定義および初期化しておくべきデータ構造体を示します。
iov_param_ver_info 構造体は次のように定義されています。
#define IOV_IOCTL (('I' << 24) | ('O' << 16) | ('V' << 8)) #define IOV_GET_VER_INFO (IOV_IOCTL | 0) #define IOV_GET_PARAM_INFO (IOV_IOCTL | 1) #define IOV_VALIDATE_PARAM (IOV_IOCTL | 2) #define IOV_PARAM_DESC_VERSION 1
iov_param_ver_info 構造体には次のフィールドが含まれています。
typedef struct iov_param_ver_info { uint32_t version; uint32_t num_params; } iov_param_ver_info_t;
各表記の意味は次のとおりです。
バージョン情報
パラメータの数
iov_param_validate 構造体は次のように定義されています。
#define IOV_IOCTL (('I' << 24) | ('O' << 16) | ('V' << 8)) #define IOV_GET_VER_INFO (IOV_IOCTL | 0) #define IOV_GET_PARAM_INFO (IOV_IOCTL | 1) #define IOV_VALIDATE_PARAM (IOV_IOCTL | 2) #define IOV_PARAM_DESC_VERSION 1
iov_param_validate には次のフィールドが含まれています。
typedef struct iov_param_validate { char pv_reason[MAX_REASON_LEN + 1]; int32_t pv_buflen; /* encoded buffer containing params */ char pv_buf[1]; /* size of buf is pv_buflen */ } iov_param_validate_t;
各表記の意味は次のとおりです。
ioctl コールが失敗した場合の失敗理由を説明する ASCII 文字列。
バッファー pv_buf の長さ
パラメータを含むバッファー
iov_param_desc 構造体は次のように定義されています。
#define IOV_IOCTL (('I' << 24) | ('O' << 16) | ('V' << 8)) #define IOV_GET_VER_INFO (IOV_IOCTL | 0) #define IOV_GET_PARAM_INFO (IOV_IOCTL | 1) #define IOV_VALIDATE_PARAM (IOV_IOCTL | 2) #define IOV_PARAM_DESC_VERSION 1
構造体 iov_param_desc には次のフィールドが含まれています。
typedef struct iov_param_desc { char pd_name[MAX_PARAM_NAME_SIZE]; char pd_desc[MAX_PARAM_DESC_SIZE]; int32_t pd_flag; /* applicable for PF or VF or both */ int32_t pd_data_type; /* integer, string, plist */ /* Following 3 are applicable for integer data types */ uint64_t pd_default_value; uint64_t pd_min64; uint64_t pd_max64; char pd_default_string [MAX_PARAM_DEFAULT_STRING_SIZE]; } iov_param_desc_t;
各表記の意味は次のとおりです。
ldm(1M) コマンド内または pci.conf ファイル内で、パラメータに値を割り当てるために使用されます。
パラメータの簡易説明。
パラメータの適用対象が、PF のみ、VF のみ、PF と VF の両方のいずれであるかを示します。
ldm() コマンドや pci.conf ファイルでパラメータが指定されていない場合にドライバによって割り当てられる値。
整数パラメータの値の最小範囲を指定します。
整数パラメータの値の最大範囲を指定します。
パラメータが文字列の場合に使用されるデフォルト文字列を指定します。
IOV_GET_VER_INFO IOCTL() ioctl を実装する SR-IOV デバイスドライバは、iov_param_ver_info 構造体の version および num_params フィールドを設定し、その値を呼び出し元の関数に返すべきです。続いて呼び出し元の関数は、IOV_GET_PARAM_INFO() ioctl コールを使ってパラメータの記述を取得する際に必要となるバッファーのサイズを、version および num_params パラメータを使用して決定します。
IOV_GET_PARAM_INFO() ioctl を呼び出すドライバの一般的な制御フローは次のようになります。
iov_param_desc_t 構造体でサポートされる構成可能パラメータのそれぞれの記述を含む、この構造体の配列を保持します。この構造体の説明については、iov_param_desc 構造体を参照してください。
iov_param_desc_t 構造体の配列をコピーして arg パラメータに出力します。iov_param_desc_t 構造体のフィールドは静的であり、コンパイル時に定義できます。
配列の要素数は、IOV_GET_VER_INFO() ioctl コールから返された num_params 値になります。バッファーのサイズは sizeof (iov_param_desc_t) * num_params になります
IOV_VALIDATE_PARAM() を呼び出すドライバの一般的な制御フローは次のようになります。
arg パラメータを pci_param_get_ioctl() インタフェースに送信し、pci_param_t 構造体へのポインタを取得します。
param 検証が失敗した場合は、pv_reason 配列に説明文字列を書き込みます。
pci_get_plist() インタフェースに続いて pci_plist_lookup() インタフェースを呼び出すことで、デバイスパラメータを取得します。
この構成の検証用として構成すべき VF の数を取得するために、PF plist 内で vfs 名前-値ペアを検索します。ドライバは、16 ビット以上の整数データ型を使って vfs 名前-値ペアの検索を行うべきです。pciv_plist_getvf() インタフェースを使って VF デバイスの plist パラメータを取得します。
デバイスにパラメータを実際に適用せずにパラメータを検証します。
有効な構成が見つかった場合は 0 を返します。
注意 - 上の手順で検証されるパラメータは、デバイスの現在の構成とは一切関係ありません。それらは、将来の構成になる可能性があると仮定して、個別に検証する必要があります。そうでない場合、ドライバは不適切な構成を示す DDI_EINVAL を返すべきです。さらに、無効な構成が見つかった場合は、ドライバは iov_param_validate 構造体の pv_reason フィールドに説明文字列を提供すべきです。この文字列は、構成が失敗した理由を管理者に伝えます。 |
コールバックを登録するには、DDI インタフェース ddi_cb_register() と ddi_cb_unregister() を使用します。コールバックはイベント通知および着信データトラフィックに使用されます。コールバックは、送信時の各イベントのイベントハンドラとしての役割を果たします。
SR-IOV ドライバは、VF の構成または構成解除の前後に PF ドライバに通知するための追加コールバックを実装すべきです。
ドライバでコールバックを実装するには、次の DDI コールバック登録メカニズムインタフェースを使用します。
int ddi_cb_register(dev_info_t *dip, ddi_cb_flags_t flags, ddi_cb_func_t cbfunc, void *arg1, void *arg2,ddi_cb_handle_t *ret_hdlp)
詳細は、ddi_cb_register(9F) のマニュアルページを参照してください。
typedef int(*ddi_cb_func_t) (dev_info_t *dip, ddi_cb_action_t action, void *cbarg, void *arg1, void *arg2)
各表記の意味は次のとおりです。
dev_info 構造体へのポインタです
構造体 pciv_config_vf_t へのポインタです。
VF 構成への変更に関する通知を受け取るには、DDI_CB_PCIV_CONFIG_VF として設定します。
cbfunc() ルーチンが実行されるたびに自身に送信される非公開引数。
cbfunc() ルーチンが実行されるたびに自身に送信される非公開引数。
追加情報については、「コールバックハンドラ関数の登録」を参照してください。
注 - SR-IOV に対応している PF ドライバは必ず、ddi_cb_flags_t DDI_CB_FLAG_SRIOV を使用することで、PF ドライバが SR-IOV に対応していることを Oracle Solaris IOV フレームワークに知らせる必要があります。
enum ioc_reply igb_ioctl(igb_t *igb, struct iocblk *iocp, mblk_t *mp) { int rval = 0; iov_param_ver_info_t *iov_param_ver; iov_param_validate_t pvalidate; pci_param_t my_params; char reason[81]; if (mp->b_cont == NULL) return (IOC_INVAL); if ((int)iocp->ioc_count < 0) return (IOC_INVAL); switch (iocp->ioc_cmd) { case IOV_GET_PARAM_VER_INFO: if (iocp->ioc_count < sizeof (iov_param_ver_info_t)) return (IOC_INVAL); iov_param_ver = (iov_param_ver_info_t *)(mp->b_cont->b_rptr); iov_param_ver->version = IOV_PARAM_DESC_VERSION; iov_param_ver->num_params = NUM_OF_PARAMS; return (IOC_REPLY); case IOV_GET_PARAM_INFO: if (iocp->ioc_count < sizeof (pci_list)) return (IOC_INVAL); memcpy((caddr_t)(mp->b_cont->b_rptr), &pci_list,sizeof (pci_list)); return (IOC_REPLY); case IOV_VALIDATE_PARAM: if (iocp->ioc_count <= 0) return (IOC_INVAL); strcpy(reason, "Failed to read params sent\n"); rval = pci_param_get_ioctl(igb->dip,(uintptr_t)(mp->b_cont->b_rptr), iocp->ioc_flag | FKIOCTL,&my_params ); if (rval == 0) { rval = validate_params(igb->dip, my_params, reason); pci_param_free(my_params); } if (rval) { memcpy(mp->b_cont->b_rptr, reason, sizeof (reason)); iocp->ioc_count = sizeof (reason); return (IOC_REPLY); } iocp->ioc_count = 0; return (IOC_REPLY); iov_param_ver_info_t iov_param_ver; iov_param_validate_t pvalidate; pci_param_t my_params; switch (cmd) { case IOV_GET_PARAM_VER_INFO: iov_param_ver.version = IOV_PARAM_DESC_VERSION; iov_param_ver.num_params = NUM_OF_PARAMS; if (ddi_copyout(&iov_param_ver, (caddr_t)arg, sizeof (iov_param_ver_info_t), mode) != DDI_SUCCESS) return (DEFAULT); return (0); case IOV_GET_PARAM_INFO: if (ddi_copyout(&pci_list, (caddr_t)arg,param_list_size, mode) != DDI_SUCCESS) return (DEFAULT); return (0); case IOV_VALIDATE_PARAM: strcpy(reason, "Failed to read params sent\n"); rv = pci_param_get_ioctl(state->dip, arg, mode, &my_params); if (rv == 0) rv = validate_params(state->dip, my_params, reason); else return (rv); pci_param_free(my_params); if (rv) { if (ddi_copyout(reason,iov_param_validate_t *)arg)->pv_reason, sizeof (reason), mode) != DDI_SUCCESS) return (DEFAULT); return (rv); } return (0);