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

印刷ビューの終了

更新: 2016 年 11 月
 
 

SR-IOV ドライバの ioctl

SR-IOV ドライバの ioctl は、管理者が構成できるデバイス固有のパラメータを特定したり、特定の構成を適用する前にその構成を検証したりする場合に使用されます。次の各セクションでは、ioctl のデータ構造体やインタフェースについて説明します。

データ構造体

次の各セクションでは、ioctl を実装する前に PF ドライバで定義および初期化しておくべきデータ構造体を示します。

iov_param_ver_info 構造体

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;

ここでは:

version

バージョン情報

num_params

パラメータの数

iov_param_validate 構造体

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;

ここでは:

pv_reason

ioctl コールが失敗した場合の失敗理由を説明する ASCII 文字列。

pv_buflen

バッファー pv_buf の長さ

pv_buf

パラメータを含むバッファー

iov_param_desc 構造体

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; 

ここでは:

pd_name

ldm (1M) コマンド内または pci.conf ファイル内で、パラメータに値を割り当てるために使用されます。

pd_desc

パラメータの簡易説明。

pd_flag

パラメータの適用対象が、PF のみ、VF のみ、PF と VF の両方のいずれであるかを示します。

pd_default_value

ldm() コマンドや pci.conf ファイルでパラメータが指定されていない場合にドライバによって割り当てられる値。

pd_min64

整数パラメータの値の最小範囲を指定します。

pd_max64

整数パラメータの値の最大範囲を指定します。

pd_default_string

パラメータが文字列の場合に使用されるデフォルト文字列を指定します。

IOV_GET_VER_INFO ioctl

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_GET_PARAM_INFO() ioctl を呼び出すドライバの一般的な制御フローは次のようになります。

  1. iov_param_desc_t 構造体でサポートされる構成可能パラメータのそれぞれの記述を含む、この構造体の配列を保持します。この構造体の説明については、iov_param_desc 構造体を参照してください。

  2. 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 ioctl

IOV_VALIDATE_PARAM() を呼び出すドライバの一般的な制御フローは次のようになります。

  1. arg パラメータを pci_param_get_ioctl() インタフェースに送信し、pci_param_t 構造体へのポインタを取得します。

  2. param 検証が失敗した場合は、pv_reason 配列に説明文字列を書き込みます。

  3. pci_get_plist() インタフェースに続いて pci_plist_lookup() インタフェースを呼び出すことで、デバイスパラメータを取得します。

  4. この構成の検証用として構成すべき VF の数を取得するために、PF plist 内で vfs 名前-値ペアを検索します。ドライバは、16 ビット以上の整数データ型を使って vfs 名前-値ペアの検索を行うべきです。pciv_plist_getvf() インタフェースを使って VF デバイスの plist パラメータを取得します。

  5. デバイスにパラメータを実際に適用せずにパラメータを検証します。

  6. 有効な構成が見つかった場合は 0 を返します。


Caution

注意  - 上の手順で検証されるパラメータは、デバイスの現在の構成とは一切関係ありません。それらは、将来の構成になる可能性があると仮定して、個別に検証する必要があります。そうでない場合、ドライバは不適切な構成を示す DDI_EINVAL を返すべきです。さらに、無効な構成が見つかった場合は、ドライバは iov_param_validate 構造体の pv_reason フィールドに説明文字列を提供すべきです。この文字列は、構成が失敗した理由を管理者に伝えます。


ドライバ ioctl のサンプルコード

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);