From 5ec4a5181424a4d6f4209a2d27fd70808b33b790 Mon Sep 17 00:00:00 2001 From: cem Date: Tue, 4 Jun 2019 02:34:59 +0000 Subject: [PATCH] virtio(4): Expose PNP metadata through newbus Expose the same fields and widths from both vtio buses, even though they don't quite line up; several virtio drivers can attach to both buses, and sharing a PNP info table for both seems more convenient. In practice, I doubt any virtio driver really needs to match on anything other than bus and device_type (eliminating the unused entries for vtmmio), and also in practice device_type is << 2^16 (so far, values range from 1 to 20). So it might be fine to only expose a 16-bit device_type for PNP purposes. On the other hand, I don't see much harm in overkill here. Reviewed by: bryanv, markj (earlier version) Differential Revision: https://reviews.freebsd.org/D20406 --- sys/dev/virtio/mmio/virtio_mmio.c | 9 +++++++++ sys/dev/virtio/pci/virtio_pci.c | 1 + sys/dev/virtio/virtio.c | 24 ++++++++++++++++++++++++ sys/dev/virtio/virtio.h | 2 ++ 4 files changed, 36 insertions(+) diff --git a/sys/dev/virtio/mmio/virtio_mmio.c b/sys/dev/virtio/mmio/virtio_mmio.c index 48b046e32e2f..0b3168d3f1f7 100644 --- a/sys/dev/virtio/mmio/virtio_mmio.c +++ b/sys/dev/virtio/mmio/virtio_mmio.c @@ -145,6 +145,7 @@ static device_method_t vtmmio_methods[] = { /* Bus interface. */ DEVMETHOD(bus_driver_added, vtmmio_driver_added), DEVMETHOD(bus_child_detached, vtmmio_child_detached), + DEVMETHOD(bus_child_pnpinfo_str, virtio_child_pnpinfo_str), DEVMETHOD(bus_read_ivar, vtmmio_read_ivar), DEVMETHOD(bus_write_ivar, vtmmio_write_ivar), @@ -332,6 +333,14 @@ vtmmio_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) case VIRTIO_IVAR_VENDOR: *result = vtmmio_read_config_4(sc, VIRTIO_MMIO_VENDOR_ID); break; + case VIRTIO_IVAR_SUBVENDOR: + case VIRTIO_IVAR_DEVICE: + /* + * Dummy value for fields not present in this bus. Used by + * bus-agnostic virtio_child_pnpinfo_str. + */ + *result = 0; + break; default: return (ENOENT); } diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index e23b961f0f9d..a203b09178c6 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -200,6 +200,7 @@ static device_method_t vtpci_methods[] = { /* Bus interface. */ DEVMETHOD(bus_driver_added, vtpci_driver_added), DEVMETHOD(bus_child_detached, vtpci_child_detached), + DEVMETHOD(bus_child_pnpinfo_str, virtio_child_pnpinfo_str), DEVMETHOD(bus_read_ivar, vtpci_read_ivar), DEVMETHOD(bus_write_ivar, vtpci_write_ivar), diff --git a/sys/dev/virtio/virtio.c b/sys/dev/virtio/virtio.c index 131c4c7d954d..30230a506028 100644 --- a/sys/dev/virtio/virtio.c +++ b/sys/dev/virtio/virtio.c @@ -263,6 +263,30 @@ virtio_write_device_config(device_t dev, bus_size_t offset, void *dst, int len) offset, dst, len); } +int +virtio_child_pnpinfo_str(device_t busdev __unused, device_t child, char *buf, + size_t buflen) +{ + + /* + * All of these PCI fields will be only 16 bits, but on the vtmmio bus + * the corresponding fields (only "vendor" and "device_type") are 32 + * bits. Many virtio drivers can attach below either bus. + * Gratuitously expand these two fields to 32-bits to allow sharing PNP + * match table data between the mostly-similar buses. + * + * Subdevice and device_type are redundant in both buses, so I don't + * see a lot of PNP utility in exposing the same value under a + * different name. + */ + snprintf(buf, buflen, "vendor=0x%08x device=0x%04x subvendor=0x%04x " + "device_type=0x%08x", (unsigned)virtio_get_vendor(child), + (unsigned)virtio_get_device(child), + (unsigned)virtio_get_subvendor(child), + (unsigned)virtio_get_device_type(child)); + return (0); +} + static int virtio_modevent(module_t mod, int type, void *unused) { diff --git a/sys/dev/virtio/virtio.h b/sys/dev/virtio/virtio.h index 15e598a11d16..eac449ad3c4e 100644 --- a/sys/dev/virtio/virtio.h +++ b/sys/dev/virtio/virtio.h @@ -81,6 +81,8 @@ void virtio_stop(device_t dev); int virtio_config_generation(device_t dev); int virtio_reinit(device_t dev, uint64_t features); void virtio_reinit_complete(device_t dev); +int virtio_child_pnpinfo_str(device_t busdev, device_t child, char *buf, + size_t buflen); /* * Read/write a variable amount from the device specific (ie, network)