Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Mar 2015 00:40:42 +0000 (UTC)
From:      Ryan Stone <rstone@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r279451 - in head/sys: conf dev/pci sys
Message-ID:  <201503010040.t210eg5X093140@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rstone
Date: Sun Mar  1 00:40:42 2015
New Revision: 279451
URL: https://svnweb.freebsd.org/changeset/base/279451

Log:
  Add infrastructure for exporting config schema from PF drivers
  
  Differential Revision:	https://reviews.freebsd.org/D80
  MFC after: 		1 month
  Sponsored by:		Sandvine Inc.

Added:
  head/sys/dev/pci/pci_iov_schema.c   (contents, props changed)
  head/sys/dev/pci/schema_private.h   (contents, props changed)
  head/sys/sys/iov_schema.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/pci/pci_if.m
  head/sys/dev/pci/pci_iov.c
  head/sys/dev/pci/pci_iov_private.h
  head/sys/dev/pci/pci_private.h
  head/sys/dev/pci/pcivar.h
  head/sys/sys/iov.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/conf/files	Sun Mar  1 00:40:42 2015	(r279451)
@@ -2032,6 +2032,7 @@ dev/pci/isa_pci.c		optional pci isa
 dev/pci/pci.c			optional pci
 dev/pci/pci_if.m		standard
 dev/pci/pci_iov.c		optional pci pci_iov
+dev/pci/pci_iov_schema.c	optional pci pci_iov
 dev/pci/pci_pci.c		optional pci
 dev/pci/pci_subr.c		optional pci
 dev/pci/pci_user.c		optional pci

Modified: head/sys/dev/pci/pci_if.m
==============================================================================
--- head/sys/dev/pci/pci_if.m	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/dev/pci/pci_if.m	Sun Mar  1 00:40:42 2015	(r279451)
@@ -46,6 +46,10 @@ CODE {
 	}
 };
 
