diff options
Diffstat (limited to 'drivers/staging/unisys/visorbus')
-rw-r--r-- | drivers/staging/unisys/visorbus/controlvmchannel.h | 208 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/vbuschannel.h | 57 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorbus_main.c | 420 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorbus_private.h | 26 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchannel.c | 95 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchipset.c | 1043 | ||||
-rw-r--r-- | drivers/staging/unisys/visorbus/vmcallinterface.h | 149 |
7 files changed, 808 insertions, 1190 deletions
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index 859345243afe..274f72422166 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -19,9 +19,9 @@ #include "channel.h" /* {2B3C2D10-7EF5-4ad8-B966-3448B7386B3D} */ -#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ - 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) +#define SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID \ + UUID_LE(0x2b3c2d10, 0x7ef5, 0x4ad8, \ + 0xb9, 0x66, 0x34, 0x48, 0xb7, 0x38, 0x6b, 0x3d) #define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE \ ULTRA_CHANNEL_PROTOCOL_SIGNATURE @@ -33,24 +33,24 @@ * software. Note that you can usually add fields to the END of the * channel struct withOUT needing to increment this. */ -#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 +#define ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID 1 -#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ - spar_check_channel_client(ch, \ - SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ - "controlvm", \ - sizeof(struct spar_controlvm_channel_protocol), \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ - ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE) +#define SPAR_CONTROLVM_CHANNEL_OK_CLIENT(ch) \ + (spar_check_channel(ch, \ + SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID, \ + "controlvm", \ + sizeof(struct spar_controlvm_channel_protocol), \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_VERSIONID, \ + ULTRA_CONTROLVM_CHANNEL_PROTOCOL_SIGNATURE)) /* Defines for various channel queues */ -#define CONTROLVM_QUEUE_REQUEST 0 -#define CONTROLVM_QUEUE_RESPONSE 1 -#define CONTROLVM_QUEUE_EVENT 2 -#define CONTROLVM_QUEUE_ACK 3 +#define CONTROLVM_QUEUE_REQUEST 0 +#define CONTROLVM_QUEUE_RESPONSE 1 +#define CONTROLVM_QUEUE_EVENT 2 +#define CONTROLVM_QUEUE_ACK 3 /* Max num of messages stored during IOVM creation to be reused after crash */ -#define CONTROLVM_CRASHMSG_MAX 2 +#define CONTROLVM_CRASHMSG_MAX 2 struct spar_segment_state { /* Bit 0: May enter other states */ @@ -69,10 +69,12 @@ struct spar_segment_state { u16 ready:1; /* Bit 7: resource is configured and operating */ u16 operating:1; + /* Natural alignment*/ + u16 reserved:8; /* Note: don't use high bit unless we need to switch to ushort * which is non-compliant */ -}; +} __packed; static const struct spar_segment_state segment_state_running = { 1, 1, 1, 0, 1, 1, 1, 1 @@ -145,15 +147,7 @@ struct irq_info { */ u8 recv_irq_shared; u8 reserved[3]; /* Natural alignment purposes */ -}; - -struct pci_id { - u16 domain; - u8 bus; - u8 slot; - u8 func; - u8 reserved[3]; /* Natural alignment purposes */ -}; +} __packed; struct efi_spar_indication { u64 boot_to_fw_ui:1; /* Bit 0: Stop in uefi ui */ @@ -161,7 +155,8 @@ struct efi_spar_indication { u64 clear_cmos:1; /* Bit 2: Clear CMOS */ u64 boot_to_tool:1; /* Bit 3: Run install tool */ /* remaining bits are available */ -}; + u64 reserved:60; /* Natural alignment */ +} __packed; enum ultra_chipset_feature { ULTRA_CHIPSET_FEATURE_REPLY = 0x00000001, @@ -203,7 +198,9 @@ struct controlvm_message_header { u32 preserve:1; /* =1 the DiagWriter is active in the Diagnostic Partition */ u32 writer_in_diag:1; - } flags; + /* Natural alignment */ + u32 reserve:25; + } __packed flags; /* Natural alignment */ u32 reserved; /* Identifies the particular message instance */ @@ -216,7 +213,7 @@ struct controlvm_message_header { /* Actual number of bytes of payload area to copy between IO/Command */ u32 payload_bytes; /* if non-zero, there is a payload to copy. */ -}; +} __packed; struct controlvm_packet_device_create { u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ @@ -229,24 +226,24 @@ struct controlvm_packet_device_create { uuid_le data_type_uuid; /* specifies format of data in channel */ uuid_le dev_inst_uuid; /* instance guid for the device */ struct irq_info intr; /* specifies interrupt information */ -}; /* for CONTROLVM_DEVICE_CREATE */ +} __packed; /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_configure { /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; /* Control uses header SegmentIndex field to access bus number... */ u32 dev_no; /* bus-relative (0..n-1) device number */ -} ; /* for CONTROLVM_DEVICE_CONFIGURE */ +} __packed; /* for CONTROLVM_DEVICE_CONFIGURE */ struct controlvm_message_device_create { struct controlvm_message_header header; struct controlvm_packet_device_create packet; -}; /* total 128 bytes */ +} __packed; /* total 128 bytes */ struct controlvm_message_device_configure { struct controlvm_message_header header; struct controlvm_packet_device_configure packet; -}; /* total 56 bytes */ +} __packed; /* total 56 bytes */ /* This is the format for a message in any ControlVm queue. */ struct controlvm_message_packet { @@ -264,12 +261,12 @@ struct controlvm_message_packet { /* indicates format of data in bus channel*/ uuid_le bus_data_type_uuid; uuid_le bus_inst_uuid; /* instance uuid for the bus */ - } create_bus; /* for CONTROLVM_BUS_CREATE */ + } __packed create_bus; /* for CONTROLVM_BUS_CREATE */ struct { /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; u32 reserved; /* Natural alignment purposes */ - } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ + } __packed destroy_bus; /* for CONTROLVM_BUS_DESTROY */ struct { /* bus # (0..n-1) from the receiver's perspective */ u32 bus_no; @@ -283,26 +280,27 @@ struct controlvm_message_packet { * notifications. The corresponding * sendBusInterruptHandle is kept in CP. */ - } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ + } __packed configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_create create_device; struct { /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; u32 dev_no; /* bus-relative (0..n-1) device # */ - } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ + } __packed destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ /* for CONTROLVM_DEVICE_CONFIGURE */ struct controlvm_packet_device_configure configure_device; struct { /* bus # (0..n-1) from the msg receiver's perspective */ u32 bus_no; u32 dev_no; /* bus-relative (0..n-1) device # */ - } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ + } __packed reconfigure_device; + /* for CONTROLVM_DEVICE_RECONFIGURE */ struct { u32 bus_no; struct spar_segment_state state; u8 reserved[2]; /* Natural alignment purposes */ - } bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ + } __packed bus_change_state; /* for CONTROLVM_BUS_CHANGESTATE */ struct { u32 bus_no; u32 dev_no; @@ -310,15 +308,18 @@ struct controlvm_message_packet { struct { /* =1 if message is for a physical device */ u32 phys_device:1; - } flags; + u32 reserved:31; /* Natural alignment */ + u32 reserved1; /* Natural alignment */ + } __packed flags; u8 reserved[2]; /* Natural alignment purposes */ - } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ + } __packed device_change_state; + /* for CONTROLVM_DEVICE_CHANGESTATE */ struct { u32 bus_no; u32 dev_no; struct spar_segment_state state; u8 reserved[6]; /* Natural alignment purposes */ - } device_change_state_event; + } __packed device_change_state_event; /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ struct { /* indicates the max number of busses */ @@ -327,11 +328,12 @@ struct controlvm_message_packet { u32 switch_count; enum ultra_chipset_feature features; u32 platform_number; /* Platform Number */ - } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ + } __packed init_chipset; /* for CONTROLVM_CHIPSET_INIT */ struct { u32 options; /* reserved */ u32 test; /* bit 0 set to run embedded selftest */ - } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ + } __packed chipset_selftest; + /* for CONTROLVM_CHIPSET_SELFTEST */ /* a physical address of something, that can be dereferenced * by the receiver of this ControlVm command */ @@ -339,13 +341,13 @@ struct controlvm_message_packet { /* a handle of something (depends on command id) */ u64 handle; }; -}; +} __packed; /* All messages in any ControlVm queue have this layout. */ struct controlvm_message { struct controlvm_message_header hdr; struct controlvm_message_packet cmd; -}; +} __packed; struct spar_controlvm_channel_protocol { struct channel_header header; @@ -432,7 +434,7 @@ struct spar_controlvm_channel_protocol { /* Message stored during IOVM creation to be reused after crash */ struct controlvm_message saved_crash_msg[CONTROLVM_CRASHMSG_MAX]; -}; +} __packed; /* The following header will be located at the beginning of PayloadVmOffset for * various ControlVm commands. The receiver of a ControlVm command with a @@ -458,81 +460,81 @@ struct spar_controlvm_parameters_header { uuid_le id; u32 revision; u32 reserved; /* Natural alignment */ -}; +} __packed; /* General Errors------------------------------------------------------[0-99] */ -#define CONTROLVM_RESP_SUCCESS 0 -#define CONTROLVM_RESP_ALREADY_DONE 1 -#define CONTROLVM_RESP_IOREMAP_FAILED 2 -#define CONTROLVM_RESP_KMALLOC_FAILED 3 -#define CONTROLVM_RESP_ID_UNKNOWN 4 -#define CONTROLVM_RESP_ID_INVALID_FOR_CLIENT 5 +#define CONTROLVM_RESP_SUCCESS 0 +#define CONTROLVM_RESP_ALREADY_DONE 1 +#define CONTROLVM_RESP_IOREMAP_FAILED 2 +#define CONTROLVM_RESP_KMALLOC_FAILED 3 +#define CONTROLVM_RESP_ID_UNKNOWN 4 +#define CONTROLVM_RESP_ID_INVALID_FOR_CLIENT 5 /* CONTROLVM_INIT_CHIPSET-------------------------------------------[100-199] */ -#define CONTROLVM_RESP_CLIENT_SWITCHCOUNT_NONZERO 100 -#define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT 101 +#define CONTROLVM_RESP_CLIENT_SWITCHCOUNT_NONZERO 100 +#define CONTROLVM_RESP_EXPECTED_CHIPSET_INIT 101 /* Maximum Limit----------------------------------------------------[200-299] */ -#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ -#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_BUSES 201 /* BUS_CREATE */ +#define CONTROLVM_RESP_ERROR_MAX_DEVICES 202 /* DEVICE_CREATE */ /* Payload and Parameter Related------------------------------------[400-499] */ -#define CONTROLVM_RESP_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, - * DEVICE_CONFIGURE - */ -#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ -#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ -#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_PAYLOAD_INVALID 400 /* SWITCH_ATTACHEXTPORT, + * DEVICE_CONFIGURE + */ +#define CONTROLVM_RESP_INITIATOR_PARAMETER_INVALID 401 /* Multiple */ +#define CONTROLVM_RESP_TARGET_PARAMETER_INVALID 402 /* DEVICE_CONFIGURE */ +#define CONTROLVM_RESP_CLIENT_PARAMETER_INVALID 403 /* DEVICE_CONFIGURE */ /* Specified[Packet Structure] Value-------------------------------[500-599] */ -#define CONTROLVM_RESP_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, - * BUS_CONFIGURE, - * DEVICE_CREATE, - * DEVICE_CONFIG - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT */ - /* DEVICE_CREATE, - * DEVICE_CONFIGURE, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_CHANNEL_INVALID 502 /* DEVICE_CREATE, - * DEVICE_CONFIGURE - */ +#define CONTROLVM_RESP_BUS_INVALID 500 /* SWITCH_ATTACHINTPORT, + * BUS_CONFIGURE, + * DEVICE_CREATE, + * DEVICE_CONFIG + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_DEVICE_INVALID 501 /* SWITCH_ATTACHINTPORT*/ + /* DEVICE_CREATE, + * DEVICE_CONFIGURE, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_CHANNEL_INVALID 502 /* DEVICE_CREATE, + * DEVICE_CONFIGURE + */ /* Partition Driver Callback Interface----------------------[600-699] */ -#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ +#define CONTROLVM_RESP_VIRTPCI_DRIVER_FAILURE 604 /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ /* Unable to invoke VIRTPCI callback */ -#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR 605 /* BUS_CREATE, - * BUS_DESTROY, - * DEVICE_CREATE, - * DEVICE_DESTROY - */ +#define CONTROLVM_RESP_VIRTPCI_DRIVER_CALLBACK_ERROR 605 /* BUS_CREATE, + * BUS_DESTROY, + * DEVICE_CREATE, + * DEVICE_DESTROY + */ /* VIRTPCI Callback returned error */ -#define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR 606 - /* SWITCH_ATTACHEXTPORT, - * SWITCH_DETACHEXTPORT - * DEVICE_CONFIGURE - */ +#define CONTROLVM_RESP_GENERIC_DRIVER_CALLBACK_ERROR 606 + /* SWITCH_ATTACHEXTPORT, + * SWITCH_DETACHEXTPORT + * DEVICE_CONFIGURE + */ /* generic device callback returned error */ /* Bus Related------------------------------------------------------[700-799] */ -#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ +#define CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED 700 /* BUS_DESTROY */ /* Channel Related--------------------------------------------------[800-899] */ -#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, - * DEVICE_DESTROY - */ -#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ +#define CONTROLVM_RESP_CHANNEL_TYPE_UNKNOWN 800 /* GET_CHANNELINFO, + * DEVICE_DESTROY + */ +#define CONTROLVM_RESP_CHANNEL_SIZE_TOO_SMALL 801 /* DEVICE_CREATE */ /* Chipset Shutdown Related---------------------------------------[1000-1099] */ -#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED 1000 -#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 +#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_FAILED 1000 +#define CONTROLVM_RESP_CHIPSET_SHUTDOWN_ALREADY_ACTIVE 1001 /* Chipset Stop Related-------------------------------------------[1100-1199] */ -#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_BUS 1100 -#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_SWITCH 1101 +#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_BUS 1100 +#define CONTROLVM_RESP_CHIPSET_STOP_FAILED_SWITCH 1101 /* Device Related-------------------------------------------------[1400-1499] */ -#define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT 1400 +#define CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT 1400 #endif /* __CONTROLVMCHANNEL_H__ */ diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h index b0df26155d02..f0ef5ecf3d7d 100644 --- a/drivers/staging/unisys/visorbus/vbuschannel.h +++ b/drivers/staging/unisys/visorbus/vbuschannel.h @@ -28,8 +28,8 @@ /* {193b331b-c58f-11da-95a9-00e08161165f} */ #define SPAR_VBUS_CHANNEL_PROTOCOL_UUID \ - UUID_LE(0x193b331b, 0xc58f, 0x11da, \ - 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) + UUID_LE(0x193b331b, 0xc58f, 0x11da, \ + 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) static const uuid_le spar_vbus_channel_protocol_uuid = SPAR_VBUS_CHANNEL_PROTOCOL_UUID; @@ -43,16 +43,6 @@ static const uuid_le spar_vbus_channel_protocol_uuid = */ #define SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID 1 -#define SPAR_VBUS_CHANNEL_OK_CLIENT(ch) \ - spar_check_channel_client(ch, \ - spar_vbus_channel_protocol_uuid, \ - "vbus", \ - sizeof(struct spar_vbus_channel_protocol),\ - SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID, \ - SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE) - -#pragma pack(push, 1) /* both GCC and VC now allow this pragma */ - /* * An array of this struct is present in the channel area for each vbus. * (See vbuschannel.h.) @@ -64,42 +54,7 @@ struct ultra_vbus_deviceinfo { u8 drvname[16]; /* driver .sys file name */ u8 infostrs[96]; /* kernel version */ u8 reserved[128]; /* pad size to 256 bytes */ -}; - -/** - * vbuschannel_print_devinfo() - format a struct ultra_vbus_deviceinfo - * and write it to a seq_file - * @devinfo: the struct ultra_vbus_deviceinfo to format - * @seq: seq_file to write to - * @devix: the device index to be included in the output data, or -1 if no - * device index is to be included - * - * Reads @devInfo, and writes it in human-readable notation to @seq. - */ -static inline void -vbuschannel_print_devinfo(struct ultra_vbus_deviceinfo *devinfo, - struct seq_file *seq, int devix) -{ - if (!isprint(devinfo->devtype[0])) - return; /* uninitialized vbus device entry */ - - if (devix >= 0) - seq_printf(seq, "[%d]", devix); - else - /* vbus device entry is for bus or chipset */ - seq_puts(seq, " "); - - /* - * Note: because the s-Par back-end is free to scribble in this area, - * we never assume '\0'-termination. - */ - seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->devtype), - (int)sizeof(devinfo->devtype), devinfo->devtype); - seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->drvname), - (int)sizeof(devinfo->drvname), devinfo->drvname); - seq_printf(seq, "%.*s\n", (int)sizeof(devinfo->infostrs), - devinfo->infostrs); -} +} __packed; struct spar_vbus_headerinfo { u32 struct_bytes; /* size of this struct in bytes */ @@ -113,7 +68,7 @@ struct spar_vbus_headerinfo { u32 dev_info_offset; /* byte offset from beginning of this struct */ /* to the DevInfo array (below) */ u8 reserved[104]; -}; +} __packed; struct spar_vbus_channel_protocol { struct channel_header channel_header; /* initialized by server */ @@ -125,8 +80,6 @@ struct spar_vbus_channel_protocol { /* describes client bus device and driver */ struct ultra_vbus_deviceinfo dev_info[0]; /* describes client device and driver for each device on the bus */ -}; - -#pragma pack(pop) +} __packed; #endif diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 55f29ae8e015..a692561c81c8 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -19,21 +19,16 @@ #include "visorbus.h" #include "visorbus_private.h" -#include "vmcallinterface.h" #define MYDRVNAME "visorbus" -/* module parameters */ -static int visorbus_forcematch; -static int visorbus_forcenomatch; - /* 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_NORMALCHANNEL 10 +#define POLLJIFFIES_NORMALCHANNEL 10 -static int busreg_rc = -ENODEV; /* stores the result from bus registration */ +static bool initialized; /* stores whether bus_registration was successful */ static struct dentry *visorbus_debugfs_dir; /* @@ -87,12 +82,10 @@ visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env) dev = to_visor_device(xdev); guid = visorchannel_get_uuid(dev->visorchannel); - if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid)) - return -ENOMEM; - return 0; + return add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid); } -/** +/* * visorbus_match() - called automatically upon adding a visor_device * (device_add), or adding a visor_driver * (visorbus_register_visor_driver) @@ -113,10 +106,6 @@ visorbus_match(struct device *xdev, struct device_driver *xdrv) drv = to_visor_driver(xdrv); channel_type = visorchannel_get_uuid(dev->visorchannel); - if (visorbus_forcematch) - return 1; - if (visorbus_forcenomatch) - return 0; if (!drv->channel_types) return 0; @@ -142,10 +131,10 @@ struct bus_type visorbus_type = { .dev_groups = visorbus_dev_groups, }; -/** - * visorbus_releae_busdevice() - called when device_unregister() is called for - * the bus device instance, after all other tasks - * involved with destroying the dev are complete +/* + * visorbus_release_busdevice() - called when device_unregister() is called for + * the bus device instance, after all other tasks + * involved with destroying the dev are complete * @xdev: struct device for the bus being released */ static void @@ -158,7 +147,7 @@ visorbus_release_busdevice(struct device *xdev) kfree(dev); } -/** +/* * visorbus_release_device() - called when device_unregister() is called for * each child device instance * @xdev: struct device for the visor device being released @@ -185,8 +174,6 @@ static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr, { struct visor_device *vdev = to_visor_device(dev); - if (!vdev->visorchannel) - return 0; return sprintf(buf, "0x%llx\n", visorchannel_get_physaddr(vdev->visorchannel)); } @@ -197,8 +184,6 @@ static ssize_t nbytes_show(struct device *dev, struct device_attribute *attr, { struct visor_device *vdev = to_visor_device(dev); - if (!vdev->visorchannel) - return 0; return sprintf(buf, "0x%lx\n", visorchannel_get_nbytes(vdev->visorchannel)); } @@ -209,8 +194,6 @@ static ssize_t clientpartition_show(struct device *dev, { struct visor_device *vdev = to_visor_device(dev); - if (!vdev->visorchannel) - return 0; return sprintf(buf, "0x%llx\n", visorchannel_get_clientpartition(vdev->visorchannel)); } @@ -222,8 +205,6 @@ static ssize_t typeguid_show(struct device *dev, struct device_attribute *attr, struct visor_device *vdev = to_visor_device(dev); char typeid[LINESIZE]; - if (!vdev->visorchannel) - return 0; return sprintf(buf, "%s\n", visorchannel_id(vdev->visorchannel, typeid)); } @@ -235,8 +216,6 @@ static ssize_t zoneguid_show(struct device *dev, struct device_attribute *attr, struct visor_device *vdev = to_visor_device(dev); char zoneid[LINESIZE]; - if (!vdev->visorchannel) - return 0; return sprintf(buf, "%s\n", visorchannel_zoneid(vdev->visorchannel, zoneid)); } @@ -245,13 +224,12 @@ static DEVICE_ATTR_RO(zoneguid); static ssize_t typename_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct visor_device *vdev = to_visor_device(dev); int i = 0; struct bus_type *xbus = dev->bus; struct device_driver *xdrv = dev->driver; struct visor_driver *drv = NULL; - if (!vdev->visorchannel || !xbus || !xdrv) + if (!xbus || !xdrv) return 0; i = xbus->match(dev, xdrv); if (!i) @@ -344,11 +322,10 @@ static ssize_t channel_id_show(struct device *dev, struct visor_device *vdev = to_visor_device(dev); int len = 0; - if (vdev->visorchannel) { - visorchannel_id(vdev->visorchannel, buf); - len = strlen(buf); - buf[len++] = '\n'; - } + visorchannel_id(vdev->visorchannel, buf); + len = strlen(buf); + buf[len++] = '\n'; + return len; } static DEVICE_ATTR_RO(channel_id); @@ -378,6 +355,40 @@ static const struct attribute_group *visorbus_groups[] = { * define & implement display of debugfs attributes under * /sys/kernel/debug/visorbus/visorbus<n>. */ +/* + * vbuschannel_print_devinfo() - format a struct ultra_vbus_deviceinfo + * and write it to a seq_file + * @devinfo: the struct ultra_vbus_deviceinfo to format + * @seq: seq_file to write to + * @devix: the device index to be included in the output data, or -1 if no + * device index is to be included + * + * Reads @devInfo, and writes it in human-readable notation to @seq. + */ +static void +vbuschannel_print_devinfo(struct ultra_vbus_deviceinfo *devinfo, + struct seq_file *seq, int devix) +{ + if (!isprint(devinfo->devtype[0])) + return; /* uninitialized vbus device entry */ + + if (devix >= 0) + seq_printf(seq, "[%d]", devix); + else + /* vbus device entry is for bus or chipset */ + seq_puts(seq, " "); + + /* + * Note: because the s-Par back-end is free to scribble in this area, + * we never assume '\0'-termination. + */ + seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->devtype), + (int)sizeof(devinfo->devtype), devinfo->devtype); + seq_printf(seq, "%-*.*s ", (int)sizeof(devinfo->drvname), + (int)sizeof(devinfo->drvname), devinfo->drvname); + seq_printf(seq, "%.*s\n", (int)sizeof(devinfo->infostrs), + devinfo->infostrs); +} static int client_bus_info_debugfs_show(struct seq_file *seq, void *v) { @@ -442,16 +453,17 @@ dev_periodic_work(unsigned long __opaque) mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL); } -static void +static int dev_start_periodic_work(struct visor_device *dev) { if (dev->being_removed || dev->timer_active) - return; + return -EINVAL; /* now up by at least 2 */ get_device(&dev->device); dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL; add_timer(&dev->timer); dev->timer_active = true; + return 0; } static void @@ -464,7 +476,7 @@ dev_stop_periodic_work(struct visor_device *dev) put_device(&dev->device); } -/** +/* * visordriver_remove_device() - handle visor device going away * @xdev: struct device for the visor device being removed * @@ -557,17 +569,17 @@ EXPORT_SYMBOL_GPL(visorbus_write_channel); * Currently we don't yet have a real interrupt, so for now we just call the * interrupt function periodically via a timer. */ -void +int visorbus_enable_channel_interrupts(struct visor_device *dev) { struct visor_driver *drv = to_visor_driver(dev->device.driver); if (!drv->channel_interrupt) { dev_err(&dev->device, "%s no interrupt function!\n", __func__); - return; + return -ENOENT; } - dev_start_periodic_work(dev); + return dev_start_periodic_work(dev); } EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts); @@ -583,7 +595,7 @@ visorbus_disable_channel_interrupts(struct visor_device *dev) } EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); -/** +/* * create_visor_device() - create visor device as a result of receiving the * controlvm device_create message for a new device * @dev: a freshly-zeroed struct visor_device, containing only filled-in values @@ -613,9 +625,6 @@ create_visor_device(struct visor_device *dev) u32 chipset_bus_no = dev->chipset_bus_no; u32 chipset_dev_no = dev->chipset_dev_no; - POSTCODE_LINUX(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no, - DIAG_SEVERITY_PRINT); - mutex_init(&dev->visordriver_callback_lock); dev->device.bus = &visorbus_type; dev->device.groups = visorbus_channel_groups; @@ -630,8 +639,10 @@ create_visor_device(struct visor_device *dev) * (NOT bus instance). That's why we need to include the bus * number within the name. */ - dev_set_name(&dev->device, "vbus%u:dev%u", - chipset_bus_no, chipset_dev_no); + err = dev_set_name(&dev->device, "vbus%u:dev%u", + chipset_bus_no, chipset_dev_no); + if (err) + goto err_put; /* * device_add does this: @@ -651,17 +662,15 @@ create_visor_device(struct visor_device *dev) * bus_type.klist_devices regardless (use bus_for_each_dev). */ err = device_add(&dev->device); - if (err < 0) { - POSTCODE_LINUX(DEVICE_ADD_PC, 0, chipset_bus_no, - DIAG_SEVERITY_ERR); + if (err < 0) goto err_put; - } list_add_tail(&dev->list_all, &list_all_device_instances); return 0; /* success: reference kept via unmatched get_device() */ err_put: put_device(&dev->device); + dev_err(&dev->device, "Creating visor device failed. %d\n", err); return err; } @@ -677,24 +686,32 @@ static int get_vbus_header_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info) { - if (!SPAR_VBUS_CHANNEL_OK_CLIENT(visorchannel_get_header(chan))) + int err; + + if (!spar_check_channel(visorchannel_get_header(chan), + spar_vbus_channel_protocol_uuid, + "vbus", + sizeof(struct spar_vbus_channel_protocol), + SPAR_VBUS_CHANNEL_PROTOCOL_VERSIONID, + SPAR_VBUS_CHANNEL_PROTOCOL_SIGNATURE)) return -EINVAL; - if (visorchannel_read(chan, sizeof(struct channel_header), hdr_info, - sizeof(*hdr_info)) < 0) { - return -EIO; - } + err = visorchannel_read(chan, sizeof(struct channel_header), hdr_info, + sizeof(*hdr_info)); + if (err < 0) + return err; + if (hdr_info->struct_bytes < sizeof(struct spar_vbus_headerinfo)) return -EINVAL; if (hdr_info->device_info_struct_bytes < - sizeof(struct ultra_vbus_deviceinfo)) { + sizeof(struct ultra_vbus_deviceinfo)) return -EINVAL; - } + return 0; } -/** +/* * write_vbus_chp_info() - write the contents of <info> to the struct * spar_vbus_channel_protocol.chp_info * @chan: indentifies the s-Par channel that will be updated @@ -720,7 +737,7 @@ write_vbus_chp_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/** +/* * write_vbus_bus_info() - write the contents of <info> to the struct * spar_vbus_channel_protocol.bus_info * @chan: indentifies the s-Par channel that will be updated @@ -746,7 +763,7 @@ write_vbus_bus_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/** +/* * write_vbus_dev_info() - write the contents of <info> to the struct * spar_vbus_channel_protocol.dev_info[<devix>] * @chan: indentifies the s-Par channel that will be updated @@ -775,10 +792,26 @@ write_vbus_dev_info(struct visorchannel *chan, visorchannel_write(chan, off, info, sizeof(*info)); } -/** +static void bus_device_info_init( + struct ultra_vbus_deviceinfo *bus_device_info_ptr, + const char *dev_type, const char *drv_name) +{ + memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); + snprintf(bus_device_info_ptr->devtype, + sizeof(bus_device_info_ptr->devtype), + "%s", (dev_type) ? dev_type : "unknownType"); + snprintf(bus_device_info_ptr->drvname, + sizeof(bus_device_info_ptr->drvname), + "%s", (drv_name) ? drv_name : "unknownDriver"); + snprintf(bus_device_info_ptr->infostrs, + sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s", + utsname()->release); +} + +/* * fix_vbus_dev_info() - for a child device just created on a client bus, fill * in information about the driver that is controlling - * this device into the the appropriate slot within the + * this device into the appropriate slot within the * vbus channel of the bus instance * @visordev: struct visor_device for the desired device */ @@ -823,16 +856,12 @@ fix_vbus_dev_info(struct visor_device *visordev) bus_device_info_init(&dev_info, chan_type_name, visordrv->name); write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no); - /* - * Re-write bus+chipset info, because it is possible that this - * was previously written by our evil counterpart, virtpci. - */ write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo); write_vbus_bus_info(bdev->visorchannel, hdr_info, &clientbus_driverinfo); } -/** +/* * visordriver_probe_device() - handle new visor device coming online * @xdev: struct device for the visor device being probed * @@ -925,10 +954,8 @@ visordriver_probe_device(struct device *xdev) */ int visorbus_register_visor_driver(struct visor_driver *drv) { - int rc = 0; - - if (busreg_rc < 0) - return -ENODEV; /*can't register on a nonexistent bus*/ + if (!initialized) + return -ENODEV; /* can't register on a nonexistent bus */ drv->driver.name = drv->name; drv->driver.bus = &visorbus_type; @@ -949,14 +976,11 @@ int visorbus_register_visor_driver(struct visor_driver *drv) * dev.drv = NULL */ - rc = driver_register(&drv->driver); - if (rc < 0) - driver_unregister(&drv->driver); - return rc; + return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(visorbus_register_visor_driver); -/** +/* * create_bus_instance() - create a device instance for the visor bus itself * @dev: struct visor_device indicating the bus instance * @@ -970,8 +994,6 @@ create_bus_instance(struct visor_device *dev) int err; struct spar_vbus_headerinfo *hdr_info; - POSTCODE_LINUX(BUS_CREATE_ENTRY_PC, 0, 0, DIAG_SEVERITY_PRINT); - hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL); if (!hdr_info) return -ENOMEM; @@ -983,51 +1005,38 @@ create_bus_instance(struct visor_device *dev) dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->device), visorbus_debugfs_dir); - if (!dev->debugfs_dir) { - err = -ENOMEM; - goto err_hdr_info; - } dev->debugfs_client_bus_info = debugfs_create_file("client_bus_info", 0440, dev->debugfs_dir, dev, &client_bus_info_debugfs_fops); - if (!dev->debugfs_client_bus_info) { - err = -ENOMEM; + + dev_set_drvdata(&dev->device, dev); + err = get_vbus_header_info(dev->visorchannel, hdr_info); + if (err < 0) goto err_debugfs_dir; - } - if (device_register(&dev->device) < 0) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, 0, id, - DIAG_SEVERITY_ERR); - err = -ENODEV; - goto err_debugfs_created; - } + err = device_register(&dev->device); + if (err < 0) + goto err_debugfs_dir; - if (get_vbus_header_info(dev->visorchannel, hdr_info) >= 0) { - dev->vbus_hdr_info = (void *)hdr_info; - write_vbus_chp_info(dev->visorchannel, hdr_info, - &chipset_driverinfo); - write_vbus_bus_info(dev->visorchannel, hdr_info, - &clientbus_driverinfo); - } else { - kfree(hdr_info); - } list_add_tail(&dev->list_all, &list_all_bus_instances); - dev_set_drvdata(&dev->device, dev); - return 0; -err_debugfs_created: - debugfs_remove(dev->debugfs_client_bus_info); + dev->vbus_hdr_info = (void *)hdr_info; + write_vbus_chp_info(dev->visorchannel, hdr_info, + &chipset_driverinfo); + write_vbus_bus_info(dev->visorchannel, hdr_info, + &clientbus_driverinfo); + + return 0; err_debugfs_dir: debugfs_remove_recursive(dev->debugfs_dir); - -err_hdr_info: kfree(hdr_info); + dev_err(&dev->device, "create_bus_instance failed: %d\n", err); return err; } -/** +/* * remove_bus_instance() - remove a device instance for the visor bus itself * @dev: struct visor_device indentifying the bus to remove */ @@ -1051,30 +1060,7 @@ remove_bus_instance(struct visor_device *dev) device_unregister(&dev->device); } -/** - * create_bus_type() - create and register the one-and-only one instance of - * the visor bus type (visorbus_type) - * Return: 0 for success, otherwise negative errno value returned by - * bus_register() indicating the reason for failure - */ -static int -create_bus_type(void) -{ - busreg_rc = bus_register(&visorbus_type); - return busreg_rc; -} - -/** - * remove_bus_type() - remove the one-and-only one instance of the visor bus - * type (visorbus_type) - */ -static void -remove_bus_type(void) -{ - bus_unregister(&visorbus_type); -} - -/** +/* * remove_all_visor_devices() - remove all child visor bus device instances */ static void @@ -1090,24 +1076,19 @@ remove_all_visor_devices(void) } } -void +int chipset_bus_create(struct visor_device *dev) { - int rc; - u32 bus_no = dev->chipset_bus_no; + int err; - POSTCODE_LINUX(BUS_CREATE_ENTRY_PC, 0, bus_no, DIAG_SEVERITY_PRINT); - rc = create_bus_instance(dev); - POSTCODE_LINUX(BUS_CREATE_EXIT_PC, 0, bus_no, DIAG_SEVERITY_PRINT); + err = create_bus_instance(dev); - if (rc < 0) - POSTCODE_LINUX(BUS_CREATE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); - else - POSTCODE_LINUX(CHIPSET_INIT_SUCCESS_PC, 0, bus_no, - DIAG_SEVERITY_PRINT); + if (err < 0) + return err; + + bus_create_response(dev, err); - bus_create_response(dev, rc); + return 0; } void @@ -1117,25 +1098,18 @@ chipset_bus_destroy(struct visor_device *dev) bus_destroy_response(dev, 0); } -void +int chipset_device_create(struct visor_device *dev_info) { - int rc; - u32 bus_no = dev_info->chipset_bus_no; - u32 dev_no = dev_info->chipset_dev_no; + int err; - POSTCODE_LINUX(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, - DIAG_SEVERITY_PRINT); + err = create_visor_device(dev_info); + if (err < 0) + return err; - rc = create_visor_device(dev_info); - device_create_response(dev_info, rc); + device_create_response(dev_info, err); - if (rc < 0) - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); - else - POSTCODE_LINUX(DEVICE_CREATE_SUCCESS_PC, dev_no, bus_no, - DIAG_SEVERITY_PRINT); + return 0; } void @@ -1146,7 +1120,7 @@ chipset_device_destroy(struct visor_device *dev_info) device_destroy_response(dev_info, 0); } -/** +/* * pause_state_change_complete() - the callback function to be called by a * visorbus function driver when a * pending "pause device" operation has @@ -1166,7 +1140,7 @@ pause_state_change_complete(struct visor_device *dev, int status) device_pause_response(dev, status); } -/** +/* * resume_state_change_complete() - the callback function to be called by a * visorbus function driver when a * pending "resume device" operation has @@ -1191,7 +1165,7 @@ resume_state_change_complete(struct visor_device *dev, int status) device_resume_response(dev, status); } -/** +/* * initiate_chipset_device_pause_resume() - start a pause or resume operation * for a visor device * @dev: struct visor_device identifying the device being paused or resumed @@ -1202,70 +1176,38 @@ resume_state_change_complete(struct visor_device *dev, int status) * via a callback function; see pause_state_change_complete() and * resume_state_change_complete(). */ -static void +static int initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) { - int rc; + int err; struct visor_driver *drv = NULL; - void (*notify_func)(struct visor_device *dev, int response) = NULL; - - if (is_pause) - notify_func = device_pause_response; - else - notify_func = device_resume_response; - if (!notify_func) - return; drv = to_visor_driver(dev->device.driver); - if (!drv) { - (*notify_func)(dev, -ENODEV); - return; - } + if (!drv) + return -ENODEV; - if (dev->pausing || dev->resuming) { - (*notify_func)(dev, -EBUSY); - return; - } + if (dev->pausing || dev->resuming) + return -EBUSY; - /* - * Note that even though both drv->pause() and drv->resume - * specify a callback function, it is NOT necessary for us to - * increment our local module usage count. Reason is, there - * is already a linkage dependency between child function - * drivers and visorbus, so it is already IMPOSSIBLE to unload - * visorbus while child function drivers are still running. - */ if (is_pause) { - if (!drv->pause) { - (*notify_func)(dev, -EINVAL); - return; - } + if (!drv->pause) + return -EINVAL; dev->pausing = true; - rc = drv->pause(dev, pause_state_change_complete); + err = drv->pause(dev, pause_state_change_complete); } else { - /* This should be done at BUS resume time, but an - * existing problem prevents us from ever getting a bus - * resume... This hack would fail to work should we - * ever have a bus that contains NO devices, since we - * would never even get here in that case. + /* The vbus_dev_info structure in the channel was been + * cleared, make sure it is valid. */ fix_vbus_dev_info(dev); - if (!drv->resume) { - (*notify_func)(dev, -EINVAL); - return; - } + if (!drv->resume) + return -EINVAL; dev->resuming = true; - rc = drv->resume(dev, resume_state_change_complete); - } - if (rc < 0) { - if (is_pause) - dev->pausing = false; - else - dev->resuming = false; - (*notify_func)(dev, -EINVAL); + err = drv->resume(dev, resume_state_change_complete); } + + return err; } /** @@ -1276,10 +1218,19 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) * that device. Success/failure result is returned asynchronously * via a callback function; see pause_state_change_complete(). */ -void +int chipset_device_pause(struct visor_device *dev_info) { - initiate_chipset_device_pause_resume(dev_info, true); + int err; + + err = initiate_chipset_device_pause_resume(dev_info, true); + + if (err < 0) { + dev_info->pausing = false; + return err; + } + + return 0; } /** @@ -1290,10 +1241,19 @@ chipset_device_pause(struct visor_device *dev_info) * that device. Success/failure result is returned asynchronously * via a callback function; see resume_state_change_complete(). */ -void +int chipset_device_resume(struct visor_device *dev_info) { - initiate_chipset_device_pause_resume(dev_info, false); + int err; + + err = initiate_chipset_device_pause_resume(dev_info, false); + + if (err < 0) { + dev_info->resuming = false; + return err; + } + + return 0; } int @@ -1301,27 +1261,21 @@ visorbus_init(void) { int err; - POSTCODE_LINUX(DRIVER_ENTRY_PC, 0, 0, DIAG_SEVERITY_PRINT); - visorbus_debugfs_dir = debugfs_create_dir("visorbus", NULL); if (!visorbus_debugfs_dir) return -ENOMEM; bus_device_info_init(&clientbus_driverinfo, "clientbus", "visorbus"); - err = create_bus_type(); - if (err < 0) { - POSTCODE_LINUX(BUS_CREATE_ENTRY_PC, 0, 0, DIAG_SEVERITY_ERR); - goto error; - } + err = bus_register(&visorbus_type); + if (err < 0) + return err; + + initialized = true; bus_device_info_init(&chipset_driverinfo, "chipset", "visorchipset"); return 0; - -error: - POSTCODE_LINUX(CHIPSET_INIT_FAILURE_PC, 0, err, DIAG_SEVERITY_ERR); - return err; } void @@ -1337,14 +1291,8 @@ visorbus_exit(void) list_all); remove_bus_instance(dev); } - remove_bus_type(); + + bus_unregister(&visorbus_type); + initialized = false; debugfs_remove_recursive(visorbus_debugfs_dir); } - -module_param_named(forcematch, visorbus_forcematch, int, 0444); -MODULE_PARM_DESC(visorbus_forcematch, - "1 to force a successful dev <--> drv match"); - -module_param_named(forcenomatch, visorbus_forcenomatch, int, 0444); -MODULE_PARM_DESC(visorbus_forcenomatch, - "1 to force an UNsuccessful dev <--> drv match"); diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h index 49bec1763e33..9f030b1f589f 100644 --- a/drivers/staging/unisys/visorbus/visorbus_private.h +++ b/drivers/staging/unisys/visorbus/visorbus_private.h @@ -27,28 +27,12 @@ * command line */ -static inline void bus_device_info_init( - struct ultra_vbus_deviceinfo *bus_device_info_ptr, - const char *dev_type, const char *drv_name) -{ - memset(bus_device_info_ptr, 0, sizeof(struct ultra_vbus_deviceinfo)); - snprintf(bus_device_info_ptr->devtype, - sizeof(bus_device_info_ptr->devtype), - "%s", (dev_type) ? dev_type : "unknownType"); - snprintf(bus_device_info_ptr->drvname, - sizeof(bus_device_info_ptr->drvname), - "%s", (drv_name) ? drv_name : "unknownDriver"); - snprintf(bus_device_info_ptr->infostrs, - sizeof(bus_device_info_ptr->infostrs), "kernel ver. %s", - utsname()->release); -} - -void chipset_bus_create(struct visor_device *bus_info); +int chipset_bus_create(struct visor_device *bus_info); void chipset_bus_destroy(struct visor_device *bus_info); -void chipset_device_create(struct visor_device *dev_info); +int chipset_device_create(struct visor_device *dev_info); void chipset_device_destroy(struct visor_device *dev_info); -void chipset_device_pause(struct visor_device *dev_info); -void chipset_device_resume(struct visor_device *dev_info); +int chipset_device_pause(struct visor_device *dev_info); +int chipset_device_resume(struct visor_device *dev_info); void bus_create_response(struct visor_device *p, int response); void bus_destroy_response(struct visor_device *p, int response); @@ -81,5 +65,5 @@ u64 visorchannel_get_clientpartition(struct visorchannel *channel); int visorchannel_set_clientpartition(struct visorchannel *channel, u64 partition_handle); char *visorchannel_uuid_id(uuid_le *guid, char *s); -void __iomem *visorchannel_get_header(struct visorchannel *channel); +void *visorchannel_get_header(struct visorchannel *channel); #endif diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index e91febcc6c1e..9e1cea22ce68 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -29,8 +29,9 @@ #define MYDRVNAME "visorchannel" #define SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID \ - UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5, \ + UUID_LE(0x3cd6e705, 0xd6a2, 0x4aa5, \ 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2) + static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID; struct visorchannel { @@ -153,10 +154,10 @@ visorchannel_write(struct visorchannel *channel, ulong offset, return 0; } -void __iomem * +void * visorchannel_get_header(struct visorchannel *channel) { - return (void __iomem *)&channel->chan_hdr; + return &channel->chan_hdr; } /* @@ -173,17 +174,17 @@ visorchannel_get_header(struct visorchannel *channel) */ #define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \ (SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \ - ((slot) * (sig_hdr)->signal_size)) + ((slot) * (sig_hdr)->signal_size)) /* * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back * into host memory */ -#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ - visorchannel_write(channel, \ - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) +\ +#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ + visorchannel_write(channel, \ + SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) + \ offsetof(struct signal_queue_header, FIELD), \ - &((sig_hdr)->FIELD), \ + &((sig_hdr)->FIELD), \ sizeof((sig_hdr)->FIELD)) static int @@ -199,7 +200,7 @@ sig_read_header(struct visorchannel *channel, u32 queue, sig_hdr, sizeof(struct signal_queue_header)); } -static inline int +static int sig_read_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { @@ -210,7 +211,7 @@ sig_read_data(struct visorchannel *channel, u32 queue, data, sig_hdr->signal_size); } -static inline int +static int sig_write_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { @@ -286,16 +287,6 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) } EXPORT_SYMBOL_GPL(visorchannel_signalremove); -/** - * visorchannel_signalempty() - checks if the designated channel/queue - * contains any messages - * @channel: the channel to query - * @queue: the queue in the channel to query - * - * Return: boolean indicating whether any messages in the designated - * channel/queue are present - */ - static bool queue_empty(struct visorchannel *channel, u32 queue) { @@ -307,6 +298,15 @@ queue_empty(struct visorchannel *channel, u32 queue) return (sig_hdr.head == sig_hdr.tail); } +/** + * visorchannel_signalempty() - checks if the designated channel/queue + * contains any messages + * @channel: the channel to query + * @queue: the queue in the channel to query + * + * Return: boolean indicating whether any messages in the designated + * channel/queue are present + */ bool visorchannel_signalempty(struct visorchannel *channel, u32 queue) { @@ -328,27 +328,24 @@ static int signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) { struct signal_queue_header sig_hdr; - int error; + int err; - error = sig_read_header(channel, queue, &sig_hdr); - if (error) - return error; + err = sig_read_header(channel, queue, &sig_hdr); + if (err) + return err; sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; if (sig_hdr.head == sig_hdr.tail) { sig_hdr.num_overflows++; - visorchannel_write(channel, - SIG_QUEUE_OFFSET(&channel->chan_hdr, queue) + - offsetof(struct signal_queue_header, - num_overflows), - &sig_hdr.num_overflows, - sizeof(sig_hdr.num_overflows)); + err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows); + if (err) + return err; return -EIO; } - error = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); - if (error) - return error; + err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); + if (err) + return err; sig_hdr.num_sent++; @@ -358,17 +355,17 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) */ mb(); /* required for channel synch */ - error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); - if (error) - return error; - error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); - if (error) - return error; + err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); + if (err) + return err; + err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); + if (err) + return err; return 0; } -/** +/* * visorchannel_create_guts() - creates the struct visorchannel abstraction * for a data area in memory, but does NOT modify * this data area @@ -418,12 +415,9 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, * release later on. */ channel->requested = request_mem_region(physaddr, size, MYDRVNAME); - if (!channel->requested) { - if (uuid_le_cmp(guid, spar_video_guid)) { - /* Not the video channel we care about this */ - goto err_destroy_channel; - } - } + if (!channel->requested && uuid_le_cmp(guid, spar_video_guid)) + /* we only care about errors if this is not the video channel */ + goto err_destroy_channel; channel->mapped = memremap(physaddr, size, MEMREMAP_WB); if (!channel->mapped) { @@ -451,12 +445,9 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, channel->mapped = NULL; channel->requested = request_mem_region(channel->physaddr, channel_bytes, MYDRVNAME); - if (!channel->requested) { - if (uuid_le_cmp(guid, spar_video_guid)) { - /* Different we care about this */ - goto err_destroy_channel; - } - } + if (!channel->requested && uuid_le_cmp(guid, spar_video_guid)) + /* we only care about errors if this is not the video channel */ + goto err_destroy_channel; channel->mapped = memremap(channel->physaddr, channel_bytes, MEMREMAP_WB); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 97778d733e1e..4cfd0fae9bd5 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -15,13 +15,11 @@ */ #include <linux/acpi.h> -#include <linux/cdev.h> #include <linux/ctype.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/nls.h> #include <linux/netdevice.h> -#include <linux/platform_device.h> #include <linux/uuid.h> #include <linux/crash_dump.h> @@ -31,13 +29,11 @@ #define CURRENT_FILE_PC VISOR_BUS_PC_visorchipset_c -#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 +#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 #define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128) -#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 - #define UNISYS_SPAR_LEAF_ID 0x40000000 /* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */ @@ -46,35 +42,11 @@ #define UNISYS_SPAR_ID_EDX 0x34367261 /* - * Module parameters - */ -static int visorchipset_major; - -static int -visorchipset_open(struct inode *inode, struct file *file) -{ - unsigned int minor_number = iminor(inode); - - if (minor_number) - return -ENODEV; - return 0; -} - -static int -visorchipset_release(struct inode *inode, struct file *file) -{ - return 0; -} - -/* * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, * we switch to slow polling mode. As soon as we get a controlvm * message, we switch back to fast polling mode. */ #define MIN_IDLE_SECONDS 10 -static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -/* when we got our last controlvm message */ -static unsigned long most_recent_message_jiffies; struct parser_context { unsigned long allocbytes; @@ -85,22 +57,33 @@ struct parser_context { char data[0]; }; -static struct delayed_work periodic_controlvm_work; - -static struct cdev file_cdev; -static struct visorchannel **file_controlvm_channel; +struct vmcall_controlvm_addr { + struct vmcall_io_controlvm_addr_params params; + int err; + u64 physaddr; +}; -static struct visorchannel *controlvm_channel; -static unsigned long controlvm_payload_bytes_buffered; +struct visorchipset_device { + struct acpi_device *acpi_device; + unsigned long poll_jiffies; + /* when we got our last controlvm message */ + unsigned long most_recent_message_jiffies; + struct delayed_work periodic_controlvm_work; + struct visorchannel *controlvm_channel; + unsigned long controlvm_payload_bytes_buffered; + /* + * The following variables are used to handle the scenario where we are + * unable to offload the payload from a controlvm message due to memory + * requirements. In this scenario, we simply stash the controlvm + * message, then attempt to process it again the next time + * controlvm_periodic_work() runs. + */ + struct controlvm_message controlvm_pending_msg; + bool controlvm_pending_msg_valid; + struct vmcall_controlvm_addr controlvm_addr; +}; -/* - * The following globals are used to handle the scenario where we are unable to - * offload the payload from a controlvm message due to memory requirements. In - * this scenario, we simply stash the controlvm message, then attempt to - * process it again the next time controlvm_periodic_work() runs. - */ -static struct controlvm_message controlvm_pending_msg; -static bool controlvm_pending_msg_valid; +static struct visorchipset_device *chipset_dev; struct parahotplug_request { struct list_head list; @@ -109,19 +92,21 @@ struct parahotplug_request { struct controlvm_message msg; }; -/* info for /dev/visorchipset */ -static dev_t major_dev = -1; /*< indicates major num for device */ - /* prototypes for attributes */ static ssize_t toolaction_show(struct device *dev, struct device_attribute *attr, char *buf) { u8 tool_action = 0; + int err; + + err = visorchannel_read(chipset_dev->controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + tool_action), + &tool_action, sizeof(u8)); + if (err) + return err; - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); return sprintf(buf, "%u\n", tool_action); } @@ -130,19 +115,19 @@ static ssize_t toolaction_store(struct device *dev, const char *buf, size_t count) { u8 tool_action; - int ret; + int err; if (kstrtou8(buf, 10, &tool_action)) return -EINVAL; - ret = visorchannel_write - (controlvm_channel, + err = visorchannel_write + (chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, tool_action), &tool_action, sizeof(u8)); - if (ret) - return ret; + if (err) + return err; return count; } static DEVICE_ATTR_RW(toolaction); @@ -152,11 +137,16 @@ static ssize_t boottotool_show(struct device *dev, char *buf) { struct efi_spar_indication efi_spar_indication; + int err; + + err = visorchannel_read(chipset_dev->controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + efi_spar_ind), + &efi_spar_indication, + sizeof(struct efi_spar_indication)); - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - efi_spar_ind), &efi_spar_indication, - sizeof(struct efi_spar_indication)); + if (err) + return err; return sprintf(buf, "%u\n", efi_spar_indication.boot_to_tool); } @@ -164,21 +154,21 @@ static ssize_t boottotool_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - int val, ret; + int val, err; struct efi_spar_indication efi_spar_indication; if (kstrtoint(buf, 10, &val)) return -EINVAL; efi_spar_indication.boot_to_tool = val; - ret = visorchannel_write - (controlvm_channel, + err = visorchannel_write + (chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, efi_spar_ind), &(efi_spar_indication), sizeof(struct efi_spar_indication)); - if (ret) - return ret; + if (err) + return err; return count; } static DEVICE_ATTR_RW(boottotool); @@ -187,11 +177,14 @@ static ssize_t error_show(struct device *dev, struct device_attribute *attr, char *buf) { u32 error = 0; + int err; - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_error), - &error, sizeof(u32)); + err = visorchannel_read(chipset_dev->controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_error), + &error, sizeof(u32)); + if (err) + return err; return sprintf(buf, "%i\n", error); } @@ -199,18 +192,18 @@ static ssize_t error_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u32 error; - int ret; + int err; if (kstrtou32(buf, 10, &error)) return -EINVAL; - ret = visorchannel_write - (controlvm_channel, + err = visorchannel_write + (chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, installation_error), &error, sizeof(u32)); - if (ret) - return ret; + if (err) + return err; return count; } static DEVICE_ATTR_RW(error); @@ -219,12 +212,16 @@ static ssize_t textid_show(struct device *dev, struct device_attribute *attr, char *buf) { u32 text_id = 0; + int err; + + err = visorchannel_read + (chipset_dev->controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_text_id), + &text_id, sizeof(u32)); + if (err) + return err; - visorchannel_read - (controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_text_id), - &text_id, sizeof(u32)); return sprintf(buf, "%i\n", text_id); } @@ -232,18 +229,18 @@ static ssize_t textid_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u32 text_id; - int ret; + int err; if (kstrtou32(buf, 10, &text_id)) return -EINVAL; - ret = visorchannel_write - (controlvm_channel, + err = visorchannel_write + (chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, installation_text_id), &text_id, sizeof(u32)); - if (ret) - return ret; + if (err) + return err; return count; } static DEVICE_ATTR_RW(textid); @@ -252,11 +249,15 @@ static ssize_t remaining_steps_show(struct device *dev, struct device_attribute *attr, char *buf) { u16 remaining_steps = 0; + int err; + + err = visorchannel_read(chipset_dev->controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + installation_remaining_steps), + &remaining_steps, sizeof(u16)); + if (err) + return err; - visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - installation_remaining_steps), - &remaining_steps, sizeof(u16)); return sprintf(buf, "%hu\n", remaining_steps); } @@ -265,18 +266,18 @@ static ssize_t remaining_steps_store(struct device *dev, const char *buf, size_t count) { u16 remaining_steps; - int ret; + int err; if (kstrtou16(buf, 10, &remaining_steps)) return -EINVAL; - ret = visorchannel_write - (controlvm_channel, + err = visorchannel_write + (chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, installation_remaining_steps), &remaining_steps, sizeof(u16)); - if (ret) - return ret; + if (err) + return err; return count; } static DEVICE_ATTR_RW(remaining_steps); @@ -292,7 +293,7 @@ parser_id_get(struct parser_context *ctx) static void parser_done(struct parser_context *ctx) { - controlvm_payload_bytes_buffered -= ctx->param_bytes; + chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes; kfree(ctx); } @@ -318,7 +319,7 @@ parser_string_get(struct parser_context *ctx) } if (value_length < 0) /* '\0' was not included in the length */ value_length = nscan; - value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY); + value = kmalloc(value_length + 1, GFP_KERNEL); if (!value) return NULL; if (value_length > 0) @@ -405,7 +406,7 @@ controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr, controlvm_init_response(&outmsg, msg_hdr, response); outmsg.cmd.init_chipset.features = features; - return visorchannel_signalinsert(controlvm_channel, + return visorchannel_signalinsert(chipset_dev->controlvm_channel, CONTROLVM_QUEUE_REQUEST, &outmsg); } @@ -417,14 +418,12 @@ chipset_init(struct controlvm_message *inmsg) int rc = CONTROLVM_RESP_SUCCESS; int res = 0; - POSTCODE_LINUX(CHIPSET_INIT_ENTRY_PC, 0, 0, DIAG_SEVERITY_PRINT); if (chipset_inited) { rc = -CONTROLVM_RESP_ALREADY_DONE; res = -EIO; goto out_respond; } chipset_inited = 1; - POSTCODE_LINUX(CHIPSET_INIT_EXIT_PC, 0, 0, DIAG_SEVERITY_PRINT); /* * Set features to indicate we support parahotplug (if Command @@ -447,7 +446,8 @@ out_respond: } static int -controlvm_respond(struct controlvm_message_header *msg_hdr, int response) +controlvm_respond(struct controlvm_message_header *msg_hdr, int response, + struct spar_segment_state *state) { struct controlvm_message outmsg; @@ -455,20 +455,12 @@ controlvm_respond(struct controlvm_message_header *msg_hdr, int response) if (outmsg.hdr.flags.test_message == 1) return -EINVAL; - return visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_REQUEST, &outmsg); -} - -static int controlvm_respond_physdev_changestate( - struct controlvm_message_header *msg_hdr, int response, - struct spar_segment_state state) -{ - struct controlvm_message outmsg; + if (state) { + outmsg.cmd.device_change_state.state = *state; + outmsg.cmd.device_change_state.flags.phys_device = 1; + } - controlvm_init_response(&outmsg, msg_hdr, response); - outmsg.cmd.device_change_state.state = state; - outmsg.cmd.device_change_state.flags.phys_device = 1; - return visorchannel_signalinsert(controlvm_channel, + return visorchannel_signalinsert(chipset_dev->controlvm_channel, CONTROLVM_QUEUE_REQUEST, &outmsg); } @@ -484,68 +476,68 @@ save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ) u16 local_crash_msg_count; int err; - err = visorchannel_read(controlvm_channel, + err = visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, saved_crash_message_count), &local_crash_msg_count, sizeof(u16)); if (err) { - POSTCODE_LINUX(CRASH_DEV_CTRL_RD_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read message count\n"); return err; } if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { - POSTCODE_LINUX(CRASH_DEV_COUNT_FAILURE_PC, 0, - local_crash_msg_count, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "invalid number of messages\n"); return -EIO; } - err = visorchannel_read(controlvm_channel, + err = visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, saved_crash_message_offset), &local_crash_msg_offset, sizeof(u32)); if (err) { - POSTCODE_LINUX(CRASH_DEV_CTRL_RD_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read offset\n"); return err; } switch (typ) { case CRASH_DEV: local_crash_msg_offset += sizeof(struct controlvm_message); - err = visorchannel_write(controlvm_channel, + err = visorchannel_write(chipset_dev->controlvm_channel, local_crash_msg_offset, msg, sizeof(struct controlvm_message)); if (err) { - POSTCODE_LINUX(SAVE_MSG_DEV_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to write dev msg\n"); return err; } break; case CRASH_BUS: - err = visorchannel_write(controlvm_channel, + err = visorchannel_write(chipset_dev->controlvm_channel, local_crash_msg_offset, msg, sizeof(struct controlvm_message)); if (err) { - POSTCODE_LINUX(SAVE_MSG_BUS_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to write bus msg\n"); return err; } break; default: - pr_info("Invalid crash_obj_type\n"); + dev_err(&chipset_dev->acpi_device->dev, + "Invalid crash_obj_type\n"); break; } return 0; } static int -bus_responder(enum controlvm_id cmd_id, - struct controlvm_message_header *pending_msg_hdr, - int response) +controlvm_responder(enum controlvm_id cmd_id, + struct controlvm_message_header *pending_msg_hdr, + int response) { if (!pending_msg_hdr) return -EIO; @@ -553,7 +545,7 @@ bus_responder(enum controlvm_id cmd_id, if (pending_msg_hdr->id != (u32)cmd_id) return -EINVAL; - return controlvm_respond(pending_msg_hdr, response); + return controlvm_respond(pending_msg_hdr, response, NULL); } static int @@ -576,25 +568,11 @@ device_changestate_responder(enum controlvm_id cmd_id, outmsg.cmd.device_change_state.dev_no = dev_no; outmsg.cmd.device_change_state.state = response_state; - return visorchannel_signalinsert(controlvm_channel, + return visorchannel_signalinsert(chipset_dev->controlvm_channel, CONTROLVM_QUEUE_REQUEST, &outmsg); } static int -device_responder(enum controlvm_id cmd_id, - struct controlvm_message_header *pending_msg_hdr, - int response) -{ - if (!pending_msg_hdr) - return -EIO; - - if (pending_msg_hdr->id != (u32)cmd_id) - return -EINVAL; - - return controlvm_respond(pending_msg_hdr, response); -} - -static int bus_create(struct controlvm_message *inmsg) { struct controlvm_message_packet *cmd = &inmsg->cmd; @@ -606,16 +584,14 @@ bus_create(struct controlvm_message *inmsg) bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (bus_info && (bus_info->state.created == 1)) { - POSTCODE_LINUX(BUS_CREATE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed bus_create: already exists\n"); err = -EEXIST; goto err_respond; } bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL); if (!bus_info) { - POSTCODE_LINUX(BUS_CREATE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); err = -ENOMEM; goto err_respond; } @@ -624,8 +600,6 @@ bus_create(struct controlvm_message *inmsg) bus_info->chipset_bus_no = bus_no; bus_info->chipset_dev_no = BUS_ROOT_DEVICE; - POSTCODE_LINUX(BUS_CREATE_ENTRY_PC, 0, bus_no, DIAG_SEVERITY_PRINT); - if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { err = save_crash_message(inmsg, CRASH_BUS); if (err) @@ -636,9 +610,6 @@ bus_create(struct controlvm_message *inmsg) pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { - POSTCODE_LINUX(MALLOC_FAILURE_PC, cmd, - bus_info->chipset_bus_no, - DIAG_SEVERITY_ERR); err = -ENOMEM; goto err_free_bus_info; } @@ -654,19 +625,22 @@ bus_create(struct controlvm_message *inmsg) cmd->create_bus.bus_data_type_uuid); if (!visorchannel) { - POSTCODE_LINUX(BUS_CREATE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); err = -ENOMEM; goto err_free_pending_msg; } bus_info->visorchannel = visorchannel; /* Response will be handled by chipset_bus_create */ - chipset_bus_create(bus_info); + err = chipset_bus_create(bus_info); + /* If error chipset_bus_create didn't respond, need to respond here */ + if (err) + goto err_destroy_channel; - POSTCODE_LINUX(BUS_CREATE_EXIT_PC, 0, bus_no, DIAG_SEVERITY_PRINT); return 0; +err_destroy_channel: + visorchannel_destroy(visorchannel); + err_free_pending_msg: kfree(bus_info->pending_msg_hdr); @@ -675,7 +649,7 @@ err_free_bus_info: err_respond: if (inmsg->hdr.flags.response_expected == 1) - bus_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -705,9 +679,6 @@ bus_destroy(struct controlvm_message *inmsg) if (inmsg->hdr.flags.response_expected == 1) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { - POSTCODE_LINUX(MALLOC_FAILURE_PC, cmd, - bus_info->chipset_bus_no, - DIAG_SEVERITY_ERR); err = -ENOMEM; goto err_respond; } @@ -723,7 +694,7 @@ bus_destroy(struct controlvm_message *inmsg) err_respond: if (inmsg->hdr.flags.response_expected == 1) - bus_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -737,23 +708,14 @@ bus_configure(struct controlvm_message *inmsg, int err = 0; bus_no = cmd->configure_bus.bus_no; - POSTCODE_LINUX(BUS_CONFIGURE_ENTRY_PC, 0, bus_no, - DIAG_SEVERITY_PRINT); - bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (!bus_info) { - POSTCODE_LINUX(BUS_CONFIGURE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); err = -EINVAL; goto err_respond; } else if (bus_info->state.created == 0) { - POSTCODE_LINUX(BUS_CONFIGURE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); err = -EINVAL; goto err_respond; } else if (bus_info->pending_msg_hdr) { - POSTCODE_LINUX(BUS_CONFIGURE_FAILURE_PC, 0, bus_no, - DIAG_SEVERITY_ERR); err = -EIO; goto err_respond; } @@ -769,16 +731,15 @@ bus_configure(struct controlvm_message *inmsg, bus_info->name = parser_name_get(parser_ctx); } - POSTCODE_LINUX(BUS_CONFIGURE_EXIT_PC, 0, bus_no, - DIAG_SEVERITY_PRINT); - if (inmsg->hdr.flags.response_expected == 1) - bus_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return 0; err_respond: + dev_err(&chipset_dev->acpi_device->dev, + "bus_configured exited with err: %d\n", err); if (inmsg->hdr.flags.response_expected == 1) - bus_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -796,31 +757,29 @@ my_device_create(struct controlvm_message *inmsg) bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL); if (!bus_info) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to get bus by id: %d\n", bus_no); err = -ENODEV; goto err_respond; } if (bus_info->state.created == 0) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "bus not created, id: %d\n", bus_no); err = -EINVAL; goto err_respond; } dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL); if (dev_info && (dev_info->state.created == 1)) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to get bus by id: %d/%d\n", bus_no, dev_no); err = -EEXIST; goto err_respond; } dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL); if (!dev_info) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); err = -ENOMEM; goto err_respond; } @@ -832,9 +791,6 @@ my_device_create(struct controlvm_message *inmsg) /* not sure where the best place to set the 'parent' */ dev_info->device.parent = &bus_info->device; - POSTCODE_LINUX(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, - DIAG_SEVERITY_PRINT); - visorchannel = visorchannel_create_with_lock(cmd->create_device.channel_addr, cmd->create_device.channel_bytes, @@ -842,8 +798,9 @@ my_device_create(struct controlvm_message *inmsg) cmd->create_device.data_type_uuid); if (!visorchannel) { - POSTCODE_LINUX(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to create visorchannel: %d/%d\n", + bus_no, dev_no); err = -ENOMEM; goto err_free_dev_info; } @@ -853,14 +810,14 @@ my_device_create(struct controlvm_message *inmsg) spar_vhba_channel_protocol_uuid) == 0) { err = save_crash_message(inmsg, CRASH_DEV); if (err) - goto err_free_dev_info; + goto err_destroy_visorchannel; } if (inmsg->hdr.flags.response_expected == 1) { pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL); if (!pmsg_hdr) { err = -ENOMEM; - goto err_free_dev_info; + goto err_destroy_visorchannel; } memcpy(pmsg_hdr, &inmsg->hdr, @@ -868,17 +825,21 @@ my_device_create(struct controlvm_message *inmsg) dev_info->pending_msg_hdr = pmsg_hdr; } /* Chipset_device_create will send response */ - chipset_device_create(dev_info); - POSTCODE_LINUX(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, - DIAG_SEVERITY_PRINT); + err = chipset_device_create(dev_info); + if (err) + goto err_destroy_visorchannel; + return 0; +err_destroy_visorchannel: + visorchannel_destroy(visorchannel); + err_free_dev_info: kfree(dev_info); err_respond: if (inmsg->hdr.flags.response_expected == 1) - device_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -891,18 +852,14 @@ my_device_changestate(struct controlvm_message *inmsg) u32 dev_no = cmd->device_change_state.dev_no; struct spar_segment_state state = cmd->device_change_state.state; struct visor_device *dev_info; - int err; + int err = 0; dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL); if (!dev_info) { - POSTCODE_LINUX(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); err = -ENODEV; goto err_respond; } if (dev_info->state.created == 0) { - POSTCODE_LINUX(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no, - DIAG_SEVERITY_ERR); err = -EINVAL; goto err_respond; } @@ -926,7 +883,7 @@ my_device_changestate(struct controlvm_message *inmsg) if (state.alive == segment_state_running.alive && state.operating == segment_state_running.operating) /* Response will be sent from chipset_device_resume */ - chipset_device_resume(dev_info); + err = chipset_device_resume(dev_info); /* ServerNotReady / ServerLost / SegmentStateStandby */ else if (state.alive == segment_state_standby.alive && state.operating == segment_state_standby.operating) @@ -934,12 +891,16 @@ my_device_changestate(struct controlvm_message *inmsg) * technically this is standby case where server is lost. * Response will be sent from chipset_device_pause. */ - chipset_device_pause(dev_info); + err = chipset_device_pause(dev_info); + if (err) + goto err_respond; + return 0; err_respond: + dev_err(&chipset_dev->acpi_device->dev, "failed: %d\n", err); if (inmsg->hdr.flags.response_expected == 1) - device_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -985,7 +946,7 @@ my_device_destroy(struct controlvm_message *inmsg) err_respond: if (inmsg->hdr.flags.response_expected == 1) - device_responder(inmsg->hdr.id, &inmsg->hdr, err); + controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err); return err; } @@ -1004,7 +965,7 @@ err_respond: #define PARAHOTPLUG_TIMEOUT_MS 2000 -/** +/* * parahotplug_next_id() - generate unique int to match an outstanding * CONTROLVM message with a udev script /sys * response @@ -1019,7 +980,7 @@ parahotplug_next_id(void) return atomic_inc_return(&id); } -/** +/* * parahotplug_next_expiration() - returns the time (in jiffies) when a * CONTROLVM message on the list should expire * -- PARAHOTPLUG_TIMEOUT_MS in the future @@ -1032,7 +993,7 @@ parahotplug_next_expiration(void) return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); } -/** +/* * parahotplug_request_create() - create a parahotplug_request, which is * basically a wrapper for a CONTROLVM_MESSAGE * that we can stick on a list @@ -1045,7 +1006,7 @@ parahotplug_request_create(struct controlvm_message *msg) { struct parahotplug_request *req; - req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY); + req = kmalloc(sizeof(*req), GFP_KERNEL); if (!req) return NULL; @@ -1056,7 +1017,7 @@ parahotplug_request_create(struct controlvm_message *msg) return req; } -/** +/* * parahotplug_request_destroy() - free a parahotplug_request * @req: the request to deallocate */ @@ -1069,7 +1030,7 @@ parahotplug_request_destroy(struct parahotplug_request *req) static LIST_HEAD(parahotplug_request_list); static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */ -/** +/* * parahotplug_request_complete() - mark request as complete * @id: the id of the request * @active: indicates whether the request is assigned to active partition @@ -1101,9 +1062,9 @@ parahotplug_request_complete(int id, u16 active) spin_unlock(¶hotplug_request_list_lock); req->msg.cmd.device_change_state.state.active = active; if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( - &req->msg.hdr, CONTROLVM_RESP_SUCCESS, - req->msg.cmd.device_change_state.state); + controlvm_respond( + &req->msg.hdr, CONTROLVM_RESP_SUCCESS, + &req->msg.cmd.device_change_state.state); parahotplug_request_destroy(req); return 0; } @@ -1113,7 +1074,7 @@ parahotplug_request_complete(int id, u16 active) return -EINVAL; } -/** +/* * devicedisabled_store() - disables the hotplug device * @dev: sysfs interface variable not utilized in this function * @attr: sysfs interface variable not utilized in this function @@ -1143,7 +1104,7 @@ static ssize_t devicedisabled_store(struct device *dev, } static DEVICE_ATTR_WO(devicedisabled); -/** +/* * deviceenabled_store() - enables the hotplug device * @dev: sysfs interface variable not utilized in this function * @attr: sysfs interface variable not utilized in this function @@ -1201,26 +1162,14 @@ static const struct attribute_group *visorchipset_dev_groups[] = { NULL }; -static void visorchipset_dev_release(struct device *dev) -{ -} - -/* /sys/devices/platform/visorchipset */ -static struct platform_device visorchipset_platform_device = { - .name = "visorchipset", - .id = -1, - .dev.groups = visorchipset_dev_groups, - .dev.release = visorchipset_dev_release, -}; - -/** +/* * parahotplug_request_kickoff() - initiate parahotplug request * @req: the request to initiate * * Cause uevent to run the user level script to do the disable/enable specified * in the parahotplug_request. */ -static void +static int parahotplug_request_kickoff(struct parahotplug_request *req) { struct controlvm_message_packet *cmd = &req->msg.cmd; @@ -1241,56 +1190,59 @@ parahotplug_request_kickoff(struct parahotplug_request *req) sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d", cmd->device_change_state.dev_no & 0x7); - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); + return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj, + KOBJ_CHANGE, envp); } -/** +/* * parahotplug_process_message() - enables or disables a PCI device by kicking * off a udev script * @inmsg: the message indicating whether to enable or disable */ -static void +static int parahotplug_process_message(struct controlvm_message *inmsg) { struct parahotplug_request *req; + int err; req = parahotplug_request_create(inmsg); if (!req) - return; + return -ENOMEM; + /* + * For enable messages, just respond with success right away, we don't + * need to wait to see if the enable was successful. + */ if (inmsg->cmd.device_change_state.state.active) { - /* - * For enable messages, just respond with success - * right away. This is a bit of a hack, but there are - * issues with the early enable messages we get (with - * either the udev script not detecting that the device - * is up, or not getting called at all). Fortunately - * the messages that get lost don't matter anyway, as - * - * devices are automatically enabled at - * initialization. - */ - parahotplug_request_kickoff(req); - controlvm_respond_physdev_changestate - (&inmsg->hdr, - CONTROLVM_RESP_SUCCESS, - inmsg->cmd.device_change_state.state); + err = parahotplug_request_kickoff(req); + if (err) + goto err_respond; + controlvm_respond(&inmsg->hdr, CONTROLVM_RESP_SUCCESS, + &inmsg->cmd.device_change_state.state); parahotplug_request_destroy(req); - } else { - /* - * For disable messages, add the request to the - * request list before kicking off the udev script. It - * won't get responded to until the script has - * indicated it's done. - */ - spin_lock(¶hotplug_request_list_lock); - list_add_tail(&req->list, ¶hotplug_request_list); - spin_unlock(¶hotplug_request_list_lock); - - parahotplug_request_kickoff(req); + return 0; } + + /* + * For disable messages, add the request to the + * request list before kicking off the udev script. It + * won't get responded to until the script has + * indicated it's done. + */ + spin_lock(¶hotplug_request_list_lock); + list_add_tail(&req->list, ¶hotplug_request_list); + spin_unlock(¶hotplug_request_list_lock); + + err = parahotplug_request_kickoff(req); + if (err) + goto err_respond; + return 0; + +err_respond: + controlvm_respond(&inmsg->hdr, err, + &inmsg->cmd.device_change_state.state); + return err; } /* @@ -1303,12 +1255,15 @@ parahotplug_process_message(struct controlvm_message *inmsg) static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr) { - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE); + int res; + + res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, + KOBJ_ONLINE); if (msg_hdr->flags.response_expected) - return controlvm_respond(msg_hdr, CONTROLVM_RESP_SUCCESS); + controlvm_respond(msg_hdr, res, NULL); - return 0; + return res; } /* @@ -1323,15 +1278,16 @@ chipset_selftest_uevent(struct controlvm_message_header *msg_hdr) { char env_selftest[20]; char *envp[] = { env_selftest, NULL }; + int res; sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1); - kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE, - envp); + res = kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj, + KOBJ_CHANGE, envp); if (msg_hdr->flags.response_expected) - return controlvm_respond(msg_hdr, CONTROLVM_RESP_SUCCESS); + controlvm_respond(msg_hdr, res, NULL); - return 0; + return res; } /* @@ -1344,28 +1300,62 @@ chipset_selftest_uevent(struct controlvm_message_header *msg_hdr) static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr) { - kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE); + int res; + res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, + KOBJ_OFFLINE); if (msg_hdr->flags.response_expected) - return controlvm_respond(msg_hdr, CONTROLVM_RESP_SUCCESS); + controlvm_respond(msg_hdr, res, NULL); - return 0; + return res; } -static inline unsigned int -issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) +static int unisys_vmcall(unsigned long tuple, unsigned long param) { - struct vmcall_io_controlvm_addr_params params; - int result = VMCALL_SUCCESS; - u64 physaddr; + int result = 0; + unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; + unsigned long reg_ebx; + unsigned long reg_ecx; + + reg_ebx = param & 0xFFFFFFFF; + reg_ecx = param >> 32; + + cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); + if (!(cpuid_ecx & 0x80000000)) + return -EPERM; + + __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : + "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); + + if (result) + goto error; - physaddr = virt_to_phys(¶ms); - ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result); - if (VMCALL_SUCCESSFUL(result)) { - *control_addr = params.address; - *control_bytes = params.channel_bytes; + return 0; + +error: /* Need to convert from VMCALL error codes to Linux */ + switch (result) { + case VMCALL_RESULT_INVALID_PARAM: + return -EINVAL; + case VMCALL_RESULT_DATA_UNAVAILABLE: + return -ENODEV; + default: + return -EFAULT; } - return result; +} +static unsigned int +issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes) +{ + chipset_dev->controlvm_addr.physaddr = virt_to_phys( + &chipset_dev->controlvm_addr.params); + chipset_dev->controlvm_addr.err = unisys_vmcall(VMCALL_CONTROLVM_ADDR, + chipset_dev->controlvm_addr.physaddr); + if (chipset_dev->controlvm_addr.err) + return chipset_dev->controlvm_addr.err; + + *control_addr = chipset_dev->controlvm_addr.params.address; + *control_bytes = chipset_dev->controlvm_addr.params.channel_bytes; + + return 0; } static u64 controlvm_get_channel_address(void) @@ -1373,7 +1363,7 @@ static u64 controlvm_get_channel_address(void) u64 addr = 0; u32 size = 0; - if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size))) + if (issue_vmcall_io_controlvm_addr(&addr, &size)) return 0; return addr; @@ -1388,8 +1378,6 @@ setup_crash_devices_work_queue(struct work_struct *work) u32 local_crash_msg_offset; u16 local_crash_msg_count; - POSTCODE_LINUX(CRASH_DEV_ENTRY_PC, 0, 0, DIAG_SEVERITY_PRINT); - /* send init chipset msg */ msg.hdr.id = CONTROLVM_CHIPSET_INIT; msg.cmd.init_chipset.bus_count = 23; @@ -1398,71 +1386,67 @@ setup_crash_devices_work_queue(struct work_struct *work) chipset_init(&msg); /* get saved message count */ - if (visorchannel_read(controlvm_channel, + if (visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, saved_crash_message_count), &local_crash_msg_count, sizeof(u16)) < 0) { - POSTCODE_LINUX(CRASH_DEV_CTRL_RD_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read channel\n"); return; } if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { - POSTCODE_LINUX(CRASH_DEV_COUNT_FAILURE_PC, 0, - local_crash_msg_count, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "invalid count\n"); return; } /* get saved crash message offset */ - if (visorchannel_read(controlvm_channel, + if (visorchannel_read(chipset_dev->controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, saved_crash_message_offset), &local_crash_msg_offset, sizeof(u32)) < 0) { - POSTCODE_LINUX(CRASH_DEV_CTRL_RD_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read channel\n"); return; } /* read create device message for storage bus offset */ - if (visorchannel_read(controlvm_channel, + if (visorchannel_read(chipset_dev->controlvm_channel, local_crash_msg_offset, &local_crash_bus_msg, sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX(CRASH_DEV_RD_BUS_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read channel\n"); return; } /* read create device message for storage device */ - if (visorchannel_read(controlvm_channel, + if (visorchannel_read(chipset_dev->controlvm_channel, local_crash_msg_offset + sizeof(struct controlvm_message), &local_crash_dev_msg, sizeof(struct controlvm_message)) < 0) { - POSTCODE_LINUX(CRASH_DEV_RD_DEV_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + dev_err(&chipset_dev->acpi_device->dev, + "failed to read channel\n"); return; } /* reuse IOVM create bus message */ - if (local_crash_bus_msg.cmd.create_bus.channel_addr) { - bus_create(&local_crash_bus_msg); - } else { - POSTCODE_LINUX(CRASH_DEV_BUS_NULL_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + if (!local_crash_bus_msg.cmd.create_bus.channel_addr) { + dev_err(&chipset_dev->acpi_device->dev, + "no valid create_bus message\n"); return; } + bus_create(&local_crash_bus_msg); /* reuse create device message for storage device */ - if (local_crash_dev_msg.cmd.create_device.channel_addr) { - my_device_create(&local_crash_dev_msg); - } else { - POSTCODE_LINUX(CRASH_DEV_DEV_NULL_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); + if (!local_crash_dev_msg.cmd.create_device.channel_addr) { + dev_err(&chipset_dev->acpi_device->dev, + "no valid create_device message\n"); return; } - POSTCODE_LINUX(CRASH_DEV_EXIT_PC, 0, 0, DIAG_SEVERITY_PRINT); + my_device_create(&local_crash_dev_msg); } void @@ -1471,8 +1455,8 @@ bus_create_response(struct visor_device *bus_info, int response) if (response >= 0) bus_info->state.created = 1; - bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr, - response); + controlvm_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr, + response); kfree(bus_info->pending_msg_hdr); bus_info->pending_msg_hdr = NULL; @@ -1481,8 +1465,8 @@ bus_create_response(struct visor_device *bus_info, int response) void bus_destroy_response(struct visor_device *bus_info, int response) { - bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr, - response); + controlvm_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr, + response); kfree(bus_info->pending_msg_hdr); bus_info->pending_msg_hdr = NULL; @@ -1494,8 +1478,8 @@ device_create_response(struct visor_device *dev_info, int response) if (response >= 0) dev_info->state.created = 1; - device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr, - response); + controlvm_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr, + response); kfree(dev_info->pending_msg_hdr); dev_info->pending_msg_hdr = NULL; @@ -1504,8 +1488,8 @@ device_create_response(struct visor_device *dev_info, int response) void device_destroy_response(struct visor_device *dev_info, int response) { - device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr, - response); + controlvm_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr, + response); kfree(dev_info->pending_msg_hdr); dev_info->pending_msg_hdr = NULL; @@ -1534,136 +1518,6 @@ device_resume_response(struct visor_device *dev_info, int response) dev_info->pending_msg_hdr = NULL; } -static int -visorchipset_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned long physaddr = 0; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - u64 addr = 0; - - /* sv_enable_dfp(); */ - if (offset & (PAGE_SIZE - 1)) - return -ENXIO; /* need aligned offsets */ - - switch (offset) { - case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: - vma->vm_flags |= VM_IO; - if (!*file_controlvm_channel) - return -ENXIO; - - visorchannel_read - (*file_controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - gp_control_channel), - &addr, sizeof(addr)); - if (!addr) - return -ENXIO; - - physaddr = (unsigned long)addr; - if (remap_pfn_range(vma, vma->vm_start, - physaddr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - /*pgprot_noncached */ - (vma->vm_page_prot))) { - return -EAGAIN; - } - break; - default: - return -ENXIO; - } - return 0; -} - -static inline s64 issue_vmcall_query_guest_virtual_time_offset(void) -{ - u64 result = VMCALL_SUCCESS; - u64 physaddr = 0; - - ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr, - result); - return result; -} - -static inline int issue_vmcall_update_physical_time(u64 adjustment) -{ - int result = VMCALL_SUCCESS; - - ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result); - return result; -} - -static long visorchipset_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - u64 adjustment; - s64 vrtc_offset; - - switch (cmd) { - case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET: - /* get the physical rtc offset */ - vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); - if (copy_to_user((void __user *)arg, &vrtc_offset, - sizeof(vrtc_offset))) { - return -EFAULT; - } - return 0; - case VMCALL_UPDATE_PHYSICAL_TIME: - if (copy_from_user(&adjustment, (void __user *)arg, - sizeof(adjustment))) { - return -EFAULT; - } - return issue_vmcall_update_physical_time(adjustment); - default: - return -EFAULT; - } -} - -static const struct file_operations visorchipset_fops = { - .owner = THIS_MODULE, - .open = visorchipset_open, - .read = NULL, - .write = NULL, - .unlocked_ioctl = visorchipset_ioctl, - .release = visorchipset_release, - .mmap = visorchipset_mmap, -}; - -static int -visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) -{ - int rc = 0; - - file_controlvm_channel = controlvm_channel; - cdev_init(&file_cdev, &visorchipset_fops); - file_cdev.owner = THIS_MODULE; - if (MAJOR(major_dev) == 0) { - rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset"); - /* dynamic major device number registration required */ - if (rc < 0) - return rc; - } else { - /* static major device number registration required */ - rc = register_chrdev_region(major_dev, 1, "visorchipset"); - if (rc < 0) - return rc; - } - rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1); - if (rc < 0) { - unregister_chrdev_region(major_dev, 1); - return rc; - } - 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 struct parser_context * parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) { @@ -1677,12 +1531,12 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) * '\0'-terminated */ allocbytes++; - if ((controlvm_payload_bytes_buffered + bytes) + if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) > MAX_CONTROLVM_PAYLOAD_BYTES) { *retry = true; return NULL; } - ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); + ctx = kzalloc(allocbytes, GFP_KERNEL); if (!ctx) { *retry = true; return NULL; @@ -1710,7 +1564,7 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) } ctx->byte_stream = true; - controlvm_payload_bytes_buffered += ctx->param_bytes; + chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes; return ctx; @@ -1719,22 +1573,20 @@ err_finish_ctx: return NULL; } -/** +/* * handle_command() - process a controlvm message * @inmsg: the message to process * @channel_addr: address of the controlvm channel * * Return: - * false - this function will return false only in the case where the - * controlvm message was NOT processed, but processing must be - * retried before reading the next controlvm message; a - * scenario where this can occur is when we need to throttle - * the allocation of memory in which to copy out controlvm - * payload data - * true - processing of the controlvm message completed, - * either successfully or with an error + * 0 - Successfully processed the message + * -EAGAIN - ControlVM message was not processed and should be retried + * reading the next controlvm message; a scenario where this can + * occur is when we need to throttle the allocation of memory in + * which to copy out controlvm payload data. + * < 0 - error: ControlVM message was processed but an error occurred. */ -static bool +static int handle_command(struct controlvm_message inmsg, u64 channel_addr) { struct controlvm_message_packet *cmd = &inmsg.cmd; @@ -1743,11 +1595,13 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) struct parser_context *parser_ctx = NULL; bool local_addr; struct controlvm_message ackmsg; + int err = 0; /* create parsing context if necessary */ local_addr = (inmsg.hdr.flags.test_message == 1); if (channel_addr == 0) - return true; + return -EINVAL; + parm_addr = channel_addr + inmsg.hdr.payload_vm_offset; parm_bytes = inmsg.hdr.payload_bytes; @@ -1763,66 +1617,69 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) parser_init_byte_stream(parm_addr, parm_bytes, local_addr, &retry); if (!parser_ctx && retry) - return false; + return -EAGAIN; } if (!local_addr) { controlvm_init_response(&ackmsg, &inmsg.hdr, CONTROLVM_RESP_SUCCESS); - if (controlvm_channel) - visorchannel_signalinsert(controlvm_channel, - CONTROLVM_QUEUE_ACK, - &ackmsg); + err = visorchannel_signalinsert(chipset_dev->controlvm_channel, + CONTROLVM_QUEUE_ACK, + &ackmsg); + if (err) + return err; } switch (inmsg.hdr.id) { case CONTROLVM_CHIPSET_INIT: - chipset_init(&inmsg); + err = chipset_init(&inmsg); break; case CONTROLVM_BUS_CREATE: - bus_create(&inmsg); + err = bus_create(&inmsg); break; case CONTROLVM_BUS_DESTROY: - bus_destroy(&inmsg); + err = bus_destroy(&inmsg); break; case CONTROLVM_BUS_CONFIGURE: - bus_configure(&inmsg, parser_ctx); + err = bus_configure(&inmsg, parser_ctx); break; case CONTROLVM_DEVICE_CREATE: - my_device_create(&inmsg); + err = my_device_create(&inmsg); break; case CONTROLVM_DEVICE_CHANGESTATE: if (cmd->device_change_state.flags.phys_device) { - parahotplug_process_message(&inmsg); + err = parahotplug_process_message(&inmsg); } else { /* * save the hdr and cmd structures for later use * when sending back the response to Command */ - my_device_changestate(&inmsg); + err = my_device_changestate(&inmsg); break; } break; case CONTROLVM_DEVICE_DESTROY: - my_device_destroy(&inmsg); + err = my_device_destroy(&inmsg); break; case CONTROLVM_DEVICE_CONFIGURE: - /* no op for now, just send a respond that we passed */ + /* no op just send a respond that we passed */ if (inmsg.hdr.flags.response_expected) - controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS); + controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS, + NULL); break; case CONTROLVM_CHIPSET_READY: - chipset_ready_uevent(&inmsg.hdr); + err = chipset_ready_uevent(&inmsg.hdr); break; case CONTROLVM_CHIPSET_SELFTEST: - chipset_selftest_uevent(&inmsg.hdr); + err = chipset_selftest_uevent(&inmsg.hdr); break; case CONTROLVM_CHIPSET_STOP: - chipset_notready_uevent(&inmsg.hdr); + err = chipset_notready_uevent(&inmsg.hdr); break; default: + err = -ENOMSG; if (inmsg.hdr.flags.response_expected) - controlvm_respond - (&inmsg.hdr, -CONTROLVM_RESP_ID_UNKNOWN); + controlvm_respond(&inmsg.hdr, + -CONTROLVM_RESP_ID_UNKNOWN, NULL); break; } @@ -1830,31 +1687,35 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr) parser_done(parser_ctx); parser_ctx = NULL; } - return true; + return err; } -/** +/* * read_controlvm_event() - retreives the next message from the * CONTROLVM_QUEUE_EVENT queue in the controlvm * channel * @msg: pointer to the retrieved message * - * Return: true if a valid message was retrieved or false otherwise + * Return: 0 if valid message was retrieved or -error */ -static bool +static int read_controlvm_event(struct controlvm_message *msg) { - if (!visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_EVENT, msg)) { - /* got a message */ - if (msg->hdr.flags.test_message == 1) - return false; - return true; - } - return false; + int err; + + err = visorchannel_signalremove(chipset_dev->controlvm_channel, + CONTROLVM_QUEUE_EVENT, msg); + if (err) + return err; + + /* got a message */ + if (msg->hdr.flags.test_message == 1) + return -EINVAL; + + return 0; } -/** +/* * parahotplug_process_list() - remove any request from the list that's been on * there too long and respond with an error */ @@ -1875,10 +1736,10 @@ parahotplug_process_list(void) list_del(pos); if (req->msg.hdr.flags.response_expected) - controlvm_respond_physdev_changestate( + controlvm_respond( &req->msg.hdr, CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT, - req->msg.cmd.device_change_state.state); + &req->msg.cmd.device_change_state.state); parahotplug_request_destroy(req); } @@ -1889,67 +1750,70 @@ static void controlvm_periodic_work(struct work_struct *work) { struct controlvm_message inmsg; - bool got_command = false; - bool handle_command_failed = false; - - while (!visorchannel_signalremove(controlvm_channel, - CONTROLVM_QUEUE_RESPONSE, - &inmsg)) - ; - if (!got_command) { - if (controlvm_pending_msg_valid) { - /* - * we throttled processing of a prior - * msg, so try to process it again - * rather than reading a new one - */ - inmsg = controlvm_pending_msg; - controlvm_pending_msg_valid = false; - got_command = true; - } else { - got_command = read_controlvm_event(&inmsg); - } + int count = 0; + int err; + + /* Drain the RESPONSE queue make it empty */ + do { + err = visorchannel_signalremove(chipset_dev->controlvm_channel, + CONTROLVM_QUEUE_RESPONSE, + &inmsg); + } while ((!err) && (++count < CONTROLVM_MESSAGE_MAX)); + + if (err != -EAGAIN) + goto schedule_out; + + if (chipset_dev->controlvm_pending_msg_valid) { + /* + * we throttled processing of a prior + * msg, so try to process it again + * rather than reading a new one + */ + inmsg = chipset_dev->controlvm_pending_msg; + chipset_dev->controlvm_pending_msg_valid = false; + err = 0; + } else { + err = read_controlvm_event(&inmsg); } - handle_command_failed = false; - while (got_command && (!handle_command_failed)) { - most_recent_message_jiffies = jiffies; - if (handle_command(inmsg, - visorchannel_get_physaddr - (controlvm_channel))) - got_command = read_controlvm_event(&inmsg); - else { - /* - * this is a scenario where throttling - * is required, but probably NOT an - * error...; we stash the current - * controlvm msg so we will attempt to - * reprocess it on our next loop - */ - handle_command_failed = true; - controlvm_pending_msg = inmsg; - controlvm_pending_msg_valid = true; + while (!err) { + chipset_dev->most_recent_message_jiffies = jiffies; + err = handle_command(inmsg, + visorchannel_get_physaddr + (chipset_dev->controlvm_channel)); + if (err == -EAGAIN) { + chipset_dev->controlvm_pending_msg = inmsg; + chipset_dev->controlvm_pending_msg_valid = true; + break; } + + err = read_controlvm_event(&inmsg); } /* parahotplug_worker */ parahotplug_process_list(); - if (time_after(jiffies, - most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) { +schedule_out: + if (time_after(jiffies, chipset_dev->most_recent_message_jiffies + + (HZ * MIN_IDLE_SECONDS))) { /* * it's been longer than MIN_IDLE_SECONDS since we * processed our last controlvm message; slow down the * polling */ - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; + if (chipset_dev->poll_jiffies != + POLLJIFFIES_CONTROLVMCHANNEL_SLOW) + chipset_dev->poll_jiffies = + POLLJIFFIES_CONTROLVMCHANNEL_SLOW; } else { - if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST) - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + if (chipset_dev->poll_jiffies != + POLLJIFFIES_CONTROLVMCHANNEL_FAST) + chipset_dev->poll_jiffies = + POLLJIFFIES_CONTROLVMCHANNEL_FAST; } - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); + schedule_delayed_work(&chipset_dev->periodic_controlvm_work, + chipset_dev->poll_jiffies); } static int @@ -1958,81 +1822,84 @@ visorchipset_init(struct acpi_device *acpi_device) int err = -ENODEV; u64 addr; uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID; + struct visorchannel *controlvm_channel; + + chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL); + if (!chipset_dev) + goto error; addr = controlvm_get_channel_address(); if (!addr) goto error; - controlvm_channel = visorchannel_create_with_lock(addr, 0, - GFP_KERNEL, uuid); + acpi_device->driver_data = chipset_dev; + + chipset_dev->acpi_device = acpi_device; + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + controlvm_channel = visorchannel_create_with_lock(addr, + 0, GFP_KERNEL, uuid); + if (!controlvm_channel) - goto error; + goto error_free_chipset_dev; - if (!SPAR_CONTROLVM_CHANNEL_OK_CLIENT( - visorchannel_get_header(controlvm_channel))) - goto error_destroy_channel; + chipset_dev->controlvm_channel = controlvm_channel; - major_dev = MKDEV(visorchipset_major, 0); - err = visorchipset_file_init(major_dev, &controlvm_channel); + err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj, + visorchipset_dev_groups); if (err < 0) goto error_destroy_channel; + if (!SPAR_CONTROLVM_CHANNEL_OK_CLIENT( + visorchannel_get_header(controlvm_channel))) + goto error_delete_groups; + /* if booting in a crash kernel */ if (is_kdump_kernel()) - INIT_DELAYED_WORK(&periodic_controlvm_work, + INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, setup_crash_devices_work_queue); else - INIT_DELAYED_WORK(&periodic_controlvm_work, + INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, controlvm_periodic_work); - most_recent_message_jiffies = jiffies; - poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); - - visorchipset_platform_device.dev.devt = major_dev; - if (platform_device_register(&visorchipset_platform_device) < 0) { - POSTCODE_LINUX(DEVICE_REGISTER_FAILURE_PC, 0, 0, - DIAG_SEVERITY_ERR); - err = -ENODEV; - goto error_cancel_work; - } - POSTCODE_LINUX(CHIPSET_INIT_SUCCESS_PC, 0, 0, DIAG_SEVERITY_PRINT); + chipset_dev->most_recent_message_jiffies = jiffies; + chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; + schedule_delayed_work(&chipset_dev->periodic_controlvm_work, + chipset_dev->poll_jiffies); err = visorbus_init(); if (err < 0) - goto error_unregister; + goto error_cancel_work; 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); + cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work); + +error_delete_groups: + sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj, + visorchipset_dev_groups); error_destroy_channel: - visorchannel_destroy(controlvm_channel); + visorchannel_destroy(chipset_dev->controlvm_channel); + +error_free_chipset_dev: + kfree(chipset_dev); error: - POSTCODE_LINUX(CHIPSET_INIT_FAILURE_PC, 0, err, DIAG_SEVERITY_ERR); + dev_err(&acpi_device->dev, "failed with error %d\n", err); return err; } static int visorchipset_exit(struct acpi_device *acpi_device) { - POSTCODE_LINUX(DRIVER_EXIT_PC, 0, 0, DIAG_SEVERITY_PRINT); - visorbus_exit(); + cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work); + sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj, + visorchipset_dev_groups); - cancel_delayed_work_sync(&periodic_controlvm_work); - - visorchannel_destroy(controlvm_channel); - - visorchipset_file_cleanup(visorchipset_platform_device.dev.devt); - platform_device_unregister(&visorchipset_platform_device); - POSTCODE_LINUX(DRIVER_EXIT_PC, 0, 0, DIAG_SEVERITY_PRINT); + visorchannel_destroy(chipset_dev->controlvm_channel); + kfree(chipset_dev); return 0; } @@ -2050,12 +1917,12 @@ static struct acpi_driver unisys_acpi_driver = { .ops = { .add = visorchipset_init, .remove = visorchipset_exit, - }, + }, }; MODULE_DEVICE_TABLE(acpi, unisys_device_ids); -static __init uint32_t visorutil_spar_detect(void) +static __init int visorutil_spar_detect(void) { unsigned int eax, ebx, ecx, edx; @@ -2090,10 +1957,6 @@ static void exit_unisys(void) acpi_bus_unregister_driver(&unisys_acpi_driver); } -module_param_named(major, visorchipset_major, int, 0444); -MODULE_PARM_DESC(visorchipset_major, - "major device number to use for the device node"); - module_init(init_unisys); module_exit(exit_unisys); diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h index d1d72c184e29..cc70e1b16bda 100644 --- a/drivers/staging/unisys/visorbus/vmcallinterface.h +++ b/drivers/staging/unisys/visorbus/vmcallinterface.h @@ -12,54 +12,9 @@ * details. */ -#ifndef __IOMONINTF_H__ -#define __IOMONINTF_H__ +#ifndef __VMCALLINTERFACE_H__ +#define __VMCALLINTERFACE_H__ -/* - * This file contains all structures needed to support the VMCALLs for IO - * Virtualization. The VMCALLs are provided by Monitor and used by IO code - * running on IO Partitions. - */ -static inline unsigned long -__unisys_vmcall_gnuc(unsigned long tuple, unsigned long reg_ebx, - unsigned long reg_ecx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx)); - return result; -} - -static inline unsigned long -__unisys_extended_vmcall_gnuc(unsigned long long tuple, - unsigned long long reg_ebx, - unsigned long long reg_ecx, - unsigned long long reg_edx) -{ - unsigned long result = 0; - unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - - cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx); - if (!(cpuid_ecx & 0x80000000)) - return -EPERM; - - __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) : - "a"(tuple), "b"(reg_ebx), "c"(reg_ecx), "d"(reg_edx)); - return result; -} - -#ifdef VMCALL_IO_CONTROLVM_ADDR -#undef VMCALL_IO_CONTROLVM_ADDR -#endif /* */ - -/* define subsystem number for AppOS, used in uislib driver */ -#define MDS_APPOS 0x4000000000000000L /* subsystem = 62 - AppOS */ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ /* Note: when a new VMCALL is added: * - the 1st 2 hex digits correspond to one of the @@ -72,30 +27,20 @@ enum vmcall_monitor_interface_method_tuple { /* VMCALL identification tuples */ * type of VMCALL */ /* used by all Guests, not just IO */ - VMCALL_IO_CONTROLVM_ADDR = 0x0501, - /* Allow caller to query virtual time offset */ - VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET = 0x0708, - /* LOGEVENT Post Code (RDX) with specified subsystem mask */ - /* (RCX - monitor_subsystems.h) and severity (RDX) */ - VMCALL_POST_CODE_LOGEVENT = 0x070B, - /* Allow ULTRA_SERVICE_CAPABILITY_TIME capable guest to make VMCALL */ - VMCALL_UPDATE_PHYSICAL_TIME = 0x0a02 + VMCALL_CONTROLVM_ADDR = 0x0501, }; -#define VMCALL_SUCCESS 0 -#define VMCALL_SUCCESSFUL(result) (result == 0) - -#define unisys_vmcall(tuple, reg_ebx, reg_ecx) \ - __unisys_vmcall_gnuc(tuple, reg_ebx, reg_ecx) -#define unisys_extended_vmcall(tuple, reg_ebx, reg_ecx, reg_edx) \ - __unisys_extended_vmcall_gnuc(tuple, reg_ebx, reg_ecx, reg_edx) -#define ISSUE_IO_VMCALL(method, param, result) \ - (result = unisys_vmcall(method, (param) & 0xFFFFFFFF, \ - (param) >> 32)) +enum vmcall_result { + VMCALL_RESULT_SUCCESS = 0, + VMCALL_RESULT_INVALID_PARAM = 1, + VMCALL_RESULT_DATA_UNAVAILABLE = 2, + VMCALL_RESULT_FAILURE_UNAVAILABLE = 3, + VMCALL_RESULT_DEVICE_ERROR = 4, + VMCALL_RESULT_DEVICE_NOT_READY = 5 +}; /* Structures for IO VMCALLs */ - -/* Parameters to VMCALL_IO_CONTROLVM_ADDR interface */ +/* Parameters to VMCALL_CONTROLVM_ADDR interface */ struct vmcall_io_controlvm_addr_params { /* The Guest-relative physical address of the ControlVm channel. */ /* This VMCall fills this in with the appropriate address. */ @@ -106,72 +51,4 @@ struct vmcall_io_controlvm_addr_params { u8 unused[4]; /* Unused Bytes in the 64-Bit Aligned Struct */ } __packed; -/******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ -enum driver_pc { /* POSTCODE driver identifier tuples */ - /* visorbus driver files */ - VISOR_BUS_PC = 0xF0, - VISOR_BUS_PC_visorbus_main_c = 0xFF, - VISOR_BUS_PC_visorchipset_c = 0xFE, -}; - -enum event_pc { /* POSTCODE event identifier tuples */ - BUS_CREATE_ENTRY_PC = 0x001, - BUS_CREATE_FAILURE_PC = 0x002, - BUS_CREATE_EXIT_PC = 0x003, - BUS_CONFIGURE_ENTRY_PC = 0x004, - BUS_CONFIGURE_FAILURE_PC = 0x005, - BUS_CONFIGURE_EXIT_PC = 0x006, - CHIPSET_INIT_ENTRY_PC = 0x007, - CHIPSET_INIT_SUCCESS_PC = 0x008, - CHIPSET_INIT_FAILURE_PC = 0x009, - CHIPSET_INIT_EXIT_PC = 0x00A, - CONTROLVM_INIT_FAILURE_PC = 0x00B, - DEVICE_CREATE_ENTRY_PC = 0x00C, - DEVICE_CREATE_FAILURE_PC = 0x00D, - DEVICE_CREATE_SUCCESS_PC = 0x00E, - DEVICE_CREATE_EXIT_PC = 0x00F, - DEVICE_ADD_PC = 0x010, - DEVICE_REGISTER_FAILURE_PC = 0x011, - DEVICE_CHANGESTATE_FAILURE_PC = 0x012, - DRIVER_ENTRY_PC = 0x013, - DRIVER_EXIT_PC = 0x014, - MALLOC_FAILURE_PC = 0x015, - CRASH_DEV_ENTRY_PC = 0x016, - CRASH_DEV_EXIT_PC = 0x017, - CRASH_DEV_RD_BUS_FAILURE_PC = 0x018, - CRASH_DEV_RD_DEV_FAILURE_PC = 0x019, - CRASH_DEV_BUS_NULL_FAILURE_PC = 0x01A, - CRASH_DEV_DEV_NULL_FAILURE_PC = 0x01B, - CRASH_DEV_CTRL_RD_FAILURE_PC = 0x01C, - CRASH_DEV_COUNT_FAILURE_PC = 0x01D, - SAVE_MSG_BUS_FAILURE_PC = 0x01E, - SAVE_MSG_DEV_FAILURE_PC = 0x01F, -}; - -/* Write a 64-bit value to the hypervisor's log file - * POSTCODE_LINUX generates a value in the form 0xAABBBCCCDDDDEEEE where - * A is an identifier for the file logging the postcode - * B is an identifier for the event logging the postcode - * C is the line logging the postcode - * D is additional information the caller wants to log - * E is additional information the caller wants to log - * Please also note that the resulting postcode is in hex, so if you are - * searching for the __LINE__ number, convert it first to decimal. The line - * number combined with driver and type of call, will allow you to track down - * exactly what line an error occurred on, or where the last driver - * entered/exited from. - */ - -#define POSTCODE_LINUX(EVENT_PC, pc16bit1, pc16bit2, severity) \ -do { \ - unsigned long long post_code_temp; \ - post_code_temp = (((u64)CURRENT_FILE_PC) << 56) | \ - (((u64)EVENT_PC) << 44) | \ - ((((u64)__LINE__) & 0xFFF) << 32) | \ - ((((u64)pc16bit1) & 0xFFFF) << 16) | \ - (((u64)pc16bit2) & 0xFFFF); \ - unisys_extended_vmcall(VMCALL_POST_CODE_LOGEVENT, severity, \ - MDS_APPOS, post_code_temp); \ -} while (0) - -#endif /* __IOMONINTF_H__ */ +#endif /* __VMCALLINTERFACE_H__ */ |