diff options
Diffstat (limited to 'drivers/staging/unisys')
-rw-r--r-- | drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset | 14 | ||||
-rw-r--r-- | drivers/staging/unisys/Documentation/overview.txt | 19 | ||||
-rw-r--r-- | drivers/staging/unisys/Documentation/proc-entries.txt | 93 | ||||
-rw-r--r-- | drivers/staging/unisys/MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/staging/unisys/include/channel.h | 10 | ||||
-rw-r--r-- | drivers/staging/unisys/include/iochannel.h | 42 | ||||
-rw-r--r-- | drivers/staging/unisys/include/visorbus.h | 127 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorbus_main.c | 394 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchannel.c | 5 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchipset.c | 444 | ||||
-rw-r--r-- | drivers/staging/unisys/visorhba/visorhba_main.c | 114 | ||||
-rw-r--r-- | drivers/staging/unisys/visorinput/visorinput.c | 24 | ||||
-rw-r--r-- | drivers/staging/unisys/visornic/visornic_main.c | 223 |
13 files changed, 502 insertions, 1008 deletions
diff --git a/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset b/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset index b0498ff32..c2359de17 100644 --- a/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset +++ b/drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset @@ -50,20 +50,6 @@ Description: This field is used to tell s-Par which type of recovery tool commission the guest. Users: sparmaintainer@unisys.com -What: guest/chipsetready -Date: 7/18/2014 -KernelVersion: TBD -Contact: sparmaintainer@unisys.com -Description: This entry is used by Unisys application software on the guest - to acknowledge completion of specific events for integration - purposes, but these acknowledgements are not required for the - guest to operate correctly. The interface accepts one of two - strings: MODULES_LOADED to indicate that the s-Par driver - modules have been loaded successfully, or CALLHOMEDISK_MOUNTED, - which indicates that the disk used to support call home services - has been successfully mounted. -Users: sparmaintainer@unisys.com - What: parahotplug/deviceenabled Date: 7/18/2014 KernelVersion: TBD diff --git a/drivers/staging/unisys/Documentation/overview.txt b/drivers/staging/unisys/Documentation/overview.txt index c2d8dd4a2..1146c1cf5 100644 --- a/drivers/staging/unisys/Documentation/overview.txt +++ b/drivers/staging/unisys/Documentation/overview.txt @@ -137,12 +137,6 @@ called automatically by the visorbus driver at appropriate times: * The resume() function is the "book-end" to pause(), and is described above. -If/when a function driver creates a Linux device (that needs to be accessed -from usermode), it calls visorbus_registerdevnode(), passing the major and -minor number of the device. (Of course not all function drivers will need -to do this.) This simply creates the appropriate "devmajorminor" sysfs entry -described below, so that a hotplug script can use it to create a device node. - 2.1.3. sysfs Advertised Information ----------------------------------- @@ -197,19 +191,6 @@ The following files exist under /sys/devices/visorbus<x>/vbus<x>:dev<y>: if the appropriate function driver has not been loaded yet. - devmajorminor - - <devname> if applicable, each file here identifies (via - ... its file contents) the - "<major>:<minor>" needed for a device node to - enable access from usermode. There is exactly - one file here for each different device node - that can be accessed (from usermode). Note - that this info is provided by a particular - function driver, so these will not exist - until AFTER the appropriate function driver - controlling this device class is loaded. - channel properties of the device channel (all in ascii text format) diff --git a/drivers/staging/unisys/Documentation/proc-entries.txt b/drivers/staging/unisys/Documentation/proc-entries.txt deleted file mode 100644 index 426f92b1c..000000000 --- a/drivers/staging/unisys/Documentation/proc-entries.txt +++ /dev/null @@ -1,93 +0,0 @@ - s-Par Proc Entries -This document describes the proc entries created by the Unisys s-Par modules. - -Support Module Entries -These entries are provided primarily for debugging. - -/proc/uislib/info: This entry contains debugging information for the -uislib module, including bus information and memory usage. - -/proc/visorchipset/controlvm: This directory contains debugging -entries for the controlvm channel used by visorchipset. - -/proc/uislib/platform: This entry is used to display the platform -number this node is in the system. For some guests, this may be -invalid. - -/proc/visorchipset/chipsetready: This entry is written to by scripts -to signify that any user level activity has been completed before the -guest can be considered running and is shown as running in the s-Par -UI. - -Device Entries -These entries provide status of the devices shared by a service partition. - -/proc/uislib/vbus: this is a directory containing entries for each -virtual bus. Each numbered sub-directory contains an info entry, which -describes the devices that appear on that bus. - -/proc/uislib/cycles_before_wait: This entry is used to tune -performance, by setting the number of cycles we wait before going idle -when in polling mode. A longer time will reduce message latency but -spend more processing time polling. - -/proc/uislib/smart_wakeup: This entry is used to tune performance, by -enabling or disabling smart wakeup. - -/proc/virthba/info: This entry contains debugging information for the -virthba module, including interrupt information and memory usage. - -/proc/virthba/enable_ints: This entry controls interrupt use by the -virthba module. Writing a 0 to this entry will disable interrupts. - -/proc/virtnic/info: This entry contains debugging information for the -virtnic module, including interrupt information, send and receive -counts, and other device information. - -/proc/virtnic/ethX: This is a directory containing entries for each -virtual NIC. Each named subdirectory contains two entries, -clientstring and zone. - -/proc/virtpci/info: This entry contains debugging information for the -virtpci module, including virtual PCI bus information and device -locations. - -/proc/virtnic/enable_ints: This entry controls interrupt use by the -virtnic module. Writing a 0 to this entry will disable interrupts. - -Visorconinclient, visordiag, visornoop, visorserialclient, and -visorvideoclient Entries - -The entries in proc for these modules all follow the same -pattern. Each module has its own proc directory with the same name, -e.g. visordiag presents a /proc/visordiag directory. Inside of the -module's directory are a device directory, which contains one numbered -directory for each device provided by that module. Each device has a -diag entry that presents the device number and visorbus name for that -device. The module directory also has a driver/diag entry, which -reports the corresponding s-Par version number of the driver. - -Automated Installation Entries - -These entries are used to pass information between the s-Par platform -and the Linux-based installation and recovery tool. These values are -read/write, however, the guest can only reset them to 0, or report an -error status through the installer entry. The values are only set via -s-Par's firmware interface, to help prevent accidentally booting into -the tool. - -/proc/visorchipset/boottotool: This entry instructs s-Par that the -next reboot will launch the installation and recovery tool. If set to -0, the next boot will happen according to the UEFI boot manager -settings. - -/proc/visorchipset/toolaction: This entry indicates the installation -and recovery tool mode requested for the next boot. - -/proc/visorchipset/installer: this entry is used by the installation -and recovery tool to pass status and result information back to the -s-Par firmware. - -/proc/visorchipset/partition: This directory contains the guest -partition configuration data for each virtual bus, for use during -installation and at runtime for s-Par service partitions. diff --git a/drivers/staging/unisys/MAINTAINERS b/drivers/staging/unisys/MAINTAINERS index cc46e37e6..1f0425bf3 100644 --- a/drivers/staging/unisys/MAINTAINERS +++ b/drivers/staging/unisys/MAINTAINERS @@ -2,5 +2,4 @@ Unisys s-Par drivers M: David Kershner <sparmaintainer@unisys.com> S: Maintained F: Documentation/s-Par/overview.txt -F: Documentation/s-Par/proc-entries.txt F: drivers/staging/unisys/ diff --git a/drivers/staging/unisys/include/channel.h b/drivers/staging/unisys/include/channel.h index 5af59a5fc..db4e6b287 100644 --- a/drivers/staging/unisys/include/channel.h +++ b/drivers/staging/unisys/include/channel.h @@ -76,9 +76,9 @@ enum channel_clientstate { }; static inline const u8 * -ULTRA_CHANNELCLI_STRING(u32 v) +ULTRA_CHANNELCLI_STRING(u32 state) { - switch (v) { + switch (state) { case CHANNELCLI_DETACHED: return (const u8 *)("DETACHED"); case CHANNELCLI_DISABLED: @@ -411,7 +411,7 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id) mb(); /* required for channel synch */ } if (readl(&hdr->cli_state_os) == CHANNELCLI_OWNED) { - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; * come out of it */ @@ -459,7 +459,7 @@ spar_channel_client_acquire_os(void __iomem *ch, u8 *id) mb(); /* required for channel synch */ return 0; } - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; come out of it */ pr_info("%s Channel OS client acquire now successful\n", id); writeb(0, &hdr->cli_error_os); @@ -472,7 +472,7 @@ spar_channel_client_release_os(void __iomem *ch, u8 *id) { struct channel_header __iomem *hdr = ch; - if (readb(&hdr->cli_error_os) != 0) { + if (readb(&hdr->cli_error_os)) { /* we are in an error msg throttling state; come out of it */ pr_info("%s Channel OS client error state cleared\n", id); writeb(0, &hdr->cli_error_os); diff --git a/drivers/staging/unisys/include/iochannel.h b/drivers/staging/unisys/include/iochannel.h index 880d9f04c..5ccf81485 100644 --- a/drivers/staging/unisys/include/iochannel.h +++ b/drivers/staging/unisys/include/iochannel.h @@ -253,48 +253,6 @@ struct uiscmdrsp_scsi { /* SCSI device version for no disk inquiry result */ #define SCSI_SPC2_VER 4 /* indicates SCSI SPC2 (SPC3 is 5) */ -/* Windows and Linux want different things for a non-existent lun. So, we'll let - * caller pass in the peripheral qualifier and type. - * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5. - */ - -#define SET_NO_DISK_INQUIRY_RESULT(buf, len, lun, lun0notpresent, notpresent) \ - do { \ - memset(buf, 0, \ - MINNUM(len, \ - (unsigned int)NO_DISK_INQUIRY_RESULT_LEN)); \ - buf[2] = (u8)SCSI_SPC2_VER; \ - if (lun == 0) { \ - buf[0] = (u8)lun0notpresent; \ - buf[3] = (u8)DEV_HISUPPORT; \ - } else \ - buf[0] = (u8)notpresent; \ - buf[4] = (u8)( \ - MINNUM(len, \ - (unsigned int)NO_DISK_INQUIRY_RESULT_LEN) - 5);\ - if (len >= NO_DISK_INQUIRY_RESULT_LEN) { \ - buf[8] = 'D'; \ - buf[9] = 'E'; \ - buf[10] = 'L'; \ - buf[11] = 'L'; \ - buf[16] = 'P'; \ - buf[17] = 'S'; \ - buf[18] = 'E'; \ - buf[19] = 'U'; \ - buf[20] = 'D'; \ - buf[21] = 'O'; \ - buf[22] = ' '; \ - buf[23] = 'D'; \ - buf[24] = 'E'; \ - buf[25] = 'V'; \ - buf[26] = 'I'; \ - buf[27] = 'C'; \ - buf[28] = 'E'; \ - buf[30] = ' '; \ - buf[31] = '.'; \ - } \ - } while (0) - /* Struct & Defines to support sense information. */ /* The following struct is returned in sensebuf field in uiscmdrsp_scsi. It is diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index 2a64a9ce0..9baf1ec70 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -61,54 +61,55 @@ struct visor_channeltype_descriptor { const char *name; }; -/** Information provided by each visor driver when it registers with the - * visorbus driver. +/** + * struct visor_driver - Information provided by each visor driver when it + * registers with the visorbus driver. + * @name: Name of the visor driver. + * @version: The numbered version of the driver (x.x.xxx). + * @vertag: A human readable version string. + * @owner: The module owner. + * @channel_types: Types of channels handled by this driver, ending with + * a zero GUID. Our specialized BUS.match() method knows + * about this list, and uses it to determine whether this + * driver will in fact handle a new device that it has + * detected. + * @probe: Called when a new device comes online, by our probe() + * function specified by driver.probe() (triggered + * ultimately by some call to driver_register(), + * bus_add_driver(), or driver_attach()). + * @remove: Called when a new device is removed, by our remove() + * function specified by driver.remove() (triggered + * ultimately by some call to device_release_driver()). + * @channel_interrupt: Called periodically, whenever there is a possiblity + * that "something interesting" may have happened to the + * channel. + * @pause: Called to initiate a change of the device's state. If + * the return valu`e is < 0, there was an error and the + * state transition will NOT occur. If the return value + * is >= 0, then the state transition was INITIATED + * successfully, and complete_func() will be called (or + * was just called) with the final status when either the + * state transition fails or completes successfully. + * @resume: Behaves similar to pause. + * @driver: Private reference to the device driver. For use by bus + * driver only. + * @version_attr: Private version field. For use by bus driver only. */ struct visor_driver { const char *name; const char *version; const char *vertag; - const char *build_date; - const char *build_time; struct module *owner; - - /** Types of channels handled by this driver, ending with 0 GUID. - * Our specialized BUS.match() method knows about this list, and - * uses it to determine whether this driver will in fact handle a - * new device that it has detected. - */ struct visor_channeltype_descriptor *channel_types; - - /** Called when a new device comes online, by our probe() function - * specified by driver.probe() (triggered ultimately by some call - * to driver_register() / bus_add_driver() / driver_attach()). - */ int (*probe)(struct visor_device *dev); - - /** Called when a new device is removed, by our remove() function - * specified by driver.remove() (triggered ultimately by some call - * to device_release_driver()). - */ void (*remove)(struct visor_device *dev); - - /** Called periodically, whenever there is a possibility that - * "something interesting" may have happened to the channel state. - */ void (*channel_interrupt)(struct visor_device *dev); - - /** Called to initiate a change of the device's state. If the return - * valu`e is < 0, there was an error and the state transition will NOT - * occur. If the return value is >= 0, then the state transition was - * INITIATED successfully, and complete_func() will be called (or was - * just called) with the final status when either the state transition - * fails or completes successfully. - */ int (*pause)(struct visor_device *dev, visorbus_state_complete_func complete_func); int (*resume)(struct visor_device *dev, visorbus_state_complete_func complete_func); - /** These fields are for private use by the bus driver only. */ + /* These fields are for private use by the bus driver only. */ struct device_driver driver; struct driver_attribute version_attr; }; @@ -116,48 +117,58 @@ struct visor_driver { #define to_visor_driver(x) ((x) ? \ (container_of(x, struct visor_driver, driver)) : (NULL)) -/** A device type for things "plugged" into the visorbus bus */ +/** + * struct visor_device - A device type for things "plugged" into the visorbus + * bus + * visorchannel: Points to the channel that the device is + * associated with. + * channel_type_guid: Identifies the channel type to the bus driver. + * device: Device struct meant for use by the bus driver + * only. + * list_all: Used by the bus driver to enumerate devices. + * periodic_work: Device work queue. Private use by bus driver + * only. + * being_removed: Indicates that the device is being removed from + * the bus. Private bus driver use only. + * visordriver_callback_lock: Used by the bus driver to lock when handling + * channel events. + * pausing: Indicates that a change towards a paused state. + * is in progress. Only modified by the bus driver. + * resuming: Indicates that a change towards a running state + * is in progress. Only modified by the bus driver. + * chipset_bus_no: Private field used by the bus driver. + * chipset_dev_no: Private field used the bus driver. + * state: Used to indicate the current state of the + * device. + * inst: Unique GUID for this instance of the device. + * name: Name of the device. + * pending_msg_hdr: For private use by bus driver to respond to + * hypervisor requests. + * vbus_hdr_info: A pointer to header info. Private use by bus + * driver. + * partition_uuid: Indicates client partion id. This should be the + * same across all visor_devices in the current + * guest. Private use by bus driver only. + */ struct visor_device { - /** visor driver can use the visorchannel member with the functions - * defined in visorchannel.h to access the channel - */ struct visorchannel *visorchannel; uuid_le channel_type_guid; - u64 channel_bytes; - - /** These fields are for private use by the bus driver only. - * A notable exception is that the visor driver can use - * visor_get_drvdata() and visor_set_drvdata() to retrieve or stash - * private visor driver specific data within the device member. - */ + /* These fields are for private use by the bus driver only. */ struct device device; struct list_head list_all; struct periodic_work *periodic_work; bool being_removed; - bool responded_to_device_create; - struct kobject kobjdevmajorminor; /* visorbus<x>/dev<y>/devmajorminor/*/ - struct { - int major, minor; - void *attr; /* private use by devmajorminor_attr.c you can - * change this constant to whatever you want - */ - } devnodes[5]; - /* the code will detect and behave appropriately) */ struct semaphore visordriver_callback_lock; bool pausing; bool resuming; u32 chipset_bus_no; u32 chipset_dev_no; struct visorchipset_state state; - uuid_le type; uuid_le inst; u8 *name; - u8 *description; struct controlvm_message_header *pending_msg_hdr; void *vbus_hdr_info; - u32 switch_no; - u32 internal_port_no; uuid_le partition_uuid; }; @@ -174,8 +185,6 @@ int visorbus_write_channel(struct visor_device *dev, unsigned long nbytes); int visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch, unsigned long nbytes); -int visorbus_registerdevnode(struct visor_device *dev, - const char *name, int major, int minor); void visorbus_enable_channel_interrupts(struct visor_device *dev); void visorbus_disable_channel_interrupts(struct visor_device *dev); #endif 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<x>/dev<y>/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<x>/dev<y>/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 diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index b68a904ac..43373582c 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -40,7 +40,6 @@ struct visorchannel { bool requested; struct channel_header chan_hdr; uuid_le guid; - ulong size; bool needs_lock; /* channel creator knows if more than one */ /* thread will be inserting or removing */ spinlock_t insert_lock; /* protect head writes in chan_hdr */ @@ -134,8 +133,6 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, } channel->nbytes = channel_bytes; - - channel->size = channel_bytes; channel->guid = guid; return channel; @@ -186,7 +183,7 @@ EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); ulong visorchannel_get_nbytes(struct visorchannel *channel) { - return channel->size; + return channel->nbytes; } EXPORT_SYMBOL_GPL(visorchannel_get_nbytes); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5fbda7b21..5ba5936e2 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -59,14 +59,13 @@ */ static int visorchipset_major; static int visorchipset_visorbusregwait = 1; /* default is on */ -static int visorchipset_holdchipsetready; static unsigned long controlvm_payload_bytes_buffered; static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) { - unsigned minor_number = iminor(inode); + unsigned int minor_number = iminor(inode); if (minor_number) return -ENODEV; @@ -90,9 +89,6 @@ static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; static unsigned long most_recent_message_jiffies; static int visorbusregistered; -#define MAX_CHIPSET_EVENTS 2 -static u8 chipset_events[MAX_CHIPSET_EVENTS] = { 0, 0 }; - struct parser_context { unsigned long allocbytes; unsigned long param_bytes; @@ -107,7 +103,6 @@ static DEFINE_SEMAPHORE(notifier_lock); static struct cdev file_cdev; static struct visorchannel **file_controlvm_channel; -static struct controlvm_message_header g_chipset_msg_hdr; static struct controlvm_message_packet g_devicechangestate_packet; static LIST_HEAD(bus_info_list); @@ -156,8 +151,6 @@ struct putfile_active_buffer { /* a payload from a controlvm message, containing a file data buffer */ struct parser_context *parser_ctx; /* points within data area of parser_ctx to next byte of data */ - u8 *pnext; - /* # bytes left from <pnext> to the end of this data buffer */ size_t bytes_remaining; }; @@ -171,14 +164,10 @@ struct putfile_request { /* header from original TransmitFile request */ struct controlvm_message_header controlvm_header; - u64 file_request_number; /* from original TransmitFile request */ /* link to next struct putfile_request */ struct list_head next_putfile_request; - /* most-recent sequence number supplied via a controlvm message */ - u64 data_sequence_number; - /* head of putfile_buffer_entry list, which describes the data to be * supplied as putfile data; * - this list is added to when controlvm messages come in that supply @@ -274,11 +263,6 @@ static ssize_t remaining_steps_store(struct device *dev, const char *buf, size_t count); static DEVICE_ATTR_RW(remaining_steps); -static ssize_t chipsetready_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count); -static DEVICE_ATTR_WO(chipsetready); - static ssize_t devicedisabled_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); @@ -303,16 +287,6 @@ static struct attribute_group visorchipset_install_group = { .attrs = visorchipset_install_attrs }; -static struct attribute *visorchipset_guest_attrs[] = { - &dev_attr_chipsetready.attr, - NULL -}; - -static struct attribute_group visorchipset_guest_group = { - .name = "guest", - .attrs = visorchipset_guest_attrs -}; - static struct attribute *visorchipset_parahotplug_attrs[] = { &dev_attr_devicedisabled.attr, &dev_attr_deviceenabled.attr, @@ -326,7 +300,6 @@ static struct attribute_group visorchipset_parahotplug_group = { static const struct attribute_group *visorchipset_dev_groups[] = { &visorchipset_install_group, - &visorchipset_guest_group, &visorchipset_parahotplug_group, NULL }; @@ -359,8 +332,7 @@ static struct parser_context * parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) { int allocbytes = sizeof(struct parser_context) + bytes; - struct parser_context *rc = NULL; - struct parser_context *ctx = NULL; + struct parser_context *ctx; if (retry) *retry = false; @@ -374,15 +346,13 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) > MAX_CONTROLVM_PAYLOAD_BYTES) { if (retry) *retry = true; - rc = NULL; - goto cleanup; + return NULL; } ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); if (!ctx) { if (retry) *retry = true; - rc = NULL; - goto cleanup; + return NULL; } ctx->allocbytes = allocbytes; @@ -393,35 +363,27 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) if (local) { void *p; - if (addr > virt_to_phys(high_memory - 1)) { - rc = NULL; - goto cleanup; - } + if (addr > virt_to_phys(high_memory - 1)) + goto err_finish_ctx; p = __va((unsigned long)(addr)); memcpy(ctx->data, p, bytes); } else { void *mapping = memremap(addr, bytes, MEMREMAP_WB); - if (!mapping) { - rc = NULL; - goto cleanup; - } + if (!mapping) + goto err_finish_ctx; memcpy(ctx->data, mapping, bytes); memunmap(mapping); } ctx->byte_stream = true; - rc = ctx; -cleanup: - if (rc) { - controlvm_payload_bytes_buffered += ctx->param_bytes; - } else { - if (ctx) { - parser_done(ctx); - ctx = NULL; - } - } - return rc; + controlvm_payload_bytes_buffered += ctx->param_bytes; + + return ctx; + +err_finish_ctx: + parser_done(ctx); + return NULL; } static uuid_le @@ -523,7 +485,7 @@ static ssize_t toolaction_show(struct device *dev, struct device_attribute *attr, char *buf) { - u8 tool_action; + u8 tool_action = 0; visorchannel_read(controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, @@ -541,10 +503,11 @@ static ssize_t toolaction_store(struct device *dev, if (kstrtou8(buf, 10, &tool_action)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), - &tool_action, sizeof(u8)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); if (ret) return ret; @@ -576,10 +539,11 @@ static ssize_t boottotool_store(struct device *dev, return -EINVAL; efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &(efi_spar_indication), - sizeof(struct efi_spar_indication)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), &(efi_spar_indication), + sizeof(struct efi_spar_indication)); if (ret) return ret; @@ -589,7 +553,7 @@ static ssize_t boottotool_store(struct device *dev, static ssize_t error_show(struct device *dev, struct device_attribute *attr, char *buf) { - u32 error; + u32 error = 0; visorchannel_read(controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, @@ -607,10 +571,11 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &error)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); if (ret) return ret; return count; @@ -619,12 +584,13 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, static ssize_t textid_show(struct device *dev, struct device_attribute *attr, char *buf) { - u32 text_id; + u32 text_id = 0; - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); + visorchannel_read + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); return scnprintf(buf, PAGE_SIZE, "%i\n", text_id); } @@ -637,10 +603,11 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, if (kstrtou32(buf, 10, &text_id)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); if (ret) return ret; return count; @@ -649,7 +616,7 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, static ssize_t remaining_steps_show(struct device *dev, struct device_attribute *attr, char *buf) { - u16 remaining_steps; + u16 remaining_steps = 0; visorchannel_read(controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, @@ -668,10 +635,11 @@ static ssize_t remaining_steps_store(struct device *dev, if (kstrtou16(buf, 10, &remaining_steps)) return -EINVAL; - ret = visorchannel_write(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); + ret = visorchannel_write + (controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); if (ret) return ret; return count; @@ -717,26 +685,6 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, } EXPORT_SYMBOL(visorbus_get_device_by_id); -static u8 -check_chipset_events(void) -{ - int i; - u8 send_msg = 1; - /* Check events to determine if response should be sent */ - for (i = 0; i < MAX_CHIPSET_EVENTS; i++) - send_msg &= chipset_events[i]; - return send_msg; -} - -static void -clear_chipset_events(void) -{ - int i; - /* Clear chipset_events */ - for (i = 0; i < MAX_CHIPSET_EVENTS; i++) - chipset_events[i] = 0; -} - void visorchipset_register_busdev( struct visorchipset_busdev_notifiers *notifiers, @@ -772,7 +720,7 @@ chipset_init(struct controlvm_message *inmsg) POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); if (chipset_inited) { rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_respond; } chipset_inited = 1; POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); @@ -789,7 +737,7 @@ chipset_init(struct controlvm_message *inmsg) */ features |= ULTRA_CHIPSET_FEATURE_REPLY; -cleanup: +out_respond: if (inmsg->hdr.flags.response_expected) controlvm_respond_chipset_init(&inmsg->hdr, rc, features); } @@ -970,28 +918,31 @@ bus_epilog(struct visor_device *bus_info, u32 cmd, struct controlvm_message_header *msg_hdr, int response, bool need_response) { - bool notified = false; struct controlvm_message_header *pmsg_hdr = NULL; + down(¬ifier_lock); + if (!bus_info) { /* relying on a valid passed in response code */ /* be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto away; + goto out_respond_and_unlock; } if (bus_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = bus_info->pending_msg_hdr; - goto away; + goto out_respond_and_unlock; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { - response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto away; + POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd, + bus_info->chipset_bus_no, + POSTCODE_SEVERITY_ERR); + goto out_unlock; } memcpy(pmsg_hdr, msg_hdr, @@ -999,37 +950,27 @@ bus_epilog(struct visor_device *bus_info, bus_info->pending_msg_hdr = pmsg_hdr; } - down(¬ifier_lock); if (response == CONTROLVM_RESP_SUCCESS) { switch (cmd) { case CONTROLVM_BUS_CREATE: if (busdev_notifiers.bus_create) { (*busdev_notifiers.bus_create) (bus_info); - notified = true; + goto out_unlock; } break; case CONTROLVM_BUS_DESTROY: if (busdev_notifiers.bus_destroy) { (*busdev_notifiers.bus_destroy) (bus_info); - notified = true; + goto out_unlock; } break; } } -away: - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call bus_responder() - */ - ; - else - /* - * Do not kfree(pmsg_hdr) as this is the failure path. - * The success path ('notified') will call the responder - * directly and kfree() there. - */ - bus_responder(cmd, pmsg_hdr, response); + +out_respond_and_unlock: + bus_responder(cmd, pmsg_hdr, response); + +out_unlock: up(¬ifier_lock); } @@ -1040,30 +981,30 @@ device_epilog(struct visor_device *dev_info, bool need_response, bool for_visorbus) { struct visorchipset_busdev_notifiers *notifiers; - bool notified = false; struct controlvm_message_header *pmsg_hdr = NULL; notifiers = &busdev_notifiers; + down(¬ifier_lock); if (!dev_info) { /* relying on a valid passed in response code */ /* be lazy and re-use msg_hdr for this failure, is this ok?? */ pmsg_hdr = msg_hdr; - goto away; + goto out_respond_and_unlock; } if (dev_info->pending_msg_hdr) { /* only non-NULL if dev is still waiting on a response */ response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; pmsg_hdr = dev_info->pending_msg_hdr; - goto away; + goto out_respond_and_unlock; } if (need_response) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto away; + goto out_respond_and_unlock; } memcpy(pmsg_hdr, msg_hdr, @@ -1071,13 +1012,12 @@ device_epilog(struct visor_device *dev_info, dev_info->pending_msg_hdr = pmsg_hdr; } - down(¬ifier_lock); if (response >= 0) { switch (cmd) { case CONTROLVM_DEVICE_CREATE: if (notifiers->device_create) { (*notifiers->device_create) (dev_info); - notified = true; + goto out_unlock; } break; case CONTROLVM_DEVICE_CHANGESTATE: @@ -1087,7 +1027,7 @@ device_epilog(struct visor_device *dev_info, segment_state_running.operating) { if (notifiers->device_resume) { (*notifiers->device_resume) (dev_info); - notified = true; + goto out_unlock; } } /* ServerNotReady / ServerLost / SegmentStateStandby */ @@ -1099,32 +1039,23 @@ device_epilog(struct visor_device *dev_info, */ if (notifiers->device_pause) { (*notifiers->device_pause) (dev_info); - notified = true; + goto out_unlock; } } break; case CONTROLVM_DEVICE_DESTROY: if (notifiers->device_destroy) { (*notifiers->device_destroy) (dev_info); - notified = true; + goto out_unlock; } break; } } -away: - if (notified) - /* The callback function just called above is responsible - * for calling the appropriate visorchipset_busdev_responders - * function, which will call device_responder() - */ - ; - else - /* - * Do not kfree(pmsg_hdr) as this is the failure path. - * The success path ('notified') will call the responder - * directly and kfree() there. - */ - device_responder(cmd, pmsg_hdr, response); + +out_respond_and_unlock: + device_responder(cmd, pmsg_hdr, response); + +out_unlock: up(¬ifier_lock); } @@ -1142,14 +1073,14 @@ bus_create(struct controlvm_message *inmsg) POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_bus_epilog; } bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); if (!bus_info) { POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; + goto out_bus_epilog; } INIT_LIST_HEAD(&bus_info->list_all); @@ -1169,7 +1100,7 @@ bus_create(struct controlvm_message *inmsg) rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; kfree(bus_info); bus_info = NULL; - goto cleanup; + goto out_bus_epilog; } bus_info->visorchannel = visorchannel; if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { @@ -1179,7 +1110,7 @@ bus_create(struct controlvm_message *inmsg) POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); -cleanup: +out_bus_epilog: bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr, rc, inmsg->hdr.flags.response_expected == 1); } @@ -1231,8 +1162,9 @@ bus_configure(struct controlvm_message *inmsg, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; } else { - visorchannel_set_clientpartition(bus_info->visorchannel, - cmd->configure_bus.guest_handle); + visorchannel_set_clientpartition + (bus_info->visorchannel, + cmd->configure_bus.guest_handle); bus_info->partition_uuid = parser_id_get(parser_ctx); parser_param_start(parser_ctx, PARSERSTRING_NAME); bus_info->name = parser_string_get(parser_ctx); @@ -1260,14 +1192,14 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; + goto out_respond; } if (bus_info->state.created == 0) { POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - goto cleanup; + goto out_respond; } dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL); @@ -1275,7 +1207,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE; - goto cleanup; + goto out_respond; } dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); @@ -1283,7 +1215,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; - goto cleanup; + goto out_respond; } dev_info->chipset_bus_no = bus_no; @@ -1308,7 +1240,7 @@ my_device_create(struct controlvm_message *inmsg) rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED; kfree(dev_info); dev_info = NULL; - goto cleanup; + goto out_respond; } dev_info->visorchannel = visorchannel; dev_info->channel_type_guid = cmd->create_device.data_type_uuid; @@ -1318,7 +1250,7 @@ my_device_create(struct controlvm_message *inmsg) POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); -cleanup: +out_respond: device_epilog(dev_info, segment_state_running, CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc, inmsg->hdr.flags.response_expected == 1, 1); @@ -1382,35 +1314,23 @@ initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes, struct visor_controlvm_payload_info *info) { u8 *payload = NULL; - int rc = CONTROLVM_RESP_SUCCESS; - if (!info) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } + if (!info) + return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + memset(info, 0, sizeof(struct visor_controlvm_payload_info)); - if ((offset == 0) || (bytes == 0)) { - rc = -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; - goto cleanup; - } + if ((offset == 0) || (bytes == 0)) + return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID; + payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB); - if (!payload) { - rc = -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - goto cleanup; - } + if (!payload) + return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED; info->offset = offset; info->bytes = bytes; info->ptr = payload; -cleanup: - if (rc < 0) { - if (payload) { - memunmap(payload); - payload = NULL; - } - } - return rc; + return CONTROLVM_RESP_SUCCESS; } static void @@ -1490,14 +1410,8 @@ chipset_ready(struct controlvm_message_header *msg_hdr) if (rc != CONTROLVM_RESP_SUCCESS) rc = -rc; - if (msg_hdr->flags.response_expected && !visorchipset_holdchipsetready) + if (msg_hdr->flags.response_expected) controlvm_respond(msg_hdr, rc); - if (msg_hdr->flags.response_expected && visorchipset_holdchipsetready) { - /* Send CHIPSET_READY response when all modules have been loaded - * and disks mounted for the partition - */ - g_chipset_msg_hdr = *msg_hdr; - } } static void @@ -1726,9 +1640,10 @@ parahotplug_process_message(struct controlvm_message *inmsg) * initialization. */ parahotplug_request_kickoff(req); - controlvm_respond_physdev_changestate(&inmsg->hdr, - CONTROLVM_RESP_SUCCESS, - inmsg->cmd.device_change_state.state); + controlvm_respond_physdev_changestate + (&inmsg->hdr, + CONTROLVM_RESP_SUCCESS, + inmsg->cmd.device_change_state.state); parahotplug_request_destroy(req); } else { /* For disable messages, add the request to the @@ -1840,8 +1755,9 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) break; default: if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, - -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); + controlvm_respond + (&inmsg.hdr, + -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN); break; } @@ -1885,31 +1801,11 @@ controlvm_periodic_work(struct work_struct *work) struct controlvm_message inmsg; bool got_command = false; bool handle_command_failed = false; - static u64 poll_count; /* make sure visorbus server is registered for controlvm callbacks */ if (visorchipset_visorbusregwait && !visorbusregistered) goto cleanup; - poll_count++; - if (poll_count >= 250) - ; /* keep going */ - else - goto cleanup; - - /* Check events to determine if response to CHIPSET_READY - * should be sent - */ - if (visorchipset_holdchipsetready && - (g_chipset_msg_hdr.id != CONTROLVM_INVALID)) { - if (check_chipset_events() == 1) { - controlvm_respond(&g_chipset_msg_hdr, 0); - clear_chipset_events(); - memset(&g_chipset_msg_hdr, 0, - sizeof(struct controlvm_message_header)); - } - } - while (visorchannel_signalremove(controlvm_channel, CONTROLVM_QUEUE_RESPONSE, &inmsg)) @@ -1979,8 +1875,11 @@ setup_crash_devices_work_queue(struct work_struct *work) u16 local_crash_msg_count; /* make sure visorbus is registered for controlvm callbacks */ - if (visorchipset_visorbusregwait && !visorbusregistered) - goto cleanup; + if (visorchipset_visorbusregwait && !visorbusregistered) { + poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); + return; + } POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO); @@ -2057,13 +1956,6 @@ setup_crash_devices_work_queue(struct work_struct *work) return; } POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO); - return; - -cleanup: - - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); } static void @@ -2135,25 +2027,6 @@ device_resume_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static ssize_t chipsetready_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - char msgtype[64]; - - if (sscanf(buf, "%63s", msgtype) != 1) - return -EINVAL; - - if (!strcmp(msgtype, "CALLHOMEDISK_MOUNTED")) { - chipset_events[0] = 1; - return count; - } else if (!strcmp(msgtype, "MODULES_LOADED")) { - chipset_events[1] = 1; - return count; - } - return -EINVAL; -} - /* The parahotplug/devicedisabled interface gets called by our support script * when an SR-IOV device has been shut down. The ID is passed to the script * and then passed back when the device has been removed. @@ -2205,10 +2078,11 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) if (!*file_controlvm_channel) return -ENXIO; - visorchannel_read(*file_controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - gp_control_channel), - &addr, sizeof(addr)); + visorchannel_read + (*file_controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + gp_control_channel), + &addr, sizeof(addr)); if (!addr) return -ENXIO; @@ -2308,16 +2182,25 @@ visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) return 0; } +static void +visorchipset_file_cleanup(dev_t major_dev) +{ + if (file_cdev.ops) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + unregister_chrdev_region(major_dev, 1); +} + static int visorchipset_init(struct acpi_device *acpi_device) { - int rc = 0; + int err = -ENODEV; u64 addr; uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID; addr = controlvm_get_channel_address(); if (!addr) - return -ENODEV; + goto error; memset(&busdev_notifiers, 0, sizeof(busdev_notifiers)); memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); @@ -2325,24 +2208,19 @@ visorchipset_init(struct acpi_device *acpi_device) controlvm_channel = visorchannel_create_with_lock(addr, 0, GFP_KERNEL, uuid); if (!controlvm_channel) - return -ENODEV; + goto error; + if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT( visorchannel_get_header(controlvm_channel))) { initialize_controlvm_payload(); } else { - visorchannel_destroy(controlvm_channel); - controlvm_channel = NULL; - return -ENODEV; + goto error_destroy_channel; } major_dev = MKDEV(visorchipset_major, 0); - rc = visorchipset_file_init(major_dev, &controlvm_channel); - if (rc < 0) { - POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR); - goto cleanup; - } - - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); + err = visorchipset_file_init(major_dev, &controlvm_channel); + if (err < 0) + goto error_destroy_payload; /* if booting in a crash kernel */ if (is_kdump_kernel()) @@ -2359,27 +2237,33 @@ visorchipset_init(struct acpi_device *acpi_device) visorchipset_platform_device.dev.devt = major_dev; if (platform_device_register(&visorchipset_platform_device) < 0) { POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR); - rc = -ENODEV; - goto cleanup; + err = -ENODEV; + goto error_cancel_work; } POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO); - rc = visorbus_init(); -cleanup: - if (rc) { - POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc, - POSTCODE_SEVERITY_ERR); - } - return rc; -} + err = visorbus_init(); + if (err < 0) + goto error_unregister; -static void -visorchipset_file_cleanup(dev_t major_dev) -{ - if (file_cdev.ops) - cdev_del(&file_cdev); - file_cdev.ops = NULL; - unregister_chrdev_region(major_dev, 1); + return 0; + +error_unregister: + platform_device_unregister(&visorchipset_platform_device); + +error_cancel_work: + cancel_delayed_work_sync(&periodic_controlvm_work); + visorchipset_file_cleanup(major_dev); + +error_destroy_payload: + destroy_controlvm_payload_info(&controlvm_payload_info); + +error_destroy_channel: + visorchannel_destroy(controlvm_channel); + +error: + POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR); + return err; } static int @@ -2392,8 +2276,6 @@ visorchipset_exit(struct acpi_device *acpi_device) cancel_delayed_work_sync(&periodic_controlvm_work); destroy_controlvm_payload_info(&controlvm_payload_info); - memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); - visorchannel_destroy(controlvm_channel); visorchipset_file_cleanup(visorchipset_platform_device.dev.devt); @@ -2425,7 +2307,7 @@ static __init uint32_t visorutil_spar_detect(void) { unsigned int eax, ebx, ecx, edx; - if (cpu_has_hypervisor) { + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) { /* check the ID */ cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx); return (ebx == UNISYS_SPAR_ID_EBX) && @@ -2460,12 +2342,8 @@ module_param_named(major, visorchipset_major, int, S_IRUGO); MODULE_PARM_DESC(visorchipset_major, "major device number to use for the device node"); module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_visorbusreqwait, +MODULE_PARM_DESC(visorchipset_visorbusregwait, "1 to have the module wait for the visor bus to register"); -module_param_named(holdchipsetready, visorchipset_holdchipsetready, - int, S_IRUGO); -MODULE_PARM_DESC(visorchipset_holdchipsetready, - "1 to hold response to CHIPSET_READY"); module_init(init_unisys); module_exit(exit_unisys); diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index e93bb1dbf..6a4570d10 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -52,6 +52,8 @@ static int visorhba_resume(struct visor_device *dev, static ssize_t info_debugfs_read(struct file *file, char __user *buf, size_t len, loff_t *offset); +static int set_no_disk_inquiry_result(unsigned char *buf, + size_t len, bool is_lun0); static struct dentry *visorhba_debugfs_dir; static const struct file_operations debugfs_info_fops = { .read = info_debugfs_read, @@ -83,12 +85,6 @@ static struct visor_driver visorhba_driver = { MODULE_DEVICE_TABLE(visorbus, visorhba_channel_types); MODULE_ALIAS("visorbus:" SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR); -struct visor_thread_info { - struct task_struct *task; - struct completion has_stopped; - int id; -}; - struct visordisk_info { u32 valid; u32 channel, id, lun; /* Disk Path */ @@ -135,7 +131,7 @@ struct visorhba_devdata { struct visordisk_info head; unsigned int max_buff_len; int devnum; - struct visor_thread_info threadinfo; + struct task_struct *thread; int thread_wait_ms; }; @@ -152,28 +148,36 @@ static struct visorhba_devices_open visorhbas_open[VISORHBA_OPEN_MAX]; (iter->lun == match->lun)) /** * visor_thread_start - starts a thread for the device - * @thrinfo: The thread to start * @threadfn: Function the thread starts * @thrcontext: Context to pass to the thread, i.e. devdata * @name: string describing name of thread * * Starts a thread for the device. * - * Return 0 on success; + * Return the task_struct * denoting the thread on success, + * or NULL on failure */ -static int visor_thread_start(struct visor_thread_info *thrinfo, - int (*threadfn)(void *), - void *thrcontext, char *name) +static struct task_struct *visor_thread_start +(int (*threadfn)(void *), void *thrcontext, char *name) { - /* used to stop the thread */ - init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, "%s", name); - if (IS_ERR(thrinfo->task)) { - thrinfo->id = 0; - return PTR_ERR(thrinfo->task); + struct task_struct *task; + + task = kthread_run(threadfn, thrcontext, "%s", name); + if (IS_ERR(task)) { + pr_err("visorbus failed to start thread\n"); + return NULL; } - thrinfo->id = thrinfo->task->pid; - return 0; + return task; +} + +/** + * visor_thread_stop - stops the thread if it is running + */ +static void visor_thread_stop(struct task_struct *task) +{ + if (!task) + return; /* no thread running */ + kthread_stop(task); } /** @@ -231,16 +235,17 @@ static void *del_scsipending_ent(struct visorhba_devdata *devdata, int del) { unsigned long flags; - void *sent = NULL; + void *sent; - if (del < MAX_PENDING_REQUESTS) { - spin_lock_irqsave(&devdata->privlock, flags); - sent = devdata->pending[del].sent; + if (del >= MAX_PENDING_REQUESTS) + return NULL; - devdata->pending[del].cmdtype = 0; - devdata->pending[del].sent = NULL; - spin_unlock_irqrestore(&devdata->privlock, flags); - } + spin_lock_irqsave(&devdata->privlock, flags); + sent = devdata->pending[del].sent; + + devdata->pending[del].cmdtype = 0; + devdata->pending[del].sent = NULL; + spin_unlock_irqrestore(&devdata->privlock, flags); return sent; } @@ -681,7 +686,7 @@ static void visorhba_serverdown_complete(struct visorhba_devdata *devdata) /* Stop using the IOVM response queue (queue should be drained * by the end) */ - kthread_stop(devdata->threadinfo.task); + visor_thread_stop(devdata->thread); /* Fail commands that weren't completed */ spin_lock_irqsave(&devdata->privlock, flags); @@ -772,6 +777,24 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) } } +static int set_no_disk_inquiry_result(unsigned char *buf, + size_t len, bool is_lun0) +{ + if (!buf || len < NO_DISK_INQUIRY_RESULT_LEN) + return -EINVAL; + memset(buf, 0, NO_DISK_INQUIRY_RESULT_LEN); + buf[2] = SCSI_SPC2_VER; + if (is_lun0) { + buf[0] = DEV_DISK_CAPABLE_NOT_PRESENT; + buf[3] = DEV_HISUPPORT; + } else { + buf[0] = DEV_NOT_CAPABLE; + } + buf[4] = NO_DISK_INQUIRY_RESULT_LEN - 5; + strncpy(buf + 8, "DELLPSEUDO DEVICE .", NO_DISK_INQUIRY_RESULT_LEN - 8); + return 0; +} + /** * do_scsi_nolinuxstat - scsi command didn't have linuxstat * @cmdrsp: response from IOVM @@ -804,10 +827,8 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) * a disk there so we'll present a processor * there. */ - SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen, - scsidev->lun, - DEV_DISK_CAPABLE_NOT_PRESENT, - DEV_NOT_CAPABLE); + set_no_disk_inquiry_result(buf, (size_t)cmdrsp->scsi.bufflen, + scsidev->lun == 0); if (scsi_sg_count(scsicmd) == 0) { memcpy(scsi_sglist(scsicmd), buf, @@ -929,14 +950,15 @@ static void process_disk_notify(struct Scsi_Host *shost, struct diskaddremove *dar; dar = kzalloc(sizeof(*dar), GFP_ATOMIC); - if (dar) { - dar->add = cmdrsp->disknotify.add; - dar->shost = shost; - dar->channel = cmdrsp->disknotify.channel; - dar->id = cmdrsp->disknotify.id; - dar->lun = cmdrsp->disknotify.lun; - queue_disk_add_remove(dar); - } + if (!dar) + return; + + dar->add = cmdrsp->disknotify.add; + dar->shost = shost; + dar->channel = cmdrsp->disknotify.channel; + dar->id = cmdrsp->disknotify.id; + dar->lun = cmdrsp->disknotify.lun; + queue_disk_add_remove(dar); } /** @@ -1064,8 +1086,8 @@ static int visorhba_resume(struct visor_device *dev, if (devdata->serverdown && !devdata->serverchangingstate) devdata->serverchangingstate = true; - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vhba_incming"); + devdata->thread = visor_thread_start(process_incoming_rsps, devdata, + "vhba_incming"); devdata->serverdown = false; devdata->serverchangingstate = false; @@ -1141,8 +1163,8 @@ static int visorhba_probe(struct visor_device *dev) goto err_scsi_remove_host; devdata->thread_wait_ms = 2; - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vhba_incoming"); + devdata->thread = visor_thread_start(process_incoming_rsps, devdata, + "vhba_incoming"); scsi_scan_host(scsihost); @@ -1172,7 +1194,7 @@ static void visorhba_remove(struct visor_device *dev) return; scsihost = devdata->scsihost; - kthread_stop(devdata->threadinfo.task); + visor_thread_stop(devdata->thread); scsi_remove_host(scsihost); scsi_host_put(scsihost); diff --git a/drivers/staging/unisys/visorinput/visorinput.c b/drivers/staging/unisys/visorinput/visorinput.c index 13c031611..12a357078 100644 --- a/drivers/staging/unisys/visorinput/visorinput.c +++ b/drivers/staging/unisys/visorinput/visorinput.c @@ -123,9 +123,9 @@ static const unsigned char visorkbd_keycode[KEYCODE_TABLE_BYTES] = { [38] = KEY_L, [39] = KEY_SEMICOLON, [40] = KEY_APOSTROPHE, - [41] = KEY_GRAVE, /* FIXME, '#' */ + [41] = KEY_GRAVE, [42] = KEY_LEFTSHIFT, - [43] = KEY_BACKSLASH, /* FIXME, '~' */ + [43] = KEY_BACKSLASH, [44] = KEY_Z, [45] = KEY_X, [46] = KEY_C, @@ -173,7 +173,7 @@ static const unsigned char visorkbd_keycode[KEYCODE_TABLE_BYTES] = { [88] = KEY_F12, [90] = KEY_KPLEFTPAREN, [91] = KEY_KPRIGHTPAREN, - [92] = KEY_KPASTERISK, /* FIXME */ + [92] = KEY_KPASTERISK, [93] = KEY_KPASTERISK, [94] = KEY_KPPLUS, [95] = KEY_HELP, @@ -467,18 +467,14 @@ handle_locking_key(struct input_dev *visorinput_dev, break; default: led = -1; - break; + return; } - if (led >= 0) { - int old_state = (test_bit(led, visorinput_dev->led) != 0); - - if (old_state != desired_state) { - input_report_key(visorinput_dev, keycode, 1); - input_sync(visorinput_dev); - input_report_key(visorinput_dev, keycode, 0); - input_sync(visorinput_dev); - __change_bit(led, visorinput_dev->led); - } + if (test_bit(led, visorinput_dev->led) != desired_state) { + input_report_key(visorinput_dev, keycode, 1); + input_sync(visorinput_dev); + input_report_key(visorinput_dev, keycode, 0); + input_sync(visorinput_dev); + __change_bit(led, visorinput_dev->led); } } diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index be0d05734..fd7c9a6cb 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -109,51 +109,46 @@ struct chanstat { }; struct visornic_devdata { - unsigned short enabled; /* 0 disabled 1 enabled to receive */ - unsigned short enab_dis_acked; /* NET_RCV_ENABLE/DISABLE acked by - * IOPART - */ + /* 0 disabled 1 enabled to receive */ + unsigned short enabled; + /* NET_RCV_ENABLE/DISABLE acked by IOPART */ + unsigned short enab_dis_acked; + struct visor_device *dev; struct net_device *netdev; struct net_device_stats net_stats; atomic_t interrupt_rcvd; wait_queue_head_t rsp_queue; struct sk_buff **rcvbuf; - u64 incarnation_id; /* lets IOPART know about re-birth */ - unsigned short old_flags; /* flags as they were prior to - * set_multicast_list - */ - atomic_t usage; /* count of users */ - int num_rcv_bufs; /* indicates how many rcv buffers - * the vnic will post - */ + /* incarnation_id lets IOPART know about re-birth */ + u64 incarnation_id; + /* flags as they were prior to set_multicast_list */ + unsigned short old_flags; + atomic_t usage; /* count of users */ + + /* number of rcv buffers the vnic will post */ + int num_rcv_bufs; int num_rcv_bufs_could_not_alloc; atomic_t num_rcvbuf_in_iovm; unsigned long alloc_failed_in_if_needed_cnt; unsigned long alloc_failed_in_repost_rtn_cnt; - unsigned long max_outstanding_net_xmits; /* absolute max number of - * outstanding xmits - should - * never hit this - */ - unsigned long upper_threshold_net_xmits; /* high water mark for - * calling netif_stop_queue() - */ - unsigned long lower_threshold_net_xmits; /* high water mark for calling - * netif_wake_queue() - */ - struct sk_buff_head xmitbufhead; /* xmitbufhead is the head of the - * xmit buffer list that have been - * sent to the IOPART end - */ + + /* absolute max number of outstanding xmits - should never hit this */ + unsigned long max_outstanding_net_xmits; + /* high water mark for calling netif_stop_queue() */ + unsigned long upper_threshold_net_xmits; + /* high water mark for calling netif_wake_queue() */ + unsigned long lower_threshold_net_xmits; + /* xmitbufhead - head of the xmit buffer list sent to the IOPART end */ + struct sk_buff_head xmitbufhead; + visorbus_state_complete_func server_down_complete_func; struct work_struct timeout_reset; - struct uiscmdrsp *cmdrsp_rcv; /* cmdrsp_rcv is used for - * posting/unposting rcv buffers - */ - struct uiscmdrsp *xmit_cmdrsp; /* used to issue NET_XMIT - there is - * never more that one xmit in - * progress at a time - */ + /* cmdrsp_rcv is used for posting/unposting rcv buffers */ + struct uiscmdrsp *cmdrsp_rcv; + /* xmit_cmdrsp - issues NET_XMIT - only one active xmit at a time */ + struct uiscmdrsp *xmit_cmdrsp; + bool server_down; /* IOPART is down */ bool server_change_state; /* Processing SERVER_CHANGESTATE msg */ bool going_away; /* device is being torn down */ @@ -173,18 +168,10 @@ struct visornic_devdata { unsigned long n_rcv1; /* # rcvs of 1 buffers */ unsigned long n_rcv2; /* # rcvs of 2 buffers */ unsigned long n_rcvx; /* # rcvs of >2 buffers */ - unsigned long found_repost_rcvbuf_cnt; /* # times we called - * repost_rcvbuf_cnt - */ - unsigned long repost_found_skb_cnt; /* # times found the skb */ - unsigned long n_repost_deficit; /* # times we couldn't find - * all of the rcv buffers - */ - unsigned long bad_rcv_buf; /* # times we negleted to - * free the rcv skb because - * we didn't know where it - * came from - */ + unsigned long found_repost_rcvbuf_cnt; /* # repost_rcvbuf_cnt */ + unsigned long repost_found_skb_cnt; /* # of found the skb */ + unsigned long n_repost_deficit; /* # of lost rcv buffers */ + unsigned long bad_rcv_buf; /* # of unknown rcv skb not freed */ unsigned long n_rcv_packets_not_accepted;/* # bogs rcv packets */ int queuefullmsg_logged; @@ -209,18 +196,17 @@ static void poll_for_irq(unsigned long v); * Return value indicates number of entries filled in frags * Negative values indicate an error. */ -static unsigned int +static int visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen, unsigned int frags_max, struct phys_info frags[]) { - unsigned int count = 0, ii, size, offset = 0, numfrags; + unsigned int count = 0, frag, size, offset = 0, numfrags; unsigned int total_count; numfrags = skb_shinfo(skb)->nr_frags; - /* - * Compute the number of fragments this skb has, and if its more than + /* Compute the number of fragments this skb has, and if its more than * frag array can hold, linearize the skb */ total_count = numfrags + (firstfraglen / PI_PAGE_SIZE); @@ -257,23 +243,20 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen, if ((count + numfrags) > frags_max) return -EINVAL; - for (ii = 0; ii < numfrags; ii++) { + for (frag = 0; frag < numfrags; frag++) { count = add_physinfo_entries(page_to_pfn( - skb_frag_page(&skb_shinfo(skb)->frags[ii])), - skb_shinfo(skb)->frags[ii]. + skb_frag_page(&skb_shinfo(skb)->frags[frag])), + skb_shinfo(skb)->frags[frag]. page_offset, - skb_shinfo(skb)->frags[ii]. + skb_shinfo(skb)->frags[frag]. size, count, frags_max, frags); - /* - * add_physinfo_entries only returns + /* add_physinfo_entries only returns * zero if the frags array is out of room * That should never happen because we * fail above, if count+numfrags > frags_max. - * Given that theres no recovery mechanism from putting - * half a packet in the I/O channel, panic here as this - * should never happen */ - BUG_ON(!count); + if (!count) + return -EINVAL; } } if (skb_shinfo(skb)->frag_list) { @@ -299,8 +282,7 @@ static ssize_t enable_ints_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - /* - * Don't want to break ABI here by having a debugfs + /* Don't want to break ABI here by having a debugfs * file that no longer exists or is writable, so * lets just make this a vestigual function */ @@ -308,8 +290,7 @@ static ssize_t enable_ints_write(struct file *file, } /** - * visornic_serverdown_complete - IOPART went down, need to pause - * device + * visornic_serverdown_complete - IOPART went down, pause device * @work: Work queue it was scheduled on * * The IO partition has gone down and we need to do some cleanup @@ -344,7 +325,7 @@ visornic_serverdown_complete(struct visornic_devdata *devdata) } /** - * visornic_serverdown - Command has notified us that IOPARt is down + * visornic_serverdown - Command has notified us that IOPART is down * @devdata: device that is being managed by IOPART * * Schedule the work needed to handle the server down request. Make @@ -356,28 +337,38 @@ visornic_serverdown(struct visornic_devdata *devdata, visorbus_state_complete_func complete_func) { unsigned long flags; + int err; spin_lock_irqsave(&devdata->priv_lock, flags); - if (!devdata->server_down && !devdata->server_change_state) { - if (devdata->going_away) { - spin_unlock_irqrestore(&devdata->priv_lock, flags); - dev_dbg(&devdata->dev->device, - "%s aborting because device removal pending\n", - __func__); - return -ENODEV; - } - devdata->server_change_state = true; - devdata->server_down_complete_func = complete_func; - spin_unlock_irqrestore(&devdata->priv_lock, flags); - visornic_serverdown_complete(devdata); - } else if (devdata->server_change_state) { + if (devdata->server_change_state) { dev_dbg(&devdata->dev->device, "%s changing state\n", __func__); - spin_unlock_irqrestore(&devdata->priv_lock, flags); - return -EINVAL; + err = -EINVAL; + goto err_unlock; + } + if (devdata->server_down) { + dev_dbg(&devdata->dev->device, "%s already down\n", + __func__); + err = -EINVAL; + goto err_unlock; + } + if (devdata->going_away) { + dev_dbg(&devdata->dev->device, + "%s aborting because device removal pending\n", + __func__); + err = -ENODEV; + goto err_unlock; } + devdata->server_change_state = true; + devdata->server_down_complete_func = complete_func; spin_unlock_irqrestore(&devdata->priv_lock, flags); + + visornic_serverdown_complete(devdata); return 0; + +err_unlock: + spin_unlock_irqrestore(&devdata->priv_lock, flags); + return err; } /** @@ -395,20 +386,19 @@ alloc_rcv_buf(struct net_device *netdev) /* NOTE: the first fragment in each rcv buffer is pointed to by * rcvskb->data. For now all rcv buffers will be RCVPOST_BUF_SIZE - * in length, so the firstfrag is large enough to hold 1514. + * in length, so the first frag is large enough to hold 1514. */ skb = alloc_skb(RCVPOST_BUF_SIZE, GFP_ATOMIC); if (!skb) return NULL; skb->dev = netdev; - skb->len = RCVPOST_BUF_SIZE; /* current value of mtu doesn't come into play here; large * packets will just end up using multiple rcv buffers all of - * same size + * same size. */ - skb->data_len = 0; /* dev_alloc_skb already zeroes it out - * for clarification. - */ + skb->len = RCVPOST_BUF_SIZE; + /* alloc_skb already zeroes it out for clarification. */ + skb->data_len = 0; return skb; } @@ -436,8 +426,8 @@ post_skb(struct uiscmdrsp *cmdrsp, cmdrsp->net.type = NET_RCV_POST; cmdrsp->cmdtype = CMD_NET_TYPE; if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - cmdrsp)) { + IOCHAN_TO_IOPART, + cmdrsp)) { atomic_inc(&devdata->num_rcvbuf_in_iovm); devdata->chstat.sent_post++; } else { @@ -465,8 +455,8 @@ send_enbdis(struct net_device *netdev, int state, devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS; devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE; if (visorchannel_signalinsert(devdata->dev->visorchannel, - IOCHAN_TO_IOPART, - devdata->cmdrsp_rcv)) + IOCHAN_TO_IOPART, + devdata->cmdrsp_rcv)) devdata->chstat.sent_enbdis++; } @@ -872,8 +862,7 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) if (vnic_hit_high_watermark(devdata, devdata->max_outstanding_net_xmits)) { - /* too many NET_XMITs queued over to IOVM - need to wait - */ + /* extra NET_XMITs queued over to IOVM - need to wait */ devdata->chstat.reject_count++; if (!devdata->queuefullmsg_logged && ((devdata->chstat.reject_count & 0x3ff) == 1)) @@ -950,16 +939,12 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) devdata->net_stats.tx_bytes += skb->len; devdata->chstat.sent_xmit++; - /* check to see if we have hit the high watermark for - * netif_stop_queue() - */ + /* check if we have hit the high watermark for netif_stop_queue() */ if (vnic_hit_high_watermark(devdata, devdata->upper_threshold_net_xmits)) { - /* too many NET_XMITs queued over to IOVM - need to wait */ - netif_stop_queue(netdev); /* calling stop queue - call - * netif_wake_queue() after lower - * threshold - */ + /* extra NET_XMITs queued over to IOVM - need to wait */ + /* stop queue - call netif_wake_queue() after lower threshold */ + netif_stop_queue(netdev); dev_dbg(&netdev->dev, "%s busy - invoking iovm flow control\n", __func__); @@ -1312,16 +1297,13 @@ visornic_rx(struct uiscmdrsp *cmdrsp) break; } } + /* accept pkt, dest matches a multicast addr */ if (found_mc) - break; /* accept packet, dest - * matches a multicast - * address - */ + break; } + /* accept packet, h_dest must match vnic mac address */ } else if (skb->pkt_type == PACKET_HOST) { - break; /* accept packet, h_dest must match vnic - * mac address - */ + break; } else if (skb->pkt_type == PACKET_OTHERHOST) { /* something is not right */ dev_err(&devdata->netdev->dev, @@ -1409,14 +1391,10 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf, if (!vbuf) return -ENOMEM; - /* for each vnic channel - * dump out channel specific data - */ + /* for each vnic channel dump out channel specific data */ rcu_read_lock(); for_each_netdev_rcu(current->nsproxy->net_ns, dev) { - /* - * Only consider netdevs that are visornic, and are open - */ + /* Only consider netdevs that are visornic, and are open */ if ((dev->netdev_ops != &visornic_dev_ops) || (!netif_queue_stopped(dev))) continue; @@ -1643,12 +1621,12 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, /* ASSERT netdev == vnicinfo->netdev; */ if ((netdev == devdata->netdev) && netif_queue_stopped(netdev)) { - /* check to see if we have crossed - * the lower watermark for - * netif_wake_queue() + /* check if we have crossed the lower watermark + * for netif_wake_queue() */ - if (vnic_hit_low_watermark(devdata, - devdata->lower_threshold_net_xmits)) { + if (vnic_hit_low_watermark + (devdata, + devdata->lower_threshold_net_xmits)) { /* enough NET_XMITs completed * so can restart netif queue */ @@ -1712,10 +1690,7 @@ static int visornic_poll(struct napi_struct *napi, int budget) send_rcv_posts_if_needed(devdata); service_resp_queue(devdata->cmdrsp, devdata, &rx_count, budget); - /* - * If there aren't any more packets to receive - * stop the poll - */ + /* If there aren't any more packets to receive stop the poll */ if (rx_count < budget) napi_complete(napi); @@ -1867,8 +1842,7 @@ static int visornic_probe(struct visor_device *dev) setup_timer(&devdata->irq_poll_timer, poll_for_irq, (unsigned long)devdata); - /* - * Note: This time has to start running before the while + /* Note: This time has to start running before the while * loop below because the napi routine is responsible for * setting enab_dis_acked */ @@ -1897,8 +1871,7 @@ static int visornic_probe(struct visor_device *dev) /* Let's start our threads to get responses */ netif_napi_add(netdev, &devdata->napi, visornic_poll, NAPI_WEIGHT); - /* - * Note: Interupts have to be enable before the while + /* Note: Interupts have to be enable before the while * loop below because the napi routine is responsible for * setting enab_dis_acked */ |