summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus/vmbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hyperv/vmbus/vmbus.c')
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c120
1 files changed, 45 insertions, 75 deletions
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 350e120..cd0fd24 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -1040,113 +1040,73 @@ vmbus_intr_teardown(struct vmbus_softc *sc)
static int
vmbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
{
- struct hv_device *child_dev_ctx = device_get_ivars(child);
-
- switch (index) {
- case HV_VMBUS_IVAR_TYPE:
- *result = (uintptr_t)&child_dev_ctx->class_id;
- return (0);
-
- case HV_VMBUS_IVAR_INSTANCE:
- *result = (uintptr_t)&child_dev_ctx->device_id;
- return (0);
-
- case HV_VMBUS_IVAR_DEVCTX:
- *result = (uintptr_t)child_dev_ctx;
- return (0);
-
- case HV_VMBUS_IVAR_NODE:
- *result = (uintptr_t)child_dev_ctx->device;
- return (0);
- }
- return (ENOENT);
-}
-
-static int
-vmbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
-{
- switch (index) {
- case HV_VMBUS_IVAR_TYPE:
- case HV_VMBUS_IVAR_INSTANCE:
- case HV_VMBUS_IVAR_DEVCTX:
- case HV_VMBUS_IVAR_NODE:
- /* read-only */
- return (EINVAL);
- }
return (ENOENT);
}
static int
vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
{
- struct hv_device *dev_ctx = device_get_ivars(child);
+ const struct hv_vmbus_channel *chan;
char guidbuf[HYPERV_GUID_STRLEN];
- if (dev_ctx == NULL)
+ chan = vmbus_get_channel(child);
+ if (chan == NULL) {
+ /* Event timer device, which does not belong to a channel */
return (0);
+ }
strlcat(buf, "classid=", buflen);
- hyperv_guid2str(&dev_ctx->class_id, guidbuf, sizeof(guidbuf));
+ hyperv_guid2str(&chan->ch_guid_type, guidbuf, sizeof(guidbuf));
strlcat(buf, guidbuf, buflen);
strlcat(buf, " deviceid=", buflen);
- hyperv_guid2str(&dev_ctx->device_id, guidbuf, sizeof(guidbuf));
+ hyperv_guid2str(&chan->ch_guid_inst, guidbuf, sizeof(guidbuf));
strlcat(buf, guidbuf, buflen);
return (0);
}
-struct hv_device *
-hv_vmbus_child_device_create(struct hv_vmbus_channel *channel)
-{
- hv_device *child_dev;
-
- /*
- * Allocate the new child device
- */
- child_dev = malloc(sizeof(hv_device), M_DEVBUF, M_WAITOK | M_ZERO);
-
- child_dev->channel = channel;
- child_dev->class_id = channel->ch_guid_type;
- child_dev->device_id = channel->ch_guid_inst;
-
- return (child_dev);
-}
-
-void
-hv_vmbus_child_device_register(struct vmbus_softc *sc,
- struct hv_device *child_dev)
+int
+hv_vmbus_child_device_register(struct hv_vmbus_channel *chan)
{
- device_t child, parent;
-
- parent = sc->vmbus_dev;
- if (bootverbose) {
- char name[HYPERV_GUID_STRLEN];
-
- hyperv_guid2str(&child_dev->class_id, name, sizeof(name));
- device_printf(parent, "add device, classid: %s\n", name);
+ struct vmbus_softc *sc = chan->vmbus_sc;
+ device_t parent = sc->vmbus_dev;
+ int error = 0;
+
+ chan->ch_dev = device_add_child(parent, NULL, -1);
+ if (chan->ch_dev == NULL) {
+ device_printf(parent, "device_add_child for chan%u failed\n",
+ chan->ch_id);
+ error = ENXIO;
+ goto done;
}
+ device_set_ivars(chan->ch_dev, chan);
- child = device_add_child(parent, NULL, -1);
- child_dev->device = child;
- device_set_ivars(child, child_dev);
-
- /* New device was added to vmbus */
+done:
+ /* New device has been/should be added to vmbus. */
vmbus_scan_newdev(sc);
+ return error;
}
int
-hv_vmbus_child_device_unregister(struct hv_device *child_dev)
+hv_vmbus_child_device_unregister(struct hv_vmbus_channel *chan)
{
- int ret = 0;
+ int error;
+
+ if (chan->ch_dev == NULL) {
+ /* Failed to add a device. */
+ return 0;
+ }
+
/*
* XXXKYS: Ensure that this is the opposite of
* device_add_child()
*/
mtx_lock(&Giant);
- ret = device_delete_child(vmbus_get_device(), child_dev->device);
+ error = device_delete_child(chan->vmbus_sc->vmbus_dev, chan->ch_dev);
mtx_unlock(&Giant);
- return(ret);
+
+ return error;
}
static int
@@ -1170,6 +1130,16 @@ vmbus_get_version_method(device_t bus, device_t dev)
}
static int
+vmbus_probe_guid_method(device_t bus, device_t dev, const struct hv_guid *guid)
+{
+ const struct hv_vmbus_channel *chan = vmbus_get_channel(dev);
+
+ if (memcmp(&chan->ch_guid_type, guid, sizeof(struct hv_guid)) == 0)
+ return 0;
+ return ENXIO;
+}
+
+static int
vmbus_probe(device_t dev)
{
char *id[] = { "VMBUS", NULL };
@@ -1376,11 +1346,11 @@ static device_method_t vmbus_methods[] = {
DEVMETHOD(bus_add_child, bus_generic_add_child),
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, vmbus_read_ivar),
- DEVMETHOD(bus_write_ivar, vmbus_write_ivar),
DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str),
/* Vmbus interface */
DEVMETHOD(vmbus_get_version, vmbus_get_version_method),
+ DEVMETHOD(vmbus_probe_guid, vmbus_probe_guid_method),
DEVMETHOD_END
};
OpenPOWER on IntegriCloud