From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/staging/unisys/visorbus/controlvmchannel.h | 237 +++++++++++---------- drivers/staging/unisys/visorbus/vbusdeviceinfo.h | 7 +- drivers/staging/unisys/visorbus/visorbus_main.c | 97 ++++----- drivers/staging/unisys/visorbus/visorchannel.c | 22 +- drivers/staging/unisys/visorbus/visorchipset.c | 165 ++++++++------ 5 files changed, 278 insertions(+), 250 deletions(-) (limited to 'drivers/staging/unisys/visorbus') diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index ec25366b1..03e36fb6a 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -55,22 +55,25 @@ #define CONTROLVM_CRASHMSG_MAX 2 struct spar_segment_state { - u16 enabled:1; /* Bit 0: May enter other states */ - u16 active:1; /* Bit 1: Assigned to active partition */ - u16 alive:1; /* Bit 2: Configure message sent to - * service/server */ - u16 revoked:1; /* Bit 3: similar to partition state - * ShuttingDown */ - u16 allocated:1; /* Bit 4: memory (device/port number) - * has been selected by Command */ - u16 known:1; /* Bit 5: has been introduced to the - * service/guest partition */ - u16 ready:1; /* Bit 6: service/Guest partition has - * responded to introduction */ - u16 operating:1; /* Bit 7: resource is configured and - * operating */ - /* Note: don't use high bit unless we need to switch to ushort - * which is non-compliant */ + /* Bit 0: May enter other states */ + u16 enabled:1; + /* Bit 1: Assigned to active partition */ + u16 active:1; + /* Bit 2: Configure message sent to service/server */ + u16 alive:1; + /* Bit 3: similar to partition state ShuttingDown */ + u16 revoked:1; + /* Bit 4: memory (device/port number) has been selected by Command */ + u16 allocated:1; + /* Bit 5: has been introduced to the service/guest partition */ + u16 known:1; + /* Bit 6: service/Guest partition has responded to introduction */ + u16 ready:1; + /* Bit 7: resource is configured and operating */ + u16 operating:1; +/* Note: don't use high bit unless we need to switch to ushort + * which is non-compliant + */ }; static const struct spar_segment_state segment_state_running = { @@ -177,53 +180,53 @@ struct controlvm_message_header { /* For requests, indicates the message type. */ /* For responses, indicates the type of message we are responding to. */ - u32 message_size; /* Includes size of this struct + size - * of message */ - u32 segment_index; /* Index of segment containing Vm - * message/information */ - u32 completion_status; /* Error status code or result of - * message completion */ + /* Includes size of this struct + size of message */ + u32 message_size; + /* Index of segment containing Vm message/information */ + u32 segment_index; + /* Error status code or result of message completion */ + u32 completion_status; struct { - u32 failed:1; /* =1 in a response to * signify - * failure */ - u32 response_expected:1; /* =1 in all messages that expect a - * response (Control ignores this - * bit) */ - u32 server:1; /* =1 in all bus & device-related - * messages where the message - * receiver is to act as the bus or - * device server */ - u32 test_message:1; /* =1 for testing use only - * (Control and Command ignore this - * bit) */ - u32 partial_completion:1; /* =1 if there are forthcoming - * responses/acks associated - * with this message */ - u32 preserve:1; /* =1 this is to let us know to - * preserve channel contents - * (for running guests)*/ - u32 writer_in_diag:1; /* =1 the DiagWriter is active in the - * Diagnostic Partition*/ + /* =1 in a response to signify failure */ + u32 failed:1; + /* =1 in all messages that expect a response */ + u32 response_expected:1; + /* =1 in all bus & device-related messages where the message + * receiver is to act as the bus or device server + */ + u32 server:1; + /* =1 for testing use only (Control and Command ignore this */ + u32 test_message:1; + /* =1 if there are forthcoming responses/acks associated + * with this message + */ + u32 partial_completion:1; + /* =1 this is to let us know to preserve channel contents */ + u32 preserve:1; + /* =1 the DiagWriter is active in the Diagnostic Partition */ + u32 writer_in_diag:1; } flags; - u32 reserved; /* Natural alignment */ - u64 message_handle; /* Identifies the particular message instance, - * and is used to match particular */ + /* Natural alignment */ + u32 reserved; + /* Identifies the particular message instance */ + u64 message_handle; /* request instances with the corresponding response instance. */ - u64 payload_vm_offset; /* Offset of payload area from start of this - * instance of ControlVm segment */ - u32 payload_max_bytes; /* Maximum bytes allocated in payload - * area of ControlVm segment */ - u32 payload_bytes; /* Actual number of bytes of payload - * area to copy between IO/Command; */ + /* Offset of payload area from start of this instance */ + u64 payload_vm_offset; + /* Maximum bytes allocated in payload area of ControlVm segment */ + u32 payload_max_bytes; + /* Actual number of bytes of payload area to copy between IO/Command */ + u32 payload_bytes; /* if non-zero, there is a payload to copy. */ }; struct controlvm_packet_device_create { u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ u32 dev_no; /* bus-relative (0..n-1) device number */ - u64 channel_addr; /* Guest physical address of the channel, which - * can be dereferenced by the receiver of this - * ControlVm command */ + /* Guest physical address of the channel, which can be dereferenced by + * the receiver of this ControlVm command + */ + u64 channel_addr; u64 channel_bytes; /* specifies size of the channel in bytes */ uuid_le data_type_uuid; /* specifies format of data in channel */ uuid_le dev_inst_uuid; /* instance guid for the device */ @@ -231,8 +234,8 @@ struct controlvm_packet_device_create { }; /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_configure { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* 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 */ @@ -251,50 +254,50 @@ struct controlvm_message_device_configure { struct controlvm_message_packet { union { struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_count; /* indicates the max number of - * devices on this bus */ - u64 channel_addr; /* Guest physical address of - * the channel, which can be - * dereferenced by the receiver - * of this ControlVm command */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; + /* indicates the max number of devices on this bus */ + u32 dev_count; + /* Guest physical address of the channel, which can be + * dereferenced by the receiver of this ControlVm command + */ + u64 channel_addr; u64 channel_bytes; /* size of the channel */ - uuid_le bus_data_type_uuid; /* indicates format of - * data in bus channel*/ + /* 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 */ struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; u32 reserved; /* Natural alignment purposes */ } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ struct { - u32 bus_no; /* bus # (0..n-1) from the receiver's - * perspective */ + /* bus # (0..n-1) from the receiver's perspective */ + u32 bus_no; u32 reserved1; /* for alignment purposes */ - u64 guest_handle; /* This is used to convert - * guest physical address to - * physical address */ + /* This is used to convert guest physical address to physical address */ + u64 guest_handle; u64 recv_bus_irq_handle; /* specifies interrupt info. It is used by SP * to register to receive interrupts from the * CP. This interrupt is used for bus level * notifications. The corresponding - * sendBusInterruptHandle is kept in CP. */ + * sendBusInterruptHandle is kept in CP. + */ } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_create create_device; struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* 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 */ /* for CONTROLVM_DEVICE_CONFIGURE */ struct controlvm_packet_device_configure configure_device; struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* 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 */ struct { @@ -307,8 +310,8 @@ struct controlvm_message_packet { u32 dev_no; struct spar_segment_state state; struct { - u32 phys_device:1; /* =1 if message is for - * a physical device */ + /* =1 if message is for a physical device */ + u32 phys_device:1; } flags; u8 reserved[2]; /* Natural alignment purposes */ } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ @@ -320,9 +323,10 @@ struct controlvm_message_packet { } device_change_state_event; /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ struct { - u32 bus_count; /* indicates the max number of busses */ - u32 switch_count; /* indicates the max number of - * switches if a service partition */ + /* indicates the max number of busses */ + u32 bus_count; + /* indicates the max number of switches */ + u32 switch_count; enum ultra_chipset_feature features; u32 platform_number; /* Platform Number */ } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ @@ -330,11 +334,12 @@ struct controlvm_message_packet { u32 options; /* reserved */ u32 test; /* bit 0 set to run embedded selftest */ } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ - u64 addr; /* a physical address of something, that can be - * dereferenced by the receiver of this - * ControlVm command (depends on command id) */ - u64 handle; /* a handle of something (depends on command - * id) */ + /* a physical address of something, that can be dereferenced + * by the receiver of this ControlVm command + */ + u64 addr; + /* a handle of something (depends on command id) */ + u64 handle; }; }; @@ -357,8 +362,8 @@ struct spar_controlvm_channel_protocol { u64 gp_nvram; /* guest phys addr of NVRAM channel */ u64 request_payload_offset; /* Offset to request payload area */ u64 event_payload_offset; /* Offset to event payload area */ - u32 request_payload_bytes; /* Bytes available in request payload - * area */ + /* Bytes available in request payload area */ + u32 request_payload_bytes; u32 event_payload_bytes;/* Bytes available in event payload area */ u32 control_channel_bytes; u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ @@ -384,41 +389,37 @@ struct spar_controlvm_channel_protocol { u64 virtual_guest_image_size; u64 prototype_control_channel_offset; u64 virtual_guest_partition_handle; - - u16 restore_action; /* Restore Action field to restore the guest - * partition */ - u16 dump_action; /* For Windows guests it shows if the visordisk - * is running in dump mode */ + /* Restore Action field to restore the guest partition */ + u16 restore_action; + /* For Windows guests it shows if the visordisk is in dump mode */ + u16 dump_action; u16 nvram_fail_count; u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ - u32 saved_crash_message_offset; /* Offset to request payload area needed - * for crash dump */ - u32 installation_error; /* Type of error encountered during - * installation */ + /* Offset to request payload area needed for crash dump */ + u32 saved_crash_message_offset; + /* Type of error encountered during installation */ + u32 installation_error; u32 installation_text_id; /* Id of string to display */ - u16 installation_remaining_steps;/* Number of remaining installation - * steps (for progress bars) */ - u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action - * field */ + /* Number of remaining installation steps (for progress bars) */ + u16 installation_remaining_steps; + /* ULTRA_TOOL_ACTIONS Installation Action field */ + u8 tool_action; u8 reserved; /* alignment */ struct efi_spar_indication efi_spar_ind; struct efi_spar_indication efi_spar_ind_supported; u32 sp_reserved; - u8 reserved2[28]; /* Force signals to begin on 128-byte cache - * line */ - struct signal_queue_header request_queue;/* Service or guest partition - * uses this queue to send - * requests to Control */ - struct signal_queue_header response_queue;/* Control uses this queue to - * respond to service or guest - * partition requests */ - struct signal_queue_header event_queue; /* Control uses this queue to - * send events to service or - * guest partition */ - struct signal_queue_header event_ack_queue;/* Service or guest partition - * uses this queue to ack - * Control events */ - + /* Force signals to begin on 128-byte cache line */ + u8 reserved2[28]; + /* guest partition uses this queue to send requests to Control */ + struct signal_queue_header request_queue; + /* Control uses this queue to respond to service or guest + * partition requests + */ + struct signal_queue_header response_queue; + /* Control uses this queue to send events to guest partition */ + struct signal_queue_header event_queue; + /* Service or guest partition uses this queue to ack Control events */ + struct signal_queue_header event_ack_queue; /* Request fixed-size message pool - does not include payload */ struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h index f59fd8a52..abdab4ad0 100644 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h @@ -62,7 +62,7 @@ vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) p++; remain--; chars++; - } else if (p == NULL) { + } else if (!p) { chars++; } nonprintable_streak = 0; @@ -72,7 +72,7 @@ vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) p++; remain--; chars++; - } else if (p == NULL) { + } else if (!p) { chars++; } } else { @@ -124,7 +124,8 @@ vbuschannel_itoa(char *p, int remain, int num) } if (remain < digits) { /* not enough room left at

