|
@@ -685,6 +685,7 @@ destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
|
|
|
struct bus_info *bus;
|
|
|
struct device_info *dev;
|
|
|
struct guest_msgs cmd;
|
|
|
+ int retval = CONTROLVM_RESP_SUCCESS;
|
|
|
|
|
|
busNo = msg->cmd.destroyDevice.busNo;
|
|
|
devNo = msg->cmd.destroyDevice.devNo;
|
|
@@ -696,63 +697,18 @@ destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
|
|
|
/* make sure the device number is valid */
|
|
|
if (devNo >= bus->deviceCount) {
|
|
|
LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).",
|
|
|
- devNo, bus->deviceCount);
|
|
|
- read_unlock(&BusListLock);
|
|
|
- return CONTROLVM_RESP_ERROR_DEVICE_INVALID;
|
|
|
- }
|
|
|
- /* make sure this device exists */
|
|
|
- dev = bus->device[devNo];
|
|
|
- if (!dev) {
|
|
|
- LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
|
|
|
- devNo);
|
|
|
- read_unlock(&BusListLock);
|
|
|
- return CONTROLVM_RESP_ERROR_ALREADY_DONE;
|
|
|
- }
|
|
|
- read_unlock(&BusListLock);
|
|
|
- /* the msg is bound for virtpci; send
|
|
|
- * guest_msgs struct to callback
|
|
|
- */
|
|
|
- if (!uuid_le_cmp(dev->channelTypeGuid,
|
|
|
- UltraVhbaChannelProtocolGuid)) {
|
|
|
- cmd.msgtype = GUEST_DEL_VHBA;
|
|
|
- cmd.del_vhba.chanptr = dev->chanptr;
|
|
|
- } else
|
|
|
- if (!uuid_le_cmp(dev->channelTypeGuid,
|
|
|
- UltraVnicChannelProtocolGuid)) {
|
|
|
- cmd.msgtype = GUEST_DEL_VNIC;
|
|
|
- cmd.del_vnic.chanptr = dev->chanptr;
|
|
|
+ devNo, bus->deviceCount);
|
|
|
+ retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
|
|
|
} else {
|
|
|
- LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
|
|
|
- return
|
|
|
- CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
|
|
|
- }
|
|
|
-
|
|
|
- if (!VirtControlChanFunc) {
|
|
|
- LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
|
|
|
- return
|
|
|
- CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
|
|
|
- }
|
|
|
-
|
|
|
- if (!VirtControlChanFunc(&cmd)) {
|
|
|
- LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
|
|
|
- return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
|
|
|
- }
|
|
|
-/* you must disable channel interrupts BEFORE you unmap the channel,
|
|
|
- * because if you unmap first, there may still be some activity going
|
|
|
- * on which accesses the channel and you will get a "unable to handle
|
|
|
- * kernel paging request"
|
|
|
- */
|
|
|
- if (dev->polling) {
|
|
|
- LOGINF("calling uislib_disable_channel_interrupts");
|
|
|
- uislib_disable_channel_interrupts(busNo, devNo);
|
|
|
- }
|
|
|
- /* unmap the channel memory for the device. */
|
|
|
- if (!msg->hdr.Flags.testMessage) {
|
|
|
- LOGINF("destroy_device, doing iounmap");
|
|
|
- uislib_iounmap(dev->chanptr);
|
|
|
+ /* make sure this device exists */
|
|
|
+ dev = bus->device[devNo];
|
|
|
+ if (!dev) {
|
|
|
+ LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.",
|
|
|
+ devNo);
|
|
|
+ retval =
|
|
|
+ CONTROLVM_RESP_ERROR_ALREADY_DONE;
|
|
|
+ }
|
|
|
}
|
|
|
- kfree(dev);
|
|
|
- bus->device[devNo] = NULL;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -760,11 +716,54 @@ destroy_device(CONTROLVM_MESSAGE *msg, char *buf)
|
|
|
if (!bus) {
|
|
|
LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist",
|
|
|
busNo);
|
|
|
- read_unlock(&BusListLock);
|
|
|
- return CONTROLVM_RESP_ERROR_BUS_INVALID;
|
|
|
+ retval = CONTROLVM_RESP_ERROR_BUS_INVALID;
|
|
|
}
|
|
|
-
|
|
|
- return CONTROLVM_RESP_SUCCESS;
|
|
|
+ read_unlock(&BusListLock);
|
|
|
+ if (retval == CONTROLVM_RESP_SUCCESS) {
|
|
|
+ /* the msg is bound for virtpci; send
|
|
|
+ * guest_msgs struct to callback
|
|
|
+ */
|
|
|
+ if (!uuid_le_cmp(dev->channelTypeGuid,
|
|
|
+ UltraVhbaChannelProtocolGuid)) {
|
|
|
+ cmd.msgtype = GUEST_DEL_VHBA;
|
|
|
+ cmd.del_vhba.chanptr = dev->chanptr;
|
|
|
+ } else if (!uuid_le_cmp(dev->channelTypeGuid,
|
|
|
+ UltraVnicChannelProtocolGuid)) {
|
|
|
+ cmd.msgtype = GUEST_DEL_VNIC;
|
|
|
+ cmd.del_vnic.chanptr = dev->chanptr;
|
|
|
+ } else {
|
|
|
+ LOGERR("CONTROLVM_DEVICE_DESTROY Failed: unknown channelTypeGuid.\n");
|
|
|
+ return
|
|
|
+ CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
|
|
|
+ }
|
|
|
+ if (!VirtControlChanFunc) {
|
|
|
+ LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered.");
|
|
|
+ return
|
|
|
+ CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
|
|
|
+ }
|
|
|
+ if (!VirtControlChanFunc(&cmd)) {
|
|
|
+ LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci GUEST_DEL_[VHBA||VNIC] returned error.");
|
|
|
+ return
|
|
|
+ CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
|
|
|
+ }
|
|
|
+/* you must disable channel interrupts BEFORE you unmap the channel,
|
|
|
+ * because if you unmap first, there may still be some activity going
|
|
|
+ * on which accesses the channel and you will get a "unable to handle
|
|
|
+ * kernel paging request"
|
|
|
+ */
|
|
|
+ if (dev->polling) {
|
|
|
+ LOGINF("calling uislib_disable_channel_interrupts");
|
|
|
+ uislib_disable_channel_interrupts(busNo, devNo);
|
|
|
+ }
|
|
|
+ /* unmap the channel memory for the device. */
|
|
|
+ if (!msg->hdr.Flags.testMessage) {
|
|
|
+ LOGINF("destroy_device, doing iounmap");
|
|
|
+ uislib_iounmap(dev->chanptr);
|
|
|
+ }
|
|
|
+ kfree(dev);
|
|
|
+ bus->device[devNo] = NULL;
|
|
|
+ }
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
static int
|