blob: ca752b8f495fa509fd8bd55bfbe9eecf68054f57 [file] [log] [blame]
Greg Kroah-Hartmanb79c0f42017-11-07 14:58:47 +01001// SPDX-License-Identifier: GPL-2.0
Zohaib Javede5178572017-08-22 13:26:51 -04002/*
Benjamin Romer6f14cc12015-07-16 12:40:48 -04003 * Copyright (C) 2010 - 2015 UNISYS CORPORATION
Ken Cox12e364b2014-03-04 07:58:07 -06004 * All rights reserved.
Ken Cox12e364b2014-03-04 07:58:07 -06005 */
6
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04007#include <linux/acpi.h>
Benjamin Romer1ba00982015-04-06 10:27:40 -04008#include <linux/crash_dump.h>
David Kershner93d3ad92017-12-07 12:11:07 -05009#include <linux/visorbus.h>
Ken Cox12e364b2014-03-04 07:58:07 -060010
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040011#include "visorbus_private.h"
12
David Kershnerf79e1df2017-08-22 13:27:20 -040013/* {72120008-4AAB-11DC-8530-444553544200} */
David Kershner1604ebe2017-08-30 13:36:33 -040014#define VISOR_SIOVM_GUID GUID_INIT(0x72120008, 0x4AAB, 0x11DC, 0x85, 0x30, \
15 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
David Kershnerf79e1df2017-08-22 13:27:20 -040016
Andy Shevchenkob32c5cb2017-08-22 13:26:54 -040017static const guid_t visor_vhba_channel_guid = VISOR_VHBA_CHANNEL_GUID;
18static const guid_t visor_siovm_guid = VISOR_SIOVM_GUID;
19static const guid_t visor_controlvm_channel_guid = VISOR_CONTROLVM_CHANNEL_GUID;
20
David Kershner3fbee192017-09-27 13:14:38 -040021#define POLLJIFFIES_CONTROLVM_FAST 1
22#define POLLJIFFIES_CONTROLVM_SLOW 100
Ken Cox12e364b2014-03-04 07:58:07 -060023
Bhaktipriya Shridhar2c7e1d42015-12-09 20:57:05 +053024#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -040025
Sameer Wadgaonkara27ded92017-05-19 16:17:47 -040026#define UNISYS_VISOR_LEAF_ID 0x40000000
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -040027
28/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
Sameer Wadgaonkara27ded92017-05-19 16:17:47 -040029#define UNISYS_VISOR_ID_EBX 0x73696e55
30#define UNISYS_VISOR_ID_ECX 0x70537379
31#define UNISYS_VISOR_ID_EDX 0x34367261
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -040032
Jes Sorensenb615d622015-05-05 18:35:38 -040033/*
David Kershner6577cbf2017-08-30 13:36:29 -040034 * When the controlvm channel is idle for at least MIN_IDLE_SECONDS, we switch
35 * to slow polling mode. As soon as we get a controlvm message, we switch back
36 * to fast polling mode.
David Binderec17f452016-06-10 21:48:18 -040037 */
Ken Cox12e364b2014-03-04 07:58:07 -060038#define MIN_IDLE_SECONDS 10
Ken Cox12e364b2014-03-04 07:58:07 -060039
Erik Arfvidson46168812015-05-05 18:36:14 -040040struct parser_context {
41 unsigned long allocbytes;
42 unsigned long param_bytes;
43 u8 *curr;
44 unsigned long bytes_remaining;
45 bool byte_stream;
David Kershner26a42c22017-08-30 13:36:24 -040046 struct visor_controlvm_parameters_header data;
Erik Arfvidson46168812015-05-05 18:36:14 -040047};
48
David Binder12cbd492017-08-22 13:27:01 -040049/* VMCALL_CONTROLVM_ADDR: Used by all guests, not just IO. */
David Binderc8684a92017-08-22 13:27:00 -040050#define VMCALL_CONTROLVM_ADDR 0x0501
51
52enum vmcall_result {
53 VMCALL_RESULT_SUCCESS = 0,
54 VMCALL_RESULT_INVALID_PARAM = 1,
55 VMCALL_RESULT_DATA_UNAVAILABLE = 2,
56 VMCALL_RESULT_FAILURE_UNAVAILABLE = 3,
57 VMCALL_RESULT_DEVICE_ERROR = 4,
58 VMCALL_RESULT_DEVICE_NOT_READY = 5
59};
60
61/*
62 * struct vmcall_io_controlvm_addr_params - Structure for IO VMCALLS. Has
63 * parameters to VMCALL_CONTROLVM_ADDR
64 * interface.
65 * @address: The Guest-relative physical address of the ControlVm channel.
66 * This VMCall fills this in with the appropriate address.
67 * Contents provided by this VMCALL (OUT).
68 * @channel_bytes: The size of the ControlVm channel in bytes This VMCall fills
69 * this in with the appropriate address. Contents provided by
70 * this VMCALL (OUT).
71 * @unused: Unused Bytes in the 64-Bit Aligned Struct.
72 */
73struct vmcall_io_controlvm_addr_params {
74 u64 address;
75 u32 channel_bytes;
76 u8 unused[4];
77} __packed;
78
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -050079struct visorchipset_device {
80 struct acpi_device *acpi_device;
81 unsigned long poll_jiffies;
82 /* when we got our last controlvm message */
83 unsigned long most_recent_message_jiffies;
84 struct delayed_work periodic_controlvm_work;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -050085 struct visorchannel *controlvm_channel;
86 unsigned long controlvm_payload_bytes_buffered;
87 /*
88 * The following variables are used to handle the scenario where we are
89 * unable to offload the payload from a controlvm message due to memory
90 * requirements. In this scenario, we simply stash the controlvm
91 * message, then attempt to process it again the next time
92 * controlvm_periodic_work() runs.
93 */
94 struct controlvm_message controlvm_pending_msg;
95 bool controlvm_pending_msg_valid;
David Kershner800da5f2017-08-30 13:36:13 -040096 struct vmcall_io_controlvm_addr_params controlvm_params;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -050097};
Ken Cox12e364b2014-03-04 07:58:07 -060098
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -050099static struct visorchipset_device *chipset_dev;
Ken Cox12e364b2014-03-04 07:58:07 -0600100
Ken Cox12e364b2014-03-04 07:58:07 -0600101struct parahotplug_request {
102 struct list_head list;
103 int id;
104 unsigned long expiration;
Benjamin Romer3ab47702014-10-23 14:30:31 -0400105 struct controlvm_message msg;
Ken Cox12e364b2014-03-04 07:58:07 -0600106};
107
Benjamin Romer19f66342014-07-22 09:56:25 -0400108/* prototypes for attributes */
109static ssize_t toolaction_show(struct device *dev,
David Kershner84efd202016-09-19 17:09:29 -0400110 struct device_attribute *attr,
111 char *buf)
112{
113 u8 tool_action = 0;
David Kershner002a5ab2017-03-28 09:34:23 -0400114 int err;
David Kershner84efd202016-09-19 17:09:29 -0400115
David Kershner002a5ab2017-03-28 09:34:23 -0400116 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400117 offsetof(struct visor_controlvm_channel,
David Kershner002a5ab2017-03-28 09:34:23 -0400118 tool_action),
119 &tool_action, sizeof(u8));
120 if (err)
121 return err;
David Binder746fb132017-01-03 16:01:15 -0500122 return sprintf(buf, "%u\n", tool_action);
David Kershner84efd202016-09-19 17:09:29 -0400123}
124
Benjamin Romer19f66342014-07-22 09:56:25 -0400125static ssize_t toolaction_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400126 struct device_attribute *attr,
David Kershner84efd202016-09-19 17:09:29 -0400127 const char *buf, size_t count)
128{
129 u8 tool_action;
David Kershnerdc35cdf2017-03-28 09:34:30 -0400130 int err;
David Kershner84efd202016-09-19 17:09:29 -0400131
132 if (kstrtou8(buf, 10, &tool_action))
133 return -EINVAL;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400134 err = visorchannel_write(chipset_dev->controlvm_channel,
135 offsetof(struct visor_controlvm_channel,
136 tool_action),
137 &tool_action, sizeof(u8));
David Kershnerdc35cdf2017-03-28 09:34:30 -0400138 if (err)
139 return err;
David Kershner84efd202016-09-19 17:09:29 -0400140 return count;
141}
Benjamin Romer19f66342014-07-22 09:56:25 -0400142static DEVICE_ATTR_RW(toolaction);
143
Benjamin Romer54b31222014-07-22 09:56:26 -0400144static ssize_t boottotool_show(struct device *dev,
David Kershner1b1d4632016-09-19 17:09:30 -0400145 struct device_attribute *attr,
146 char *buf)
147{
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400148 struct efi_visor_indication efi_visor_indication;
David Kershner0b01c6c2017-03-28 09:34:24 -0400149 int err;
David Kershner1b1d4632016-09-19 17:09:30 -0400150
David Kershner0b01c6c2017-03-28 09:34:24 -0400151 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400152 offsetof(struct visor_controlvm_channel,
153 efi_visor_ind),
154 &efi_visor_indication,
155 sizeof(struct efi_visor_indication));
David Kershner0b01c6c2017-03-28 09:34:24 -0400156 if (err)
157 return err;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400158 return sprintf(buf, "%u\n", efi_visor_indication.boot_to_tool);
David Kershner1b1d4632016-09-19 17:09:30 -0400159}
160
Benjamin Romer54b31222014-07-22 09:56:26 -0400161static ssize_t boottotool_store(struct device *dev,
David Kershner1b1d4632016-09-19 17:09:30 -0400162 struct device_attribute *attr,
163 const char *buf, size_t count)
164{
David Kershnerb3092662017-03-28 09:34:31 -0400165 int val, err;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400166 struct efi_visor_indication efi_visor_indication;
David Kershner1b1d4632016-09-19 17:09:30 -0400167
168 if (kstrtoint(buf, 10, &val))
169 return -EINVAL;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400170 efi_visor_indication.boot_to_tool = val;
171 err = visorchannel_write(chipset_dev->controlvm_channel,
172 offsetof(struct visor_controlvm_channel,
173 efi_visor_ind),
174 &(efi_visor_indication),
175 sizeof(struct efi_visor_indication));
David Kershnerb3092662017-03-28 09:34:31 -0400176 if (err)
177 return err;
David Kershner1b1d4632016-09-19 17:09:30 -0400178 return count;
179}
Benjamin Romer54b31222014-07-22 09:56:26 -0400180static DEVICE_ATTR_RW(boottotool);
181
Benjamin Romer422af172014-07-24 14:08:42 -0400182static ssize_t error_show(struct device *dev, struct device_attribute *attr,
David Kershner8a4a8a02016-09-19 17:09:31 -0400183 char *buf)
184{
185 u32 error = 0;
David Kershnerd9857c72017-03-28 09:34:25 -0400186 int err;
David Kershner8a4a8a02016-09-19 17:09:31 -0400187
David Kershnerd9857c72017-03-28 09:34:25 -0400188 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400189 offsetof(struct visor_controlvm_channel,
David Kershnerd9857c72017-03-28 09:34:25 -0400190 installation_error),
191 &error, sizeof(u32));
192 if (err)
193 return err;
David Binder6df555c2017-08-22 13:27:25 -0400194 return sprintf(buf, "%u\n", error);
David Kershner8a4a8a02016-09-19 17:09:31 -0400195}
196
Benjamin Romer422af172014-07-24 14:08:42 -0400197static ssize_t error_store(struct device *dev, struct device_attribute *attr,
David Kershner8a4a8a02016-09-19 17:09:31 -0400198 const char *buf, size_t count)
199{
200 u32 error;
David Kershnerea295852017-03-28 09:34:32 -0400201 int err;
David Kershner8a4a8a02016-09-19 17:09:31 -0400202
203 if (kstrtou32(buf, 10, &error))
204 return -EINVAL;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400205 err = visorchannel_write(chipset_dev->controlvm_channel,
206 offsetof(struct visor_controlvm_channel,
207 installation_error),
208 &error, sizeof(u32));
David Kershnerea295852017-03-28 09:34:32 -0400209 if (err)
210 return err;
David Kershner8a4a8a02016-09-19 17:09:31 -0400211 return count;
212}
Benjamin Romer422af172014-07-24 14:08:42 -0400213static DEVICE_ATTR_RW(error);
214
215static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
David Kershner79730c72016-09-19 17:09:32 -0400216 char *buf)
217{
218 u32 text_id = 0;
David Kershner0d406432017-03-28 09:34:26 -0400219 int err;
David Kershner79730c72016-09-19 17:09:32 -0400220
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400221 err = visorchannel_read(chipset_dev->controlvm_channel,
222 offsetof(struct visor_controlvm_channel,
223 installation_text_id),
224 &text_id, sizeof(u32));
David Kershner0d406432017-03-28 09:34:26 -0400225 if (err)
226 return err;
David Binder6df555c2017-08-22 13:27:25 -0400227 return sprintf(buf, "%u\n", text_id);
David Kershner79730c72016-09-19 17:09:32 -0400228}
229
Benjamin Romer422af172014-07-24 14:08:42 -0400230static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
David Kershner79730c72016-09-19 17:09:32 -0400231 const char *buf, size_t count)
232{
233 u32 text_id;
David Kershner08a55d22017-03-28 09:34:33 -0400234 int err;
David Kershner79730c72016-09-19 17:09:32 -0400235
236 if (kstrtou32(buf, 10, &text_id))
237 return -EINVAL;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400238 err = visorchannel_write(chipset_dev->controlvm_channel,
239 offsetof(struct visor_controlvm_channel,
240 installation_text_id),
241 &text_id, sizeof(u32));
David Kershner08a55d22017-03-28 09:34:33 -0400242 if (err)
243 return err;
David Kershner79730c72016-09-19 17:09:32 -0400244 return count;
245}
Benjamin Romer422af172014-07-24 14:08:42 -0400246static DEVICE_ATTR_RW(textid);
247
248static ssize_t remaining_steps_show(struct device *dev,
David Kershner97f792e2016-09-19 17:09:33 -0400249 struct device_attribute *attr, char *buf)
250{
251 u16 remaining_steps = 0;
David Kershnerc53578b2017-03-28 09:34:27 -0400252 int err;
David Kershner97f792e2016-09-19 17:09:33 -0400253
David Kershnerc53578b2017-03-28 09:34:27 -0400254 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400255 offsetof(struct visor_controlvm_channel,
David Kershnerc53578b2017-03-28 09:34:27 -0400256 installation_remaining_steps),
257 &remaining_steps, sizeof(u16));
258 if (err)
259 return err;
David Binder746fb132017-01-03 16:01:15 -0500260 return sprintf(buf, "%hu\n", remaining_steps);
David Kershner97f792e2016-09-19 17:09:33 -0400261}
262
Benjamin Romer422af172014-07-24 14:08:42 -0400263static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400264 struct device_attribute *attr,
David Kershner97f792e2016-09-19 17:09:33 -0400265 const char *buf, size_t count)
266{
267 u16 remaining_steps;
David Kershnere030d392017-03-28 09:34:34 -0400268 int err;
David Kershner97f792e2016-09-19 17:09:33 -0400269
270 if (kstrtou16(buf, 10, &remaining_steps))
271 return -EINVAL;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400272 err = visorchannel_write(chipset_dev->controlvm_channel,
273 offsetof(struct visor_controlvm_channel,
274 installation_remaining_steps),
275 &remaining_steps, sizeof(u16));
David Kershnere030d392017-03-28 09:34:34 -0400276 if (err)
277 return err;
David Kershner97f792e2016-09-19 17:09:33 -0400278 return count;
279}
Benjamin Romer422af172014-07-24 14:08:42 -0400280static DEVICE_ATTR_RW(remaining_steps);
281
Charles Danielse80ffd42017-08-22 13:26:57 -0400282static void controlvm_init_response(struct controlvm_message *msg,
283 struct controlvm_message_header *msg_hdr,
284 int response)
David Kershner5f251392016-09-19 17:09:26 -0400285{
286 memset(msg, 0, sizeof(struct controlvm_message));
287 memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
288 msg->hdr.payload_bytes = 0;
289 msg->hdr.payload_vm_offset = 0;
290 msg->hdr.payload_max_bytes = 0;
291 if (response < 0) {
292 msg->hdr.flags.failed = 1;
293 msg->hdr.completion_status = (u32)(-response);
294 }
295}
296
Charles Danielse80ffd42017-08-22 13:26:57 -0400297static int controlvm_respond_chipset_init(
298 struct controlvm_message_header *msg_hdr,
299 int response,
300 enum visor_chipset_feature features)
David Kershner5f251392016-09-19 17:09:26 -0400301{
302 struct controlvm_message outmsg;
303
304 controlvm_init_response(&outmsg, msg_hdr, response);
305 outmsg.cmd.init_chipset.features = features;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500306 return visorchannel_signalinsert(chipset_dev->controlvm_channel,
David Kershner1d7f5522016-11-21 12:15:44 -0500307 CONTROLVM_QUEUE_REQUEST, &outmsg);
David Kershner5f251392016-09-19 17:09:26 -0400308}
309
Charles Danielse80ffd42017-08-22 13:26:57 -0400310static int chipset_init(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600311{
312 static int chipset_inited;
Sameer Wadgaonkard3ad6e62017-05-19 16:17:50 -0400313 enum visor_chipset_feature features = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600314 int rc = CONTROLVM_RESP_SUCCESS;
David Kershner79c3f972016-11-21 12:15:45 -0500315 int res = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600316
Ken Cox12e364b2014-03-04 07:58:07 -0600317 if (chipset_inited) {
Sameer Wadgaonkar98f9ed92016-12-22 11:08:58 -0500318 rc = -CONTROLVM_RESP_ALREADY_DONE;
David Kershner79c3f972016-11-21 12:15:45 -0500319 res = -EIO;
David Kershner5233d1e2016-03-11 17:01:41 -0500320 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600321 }
322 chipset_inited = 1;
David Binderec17f452016-06-10 21:48:18 -0400323 /*
David Kershner6577cbf2017-08-30 13:36:29 -0400324 * Set features to indicate we support parahotplug (if Command also
David Kershner977980a2017-09-27 13:14:06 -0400325 * supports it). Set the "reply" bit so Command knows this is a
326 * features-aware driver.
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500327 */
David Binder07621882016-11-03 11:44:28 -0400328 features = inmsg->cmd.init_chipset.features &
Sameer Wadgaonkard3ad6e62017-05-19 16:17:50 -0400329 VISOR_CHIPSET_FEATURE_PARA_HOTPLUG;
Sameer Wadgaonkard3ad6e62017-05-19 16:17:50 -0400330 features |= VISOR_CHIPSET_FEATURE_REPLY;
Ken Cox12e364b2014-03-04 07:58:07 -0600331
David Kershner5233d1e2016-03-11 17:01:41 -0500332out_respond:
Benjamin Romer98d7b592014-10-23 14:30:26 -0400333 if (inmsg->hdr.flags.response_expected)
David Kershner79c3f972016-11-21 12:15:45 -0500334 res = controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
335
336 return res;
Ken Cox12e364b2014-03-04 07:58:07 -0600337}
338
Charles Danielse80ffd42017-08-22 13:26:57 -0400339static int controlvm_respond(struct controlvm_message_header *msg_hdr,
David Kershner040b78f2017-09-27 13:14:10 -0400340 int response, struct visor_segment_state *state)
Ken Cox12e364b2014-03-04 07:58:07 -0600341{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400342 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400343
Benjamin Romerb3168c72015-03-16 13:58:46 -0400344 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500345 if (outmsg.hdr.flags.test_message == 1)
David Kershner2d26aeb2016-11-21 12:15:46 -0500346 return -EINVAL;
David Kershner4c0e65f2017-04-18 16:55:01 -0400347 if (state) {
348 outmsg.cmd.device_change_state.state = *state;
349 outmsg.cmd.device_change_state.flags.phys_device = 1;
350 }
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500351 return visorchannel_signalinsert(chipset_dev->controlvm_channel,
David Kershner2c4ef562016-11-21 12:15:47 -0500352 CONTROLVM_QUEUE_REQUEST, &outmsg);
Ken Cox12e364b2014-03-04 07:58:07 -0600353}
354
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400355enum crash_obj_type {
356 CRASH_DEV,
357 CRASH_BUS,
358};
359
Charles Danielse80ffd42017-08-22 13:26:57 -0400360static int save_crash_message(struct controlvm_message *msg,
361 enum crash_obj_type cr_type)
Tim Sell12c957d2016-03-01 19:45:04 -0500362{
363 u32 local_crash_msg_offset;
364 u16 local_crash_msg_count;
David Kershner8dff01f2016-11-21 12:15:48 -0500365 int err;
Tim Sell12c957d2016-03-01 19:45:04 -0500366
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500367 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400368 offsetof(struct visor_controlvm_channel,
David Kershner8dff01f2016-11-21 12:15:48 -0500369 saved_crash_message_count),
370 &local_crash_msg_count, sizeof(u16));
371 if (err) {
David Kershner35301b82017-04-18 16:55:16 -0400372 dev_err(&chipset_dev->acpi_device->dev,
373 "failed to read message count\n");
David Kershner8dff01f2016-11-21 12:15:48 -0500374 return err;
Tim Sell12c957d2016-03-01 19:45:04 -0500375 }
Tim Sell12c957d2016-03-01 19:45:04 -0500376 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
David Kershner35301b82017-04-18 16:55:16 -0400377 dev_err(&chipset_dev->acpi_device->dev,
378 "invalid number of messages\n");
David Kershner8dff01f2016-11-21 12:15:48 -0500379 return -EIO;
Tim Sell12c957d2016-03-01 19:45:04 -0500380 }
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500381 err = visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400382 offsetof(struct visor_controlvm_channel,
David Kershner8dff01f2016-11-21 12:15:48 -0500383 saved_crash_message_offset),
384 &local_crash_msg_offset, sizeof(u32));
385 if (err) {
David Kershner35301b82017-04-18 16:55:16 -0400386 dev_err(&chipset_dev->acpi_device->dev,
387 "failed to read offset\n");
David Kershner8dff01f2016-11-21 12:15:48 -0500388 return err;
Tim Sell12c957d2016-03-01 19:45:04 -0500389 }
Jon Frisch603a1982017-05-19 16:17:35 -0400390 switch (cr_type) {
David Binder36309d32016-12-22 11:08:59 -0500391 case CRASH_DEV:
Tim Sell12c957d2016-03-01 19:45:04 -0500392 local_crash_msg_offset += sizeof(struct controlvm_message);
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500393 err = visorchannel_write(chipset_dev->controlvm_channel,
David Kershner040b78f2017-09-27 13:14:10 -0400394 local_crash_msg_offset, msg,
David Kershner8dff01f2016-11-21 12:15:48 -0500395 sizeof(struct controlvm_message));
396 if (err) {
David Kershner35301b82017-04-18 16:55:16 -0400397 dev_err(&chipset_dev->acpi_device->dev,
398 "failed to write dev msg\n");
David Kershner8dff01f2016-11-21 12:15:48 -0500399 return err;
Tim Sell12c957d2016-03-01 19:45:04 -0500400 }
David Binder36309d32016-12-22 11:08:59 -0500401 break;
402 case CRASH_BUS:
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500403 err = visorchannel_write(chipset_dev->controlvm_channel,
David Kershner040b78f2017-09-27 13:14:10 -0400404 local_crash_msg_offset, msg,
David Binder36309d32016-12-22 11:08:59 -0500405 sizeof(struct controlvm_message));
406 if (err) {
David Kershner35301b82017-04-18 16:55:16 -0400407 dev_err(&chipset_dev->acpi_device->dev,
408 "failed to write bus msg\n");
David Binder36309d32016-12-22 11:08:59 -0500409 return err;
410 }
411 break;
412 default:
David Kershner35301b82017-04-18 16:55:16 -0400413 dev_err(&chipset_dev->acpi_device->dev,
414 "Invalid crash_obj_type\n");
David Binder36309d32016-12-22 11:08:59 -0500415 break;
Tim Sell12c957d2016-03-01 19:45:04 -0500416 }
David Kershner8dff01f2016-11-21 12:15:48 -0500417 return 0;
Tim Sell12c957d2016-03-01 19:45:04 -0500418}
419
Charles Danielse80ffd42017-08-22 13:26:57 -0400420static int controlvm_responder(enum controlvm_id cmd_id,
421 struct controlvm_message_header *pending_msg_hdr,
422 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600423{
Don Zickus0274b5a2015-06-01 13:00:27 -0400424 if (pending_msg_hdr->id != (u32)cmd_id)
David Kershner734ad932016-11-21 12:15:49 -0500425 return -EINVAL;
Don Zickus0274b5a2015-06-01 13:00:27 -0400426
David Kershner4c0e65f2017-04-18 16:55:01 -0400427 return controlvm_respond(pending_msg_hdr, response, NULL);
Ken Cox12e364b2014-03-04 07:58:07 -0600428}
429
David Kershnerda56cb02017-09-27 13:14:39 -0400430static int device_changestate_responder(enum controlvm_id cmd_id,
431 struct visor_device *p, int response,
432 struct visor_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -0600433{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400434 struct controlvm_message outmsg;
Ken Cox12e364b2014-03-04 07:58:07 -0600435
Don Zickus0274b5a2015-06-01 13:00:27 -0400436 if (p->pending_msg_hdr->id != cmd_id)
David Kershner68f99d42016-11-21 12:15:50 -0500437 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -0600438
Don Zickus0274b5a2015-06-01 13:00:27 -0400439 controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
David Kershnerb253ff52017-08-22 13:27:23 -0400440 outmsg.cmd.device_change_state.bus_no = p->chipset_bus_no;
441 outmsg.cmd.device_change_state.dev_no = p->chipset_dev_no;
David Kershnerda56cb02017-09-27 13:14:39 -0400442 outmsg.cmd.device_change_state.state = state;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -0500443 return visorchannel_signalinsert(chipset_dev->controlvm_channel,
David Kershner68f99d42016-11-21 12:15:50 -0500444 CONTROLVM_QUEUE_REQUEST, &outmsg);
Ken Cox12e364b2014-03-04 07:58:07 -0600445}
446
Charles Danielse80ffd42017-08-22 13:26:57 -0400447static int visorbus_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600448{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400449 struct controlvm_message_packet *cmd = &inmsg->cmd;
David Kershneref7b9dc2017-09-27 13:14:37 -0400450 struct controlvm_message_header *pmsg_hdr;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400451 u32 bus_no = cmd->create_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400452 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -0400453 struct visorchannel *visorchannel;
David Kershner33161a22016-11-03 11:44:22 -0400454 int err;
Ken Cox12e364b2014-03-04 07:58:07 -0600455
Don Zickusd32517e2015-06-04 09:22:41 -0400456 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
David Kershner614b0832017-09-27 13:14:48 -0400457 if (bus_info && bus_info->state.created == 1) {
David Kershner055bc902017-04-18 16:55:17 -0400458 dev_err(&chipset_dev->acpi_device->dev,
Zachary Dremann87408fe2017-06-30 15:43:25 -0400459 "failed %s: already exists\n", __func__);
David Kershner33161a22016-11-03 11:44:22 -0400460 err = -EEXIST;
461 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600462 }
Benjamin Romer6c5fed32015-03-16 13:58:20 -0400463 bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
464 if (!bus_info) {
David Kershner33161a22016-11-03 11:44:22 -0400465 err = -ENOMEM;
466 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600467 }
David Kershner4abce832015-06-04 09:22:49 -0400468 INIT_LIST_HEAD(&bus_info->list_all);
Don Zickusd32517e2015-06-04 09:22:41 -0400469 bus_info->chipset_bus_no = bus_no;
470 bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
Andy Shevchenkob32c5cb2017-08-22 13:26:54 -0400471 if (guid_equal(&cmd->create_bus.bus_inst_guid, &visor_siovm_guid)) {
David Kershner300ed612016-12-22 11:09:05 -0500472 err = save_crash_message(inmsg, CRASH_BUS);
473 if (err)
474 goto err_free_bus_info;
475 }
David Kershner8f334e32016-11-03 11:44:19 -0400476 if (inmsg->hdr.flags.response_expected == 1) {
David Kershner040b78f2017-09-27 13:14:10 -0400477 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
David Kershner8f334e32016-11-03 11:44:19 -0400478 if (!pmsg_hdr) {
David Kershner33161a22016-11-03 11:44:22 -0400479 err = -ENOMEM;
480 goto err_free_bus_info;
David Kershner8f334e32016-11-03 11:44:19 -0400481 }
David Kershner8f334e32016-11-03 11:44:19 -0400482 memcpy(pmsg_hdr, &inmsg->hdr,
483 sizeof(struct controlvm_message_header));
484 bus_info->pending_msg_hdr = pmsg_hdr;
485 }
David Kershner33161a22016-11-03 11:44:22 -0400486 visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
David Kershner33161a22016-11-03 11:44:22 -0400487 GFP_KERNEL,
Sameer Wadgaonkar90476672017-09-27 13:14:44 -0400488 &cmd->create_bus.bus_data_type_guid,
489 false);
David Kershner33161a22016-11-03 11:44:22 -0400490 if (!visorchannel) {
David Kershner33161a22016-11-03 11:44:22 -0400491 err = -ENOMEM;
492 goto err_free_pending_msg;
493 }
494 bus_info->visorchannel = visorchannel;
David Kershnerfdf5b9a2017-08-22 13:27:24 -0400495 /* Response will be handled by visorbus_create_instance on success */
496 err = visorbus_create_instance(bus_info);
David Kershner621f5e12017-03-28 09:34:35 -0400497 if (err)
498 goto err_destroy_channel;
David Kershner33161a22016-11-03 11:44:22 -0400499 return 0;
David Kershner8f334e32016-11-03 11:44:19 -0400500
David Kershner621f5e12017-03-28 09:34:35 -0400501err_destroy_channel:
502 visorchannel_destroy(visorchannel);
503
David Kershner33161a22016-11-03 11:44:22 -0400504err_free_pending_msg:
505 kfree(bus_info->pending_msg_hdr);
506
507err_free_bus_info:
David Kershner8f334e32016-11-03 11:44:19 -0400508 kfree(bus_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600509
David Kershner33161a22016-11-03 11:44:22 -0400510err_respond:
David Kershner8f334e32016-11-03 11:44:19 -0400511 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400512 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershner33161a22016-11-03 11:44:22 -0400513 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600514}
515
Charles Danielse80ffd42017-08-22 13:26:57 -0400516static int visorbus_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600517{
David Kershneref7b9dc2017-09-27 13:14:37 -0400518 struct controlvm_message_header *pmsg_hdr;
David Kershner3f5a5622017-09-27 13:14:07 -0400519 u32 bus_no = inmsg->cmd.destroy_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400520 struct visor_device *bus_info;
David Kershner30f6c3f2016-11-03 11:44:21 -0400521 int err;
Ken Cox12e364b2014-03-04 07:58:07 -0600522
Don Zickusd32517e2015-06-04 09:22:41 -0400523 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
David Kershner3e0e8db2016-11-03 11:44:20 -0400524 if (!bus_info) {
David Kershner30f6c3f2016-11-03 11:44:21 -0400525 err = -ENODEV;
526 goto err_respond;
David Kershner3e0e8db2016-11-03 11:44:20 -0400527 }
528 if (bus_info->state.created == 0) {
David Kershner30f6c3f2016-11-03 11:44:21 -0400529 err = -ENOENT;
530 goto err_respond;
David Kershner3e0e8db2016-11-03 11:44:20 -0400531 }
532 if (bus_info->pending_msg_hdr) {
533 /* only non-NULL if dev is still waiting on a response */
David Kershner30f6c3f2016-11-03 11:44:21 -0400534 err = -EEXIST;
535 goto err_respond;
David Kershner3e0e8db2016-11-03 11:44:20 -0400536 }
537 if (inmsg->hdr.flags.response_expected == 1) {
538 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
539 if (!pmsg_hdr) {
David Kershner30f6c3f2016-11-03 11:44:21 -0400540 err = -ENOMEM;
541 goto err_respond;
David Kershner3e0e8db2016-11-03 11:44:20 -0400542 }
David Kershner3e0e8db2016-11-03 11:44:20 -0400543 memcpy(pmsg_hdr, &inmsg->hdr,
544 sizeof(struct controlvm_message_header));
545 bus_info->pending_msg_hdr = pmsg_hdr;
546 }
Sameer Wadgaonkara7093ba2017-08-22 13:27:33 -0400547 /* Response will be handled by visorbus_remove_instance */
548 visorbus_remove_instance(bus_info);
David Kershner30f6c3f2016-11-03 11:44:21 -0400549 return 0;
David Kershner3e0e8db2016-11-03 11:44:20 -0400550
David Kershner30f6c3f2016-11-03 11:44:21 -0400551err_respond:
David Kershner3e0e8db2016-11-03 11:44:20 -0400552 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400553 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershner30f6c3f2016-11-03 11:44:21 -0400554 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600555}
556
David Kershner39b486d2017-08-30 13:36:27 -0400557static const guid_t *parser_id_get(struct parser_context *ctx)
558{
559 return &ctx->data.id;
560}
561
David Kershner90d1ecf2017-09-27 13:14:08 -0400562static void *parser_string_get(u8 *pscan, int nscan)
David Kershner39b486d2017-08-30 13:36:27 -0400563{
David Kershner39b486d2017-08-30 13:36:27 -0400564 int value_length;
565 void *value;
David Kershner39b486d2017-08-30 13:36:27 -0400566
David Kershner39b486d2017-08-30 13:36:27 -0400567 if (nscan == 0)
568 return NULL;
569
David Kershner90d1ecf2017-09-27 13:14:08 -0400570 value_length = strnlen(pscan, nscan);
571 value = kzalloc(value_length + 1, GFP_KERNEL);
David Kershner39b486d2017-08-30 13:36:27 -0400572 if (!value)
573 return NULL;
574 if (value_length > 0)
575 memcpy(value, pscan, value_length);
David Kershner39b486d2017-08-30 13:36:27 -0400576 return value;
577}
578
579static void *parser_name_get(struct parser_context *ctx)
580{
David Kershneref7b9dc2017-09-27 13:14:37 -0400581 struct visor_controlvm_parameters_header *phdr;
David Kershner39b486d2017-08-30 13:36:27 -0400582
583 phdr = &ctx->data;
Tim Sella5eb2182017-11-17 12:27:38 -0500584 if ((unsigned long)phdr->name_offset +
585 (unsigned long)phdr->name_length > ctx->param_bytes)
David Kershner39b486d2017-08-30 13:36:27 -0400586 return NULL;
David Kershner39b486d2017-08-30 13:36:27 -0400587 ctx->curr = (char *)&phdr + phdr->name_offset;
588 ctx->bytes_remaining = phdr->name_length;
David Kershner90d1ecf2017-09-27 13:14:08 -0400589 return parser_string_get(ctx->curr, phdr->name_length);
David Kershner39b486d2017-08-30 13:36:27 -0400590}
591
Charles Danielse80ffd42017-08-22 13:26:57 -0400592static int visorbus_configure(struct controlvm_message *inmsg,
593 struct parser_context *parser_ctx)
Ken Cox12e364b2014-03-04 07:58:07 -0600594{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400595 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -0400596 u32 bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400597 struct visor_device *bus_info;
David Kershnerc71529f2016-11-21 12:15:53 -0500598 int err = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600599
Benjamin Romer654bada2015-03-16 13:58:22 -0400600 bus_no = cmd->configure_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400601 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer654bada2015-03-16 13:58:22 -0400602 if (!bus_info) {
David Kershnerc71529f2016-11-21 12:15:53 -0500603 err = -EINVAL;
604 goto err_respond;
David Kershneraf53ce42017-08-30 13:36:23 -0400605 }
606 if (bus_info->state.created == 0) {
David Kershnerc71529f2016-11-21 12:15:53 -0500607 err = -EINVAL;
608 goto err_respond;
David Kershneraf53ce42017-08-30 13:36:23 -0400609 }
610 if (bus_info->pending_msg_hdr) {
David Kershnerc71529f2016-11-21 12:15:53 -0500611 err = -EIO;
612 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600613 }
David Kershner34fbf6a2017-09-27 13:14:11 -0400614 err = visorchannel_set_clientpartition(bus_info->visorchannel,
615 cmd->configure_bus.guest_handle);
David Kershnerc71529f2016-11-21 12:15:53 -0500616 if (err)
617 goto err_respond;
David Kershner046f93d2017-01-09 13:02:23 -0500618 if (parser_ctx) {
Andy Shevchenkob32c5cb2017-08-22 13:26:54 -0400619 const guid_t *partition_guid = parser_id_get(parser_ctx);
620
621 guid_copy(&bus_info->partition_guid, partition_guid);
David Kershner046f93d2017-01-09 13:02:23 -0500622 bus_info->name = parser_name_get(parser_ctx);
623 }
David Kershnerb6b057d2016-11-03 11:44:23 -0400624 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400625 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershnerc71529f2016-11-21 12:15:53 -0500626 return 0;
627
628err_respond:
David Kershner71a0265d2017-04-18 16:55:18 -0400629 dev_err(&chipset_dev->acpi_device->dev,
David Kershner9a8dc902017-08-30 13:36:16 -0400630 "%s exited with err: %d\n", __func__, err);
David Kershnerc71529f2016-11-21 12:15:53 -0500631 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400632 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershnerc71529f2016-11-21 12:15:53 -0500633 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600634}
635
Charles Danielse80ffd42017-08-22 13:26:57 -0400636static int visorbus_device_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600637{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400638 struct controlvm_message_packet *cmd = &inmsg->cmd;
David Kershneref7b9dc2017-09-27 13:14:37 -0400639 struct controlvm_message_header *pmsg_hdr;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400640 u32 bus_no = cmd->create_device.bus_no;
641 u32 dev_no = cmd->create_device.dev_no;
David Kershneref7b9dc2017-09-27 13:14:37 -0400642 struct visor_device *dev_info;
Don Zickusd32517e2015-06-04 09:22:41 -0400643 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -0400644 struct visorchannel *visorchannel;
David Kershnerad2a7d652016-12-22 11:09:04 -0500645 int err;
Ken Cox12e364b2014-03-04 07:58:07 -0600646
Don Zickusa298bc02015-06-04 09:22:42 -0400647 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400648 if (!bus_info) {
David Kershnera8c26e42017-04-18 16:55:19 -0400649 dev_err(&chipset_dev->acpi_device->dev,
650 "failed to get bus by id: %d\n", bus_no);
David Kershnerad2a7d652016-12-22 11:09:04 -0500651 err = -ENODEV;
652 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600653 }
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400654 if (bus_info->state.created == 0) {
David Kershnera8c26e42017-04-18 16:55:19 -0400655 dev_err(&chipset_dev->acpi_device->dev,
656 "bus not created, id: %d\n", bus_no);
David Kershnerad2a7d652016-12-22 11:09:04 -0500657 err = -EINVAL;
658 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600659 }
Don Zickusa298bc02015-06-04 09:22:42 -0400660 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
David Kershner614b0832017-09-27 13:14:48 -0400661 if (dev_info && dev_info->state.created == 1) {
David Kershnera8c26e42017-04-18 16:55:19 -0400662 dev_err(&chipset_dev->acpi_device->dev,
663 "failed to get bus by id: %d/%d\n", bus_no, dev_no);
David Kershnerad2a7d652016-12-22 11:09:04 -0500664 err = -EEXIST;
665 goto err_respond;
Don Zickusa298bc02015-06-04 09:22:42 -0400666 }
667
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400668 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
669 if (!dev_info) {
David Kershnerad2a7d652016-12-22 11:09:04 -0500670 err = -ENOMEM;
671 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600672 }
Don Zickusa298bc02015-06-04 09:22:42 -0400673 dev_info->chipset_bus_no = bus_no;
674 dev_info->chipset_dev_no = dev_no;
Andy Shevchenkob32c5cb2017-08-22 13:26:54 -0400675 guid_copy(&dev_info->inst, &cmd->create_device.dev_inst_guid);
Don Zickusa298bc02015-06-04 09:22:42 -0400676 dev_info->device.parent = &bus_info->device;
Sameer Wadgaonkar90476672017-09-27 13:14:44 -0400677 visorchannel = visorchannel_create(cmd->create_device.channel_addr,
678 GFP_KERNEL,
679 &cmd->create_device.data_type_guid,
680 true);
Don Zickusb32c4992015-06-01 13:00:26 -0400681 if (!visorchannel) {
David Kershnera8c26e42017-04-18 16:55:19 -0400682 dev_err(&chipset_dev->acpi_device->dev,
683 "failed to create visorchannel: %d/%d\n",
684 bus_no, dev_no);
David Kershnerad2a7d652016-12-22 11:09:04 -0500685 err = -ENOMEM;
686 goto err_free_dev_info;
Don Zickusb32c4992015-06-01 13:00:26 -0400687 }
688 dev_info->visorchannel = visorchannel;
Sameer Wadgaonkarfe9f4b52017-09-27 13:14:45 -0400689 guid_copy(&dev_info->channel_type_guid,
690 &cmd->create_device.data_type_guid);
691 if (guid_equal(&cmd->create_device.data_type_guid,
692 &visor_vhba_channel_guid)) {
David Kershnerad2a7d652016-12-22 11:09:04 -0500693 err = save_crash_message(inmsg, CRASH_DEV);
694 if (err)
David Kershner3f49a212017-03-28 09:34:38 -0400695 goto err_destroy_visorchannel;
David Kershnerad2a7d652016-12-22 11:09:04 -0500696 }
David Kershner5a80e982016-11-03 11:44:24 -0400697 if (inmsg->hdr.flags.response_expected == 1) {
698 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
699 if (!pmsg_hdr) {
David Kershnerad2a7d652016-12-22 11:09:04 -0500700 err = -ENOMEM;
David Kershner3f49a212017-03-28 09:34:38 -0400701 goto err_destroy_visorchannel;
David Kershner5a80e982016-11-03 11:44:24 -0400702 }
David Kershner5a80e982016-11-03 11:44:24 -0400703 memcpy(pmsg_hdr, &inmsg->hdr,
704 sizeof(struct controlvm_message_header));
705 dev_info->pending_msg_hdr = pmsg_hdr;
706 }
Sameer Wadgaonkar51c0f812017-08-22 13:27:34 -0400707 /* create_visor_device will send response */
708 err = create_visor_device(dev_info);
David Kershner3f49a212017-03-28 09:34:38 -0400709 if (err)
710 goto err_destroy_visorchannel;
711
David Kershnerad2a7d652016-12-22 11:09:04 -0500712 return 0;
David Kershner5a80e982016-11-03 11:44:24 -0400713
David Kershner3f49a212017-03-28 09:34:38 -0400714err_destroy_visorchannel:
715 visorchannel_destroy(visorchannel);
716
David Kershnerad2a7d652016-12-22 11:09:04 -0500717err_free_dev_info:
David Kershner5a80e982016-11-03 11:44:24 -0400718 kfree(dev_info);
719
David Kershnerad2a7d652016-12-22 11:09:04 -0500720err_respond:
David Kershner5a80e982016-11-03 11:44:24 -0400721 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400722 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershnerad2a7d652016-12-22 11:09:04 -0500723 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600724}
725
Charles Danielse80ffd42017-08-22 13:26:57 -0400726static int visorbus_device_changestate(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600727{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400728 struct controlvm_message_packet *cmd = &inmsg->cmd;
David Kershneref7b9dc2017-09-27 13:14:37 -0400729 struct controlvm_message_header *pmsg_hdr;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400730 u32 bus_no = cmd->device_change_state.bus_no;
731 u32 dev_no = cmd->device_change_state.dev_no;
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -0400732 struct visor_segment_state state = cmd->device_change_state.state;
Don Zickusa298bc02015-06-04 09:22:42 -0400733 struct visor_device *dev_info;
David Kershnerb4a8e6a2017-03-28 09:34:54 -0400734 int err = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600735
Don Zickusa298bc02015-06-04 09:22:42 -0400736 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer0278a902015-03-16 13:58:24 -0400737 if (!dev_info) {
David Kershner40fc79f2016-12-22 11:09:06 -0500738 err = -ENODEV;
David Kershner0825f192016-11-03 11:44:25 -0400739 goto err_respond;
740 }
741 if (dev_info->state.created == 0) {
David Kershner40fc79f2016-12-22 11:09:06 -0500742 err = -EINVAL;
David Kershner0825f192016-11-03 11:44:25 -0400743 goto err_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600744 }
David Kershner8e609b52016-11-03 11:44:26 -0400745 if (dev_info->pending_msg_hdr) {
746 /* only non-NULL if dev is still waiting on a response */
David Kershner40fc79f2016-12-22 11:09:06 -0500747 err = -EIO;
David Kershner8e609b52016-11-03 11:44:26 -0400748 goto err_respond;
749 }
David Kershner9116ae72017-09-27 13:14:26 -0400750
David Kershner8e609b52016-11-03 11:44:26 -0400751 if (inmsg->hdr.flags.response_expected == 1) {
752 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
753 if (!pmsg_hdr) {
David Kershner40fc79f2016-12-22 11:09:06 -0500754 err = -ENOMEM;
David Kershner8e609b52016-11-03 11:44:26 -0400755 goto err_respond;
756 }
David Kershner8e609b52016-11-03 11:44:26 -0400757 memcpy(pmsg_hdr, &inmsg->hdr,
758 sizeof(struct controlvm_message_header));
759 dev_info->pending_msg_hdr = pmsg_hdr;
760 }
David Kershner8e609b52016-11-03 11:44:26 -0400761 if (state.alive == segment_state_running.alive &&
762 state.operating == segment_state_running.operating)
Sameer Wadgaonkarc0b44132017-05-19 16:17:41 -0400763 /* Response will be sent from visorchipset_device_resume */
764 err = visorchipset_device_resume(dev_info);
David Kershner8e609b52016-11-03 11:44:26 -0400765 /* ServerNotReady / ServerLost / SegmentStateStandby */
766 else if (state.alive == segment_state_standby.alive &&
767 state.operating == segment_state_standby.operating)
768 /*
769 * technically this is standby case where server is lost.
Sameer Wadgaonkarc0b44132017-05-19 16:17:41 -0400770 * Response will be sent from visorchipset_device_pause.
David Kershner8e609b52016-11-03 11:44:26 -0400771 */
Sameer Wadgaonkarc0b44132017-05-19 16:17:41 -0400772 err = visorchipset_device_pause(dev_info);
David Kershnerb4a8e6a2017-03-28 09:34:54 -0400773 if (err)
774 goto err_respond;
David Kershner40fc79f2016-12-22 11:09:06 -0500775 return 0;
David Kershner0825f192016-11-03 11:44:25 -0400776
777err_respond:
David Kershner03662df2017-04-18 16:55:20 -0400778 dev_err(&chipset_dev->acpi_device->dev, "failed: %d\n", err);
David Kershner8e609b52016-11-03 11:44:26 -0400779 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400780 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershner40fc79f2016-12-22 11:09:06 -0500781 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600782}
783
Charles Danielse80ffd42017-08-22 13:26:57 -0400784static int visorbus_device_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600785{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400786 struct controlvm_message_packet *cmd = &inmsg->cmd;
David Kershneref7b9dc2017-09-27 13:14:37 -0400787 struct controlvm_message_header *pmsg_hdr;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400788 u32 bus_no = cmd->destroy_device.bus_no;
789 u32 dev_no = cmd->destroy_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -0400790 struct visor_device *dev_info;
David Kershnere7954912016-12-22 11:09:07 -0500791 int err;
Ken Cox12e364b2014-03-04 07:58:07 -0600792
Don Zickusa298bc02015-06-04 09:22:42 -0400793 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
David Kershner9e9eec62016-11-03 11:44:27 -0400794 if (!dev_info) {
David Kershnere7954912016-12-22 11:09:07 -0500795 err = -ENODEV;
David Kershner9e9eec62016-11-03 11:44:27 -0400796 goto err_respond;
797 }
798 if (dev_info->state.created == 0) {
David Kershnere7954912016-12-22 11:09:07 -0500799 err = -EINVAL;
David Kershner9e9eec62016-11-03 11:44:27 -0400800 goto err_respond;
801 }
David Kershner9e9eec62016-11-03 11:44:27 -0400802 if (dev_info->pending_msg_hdr) {
803 /* only non-NULL if dev is still waiting on a response */
David Kershnere7954912016-12-22 11:09:07 -0500804 err = -EIO;
David Kershner9e9eec62016-11-03 11:44:27 -0400805 goto err_respond;
806 }
807 if (inmsg->hdr.flags.response_expected == 1) {
808 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
809 if (!pmsg_hdr) {
David Kershnere7954912016-12-22 11:09:07 -0500810 err = -ENOMEM;
David Kershner9e9eec62016-11-03 11:44:27 -0400811 goto err_respond;
812 }
813
814 memcpy(pmsg_hdr, &inmsg->hdr,
815 sizeof(struct controlvm_message_header));
816 dev_info->pending_msg_hdr = pmsg_hdr;
817 }
Zachary Dremann661a2152017-07-17 16:17:03 -0400818 kfree(dev_info->name);
Sameer Wadgaonkarb74856b2017-08-22 13:27:35 -0400819 remove_visor_device(dev_info);
David Kershnere7954912016-12-22 11:09:07 -0500820 return 0;
David Kershner9e9eec62016-11-03 11:44:27 -0400821
822err_respond:
823 if (inmsg->hdr.flags.response_expected == 1)
David Kershner4fb25392017-03-28 09:34:39 -0400824 controlvm_responder(inmsg->hdr.id, &inmsg->hdr, err);
David Kershnere7954912016-12-22 11:09:07 -0500825 return err;
Ken Cox12e364b2014-03-04 07:58:07 -0600826}
827
Ken Cox12e364b2014-03-04 07:58:07 -0600828/*
David Binder5d501ef2016-12-22 11:09:02 -0500829 * The general parahotplug flow works as follows. The visorchipset receives
830 * a DEVICE_CHANGESTATE message from Command specifying a physical device
831 * to enable or disable. The CONTROLVM message handler calls
832 * parahotplug_process_message, which then adds the message to a global list
833 * and kicks off a udev event which causes a user level script to enable or
834 * disable the specified device. The udev script then writes to
835 * /sys/devices/platform/visorchipset/parahotplug, which causes the
836 * parahotplug store functions to get called, at which point the
David Binder904ee622017-07-17 16:16:42 -0400837 * appropriate CONTROLVM message is retrieved from the list and responded to.
Ken Cox12e364b2014-03-04 07:58:07 -0600838 */
839
840#define PARAHOTPLUG_TIMEOUT_MS 2000
841
David Binder04dbfea2017-02-21 12:53:25 -0500842/*
David Binder5d501ef2016-12-22 11:09:02 -0500843 * parahotplug_next_id() - generate unique int to match an outstanding
844 * CONTROLVM message with a udev script /sys
845 * response
David Binderec17f452016-06-10 21:48:18 -0400846 *
847 * Return: a unique integer value
Ken Cox12e364b2014-03-04 07:58:07 -0600848 */
Charles Danielse80ffd42017-08-22 13:26:57 -0400849static int parahotplug_next_id(void)
Ken Cox12e364b2014-03-04 07:58:07 -0600850{
851 static atomic_t id = ATOMIC_INIT(0);
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400852
Ken Cox12e364b2014-03-04 07:58:07 -0600853 return atomic_inc_return(&id);
854}
855
David Binder04dbfea2017-02-21 12:53:25 -0500856/*
David Binderec17f452016-06-10 21:48:18 -0400857 * parahotplug_next_expiration() - returns the time (in jiffies) when a
858 * CONTROLVM message on the list should expire
859 * -- PARAHOTPLUG_TIMEOUT_MS in the future
860 *
861 * Return: expected expiration time (in jiffies)
Ken Cox12e364b2014-03-04 07:58:07 -0600862 */
Charles Danielse80ffd42017-08-22 13:26:57 -0400863static unsigned long parahotplug_next_expiration(void)
Ken Cox12e364b2014-03-04 07:58:07 -0600864{
Nicholas Mc Guire2cc1a1b2015-01-31 12:02:08 +0100865 return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
Ken Cox12e364b2014-03-04 07:58:07 -0600866}
867
David Binder04dbfea2017-02-21 12:53:25 -0500868/*
David Binderec17f452016-06-10 21:48:18 -0400869 * parahotplug_request_create() - create a parahotplug_request, which is
870 * basically a wrapper for a CONTROLVM_MESSAGE
871 * that we can stick on a list
872 * @msg: the message to insert in the request
873 *
874 * Return: the request containing the provided message
Ken Cox12e364b2014-03-04 07:58:07 -0600875 */
Charles Danielse80ffd42017-08-22 13:26:57 -0400876static struct parahotplug_request *parahotplug_request_create(
877 struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -0600878{
Quentin Lambertea0dcfc2015-02-10 15:12:07 +0100879 struct parahotplug_request *req;
880
David Kershner8c8c9752017-04-18 16:55:08 -0400881 req = kmalloc(sizeof(*req), GFP_KERNEL);
Benjamin Romer38f736e2015-03-16 13:58:13 -0400882 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -0600883 return NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600884 req->id = parahotplug_next_id();
885 req->expiration = parahotplug_next_expiration();
886 req->msg = *msg;
Ken Cox12e364b2014-03-04 07:58:07 -0600887 return req;
888}
889
David Binder04dbfea2017-02-21 12:53:25 -0500890/*
David Binderec17f452016-06-10 21:48:18 -0400891 * parahotplug_request_destroy() - free a parahotplug_request
892 * @req: the request to deallocate
Ken Cox12e364b2014-03-04 07:58:07 -0600893 */
Charles Danielse80ffd42017-08-22 13:26:57 -0400894static void parahotplug_request_destroy(struct parahotplug_request *req)
Ken Cox12e364b2014-03-04 07:58:07 -0600895{
896 kfree(req);
897}
898
David Kershner51319662016-09-19 17:09:37 -0400899static LIST_HEAD(parahotplug_request_list);
Sameer Wadgaonkarac0aba62017-06-30 15:43:08 -0400900/* lock for above */
901static DEFINE_SPINLOCK(parahotplug_request_list_lock);
David Kershner51319662016-09-19 17:09:37 -0400902
David Binder04dbfea2017-02-21 12:53:25 -0500903/*
David Binderec17f452016-06-10 21:48:18 -0400904 * parahotplug_request_complete() - mark request as complete
905 * @id: the id of the request
906 * @active: indicates whether the request is assigned to active partition
907 *
David Binder5d501ef2016-12-22 11:09:02 -0500908 * Called from the /sys handler, which means the user script has
David Binderec17f452016-06-10 21:48:18 -0400909 * finished the enable/disable. Find the matching identifier, and
Ken Cox12e364b2014-03-04 07:58:07 -0600910 * respond to the CONTROLVM message with success.
David Binderec17f452016-06-10 21:48:18 -0400911 *
912 * Return: 0 on success or -EINVAL on failure
Ken Cox12e364b2014-03-04 07:58:07 -0600913 */
Charles Danielse80ffd42017-08-22 13:26:57 -0400914static int parahotplug_request_complete(int id, u16 active)
Ken Cox12e364b2014-03-04 07:58:07 -0600915{
Jes Sorensene82ba622015-05-05 18:35:45 -0400916 struct list_head *pos;
917 struct list_head *tmp;
David Kershner040b78f2017-09-27 13:14:10 -0400918 struct parahotplug_request *req;
Ken Cox12e364b2014-03-04 07:58:07 -0600919
Benjamin Romerddf5de52015-03-16 13:58:41 -0400920 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600921 /* Look for a request matching "id". */
Benjamin Romerddf5de52015-03-16 13:58:41 -0400922 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
David Kershner040b78f2017-09-27 13:14:10 -0400923 req = list_entry(pos, struct parahotplug_request, list);
Ken Cox12e364b2014-03-04 07:58:07 -0600924 if (req->id == id) {
David Binderec17f452016-06-10 21:48:18 -0400925 /*
926 * Found a match. Remove it from the list and
Ken Cox12e364b2014-03-04 07:58:07 -0600927 * respond.
928 */
929 list_del(pos);
Benjamin Romerddf5de52015-03-16 13:58:41 -0400930 spin_unlock(&parahotplug_request_list_lock);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400931 req->msg.cmd.device_change_state.state.active = active;
Benjamin Romer98d7b592014-10-23 14:30:26 -0400932 if (req->msg.hdr.flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -0400933 controlvm_respond(
934 &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
935 &req->msg.cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -0600936 parahotplug_request_destroy(req);
937 return 0;
938 }
939 }
Benjamin Romerddf5de52015-03-16 13:58:41 -0400940 spin_unlock(&parahotplug_request_list_lock);
Erik Arfvidson119296e2016-05-13 23:17:20 -0400941 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -0600942}
943
David Binder04dbfea2017-02-21 12:53:25 -0500944/*
David Kershnerebeff052016-09-19 17:09:34 -0400945 * devicedisabled_store() - disables the hotplug device
946 * @dev: sysfs interface variable not utilized in this function
947 * @attr: sysfs interface variable not utilized in this function
948 * @buf: buffer containing the device id
949 * @count: the size of the buffer
950 *
951 * The parahotplug/devicedisabled interface gets called by our support script
952 * when an SR-IOV device has been shut down. The ID is passed to the script
953 * and then passed back when the device has been removed.
954 *
955 * Return: the size of the buffer for success or negative for error
956 */
957static ssize_t devicedisabled_store(struct device *dev,
958 struct device_attribute *attr,
959 const char *buf, size_t count)
960{
961 unsigned int id;
962 int err;
963
964 if (kstrtouint(buf, 10, &id))
965 return -EINVAL;
David Kershnerebeff052016-09-19 17:09:34 -0400966 err = parahotplug_request_complete(id, 0);
967 if (err < 0)
968 return err;
969 return count;
970}
971static DEVICE_ATTR_WO(devicedisabled);
972
David Binder04dbfea2017-02-21 12:53:25 -0500973/*
David Kershnerebeff052016-09-19 17:09:34 -0400974 * deviceenabled_store() - enables the hotplug device
975 * @dev: sysfs interface variable not utilized in this function
976 * @attr: sysfs interface variable not utilized in this function
977 * @buf: buffer containing the device id
978 * @count: the size of the buffer
979 *
980 * The parahotplug/deviceenabled interface gets called by our support script
981 * when an SR-IOV device has been recovered. The ID is passed to the script
982 * and then passed back when the device has been brought back up.
983 *
984 * Return: the size of the buffer for success or negative for error
985 */
986static ssize_t deviceenabled_store(struct device *dev,
987 struct device_attribute *attr,
988 const char *buf, size_t count)
989{
990 unsigned int id;
991
992 if (kstrtouint(buf, 10, &id))
993 return -EINVAL;
David Kershnerebeff052016-09-19 17:09:34 -0400994 parahotplug_request_complete(id, 1);
995 return count;
996}
997static DEVICE_ATTR_WO(deviceenabled);
998
999static struct attribute *visorchipset_install_attrs[] = {
1000 &dev_attr_toolaction.attr,
1001 &dev_attr_boottotool.attr,
1002 &dev_attr_error.attr,
1003 &dev_attr_textid.attr,
1004 &dev_attr_remaining_steps.attr,
1005 NULL
1006};
1007
Mihaela Murarua2d1e422016-10-16 01:41:14 +03001008static const struct attribute_group visorchipset_install_group = {
David Kershnerebeff052016-09-19 17:09:34 -04001009 .name = "install",
1010 .attrs = visorchipset_install_attrs
1011};
1012
1013static struct attribute *visorchipset_parahotplug_attrs[] = {
1014 &dev_attr_devicedisabled.attr,
1015 &dev_attr_deviceenabled.attr,
1016 NULL
1017};
1018
Arvind Yadav17222702017-07-18 13:40:54 +05301019static const struct attribute_group visorchipset_parahotplug_group = {
David Kershnerebeff052016-09-19 17:09:34 -04001020 .name = "parahotplug",
1021 .attrs = visorchipset_parahotplug_attrs
1022};
1023
1024static const struct attribute_group *visorchipset_dev_groups[] = {
1025 &visorchipset_install_group,
1026 &visorchipset_parahotplug_group,
1027 NULL
1028};
1029
David Binder04dbfea2017-02-21 12:53:25 -05001030/*
David Kershnerebeff052016-09-19 17:09:34 -04001031 * parahotplug_request_kickoff() - initiate parahotplug request
1032 * @req: the request to initiate
1033 *
1034 * Cause uevent to run the user level script to do the disable/enable specified
1035 * in the parahotplug_request.
1036 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001037static int parahotplug_request_kickoff(struct parahotplug_request *req)
David Kershnerebeff052016-09-19 17:09:34 -04001038{
1039 struct controlvm_message_packet *cmd = &req->msg.cmd;
1040 char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
David Kershnerda56cb02017-09-27 13:14:39 -04001041 env_func[40];
1042 char *envp[] = { env_cmd, env_id, env_state, env_bus, env_dev,
1043 env_func, NULL
David Kershnerebeff052016-09-19 17:09:34 -04001044 };
1045
Sameer Wadgaonkarc5a28902017-05-19 16:17:48 -04001046 sprintf(env_cmd, "VISOR_PARAHOTPLUG=1");
1047 sprintf(env_id, "VISOR_PARAHOTPLUG_ID=%d", req->id);
1048 sprintf(env_state, "VISOR_PARAHOTPLUG_STATE=%d",
David Kershnerebeff052016-09-19 17:09:34 -04001049 cmd->device_change_state.state.active);
Sameer Wadgaonkarc5a28902017-05-19 16:17:48 -04001050 sprintf(env_bus, "VISOR_PARAHOTPLUG_BUS=%d",
David Kershnerebeff052016-09-19 17:09:34 -04001051 cmd->device_change_state.bus_no);
Sameer Wadgaonkarc5a28902017-05-19 16:17:48 -04001052 sprintf(env_dev, "VISOR_PARAHOTPLUG_DEVICE=%d",
David Kershnerebeff052016-09-19 17:09:34 -04001053 cmd->device_change_state.dev_no >> 3);
Sameer Wadgaonkarc5a28902017-05-19 16:17:48 -04001054 sprintf(env_func, "VISOR_PARAHOTPLUG_FUNCTION=%d",
David Kershnerebeff052016-09-19 17:09:34 -04001055 cmd->device_change_state.dev_no & 0x7);
David Kershnerae0fa822017-03-28 09:34:21 -04001056 return kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
1057 KOBJ_CHANGE, envp);
David Kershnerebeff052016-09-19 17:09:34 -04001058}
1059
David Binder04dbfea2017-02-21 12:53:25 -05001060/*
David Binderec17f452016-06-10 21:48:18 -04001061 * parahotplug_process_message() - enables or disables a PCI device by kicking
1062 * off a udev script
1063 * @inmsg: the message indicating whether to enable or disable
Ken Cox12e364b2014-03-04 07:58:07 -06001064 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001065static int parahotplug_process_message(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001066{
1067 struct parahotplug_request *req;
David Kershnerae0fa822017-03-28 09:34:21 -04001068 int err;
Ken Cox12e364b2014-03-04 07:58:07 -06001069
1070 req = parahotplug_request_create(inmsg);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001071 if (!req)
David Kershner114d5dc2017-03-28 09:34:18 -04001072 return -ENOMEM;
David Kershnerd02bde92017-04-18 16:55:05 -04001073 /*
1074 * For enable messages, just respond with success right away, we don't
1075 * need to wait to see if the enable was successful.
1076 */
Benjamin Romer2ea51172014-10-23 14:30:25 -04001077 if (inmsg->cmd.device_change_state.state.active) {
David Kershnerae0fa822017-03-28 09:34:21 -04001078 err = parahotplug_request_kickoff(req);
1079 if (err)
1080 goto err_respond;
David Kershner4c0e65f2017-04-18 16:55:01 -04001081 controlvm_respond(&inmsg->hdr, CONTROLVM_RESP_SUCCESS,
1082 &inmsg->cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001083 parahotplug_request_destroy(req);
David Kershnerae0fa822017-03-28 09:34:21 -04001084 return 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001085 }
David Kershnerae0fa822017-03-28 09:34:21 -04001086 /*
David Kershner6577cbf2017-08-30 13:36:29 -04001087 * For disable messages, add the request to the request list before
1088 * kicking off the udev script. It won't get responded to until the
1089 * script has indicated it's done.
David Kershnerae0fa822017-03-28 09:34:21 -04001090 */
1091 spin_lock(&parahotplug_request_list_lock);
1092 list_add_tail(&req->list, &parahotplug_request_list);
1093 spin_unlock(&parahotplug_request_list_lock);
David Kershnerae0fa822017-03-28 09:34:21 -04001094 err = parahotplug_request_kickoff(req);
1095 if (err)
1096 goto err_respond;
David Kershner114d5dc2017-03-28 09:34:18 -04001097 return 0;
David Kershnerae0fa822017-03-28 09:34:21 -04001098
1099err_respond:
David Kershner4c0e65f2017-04-18 16:55:01 -04001100 controlvm_respond(&inmsg->hdr, err,
1101 &inmsg->cmd.device_change_state.state);
David Kershnerae0fa822017-03-28 09:34:21 -04001102 return err;
Ken Cox12e364b2014-03-04 07:58:07 -06001103}
1104
David Binder7289a8d2017-02-01 17:38:56 -05001105/*
1106 * chipset_ready_uevent() - sends chipset_ready action
David Kershnerebeff052016-09-19 17:09:34 -04001107 *
1108 * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1109 *
David Binder7289a8d2017-02-01 17:38:56 -05001110 * Return: 0 on success, negative on failure
David Kershnerebeff052016-09-19 17:09:34 -04001111 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001112static int chipset_ready_uevent(struct controlvm_message_header *msg_hdr)
David Kershnerebeff052016-09-19 17:09:34 -04001113{
David Kershnerdeeeca62017-03-28 09:34:22 -04001114 int res;
1115
David Kershner040b78f2017-09-27 13:14:10 -04001116 res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj, KOBJ_ONLINE);
David Binder7289a8d2017-02-01 17:38:56 -05001117 if (msg_hdr->flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -04001118 controlvm_respond(msg_hdr, res, NULL);
David Kershnerdeeeca62017-03-28 09:34:22 -04001119 return res;
David Kershnerebeff052016-09-19 17:09:34 -04001120}
1121
David Binder7289a8d2017-02-01 17:38:56 -05001122/*
1123 * chipset_selftest_uevent() - sends chipset_selftest action
1124 *
1125 * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1126 *
1127 * Return: 0 on success, negative on failure
1128 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001129static int chipset_selftest_uevent(struct controlvm_message_header *msg_hdr)
David Kershnerebeff052016-09-19 17:09:34 -04001130{
1131 char env_selftest[20];
1132 char *envp[] = { env_selftest, NULL };
David Kershnerdeeeca62017-03-28 09:34:22 -04001133 int res;
David Kershnerebeff052016-09-19 17:09:34 -04001134
1135 sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
David Kershnerdeeeca62017-03-28 09:34:22 -04001136 res = kobject_uevent_env(&chipset_dev->acpi_device->dev.kobj,
1137 KOBJ_CHANGE, envp);
David Binder7289a8d2017-02-01 17:38:56 -05001138 if (msg_hdr->flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -04001139 controlvm_respond(msg_hdr, res, NULL);
David Kershnerdeeeca62017-03-28 09:34:22 -04001140 return res;
David Kershnerebeff052016-09-19 17:09:34 -04001141}
1142
David Binder7289a8d2017-02-01 17:38:56 -05001143/*
1144 * chipset_notready_uevent() - sends chipset_notready action
David Kershnerebeff052016-09-19 17:09:34 -04001145 *
1146 * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
1147 *
David Binder7289a8d2017-02-01 17:38:56 -05001148 * Return: 0 on success, negative on failure
David Kershnerebeff052016-09-19 17:09:34 -04001149 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001150static int chipset_notready_uevent(struct controlvm_message_header *msg_hdr)
David Kershnerebeff052016-09-19 17:09:34 -04001151{
David Binder904ee622017-07-17 16:16:42 -04001152 int res = kobject_uevent(&chipset_dev->acpi_device->dev.kobj,
David Kershner34fbf6a2017-09-27 13:14:11 -04001153 KOBJ_OFFLINE);
David Binder904ee622017-07-17 16:16:42 -04001154
David Kershnerebeff052016-09-19 17:09:34 -04001155 if (msg_hdr->flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -04001156 controlvm_respond(msg_hdr, res, NULL);
David Kershnerdeeeca62017-03-28 09:34:22 -04001157 return res;
David Kershnerebeff052016-09-19 17:09:34 -04001158}
1159
David Kershner88845f42017-03-28 09:35:00 -04001160static int unisys_vmcall(unsigned long tuple, unsigned long param)
1161{
1162 int result = 0;
1163 unsigned int cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
1164 unsigned long reg_ebx;
1165 unsigned long reg_ecx;
1166
1167 reg_ebx = param & 0xFFFFFFFF;
1168 reg_ecx = param >> 32;
David Kershner88845f42017-03-28 09:35:00 -04001169 cpuid(0x00000001, &cpuid_eax, &cpuid_ebx, &cpuid_ecx, &cpuid_edx);
1170 if (!(cpuid_ecx & 0x80000000))
1171 return -EPERM;
David Kershner88845f42017-03-28 09:35:00 -04001172 __asm__ __volatile__(".byte 0x00f, 0x001, 0x0c1" : "=a"(result) :
David Kershner34fbf6a2017-09-27 13:14:11 -04001173 "a"(tuple), "b"(reg_ebx), "c"(reg_ecx));
David Kershnerbd801a02017-03-28 09:35:01 -04001174 if (result)
1175 goto error;
David Kershnerbd801a02017-03-28 09:35:01 -04001176 return 0;
David Kershner9116ae72017-09-27 13:14:26 -04001177
Sameer Wadgaonkarac0aba62017-06-30 15:43:08 -04001178/* Need to convert from VMCALL error codes to Linux */
1179error:
David Kershnerbd801a02017-03-28 09:35:01 -04001180 switch (result) {
1181 case VMCALL_RESULT_INVALID_PARAM:
1182 return -EINVAL;
1183 case VMCALL_RESULT_DATA_UNAVAILABLE:
1184 return -ENODEV;
1185 default:
1186 return -EFAULT;
1187 }
David Kershner88845f42017-03-28 09:35:00 -04001188}
Zohaib Javedab610972017-08-22 13:26:53 -04001189
David Kershnerf1f537c2017-08-30 13:36:19 -04001190static int controlvm_channel_create(struct visorchipset_device *dev)
David Kershner5f3a7e32015-05-13 13:22:10 -04001191{
David Kershnerf1f537c2017-08-30 13:36:19 -04001192 struct visorchannel *chan;
1193 u64 addr;
David Kershner800da5f2017-08-30 13:36:13 -04001194 int err;
David Kershner5f3a7e32015-05-13 13:22:10 -04001195
David Kershnerf1f537c2017-08-30 13:36:19 -04001196 err = unisys_vmcall(VMCALL_CONTROLVM_ADDR,
1197 virt_to_phys(&dev->controlvm_params));
David Kershner800da5f2017-08-30 13:36:13 -04001198 if (err)
1199 return err;
David Kershnerf1f537c2017-08-30 13:36:19 -04001200 addr = dev->controlvm_params.address;
Sameer Wadgaonkar90476672017-09-27 13:14:44 -04001201 chan = visorchannel_create(addr, GFP_KERNEL,
1202 &visor_controlvm_channel_guid, true);
David Kershnerf1f537c2017-08-30 13:36:19 -04001203 if (!chan)
1204 return -ENOMEM;
1205 dev->controlvm_channel = chan;
David Kershnerbd801a02017-03-28 09:35:01 -04001206 return 0;
David Kershner5f3a7e32015-05-13 13:22:10 -04001207}
1208
Charles Danielse80ffd42017-08-22 13:26:57 -04001209static void setup_crash_devices_work_queue(struct work_struct *work)
Ken Cox12e364b2014-03-04 07:58:07 -06001210{
Benjamin Romere6bdb902015-03-16 13:58:33 -04001211 struct controlvm_message local_crash_bus_msg;
1212 struct controlvm_message local_crash_dev_msg;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001213 struct controlvm_message msg;
Benjamin Romere6bdb902015-03-16 13:58:33 -04001214 u32 local_crash_msg_offset;
1215 u16 local_crash_msg_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001216
Ken Cox12e364b2014-03-04 07:58:07 -06001217 /* send init chipset msg */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001218 msg.hdr.id = CONTROLVM_CHIPSET_INIT;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001219 msg.cmd.init_chipset.bus_count = 23;
1220 msg.cmd.init_chipset.switch_count = 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001221 chipset_init(&msg);
Ken Cox12e364b2014-03-04 07:58:07 -06001222 /* get saved message count */
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001223 if (visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -04001224 offsetof(struct visor_controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001225 saved_crash_message_count),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001226 &local_crash_msg_count, sizeof(u16)) < 0) {
David Kershner0f7453a2017-04-18 16:55:22 -04001227 dev_err(&chipset_dev->acpi_device->dev,
1228 "failed to read channel\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001229 return;
1230 }
Benjamin Romere6bdb902015-03-16 13:58:33 -04001231 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
David Kershner040b78f2017-09-27 13:14:10 -04001232 dev_err(&chipset_dev->acpi_device->dev, "invalid count\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001233 return;
1234 }
Ken Cox12e364b2014-03-04 07:58:07 -06001235 /* get saved crash message offset */
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001236 if (visorchannel_read(chipset_dev->controlvm_channel,
Sameer Wadgaonkar545f0912017-05-19 16:17:49 -04001237 offsetof(struct visor_controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001238 saved_crash_message_offset),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001239 &local_crash_msg_offset, sizeof(u32)) < 0) {
David Kershner0f7453a2017-04-18 16:55:22 -04001240 dev_err(&chipset_dev->acpi_device->dev,
1241 "failed to read channel\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001242 return;
1243 }
Ken Cox12e364b2014-03-04 07:58:07 -06001244 /* read create device message for storage bus offset */
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001245 if (visorchannel_read(chipset_dev->controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001246 local_crash_msg_offset,
1247 &local_crash_bus_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001248 sizeof(struct controlvm_message)) < 0) {
David Kershner0f7453a2017-04-18 16:55:22 -04001249 dev_err(&chipset_dev->acpi_device->dev,
1250 "failed to read channel\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001251 return;
1252 }
Ken Cox12e364b2014-03-04 07:58:07 -06001253 /* read create device message for storage device */
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001254 if (visorchannel_read(chipset_dev->controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001255 local_crash_msg_offset +
Benjamin Romer3ab47702014-10-23 14:30:31 -04001256 sizeof(struct controlvm_message),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001257 &local_crash_dev_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001258 sizeof(struct controlvm_message)) < 0) {
David Kershner0f7453a2017-04-18 16:55:22 -04001259 dev_err(&chipset_dev->acpi_device->dev,
1260 "failed to read channel\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001261 return;
1262 }
Ken Cox12e364b2014-03-04 07:58:07 -06001263 /* reuse IOVM create bus message */
David Kershnerd9b89ef2017-04-18 16:55:21 -04001264 if (!local_crash_bus_msg.cmd.create_bus.channel_addr) {
David Kershner0f7453a2017-04-18 16:55:22 -04001265 dev_err(&chipset_dev->acpi_device->dev,
1266 "no valid create_bus message\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001267 return;
1268 }
Sameer Wadgaonkarec17cb82017-05-19 16:17:36 -04001269 visorbus_create(&local_crash_bus_msg);
Ken Cox12e364b2014-03-04 07:58:07 -06001270 /* reuse create device message for storage device */
David Kershnerd9b89ef2017-04-18 16:55:21 -04001271 if (!local_crash_dev_msg.cmd.create_device.channel_addr) {
David Kershner0f7453a2017-04-18 16:55:22 -04001272 dev_err(&chipset_dev->acpi_device->dev,
1273 "no valid create_device message\n");
Ken Cox12e364b2014-03-04 07:58:07 -06001274 return;
1275 }
Sameer Wadgaonkar8b0a6cf2017-05-19 16:17:43 -04001276 visorbus_device_create(&local_crash_dev_msg);
Ken Cox12e364b2014-03-04 07:58:07 -06001277}
1278
Sameer Wadgaonkar76956aa2017-08-22 13:27:03 -04001279void visorbus_response(struct visor_device *bus_info, int response,
1280 int controlvm_id)
Ken Cox12e364b2014-03-04 07:58:07 -06001281{
David Kershnerfd9e4502017-09-27 13:14:16 -04001282 if (!bus_info->pending_msg_hdr)
1283 return;
Don Zickus0274b5a2015-06-01 13:00:27 -04001284
David Kershnerfd9e4502017-09-27 13:14:16 -04001285 controlvm_responder(controlvm_id, bus_info->pending_msg_hdr, response);
Don Zickus0274b5a2015-06-01 13:00:27 -04001286 kfree(bus_info->pending_msg_hdr);
1287 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001288}
1289
Sameer Wadgaonkar722e73d2017-08-22 13:27:04 -04001290void visorbus_device_changestate_response(struct visor_device *dev_info,
1291 int response,
1292 struct visor_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -06001293{
David Kershnerfd9e4502017-09-27 13:14:16 -04001294 if (!dev_info->pending_msg_hdr)
1295 return;
1296
David Kershner040b78f2017-09-27 13:14:10 -04001297 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE, dev_info,
1298 response, state);
Don Zickus0274b5a2015-06-01 13:00:27 -04001299 kfree(dev_info->pending_msg_hdr);
1300 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001301}
1302
David Kershner39b486d2017-08-30 13:36:27 -04001303static void parser_done(struct parser_context *ctx)
1304{
1305 chipset_dev->controlvm_payload_bytes_buffered -= ctx->param_bytes;
1306 kfree(ctx);
1307}
1308
David Kershner45311432017-08-30 13:36:28 -04001309static struct parser_context *parser_init_stream(u64 addr, u32 bytes,
1310 bool *retry)
David Kershner612b81c2016-09-19 17:09:22 -04001311{
Tim Sella5eb2182017-11-17 12:27:38 -05001312 unsigned long allocbytes;
David Kershner612b81c2016-09-19 17:09:22 -04001313 struct parser_context *ctx;
Erik Arfvidsona35e3262017-07-17 16:17:09 -04001314 void *mapping;
David Kershner612b81c2016-09-19 17:09:22 -04001315
David Binder3e4273d2016-12-22 11:09:00 -05001316 *retry = false;
David Kershner26a42c22017-08-30 13:36:24 -04001317 /* alloc an extra byte to ensure payload is \0 terminated */
Tim Sella5eb2182017-11-17 12:27:38 -05001318 allocbytes = (unsigned long)bytes + 1 + (sizeof(struct parser_context) -
David Kershner26a42c22017-08-30 13:36:24 -04001319 sizeof(struct visor_controlvm_parameters_header));
David Kershner040b78f2017-09-27 13:14:10 -04001320 if ((chipset_dev->controlvm_payload_bytes_buffered + bytes) >
1321 MAX_CONTROLVM_PAYLOAD_BYTES) {
David Binder3e4273d2016-12-22 11:09:00 -05001322 *retry = true;
David Kershner612b81c2016-09-19 17:09:22 -04001323 return NULL;
1324 }
David Kershner8c8c9752017-04-18 16:55:08 -04001325 ctx = kzalloc(allocbytes, GFP_KERNEL);
David Kershner612b81c2016-09-19 17:09:22 -04001326 if (!ctx) {
David Binder3e4273d2016-12-22 11:09:00 -05001327 *retry = true;
David Kershner612b81c2016-09-19 17:09:22 -04001328 return NULL;
1329 }
David Kershner612b81c2016-09-19 17:09:22 -04001330 ctx->allocbytes = allocbytes;
1331 ctx->param_bytes = bytes;
Erik Arfvidsona35e3262017-07-17 16:17:09 -04001332 mapping = memremap(addr, bytes, MEMREMAP_WB);
1333 if (!mapping)
1334 goto err_finish_ctx;
David Kershner26a42c22017-08-30 13:36:24 -04001335 memcpy(&ctx->data, mapping, bytes);
Erik Arfvidsona35e3262017-07-17 16:17:09 -04001336 memunmap(mapping);
David Kershner612b81c2016-09-19 17:09:22 -04001337 ctx->byte_stream = true;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001338 chipset_dev->controlvm_payload_bytes_buffered += ctx->param_bytes;
David Kershner612b81c2016-09-19 17:09:22 -04001339 return ctx;
1340
1341err_finish_ctx:
Sameer Wadgaonkar90544cb2017-08-30 13:36:09 -04001342 kfree(ctx);
David Kershner612b81c2016-09-19 17:09:22 -04001343 return NULL;
1344}
1345
David Binder04dbfea2017-02-21 12:53:25 -05001346/*
David Kershner511474a2016-09-19 17:09:21 -04001347 * handle_command() - process a controlvm message
1348 * @inmsg: the message to process
1349 * @channel_addr: address of the controlvm channel
1350 *
1351 * Return:
David Kershner25a51282017-03-28 09:34:19 -04001352 * 0 - Successfully processed the message
1353 * -EAGAIN - ControlVM message was not processed and should be retried
1354 * reading the next controlvm message; a scenario where this can
1355 * occur is when we need to throttle the allocation of memory in
1356 * which to copy out controlvm payload data.
1357 * < 0 - error: ControlVM message was processed but an error occurred.
David Kershner511474a2016-09-19 17:09:21 -04001358 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001359static int handle_command(struct controlvm_message inmsg, u64 channel_addr)
David Kershner511474a2016-09-19 17:09:21 -04001360{
1361 struct controlvm_message_packet *cmd = &inmsg.cmd;
1362 u64 parm_addr;
1363 u32 parm_bytes;
1364 struct parser_context *parser_ctx = NULL;
David Kershner511474a2016-09-19 17:09:21 -04001365 struct controlvm_message ackmsg;
David Kershner25a51282017-03-28 09:34:19 -04001366 int err = 0;
David Kershner511474a2016-09-19 17:09:21 -04001367
1368 /* create parsing context if necessary */
David Kershner511474a2016-09-19 17:09:21 -04001369 parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
1370 parm_bytes = inmsg.hdr.payload_bytes;
David Kershner511474a2016-09-19 17:09:21 -04001371 /*
1372 * Parameter and channel addresses within test messages actually lie
1373 * within our OS-controlled memory. We need to know that, because it
1374 * makes a difference in how we compute the virtual address.
1375 */
David Kershner4d77e602017-08-30 13:36:22 -04001376 if (parm_bytes) {
David Kershneref7b9dc2017-09-27 13:14:37 -04001377 bool retry;
David Kershner511474a2016-09-19 17:09:21 -04001378
David Kershner45311432017-08-30 13:36:28 -04001379 parser_ctx = parser_init_stream(parm_addr, parm_bytes, &retry);
David Kershner511474a2016-09-19 17:09:21 -04001380 if (!parser_ctx && retry)
David Kershner25a51282017-03-28 09:34:19 -04001381 return -EAGAIN;
David Kershner511474a2016-09-19 17:09:21 -04001382 }
Erik Arfvidsona35e3262017-07-17 16:17:09 -04001383 controlvm_init_response(&ackmsg, &inmsg.hdr, CONTROLVM_RESP_SUCCESS);
1384 err = visorchannel_signalinsert(chipset_dev->controlvm_channel,
1385 CONTROLVM_QUEUE_ACK, &ackmsg);
1386 if (err)
1387 return err;
David Kershner511474a2016-09-19 17:09:21 -04001388 switch (inmsg.hdr.id) {
1389 case CONTROLVM_CHIPSET_INIT:
David Kershner25a51282017-03-28 09:34:19 -04001390 err = chipset_init(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001391 break;
1392 case CONTROLVM_BUS_CREATE:
Sameer Wadgaonkarec17cb82017-05-19 16:17:36 -04001393 err = visorbus_create(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001394 break;
1395 case CONTROLVM_BUS_DESTROY:
Sameer Wadgaonkarec17cb82017-05-19 16:17:36 -04001396 err = visorbus_destroy(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001397 break;
1398 case CONTROLVM_BUS_CONFIGURE:
Sameer Wadgaonkarec17cb82017-05-19 16:17:36 -04001399 err = visorbus_configure(&inmsg, parser_ctx);
David Kershner511474a2016-09-19 17:09:21 -04001400 break;
1401 case CONTROLVM_DEVICE_CREATE:
Sameer Wadgaonkar8b0a6cf2017-05-19 16:17:43 -04001402 err = visorbus_device_create(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001403 break;
1404 case CONTROLVM_DEVICE_CHANGESTATE:
1405 if (cmd->device_change_state.flags.phys_device) {
David Kershner25a51282017-03-28 09:34:19 -04001406 err = parahotplug_process_message(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001407 } else {
1408 /*
David Kershner6577cbf2017-08-30 13:36:29 -04001409 * save the hdr and cmd structures for later use when
1410 * sending back the response to Command
David Kershner511474a2016-09-19 17:09:21 -04001411 */
Sameer Wadgaonkar8b0a6cf2017-05-19 16:17:43 -04001412 err = visorbus_device_changestate(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001413 break;
1414 }
1415 break;
1416 case CONTROLVM_DEVICE_DESTROY:
Sameer Wadgaonkar8b0a6cf2017-05-19 16:17:43 -04001417 err = visorbus_device_destroy(&inmsg);
David Kershner511474a2016-09-19 17:09:21 -04001418 break;
1419 case CONTROLVM_DEVICE_CONFIGURE:
David Kershner25a51282017-03-28 09:34:19 -04001420 /* no op just send a respond that we passed */
David Kershner511474a2016-09-19 17:09:21 -04001421 if (inmsg.hdr.flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -04001422 controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS,
1423 NULL);
David Kershner511474a2016-09-19 17:09:21 -04001424 break;
1425 case CONTROLVM_CHIPSET_READY:
David Kershner25a51282017-03-28 09:34:19 -04001426 err = chipset_ready_uevent(&inmsg.hdr);
David Kershner511474a2016-09-19 17:09:21 -04001427 break;
1428 case CONTROLVM_CHIPSET_SELFTEST:
David Kershner25a51282017-03-28 09:34:19 -04001429 err = chipset_selftest_uevent(&inmsg.hdr);
David Kershner511474a2016-09-19 17:09:21 -04001430 break;
1431 case CONTROLVM_CHIPSET_STOP:
David Kershner25a51282017-03-28 09:34:19 -04001432 err = chipset_notready_uevent(&inmsg.hdr);
David Kershner511474a2016-09-19 17:09:21 -04001433 break;
1434 default:
David Kershner25a51282017-03-28 09:34:19 -04001435 err = -ENOMSG;
David Kershner511474a2016-09-19 17:09:21 -04001436 if (inmsg.hdr.flags.response_expected)
David Kershner25a51282017-03-28 09:34:19 -04001437 controlvm_respond(&inmsg.hdr,
David Kershner4c0e65f2017-04-18 16:55:01 -04001438 -CONTROLVM_RESP_ID_UNKNOWN, NULL);
David Kershner511474a2016-09-19 17:09:21 -04001439 break;
1440 }
David Kershner511474a2016-09-19 17:09:21 -04001441 if (parser_ctx) {
1442 parser_done(parser_ctx);
1443 parser_ctx = NULL;
1444 }
David Kershner25a51282017-03-28 09:34:19 -04001445 return err;
David Kershner511474a2016-09-19 17:09:21 -04001446}
1447
David Binder04dbfea2017-02-21 12:53:25 -05001448/*
David Kershner8a285322016-09-19 17:09:23 -04001449 * read_controlvm_event() - retreives the next message from the
1450 * CONTROLVM_QUEUE_EVENT queue in the controlvm
1451 * channel
1452 * @msg: pointer to the retrieved message
1453 *
David Kershner25a51282017-03-28 09:34:19 -04001454 * Return: 0 if valid message was retrieved or -error
David Kershner8a285322016-09-19 17:09:23 -04001455 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001456static int read_controlvm_event(struct controlvm_message *msg)
David Kershner8a285322016-09-19 17:09:23 -04001457{
David Binder904ee622017-07-17 16:16:42 -04001458 int err = visorchannel_signalremove(chipset_dev->controlvm_channel,
David Kershnerda56cb02017-09-27 13:14:39 -04001459 CONTROLVM_QUEUE_EVENT, msg);
David Kershner9116ae72017-09-27 13:14:26 -04001460
David Kershner25a51282017-03-28 09:34:19 -04001461 if (err)
1462 return err;
David Kershner25a51282017-03-28 09:34:19 -04001463 /* got a message */
1464 if (msg->hdr.flags.test_message == 1)
1465 return -EINVAL;
David Kershner25a51282017-03-28 09:34:19 -04001466 return 0;
David Kershner8a285322016-09-19 17:09:23 -04001467}
1468
David Binder04dbfea2017-02-21 12:53:25 -05001469/*
David Kershnera9c73932016-09-19 17:09:24 -04001470 * parahotplug_process_list() - remove any request from the list that's been on
1471 * there too long and respond with an error
1472 */
Charles Danielse80ffd42017-08-22 13:26:57 -04001473static void parahotplug_process_list(void)
David Kershnera9c73932016-09-19 17:09:24 -04001474{
1475 struct list_head *pos;
1476 struct list_head *tmp;
1477
1478 spin_lock(&parahotplug_request_list_lock);
David Kershnera9c73932016-09-19 17:09:24 -04001479 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
1480 struct parahotplug_request *req =
1481 list_entry(pos, struct parahotplug_request, list);
1482
1483 if (!time_after_eq(jiffies, req->expiration))
1484 continue;
David Kershnera9c73932016-09-19 17:09:24 -04001485 list_del(pos);
1486 if (req->msg.hdr.flags.response_expected)
David Kershner4c0e65f2017-04-18 16:55:01 -04001487 controlvm_respond(
David Kershnera9c73932016-09-19 17:09:24 -04001488 &req->msg.hdr,
Sameer Wadgaonkar98f9ed92016-12-22 11:08:58 -05001489 CONTROLVM_RESP_DEVICE_UDEV_TIMEOUT,
David Kershner4c0e65f2017-04-18 16:55:01 -04001490 &req->msg.cmd.device_change_state.state);
David Kershnera9c73932016-09-19 17:09:24 -04001491 parahotplug_request_destroy(req);
1492 }
David Kershnera9c73932016-09-19 17:09:24 -04001493 spin_unlock(&parahotplug_request_list_lock);
1494}
1495
Charles Danielse80ffd42017-08-22 13:26:57 -04001496static void controlvm_periodic_work(struct work_struct *work)
David Kershner3d8394c2016-09-19 17:09:20 -04001497{
1498 struct controlvm_message inmsg;
David Kershner04dbc092017-04-18 16:55:06 -04001499 int count = 0;
David Kershnerfbc10232017-03-28 09:34:20 -04001500 int err;
David Kershner3d8394c2016-09-19 17:09:20 -04001501
David Kershnerfbc10232017-03-28 09:34:20 -04001502 /* Drain the RESPONSE queue make it empty */
1503 do {
1504 err = visorchannel_signalremove(chipset_dev->controlvm_channel,
1505 CONTROLVM_QUEUE_RESPONSE,
1506 &inmsg);
David Kershner04dbc092017-04-18 16:55:06 -04001507 } while ((!err) && (++count < CONTROLVM_MESSAGE_MAX));
David Kershnerfbc10232017-03-28 09:34:20 -04001508 if (err != -EAGAIN)
1509 goto schedule_out;
David Kershnerfbc10232017-03-28 09:34:20 -04001510 if (chipset_dev->controlvm_pending_msg_valid) {
1511 /*
David Kershner6577cbf2017-08-30 13:36:29 -04001512 * we throttled processing of a prior msg, so try to process
1513 * it again rather than reading a new one
David Kershnerfbc10232017-03-28 09:34:20 -04001514 */
1515 inmsg = chipset_dev->controlvm_pending_msg;
1516 chipset_dev->controlvm_pending_msg_valid = false;
1517 err = 0;
1518 } else {
1519 err = read_controlvm_event(&inmsg);
David Kershner3d8394c2016-09-19 17:09:20 -04001520 }
David Kershnerfbc10232017-03-28 09:34:20 -04001521 while (!err) {
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001522 chipset_dev->most_recent_message_jiffies = jiffies;
David Kershnerfbc10232017-03-28 09:34:20 -04001523 err = handle_command(inmsg,
1524 visorchannel_get_physaddr
1525 (chipset_dev->controlvm_channel));
1526 if (err == -EAGAIN) {
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001527 chipset_dev->controlvm_pending_msg = inmsg;
1528 chipset_dev->controlvm_pending_msg_valid = true;
David Kershnerfbc10232017-03-28 09:34:20 -04001529 break;
David Kershner3d8394c2016-09-19 17:09:20 -04001530 }
David Kershnerfbc10232017-03-28 09:34:20 -04001531
1532 err = read_controlvm_event(&inmsg);
David Kershner3d8394c2016-09-19 17:09:20 -04001533 }
David Kershner3d8394c2016-09-19 17:09:20 -04001534 /* parahotplug_worker */
1535 parahotplug_process_list();
1536
Sameer Wadgaonkard36c4852017-05-19 16:17:58 -04001537/*
1538 * The controlvm messages are sent in a bulk. If we start receiving messages, we
1539 * want the polling to be fast. If we do not receive any message for
1540 * MIN_IDLE_SECONDS, we can slow down the polling.
1541 */
David Kershnerfbc10232017-03-28 09:34:20 -04001542schedule_out:
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001543 if (time_after(jiffies, chipset_dev->most_recent_message_jiffies +
1544 (HZ * MIN_IDLE_SECONDS))) {
David Kershner3d8394c2016-09-19 17:09:20 -04001545 /*
David Kershner6577cbf2017-08-30 13:36:29 -04001546 * it's been longer than MIN_IDLE_SECONDS since we processed
1547 * our last controlvm message; slow down the polling
David Kershner3d8394c2016-09-19 17:09:20 -04001548 */
David Kershner3fbee192017-09-27 13:14:38 -04001549 if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_SLOW)
1550 chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_SLOW;
David Kershner3d8394c2016-09-19 17:09:20 -04001551 } else {
David Kershner3fbee192017-09-27 13:14:38 -04001552 if (chipset_dev->poll_jiffies != POLLJIFFIES_CONTROLVM_FAST)
1553 chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
David Kershner3d8394c2016-09-19 17:09:20 -04001554 }
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001555 schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
1556 chipset_dev->poll_jiffies);
David Kershner3d8394c2016-09-19 17:09:20 -04001557}
1558
Charles Danielse80ffd42017-08-22 13:26:57 -04001559static int visorchipset_init(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06001560{
David Kershner1366a3d2016-04-04 23:31:37 -04001561 int err = -ENODEV;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001562 struct visorchannel *controlvm_channel;
Jes Sorensend3368a52015-05-13 13:21:57 -04001563
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001564 chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL);
1565 if (!chipset_dev)
David Kershner1366a3d2016-04-04 23:31:37 -04001566 goto error;
David Kershnerf1f537c2017-08-30 13:36:19 -04001567 err = controlvm_channel_create(chipset_dev);
1568 if (err)
1569 goto error_free_chipset_dev;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001570 acpi_device->driver_data = chipset_dev;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001571 chipset_dev->acpi_device = acpi_device;
David Kershner3fbee192017-09-27 13:14:38 -04001572 chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
Sameer Wadgaonkar15c012d2017-02-21 12:53:31 -05001573 err = sysfs_create_groups(&chipset_dev->acpi_device->dev.kobj,
1574 visorchipset_dev_groups);
1575 if (err < 0)
1576 goto error_destroy_channel;
David Kershnerf1f537c2017-08-30 13:36:19 -04001577 controlvm_channel = chipset_dev->controlvm_channel;
Sameer Wadgaonkar403043c2017-07-17 16:17:02 -04001578 if (!visor_check_channel(visorchannel_get_header(controlvm_channel),
Sameer Wadgaonkare25201d2017-08-30 13:36:35 -04001579 &chipset_dev->acpi_device->dev,
Andy Shevchenkob32c5cb2017-08-22 13:26:54 -04001580 &visor_controlvm_channel_guid,
Sameer Wadgaonkar403043c2017-07-17 16:17:02 -04001581 "controlvm",
1582 sizeof(struct visor_controlvm_channel),
1583 VISOR_CONTROLVM_CHANNEL_VERSIONID,
1584 VISOR_CHANNEL_SIGNATURE))
Sameer Wadgaonkar15c012d2017-02-21 12:53:31 -05001585 goto error_delete_groups;
David Kershner4da33362015-05-05 18:36:39 -04001586 /* if booting in a crash kernel */
1587 if (is_kdump_kernel())
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001588 INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
David Kershner4da33362015-05-05 18:36:39 -04001589 setup_crash_devices_work_queue);
1590 else
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001591 INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
David Kershner4da33362015-05-05 18:36:39 -04001592 controlvm_periodic_work);
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001593 chipset_dev->most_recent_message_jiffies = jiffies;
David Kershner3fbee192017-09-27 13:14:38 -04001594 chipset_dev->poll_jiffies = POLLJIFFIES_CONTROLVM_FAST;
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001595 schedule_delayed_work(&chipset_dev->periodic_controlvm_work,
1596 chipset_dev->poll_jiffies);
David Kershner1366a3d2016-04-04 23:31:37 -04001597 err = visorbus_init();
1598 if (err < 0)
Sameer Wadgaonkar15c012d2017-02-21 12:53:31 -05001599 goto error_cancel_work;
David Kershner1366a3d2016-04-04 23:31:37 -04001600 return 0;
1601
David Kershner1366a3d2016-04-04 23:31:37 -04001602error_cancel_work:
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001603 cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
David Kershner1366a3d2016-04-04 23:31:37 -04001604
Sameer Wadgaonkar15c012d2017-02-21 12:53:31 -05001605error_delete_groups:
1606 sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
1607 visorchipset_dev_groups);
1608
David Kershner1366a3d2016-04-04 23:31:37 -04001609error_destroy_channel:
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001610 visorchannel_destroy(chipset_dev->controlvm_channel);
1611
1612error_free_chipset_dev:
1613 kfree(chipset_dev);
David Kershner1366a3d2016-04-04 23:31:37 -04001614
1615error:
David Kershner372b9f22017-04-18 16:55:23 -04001616 dev_err(&acpi_device->dev, "failed with error %d\n", err);
David Kershner1366a3d2016-04-04 23:31:37 -04001617 return err;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001618}
1619
Charles Danielse80ffd42017-08-22 13:26:57 -04001620static int visorchipset_exit(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06001621{
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04001622 visorbus_exit();
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001623 cancel_delayed_work_sync(&chipset_dev->periodic_controlvm_work);
Sameer Wadgaonkar15c012d2017-02-21 12:53:31 -05001624 sysfs_remove_groups(&chipset_dev->acpi_device->dev.kobj,
1625 visorchipset_dev_groups);
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001626 visorchannel_destroy(chipset_dev->controlvm_channel);
Sameer Wadgaonkar765b2f82017-02-21 12:53:29 -05001627 kfree(chipset_dev);
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001628 return 0;
1629}
1630
1631static const struct acpi_device_id unisys_device_ids[] = {
1632 {"PNP0A07", 0},
1633 {"", 0},
1634};
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001635
1636static struct acpi_driver unisys_acpi_driver = {
1637 .name = "unisys_acpi",
1638 .class = "unisys_acpi_class",
1639 .owner = THIS_MODULE,
1640 .ids = unisys_device_ids,
1641 .ops = {
1642 .add = visorchipset_init,
1643 .remove = visorchipset_exit,
David Kershner027b03e2017-04-18 16:55:04 -04001644 },
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001645};
David Kershner1fc07f92015-07-09 13:27:53 -04001646
1647MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
1648
David Kershnerc1d28da2017-04-18 16:55:03 -04001649static __init int visorutil_spar_detect(void)
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001650{
1651 unsigned int eax, ebx, ecx, edx;
1652
Borislav Petkov0c9f35362016-03-29 17:41:55 +02001653 if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001654 /* check the ID */
Sameer Wadgaonkara27ded92017-05-19 16:17:47 -04001655 cpuid(UNISYS_VISOR_LEAF_ID, &eax, &ebx, &ecx, &edx);
1656 return (ebx == UNISYS_VISOR_ID_EBX) &&
1657 (ecx == UNISYS_VISOR_ID_ECX) &&
1658 (edx == UNISYS_VISOR_ID_EDX);
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001659 }
David Kershnere4a06432017-08-30 13:36:25 -04001660 return 0;
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001661}
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001662
Arnd Bergmann056e4fc2017-09-15 21:23:13 +02001663static int __init init_unisys(void)
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001664{
1665 int result;
Alessandro Parini35e606d2015-06-13 17:40:49 +02001666
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001667 if (!visorutil_spar_detect())
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001668 return -ENODEV;
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001669 result = acpi_bus_register_driver(&unisys_acpi_driver);
1670 if (result)
1671 return -ENODEV;
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001672 pr_info("Unisys Visorchipset Driver Loaded.\n");
1673 return 0;
1674};
1675
Arnd Bergmann056e4fc2017-09-15 21:23:13 +02001676static void __exit exit_unisys(void)
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001677{
1678 acpi_bus_unregister_driver(&unisys_acpi_driver);
Ken Cox12e364b2014-03-04 07:58:07 -06001679}
1680
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04001681module_init(init_unisys);
1682module_exit(exit_unisys);
Ken Cox12e364b2014-03-04 07:58:07 -06001683
1684MODULE_AUTHOR("Unisys");
1685MODULE_LICENSE("GPL");
Jon Frischbff8c1a2016-09-26 11:03:46 -04001686MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses");