Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/virtio/pci/virtio_pci.c
Show All 27 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/sbuf.h> | |||||
#include <sys/sysctl.h> | |||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
Show All 36 Lines | |||||
static int vtpci_reinit_virtqueue(struct vtpci_common *, int); | static int vtpci_reinit_virtqueue(struct vtpci_common *, int); | ||||
static void vtpci_intx_intr(void *); | static void vtpci_intx_intr(void *); | ||||
static int vtpci_vq_shared_intr_filter(void *); | static int vtpci_vq_shared_intr_filter(void *); | ||||
static void vtpci_vq_shared_intr(void *); | static void vtpci_vq_shared_intr(void *); | ||||
static int vtpci_vq_intr_filter(void *); | static int vtpci_vq_intr_filter(void *); | ||||
static void vtpci_vq_intr(void *); | static void vtpci_vq_intr(void *); | ||||
static void vtpci_config_intr(void *); | static void vtpci_config_intr(void *); | ||||
static void vtpci_setup_sysctl(struct vtpci_common *); | |||||
#define vtpci_setup_msi_interrupt vtpci_setup_intx_interrupt | #define vtpci_setup_msi_interrupt vtpci_setup_intx_interrupt | ||||
/* | /* | ||||
* This module contains two drivers: | * This module contains two drivers: | ||||
* - virtio_pci_legacy for pre-V1 support | * - virtio_pci_legacy for pre-V1 support | ||||
* - virtio_pci_modern for V1 support | * - virtio_pci_modern for V1 support | ||||
*/ | */ | ||||
MODULE_VERSION(virtio_pci, 1); | MODULE_VERSION(virtio_pci, 1); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | vtpci_init(struct vtpci_common *cn, device_t dev, bool modern) | ||||
pci_enable_busmaster(dev); | pci_enable_busmaster(dev); | ||||
if (modern) | if (modern) | ||||
cn->vtpci_flags |= VTPCI_FLAG_MODERN; | cn->vtpci_flags |= VTPCI_FLAG_MODERN; | ||||
if (pci_find_cap(dev, PCIY_MSI, NULL) != 0) | if (pci_find_cap(dev, PCIY_MSI, NULL) != 0) | ||||
cn->vtpci_flags |= VTPCI_FLAG_NO_MSI; | cn->vtpci_flags |= VTPCI_FLAG_NO_MSI; | ||||
if (pci_find_cap(dev, PCIY_MSIX, NULL) != 0) | if (pci_find_cap(dev, PCIY_MSIX, NULL) != 0) | ||||
cn->vtpci_flags |= VTPCI_FLAG_NO_MSIX; | cn->vtpci_flags |= VTPCI_FLAG_NO_MSIX; | ||||
vtpci_setup_sysctl(cn); | |||||
} | } | ||||
int | int | ||||
vtpci_add_child(struct vtpci_common *cn) | vtpci_add_child(struct vtpci_common *cn) | ||||
{ | { | ||||
device_t dev, child; | device_t dev, child; | ||||
dev = cn->vtpci_dev; | dev = cn->vtpci_dev; | ||||
Show All 30 Lines | |||||
void | void | ||||
vtpci_child_detached(struct vtpci_common *cn) | vtpci_child_detached(struct vtpci_common *cn) | ||||
{ | { | ||||
vtpci_release_child_resources(cn); | vtpci_release_child_resources(cn); | ||||
cn->vtpci_child_feat_desc = NULL; | cn->vtpci_child_feat_desc = NULL; | ||||
cn->vtpci_host_features = 0; | |||||
cn->vtpci_features = 0; | cn->vtpci_features = 0; | ||||
} | } | ||||
int | int | ||||
vtpci_reinit(struct vtpci_common *cn) | vtpci_reinit(struct vtpci_common *cn) | ||||
{ | { | ||||
int idx, error; | int idx, error; | ||||
Show All 28 Lines | |||||
} | } | ||||
uint64_t | uint64_t | ||||
vtpci_negotiate_features(struct vtpci_common *cn, | vtpci_negotiate_features(struct vtpci_common *cn, | ||||
uint64_t child_features, uint64_t host_features) | uint64_t child_features, uint64_t host_features) | ||||
{ | { | ||||
uint64_t features; | uint64_t features; | ||||
cn->vtpci_host_features = host_features; | |||||
vtpci_describe_features(cn, "host", host_features); | vtpci_describe_features(cn, "host", host_features); | ||||
/* | /* | ||||
* Limit negotiated features to what the driver, virtqueue, and | * Limit negotiated features to what the driver, virtqueue, and | ||||
* host all support. | * host all support. | ||||
*/ | */ | ||||
features = host_features & child_features; | features = host_features & child_features; | ||||
features = virtio_filter_transport_features(features); | features = virtio_filter_transport_features(features); | ||||
vtpci_describe_features(cn, "negotiated", features); | |||||
cn->vtpci_features = features; | cn->vtpci_features = features; | ||||
vtpci_describe_features(cn, "negotiated", features); | |||||
return (features); | return (features); | ||||
} | } | ||||
int | int | ||||
vtpci_with_feature(struct vtpci_common *cn, uint64_t feature) | vtpci_with_feature(struct vtpci_common *cn, uint64_t feature) | ||||
{ | { | ||||
return ((cn->vtpci_features & feature) != 0); | return ((cn->vtpci_features & feature) != 0); | ||||
▲ Show 20 Lines • Show All 656 Lines • ▼ Show 20 Lines | vtpci_config_intr(void *xcn) | ||||
struct vtpci_common *cn; | struct vtpci_common *cn; | ||||
device_t child; | device_t child; | ||||
cn = xcn; | cn = xcn; | ||||
child = cn->vtpci_child_dev; | child = cn->vtpci_child_dev; | ||||
if (child != NULL) | if (child != NULL) | ||||
VIRTIO_CONFIG_CHANGE(child); | VIRTIO_CONFIG_CHANGE(child); | ||||
} | |||||
static int | |||||
vtpci_feature_sysctl(struct sysctl_req *req, struct vtpci_common *cn, | |||||
uint64_t features) | |||||
{ | |||||
struct sbuf *sb; | |||||
int error; | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); | |||||
if (sb == NULL) | |||||
return (ENOMEM); | |||||
error = virtio_describe_sbuf(sb, features, cn->vtpci_child_feat_desc); | |||||
sbuf_delete(sb); | |||||
return (error); | |||||
} | |||||
static int | |||||
vtpci_host_features_sysctl(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct vtpci_common *cn; | |||||
cn = arg1; | |||||
return (vtpci_feature_sysctl(req, cn, cn->vtpci_host_features)); | |||||
} | |||||
static int | |||||
vtpci_negotiated_features_sysctl(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct vtpci_common *cn; | |||||
cn = arg1; | |||||
return (vtpci_feature_sysctl(req, cn, cn->vtpci_features)); | |||||
} | |||||
static void | |||||
vtpci_setup_sysctl(struct vtpci_common *cn) | |||||
{ | |||||
device_t dev; | |||||
struct sysctl_ctx_list *ctx; | |||||
struct sysctl_oid *tree; | |||||
struct sysctl_oid_list *child; | |||||
dev = cn->vtpci_dev; | |||||
ctx = device_get_sysctl_ctx(dev); | |||||
tree = device_get_sysctl_tree(dev); | |||||
child = SYSCTL_CHILDREN(tree); | |||||
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "nvqs", | |||||
CTLFLAG_RD, &cn->vtpci_nvqs, 0, "Number of virtqueues"); | |||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "host_features", | |||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, cn, 0, | |||||
vtpci_host_features_sysctl, "A", "Features supported by the host"); | |||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "negotiated_features", | |||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, cn, 0, | |||||
vtpci_negotiated_features_sysctl, "A", "Features negotiated"); | |||||
} | } |