summaryrefslogtreecommitdiff
path: root/drivers/staging/unisys/uislib/uislib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/unisys/uislib/uislib.c')
-rw-r--r--drivers/staging/unisys/uislib/uislib.c451
1 files changed, 228 insertions, 223 deletions
diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c
index 63c91cd6fdcc..706f1c0c2c6e 100644
--- a/drivers/staging/unisys/uislib/uislib.c
+++ b/drivers/staging/unisys/uislib/uislib.c
@@ -25,7 +25,8 @@
#include <linux/module.h>
#include <linux/debugfs.h>
-#include "commontypes.h"
+#include <linux/types.h>
+#include <linux/uuid.h>
#include <linux/version.h>
#include "uniklog.h"
@@ -133,6 +134,7 @@ init_vbus_channel(u64 channelAddr, u32 channelBytes)
{
void __iomem *rc = NULL;
void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes);
+
if (!pChan) {
LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
(unsigned long long) channelAddr,
@@ -229,6 +231,7 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf)
/* the msg is bound for virtpci; send guest_msgs struct to callback */
if (!msg->hdr.Flags.server) {
struct guest_msgs cmd;
+
cmd.msgtype = GUEST_ADD_VBUS;
cmd.add_vbus.busNo = busNo;
cmd.add_vbus.chanptr = bus->pBusChannel;
@@ -273,52 +276,19 @@ destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
{
int i;
struct bus_info *bus, *prev = NULL;
+ struct guest_msgs cmd;
u32 busNo;
busNo = msg->cmd.destroyBus.busNo;
- /* find and delete the bus */
read_lock(&BusListLock);
- for (bus = BusListHead; bus; prev = bus, bus = bus->next) {
- if (bus->busNo == busNo) {
- /* found the bus - ensure that all device
- * slots are NULL
- */
- for (i = 0; i < bus->deviceCount; i++) {
- if (bus->device[i] != NULL) {
- LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
- i, busNo);
- read_unlock(&BusListLock);
- return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
- }
- }
- read_unlock(&BusListLock);
- /* the msg is bound for virtpci; send
- * guest_msgs struct to callback
- */
- if (!msg->hdr.Flags.server) {
- struct guest_msgs cmd;
- cmd.msgtype = GUEST_DEL_VBUS;
- cmd.del_vbus.busNo = busNo;
- if (!VirtControlChanFunc) {
- LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
- return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
- }
- if (!VirtControlChanFunc(&cmd)) {
- LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
- return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
- }
- }
- /* remove the bus from the list */
- write_lock(&BusListLock);
- if (prev) /* not at head */
- prev->next = bus->next;
- else
- BusListHead = bus->next;
- BusListCount--;
- write_unlock(&BusListLock);
+
+ bus = BusListHead;
+ while (bus) {
+ if (bus->busNo == busNo)
break;
- }
+ prev = bus;
+ bus = bus->next;
}
if (!bus) {
@@ -327,6 +297,44 @@ destroy_bus(CONTROLVM_MESSAGE *msg, char *buf)
read_unlock(&BusListLock);
return CONTROLVM_RESP_ERROR_ALREADY_DONE;
}
+
+ /* verify that this bus has no devices. */
+ for (i = 0; i < bus->deviceCount; i++) {
+ if (bus->device[i] != NULL) {
+ LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.",
+ i, busNo);
+ read_unlock(&BusListLock);
+ return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED;
+ }
+ }
+ read_unlock(&BusListLock);
+
+ if (msg->hdr.Flags.server)
+ goto remove;
+
+ /* client messages require us to call the virtpci callback associated
+ with this bus. */
+ cmd.msgtype = GUEST_DEL_VBUS;
+ cmd.del_vbus.bus_no = busNo;
+ if (!VirtControlChanFunc) {
+ LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered.");
+ return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+ }
+ if (!VirtControlChanFunc(&cmd)) {
+ LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci GUEST_DEL_VBUS returned error.");
+ return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+ }
+
+ /* finally, remove the bus from the list */
+remove:
+ write_lock(&BusListLock);
+ if (prev) /* not at head */
+ prev->next = bus->next;
+ else
+ BusListHead = bus->next;
+ BusListCount--;
+ write_unlock(&BusListLock);
+
if (bus->pBusChannel) {
uislib_iounmap(bus->pBusChannel);
bus->pBusChannel = NULL;
@@ -360,18 +368,18 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
return CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
}
- dev->channelTypeGuid = msg->cmd.createDevice.dataTypeGuid;
+ dev->channel_uuid = msg->cmd.createDevice.dataTypeGuid;
dev->intr = msg->cmd.createDevice.intr;
- dev->channelAddr = msg->cmd.createDevice.channelAddr;
- dev->busNo = busNo;
- dev->devNo = devNo;
+ dev->channel_addr = msg->cmd.createDevice.channelAddr;
+ dev->bus_no = busNo;
+ dev->dev_no = devNo;
sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */
sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo);
/* map the channel memory for the device. */
if (msg->hdr.Flags.testMessage)
- dev->chanptr = (void __iomem *)__va(dev->channelAddr);
+ dev->chanptr = (void __iomem *)__va(dev->channel_addr);
else {
- pReqHandler = ReqHandlerFind(dev->channelTypeGuid);
+ pReqHandler = ReqHandlerFind(dev->channel_uuid);
if (pReqHandler)
/* generic service handler registered for this
* channel
@@ -387,11 +395,11 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
goto Away;
}
dev->chanptr =
- uislib_ioremap_cache(dev->channelAddr,
+ uislib_ioremap_cache(dev->channel_addr,
msg->cmd.createDevice.channelBytes);
if (!dev->chanptr) {
LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed",
- dev->channelAddr,
+ dev->channel_addr,
msg->cmd.createDevice.channelBytes);
result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo,
@@ -399,8 +407,8 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
goto Away;
}
}
- dev->devInstGuid = msg->cmd.createDevice.devInstGuid;
- dev->channelBytes = msg->cmd.createDevice.channelBytes;
+ dev->instance_uuid = msg->cmd.createDevice.devInstGuid;
+ dev->channel_bytes = msg->cmd.createDevice.channelBytes;
read_lock(&BusListLock);
for (bus = BusListHead; bus; bus = bus->next) {
@@ -433,7 +441,8 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
*/
if (!msg->hdr.Flags.server) {
struct guest_msgs cmd;
- if (!uuid_le_cmp(dev->channelTypeGuid,
+
+ if (!uuid_le_cmp(dev->channel_uuid,
UltraVhbaChannelProtocolGuid)) {
wait_for_valid_guid(&((CHANNEL_HEADER
__iomem *) (dev->
@@ -452,13 +461,13 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
}
cmd.msgtype = GUEST_ADD_VHBA;
cmd.add_vhba.chanptr = dev->chanptr;
- cmd.add_vhba.busNo = busNo;
- cmd.add_vhba.deviceNo = devNo;
- cmd.add_vhba.devInstGuid =
- dev->devInstGuid;
+ cmd.add_vhba.bus_no = busNo;
+ cmd.add_vhba.device_no = devNo;
+ cmd.add_vhba.instance_uuid =
+ dev->instance_uuid;
cmd.add_vhba.intr = dev->intr;
} else
- if (!uuid_le_cmp(dev->channelTypeGuid,
+ if (!uuid_le_cmp(dev->channel_uuid,
UltraVnicChannelProtocolGuid)) {
wait_for_valid_guid(&((CHANNEL_HEADER
__iomem *) (dev->
@@ -477,10 +486,10 @@ create_device(CONTROLVM_MESSAGE *msg, char *buf)
}
cmd.msgtype = GUEST_ADD_VNIC;
cmd.add_vnic.chanptr = dev->chanptr;
- cmd.add_vnic.busNo = busNo;
- cmd.add_vnic.deviceNo = devNo;
- cmd.add_vnic.devInstGuid =
- dev->devInstGuid;
+ cmd.add_vnic.bus_no = busNo;
+ cmd.add_vnic.device_no = devNo;
+ cmd.add_vnic.instance_uuid =
+ dev->instance_uuid;
cmd.add_vhba.intr = dev->intr;
} else {
LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n");
@@ -539,6 +548,7 @@ pause_device(CONTROLVM_MESSAGE *msg)
struct bus_info *bus;
struct device_info *dev;
struct guest_msgs cmd;
+ int retval = CONTROLVM_RESP_SUCCESS;
busNo = msg->cmd.deviceChangeState.busNo;
devNo = msg->cmd.deviceChangeState.devNo;
@@ -550,58 +560,53 @@ pause_device(CONTROLVM_MESSAGE *msg)
if (devNo >= bus->deviceCount) {
LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause 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_CHANGESTATE:pause 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_PAUSE_VHBA;
- cmd.pause_vhba.chanptr = dev->chanptr;
- } else
- if (!uuid_le_cmp(dev->channelTypeGuid,
- UltraVnicChannelProtocolGuid)) {
- cmd.msgtype = GUEST_PAUSE_VNIC;
- cmd.pause_vnic.chanptr = dev->chanptr;
+ retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
} else {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
- return
- CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
- }
-
- if (!VirtControlChanFunc) {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
- return
- CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
- }
-
- if (!VirtControlChanFunc(&cmd)) {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
- return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+ /* make sure this device exists */
+ dev = bus->device[devNo];
+ if (!dev) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.",
+ devNo);
+ retval =
+ CONTROLVM_RESP_ERROR_ALREADY_DONE;
+ }
}
break;
}
}
-
if (!bus) {
LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause 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->channel_uuid,
+ UltraVhbaChannelProtocolGuid)) {
+ cmd.msgtype = GUEST_PAUSE_VHBA;
+ cmd.pause_vhba.chanptr = dev->chanptr;
+ } else if (!uuid_le_cmp(dev->channel_uuid,
+ UltraVnicChannelProtocolGuid)) {
+ cmd.msgtype = GUEST_PAUSE_VNIC;
+ cmd.pause_vnic.chanptr = dev->chanptr;
+ } else {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: unknown channelTypeGuid.\n");
+ return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+ }
+ if (!VirtControlChanFunc) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+ return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+ }
+ if (!VirtControlChanFunc(&cmd)) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: virtpci GUEST_PAUSE_[VHBA||VNIC] returned error.");
+ return
+ CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+ }
+ }
+ return retval;
}
static int
@@ -611,6 +616,7 @@ resume_device(CONTROLVM_MESSAGE *msg)
struct bus_info *bus;
struct device_info *dev;
struct guest_msgs cmd;
+ int retval = CONTROLVM_RESP_SUCCESS;
busNo = msg->cmd.deviceChangeState.busNo;
devNo = msg->cmd.deviceChangeState.devNo;
@@ -622,45 +628,16 @@ resume_device(CONTROLVM_MESSAGE *msg)
if (devNo >= bus->deviceCount) {
LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume 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_CHANGESTATE:resume 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_RESUME_VHBA;
- cmd.resume_vhba.chanptr = dev->chanptr;
- } else
- if (!uuid_le_cmp(dev->channelTypeGuid,
- UltraVnicChannelProtocolGuid)) {
- cmd.msgtype = GUEST_RESUME_VNIC;
- cmd.resume_vnic.chanptr = dev->chanptr;
+ retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID;
} else {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
- return
- CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
- }
-
- if (!VirtControlChanFunc) {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
- return
- CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
- }
-
- if (!VirtControlChanFunc(&cmd)) {
- LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
- return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+ /* make sure this device exists */
+ dev = bus->device[devNo];
+ if (!dev) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.",
+ devNo);
+ retval =
+ CONTROLVM_RESP_ERROR_ALREADY_DONE;
+ }
}
break;
}
@@ -669,11 +646,36 @@ resume_device(CONTROLVM_MESSAGE *msg)
if (!bus) {
LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume 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);
+ /* the msg is bound for virtpci; send
+ * guest_msgs struct to callback
+ */
+ if (retval == CONTROLVM_RESP_SUCCESS) {
+ if (!uuid_le_cmp(dev->channel_uuid,
+ UltraVhbaChannelProtocolGuid)) {
+ cmd.msgtype = GUEST_RESUME_VHBA;
+ cmd.resume_vhba.chanptr = dev->chanptr;
+ } else if (!uuid_le_cmp(dev->channel_uuid,
+ UltraVnicChannelProtocolGuid)) {
+ cmd.msgtype = GUEST_RESUME_VNIC;
+ cmd.resume_vnic.chanptr = dev->chanptr;
+ } else {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: unknown channelTypeGuid.\n");
+ return CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN;
+ }
+ if (!VirtControlChanFunc) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE Failed: virtpci callback not registered.");
+ return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE;
+ }
+ if (!VirtControlChanFunc(&cmd)) {
+ LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: virtpci GUEST_RESUME_[VHBA||VNIC] returned error.");
+ return
+ CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR;
+ }
+ }
+ return retval;
}
static int
@@ -683,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;
@@ -694,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;
}
}
@@ -758,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->channel_uuid,
+ UltraVhbaChannelProtocolGuid)) {
+ cmd.msgtype = GUEST_DEL_VHBA;
+ cmd.del_vhba.chanptr = dev->chanptr;
+ } else if (!uuid_le_cmp(dev->channel_uuid,
+ 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
@@ -1164,6 +1165,7 @@ uislib_cache_alloc(struct kmem_cache *cur_pool, char *fn, int ln)
* invoke oom killer), which will probably cripple the system.
*/
void *p = kmem_cache_alloc(cur_pool, GFP_ATOMIC | __GFP_NORETRY);
+
if (p == NULL) {
LOGERR("uislib_malloc failed to alloc uiscmdrsp @%s:%d",
fn, ln);
@@ -1339,6 +1341,7 @@ Process_Incoming(void *v)
unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles;
struct list_head *new_tail = NULL;
int i;
+
UIS_DAEMONIZE("dev_incoming");
for (i = 0; i < 16; i++) {
old_cycles = get_cycles();
@@ -1361,18 +1364,19 @@ Process_Incoming(void *v)
struct device_info *dev = NULL;
/* poll each channel for input */
- LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+ down(&Lock_Polling_Device_Channels);
new_tail = NULL;
list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) {
int rc = 0;
+
dev = list_entry(lelt, struct device_info,
list_polling_device_channels);
- LOCKSEM_UNINTERRUPTIBLE(&dev->interrupt_callback_lock);
+ down(&dev->interrupt_callback_lock);
if (dev->interrupt)
rc = dev->interrupt(dev->interrupt_context);
else
continue;
- UNLOCKSEM(&dev->interrupt_callback_lock);
+ up(&dev->interrupt_callback_lock);
if (rc) {
/* dev->interrupt returned, but there
* is still more work to do.
@@ -1399,7 +1403,7 @@ Process_Incoming(void *v)
tot_moved_to_tail_cnt++;
list_move_tail(new_tail, &List_Polling_Device_Channels);
}
- UNLOCKSEM(&Lock_Polling_Device_Channels);
+ up(&Lock_Polling_Device_Channels);
cur_cycles = get_cycles();
delta_cycles = cur_cycles - old_cycles;
old_cycles = cur_cycles;
@@ -1458,25 +1462,26 @@ Initialize_incoming_thread(void)
* function.
*/
void
-uislib_enable_channel_interrupts(u32 busNo, u32 devNo,
+uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no,
int (*interrupt)(void *),
void *interrupt_context)
{
struct device_info *dev;
- dev = find_dev(busNo, devNo);
+
+ dev = find_dev(bus_no, dev_no);
if (!dev) {
- LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
- (int) (devNo));
+ LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no),
+ (int) (dev_no));
return;
}
- LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+ down(&Lock_Polling_Device_Channels);
Initialize_incoming_thread();
dev->interrupt = interrupt;
dev->interrupt_context = interrupt_context;
dev->polling = TRUE;
list_add_tail(&(dev->list_polling_device_channels),
&List_Polling_Device_Channels);
- UNLOCKSEM(&Lock_Polling_Device_Channels);
+ up(&Lock_Polling_Device_Channels);
}
EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
@@ -1484,20 +1489,21 @@ EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts);
* Process_Incoming().
*/
void
-uislib_disable_channel_interrupts(u32 busNo, u32 devNo)
+uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no)
{
struct device_info *dev;
- dev = find_dev(busNo, devNo);
+
+ dev = find_dev(bus_no, dev_no);
if (!dev) {
- LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (busNo),
- (int) (devNo));
+ LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no),
+ (int) (dev_no));
return;
}
- LOCKSEM_UNINTERRUPTIBLE(&Lock_Polling_Device_Channels);
+ down(&Lock_Polling_Device_Channels);
list_del(&dev->list_polling_device_channels);
dev->polling = FALSE;
dev->interrupt = NULL;
- UNLOCKSEM(&Lock_Polling_Device_Channels);
+ up(&Lock_Polling_Device_Channels);
}
EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts);
@@ -1517,7 +1523,7 @@ static DECLARE_WORK(Work_wakeup_polling_device_channels,
* your device might have more requests.
*/
void
-uislib_force_channel_interrupt(u32 busNo, u32 devNo)
+uislib_force_channel_interrupt(u32 bus_no, u32 dev_no)
{
if (en_smart_wakeup == 0)
return;
@@ -1612,7 +1618,6 @@ uislib_mod_exit(void)
debugfs_remove(dir_debugfs);
DBGINF("goodbye.\n");
- return;
}
module_init(uislib_mod_init);