From 863981e96738983919de841ec669e157e6bdaeb0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Sun, 11 Sep 2016 04:34:46 -0300 Subject: Linux-libre 4.7.1-gnu --- drivers/staging/unisys/visorbus/visorbus_main.c | 394 ++++++------------------ 1 file changed, 91 insertions(+), 303 deletions(-) (limited to 'drivers/staging/unisys/visorbus/visorbus_main.c') diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 533bb5b3d..3a147dbbd 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -33,6 +33,9 @@ static int visorbus_forcenomatch; static int visorbus_debugref; #define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024) +/* Display string that is guaranteed to be no longer the 99 characters*/ +#define LINESIZE 99 + #define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c #define POLLJIFFIES_TESTWORK 100 #define POLLJIFFIES_NORMALCHANNEL 10 @@ -182,7 +185,6 @@ static int visorbus_match(struct device *xdev, struct device_driver *xdrv) { uuid_le channel_type; - int rc = 0; int i; struct visor_device *dev; struct visor_driver *drv; @@ -190,26 +192,23 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) dev = to_visor_device(xdev); drv = to_visor_driver(xdrv); channel_type = visorchannel_get_uuid(dev->visorchannel); - if (visorbus_forcematch) { - rc = 1; - goto away; - } - if (visorbus_forcenomatch) - goto away; + if (visorbus_forcematch) + return 1; + if (visorbus_forcenomatch) + return 0; if (!drv->channel_types) - goto away; + return 0; + for (i = 0; (uuid_le_cmp(drv->channel_types[i].guid, NULL_UUID_LE) != 0) || (drv->channel_types[i].name); i++) if (uuid_le_cmp(drv->channel_types[i].guid, - channel_type) == 0) { - rc = i + 1; - goto away; - } -away: - return rc; + channel_type) == 0) + return i + 1; + + return 0; } /** This is called when device_unregister() is called for the bus device @@ -243,180 +242,6 @@ visorbus_release_device(struct device *xdev) kfree(dev); } -/* Implement publishing of device node attributes under: - * - * /sys/bus/visorbus/dev/devmajorminor - * - */ - -#define to_devmajorminor_attr(_attr) \ - container_of(_attr, struct devmajorminor_attribute, attr) -#define to_visor_device_from_kobjdevmajorminor(obj) \ - container_of(obj, struct visor_device, kobjdevmajorminor) - -struct devmajorminor_attribute { - struct attribute attr; - int slot; - ssize_t (*show)(struct visor_device *, int slot, char *buf); - ssize_t (*store)(struct visor_device *, int slot, const char *buf, - size_t count); -}; - -static ssize_t DEVMAJORMINOR_ATTR(struct visor_device *dev, int slot, char *buf) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - - if (slot < 0 || slot >= maxdevnodes) - return 0; - return snprintf(buf, PAGE_SIZE, "%d:%d\n", - dev->devnodes[slot].major, dev->devnodes[slot].minor); -} - -static ssize_t -devmajorminor_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct devmajorminor_attribute *devmajorminor_attr = - to_devmajorminor_attr(attr); - struct visor_device *dev = to_visor_device_from_kobjdevmajorminor(kobj); - ssize_t ret = 0; - - if (devmajorminor_attr->show) - ret = devmajorminor_attr->show(dev, - devmajorminor_attr->slot, buf); - return ret; -} - -static ssize_t -devmajorminor_attr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t count) -{ - struct devmajorminor_attribute *devmajorminor_attr = - to_devmajorminor_attr(attr); - struct visor_device *dev = to_visor_device_from_kobjdevmajorminor(kobj); - ssize_t ret = 0; - - if (devmajorminor_attr->store) - ret = devmajorminor_attr->store(dev, - devmajorminor_attr->slot, - buf, count); - return ret; -} - -static int register_devmajorminor_attributes(struct visor_device *dev); - -static int -devmajorminor_create_file(struct visor_device *dev, const char *name, - int major, int minor) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - struct devmajorminor_attribute *myattr = NULL; - int x = -1, rc = 0, slot = -1; - - register_devmajorminor_attributes(dev); - for (slot = 0; slot < maxdevnodes; slot++) - if (!dev->devnodes[slot].attr) - break; - if (slot == maxdevnodes) { - rc = -ENOMEM; - goto away; - } - myattr = kzalloc(sizeof(*myattr), GFP_KERNEL); - if (!myattr) { - rc = -ENOMEM; - goto away; - } - myattr->show = DEVMAJORMINOR_ATTR; - myattr->store = NULL; - myattr->slot = slot; - myattr->attr.name = name; - myattr->attr.mode = S_IRUGO; - dev->devnodes[slot].attr = myattr; - dev->devnodes[slot].major = major; - dev->devnodes[slot].minor = minor; - x = sysfs_create_file(&dev->kobjdevmajorminor, &myattr->attr); - if (x < 0) { - rc = x; - goto away; - } - kobject_uevent(&dev->device.kobj, KOBJ_ONLINE); -away: - if (rc < 0) { - kfree(myattr); - myattr = NULL; - dev->devnodes[slot].attr = NULL; - } - return rc; -} - -static void -devmajorminor_remove_file(struct visor_device *dev, int slot) -{ - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - struct devmajorminor_attribute *myattr = NULL; - - if (slot < 0 || slot >= maxdevnodes) - return; - myattr = (struct devmajorminor_attribute *)(dev->devnodes[slot].attr); - if (!myattr) - return; - sysfs_remove_file(&dev->kobjdevmajorminor, &myattr->attr); - kobject_uevent(&dev->device.kobj, KOBJ_OFFLINE); - dev->devnodes[slot].attr = NULL; - kfree(myattr); -} - -static void -devmajorminor_remove_all_files(struct visor_device *dev) -{ - int i = 0; - int maxdevnodes = ARRAY_SIZE(dev->devnodes) / sizeof(dev->devnodes[0]); - - for (i = 0; i < maxdevnodes; i++) - devmajorminor_remove_file(dev, i); -} - -static const struct sysfs_ops devmajorminor_sysfs_ops = { - .show = devmajorminor_attr_show, - .store = devmajorminor_attr_store, -}; - -static struct kobj_type devmajorminor_kobj_type = { - .sysfs_ops = &devmajorminor_sysfs_ops -}; - -static int -register_devmajorminor_attributes(struct visor_device *dev) -{ - int rc = 0, x = 0; - - if (dev->kobjdevmajorminor.parent) - goto away; /* already registered */ - x = kobject_init_and_add(&dev->kobjdevmajorminor, - &devmajorminor_kobj_type, &dev->device.kobj, - "devmajorminor"); - if (x < 0) { - rc = x; - goto away; - } - - kobject_uevent(&dev->kobjdevmajorminor, KOBJ_ADD); - -away: - return rc; -} - -static void -unregister_devmajorminor_attributes(struct visor_device *dev) -{ - if (!dev->kobjdevmajorminor.parent) - return; /* already unregistered */ - devmajorminor_remove_all_files(dev); - - kobject_del(&dev->kobjdevmajorminor); - kobject_put(&dev->kobjdevmajorminor); - dev->kobjdevmajorminor.parent = NULL; -} - /* begin implementation of specific channel attributes to appear under * /sys/bus/visorbus/dev/channel */ @@ -427,7 +252,7 @@ static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr, if (!vdev->visorchannel) return 0; - return snprintf(buf, PAGE_SIZE, "0x%Lx\n", + return snprintf(buf, PAGE_SIZE, "0x%llx\n", visorchannel_get_physaddr(vdev->visorchannel)); } @@ -449,7 +274,7 @@ static ssize_t clientpartition_show(struct device *dev, if (!vdev->visorchannel) return 0; - return snprintf(buf, PAGE_SIZE, "0x%Lx\n", + return snprintf(buf, PAGE_SIZE, "0x%llx\n", visorchannel_get_clientpartition(vdev->visorchannel)); } @@ -457,24 +282,24 @@ static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); - char s[99]; + char typeid[LINESIZE]; if (!vdev->visorchannel) return 0; return snprintf(buf, PAGE_SIZE, "%s\n", - visorchannel_id(vdev->visorchannel, s)); + visorchannel_id(vdev->visorchannel, typeid)); } static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct visor_device *vdev = to_visor_device(dev); - char s[99]; + char zoneid[LINESIZE]; if (!vdev->visorchannel) return 0; return snprintf(buf, PAGE_SIZE, "%s\n", - visorchannel_zoneid(vdev->visorchannel, s)); + visorchannel_zoneid(vdev->visorchannel, zoneid)); } static ssize_t typename_show(struct device *dev, struct device_attribute *attr, @@ -541,7 +366,7 @@ static ssize_t partition_handle_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); u64 handle = visorchannel_get_clientpartition(vdev->visorchannel); - return snprintf(buf, PAGE_SIZE, "0x%Lx\n", handle); + return snprintf(buf, PAGE_SIZE, "0x%llx\n", handle); } static ssize_t partition_guid_show(struct device *dev, @@ -566,7 +391,7 @@ static ssize_t channel_addr_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); u64 addr = visorchannel_get_physaddr(vdev->visorchannel); - return snprintf(buf, PAGE_SIZE, "0x%Lx\n", addr); + return snprintf(buf, PAGE_SIZE, "0x%llx\n", addr); } static ssize_t channel_bytes_show(struct device *dev, @@ -575,7 +400,7 @@ static ssize_t channel_bytes_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); u64 nbytes = visorchannel_get_nbytes(vdev->visorchannel); - return snprintf(buf, PAGE_SIZE, "0x%Lx\n", nbytes); + return snprintf(buf, PAGE_SIZE, "0x%llx\n", nbytes); } static ssize_t channel_id_show(struct device *dev, @@ -598,9 +423,9 @@ static ssize_t client_bus_info_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); struct visorchannel *channel = vdev->visorchannel; - int i, x, remain = PAGE_SIZE; + int i, shift, remain = PAGE_SIZE; unsigned long off; - char *p = buf; + char *pos = buf; u8 *partition_name; struct ultra_vbus_deviceinfo dev_info; @@ -608,44 +433,45 @@ static ssize_t client_bus_info_show(struct device *dev, if (channel) { if (vdev->name) partition_name = vdev->name; - x = snprintf(p, remain, - "Client device / client driver info for %s partition (vbus #%d):\n", - partition_name, vdev->chipset_dev_no); - p += x; - remain -= x; - x = visorchannel_read(channel, - offsetof(struct - spar_vbus_channel_protocol, - chp_info), - &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, p, - remain, -1); - p += x; - remain -= x; + shift = snprintf(pos, remain, + "Client device / client driver info for %s eartition (vbus #%d):\n", + partition_name, vdev->chipset_dev_no); + pos += shift; + remain -= shift; + shift = visorchannel_read(channel, + offsetof(struct + spar_vbus_channel_protocol, + chp_info), + &dev_info, sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string(&dev_info, pos, + remain, -1); + pos += shift; + remain -= shift; } - x = visorchannel_read(channel, - offsetof(struct - spar_vbus_channel_protocol, - bus_info), - &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string(&dev_info, p, - remain, -1); - p += x; - remain -= x; + shift = visorchannel_read(channel, + offsetof(struct + spar_vbus_channel_protocol, + bus_info), + &dev_info, sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string(&dev_info, pos, + remain, -1); + pos += shift; + remain -= shift; } off = offsetof(struct spar_vbus_channel_protocol, dev_info); i = 0; while (off + sizeof(dev_info) <= visorchannel_get_nbytes(channel)) { - x = visorchannel_read(channel, - off, &dev_info, sizeof(dev_info)); - if (x >= 0) { - x = vbuschannel_devinfo_to_string - (&dev_info, p, remain, i); - p += x; - remain -= x; + shift = visorchannel_read(channel, + off, &dev_info, + sizeof(dev_info)); + if (shift >= 0) { + shift = vbuschannel_devinfo_to_string + (&dev_info, pos, remain, i); + pos += shift; + remain -= shift; } off += sizeof(dev_info); i++; @@ -752,36 +578,28 @@ dev_stop_periodic_work(struct visor_device *dev) static int visordriver_probe_device(struct device *xdev) { - int rc; + int res; struct visor_driver *drv; struct visor_device *dev; drv = to_visor_driver(xdev->driver); dev = to_visor_device(xdev); + + if (!drv->probe) + return -ENODEV; + down(&dev->visordriver_callback_lock); dev->being_removed = false; - /* - * ensure that the dev->being_removed flag is cleared before - * we start the probe - */ - wmb(); - get_device(&dev->device); - if (!drv->probe) { - up(&dev->visordriver_callback_lock); - rc = -ENODEV; - goto away; + + res = drv->probe(dev); + if (res >= 0) { + /* success: reference kept via unmatched get_device() */ + get_device(&dev->device); + fix_vbus_dev_info(dev); } - rc = drv->probe(dev); - if (rc < 0) - goto away; - fix_vbus_dev_info(dev); up(&dev->visordriver_callback_lock); - rc = 0; -away: - if (rc != 0) - put_device(&dev->device); - return rc; + return res; } /** This is called when device_unregister() is called for each child device @@ -798,21 +616,12 @@ visordriver_remove_device(struct device *xdev) drv = to_visor_driver(xdev->driver); down(&dev->visordriver_callback_lock); dev->being_removed = true; - /* - * ensure that the dev->being_removed flag is set before we start the - * actual removal - */ - wmb(); - if (drv) { - if (drv->remove) - drv->remove(dev); - } + if (drv->remove) + drv->remove(dev); up(&dev->visordriver_callback_lock); dev_stop_periodic_work(dev); - devmajorminor_remove_all_files(dev); put_device(&dev->device); - return 0; } @@ -928,14 +737,6 @@ visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, } EXPORT_SYMBOL_GPL(visorbus_clear_channel); -int -visorbus_registerdevnode(struct visor_device *dev, - const char *name, int major, int minor) -{ - return devmajorminor_create_file(dev, name, major, minor); -} -EXPORT_SYMBOL_GPL(visorbus_registerdevnode); - /** We don't really have a real interrupt, so for now we just call the * interrupt function periodically... */ @@ -970,7 +771,7 @@ EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); static int create_visor_device(struct visor_device *dev) { - int rc; + int err; u32 chipset_bus_no = dev->chipset_bus_no; u32 chipset_dev_no = dev->chipset_dev_no; @@ -992,8 +793,8 @@ create_visor_device(struct visor_device *dev) if (!dev->periodic_work) { POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no, DIAG_SEVERITY_ERR); - rc = -EINVAL; - goto away; + err = -EINVAL; + goto err_put; } /* bus_id must be a unique name with respect to this bus TYPE @@ -1019,36 +820,25 @@ create_visor_device(struct visor_device *dev) * claim the device. The device will be linked onto * bus_type.klist_devices regardless (use bus_for_each_dev). */ - rc = device_add(&dev->device); - if (rc < 0) { + err = device_add(&dev->device); + if (err < 0) { POSTCODE_LINUX_3(DEVICE_ADD_PC, chipset_bus_no, DIAG_SEVERITY_ERR); - goto away; - } - - rc = register_devmajorminor_attributes(dev); - if (rc < 0) { - POSTCODE_LINUX_3(DEVICE_REGISTER_FAILURE_PC, chipset_dev_no, - DIAG_SEVERITY_ERR); - goto away_unregister; + goto err_put; } list_add_tail(&dev->list_all, &list_all_device_instances); - return 0; - -away_unregister: - device_unregister(&dev->device); + return 0; /* success: reference kept via unmatched get_device() */ -away: +err_put: put_device(&dev->device); - return rc; + return err; } static void remove_visor_device(struct visor_device *dev) { list_del(&dev->list_all); - unregister_devmajorminor_attributes(dev); put_device(&dev->device); device_unregister(&dev->device); } @@ -1477,24 +1267,24 @@ struct channel_size_info { int visorbus_init(void) { - int rc = 0; + int err; - POSTCODE_LINUX_3(DRIVER_ENTRY_PC, rc, POSTCODE_SEVERITY_INFO); + POSTCODE_LINUX_3(DRIVER_ENTRY_PC, 0, POSTCODE_SEVERITY_INFO); bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus", VERSION, NULL); - rc = create_bus_type(); - if (rc < 0) { + err = create_bus_type(); + if (err < 0) { POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, DIAG_SEVERITY_ERR); - goto away; + goto error; } periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev"); if (!periodic_dev_workqueue) { POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR); - rc = -ENOMEM; - goto away; + err = -ENOMEM; + goto error; } /* This enables us to receive notifications when devices appear for @@ -1504,13 +1294,11 @@ visorbus_init(void) &chipset_responders, &chipset_driverinfo); - rc = 0; + return 0; -away: - if (rc) - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, - POSTCODE_SEVERITY_ERR); - return rc; +error: + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR); + return err; } void -- cgit v1.2.3-54-g00ecf