aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/unisys/visorbus/visorchipset.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/unisys/visorbus/visorchipset.c')
-rw-r--r--drivers/staging/unisys/visorbus/visorchipset.c607
1 files changed, 250 insertions, 357 deletions
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index 22150564b4fb..74cce4f1a7bd 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -1,5 +1,4 @@
-/* visorchipset_main.c
- *
+/*
* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
@@ -15,19 +14,18 @@
*/
#include <linux/acpi.h>
-#include <linux/ctype.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/nls.h>
-#include <linux/netdevice.h>
-#include <linux/uuid.h>
#include <linux/crash_dump.h>
#include "visorbus.h"
#include "visorbus_private.h"
-#include "vmcallinterface.h"
-#define CURRENT_FILE_PC VISOR_BUS_PC_visorchipset_c
+/* {72120008-4AAB-11DC-8530-444553544200} */
+#define VISOR_SIOVM_GUID GUID_INIT(0x72120008, 0x4AAB, 0x11DC, 0x85, 0x30, \
+ 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
+
+static const guid_t visor_vhba_channel_guid = VISOR_VHBA_CHANNEL_GUID;
+static const guid_t visor_siovm_guid = VISOR_SIOVM_GUID;
+static const guid_t visor_controlvm_channel_guid = VISOR_CONTROLVM_CHANNEL_GUID;
#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
@@ -42,9 +40,9 @@
#define UNISYS_VISOR_ID_EDX 0x34367261
/*
- * 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.
+ * 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
@@ -54,15 +52,39 @@ struct parser_context {
u8 *curr;
unsigned long bytes_remaining;
bool byte_stream;
- char data[0];
+ struct visor_controlvm_parameters_header data;
};
-struct vmcall_controlvm_addr {
- struct vmcall_io_controlvm_addr_params params;
- int err;
- u64 physaddr;
+/* VMCALL_CONTROLVM_ADDR: Used by all guests, not just IO. */
+#define VMCALL_CONTROLVM_ADDR 0x0501
+
+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
};
+/*
+ * struct vmcall_io_controlvm_addr_params - Structure for IO VMCALLS. Has
+ * parameters to VMCALL_CONTROLVM_ADDR
+ * interface.
+ * @address: The Guest-relative physical address of the ControlVm channel.
+ * This VMCall fills this in with the appropriate address.
+ * Contents provided by this VMCALL (OUT).
+ * @channel_bytes: The size of the ControlVm channel in bytes This VMCall fills
+ * this in with the appropriate address. Contents provided by
+ * this VMCALL (OUT).
+ * @unused: Unused Bytes in the 64-Bit Aligned Struct.
+ */
+struct vmcall_io_controlvm_addr_params {
+ u64 address;
+ u32 channel_bytes;
+ u8 unused[4];
+} __packed;
+
struct visorchipset_device {
struct acpi_device *acpi_device;
unsigned long poll_jiffies;
@@ -80,7 +102,7 @@ struct visorchipset_device {
*/
struct controlvm_message controlvm_pending_msg;
bool controlvm_pending_msg_valid;
- struct vmcall_controlvm_addr controlvm_addr;
+ struct vmcall_io_controlvm_addr_params controlvm_params;
};
static struct visorchipset_device *chipset_dev;
@@ -124,7 +146,6 @@ static ssize_t toolaction_store(struct device *dev,
offsetof(struct visor_controlvm_channel,
tool_action),
&tool_action, sizeof(u8));
-
if (err)
return err;
return count;
@@ -143,7 +164,6 @@ static ssize_t boottotool_show(struct device *dev,
efi_visor_ind),
&efi_visor_indication,
sizeof(struct efi_visor_indication));
-
if (err)
return err;
return sprintf(buf, "%u\n", efi_visor_indication.boot_to_tool);
@@ -165,7 +185,6 @@ static ssize_t boottotool_store(struct device *dev,
efi_visor_ind),
&(efi_visor_indication),
sizeof(struct efi_visor_indication));
-
if (err)
return err;
return count;
@@ -184,7 +203,7 @@ static ssize_t error_show(struct device *dev, struct device_attribute *attr,
&error, sizeof(u32));
if (err)
return err;
- return sprintf(buf, "%i\n", error);
+ return sprintf(buf, "%u\n", error);
}
static ssize_t error_store(struct device *dev, struct device_attribute *attr,
@@ -219,7 +238,7 @@ static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
if (err)
return err;
- return sprintf(buf, "%i\n", text_id);
+ return sprintf(buf, "%u\n", text_id);
}
static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
@@ -277,67 +296,6 @@ static ssize_t remaining_steps_store(struct device *dev,
}
static DEVICE_ATTR_RW(remaining_steps);
-static uuid_le
-parser_id_get(struct parser_context *ctx)
-{
- struct visor_controlvm_parameters_header *phdr = NULL;
-
- phdr = (struct visor_controlvm_parameters_header *)(ctx->data);
- return phdr->id;
-}
-
-static void parser_done(struct parser_context *ctx)
-{
- chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes;
- kfree(ctx);
-}
-
-static void *
-parser_string_get(struct parser_context *ctx)
-{
- u8 *pscan;
- unsigned long nscan;
- int value_length = -1;
- void *value = NULL;
- int i;
-
- pscan = ctx->curr;
- nscan = ctx->bytes_remaining;
- if (nscan == 0)
- return NULL;
- if (!pscan)
- return NULL;
- for (i = 0, value_length = -1; i < nscan; i++)
- if (pscan[i] == '\0') {
- value_length = i;
- break;
- }
- if (value_length < 0) /* '\0' was not included in the length */
- value_length = nscan;
- value = kmalloc(value_length + 1, GFP_KERNEL);
- if (!value)
- return NULL;
- if (value_length > 0)
- memcpy(value, pscan, value_length);
- ((u8 *)(value))[value_length] = '\0';
- return value;
-}
-
-static void *
-parser_name_get(struct parser_context *ctx)
-{
- struct visor_controlvm_parameters_header *phdr = NULL;
-
- phdr = (struct visor_controlvm_parameters_header *)(ctx->data);
-
- if (phdr->name_offset + phdr->name_length > ctx->param_bytes)
- return NULL;
-
- ctx->curr = ctx->data + phdr->name_offset;
- ctx->bytes_remaining = phdr->name_length;
- return parser_string_get(ctx);
-}
-
struct visor_busdev {
u32 bus_no;
u32 dev_no;
@@ -347,11 +305,9 @@ static int match_visorbus_dev_by_id(struct device *dev, void *data)
{
struct visor_device *vdev = to_visor_device(dev);
struct visor_busdev *id = data;
- u32 bus_no = id->bus_no;
- u32 dev_no = id->dev_no;
- if ((vdev->chipset_bus_no == bus_no) &&
- (vdev->chipset_dev_no == dev_no))
+ if ((vdev->chipset_bus_no == id->bus_no) &&
+ (vdev->chipset_dev_no == id->dev_no))
return 1;
return 0;
@@ -364,9 +320,9 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
struct device *dev_start = NULL;
struct visor_device *vdev = NULL;
struct visor_busdev id = {
- .bus_no = bus_no,
- .dev_no = dev_no
- };
+ .bus_no = bus_no,
+ .dev_no = dev_no
+ };
if (from)
dev_start = &from->device;
@@ -377,9 +333,9 @@ struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
return vdev;
}
-static void
-controlvm_init_response(struct controlvm_message *msg,
- struct controlvm_message_header *msg_hdr, int response)
+static void controlvm_init_response(struct controlvm_message *msg,
+ struct controlvm_message_header *msg_hdr,
+ int response)
{
memset(msg, 0, sizeof(struct controlvm_message));
memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
@@ -392,10 +348,10 @@ controlvm_init_response(struct controlvm_message *msg,
}
}
-static int
-controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
- int response,
- enum visor_chipset_feature features)
+static int controlvm_respond_chipset_init(
+ struct controlvm_message_header *msg_hdr,
+ int response,
+ enum visor_chipset_feature features)
{
struct controlvm_message outmsg;
@@ -405,8 +361,7 @@ controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
CONTROLVM_QUEUE_REQUEST, &outmsg);
}
-static int
-chipset_init(struct controlvm_message *inmsg)
+static int chipset_init(struct controlvm_message *inmsg)
{
static int chipset_inited;
enum visor_chipset_feature features = 0;
@@ -421,15 +376,15 @@ chipset_init(struct controlvm_message *inmsg)
chipset_inited = 1;
/*
- * Set features to indicate we support parahotplug (if Command
- * also supports it).
+ * Set features to indicate we support parahotplug (if Command also
+ * supports it).
*/
features = inmsg->cmd.init_chipset.features &
VISOR_CHIPSET_FEATURE_PARA_HOTPLUG;
/*
- * Set the "reply" bit so Command knows this is a
- * features-aware driver.
+ * Set the "reply" bit so Command knows this is a features-aware
+ * driver.
*/
features |= VISOR_CHIPSET_FEATURE_REPLY;
@@ -440,9 +395,9 @@ out_respond:
return res;
}
-static int
-controlvm_respond(struct controlvm_message_header *msg_hdr, int response,
- struct visor_segment_state *state)
+static int controlvm_respond(struct controlvm_message_header *msg_hdr,
+ int response,
+ struct visor_segment_state *state)
{
struct controlvm_message outmsg;
@@ -464,8 +419,8 @@ enum crash_obj_type {
CRASH_BUS,
};
-static int
-save_crash_message(struct controlvm_message *msg, enum crash_obj_type cr_type)
+static int save_crash_message(struct controlvm_message *msg,
+ enum crash_obj_type cr_type)
{
u32 local_crash_msg_offset;
u16 local_crash_msg_count;
@@ -529,10 +484,9 @@ save_crash_message(struct controlvm_message *msg, enum crash_obj_type cr_type)
return 0;
}
-static int
-controlvm_responder(enum controlvm_id cmd_id,
- struct controlvm_message_header *pending_msg_hdr,
- int response)
+static int controlvm_responder(enum controlvm_id cmd_id,
+ struct controlvm_message_header *pending_msg_hdr,
+ int response)
{
if (!pending_msg_hdr)
return -EIO;
@@ -543,14 +497,12 @@ controlvm_responder(enum controlvm_id cmd_id,
return controlvm_respond(pending_msg_hdr, response, NULL);
}
-static int
-device_changestate_responder(enum controlvm_id cmd_id,
- struct visor_device *p, int response,
- struct visor_segment_state response_state)
+static int device_changestate_responder(
+ enum controlvm_id cmd_id,
+ struct visor_device *p, int response,
+ struct visor_segment_state response_state)
{
struct controlvm_message outmsg;
- u32 bus_no = p->chipset_bus_no;
- u32 dev_no = p->chipset_dev_no;
if (!p->pending_msg_hdr)
return -EIO;
@@ -559,16 +511,15 @@ device_changestate_responder(enum controlvm_id cmd_id,
controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
- outmsg.cmd.device_change_state.bus_no = bus_no;
- outmsg.cmd.device_change_state.dev_no = dev_no;
+ outmsg.cmd.device_change_state.bus_no = p->chipset_bus_no;
+ outmsg.cmd.device_change_state.dev_no = p->chipset_dev_no;
outmsg.cmd.device_change_state.state = response_state;
return visorchannel_signalinsert(chipset_dev->controlvm_channel,
CONTROLVM_QUEUE_REQUEST, &outmsg);
}
-static int
-visorbus_create(struct controlvm_message *inmsg)
+static int visorbus_create(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -580,7 +531,7 @@ visorbus_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)) {
dev_err(&chipset_dev->acpi_device->dev,
- "failed visorbus_create: already exists\n");
+ "failed %s: already exists\n", __func__);
err = -EEXIST;
goto err_respond;
}
@@ -595,7 +546,7 @@ visorbus_create(struct controlvm_message *inmsg)
bus_info->chipset_bus_no = bus_no;
bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
- if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, visor_siovm_uuid) == 0) {
+ if (guid_equal(&cmd->create_bus.bus_inst_guid, &visor_siovm_guid)) {
err = save_crash_message(inmsg, CRASH_BUS);
if (err)
goto err_free_bus_info;
@@ -615,19 +566,17 @@ visorbus_create(struct controlvm_message *inmsg)
}
visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
- cmd->create_bus.channel_bytes,
GFP_KERNEL,
- cmd->create_bus.bus_data_type_uuid);
-
+ &cmd->create_bus.bus_data_type_guid);
if (!visorchannel) {
err = -ENOMEM;
goto err_free_pending_msg;
}
+
bus_info->visorchannel = visorchannel;
- /* Response will be handled by visorchipset_bus_create */
- err = visorchipset_bus_create(bus_info);
- /* If visorchipset_bus_create didn't respond, need to respond here */
+ /* Response will be handled by visorbus_create_instance on success */
+ err = visorbus_create_instance(bus_info);
if (err)
goto err_destroy_channel;
@@ -648,8 +597,7 @@ err_respond:
return err;
}
-static int
-visorbus_destroy(struct controlvm_message *inmsg)
+static int visorbus_destroy(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -683,8 +631,8 @@ visorbus_destroy(struct controlvm_message *inmsg)
bus_info->pending_msg_hdr = pmsg_hdr;
}
- /* Response will be handled by visorchipset_bus_destroy */
- visorchipset_bus_destroy(bus_info);
+ /* Response will be handled by visorbus_remove_instance */
+ visorbus_remove_instance(bus_info);
return 0;
err_respond:
@@ -693,9 +641,60 @@ err_respond:
return err;
}
-static int
-visorbus_configure(struct controlvm_message *inmsg,
- struct parser_context *parser_ctx)
+static const guid_t *parser_id_get(struct parser_context *ctx)
+{
+ return &ctx->data.id;
+}
+
+static void *parser_string_get(struct parser_context *ctx)
+{
+ u8 *pscan;
+ unsigned long nscan;
+ int value_length;
+ void *value;
+ int i;
+
+ pscan = ctx->curr;
+ if (!pscan)
+ return NULL;
+ nscan = ctx->bytes_remaining;
+ if (nscan == 0)
+ return NULL;
+
+ for (i = 0, value_length = -1; i < nscan; i++)
+ if (pscan[i] == '\0') {
+ value_length = i;
+ break;
+ }
+ /* '\0' was not included in the length */
+ if (value_length < 0)
+ value_length = nscan;
+
+ value = kmalloc(value_length + 1, GFP_KERNEL);
+ if (!value)
+ return NULL;
+ if (value_length > 0)
+ memcpy(value, pscan, value_length);
+ ((u8 *)(value))[value_length] = '\0';
+ return value;
+}
+
+static void *parser_name_get(struct parser_context *ctx)
+{
+ struct visor_controlvm_parameters_header *phdr = NULL;
+
+ phdr = &ctx->data;
+
+ if (phdr->name_offset + phdr->name_length > ctx->param_bytes)
+ return NULL;
+
+ ctx->curr = (char *)&phdr + phdr->name_offset;
+ ctx->bytes_remaining = phdr->name_length;
+ return parser_string_get(ctx);
+}
+
+static int visorbus_configure(struct controlvm_message *inmsg,
+ struct parser_context *parser_ctx)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
u32 bus_no;
@@ -707,10 +706,12 @@ visorbus_configure(struct controlvm_message *inmsg,
if (!bus_info) {
err = -EINVAL;
goto err_respond;
- } else if (bus_info->state.created == 0) {
+ }
+ if (bus_info->state.created == 0) {
err = -EINVAL;
goto err_respond;
- } else if (bus_info->pending_msg_hdr) {
+ }
+ if (bus_info->pending_msg_hdr) {
err = -EIO;
goto err_respond;
}
@@ -722,7 +723,9 @@ visorbus_configure(struct controlvm_message *inmsg,
goto err_respond;
if (parser_ctx) {
- bus_info->partition_uuid = parser_id_get(parser_ctx);
+ const guid_t *partition_guid = parser_id_get(parser_ctx);
+
+ guid_copy(&bus_info->partition_guid, partition_guid);
bus_info->name = parser_name_get(parser_ctx);
}
@@ -732,14 +735,13 @@ visorbus_configure(struct controlvm_message *inmsg,
err_respond:
dev_err(&chipset_dev->acpi_device->dev,
- "visorbus_configure exited with err: %d\n", err);
+ "%s exited with err: %d\n", __func__, err);
if (inmsg->hdr.flags.response_expected == 1)
controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
return err;
}
-static int
-visorbus_device_create(struct controlvm_message *inmsg)
+static int visorbus_device_create(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -757,7 +759,6 @@ visorbus_device_create(struct controlvm_message *inmsg)
err = -ENODEV;
goto err_respond;
}
-
if (bus_info->state.created == 0) {
dev_err(&chipset_dev->acpi_device->dev,
"bus not created, id: %d\n", bus_no);
@@ -781,17 +782,13 @@ visorbus_device_create(struct controlvm_message *inmsg)
dev_info->chipset_bus_no = bus_no;
dev_info->chipset_dev_no = dev_no;
- dev_info->inst = cmd->create_device.dev_inst_uuid;
-
- /* not sure where the best place to set the 'parent' */
+ guid_copy(&dev_info->inst, &cmd->create_device.dev_inst_guid);
dev_info->device.parent = &bus_info->device;
visorchannel =
visorchannel_create_with_lock(cmd->create_device.channel_addr,
- cmd->create_device.channel_bytes,
GFP_KERNEL,
- cmd->create_device.data_type_uuid);
-
+ &cmd->create_device.data_type_guid);
if (!visorchannel) {
dev_err(&chipset_dev->acpi_device->dev,
"failed to create visorchannel: %d/%d\n",
@@ -800,9 +797,8 @@ visorbus_device_create(struct controlvm_message *inmsg)
goto err_free_dev_info;
}
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,
- visor_vhba_channel_uuid) == 0) {
+ guid_copy(&dev_info->channel_type_guid, &cmd->create_device.data_type_guid);
+ if (guid_equal(&cmd->create_device.data_type_guid, &visor_vhba_channel_guid)) {
err = save_crash_message(inmsg, CRASH_DEV);
if (err)
goto err_destroy_visorchannel;
@@ -819,8 +815,8 @@ visorbus_device_create(struct controlvm_message *inmsg)
sizeof(struct controlvm_message_header));
dev_info->pending_msg_hdr = pmsg_hdr;
}
- /* visorchipset_device_create will send response */
- err = visorchipset_device_create(dev_info);
+ /* create_visor_device will send response */
+ err = create_visor_device(dev_info);
if (err)
goto err_destroy_visorchannel;
@@ -838,8 +834,7 @@ err_respond:
return err;
}
-static int
-visorbus_device_changestate(struct controlvm_message *inmsg)
+static int visorbus_device_changestate(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -899,8 +894,7 @@ err_respond:
return err;
}
-static int
-visorbus_device_destroy(struct controlvm_message *inmsg)
+static int visorbus_device_destroy(struct controlvm_message *inmsg)
{
struct controlvm_message_packet *cmd = &inmsg->cmd;
struct controlvm_message_header *pmsg_hdr = NULL;
@@ -918,7 +912,6 @@ visorbus_device_destroy(struct controlvm_message *inmsg)
err = -EINVAL;
goto err_respond;
}
-
if (dev_info->pending_msg_hdr) {
/* only non-NULL if dev is still waiting on a response */
err = -EIO;
@@ -936,7 +929,8 @@ visorbus_device_destroy(struct controlvm_message *inmsg)
dev_info->pending_msg_hdr = pmsg_hdr;
}
- visorchipset_device_destroy(dev_info);
+ kfree(dev_info->name);
+ remove_visor_device(dev_info);
return 0;
err_respond:
@@ -954,8 +948,7 @@ err_respond:
* disable the specified device. The udev script then writes to
* /sys/devices/platform/visorchipset/parahotplug, which causes the
* parahotplug store functions to get called, at which point the
- * appropriate CONTROLVM message is retrieved from the list and responded
- * to.
+ * appropriate CONTROLVM message is retrieved from the list and responded to.
*/
#define PARAHOTPLUG_TIMEOUT_MS 2000
@@ -967,8 +960,7 @@ err_respond:
*
* Return: a unique integer value
*/
-static int
-parahotplug_next_id(void)
+static int parahotplug_next_id(void)
{
static atomic_t id = ATOMIC_INIT(0);
@@ -982,8 +974,7 @@ parahotplug_next_id(void)
*
* Return: expected expiration time (in jiffies)
*/
-static unsigned long
-parahotplug_next_expiration(void)
+static unsigned long parahotplug_next_expiration(void)
{
return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
}
@@ -996,8 +987,8 @@ parahotplug_next_expiration(void)
*
* Return: the request containing the provided message
*/
-static struct parahotplug_request *
-parahotplug_request_create(struct controlvm_message *msg)
+static struct parahotplug_request *parahotplug_request_create(
+ struct controlvm_message *msg)
{
struct parahotplug_request *req;
@@ -1016,14 +1007,14 @@ parahotplug_request_create(struct controlvm_message *msg)
* parahotplug_request_destroy() - free a parahotplug_request
* @req: the request to deallocate
*/
-static void
-parahotplug_request_destroy(struct parahotplug_request *req)
+static void parahotplug_request_destroy(struct parahotplug_request *req)
{
kfree(req);
}
static LIST_HEAD(parahotplug_request_list);
-static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
+/* lock for above */
+static DEFINE_SPINLOCK(parahotplug_request_list_lock);
/*
* parahotplug_request_complete() - mark request as complete
@@ -1036,8 +1027,7 @@ static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
*
* Return: 0 on success or -EINVAL on failure
*/
-static int
-parahotplug_request_complete(int id, u16 active)
+static int parahotplug_request_complete(int id, u16 active)
{
struct list_head *pos;
struct list_head *tmp;
@@ -1146,7 +1136,7 @@ static struct attribute *visorchipset_parahotplug_attrs[] = {
NULL
};
-static struct attribute_group visorchipset_parahotplug_group = {
+static const struct attribute_group visorchipset_parahotplug_group = {
.name = "parahotplug",
.attrs = visorchipset_parahotplug_attrs
};
@@ -1164,8 +1154,7 @@ static const struct attribute_group *visorchipset_dev_groups[] = {
* Cause uevent to run the user level script to do the disable/enable specified
* in the parahotplug_request.
*/
-static int
-parahotplug_request_kickoff(struct parahotplug_request *req)
+static int parahotplug_request_kickoff(struct parahotplug_request *req)
{
struct controlvm_message_packet *cmd = &req->msg.cmd;
char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
@@ -1194,14 +1183,12 @@ parahotplug_request_kickoff(struct parahotplug_request *req)
* off a udev script
* @inmsg: the message indicating whether to enable or disable
*/
-static int
-parahotplug_process_message(struct controlvm_message *inmsg)
+static int parahotplug_process_message(struct controlvm_message *inmsg)
{
struct parahotplug_request *req;
int err;
req = parahotplug_request_create(inmsg);
-
if (!req)
return -ENOMEM;
@@ -1220,10 +1207,9 @@ parahotplug_process_message(struct controlvm_message *inmsg)
}
/*
- * 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.
+ * 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(&parahotplug_request_list_lock);
list_add_tail(&req->list, &parahotplug_request_list);
@@ -1247,8 +1233,7 @@ err_respond:
*
* Return: 0 on success, negative on failure
*/
-static int
-chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
+static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
{
int res;
@@ -1268,8 +1253,7 @@ chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
*
* Return: 0 on success, negative on failure
*/
-static int
-chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
+static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
{
char env_selftest[20];
char *envp[] = { env_selftest, NULL };
@@ -1292,13 +1276,11 @@ chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
*
* Return: 0 on success, negative on failure
*/
-static int
-chipset_notready_uevent(struct controlvm_message_header *msg_hdr)
+static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr)
{
- int res;
-
- res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj,
+ int res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj,
KOBJ_OFFLINE);
+
if (msg_hdr->flags.response_expected)
controlvm_respond(msg_hdr, res, NULL);
@@ -1321,13 +1303,12 @@ static int unisys_vmcall(unsigned long tuple, unsigned long param)
__asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
"a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
-
if (result)
goto error;
return 0;
-
-error: /* Need to convert from VMCALL error codes to Linux */
+/* Need to convert from VMCALL error codes to Linux */
+error:
switch (result) {
case VMCALL_RESULT_INVALID_PARAM:
return -EINVAL;
@@ -1337,35 +1318,27 @@ error: /* Need to convert from VMCALL error codes to Linux */
return -EFAULT;
}
}
-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)
+static int controlvm_channel_create(struct visorchipset_device *dev)
{
- u64 addr = 0;
- u32 size = 0;
-
- if (issue_vmcall_io_controlvm_addr(&addr, &size))
- return 0;
+ struct visorchannel *chan;
+ u64 addr;
+ int err;
- return addr;
+ err = unisys_vmcall(VMCALL_CONTROLVM_ADDR,
+ virt_to_phys(&dev->controlvm_params));
+ if (err)
+ return err;
+ addr = dev->controlvm_params.address;
+ chan = visorchannel_create_with_lock(addr, GFP_KERNEL,
+ &visor_controlvm_channel_guid);
+ if (!chan)
+ return -ENOMEM;
+ dev->controlvm_channel = chan;
+ return 0;
}
-static void
-setup_crash_devices_work_queue(struct work_struct *work)
+static void setup_crash_devices_work_queue(struct work_struct *work)
{
struct controlvm_message local_crash_bus_msg;
struct controlvm_message local_crash_dev_msg;
@@ -1444,87 +1417,44 @@ setup_crash_devices_work_queue(struct work_struct *work)
visorbus_device_create(&local_crash_dev_msg);
}
-void
-visorbus_create_response(struct visor_device *bus_info, int response)
+void visorbus_response(struct visor_device *bus_info, int response,
+ int controlvm_id)
{
- if (response >= 0)
- bus_info->state.created = 1;
-
- controlvm_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
- response);
+ controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response);
kfree(bus_info->pending_msg_hdr);
bus_info->pending_msg_hdr = NULL;
}
-void
-visorbus_destroy_response(struct visor_device *bus_info, int response)
-{
- controlvm_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
- response);
-
- kfree(bus_info->pending_msg_hdr);
- bus_info->pending_msg_hdr = NULL;
-}
-
-void
-visorbus_device_create_response(struct visor_device *dev_info, int response)
-{
- if (response >= 0)
- dev_info->state.created = 1;
-
- controlvm_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
- response);
-
- kfree(dev_info->pending_msg_hdr);
- dev_info->pending_msg_hdr = NULL;
-}
-
-void
-visorbus_device_destroy_response(struct visor_device *dev_info, int response)
-{
- controlvm_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
- response);
-
- kfree(dev_info->pending_msg_hdr);
- dev_info->pending_msg_hdr = NULL;
-}
-
-void
-visorbus_device_pause_response(struct visor_device *dev_info, int response)
+void visorbus_device_changestate_response(struct visor_device *dev_info,
+ int response,
+ struct visor_segment_state state)
{
device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
- dev_info, response,
- segment_state_standby);
+ dev_info, response, state);
kfree(dev_info->pending_msg_hdr);
dev_info->pending_msg_hdr = NULL;
}
-void
-visorbus_device_resume_response(struct visor_device *dev_info, int response)
+static void parser_done(struct parser_context *ctx)
{
- device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
- dev_info, response,
- segment_state_running);
-
- kfree(dev_info->pending_msg_hdr);
- dev_info->pending_msg_hdr = NULL;
+ chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes;
+ kfree(ctx);
}
-static struct parser_context *
-parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
+static struct parser_context *parser_init_stream(u64 addr, u32 bytes,
+ bool *retry)
{
- int allocbytes = sizeof(struct parser_context) + bytes;
+ int allocbytes;
struct parser_context *ctx;
+ void *mapping;
*retry = false;
- /*
- * alloc an 0 extra byte to ensure payload is
- * '\0'-terminated
- */
- allocbytes++;
+ /* alloc an extra byte to ensure payload is \0 terminated */
+ allocbytes = bytes + 1 + (sizeof(struct parser_context) -
+ sizeof(struct visor_controlvm_parameters_header));
if ((chipset_dev->controlvm_payload_bytes_buffered + bytes)
> MAX_CONTROLVM_PAYLOAD_BYTES) {
*retry = true;
@@ -1538,32 +1468,18 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
ctx->allocbytes = allocbytes;
ctx->param_bytes = bytes;
- ctx->curr = NULL;
- ctx->bytes_remaining = 0;
- ctx->byte_stream = false;
- if (local) {
- void *p;
-
- if (addr > virt_to_phys(high_memory - 1))
- goto err_finish_ctx;
- p = __va((unsigned long)(addr));
- memcpy(ctx->data, p, bytes);
- } else {
- void *mapping = memremap(addr, bytes, MEMREMAP_WB);
-
- if (!mapping)
- goto err_finish_ctx;
- memcpy(ctx->data, mapping, bytes);
- memunmap(mapping);
- }
-
+ mapping = memremap(addr, bytes, MEMREMAP_WB);
+ if (!mapping)
+ goto err_finish_ctx;
+ memcpy(&ctx->data, mapping, bytes);
+ memunmap(mapping);
ctx->byte_stream = true;
chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes;
return ctx;
err_finish_ctx:
- parser_done(ctx);
+ kfree(ctx);
return NULL;
}
@@ -1580,19 +1496,16 @@ err_finish_ctx:
* which to copy out controlvm payload data.
* < 0 - error: ControlVM message was processed but an error occurred.
*/
-static int
-handle_command(struct controlvm_message inmsg, u64 channel_addr)
+static int handle_command(struct controlvm_message inmsg, u64 channel_addr)
{
struct controlvm_message_packet *cmd = &inmsg.cmd;
u64 parm_addr;
u32 parm_bytes;
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);
parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
parm_bytes = inmsg.hdr.payload_bytes;
@@ -1601,25 +1514,19 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
* within our OS-controlled memory. We need to know that, because it
* makes a difference in how we compute the virtual address.
*/
- if (parm_addr && parm_bytes) {
+ if (parm_bytes) {
bool retry = false;
- parser_ctx =
- parser_init_byte_stream(parm_addr, parm_bytes,
- local_addr, &retry);
+ parser_ctx = parser_init_stream(parm_addr, parm_bytes, &retry);
if (!parser_ctx && retry)
return -EAGAIN;
}
+ controlvm_init_response(&ackmsg, &inmsg.hdr, CONTROLVM_RESP_SUCCESS);
+ err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
+ CONTROLVM_QUEUE_ACK, &ackmsg);
+ if (err)
+ return err;
- if (!local_addr) {
- controlvm_init_response(&ackmsg, &inmsg.hdr,
- CONTROLVM_RESP_SUCCESS);
- err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
- CONTROLVM_QUEUE_ACK,
- &ackmsg);
- if (err)
- return err;
- }
switch (inmsg.hdr.id) {
case CONTROLVM_CHIPSET_INIT:
err = chipset_init(&inmsg);
@@ -1641,8 +1548,8 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
err = parahotplug_process_message(&inmsg);
} else {
/*
- * save the hdr and cmd structures for later use
- * when sending back the response to Command
+ * save the hdr and cmd structures for later use when
+ * sending back the response to Command
*/
err = visorbus_device_changestate(&inmsg);
break;
@@ -1689,12 +1596,9 @@ handle_command(struct controlvm_message inmsg, u64 channel_addr)
*
* Return: 0 if valid message was retrieved or -error
*/
-static int
-read_controlvm_event(struct controlvm_message *msg)
+static int read_controlvm_event(struct controlvm_message *msg)
{
- int err;
-
- err = visorchannel_signalremove(chipset_dev->controlvm_channel,
+ int err = visorchannel_signalremove(chipset_dev->controlvm_channel,
CONTROLVM_QUEUE_EVENT, msg);
if (err)
return err;
@@ -1710,8 +1614,7 @@ read_controlvm_event(struct controlvm_message *msg)
* parahotplug_process_list() - remove any request from the list that's been on
* there too long and respond with an error
*/
-static void
-parahotplug_process_list(void)
+static void parahotplug_process_list(void)
{
struct list_head *pos;
struct list_head *tmp;
@@ -1737,8 +1640,7 @@ parahotplug_process_list(void)
spin_unlock(&parahotplug_request_list_lock);
}
-static void
-controlvm_periodic_work(struct work_struct *work)
+static void controlvm_periodic_work(struct work_struct *work)
{
struct controlvm_message inmsg;
int count = 0;
@@ -1756,9 +1658,8 @@ controlvm_periodic_work(struct work_struct *work)
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
+ * 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;
@@ -1793,9 +1694,8 @@ 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
+ * it's been longer than MIN_IDLE_SECONDS since we processed
+ * our last controlvm message; slow down the polling
*/
if (chipset_dev->poll_jiffies !=
POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
@@ -1812,41 +1712,36 @@ schedule_out:
chipset_dev->poll_jiffies);
}
-static int
-visorchipset_init(struct acpi_device *acpi_device)
+static int visorchipset_init(struct acpi_device *acpi_device)
{
int err = -ENODEV;
- u64 addr;
- uuid_le uuid = VISOR_CONTROLVM_CHANNEL_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;
+ err = controlvm_channel_create(chipset_dev);
+ if (err)
+ goto error_free_chipset_dev;
acpi_device->driver_data = chipset_dev;
-
chipset_dev->acpi_device = acpi_device;
chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
- controlvm_channel = visorchannel_create_with_lock(addr,
- 0, GFP_KERNEL, uuid);
-
- if (!controlvm_channel)
- goto error_free_chipset_dev;
-
- chipset_dev->controlvm_channel = controlvm_channel;
err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj,
visorchipset_dev_groups);
if (err < 0)
goto error_destroy_channel;
- if (!VISOR_CONTROLVM_CHANNEL_OK_CLIENT(
- visorchannel_get_header(controlvm_channel)))
+ controlvm_channel = chipset_dev->controlvm_channel;
+ if (!visor_check_channel(visorchannel_get_header(controlvm_channel),
+ &chipset_dev->acpi_device->dev,
+ &visor_controlvm_channel_guid,
+ "controlvm",
+ sizeof(struct visor_controlvm_channel),
+ VISOR_CONTROLVM_CHANNEL_VERSIONID,
+ VISOR_CHANNEL_SIGNATURE))
goto error_delete_groups;
/* if booting in a crash kernel */
@@ -1886,8 +1781,7 @@ error:
return err;
}
-static int
-visorchipset_exit(struct acpi_device *acpi_device)
+static int visorchipset_exit(struct acpi_device *acpi_device)
{
visorbus_exit();
cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
@@ -1928,9 +1822,8 @@ static __init int visorutil_spar_detect(void)
return (ebx == UNISYS_VISOR_ID_EBX) &&
(ecx == UNISYS_VISOR_ID_ECX) &&
(edx == UNISYS_VISOR_ID_EDX);
- } else {
- return 0;
}
+ return 0;
}
static int init_unisys(void)