+HEADER {
+	struct nvlist;
+}
+
 
 METHOD u_int32_t read_config {
 	device_t	dev;
@@ -201,6 +205,8 @@ METHOD void child_added {
 METHOD int iov_attach {
 	device_t	dev;
 	device_t	child;
+	struct nvlist	*pf_schema;
+	struct nvlist	*vf_schema;
 };
 
 METHOD int iov_detach {

Modified: head/sys/dev/pci/pci_iov.c
==============================================================================
--- head/sys/dev/pci/pci_iov.c	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/dev/pci/pci_iov.c	Sun Mar  1 00:40:42 2015	(r279451)
@@ -46,11 +46,16 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <machine/bus.h>
+#include <machine/stdarg.h>
+
+#include <sys/nv.h>
+#include <sys/iov_schema.h>
 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pci_private.h>
 #include <dev/pci/pci_iov_private.h>
+#include <dev/pci/schema_private.h>
 
 #include "pci_if.h"
 #include "pcib_if.h"
@@ -71,18 +76,30 @@ static struct cdevsw iov_cdevsw = {
 #define IOV_WRITE(d, r, v, w) \
 	pci_write_config((d)->cfg.dev, (d)->cfg.iov->iov_pos + r, v, w)
 
+static nvlist_t	*pci_iov_build_schema(nvlist_t **pf_schema,
+		    nvlist_t **vf_schema);
+static void	pci_iov_build_pf_schema(nvlist_t *schema,
+		    nvlist_t **driver_schema);
+static void	pci_iov_build_vf_schema(nvlist_t *schema,
+		    nvlist_t **driver_schema);
+static nvlist_t	*pci_iov_get_pf_subsystem_schema(void);
+static nvlist_t	*pci_iov_get_vf_subsystem_schema(void);
+
 int
-pci_iov_attach_method(device_t bus, device_t dev)
+pci_iov_attach_method(device_t bus, device_t dev, nvlist_t *pf_schema,
+    nvlist_t *vf_schema)
 {
 	device_t pcib;
 	struct pci_devinfo *dinfo;
 	struct pcicfg_iov *iov;
+	nvlist_t *schema;
 	uint32_t version;
 	int error;
 	int iov_pos;
 
 	dinfo = device_get_ivars(dev);
 	pcib = device_get_parent(bus);
+	schema = NULL;
 	
 	error = pci_find_extcap(dev, PCIZ_SRIOV, &iov_pos);
 
@@ -108,6 +125,13 @@ pci_iov_attach_method(device_t bus, devi
 	}
 	iov->iov_pos = iov_pos;
 
+	schema = pci_iov_build_schema(&pf_schema, &vf_schema);
+	if (schema == NULL) {
+		error = ENOMEM;
+		goto cleanup;
+	}
+	iov->iov_schema = schema;
+
 	iov->iov_cdev = make_dev(&iov_cdevsw, device_get_unit(dev),
 	    UID_ROOT, GID_WHEEL, 0600, "iov/%s", device_get_nameunit(dev));
 
@@ -123,6 +147,9 @@ pci_iov_attach_method(device_t bus, devi
 	return (0);
 
 cleanup:
+	nvlist_destroy(schema);
+	nvlist_destroy(pf_schema);
+	nvlist_destroy(vf_schema);
 	free(iov, M_SRIOV);
 	mtx_unlock(&Giant);
 	return (error);
@@ -154,6 +181,7 @@ pci_iov_detach_method(device_t bus, devi
 		destroy_dev(iov->iov_cdev);
 		iov->iov_cdev = NULL;
 	}
+	nvlist_destroy(iov->iov_schema);
 
 	free(iov, M_SRIOV);
 	mtx_unlock(&Giant);
@@ -161,6 +189,115 @@ pci_iov_detach_method(device_t bus, devi
 	return (0);
 }
 
+static nvlist_t *
+pci_iov_build_schema(nvlist_t **pf, nvlist_t **vf)
+{
+	nvlist_t *schema, *pf_driver, *vf_driver;
+
+	/* We always take ownership of the schemas. */
+	pf_driver = *pf;
+	*pf = NULL;
+	vf_driver = *vf;
+	*vf = NULL;
+
+	schema = pci_iov_schema_alloc_node();
+	if (schema == NULL)
+		goto cleanup;
+
+	pci_iov_build_pf_schema(schema, &pf_driver);
+	pci_iov_build_vf_schema(schema, &vf_driver);
+
+	if (nvlist_error(schema) != 0)
+		goto cleanup;
+
+	return (schema);
+
+cleanup:
+	nvlist_destroy(schema);
+	nvlist_destroy(pf_driver);
+	nvlist_destroy(vf_driver);
+	return (NULL);
+}
+
+static void
+pci_iov_build_pf_schema(nvlist_t *schema, nvlist_t **driver_schema)
+{
+	nvlist_t *pf_schema, *iov_schema;
+
+	pf_schema = pci_iov_schema_alloc_node();
+	if (pf_schema == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	iov_schema = pci_iov_get_pf_subsystem_schema();
+
+	/*
+	 * Note that if either *driver_schema or iov_schema is NULL, then
+	 * nvlist_move_nvlist will put the schema in the error state and
+	 * SR-IOV will fail to initialize later, so we don't have to explicitly
+	 * handle that case.
+	 */
+	nvlist_move_nvlist(pf_schema, DRIVER_CONFIG_NAME, *driver_schema);
+	nvlist_move_nvlist(pf_schema, IOV_CONFIG_NAME, iov_schema);
+	nvlist_move_nvlist(schema, PF_CONFIG_NAME, pf_schema);
+	*driver_schema = NULL;
+}
+
+static void
+pci_iov_build_vf_schema(nvlist_t *schema, nvlist_t **driver_schema)
+{
+	nvlist_t *vf_schema, *iov_schema;
+
+	vf_schema = pci_iov_schema_alloc_node();
+	if (vf_schema == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	iov_schema = pci_iov_get_vf_subsystem_schema();
+
+	/*
+	 * Note that if either *driver_schema or iov_schema is NULL, then
+	 * nvlist_move_nvlist will put the schema in the error state and
+	 * SR-IOV will fail to initialize later, so we don't have to explicitly
+	 * handle that case.
+	 */
+	nvlist_move_nvlist(vf_schema, DRIVER_CONFIG_NAME, *driver_schema);
+	nvlist_move_nvlist(vf_schema, IOV_CONFIG_NAME, iov_schema);
+	nvlist_move_nvlist(schema, VF_SCHEMA_NAME, vf_schema);
+	*driver_schema = NULL;
+}
+
+static nvlist_t *
+pci_iov_get_pf_subsystem_schema(void)
+{
+	nvlist_t *pf;
+
+	pf = pci_iov_schema_alloc_node();
+	if (pf == NULL)
+		return (NULL);
+
+	pci_iov_schema_add_uint16(pf, "num_vfs", IOV_SCHEMA_REQUIRED, -1);
+	pci_iov_schema_add_string(pf, "device", IOV_SCHEMA_REQUIRED, NULL);
+
+	return (pf);
+}
+
+static nvlist_t *
+pci_iov_get_vf_subsystem_schema(void)
+{
+	nvlist_t *vf;
+
+	vf = pci_iov_schema_alloc_node();
+	if (vf == NULL)
+		return (NULL);
+
+	pci_iov_schema_add_bool(vf, "passthrough", IOV_SCHEMA_HASDEFAULT, 0);
+
+	return (vf);
+}
+
 static int
 pci_iov_alloc_bar(struct pci_devinfo *dinfo, int bar, pci_addr_t bar_shift)
 {
@@ -605,6 +742,50 @@ out:
 	return (error);
 }
 
+static int
+pci_iov_get_schema_ioctl(struct cdev *cdev, struct pci_iov_schema *output)
+{
+	struct pci_devinfo *dinfo;
+	void *packed;
+	size_t output_len, size;
+	int error;
+
+	packed = NULL;
+
+	mtx_lock(&Giant);
+	dinfo = cdev->si_drv1;
+	packed = nvlist_pack(dinfo->cfg.iov->iov_schema, &size);
+	mtx_unlock(&Giant);
+
+	if (packed == NULL) {
+		error = ENOMEM;
+		goto fail;
+	}
+
+	output_len = output->len;
+	output->len = size;
+	if (size <= output_len) {
+		error = copyout(packed, output->schema, size);
+
+		if (error != 0)
+			goto fail;
+
+		output->error = 0;
+	} else
+		/*
+		 * If we return an error then the ioctl code won't copyout
+		 * output back to userland, so we flag the error in the struct
+		 * instead.
+		 */
+		output->error = EMSGSIZE;
+
+	error = 0;
+
+fail:
+	free(packed, M_NVLIST);
+
+	return (error);
+}
 
 static int
 pci_iov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
@@ -616,6 +797,9 @@ pci_iov_ioctl(struct cdev *dev, u_long c
 		return (pci_iov_config(dev, (struct pci_iov_arg *)data));
 	case IOV_DELETE:
 		return (pci_iov_delete(dev));
+	case IOV_GET_SCHEMA:
+		return (pci_iov_get_schema_ioctl(dev,
+		    (struct pci_iov_schema *)data));
 	default:
 		return (EINVAL);
 	}

Modified: head/sys/dev/pci/pci_iov_private.h
==============================================================================
--- head/sys/dev/pci/pci_iov_private.h	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/dev/pci/pci_iov_private.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -38,6 +38,7 @@ struct pci_iov_bar {
 
 struct pcicfg_iov {
 	struct cdev *iov_cdev;
+	nvlist_t *iov_schema;
 
 	struct pci_iov_bar iov_bar[PCIR_MAX_BAR_0 + 1];
 	struct rman rman;

Added: head/sys/dev/pci/pci_iov_schema.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pci/pci_iov_schema.c	Sun Mar  1 00:40:42 2015	(r279451)
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2014-2015 Sandvine Inc.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/queue.h>
+
+#include <machine/stdarg.h>
+
+#include <sys/nv.h>
+#include <sys/iov_schema.h>
+
+#include <dev/pci/schema_private.h>
+
+static const char *pci_iov_schema_valid_types[] = {
+	"bool",
+	"string",
+	"uint8_t",
+	"uint16_t",
+	"uint32_t",
+	"uint64_t",
+	"unicast-mac",
+};
+
+static void
+pci_iov_schema_add_type(nvlist_t *entry, const char *type)
+{
+	int i, error;
+
+	error = EINVAL;
+	for (i = 0; i < nitems(pci_iov_schema_valid_types); i++) {
+		if (strcmp(type, pci_iov_schema_valid_types[i]) == 0) {
+			error = 0;
+			break;
+		}
+	}
+
+	if (error != 0) {
+		nvlist_set_error(entry, error);
+		return;
+	}
+
+	nvlist_add_string(entry, "type", type);
+}
+
+static void
+pci_iov_schema_add_required(nvlist_t *entry, uint32_t flags)
+{
+
+	if (flags & IOV_SCHEMA_REQUIRED) {
+		if (flags & IOV_SCHEMA_HASDEFAULT) {
+			nvlist_set_error(entry, EINVAL);
+			return;
+		}
+
+		nvlist_add_bool(entry, "required", 1);
+	}
+}
+
+void
+pci_iov_schema_add_bool(nvlist_t *schema, const char *name, uint32_t flags,
+    int defaultVal)
+{
+	nvlist_t *entry;
+
+	entry = nvlist_create(NV_FLAG_IGNORE_CASE);
+	if (entry == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	pci_iov_schema_add_type(entry, "bool");
+	if (flags & IOV_SCHEMA_HASDEFAULT)
+		nvlist_add_bool(entry, "default", defaultVal);
+	pci_iov_schema_add_required(entry, flags);
+
+	nvlist_move_nvlist(schema, name, entry);
+}
+
+void
+pci_iov_schema_add_string(nvlist_t *schema, const char *name, uint32_t flags,
+    const char *defaultVal)
+{
+	nvlist_t *entry;
+
+	entry = nvlist_create(NV_FLAG_IGNORE_CASE);
+	if (entry == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	pci_iov_schema_add_type(entry, "string");
+	if (flags & IOV_SCHEMA_HASDEFAULT)
+		nvlist_add_string(entry, "default", defaultVal);
+	pci_iov_schema_add_required(entry, flags);
+
+	nvlist_move_nvlist(schema, name, entry);
+}
+
+static void
+pci_iov_schema_int(nvlist_t *schema, const char *name, const char *type,
+    uint32_t flags, uint64_t defaultVal)
+{
+	nvlist_t *entry;
+
+	entry = nvlist_create(NV_FLAG_IGNORE_CASE);
+	if (entry == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	pci_iov_schema_add_type(entry, type);
+	if (flags & IOV_SCHEMA_HASDEFAULT)
+		nvlist_add_number(entry, "default", defaultVal);
+	pci_iov_schema_add_required(entry, flags);
+
+	nvlist_move_nvlist(schema, name, entry);
+}
+
+void
+pci_iov_schema_add_uint8(nvlist_t *schema, const char *name, uint32_t flags,
+    uint8_t defaultVal)
+{
+
+	pci_iov_schema_int(schema, name, "uint8_t", flags, defaultVal);
+}
+
+void
+pci_iov_schema_add_uint16(nvlist_t *schema, const char *name, uint32_t flags,
+    uint16_t defaultVal)
+{
+
+	pci_iov_schema_int(schema, name, "uint16_t", flags, defaultVal);
+}
+
+void
+pci_iov_schema_add_uint32(nvlist_t *schema, const char *name, uint32_t flags,
+    uint32_t defaultVal)
+{
+
+	pci_iov_schema_int(schema, name, "uint32_t", flags, defaultVal);
+}
+
+void
+pci_iov_schema_add_uint64(nvlist_t *schema, const char *name, uint32_t flags,
+    uint64_t defaultVal)
+{
+
+	pci_iov_schema_int(schema, name, "uint64_t", flags, defaultVal);
+}
+
+void
+pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name,
+    uint32_t flags, const uint8_t * defaultVal)
+{
+	nvlist_t *entry;
+
+	entry = nvlist_create(NV_FLAG_IGNORE_CASE);
+	if (entry == NULL) {
+		nvlist_set_error(schema, ENOMEM);
+		return;
+	}
+
+	pci_iov_schema_add_type(entry, "unicast-mac");
+	if (flags & IOV_SCHEMA_HASDEFAULT)
+		nvlist_add_binary(entry, "default", defaultVal, ETHER_ADDR_LEN);
+	pci_iov_schema_add_required(entry, flags);
+
+	nvlist_move_nvlist(schema, name, entry);
+}
+
+/* Allocate a new empty schema node. */
+nvlist_t *
+pci_iov_schema_alloc_node(void)
+{
+
+	return (nvlist_create(NV_FLAG_IGNORE_CASE));
+}
\ No newline at end of file

Modified: head/sys/dev/pci/pci_private.h
==============================================================================
--- head/sys/dev/pci/pci_private.h	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/dev/pci/pci_private.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -152,7 +152,8 @@ struct resource *pci_alloc_multi_resourc
 		    int type, int *rid, u_long start, u_long end, u_long count,
 		    u_long num, u_int flags);
 
-int		pci_iov_attach_method(device_t bus, device_t dev);
+int		pci_iov_attach_method(device_t bus, device_t dev,
+		    struct nvlist *pf_schema, struct nvlist *vf_schema);
 int		pci_iov_detach_method(device_t bus, device_t dev);
 
 device_t	pci_create_iov_child_method(device_t bus, device_t pf,

Modified: head/sys/dev/pci/pcivar.h
==============================================================================
--- head/sys/dev/pci/pcivar.h	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/dev/pci/pcivar.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -39,6 +39,8 @@
 
 typedef uint64_t pci_addr_t;
 
+struct nvlist;
+
 /* Interesting values for PCI power management */
 struct pcicfg_pp {
     uint16_t	pp_cap;		/* PCI power management capabilities */
@@ -525,9 +527,10 @@ pci_child_added(device_t dev)
 }
 
 static __inline int
-pci_iov_attach(device_t dev)
+pci_iov_attach(device_t dev, struct nvlist *pf_schema, struct nvlist *vf_schema)
 {
-	return (PCI_IOV_ATTACH(device_get_parent(dev), dev));
+	return (PCI_IOV_ATTACH(device_get_parent(dev), dev, pf_schema,
+	    vf_schema));
 }
 
 static __inline int

Added: head/sys/dev/pci/schema_private.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pci/schema_private.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2014 Sandvine Inc.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SCHEMA_PRIVATE_H_
+#define _SCHEMA_PRIVATE_H_
+
+int		pci_iov_schema_validate_config(const nvlist_t *, nvlist_t *);
+uint16_t	pci_iov_config_get_num_vfs(const nvlist_t *);
+
+#endif

Modified: head/sys/sys/iov.h
==============================================================================
--- head/sys/sys/iov.h	Sun Mar  1 00:40:34 2015	(r279450)
+++ head/sys/sys/iov.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -31,14 +31,141 @@
 
 #include <sys/ioccom.h>
 
+#define	PF_CONFIG_NAME		"PF"
+#define	VF_SCHEMA_NAME		"VF"
+
+#define	DRIVER_CONFIG_NAME	"DRIVER"
+#define	IOV_CONFIG_NAME		"IOV"
+
+#define	TYPE_SCHEMA_NAME	"TYPE"
+#define	DEFAULT_SCHEMA_NAME	"DEFAULT"
+#define	REQUIRED_SCHEMA_NAME	"REQUIRED"
+
 struct pci_iov_arg
 {
 	int num_vfs;
 	int passthrough;
 };
 
+/*
+ * Because each PF device is expected to expose a unique set of possible
+ * configurations, the SR-IOV infrastructure dynamically queries the PF
+ * driver for its capabilities.  These capabilities are exposed to userland
+ * with a configuration schema.  The schema is exported from the kernel as a
+ * packed nvlist.  See nv(3) for the details of the nvlist API.  The expected
+ * format of the nvlist is:
+ *
+ * BASIC RULES
+ *   1) All keys are case-insensitive.
+ *   2) No keys that are not specified below may exist at any level of the
+ *      schema.
+ *   3) All keys are mandatory unless explicitly documented as optional.  If a
+ *      key is mandatory then the associated value is also mandatory.
+ *   4) Order of keys is irrelevant.
+ *
+ * TOP LEVEL
+ *   1) There must be a top-level key with the name PF_CONFIG_NAME.  The value
+ *      associated with this key is a nvlist that follows the device schema
+ *      node format.  The parameters in this node specify the configuration
+ *      parameters that may be applied to a PF.
+ *   2) There must be a top-level key with the name VF_SCHEMA_NAME.  The value
+ *      associated with this key is a nvlist that follows the device schema
+ *      node format.  The parameters in this node specify the configuration
+ *      parameters that may be applied to a VF.
+ *
+ * DEVICE SCHEMA NODE
+ *   1) There must be a key with the name DRIVER_CONFIG_NAME.  The value
+ *      associated with this key is a nvlist that follows the device/subsystem
+ *      schema node format.  The parameters in this node specify the
+ *      configuration parameters that are specific to a particular device
+ *      driver.
+ *   2) There must be a key with the name IOV_CONFIG_NAME.  The value associated
+ *      with this key is an nvlist that follows the device/subsystem schema node
+ *      format.  The parameters in this node specify the configuration
+ *      parameters that are applied by the SR-IOV infrastructure.
+ *
+ * DEVICE/SUBSYSTEM SCHEMA NODE
+ *   1) All keys in the device/subsystem schema node are optional.
+ *   2) Each key specifies the name of a valid configuration parameter that may
+ *      be applied to the device/subsystem combination specified by this node.
+ *      The value associated with the key specifies the format of valid
+ *      configuration values, and must be a nvlist in parameter schema node
+ *      format.
+ *
+ * PARAMETER SCHEMA NODE
+ *   1) The parameter schema node must contain a key with the name
+ *      TYPE_SCHEMA_NAME.  The value associated with this key must be a string.
+ *      This string specifies the type of value that the parameter specified by
+ *      this node must take.  The string must have one of the following values:
+ *         - "bool"     - The configuration value must be a boolean.
+ *         - "mac-addr" - The configuration value must be a binary value.  In
+ *                         addition, the value must be exactly 6 bytes long and
+ *                         the value must not be a multicast or broadcast mac.
+ *         - "uint8_t"  - The configuration value must be a integer value in
+ *                         the range [0, UINT8_MAX].
+ *         - "uint16_t" - The configuration value must be a integer value in
+ *                         the range [0, UINT16_MAX].
+ *         - "uint32_t" - The configuration value must be a integer value in
+ *                         the range [0, UINT32_MAX].
+ *         - "uint64_t" - The configuration value must be a integer value in
+ *                         the range [0, UINT64_MAX].
+ *  2) The parameter schema may contain a key with the name
+ *     REQUIRED_SCHEMA_NAME.  This key is optional.  If this key is present, the
+ *     value associated with it must have a boolean type.  If the value is true,
+ *     then the parameter specified by this schema is a required parameter.  All
+ *     valid configurations must include all required parameters.
+ *  3) The parameter schema may contain a key with the name DEFAULT_SCHEMA_NAME.
+ *     This key is optional.  This key must not be present if the parameter
+ *     specified by this schema is required.  If this key is present, the value
+ *     associated with the parent key must follow all restrictions specified by
+ *     the type specified by this schema.  If a configuration does not supply a
+ *     value for the parameter specified by this schema, then the kernel will
+ *     apply the value associated with this key in its place.
+ *
+ * The following is an example of a valid schema, as printed by nvlist_dump.
+ * Keys are printed followed by the type of the value in parantheses.  The
+ * value is displayed following a colon.  The indentation level reflects the
+ * level of nesting of nvlists.  String values are displayed between []
+ * brackets.  Binary values are shown with the length of the binary value (in
+ * bytes) followed by the actual binary values.
+ *
+ *  PF (NVLIST):
+ *      IOV (NVLIST):
+ *          num_vfs (NVLIST):
+ *              type (STRING): [uint16_t]
+ *              required (BOOL): TRUE
+ *          device (NVLIST):
+ *              type (STRING): [string]
+ *              required (BOOL): TRUE
+ *      DRIVER (NVLIST):
+ *  VF (NVLIST):
+ *      IOV (NVLIST):
+ *          passthrough (NVLIST):
+ *              type (STRING): [bool]
+ *              default (BOOL): FALSE
+ *      DRIVER (NVLIST):
+ *          mac-addr (NVLIST):
+ *              type (STRING): [mac-addr]
+ *              default (BINARY): 6 000000000000
+ *          vlan (NVLIST):
+ *               type (STRING): [uint16_t]
+ *          spoof-check (NVLIST):
+ *              type (STRING): [bool]
+ *              default (BOOL): TRUE
+ *          allow-set-mac (NVLIST):
+ *              type (STRING): [bool]
+ *              default (BOOL): FALSE
+ */
+struct pci_iov_schema
+{
+	void *schema;
+	size_t len;
+	int error;
+};
+
 #define	IOV_CONFIG	_IOWR('p', 10, struct pci_iov_arg)
 #define	IOV_DELETE	_IO('p', 11)
+#define	IOV_GET_SCHEMA	_IOWR('p', 12, struct pci_iov_schema)
 
 #endif
 

Added: head/sys/sys/iov_schema.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/sys/iov_schema.h	Sun Mar  1 00:40:42 2015	(r279451)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2014-2015 Sandvine Inc.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_IOV_SCHEMA_H_
+#define _SYS_IOV_SCHEMA_H_
+
+#define	IOV_SCHEMA_HASDEFAULT	(1 << 0)
+#define	IOV_SCHEMA_REQUIRED	(1 << 1)
+
+nvlist_t	*pci_iov_schema_alloc_node(void);
+
+void	pci_iov_schema_add_bool(nvlist_t *schema, const char *name,
+	    uint32_t flags,  int defaultVal);
+void	pci_iov_schema_add_string(nvlist_t *schema, const char *name,
+	    uint32_t flags, const char *defaultVal);
+void	pci_iov_schema_add_uint8(nvlist_t *schema, const char *name,
+	    uint32_t flags, uint8_t defaultVal);
+void	pci_iov_schema_add_uint16(nvlist_t *schema, const char *name,
+	    uint32_t flags, uint16_t defaultVal);
+void	pci_iov_schema_add_uint32(nvlist_t *schema, const char *name,
+	    uint32_t flags, uint32_t defaultVal);
+void	pci_iov_schema_add_uint64(nvlist_t *schema, const char *name,
+	    uint32_t flags, uint64_t defaultVal);
+void	pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name,
+	    uint32_t flags, const uint8_t * defaultVal);
+
+#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503010040.t210eg5X093140>