Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

SR-IOV ドライバのインタフェース

次の各セクションでは、SR-IOV ドライバのインタフェースについて説明します。

pci_param_get() インタフェース

SR-IOV ドライバで現在構成されているパラメータのリストを取得するには、pci_param_get(9F) インタフェースを使用する必要があります。このインタフェースの呼び出しは、ドライバの接続時やほかの適切なタイミングで行われます。返されるデータはパラメータリストへのポインタになりますが、これには、PF デバイスと対応する VF デバイスの両方の名前-値情報が含まれています。

int pci_param_get(dev_info_t *dip, pci_param_t *php)

ここでは:

dip

dev_info 構造体へのポインタ

php

param ハンドル pci_param_t へのポインタ

デバイスドライバは、pci_param_get インタフェースを呼び出したあと、次の手順を実行して PF と VF のパラメータのリストを取得すべきです。

  1. pci_plist_get(9F) インタフェースを呼び出して PF デバイスのパラメータのリストを取得し、pci_plist_getvf(9F) インタフェースを呼び出して構成対象 VF のパラメータのリストを取得します。

  2. pci_plist_lookup(9F) インタフェースを呼び出してデバイスパラメータを取得します。

  3. すべての PF および VF パラメータを検証します

  4. パラメータが現在の構成と一致しない場合、ドライバはデバイスの接続を失敗させるべきです。

  5. pci_param_free(9F) インタフェースを呼び出すことで、PF デバイスと構成対象 VF デバイスのパラメータを取得するパラメータハンドルへのポインタを解放します。使用例 123 を参照してください。


注 - VF を構成する前に、パラメータの検証を完了するようにしてください。

名前-値ペアはデバイスごとに定義します。名前-値ペアは、PF 用に 1 セット、構成対象 VF ごとに 1 セットずつ存在します。名前-値ペアはオプションであり、デバイスの一部またはすべてで存在していない可能性があります。

使用例 123  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:

pci_param_get_ioctl() インタフェース

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)

ここでは:

dip

dev_info 構造体へのポインタ

arg

ドライバの ioctl コールから取得された引数

mode

ドライバの ioctl コールから取得された引数

php

pci_param_get() または pci_param_get_ioctl() インタフェースを呼び出すことで取得されたハンドルである param ハンドル pci_param_t へのポインタ

ドライバは、パラメータを取得したあと、pci_param_free() インタフェースを呼び出すことで、この呼び出しで返された param ハンドルを解放すべきです。

pci_plist_get() インタフェース

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)

ここでは:

param

pci_param_get() または pci_param_get_ioctl() インタフェースから取得されたハンドル。

plist_p

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() インタフェース

pci_plist_getvf(9F) インタフェースは、VF デバイスの名前-値ペアリストを取得するために使用します。

int pciv_plist_getvf (pci_param_t param, uint16_t vf_index, pci_plist_t *vfplist_p )

ここでは:

param

pci_param_get() または pci_param_get_ioctl() インタフェースから取得されたハンドル。

vf_index

0 から #VFS - 1 までの値。

*vfplist_p

pci_plist_t 構造体へのポインタ。

pciv_vf_config() インタフェース

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)

ここでは:

dip

dev_info 構造体へのポインタ。

vfcfg_p

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;

ここでは:

version

バージョン番号。

cmd

このインタフェースを構成情報の取得のために呼び出すのか、VF の接続のために呼び出すのかを示すために使用されます。

  • PCIV_VFCFG_PARAM – 構成情報を取得します

  • PCIV_VF_ENABLE – VF を有効にします

    • PCIV_EVT_VFENABLE_PRE

    • PCIV_EVT_VFDISABLE_PRE

    • PCIV_EVT_VFENABLE_POST

    • PCIV_EVT_VFDISABLE_POST

num_vf

バックエンドで定義される VF の数。

vf_stride

各 VF 間の距離。

first_vf_offset

最初の VF と PF とのオフセット。

ari_cap

