virtio_pci: Add sysctl to show current features
Reviewed by: grehan (mentor) Differential Revision: https://reviews.freebsd.org/D27898
This commit is contained in:
parent
fbe0c4f4c7
commit
703f17d60f
@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
@ -85,6 +87,8 @@ static int vtpci_vq_intr_filter(void *);
|
||||
static void vtpci_vq_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
|
||||
|
||||
/*
|
||||
@ -156,6 +160,8 @@ vtpci_init(struct vtpci_common *cn, device_t dev, bool modern)
|
||||
cn->vtpci_flags |= VTPCI_FLAG_NO_MSI;
|
||||
if (pci_find_cap(dev, PCIY_MSIX, NULL) != 0)
|
||||
cn->vtpci_flags |= VTPCI_FLAG_NO_MSIX;
|
||||
|
||||
vtpci_setup_sysctl(cn);
|
||||
}
|
||||
|
||||
int
|
||||
@ -202,6 +208,7 @@ vtpci_child_detached(struct vtpci_common *cn)
|
||||
vtpci_release_child_resources(cn);
|
||||
|
||||
cn->vtpci_child_feat_desc = NULL;
|
||||
cn->vtpci_host_features = 0;
|
||||
cn->vtpci_features = 0;
|
||||
}
|
||||
|
||||
@ -246,6 +253,7 @@ vtpci_negotiate_features(struct vtpci_common *cn,
|
||||
{
|
||||
uint64_t features;
|
||||
|
||||
cn->vtpci_host_features = host_features;
|
||||
vtpci_describe_features(cn, "host", host_features);
|
||||
|
||||
/*
|
||||
@ -254,9 +262,9 @@ vtpci_negotiate_features(struct vtpci_common *cn,
|
||||
*/
|
||||
features = host_features & child_features;
|
||||
features = virtio_filter_transport_features(features);
|
||||
vtpci_describe_features(cn, "negotiated", features);
|
||||
|
||||
cn->vtpci_features = features;
|
||||
vtpci_describe_features(cn, "negotiated", features);
|
||||
|
||||
return (features);
|
||||
}
|
||||
@ -930,3 +938,64 @@ vtpci_config_intr(void *xcn)
|
||||
if (child != NULL)
|
||||
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");
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ struct vtpci_virtqueue {
|
||||
|
||||
struct vtpci_common {
|
||||
device_t vtpci_dev;
|
||||
uint64_t vtpci_host_features;
|
||||
uint64_t vtpci_features;
|
||||
struct vtpci_virtqueue *vtpci_vqs;
|
||||
int vtpci_nvqs;
|
||||
|
@ -119,24 +119,15 @@ virtio_feature_name(uint64_t val, struct virtio_feature_desc *desc)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
virtio_describe(device_t dev, const char *msg,
|
||||
uint64_t features, struct virtio_feature_desc *desc)
|
||||
int
|
||||
virtio_describe_sbuf(struct sbuf *sb, uint64_t features,
|
||||
struct virtio_feature_desc *desc)
|
||||
{
|
||||
struct sbuf sb;
|
||||
uint64_t val;
|
||||
char *buf;
|
||||
const char *name;
|
||||
uint64_t val;
|
||||
int n;
|
||||
|
||||
if ((buf = malloc(1024, M_TEMP, M_NOWAIT)) == NULL) {
|
||||
device_printf(dev, "%s features: %#jx\n",
|
||||
msg, (uintmax_t) features);
|
||||
return;
|
||||
}
|
||||
|
||||
sbuf_new(&sb, buf, 1024, SBUF_FIXEDLEN);
|
||||
sbuf_printf(&sb, "%s features: %#jx", msg, (uintmax_t) features);
|
||||
sbuf_printf(sb, "%#jx", (uintmax_t) features);
|
||||
|
||||
for (n = 0, val = 1ULL << 63; val != 0; val >>= 1) {
|
||||
/*
|
||||
@ -147,25 +138,51 @@ virtio_describe(device_t dev, const char *msg,
|
||||
continue;
|
||||
|
||||
if (n++ == 0)
|
||||
sbuf_cat(&sb, " <");
|
||||
sbuf_cat(sb, " <");
|
||||
else
|
||||
sbuf_cat(&sb, ",");
|
||||
sbuf_cat(sb, ",");
|
||||
|
||||
name = virtio_feature_name(val, desc);
|
||||
if (name == NULL)
|
||||
sbuf_printf(&sb, "%#jx", (uintmax_t) val);
|
||||
sbuf_printf(sb, "%#jx", (uintmax_t) val);
|
||||
else
|
||||
sbuf_cat(&sb, name);
|
||||
sbuf_cat(sb, name);
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
sbuf_cat(&sb, ">");
|
||||
sbuf_cat(sb, ">");
|
||||
|
||||
if (sbuf_finish(&sb) == 0)
|
||||
return (sbuf_finish(sb));
|
||||
}
|
||||
|
||||
void
|
||||
virtio_describe(device_t dev, const char *msg, uint64_t features,
|
||||
struct virtio_feature_desc *desc)
|
||||
{
|
||||
struct sbuf sb;
|
||||
char *buf;
|
||||
int error;
|
||||
|
||||
if ((buf = malloc(1024, M_TEMP, M_NOWAIT)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sbuf_new(&sb, buf, 1024, SBUF_FIXEDLEN);
|
||||
sbuf_printf(&sb, "%s features: ", msg);
|
||||
|
||||
error = virtio_describe_sbuf(&sb, features, desc);
|
||||
if (error == 0)
|
||||
device_printf(dev, "%s\n", sbuf_data(&sb));
|
||||
|
||||
sbuf_delete(&sb);
|
||||
free(buf, M_TEMP);
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
device_printf(dev, "%s features: %#jx\n", msg,
|
||||
(uintmax_t) features);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <dev/virtio/virtio_ids.h>
|
||||
#include <dev/virtio/virtio_config.h>
|
||||
|
||||
struct sbuf;
|
||||
struct vq_alloc_info;
|
||||
|
||||
/*
|
||||
@ -82,7 +83,9 @@ struct virtio_pnp_match {
|
||||
|
||||
const char *virtio_device_name(uint16_t devid);
|
||||
void virtio_describe(device_t dev, const char *msg,
|
||||
uint64_t features, struct virtio_feature_desc *feature_desc);
|
||||
uint64_t features, struct virtio_feature_desc *desc);
|
||||
int virtio_describe_sbuf(struct sbuf *sb, uint64_t features,
|
||||
struct virtio_feature_desc *desc);
|
||||
uint64_t virtio_filter_transport_features(uint64_t features);
|
||||
int virtio_bus_is_modern(device_t dev);
|
||||
void virtio_read_device_config_array(device_t dev, bus_size_t offset,
|
||||
|
Loading…
Reference in New Issue
Block a user