/* * Net VSC on device remove */ int hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel) { hn_softc_t *sc = device_get_softc(device->device); netvsc_dev *net_dev = sc->net_dev;; /* Stop outbound traffic ie sends and receives completions */ net_dev->destroy = TRUE; hv_nv_disconnect_from_vsp(net_dev); /* At this point, no one should be accessing net_dev except in here */ /* Now, we can close the channel safely */ if (!destroy_channel) { device->channel->state = HV_CHANNEL_CLOSING_NONDESTRUCTIVE_STATE; } free(device->channel->hv_chan_rdbuf, M_NETVSC); hv_vmbus_channel_close(device->channel); sema_destroy(&net_dev->channel_init_sema); free(net_dev, M_NETVSC); return (0); }
/* * Net VSC on device add * * Callback when the device belonging to this driver is added */ netvsc_dev * hv_nv_on_device_add(struct hv_device *device, void *additional_info) { struct hv_vmbus_channel *chan = device->channel; netvsc_dev *net_dev; int ret = 0; net_dev = hv_nv_alloc_net_device(device); if (net_dev == NULL) return NULL; /* Initialize the NetVSC channel extension */ sema_init(&net_dev->channel_init_sema, 0, "netdev_sema"); chan->hv_chan_rdbuf = malloc(NETVSC_PACKET_SIZE, M_NETVSC, M_WAITOK); /* * Open the channel */ ret = hv_vmbus_channel_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hv_nv_on_channel_callback, chan); if (ret != 0) { free(chan->hv_chan_rdbuf, M_NETVSC); goto cleanup; } /* * Connect with the NetVsp */ ret = hv_nv_connect_to_vsp(device); if (ret != 0) goto close; return (net_dev); close: /* Now, we can close the channel safely */ free(chan->hv_chan_rdbuf, M_NETVSC); hv_vmbus_channel_close(chan); cleanup: /* * Free the packet buffers on the netvsc device packet queue. * Release other resources. */ if (net_dev) { sema_destroy(&net_dev->channel_init_sema); free(net_dev, M_NETVSC); } return (NULL); }
static int hv_kvp_detach(device_t dev) { struct hv_device* hv_dev; #ifdef DEBUG printf("hv_kvp_detach: called\n"); #endif hv_dev = vmbus_get_devctx(dev); if (kvp_hv_dev != hv_dev) printf("hv_kvp_detach: Closing an INVALID kvp device\n"); hv_vmbus_channel_close(hv_dev->channel); kvp_hv_dev = NULL; return (0); }
static int hv_util_detach(device_t dev) { struct hv_device* hv_dev; struct hv_vmbus_service* service; size_t receive_buffer_offset; hv_dev = vmbus_get_devctx(dev); hv_vmbus_channel_close(hv_dev->channel); service = device_get_softc(dev); receive_buffer_offset = service - &service_table[0]; if (service->work_queue != NULL) hv_work_queue_close(service->work_queue); free(receive_buffer[receive_buffer_offset], M_DEVBUF); receive_buffer[receive_buffer_offset] = NULL; return (0); }