diff options
Diffstat (limited to 'drivers/staging/unisys/visorbus')
-rw-r--r-- | drivers/staging/unisys/visorbus/controlvmchannel.h | 3 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/vbuschannel.h | 12 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorbus_main.c | 271 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorbus_private.h | 8 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchannel.c | 81 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchipset.c | 298 |
6 files changed, 226 insertions, 447 deletions
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 32ff5c1bb6ba..9ee9886a9aed 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -17,7 +17,8 @@ #define __CONTROLVMCHANNEL_H__ #include <linux/uuid.h> -#include "channel.h" + +#include "visorchannel.h" /* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ #define VISOR_CONTROLVM_CHANNEL_GUID \ diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index 27e04de14818..981b180f3c4b 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -26,8 +26,7 @@ */ #include <linux/uuid.h> -#include <linux/ctype.h> -#include "channel.h" +#include "visorchannel.h" /* {193b331b-c58f-11da-95a9-00e08161165f} */ #define VISOR_VBUS_CHANNEL_GUID \ @@ -50,9 +49,9 @@ * @infostrs: Kernel vversion. * @reserved: Pad size to 256 bytes. * - * An array of this struct is present in the channel area for each vbus. - * (See vbuschannel.h.). It is filled in by the client side to provide info - * about the device and driver from the client's perspective. + * An array of this struct is present in the channel area for each vbus. It is + * filled in by the client side to provide info about the device and driver from + * the client's perspective. */ struct visor_vbus_deviceinfo { u8 devtype[16]; @@ -73,7 +72,7 @@ struct visor_vbus_deviceinfo { * BusInfo struct. * @dev_info_offset: Byte offset from beginning of this struct to the * DevInfo array. - * @reserved: Natural Alignment + * @reserved: Natural alignment. */ struct visor_vbus_headerinfo { u32 struct_bytes; @@ -97,7 +96,6 @@ struct visor_vbus_headerinfo { struct visor_vbus_channel { struct channel_header channel_header; struct visor_vbus_headerinfo hdr_info; - /* The remainder of this channel is filled in by the client */ struct visor_vbus_deviceinfo chp_info; struct visor_vbus_deviceinfo bus_info; struct visor_vbus_deviceinfo dev_info[0]; diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 2bc7ff7bb96a..b604d0cccef1 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -13,7 +13,10 @@ * details. */ +#include <linux/ctype.h> #include <linux/debugfs.h> +#include <linux/module.h> +#include <linux/slab.h> #include <linux/uuid.h> #include "visorbus.h" @@ -69,12 +72,9 @@ static LIST_HEAD(list_all_device_instances); * Note that <logCtx> is only needed for callers in the EFI environment, and * is used to pass the EFI_DIAG_CAPTURE_PROTOCOL needed to log messages. */ -int visor_check_channel(struct channel_header *ch, - struct device *dev, - const guid_t *expected_guid, - char *chname, - u64 expected_min_bytes, - u32 expected_version, +int visor_check_channel(struct channel_header *ch, struct device *dev, + const guid_t *expected_guid, char *chname, + u64 expected_min_bytes, u32 expected_version, u64 expected_signature) { if (!guid_is_null(expected_guid)) { @@ -125,7 +125,6 @@ static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env) dev = to_visor_device(xdev); guid = visorchannel_get_guid(dev->visorchannel); - return add_uevent_var(env, "MODALIAS=visorbus:%pUl", guid); } @@ -144,17 +143,24 @@ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) int i; struct visor_device *dev; struct visor_driver *drv; + struct visorchannel *chan; dev = to_visor_device(xdev); channel_type = visorchannel_get_guid(dev->visorchannel); drv = to_visor_driver(xdrv); + chan = dev->visorchannel; if (!drv->channel_types) return 0; - for (i = 0; !guid_is_null(&drv->channel_types[i].guid); i++) - if (guid_equal(&drv->channel_types[i].guid, channel_type)) + if (guid_equal(&drv->channel_types[i].guid, channel_type) && + visor_check_channel(visorchannel_get_header(chan), + xdev, + &drv->channel_types[i].guid, + (char *)drv->channel_types[i].name, + drv->channel_types[i].min_bytes, + drv->channel_types[i].version, + VISOR_CHANNEL_SIGNATURE)) return i + 1; - return 0; } @@ -162,13 +168,48 @@ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) * This describes the TYPE of bus. * (Don't confuse this with an INSTANCE of the bus.) */ -struct bus_type visorbus_type = { +static struct bus_type visorbus_type = { .name = "visorbus", .match = visorbus_match, .uevent = visorbus_uevent, .dev_groups = visorbus_dev_groups, }; +struct visor_busdev { + u32 bus_no; + u32 dev_no; +}; + +static int match_visorbus_dev_by_id(struct device *dev, void *data) +{ + struct visor_device *vdev = to_visor_device(dev); + struct visor_busdev *id = data; + + if (vdev->chipset_bus_no == id->bus_no && + vdev->chipset_dev_no == id->dev_no) + return 1; + return 0; +} + +struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, + struct visor_device *from) +{ + struct device *dev; + struct device *dev_start = NULL; + struct visor_busdev id = { + .bus_no = bus_no, + .dev_no = dev_no + }; + + if (from) + dev_start = &from->device; + dev = bus_find_device(&visorbus_type, dev_start, (void *)&id, + match_visorbus_dev_by_id); + if (!dev) + return NULL; + return to_visor_device(dev); +} + /* * visorbus_release_busdevice() - called when device_unregister() is called for * the bus device instance, after all other tasks @@ -179,8 +220,9 @@ static void visorbus_release_busdevice(struct device *xdev) { struct visor_device *dev = dev_get_drvdata(xdev); - debugfs_remove(dev->debugfs_client_bus_info); + debugfs_remove(dev->debugfs_bus_info); debugfs_remove_recursive(dev->debugfs_dir); + visorchannel_destroy(dev->visorchannel); kfree(dev); } @@ -198,7 +240,7 @@ static void visorbus_release_device(struct device *xdev) } /* - * begin implementation of specific channel attributes to appear under + * BUS specific channel attributes to appear under * /sys/bus/visorbus<x>/dev<y>/channel */ @@ -218,7 +260,7 @@ static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr, struct visor_device *vdev = to_visor_device(dev); return sprintf(buf, "0x%lx\n", - visorchannel_get_nbytes(vdev->visorchannel)); + visorchannel_get_nbytes(vdev->visorchannel)); } static DEVICE_ATTR_RO(nbytes); @@ -284,18 +326,14 @@ static struct attribute *channel_attrs[] = { ATTRIBUTE_GROUPS(channel); -/* end implementation of specific channel attributes */ - /* * BUS instance attributes * * define & implement display of bus attributes under * /sys/bus/visorbus/devices/visorbus<n>. */ - static ssize_t partition_handle_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); u64 handle = visorchannel_get_clientpartition(vdev->visorchannel); @@ -305,8 +343,7 @@ static ssize_t partition_handle_show(struct device *dev, static DEVICE_ATTR_RO(partition_handle); static ssize_t partition_guid_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); @@ -315,8 +352,7 @@ static ssize_t partition_guid_show(struct device *dev, static DEVICE_ATTR_RO(partition_guid); static ssize_t partition_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); @@ -325,8 +361,7 @@ static ssize_t partition_name_show(struct device *dev, static DEVICE_ATTR_RO(partition_name); static ssize_t channel_addr_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); u64 addr = visorchannel_get_physaddr(vdev->visorchannel); @@ -336,8 +371,7 @@ static ssize_t channel_addr_show(struct device *dev, static DEVICE_ATTR_RO(channel_addr); static ssize_t channel_bytes_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel); @@ -347,8 +381,7 @@ static ssize_t channel_bytes_show(struct device *dev, static DEVICE_ATTR_RO(channel_bytes); static ssize_t channel_id_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); int len = 0; @@ -356,7 +389,6 @@ static ssize_t channel_id_show(struct device *dev, visorchannel_id(vdev->visorchannel, buf); len = strlen(buf); buf[len++] = '\n'; - return len; } static DEVICE_ATTR_RO(channel_id); @@ -396,13 +428,11 @@ static void vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo, /* uninitialized vbus device entry */ if (!isprint(devinfo->devtype[0])) return; - if (devix >= 0) seq_printf(seq, "[%d]", devix); else /* vbus device entry is for bus or chipset */ seq_puts(seq, " "); - /* * Note: because the s-Par back-end is free to scribble in this area, * we never assume '\0'-termination. @@ -415,7 +445,7 @@ static void vbuschannel_print_devinfo(struct visor_vbus_deviceinfo *devinfo, devinfo->infostrs); } -static int client_bus_info_debugfs_show(struct seq_file *seq, void *v) +static int bus_info_debugfs_show(struct seq_file *seq, void *v) { int i = 0; unsigned long off; @@ -427,10 +457,9 @@ static int client_bus_info_debugfs_show(struct seq_file *seq, void *v) return 0; seq_printf(seq, - "Client device / client driver info for %s partition (vbus #%u):\n", + "Client device/driver info for %s partition (vbus #%u):\n", ((vdev->name) ? (char *)(vdev->name) : ""), vdev->chipset_bus_no); - if (visorchannel_read(channel, offsetof(struct visor_vbus_channel, chp_info), &dev_info, sizeof(dev_info)) >= 0) @@ -448,19 +477,17 @@ static int client_bus_info_debugfs_show(struct seq_file *seq, void *v) off += sizeof(dev_info); i++; } - return 0; } -static int client_bus_info_debugfs_open(struct inode *inode, struct file *file) +static int bus_info_debugfs_open(struct inode *inode, struct file *file) { - return single_open(file, client_bus_info_debugfs_show, - inode->i_private); + return single_open(file, bus_info_debugfs_show, inode->i_private); } -static const struct file_operations client_bus_info_debugfs_fops = { +static const struct file_operations bus_info_debugfs_fops = { .owner = THIS_MODULE, - .open = client_bus_info_debugfs_open, + .open = bus_info_debugfs_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -479,6 +506,7 @@ static int dev_start_periodic_work(struct visor_device *dev) { if (dev->being_removed || dev->timer_active) return -EINVAL; + /* now up by at least 2 */ get_device(&dev->device); dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL; @@ -491,6 +519,7 @@ static void dev_stop_periodic_work(struct visor_device *dev) { if (!dev->timer_active) return; + del_timer_sync(&dev->timer); dev->timer_active = false; put_device(&dev->device); @@ -508,20 +537,15 @@ static void dev_stop_periodic_work(struct visor_device *dev) */ static int visordriver_remove_device(struct device *xdev) { - struct visor_device *dev; - struct visor_driver *drv; - - dev = to_visor_device(xdev); - drv = to_visor_driver(xdev->driver); + struct visor_device *dev = to_visor_device(xdev); + struct visor_driver *drv = to_visor_driver(xdev->driver); mutex_lock(&dev->visordriver_callback_lock); dev->being_removed = true; drv->remove(dev); mutex_unlock(&dev->visordriver_callback_lock); - dev_stop_periodic_work(dev); put_device(&dev->device); - return 0; } @@ -546,8 +570,7 @@ EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver); * @dest: the destination buffer that is written into from the channel * @nbytes: the number of bytes to read from the channel * - * If receiving a message, use the visorchannel_signalremove() - * function instead. + * If receiving a message, use the visorchannel_signalremove() function instead. * * Return: integer indicating success (zero) or failure (non-zero) */ @@ -566,8 +589,7 @@ EXPORT_SYMBOL_GPL(visorbus_read_channel); * @src: the source buffer that is written into the channel * @nbytes: the number of bytes to write into the channel * - * If sending a message, use the visorchannel_signalinsert() - * function instead. + * If sending a message, use the visorchannel_signalinsert() function instead. * * Return: integer indicating success (zero) or failure (non-zero) */ @@ -618,17 +640,16 @@ EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); * * This is how everything starts from the device end. * This function is called when a channel first appears via a ControlVM - * message. In response, this function allocates a visor_device to - * correspond to the new channel, and attempts to connect it the appropriate - * driver. If the appropriate driver is found, the visor_driver.probe() - * function for that driver will be called, and will be passed the new - * visor_device that we just created. + * message. In response, this function allocates a visor_device to correspond + * to the new channel, and attempts to connect it the appropriate * driver. If + * the appropriate driver is found, the visor_driver.probe() function for that + * driver will be called, and will be passed the new * visor_device that we + * just created. * * It's ok if the appropriate driver is not yet loaded, because in that case * the new device struct will just stick around in the bus' list of devices. * When the appropriate driver calls visorbus_register_visor_driver(), the - * visor_driver.probe() for the new driver will be called with the new - * device. + * visor_driver.probe() for the new driver will be called with the new device. * * Return: 0 if successful, otherwise the negative value returned by * device_add() indicating the reason for failure @@ -647,17 +668,15 @@ int create_visor_device(struct visor_device *dev) /* keep a reference just for us (now 2) */ get_device(&dev->device); setup_timer(&dev->timer, dev_periodic_work, (unsigned long)dev); - /* - * bus_id must be a unique name with respect to this bus TYPE - * (NOT bus instance). That's why we need to include the bus - * number within the name. + * bus_id must be a unique name with respect to this bus TYPE (NOT bus + * instance). That's why we need to include the bus number within the + * name. */ err = dev_set_name(&dev->device, "vbus%u:dev%u", chipset_bus_no, chipset_dev_no); if (err) goto err_put; - /* * device_add does this: * bus_add_device(dev) @@ -671,14 +690,13 @@ int create_visor_device(struct visor_device *dev) * if (!drv.probe(dev)) [visordriver_probe_device] * dev.drv = NULL * - * Note that device_add does NOT fail if no driver failed to - * claim the device. The device will be linked onto - * bus_type.klist_devices regardless (use bus_for_each_dev). + * Note that device_add does NOT fail if no driver failed to claim the + * device. The device will be linked onto bus_type.klist_devices + * regardless (use bus_for_each_dev). */ err = device_add(&dev->device); if (err < 0) goto err_put; - list_add_tail(&dev->list_all, &list_all_device_instances); dev->state.created = 1; visorbus_response(dev, err, CONTROLVM_DEVICE_CREATE); @@ -695,8 +713,9 @@ void remove_visor_device(struct visor_device *dev) { list_del(&dev->list_all); put_device(&dev->device); + if (dev->pending_msg_hdr) + visorbus_response(dev, 0, CONTROLVM_DEVICE_DESTROY); device_unregister(&dev->device); - visorbus_response(dev, 0, CONTROLVM_DEVICE_DESTROY); } static int get_vbus_header_info(struct visorchannel *chan, @@ -718,14 +737,11 @@ static int get_vbus_header_info(struct visorchannel *chan, sizeof(*hdr_info)); if (err < 0) return err; - if (hdr_info->struct_bytes < sizeof(struct visor_vbus_headerinfo)) return -EINVAL; - if (hdr_info->device_info_struct_bytes < sizeof(struct visor_vbus_deviceinfo)) return -EINVAL; - return 0; } @@ -746,11 +762,12 @@ static void write_vbus_chp_info(struct visorchannel *chan, struct visor_vbus_headerinfo *hdr_info, struct visor_vbus_deviceinfo *info) { - int off = sizeof(struct channel_header) + hdr_info->chp_info_offset; + int off; if (hdr_info->chp_info_offset == 0) return; + off = sizeof(struct channel_header) + hdr_info->chp_info_offset; visorchannel_write(chan, off, info, sizeof(*info)); } @@ -771,11 +788,12 @@ static void write_vbus_bus_info(struct visorchannel *chan, struct visor_vbus_headerinfo *hdr_info, struct visor_vbus_deviceinfo *info) { - int off = sizeof(struct channel_header) + hdr_info->bus_info_offset; + int off; if (hdr_info->bus_info_offset == 0) return; + off = sizeof(struct channel_header) + hdr_info->bus_info_offset; visorchannel_write(chan, off, info, sizeof(*info)); } @@ -798,13 +816,12 @@ static void write_vbus_dev_info(struct visorchannel *chan, struct visor_vbus_deviceinfo *info, unsigned int devix) { - int off = - (sizeof(struct channel_header) + hdr_info->dev_info_offset) + - (hdr_info->device_info_struct_bytes * devix); + int off; if (hdr_info->dev_info_offset == 0) return; - + off = (sizeof(struct channel_header) + hdr_info->dev_info_offset) + + (hdr_info->device_info_struct_bytes * devix); visorchannel_write(chan, off, info, sizeof(*info)); } @@ -844,7 +861,6 @@ static void publish_vbus_dev_info(struct visor_device *visordev) if (!visordev->device.driver) return; - bdev = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (!bdev) return; @@ -860,14 +876,12 @@ static void publish_vbus_dev_info(struct visor_device *visordev) * type name */ for (i = 0; visordrv->channel_types[i].name; i++) { - if (memcmp(&visordrv->channel_types[i].guid, - &visordev->channel_type_guid, - sizeof(visordrv->channel_types[i].guid)) == 0) { + if (guid_equal(&visordrv->channel_types[i].guid, + &visordev->channel_type_guid)) { chan_type_name = visordrv->channel_types[i].name; break; } } - bus_device_info_init(&dev_info, chan_type_name, visordrv->name); write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no); write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo); @@ -892,36 +906,32 @@ static void publish_vbus_dev_info(struct visor_device *visordev) */ static int visordriver_probe_device(struct device *xdev) { - int res; - struct visor_driver *drv; - struct visor_device *dev; - - dev = to_visor_device(xdev); - drv = to_visor_driver(xdev->driver); + int err; + struct visor_driver *drv = to_visor_driver(xdev->driver); + struct visor_device *dev = to_visor_device(xdev); mutex_lock(&dev->visordriver_callback_lock); dev->being_removed = false; - - res = drv->probe(dev); - if (res >= 0) { - /* success: reference kept via unmatched get_device() */ - get_device(&dev->device); - publish_vbus_dev_info(dev); + err = drv->probe(dev); + if (err) { + mutex_unlock(&dev->visordriver_callback_lock); + return err; } - + /* success: reference kept via unmatched get_device() */ + get_device(&dev->device); + publish_vbus_dev_info(dev); mutex_unlock(&dev->visordriver_callback_lock); - return res; + return 0; } /* - * visorbus_register_visor_driver() - registers the provided visor driver - * for handling one or more visor device + * visorbus_register_visor_driver() - registers the provided visor driver for + * handling one or more visor device * types (channel_types) * @drv: the driver to register * - * A visor function driver calls this function to register - * the driver. The caller MUST fill in the following fields within the - * #drv structure: + * A visor function driver calls this function to register the driver. The + * caller MUST fill in the following fields within the #drv structure: * name, version, owner, channel_types, probe, remove * * Here's how the whole Linux bus / driver / device model works. @@ -967,16 +977,12 @@ int visorbus_register_visor_driver(struct visor_driver *drv) /* can't register on a nonexistent bus */ if (!initialized) return -ENODEV; - if (!drv->probe) return -EINVAL; - if (!drv->remove) return -EINVAL; - if (!drv->pause) return -EINVAL; - if (!drv->resume) return -EINVAL; @@ -985,7 +991,6 @@ int visorbus_register_visor_driver(struct visor_driver *drv) drv->driver.probe = visordriver_probe_device; drv->driver.remove = visordriver_remove_device; drv->driver.owner = drv->owner; - /* * driver_register does this: * bus_add_driver(drv) @@ -998,7 +1003,6 @@ int visorbus_register_visor_driver(struct visor_driver *drv) * if (!drv.probe(dev)) [visordriver_probe_device] * dev.drv = NULL */ - return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); @@ -1019,39 +1023,28 @@ int visorbus_create_instance(struct visor_device *dev) hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL); if (!hdr_info) return -ENOMEM; - dev_set_name(&dev->device, "visorbus%d", id); dev->device.bus = &visorbus_type; dev->device.groups = visorbus_groups; dev->device.release = visorbus_release_busdevice; - dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->device), visorbus_debugfs_dir); - dev->debugfs_client_bus_info = - debugfs_create_file("client_bus_info", 0440, - dev->debugfs_dir, dev, - &client_bus_info_debugfs_fops); - + dev->debugfs_bus_info = debugfs_create_file("client_bus_info", 0440, + dev->debugfs_dir, dev, + &bus_info_debugfs_fops); dev_set_drvdata(&dev->device, dev); err = get_vbus_header_info(dev->visorchannel, &dev->device, hdr_info); if (err < 0) goto err_debugfs_dir; - err = device_register(&dev->device); if (err < 0) goto err_debugfs_dir; - list_add_tail(&dev->list_all, &list_all_bus_instances); - dev->state.created = 1; dev->vbus_hdr_info = (void *)hdr_info; - write_vbus_chp_info(dev->visorchannel, hdr_info, - &chipset_driverinfo); - write_vbus_bus_info(dev->visorchannel, hdr_info, - &clientbus_driverinfo); - + write_vbus_chp_info(dev->visorchannel, hdr_info, &chipset_driverinfo); + write_vbus_bus_info(dev->visorchannel, hdr_info, &clientbus_driverinfo); visorbus_response(dev, err, CONTROLVM_BUS_CREATE); - return 0; err_debugfs_dir: @@ -1075,11 +1068,11 @@ void visorbus_remove_instance(struct visor_device *dev) * successfully been able to trace thru the code to see where/how * release() gets called. But I know it does. */ - visorchannel_destroy(dev->visorchannel); kfree(dev->vbus_hdr_info); list_del(&dev->list_all); + if (dev->pending_msg_hdr) + visorbus_response(dev, 0, CONTROLVM_BUS_DESTROY); device_unregister(&dev->device); - visorbus_response(dev, 0, CONTROLVM_BUS_DESTROY); } /* @@ -1090,9 +1083,9 @@ static void remove_all_visor_devices(void) struct list_head *listentry, *listtmp; list_for_each_safe(listentry, listtmp, &list_all_device_instances) { - struct visor_device *dev = list_entry(listentry, - struct visor_device, - list_all); + struct visor_device *dev; + + dev = list_entry(listentry, struct visor_device, list_all); remove_visor_device(dev); } } @@ -1131,7 +1124,6 @@ static void resume_state_change_complete(struct visor_device *dev, int status) return; dev->resuming = false; - /* * Notify the chipset driver that the resume is complete, * which will presumably want to send some sort of response to @@ -1156,7 +1148,7 @@ static int visorchipset_initiate_device_pause_resume(struct visor_device *dev, bool is_pause) { int err; - struct visor_driver *drv = NULL; + struct visor_driver *drv; /* If no driver associated with the device nothing to pause/resume */ if (!dev->device.driver) @@ -1177,7 +1169,6 @@ static int visorchipset_initiate_device_pause_resume(struct visor_device *dev, dev->resuming = true; err = drv->resume(dev, resume_state_change_complete); } - return err; } @@ -1198,7 +1189,6 @@ int visorchipset_device_pause(struct visor_device *dev_info) dev_info->pausing = false; return err; } - return 0; } @@ -1219,7 +1209,6 @@ int visorchipset_device_resume(struct visor_device *dev_info) dev_info->resuming = false; return err; } - return 0; } @@ -1228,18 +1217,12 @@ int visorbus_init(void) int err; visorbus_debugfs_dir = debugfs_create_dir("visorbus", NULL); - if (!visorbus_debugfs_dir) - return -ENOMEM; - bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus"); - err = bus_register(&visorbus_type); if (err < 0) return err; - initialized = true; bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset"); - return 0; } @@ -1248,14 +1231,12 @@ void visorbus_exit(void) struct list_head *listentry, *listtmp; remove_all_visor_devices(); - list_for_each_safe(listentry, listtmp, &list_all_bus_instances) { - struct visor_device *dev = list_entry(listentry, - struct visor_device, - list_all); + struct visor_device *dev; + + dev = list_entry(listentry, struct visor_device, list_all); visorbus_remove_instance(dev); } - bus_unregister(&visorbus_type); initialized = false; debugfs_remove_recursive(visorbus_debugfs_dir); diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index e878d65ab668..4a8b12d7cfaa 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -23,25 +23,23 @@ #include "vbuschannel.h" #include "visorbus.h" +struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, + struct visor_device *from); int visorbus_create_instance(struct visor_device *dev); void visorbus_remove_instance(struct visor_device *bus_info); int create_visor_device(struct visor_device *dev_info); void remove_visor_device(struct visor_device *dev_info); int visorchipset_device_pause(struct visor_device *dev_info); int visorchipset_device_resume(struct visor_device *dev_info); - void visorbus_response(struct visor_device *p, int response, int controlvm_id); void visorbus_device_changestate_response(struct visor_device *p, int response, struct visor_segment_state state); - int visorbus_init(void); void visorbus_exit(void); /* visorchannel access functions */ struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp, - const guid_t *guid); -struct visorchannel *visorchannel_create_with_lock(u64 physaddr, gfp_t gfp, - const guid_t *guid); + const guid_t *guid, bool needs_lock); void visorchannel_destroy(struct visorchannel *channel); int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest, ulong nbytes); diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 2a000fee3119..aae16073ba03 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -20,6 +20,7 @@ #include <linux/uuid.h> #include <linux/io.h> +#include <linux/slab.h> #include "visorbus.h" #include "visorbus_private.h" @@ -41,8 +42,8 @@ struct visorchannel { struct channel_header chan_hdr; guid_t guid; /* - * channel creator knows if more than one - * thread will be inserting or removing + * channel creator knows if more than one thread will be inserting or + * removing */ bool needs_lock; /* protect head writes in chan_hdr */ @@ -57,6 +58,7 @@ void visorchannel_destroy(struct visorchannel *channel) { if (!channel) return; + if (channel->mapped) { memunmap(channel->mapped); if (channel->requested) @@ -122,7 +124,6 @@ int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest, return -EIO; memcpy(dest, channel->mapped + offset, nbytes); - return 0; } @@ -140,9 +141,7 @@ int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest, memcpy(((char *)(&channel->chan_hdr)) + offset, dest, copy_size); } - memcpy(channel->mapped + offset, dest, nbytes); - return 0; } @@ -173,8 +172,8 @@ static int sig_data_offset(struct channel_header *chan_hdr, int q, } /* - * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back - * into host memory + * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into + * host memory */ #define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ visorchannel_write(channel, \ @@ -226,32 +225,25 @@ static int signalremove_inner(struct visorchannel *channel, u32 queue, error = sig_read_header(channel, queue, &sig_hdr); if (error) return error; - /* No signals to remove; have caller try again. */ if (sig_hdr.head == sig_hdr.tail) return -EAGAIN; - sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; - error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg); if (error) return error; - sig_hdr.num_received++; - /* - * For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. Required for channel sync. + * For each data field in SIGNAL_QUEUE_HEADER that was modified, update + * host memory. Required for channel sync. */ mb(); - error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail); if (error) return error; error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received); if (error) return error; - return 0; } @@ -288,13 +280,12 @@ static bool queue_empty(struct visorchannel *channel, u32 queue) if (sig_read_header(channel, queue, &sig_hdr)) return true; - return (sig_hdr.head == sig_hdr.tail); } /** - * visorchannel_signalempty() - checks if the designated channel/queue - * contains any messages + * visorchannel_signalempty() - checks if the designated channel/queue contains + * any messages * @channel: the channel to query * @queue: the queue in the channel to query * @@ -308,11 +299,9 @@ bool visorchannel_signalempty(struct visorchannel *channel, u32 queue) if (!channel->needs_lock) return queue_empty(channel, queue); - spin_lock_irqsave(&channel->remove_lock, flags); rc = queue_empty(channel, queue); spin_unlock_irqrestore(&channel->remove_lock, flags); - return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalempty); @@ -326,7 +315,6 @@ static int signalinsert_inner(struct visorchannel *channel, u32 queue, err = sig_read_header(channel, queue, &sig_hdr); if (err) return err; - sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; if (sig_hdr.head == sig_hdr.tail) { sig_hdr.num_overflows++; @@ -335,33 +323,28 @@ static int signalinsert_inner(struct visorchannel *channel, u32 queue, return err; return -EIO; } - err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); if (err) return err; - sig_hdr.num_sent++; - /* - * For each data field in SIGNAL_QUEUE_HEADER that was modified, - * update host memory. Required for channel sync. + * For each data field in SIGNAL_QUEUE_HEADER that was modified, update + * host memory. Required for channel sync. */ mb(); - err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); if (err) return err; err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); if (err) return err; - return 0; } /* - * visorchannel_create_guts() - creates the struct visorchannel abstraction - * for a data area in memory, but does NOT modify - * this data area + * visorchannel_create() - creates the struct visorchannel abstraction for a + * data area in memory, but does NOT modify this data + * area * @physaddr: physical address of start of channel * @gfp: gfp_t to use when allocating memory for the data struct * @guid: GUID that identifies channel type; @@ -372,9 +355,8 @@ static int signalinsert_inner(struct visorchannel *channel, u32 queue, * Return: pointer to visorchannel that was created if successful, * otherwise NULL */ -static struct visorchannel *visorchannel_create_guts(u64 physaddr, gfp_t gfp, - const guid_t *guid, - bool needs_lock) +struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp, + const guid_t *guid, bool needs_lock) { struct visorchannel *channel; int err; @@ -386,37 +368,30 @@ static struct visorchannel *visorchannel_create_guts(u64 physaddr, gfp_t gfp, channel = kzalloc(sizeof(*channel), gfp); if (!channel) return NULL; - channel->needs_lock = needs_lock; spin_lock_init(&channel->insert_lock); spin_lock_init(&channel->remove_lock); - /* - * Video driver constains the efi framebuffer so it will get a - * conflict resource when requesting its full mem region. Since - * we are only using the efi framebuffer for video we can ignore - * this. Remember that we haven't requested it so we don't try to - * release later on. + * Video driver constains the efi framebuffer so it will get a conflict + * resource when requesting its full mem region. Since we are only + * using the efi framebuffer for video we can ignore this. Remember that + * we haven't requested it so we don't try to release later on. */ channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME); if (!channel->requested && !guid_equal(guid, &visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; - channel->mapped = memremap(physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(physaddr, size); goto err_destroy_channel; } - channel->physaddr = physaddr; channel->nbytes = size; - err = visorchannel_read(channel, 0, &channel->chan_hdr, size); if (err) goto err_destroy_channel; size = (ulong)channel->chan_hdr.size; - memunmap(channel->mapped); if (channel->requested) release_mem_region(channel->physaddr, channel->nbytes); @@ -426,13 +401,11 @@ static struct visorchannel *visorchannel_create_guts(u64 physaddr, gfp_t gfp, if (!channel->requested && !guid_equal(guid, &visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; - channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(channel->physaddr, size); goto err_destroy_channel; } - channel->nbytes = size; guid_copy(&channel->guid, guid); return channel; @@ -442,18 +415,6 @@ err_destroy_channel: return NULL; } -struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp, - const guid_t *guid) -{ - return visorchannel_create_guts(physaddr, gfp, guid, false); -} - -struct visorchannel *visorchannel_create_with_lock(u64 physaddr, gfp_t gfp, - const guid_t *guid) -{ - return visorchannel_create_guts(physaddr, gfp, guid, true); -} - /** * visorchannel_signalinsert() - inserts a message into the designated * channel/queue diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 27ecf6fb49fd..fed554a43151 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -27,8 +27,8 @@ static const guid_t visor_vhba_channel_guid = VISOR_VHBA_CHANNEL_GUID; static const guid_t visor_siovm_guid = VISOR_SIOVM_GUID; static const guid_t visor_controlvm_channel_guid = VISOR_CONTROLVM_CHANNEL_GUID; -#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 -#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 +#define POLLJIFFIES_CONTROLVM_FAST 1 +#define POLLJIFFIES_CONTROLVM_SLOW 100 #define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128) @@ -128,7 +128,6 @@ static ssize_t toolaction_show(struct device *dev, &tool_action, sizeof(u8)); if (err) return err; - return sprintf(buf, "%u\n", tool_action); } @@ -141,7 +140,6 @@ static ssize_t toolaction_store(struct device *dev, if (kstrtou8(buf, 10, &tool_action)) return -EINVAL; - err = visorchannel_write(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, tool_action), @@ -178,7 +176,6 @@ static ssize_t boottotool_store(struct device *dev, if (kstrtoint(buf, 10, &val)) return -EINVAL; - efi_visor_indication.boot_to_tool = val; err = visorchannel_write(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, @@ -214,7 +211,6 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &error)) return -EINVAL; - err = visorchannel_write(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, installation_error), @@ -237,7 +233,6 @@ static ssize_t textid_show(struct device *dev, struct device_attribute *attr, &text_id, sizeof(u32)); if (err) return err; - return sprintf(buf, "%u\n", text_id); } @@ -249,7 +244,6 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &text_id)) return -EINVAL; - err = visorchannel_write(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, installation_text_id), @@ -272,7 +266,6 @@ static ssize_t remaining_steps_show(struct device *dev, &remaining_steps, sizeof(u16)); if (err) return err; - return sprintf(buf, "%hu\n", remaining_steps); } @@ -285,7 +278,6 @@ static ssize_t remaining_steps_store(struct device *dev, if (kstrtou16(buf, 10, &remaining_steps)) return -EINVAL; - err = visorchannel_write(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, installation_remaining_steps), @@ -296,43 +288,6 @@ static ssize_t remaining_steps_store(struct device *dev, } static DEVICE_ATTR_RW(remaining_steps); -struct visor_busdev { - u32 bus_no; - u32 dev_no; -}; - -static int match_visorbus_dev_by_id(struct device *dev, void *data) -{ - struct visor_device *vdev = to_visor_device(dev); - struct visor_busdev *id = data; - - if ((vdev->chipset_bus_no == id->bus_no) && - (vdev->chipset_dev_no == id->dev_no)) - return 1; - - return 0; -} - -struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, - struct visor_device *from) -{ - struct device *dev; - struct device *dev_start = NULL; - struct visor_device *vdev = NULL; - struct visor_busdev id = { - .bus_no = bus_no, - .dev_no = dev_no - }; - - if (from) - dev_start = &from->device; - dev = bus_find_device(&visorbus_type, dev_start, (void *)&id, - match_visorbus_dev_by_id); - if (dev) - vdev = to_visor_device(dev); - return vdev; -} - static void controlvm_init_response(struct controlvm_message *msg, struct controlvm_message_header *msg_hdr, int response) @@ -374,18 +329,13 @@ static int chipset_init(struct controlvm_message *inmsg) goto out_respond; } chipset_inited = 1; - /* * Set features to indicate we support parahotplug (if Command also - * supports it). + * supports it). Set the "reply" bit so Command knows this is a + * features-aware driver. */ features = inmsg->cmd.init_chipset.features & VISOR_CHIPSET_FEATURE_PARA_HOTPLUG; - - /* - * Set the "reply" bit so Command knows this is a features-aware - * driver. - */ features |= VISOR_CHIPSET_FEATURE_REPLY; out_respond: @@ -396,20 +346,17 @@ out_respond: } static int controlvm_respond(struct controlvm_message_header *msg_hdr, - int response, - struct visor_segment_state *state) + int response, struct visor_segment_state *state) { struct controlvm_message outmsg; controlvm_init_response(&outmsg, msg_hdr, response); if (outmsg.hdr.flags.test_message == 1) return -EINVAL; - if (state) { outmsg.cmd.device_change_state.state = *state; outmsg.cmd.device_change_state.flags.phys_device = 1; } - return visorchannel_signalinsert(chipset_dev->controlvm_channel, CONTROLVM_QUEUE_REQUEST, &outmsg); } @@ -435,13 +382,11 @@ static int save_crash_message(struct controlvm_message *msg, "failed to read message count\n"); return err; } - if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { dev_err(&chipset_dev->acpi_device->dev, "invalid number of messages\n"); return -EIO; } - err = visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, saved_crash_message_offset), @@ -451,13 +396,11 @@ static int save_crash_message(struct controlvm_message *msg, "failed to read offset\n"); return err; } - switch (cr_type) { case CRASH_DEV: local_crash_msg_offset += sizeof(struct controlvm_message); err = visorchannel_write(chipset_dev->controlvm_channel, - local_crash_msg_offset, - msg, + local_crash_msg_offset, msg, sizeof(struct controlvm_message)); if (err) { dev_err(&chipset_dev->acpi_device->dev, @@ -467,8 +410,7 @@ static int save_crash_message(struct controlvm_message *msg, break; case CRASH_BUS: err = visorchannel_write(chipset_dev->controlvm_channel, - local_crash_msg_offset, - msg, + local_crash_msg_offset, msg, sizeof(struct controlvm_message)); if (err) { dev_err(&chipset_dev->acpi_device->dev, @@ -488,33 +430,25 @@ static int controlvm_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) { - if (!pending_msg_hdr) - return -EIO; - if (pending_msg_hdr->id != (u32)cmd_id) return -EINVAL; return controlvm_respond(pending_msg_hdr, response, NULL); } -static int device_changestate_responder( - enum controlvm_id cmd_id, - struct visor_device *p, int response, - struct visor_segment_state response_state) +static int device_changestate_responder(enum controlvm_id cmd_id, + struct visor_device *p, int response, + struct visor_segment_state state) { struct controlvm_message outmsg; - if (!p->pending_msg_hdr) - return -EIO; if (p->pending_msg_hdr->id != cmd_id) return -EINVAL; controlvm_init_response(&outmsg, p->pending_msg_hdr, response); - outmsg.cmd.device_change_state.bus_no = p->chipset_bus_no; outmsg.cmd.device_change_state.dev_no = p->chipset_dev_no; - outmsg.cmd.device_change_state.state = response_state; - + outmsg.cmd.device_change_state.state = state; return visorchannel_signalinsert(chipset_dev->controlvm_channel, CONTROLVM_QUEUE_REQUEST, &outmsg); } @@ -522,64 +456,55 @@ static int device_changestate_responder( static int visorbus_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - struct controlvm_message_header *pmsg_hdr = NULL; + struct controlvm_message_header *pmsg_hdr; u32 bus_no = cmd->create_bus.bus_no; struct visor_device *bus_info; struct visorchannel *visorchannel; int err; bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); - if (bus_info && (bus_info->state.created == 1)) { + if (bus_info && bus_info->state.created == 1) { dev_err(&chipset_dev->acpi_device->dev, "failed %s: already exists\n", __func__); err = -EEXIST; goto err_respond; } - bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); if (!bus_info) { err = -ENOMEM; goto err_respond; } - INIT_LIST_HEAD(&bus_info->list_all); bus_info->chipset_bus_no = bus_no; bus_info->chipset_dev_no = BUS_ROOT_DEVICE; - if (guid_equal(&cmd->create_bus.bus_inst_guid, &visor_siovm_guid)) { err = save_crash_message(inmsg, CRASH_BUS); if (err) goto err_free_bus_info; } - if (inmsg->hdr.flags.response_expected == 1) { - pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), - GFP_KERNEL); + pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { err = -ENOMEM; goto err_free_bus_info; } - memcpy(pmsg_hdr, &inmsg->hdr, sizeof(struct controlvm_message_header)); bus_info->pending_msg_hdr = pmsg_hdr; } - visorchannel = visorchannel_create(cmd->create_bus.channel_addr, GFP_KERNEL, - &cmd->create_bus.bus_data_type_guid); + &cmd->create_bus.bus_data_type_guid, + false); if (!visorchannel) { err = -ENOMEM; goto err_free_pending_msg; } - bus_info->visorchannel = visorchannel; - /* Response will be handled by visorbus_create_instance on success */ err = visorbus_create_instance(bus_info); if (err) goto err_destroy_channel; - return 0; err_destroy_channel: @@ -599,9 +524,8 @@ err_respond: static int visorbus_destroy(struct controlvm_message *inmsg) { - struct controlvm_message_packet *cmd = &inmsg->cmd; - struct controlvm_message_header *pmsg_hdr = NULL; - u32 bus_no = cmd->destroy_bus.bus_no; + struct controlvm_message_header *pmsg_hdr; + u32 bus_no = inmsg->cmd.destroy_bus.bus_no; struct visor_device *bus_info; int err; @@ -625,12 +549,10 @@ static int visorbus_destroy(struct controlvm_message *inmsg) err = -ENOMEM; goto err_respond; } - memcpy(pmsg_hdr, &inmsg->hdr, sizeof(struct controlvm_message_header)); bus_info->pending_msg_hdr = pmsg_hdr; } - /* Response will be handled by visorbus_remove_instance */ visorbus_remove_instance(bus_info); return 0; @@ -646,51 +568,33 @@ static const guid_t *parser_id_get(struct parser_context *ctx) return &ctx->data.id; } -static void *parser_string_get(struct parser_context *ctx) +static void *parser_string_get(u8 *pscan, int nscan) { - u8 *pscan; - unsigned long nscan; int value_length; void *value; - int i; - pscan = ctx->curr; - if (!pscan) - return NULL; - nscan = ctx->bytes_remaining; if (nscan == 0) return NULL; - for (i = 0, value_length = -1; i < nscan; i++) - if (pscan[i] == '\0') { - value_length = i; - break; - } - /* '\0' was not included in the length */ - if (value_length < 0) - value_length = nscan; - - value = kmalloc(value_length + 1, GFP_KERNEL); + value_length = strnlen(pscan, nscan); + value = kzalloc(value_length + 1, GFP_KERNEL); if (!value) return NULL; if (value_length > 0) memcpy(value, pscan, value_length); - ((u8 *)(value))[value_length] = '\0'; return value; } static void *parser_name_get(struct parser_context *ctx) { - struct visor_controlvm_parameters_header *phdr = NULL; + struct visor_controlvm_parameters_header *phdr; phdr = &ctx->data; - if (phdr->name_offset + phdr->name_length > ctx->param_bytes) return NULL; - ctx->curr = (char *)&phdr + phdr->name_offset; ctx->bytes_remaining = phdr->name_length; - return parser_string_get(ctx); + return parser_string_get(ctx->curr, phdr->name_length); } static int visorbus_configure(struct controlvm_message *inmsg, @@ -715,20 +619,16 @@ static int visorbus_configure(struct controlvm_message *inmsg, err = -EIO; goto err_respond; } - - err = visorchannel_set_clientpartition - (bus_info->visorchannel, - cmd->configure_bus.guest_handle); + err = visorchannel_set_clientpartition(bus_info->visorchannel, + cmd->configure_bus.guest_handle); if (err) goto err_respond; - if (parser_ctx) { const guid_t *partition_guid = parser_id_get(parser_ctx); guid_copy(&bus_info->partition_guid, partition_guid); bus_info->name = parser_name_get(parser_ctx); } - if (inmsg->hdr.flags.response_expected == 1) controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return 0; @@ -744,10 +644,10 @@ err_respond: static int visorbus_device_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - struct controlvm_message_header *pmsg_hdr = NULL; + struct controlvm_message_header *pmsg_hdr; u32 bus_no = cmd->create_device.bus_no; u32 dev_no = cmd->create_device.dev_no; - struct visor_device *dev_info = NULL; + struct visor_device *dev_info; struct visor_device *bus_info; struct visorchannel *visorchannel; int err; @@ -765,9 +665,8 @@ static int visorbus_device_create(struct controlvm_message *inmsg) err = -EINVAL; goto err_respond; } - dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL); - if (dev_info && (dev_info->state.created == 1)) { + if (dev_info && dev_info->state.created == 1) { dev_err(&chipset_dev->acpi_device->dev, "failed to get bus by id: %d/%d\n", bus_no, dev_no); err = -EEXIST; @@ -779,16 +678,14 @@ static int visorbus_device_create(struct controlvm_message *inmsg) err = -ENOMEM; goto err_respond; } - dev_info->chipset_bus_no = bus_no; dev_info->chipset_dev_no = dev_no; guid_copy(&dev_info->inst, &cmd->create_device.dev_inst_guid); dev_info->device.parent = &bus_info->device; - - visorchannel = - visorchannel_create_with_lock(cmd->create_device.channel_addr, - GFP_KERNEL, - &cmd->create_device.data_type_guid); + visorchannel = visorchannel_create(cmd->create_device.channel_addr, + GFP_KERNEL, + &cmd->create_device.data_type_guid, + true); if (!visorchannel) { dev_err(&chipset_dev->acpi_device->dev, "failed to create visorchannel: %d/%d\n", @@ -797,20 +694,20 @@ static int visorbus_device_create(struct controlvm_message *inmsg) goto err_free_dev_info; } dev_info->visorchannel = visorchannel; - guid_copy(&dev_info->channel_type_guid, &cmd->create_device.data_type_guid); - if (guid_equal(&cmd->create_device.data_type_guid, &visor_vhba_channel_guid)) { + guid_copy(&dev_info->channel_type_guid, + &cmd->create_device.data_type_guid); + if (guid_equal(&cmd->create_device.data_type_guid, + &visor_vhba_channel_guid)) { err = save_crash_message(inmsg, CRASH_DEV); if (err) goto err_destroy_visorchannel; } - if (inmsg->hdr.flags.response_expected == 1) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { err = -ENOMEM; goto err_destroy_visorchannel; } - memcpy(pmsg_hdr, &inmsg->hdr, sizeof(struct controlvm_message_header)); dev_info->pending_msg_hdr = pmsg_hdr; @@ -837,7 +734,7 @@ err_respond: static int visorbus_device_changestate(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - struct controlvm_message_header *pmsg_hdr = NULL; + struct controlvm_message_header *pmsg_hdr; u32 bus_no = cmd->device_change_state.bus_no; u32 dev_no = cmd->device_change_state.dev_no; struct visor_segment_state state = cmd->device_change_state.state; @@ -858,18 +755,17 @@ static int visorbus_device_changestate(struct controlvm_message *inmsg) err = -EIO; goto err_respond; } + if (inmsg->hdr.flags.response_expected == 1) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { err = -ENOMEM; goto err_respond; } - memcpy(pmsg_hdr, &inmsg->hdr, sizeof(struct controlvm_message_header)); dev_info->pending_msg_hdr = pmsg_hdr; } - if (state.alive == segment_state_running.alive && state.operating == segment_state_running.operating) /* Response will be sent from visorchipset_device_resume */ @@ -884,7 +780,6 @@ static int visorbus_device_changestate(struct controlvm_message *inmsg) err = visorchipset_device_pause(dev_info); if (err) goto err_respond; - return 0; err_respond: @@ -897,7 +792,7 @@ err_respond: static int visorbus_device_destroy(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; - struct controlvm_message_header *pmsg_hdr = NULL; + struct controlvm_message_header *pmsg_hdr; u32 bus_no = cmd->destroy_device.bus_no; u32 dev_no = cmd->destroy_device.dev_no; struct visor_device *dev_info; @@ -928,7 +823,6 @@ static int visorbus_device_destroy(struct controlvm_message *inmsg) sizeof(struct controlvm_message_header)); dev_info->pending_msg_hdr = pmsg_hdr; } - kfree(dev_info->name); remove_visor_device(dev_info); return 0; @@ -995,11 +889,9 @@ static struct parahotplug_request *parahotplug_request_create( req = kmalloc(sizeof(*req), GFP_KERNEL); if (!req) return NULL; - req->id = parahotplug_next_id(); req->expiration = parahotplug_next_expiration(); req->msg = *msg; - return req; } @@ -1031,13 +923,12 @@ static int parahotplug_request_complete(int id, u16 active) { struct list_head *pos; struct list_head *tmp; + struct parahotplug_request *req; spin_lock(¶hotplug_request_list_lock); - /* Look for a request matching "id". */ list_for_each_safe(pos, tmp, ¶hotplug_request_list) { - struct parahotplug_request *req = - list_entry(pos, struct parahotplug_request, list); + req = list_entry(pos, struct parahotplug_request, list); if (req->id == id) { /* * Found a match. Remove it from the list and @@ -1054,7 +945,6 @@ static int parahotplug_request_complete(int id, u16 active) return 0; } } - spin_unlock(¶hotplug_request_list_lock); return -EINVAL; } @@ -1081,7 +971,6 @@ static ssize_t devicedisabled_store(struct device *dev, if (kstrtouint(buf, 10, &id)) return -EINVAL; - err = parahotplug_request_complete(id, 0); if (err < 0) return err; @@ -1110,7 +999,6 @@ static ssize_t deviceenabled_store(struct device *dev, if (kstrtouint(buf, 10, &id)) return -EINVAL; - parahotplug_request_complete(id, 1); return count; } @@ -1158,9 +1046,9 @@ static int parahotplug_request_kickoff(struct parahotplug_request *req) { struct controlvm_message_packet *cmd = &req->msg.cmd; char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40], - env_func[40]; - char *envp[] = { - env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL + env_func[40]; + char *envp[] = { env_cmd, env_id, env_state, env_bus, env_dev, + env_func, NULL }; sprintf(env_cmd, "VISOR_PARAHOTPLUG=1"); @@ -1173,7 +1061,6 @@ static int parahotplug_request_kickoff(struct parahotplug_request *req) cmd->device_change_state.dev_no >> 3); sprintf(env_func, "VISOR_PARAHOTPLUG_FUNCTION=%d", cmd->device_change_state.dev_no & 0x7); - return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj, KOBJ_CHANGE, envp); } @@ -1191,7 +1078,6 @@ static int parahotplug_process_message(struct controlvm_message *inmsg) req = parahotplug_request_create(inmsg); if (!req) return -ENOMEM; - /* * For enable messages, just respond with success right away, we don't * need to wait to see if the enable was successful. @@ -1205,7 +1091,6 @@ static int parahotplug_process_message(struct controlvm_message *inmsg) parahotplug_request_destroy(req); return 0; } - /* * For disable messages, add the request to the request list before * kicking off the udev script. It won't get responded to until the @@ -1214,7 +1099,6 @@ static int parahotplug_process_message(struct controlvm_message *inmsg) spin_lock(¶hotplug_request_list_lock); list_add_tail(&req->list, ¶hotplug_request_list); spin_unlock(¶hotplug_request_list_lock); - err = parahotplug_request_kickoff(req); if (err) goto err_respond; @@ -1237,12 +1121,9 @@ static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr) { int res; - res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, - KOBJ_ONLINE); - + res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, KOBJ_ONLINE); if (msg_hdr->flags.response_expected) controlvm_respond(msg_hdr, res, NULL); - return res; } @@ -1262,10 +1143,8 @@ static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr) sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); res = kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj, KOBJ_CHANGE, envp); - if (msg_hdr->flags.response_expected) controlvm_respond(msg_hdr, res, NULL); - return res; } @@ -1279,11 +1158,10 @@ static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr) static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr) { int res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, - KOBJ_OFFLINE); + KOBJ_OFFLINE); if (msg_hdr->flags.response_expected) controlvm_respond(msg_hdr, res, NULL); - return res; } @@ -1296,17 +1174,15 @@ static int unisys_vmcall(unsigned long tuple, unsigned long param) reg_ebx = param & 0xFFFFFFFF; reg_ecx = param >> 32; - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); if (!(cpuid_ecx & 0x80000000)) return -EPERM; - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); if (result) goto error; - return 0; + /* Need to convert from VMCALL error codes to Linux */ error: switch (result) { @@ -1330,8 +1206,8 @@ static int controlvm_channel_create(struct visorchipset_device *dev) if (err) return err; addr = dev->controlvm_params.address; - chan = visorchannel_create_with_lock(addr, GFP_KERNEL, - &visor_controlvm_channel_guid); + chan = visorchannel_create(addr, GFP_KERNEL, + &visor_controlvm_channel_guid, true); if (!chan) return -ENOMEM; dev->controlvm_channel = chan; @@ -1350,9 +1226,7 @@ static void setup_crash_devices_work_queue(struct work_struct *work) msg.hdr.id = CONTROLVM_CHIPSET_INIT; msg.cmd.init_chipset.bus_count = 23; msg.cmd.init_chipset.switch_count = 0; - chipset_init(&msg); - /* get saved message count */ if (visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, @@ -1362,13 +1236,10 @@ static void setup_crash_devices_work_queue(struct work_struct *work) "failed to read channel\n"); return; } - if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { - dev_err(&chipset_dev->acpi_device->dev, - "invalid count\n"); + dev_err(&chipset_dev->acpi_device->dev, "invalid count\n"); return; } - /* get saved crash message offset */ if (visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct visor_controlvm_channel, @@ -1378,7 +1249,6 @@ static void setup_crash_devices_work_queue(struct work_struct *work) "failed to read channel\n"); return; } - /* read create device message for storage bus offset */ if (visorchannel_read(chipset_dev->controlvm_channel, local_crash_msg_offset, @@ -1388,7 +1258,6 @@ static void setup_crash_devices_work_queue(struct work_struct *work) "failed to read channel\n"); return; } - /* read create device message for storage device */ if (visorchannel_read(chipset_dev->controlvm_channel, local_crash_msg_offset + @@ -1399,7 +1268,6 @@ static void setup_crash_devices_work_queue(struct work_struct *work) "failed to read channel\n"); return; } - /* reuse IOVM create bus message */ if (!local_crash_bus_msg.cmd.create_bus.channel_addr) { dev_err(&chipset_dev->acpi_device->dev, @@ -1407,7 +1275,6 @@ static void setup_crash_devices_work_queue(struct work_struct *work) return; } visorbus_create(&local_crash_bus_msg); - /* reuse create device message for storage device */ if (!local_crash_dev_msg.cmd.create_device.channel_addr) { dev_err(&chipset_dev->acpi_device->dev, @@ -1420,8 +1287,10 @@ static void setup_crash_devices_work_queue(struct work_struct *work) void visorbus_response(struct visor_device *bus_info, int response, int controlvm_id) { - controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response); + if (!bus_info->pending_msg_hdr) + return; + controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response); kfree(bus_info->pending_msg_hdr); bus_info->pending_msg_hdr = NULL; } @@ -1430,9 +1299,11 @@ void visorbus_device_changestate_response(struct visor_device *dev_info, int response, struct visor_segment_state state) { - device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, - dev_info, response, state); + if (!dev_info->pending_msg_hdr) + return; + device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info, + response, state); kfree(dev_info->pending_msg_hdr); dev_info->pending_msg_hdr = NULL; } @@ -1451,12 +1322,11 @@ static struct parser_context *parser_init_stream(u64 addr, u32 bytes, void *mapping; *retry = false; - /* alloc an extra byte to ensure payload is \0 terminated */ allocbytes = bytes + 1 + (sizeof(struct parser_context) - sizeof(struct visor_controlvm_parameters_header)); - if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) - > MAX_CONTROLVM_PAYLOAD_BYTES) { + if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) > + MAX_CONTROLVM_PAYLOAD_BYTES) { *retry = true; return NULL; } @@ -1465,7 +1335,6 @@ static struct parser_context *parser_init_stream(u64 addr, u32 bytes, *retry = true; return NULL; } - ctx->allocbytes = allocbytes; ctx->param_bytes = bytes; mapping = memremap(addr, bytes, MEMREMAP_WB); @@ -1475,7 +1344,6 @@ static struct parser_context *parser_init_stream(u64 addr, u32 bytes, memunmap(mapping); ctx->byte_stream = true; chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes; - return ctx; err_finish_ctx: @@ -1508,14 +1376,13 @@ static int handle_command(struct controlvm_message inmsg, u64 channel_addr) /* create parsing context if necessary */ parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_bytes = inmsg.hdr.payload_bytes; - /* * Parameter and channel addresses within test messages actually lie * within our OS-controlled memory. We need to know that, because it * makes a difference in how we compute the virtual address. */ if (parm_bytes) { - bool retry = false; + bool retry; parser_ctx = parser_init_stream(parm_addr, parm_bytes, &retry); if (!parser_ctx && retry) @@ -1526,7 +1393,6 @@ static int handle_command(struct controlvm_message inmsg, u64 channel_addr) CONTROLVM_QUEUE_ACK, &ackmsg); if (err) return err; - switch (inmsg.hdr.id) { case CONTROLVM_CHIPSET_INIT: err = chipset_init(&inmsg); @@ -1580,7 +1446,6 @@ static int handle_command(struct controlvm_message inmsg, u64 channel_addr) -CONTROLVM_RESP_ID_UNKNOWN, NULL); break; } - if (parser_ctx) { parser_done(parser_ctx); parser_ctx = NULL; @@ -1599,14 +1464,13 @@ static int handle_command(struct controlvm_message inmsg, u64 channel_addr) static int read_controlvm_event(struct controlvm_message *msg) { int err = visorchannel_signalremove(chipset_dev->controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg); + CONTROLVM_QUEUE_EVENT, msg); + if (err) return err; - /* got a message */ if (msg->hdr.flags.test_message == 1) return -EINVAL; - return 0; } @@ -1620,14 +1484,12 @@ static void parahotplug_process_list(void) struct list_head *tmp; spin_lock(¶hotplug_request_list_lock); - list_for_each_safe(pos, tmp, ¶hotplug_request_list) { struct parahotplug_request *req = list_entry(pos, struct parahotplug_request, list); if (!time_after_eq(jiffies, req->expiration)) continue; - list_del(pos); if (req->msg.hdr.flags.response_expected) controlvm_respond( @@ -1636,7 +1498,6 @@ static void parahotplug_process_list(void) &req->msg.cmd.device_change_state.state); parahotplug_request_destroy(req); } - spin_unlock(¶hotplug_request_list_lock); } @@ -1652,10 +1513,8 @@ static void controlvm_periodic_work(struct work_struct *work) CONTROLVM_QUEUE_RESPONSE, &inmsg); } while ((!err) && (++count < CONTROLVM_MESSAGE_MAX)); - if (err != -EAGAIN) goto schedule_out; - if (chipset_dev->controlvm_pending_msg_valid) { /* * we throttled processing of a prior msg, so try to process @@ -1667,7 +1526,6 @@ static void controlvm_periodic_work(struct work_struct *work) } else { err = read_controlvm_event(&inmsg); } - while (!err) { chipset_dev->most_recent_message_jiffies = jiffies; err = handle_command(inmsg, @@ -1681,7 +1539,6 @@ static void controlvm_periodic_work(struct work_struct *work) err = read_controlvm_event(&inmsg); } - /* parahotplug_worker */ parahotplug_process_list(); @@ -1697,17 +1554,12 @@ schedule_out: * it's been longer than MIN_IDLE_SECONDS since we processed * our last controlvm message; slow down the polling */ - if (chipset_dev->poll_jiffies != - POLLJIFFIES_CONTROLVMCHANNEL_SLOW) - chipset_dev->poll_jiffies = - POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_SLOW) + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_SLOW; } else { - if (chipset_dev->poll_jiffies != - POLLJIFFIES_CONTROLVMCHANNEL_FAST) - chipset_dev->poll_jiffies = - POLLJIFFIES_CONTROLVMCHANNEL_FAST; + if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_FAST) + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST; } - schedule_delayed_work(&chipset_dev->periodic_controlvm_work, chipset_dev->poll_jiffies); } @@ -1720,20 +1572,16 @@ static int visorchipset_init(struct acpi_device *acpi_device) chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL); if (!chipset_dev) goto error; - err = controlvm_channel_create(chipset_dev); if (err) goto error_free_chipset_dev; - acpi_device->driver_data = chipset_dev; chipset_dev->acpi_device = acpi_device; - chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST; err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj, visorchipset_dev_groups); if (err < 0) goto error_destroy_channel; - controlvm_channel = chipset_dev->controlvm_channel; if (!visor_check_channel(visorchannel_get_header(controlvm_channel), &chipset_dev->acpi_device->dev, @@ -1743,7 +1591,6 @@ static int visorchipset_init(struct acpi_device *acpi_device) VISOR_CONTROLVM_CHANNEL_VERSIONID, VISOR_CHANNEL_SIGNATURE)) goto error_delete_groups; - /* if booting in a crash kernel */ if (is_kdump_kernel()) INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, @@ -1751,16 +1598,13 @@ static int visorchipset_init(struct acpi_device *acpi_device) else INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, controlvm_periodic_work); - chipset_dev->most_recent_message_jiffies = jiffies; - chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST; schedule_delayed_work(&chipset_dev->periodic_controlvm_work, chipset_dev->poll_jiffies); - err = visorbus_init(); if (err < 0) goto error_cancel_work; - return 0; error_cancel_work: @@ -1787,10 +1631,8 @@ static int visorchipset_exit(struct acpi_device *acpi_device) cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work); sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj, visorchipset_dev_groups); - visorchannel_destroy(chipset_dev->controlvm_channel); kfree(chipset_dev); - return 0; } @@ -1832,11 +1674,9 @@ static int __init init_unisys(void) if (!visorutil_spar_detect()) return -ENODEV; - result = acpi_bus_register_driver(&unisys_acpi_driver); if (result) return -ENODEV; - pr_info("Unisys Visorchipset Driver Loaded.\n"); return 0; }; |