to hold number, so fill with - * '?' */ + * '?' + */ for (i = 0; i < remain; i++, p++) *p = '?'; return remain; diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index eac97d222..533bb5b3d 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -221,7 +221,6 @@ visorbus_release_busdevice(struct device *xdev) { struct visor_device *dev = dev_get_drvdata(xdev); - dev_set_drvdata(xdev, NULL); kfree(dev); } @@ -701,12 +700,10 @@ DRIVER_ATTR_version(struct device_driver *xdrv, char *buf) static int register_driver_attributes(struct visor_driver *drv) { - int rc; struct driver_attribute version = __ATTR(version, S_IRUGO, DRIVER_ATTR_version, NULL); drv->version_attr = version; - rc = driver_create_file(&drv->driver, &drv->version_attr); - return rc; + return driver_create_file(&drv->driver, &drv->version_attr); } static void @@ -771,7 +768,7 @@ visordriver_probe_device(struct device *xdev) get_device(&dev->device); if (!drv->probe) { up(&dev->visordriver_callback_lock); - rc = -1; + rc = -ENODEV; goto away; } rc = drv->probe(dev); @@ -973,7 +970,7 @@ EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts); static int create_visor_device(struct visor_device *dev) { - int rc = -1; + int rc; u32 chipset_bus_no = dev->chipset_bus_no; u32 chipset_dev_no = dev->chipset_dev_no; @@ -995,6 +992,7 @@ create_visor_device(struct visor_device *dev) if (!dev->periodic_work) { POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no, DIAG_SEVERITY_ERR); + rc = -EINVAL; goto away; } @@ -1032,14 +1030,15 @@ create_visor_device(struct visor_device *dev) if (rc < 0) { POSTCODE_LINUX_3(DEVICE_REGISTER_FAILURE_PC, chipset_dev_no, DIAG_SEVERITY_ERR); - goto away_register; + goto away_unregister; } list_add_tail(&dev->list_all, &list_all_device_instances); return 0; -away_register: +away_unregister: device_unregister(&dev->device); + away: put_device(&dev->device); return rc; @@ -1058,23 +1057,21 @@ static int get_vbus_header_info(struct visorchannel *chan, struct spar_vbus_headerinfo *hdr_info) { - int rc = -1; - if (!SPAR_VBUS_CHANNEL_OK_CLIENT(visorchannel_get_header(chan))) - goto away; + return -EINVAL; + if (visorchannel_read(chan, sizeof(struct channel_header), hdr_info, sizeof(*hdr_info)) < 0) { - goto away; + return -EIO; } if (hdr_info->struct_bytes < sizeof(struct spar_vbus_headerinfo)) - goto away; + return -EINVAL; + if (hdr_info->device_info_struct_bytes < sizeof(struct ultra_vbus_deviceinfo)) { - goto away; + return -EINVAL; } - rc = 0; -away: - return rc; + return 0; } /* Write the contents of to the struct @@ -1197,17 +1194,14 @@ fix_vbus_dev_info(struct visor_device *visordev) static int create_bus_instance(struct visor_device *dev) { - int rc; int id = dev->chipset_bus_no; struct spar_vbus_headerinfo *hdr_info; POSTCODE_LINUX_2(BUS_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); hdr_info = kzalloc(sizeof(*hdr_info), GFP_KERNEL); - if (!hdr_info) { - rc = -1; - goto away; - } + if (!hdr_info) + return -ENOMEM; dev_set_name(&dev->device, "visorbus%d", id); dev->device.bus = &visorbus_type; @@ -1217,8 +1211,8 @@ create_bus_instance(struct visor_device *dev) if (device_register(&dev->device) < 0) { POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, id, POSTCODE_SEVERITY_ERR); - rc = -1; - goto away_mem; + kfree(hdr_info); + return -ENODEV; } if (get_vbus_header_info(dev->visorchannel, hdr_info) >= 0) { @@ -1234,11 +1228,6 @@ create_bus_instance(struct visor_device *dev) list_add_tail(&dev->list_all, &list_all_bus_instances); dev_set_drvdata(&dev->device, dev); return 0; - -away_mem: - kfree(hdr_info); -away: - return rc; } /** Remove a device instance for the visor bus itself. @@ -1328,7 +1317,7 @@ chipset_bus_destroy(struct visor_device *dev) static void chipset_device_create(struct visor_device *dev_info) { - int rc = -1; + int rc; u32 bus_no = dev_info->chipset_bus_no; u32 dev_no = dev_info->chipset_dev_no; @@ -1371,9 +1360,9 @@ pause_state_change_complete(struct visor_device *dev, int status) return; /* Notify the chipset driver that the pause is complete, which - * will presumably want to send some sort of response to the - * initiator. - */ + * will presumably want to send some sort of response to the + * initiator. + */ (*chipset_responders.device_pause) (dev, status); } @@ -1405,7 +1394,7 @@ resume_state_change_complete(struct visor_device *dev, int status) static void initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) { - int rc = -1, x; + int rc; struct visor_driver *drv = NULL; void (*notify_func)(struct visor_device *dev, int response) = NULL; @@ -1414,14 +1403,18 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) else notify_func = chipset_responders.device_resume; if (!notify_func) - goto away; + return; drv = to_visor_driver(dev->device.driver); - if (!drv) - goto away; + if (!drv) { + (*notify_func)(dev, -ENODEV); + return; + } - if (dev->pausing || dev->resuming) - goto away; + if (dev->pausing || dev->resuming) { + (*notify_func)(dev, -EBUSY); + return; + } /* Note that even though both drv->pause() and drv->resume * specify a callback function, it is NOT necessary for us to @@ -1431,11 +1424,13 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) * visorbus while child function drivers are still running. */ if (is_pause) { - if (!drv->pause) - goto away; + if (!drv->pause) { + (*notify_func)(dev, -EINVAL); + return; + } dev->pausing = true; - x = drv->pause(dev, pause_state_change_complete); + rc = 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 @@ -1444,24 +1439,20 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause) * would never even get here in that case. */ fix_vbus_dev_info(dev); - if (!drv->resume) - goto away; + if (!drv->resume) { + (*notify_func)(dev, -EINVAL); + return; + } dev->resuming = true; - x = drv->resume(dev, resume_state_change_complete); + rc = drv->resume(dev, resume_state_change_complete); } - if (x < 0) { + if (rc < 0) { if (is_pause) dev->pausing = false; else dev->resuming = false; - goto away; - } - rc = 0; -away: - if (rc < 0) { - if (notify_func) - (*notify_func)(dev, rc); + (*notify_func)(dev, -EINVAL); } } diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 891b8db7c..b68a904ac 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -73,7 +73,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, channel = kzalloc(sizeof(*channel), gfp); if (!channel) - goto cleanup; + return NULL; channel->needs_lock = needs_lock; spin_lock_init(&channel->insert_lock); @@ -89,14 +89,14 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, if (!channel->requested) { if (uuid_le_cmp(guid, spar_video_guid)) { /* Not the video channel we care about this */ - goto cleanup; + goto err_destroy_channel; } } channel->mapped = memremap(physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(physaddr, size); - goto cleanup; + goto err_destroy_channel; } channel->physaddr = physaddr; @@ -105,7 +105,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, err = visorchannel_read(channel, 0, &channel->chan_hdr, sizeof(struct channel_header)); if (err) - goto cleanup; + goto err_destroy_channel; /* we had better be a CLIENT of this channel */ if (channel_bytes == 0) @@ -122,7 +122,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, if (!channel->requested) { if (uuid_le_cmp(guid, spar_video_guid)) { /* Different we care about this */ - goto cleanup; + goto err_destroy_channel; } } @@ -130,7 +130,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(channel->physaddr, channel_bytes); - goto cleanup; + goto err_destroy_channel; } channel->nbytes = channel_bytes; @@ -139,7 +139,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, channel->guid = guid; return channel; -cleanup: +err_destroy_channel: visorchannel_destroy(channel); return NULL; } @@ -293,14 +293,14 @@ visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, err = visorchannel_write(channel, offset + written, buf, thisbytes); if (err) - goto cleanup; + goto out_free_page; written += thisbytes; nbytes -= thisbytes; } err = 0; -cleanup: +out_free_page: free_page((unsigned long)buf); return err; } @@ -461,7 +461,7 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) if (!sig_read_header(channel, queue, &sig_hdr)) return false; - sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); + 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, @@ -521,7 +521,7 @@ visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) tail = sig_hdr.tail; if (head < tail) head = head + sig_hdr.max_slots; - slots_used = (head - tail); + slots_used = head - tail; slots_avail = sig_hdr.max_signals - slots_used; return (int)slots_avail; } diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 07594f438..5fbda7b21 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -43,11 +43,10 @@ #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 -#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) +#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 */ @@ -62,6 +61,7 @@ static int visorchipset_major; static int visorchipset_visorbusregwait = 1; /* default is on */ static int visorchipset_holdchipsetready; static unsigned long controlvm_payload_bytes_buffered; +static u32 dump_vhba_bus; static int visorchipset_open(struct inode *inode, struct file *file) @@ -86,8 +86,8 @@ visorchipset_release(struct inode *inode, struct file *file) */ #define MIN_IDLE_SECONDS 10 static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -static unsigned long most_recent_message_jiffies; /* when we got our last - * controlvm message */ +/* when we got our last controlvm message */ +static unsigned long most_recent_message_jiffies; static int visorbusregistered; #define MAX_CHIPSET_EVENTS 2 @@ -103,7 +103,6 @@ struct parser_context { }; static struct delayed_work periodic_controlvm_work; -static struct workqueue_struct *periodic_controlvm_workqueue; static DEFINE_SEMAPHORE(notifier_lock); static struct cdev file_cdev; @@ -120,7 +119,8 @@ static struct visorchannel *controlvm_channel; struct visor_controlvm_payload_info { u8 *ptr; /* pointer to base address of payload pool */ u64 offset; /* offset from beginning of controlvm - * channel to beginning of payload * pool */ + * channel to beginning of payload * pool + */ u32 bytes; /* number of bytes in payload pool */ }; @@ -184,7 +184,8 @@ struct putfile_request { * - this list is added to when controlvm messages come in that supply * file data * - this list is removed from via the hotplug program that is actually - * consuming these buffers to write as file data */ + * consuming these buffers to write as file data + */ struct list_head input_buffer_list; spinlock_t req_list_lock; /* lock for input_buffer_list */ @@ -352,7 +353,6 @@ static void controlvm_respond_physdev_changestate( struct controlvm_message_header *msg_hdr, int response, struct spar_segment_state state); - static void parser_done(struct parser_context *ctx); static struct parser_context * @@ -377,7 +377,7 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) rc = NULL; goto cleanup; } - ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); + ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); if (!ctx) { if (retry) *retry = true; @@ -397,24 +397,16 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) rc = NULL; goto cleanup; } - p = __va((unsigned long) (addr)); + p = __va((unsigned long)(addr)); memcpy(ctx->data, p, bytes); } else { - void *mapping; - - if (!request_mem_region(addr, bytes, "visorchipset")) { - rc = NULL; - goto cleanup; - } + void *mapping = memremap(addr, bytes, MEMREMAP_WB); - mapping = memremap(addr, bytes, MEMREMAP_WB); if (!mapping) { - release_mem_region(addr, bytes); rc = NULL; goto cleanup; } memcpy(ctx->data, mapping, bytes); - release_mem_region(addr, bytes); memunmap(mapping); } @@ -437,7 +429,7 @@ parser_id_get(struct parser_context *ctx) { struct spar_controlvm_parameters_header *phdr = NULL; - if (ctx == NULL) + if (!ctx) return NULL_UUID_LE; phdr = (struct spar_controlvm_parameters_header *)(ctx->data); return phdr->id; @@ -460,8 +452,9 @@ parser_param_start(struct parser_context *ctx, { struct spar_controlvm_parameters_header *phdr = NULL; - if (ctx == NULL) - goto Away; + if (!ctx) + return; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); switch (which_string) { case PARSERSTRING_INITIATOR: @@ -483,9 +476,6 @@ parser_param_start(struct parser_context *ctx, default: break; } - -Away: - return; } static void parser_done(struct parser_context *ctx) @@ -520,16 +510,15 @@ 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); - if (value == NULL) + value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY); + if (!value) return NULL; if (value_length > 0) memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; + ((u8 *)(value))[value_length] = '\0'; return value; } - static ssize_t toolaction_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -537,8 +526,8 @@ static ssize_t toolaction_show(struct device *dev, u8 tool_action; visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); } @@ -706,6 +695,7 @@ static int match_visorbus_dev_by_id(struct device *dev, void *data) return 0; } + struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, struct visor_device *from) { @@ -788,13 +778,15 @@ chipset_init(struct controlvm_message *inmsg) POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); /* Set features to indicate we support parahotplug (if Command - * also supports it). */ + * also supports it). + */ features = inmsg->cmd.init_chipset. features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; /* Set the "reply" bit so Command knows this is a - * features-aware driver. */ + * features-aware driver. + */ features |= ULTRA_CHIPSET_FEATURE_REPLY; cleanup: @@ -813,7 +805,7 @@ controlvm_init_response(struct controlvm_message *msg, msg->hdr.payload_max_bytes = 0; if (response < 0) { msg->hdr.flags.failed = 1; - msg->hdr.completion_status = (u32) (-response); + msg->hdr.completion_status = (u32)(-response); } } @@ -867,12 +859,65 @@ enum crash_obj_type { CRASH_BUS, }; +static void +save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ) +{ + u32 local_crash_msg_offset; + u16 local_crash_msg_count; + + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_count), + &local_crash_msg_count, sizeof(u16)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) { + POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC, + local_crash_msg_count, + POSTCODE_SEVERITY_ERR); + return; + } + + if (visorchannel_read(controlvm_channel, + offsetof(struct spar_controlvm_channel_protocol, + saved_crash_message_offset), + &local_crash_msg_offset, sizeof(u32)) < 0) { + POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + + if (typ == CRASH_BUS) { + if (visorchannel_write(controlvm_channel, + local_crash_msg_offset, + msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } else { + local_crash_msg_offset += sizeof(struct controlvm_message); + if (visorchannel_write(controlvm_channel, + local_crash_msg_offset, + msg, + sizeof(struct controlvm_message)) < 0) { + POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC, + POSTCODE_SEVERITY_ERR); + return; + } + } +} + static void bus_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) { - if (pending_msg_hdr == NULL) + if (!pending_msg_hdr) return; /* no controlvm response needed */ if (pending_msg_hdr->id != (u32)cmd_id) @@ -890,7 +935,7 @@ device_changestate_responder(enum controlvm_id cmd_id, u32 bus_no = p->chipset_bus_no; u32 dev_no = p->chipset_dev_no; - if (p->pending_msg_hdr == NULL) + if (!p->pending_msg_hdr) return; /* no controlvm response needed */ if (p->pending_msg_hdr->id != cmd_id) return; @@ -911,7 +956,7 @@ device_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) { - if (pending_msg_hdr == NULL) + if (!pending_msg_hdr) return; /* no controlvm response needed */ if (pending_msg_hdr->id != (u32)cmd_id) @@ -1127,6 +1172,10 @@ bus_create(struct controlvm_message *inmsg) goto cleanup; } bus_info->visorchannel = visorchannel; + if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) { + dump_vhba_bus = bus_no; + save_crash_message(inmsg, CRASH_BUS); + } POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO); @@ -1177,7 +1226,7 @@ bus_configure(struct controlvm_message *inmsg, POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - } else if (bus_info->pending_msg_hdr != NULL) { + } else if (bus_info->pending_msg_hdr) { POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; @@ -1263,6 +1312,10 @@ my_device_create(struct controlvm_message *inmsg) } dev_info->visorchannel = visorchannel; dev_info->channel_type_guid = cmd->create_device.data_type_uuid; + if (uuid_le_cmp(cmd->create_device.data_type_uuid, + spar_vhba_channel_protocol_uuid) == 0) + save_crash_message(inmsg, CRASH_DEV); + POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); cleanup: @@ -1913,8 +1966,7 @@ cleanup: poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; } - queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); } static void @@ -2011,8 +2063,7 @@ cleanup: poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW; - queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); + schedule_delayed_work(&periodic_controlvm_work, poll_jiffies); } static void @@ -2197,7 +2248,7 @@ static inline int issue_vmcall_update_physical_time(u64 adjustment) static long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - s64 adjustment; + u64 adjustment; s64 vrtc_offset; switch (cmd) { @@ -2262,7 +2313,6 @@ visorchipset_init(struct acpi_device *acpi_device) { int rc = 0; u64 addr; - int tmp_sz = sizeof(struct spar_controlvm_channel_protocol); uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID; addr = controlvm_get_channel_address(); @@ -2272,8 +2322,10 @@ visorchipset_init(struct acpi_device *acpi_device) memset(&busdev_notifiers, 0, sizeof(busdev_notifiers)); memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info)); - controlvm_channel = visorchannel_create_with_lock(addr, tmp_sz, + controlvm_channel = visorchannel_create_with_lock(addr, 0, GFP_KERNEL, uuid); + if (!controlvm_channel) + return -ENODEV; if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT( visorchannel_get_header(controlvm_channel))) { initialize_controlvm_payload(); @@ -2299,29 +2351,15 @@ visorchipset_init(struct acpi_device *acpi_device) else INIT_DELAYED_WORK(&periodic_controlvm_work, controlvm_periodic_work); - periodic_controlvm_workqueue = - create_singlethread_workqueue("visorchipset_controlvm"); - if (!periodic_controlvm_workqueue) { - POSTCODE_LINUX_2(CREATE_WORKQUEUE_FAILED_PC, - DIAG_SEVERITY_ERR); - rc = -ENOMEM; - goto cleanup; - } most_recent_message_jiffies = jiffies; poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - rc = queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); - if (rc < 0) { - POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, - DIAG_SEVERITY_ERR); - goto cleanup; - } + 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_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR); - rc = -1; + rc = -ENODEV; goto cleanup; } POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO); @@ -2351,10 +2389,7 @@ visorchipset_exit(struct acpi_device *acpi_device) visorbus_exit(); - cancel_delayed_work(&periodic_controlvm_work); - flush_workqueue(periodic_controlvm_workqueue); - destroy_workqueue(periodic_controlvm_workqueue); - periodic_controlvm_workqueue = NULL; + cancel_delayed_work_sync(&periodic_controlvm_work); destroy_controlvm_payload_info(&controlvm_payload_info); memset(&g_chipset_msg_hdr, 0, sizeof(struct controlvm_message_header)); -- cgit v1.2.3-54-g00ecf