ARI 可能な階層。

page_size

システムのページサイズを指定します。

ドライバはまず、構成情報を取得するために、cmd フィールドを PCIV_VFCFG_PARAM に設定して pciv_vfconfig() インタフェースを呼び出すべきです。ドライバは次に、cmd フィールドを PCIV_VF_ENABLE に設定してこのインタフェースを再度呼び出し、VF を構成する必要があります。

ドライバは次のいずれかのエラーコードを返すことができます。

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() インタフェース

ドライバでpci_plist_lookup(9F) インタフェースを使用すると、サポートされているさまざまなデータ型の名前-値ペアを検索できます。この関数は、名前とインタフェース名で示された型に一致する nvpair (名前-値ペア) を検索します。見つかった場合、nelemval が変更され、値の要素数とデータの開始アドレスがそれぞれ格納されます。

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)

ここでは:

plist

処理対象となる pci_plist_t 構造体へのポインタ。

name

検索する名前-値ペアの名前。

nelem

値の要素数を格納するアドレス。

val

データの開始アドレス。

pci_plist_lookup() 関数は、成功時は 0 を返し、失敗時はエラー値を返します。次のエラー値がサポートされています。

DDI_EINVAL

無効な引数

ENOENT

一致する名前-値ペアが見つかりません

ENOTSUP

エンコードまたはデコードの方式がサポートされていません

pci_param_free() インタフェース

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() インタフェース

pciv_send(9F) インタフェースは、SR-IOV に対応した PF および VF ドライバが互いに通信を行うために使用されます。PF ドライバはいずれの VF ドライバとも通信できますが、VF ドライバはそれ自身の PF ドライバとしか通信できません。

int pciv_send(dev_info_t *dip, pciv_pvp_req_t *req

ここでは:

dip

dev_info 構造体へのポインタ。

req

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;

ここでは:

pvp_dstfunc

PF ドライバから呼び出された場合、VF インデックスの範囲は 1 から num_vf になります。呼び出し元が VF ドライバの場合、これは常に PCIV_PF にすべきです。

pvp_buf

送信対象となる呼び出し元のバッファーのバッファーアドレス。

pvp_nbyte

送信されるバイトの数 (8K 未満でなければならない)。

pvp_cb

pvp_flagPCIV_NOWAIT として設定された場合のコールバック関数のポインタ。

pvp_flagPCIV_NOWAIT に設定した場合、呼び出しがすぐに戻り、pvp_buf のデータが宛先に送信される前に pvp_cb のコールバックルーチンが呼び出されます。呼び出し元はその後、コールバックルーチン内でバッファーを解放することを許可されます。

typedef void (*buf_cb_t)(int rc, caddr_t buf, size_t size, caddr_t cb_arg);

ここでは:

rc

送信用の DDI リターンコード。

buf

送信対象となる呼び出し元のバッファーのバッファーアドレス。

size

送信されるバイトの数。

cb_arg

呼び出し元がルーチンの呼び出し時に設定した入力引数。

pvp_cb_arg

pvp_flagPCIV_NOWAIT として設定された場合の、pvp_cb のコールバック入力引数。

pvp_flag
  • PCIV_NOWAIT – 受信側の応答を待ちません。

  • PCIV_WAIT – これがデフォルトの状態です。受信側から送信の確認を受け取るまで待ちます。

pciv_send() インタフェースは次のいずれかの戻り値を返します。

DDI_SUCCESS

バッファーの送信が成功しました。

DDI_ENOTSUP

デバイスドライバがこの処理をサポートしていません。呼び出し元はハードウェアメールボックスなど、その他のメカニズムを使用できます。

DDI_EINVAL

pvp_nbyte または pvp_dstfunc が無効です。

DDI_ENOMEM

リソース不足により処理が失敗しました。

DDI_ETRANSPORT

着信した送信を処理するためのコールバックが、リモート側で登録されませんでした。

DDI_FAILURE

不明な理由により失敗しました。