blob: 59871495ea85b180bcda36d54e5695a6c5294c3a [file] [log] [blame]
Ken Cox12e364b2014-03-04 07:58:07 -06001/* visorchipset_main.c
2 *
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.
5 *
Benjamin Romer6f14cc12015-07-16 12:40:48 -04006 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
Ken Cox12e364b2014-03-04 07:58:07 -06009 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13 * NON INFRINGEMENT. See the GNU General Public License for more
14 * details.
15 */
16
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040017#include <linux/acpi.h>
Erik Arfvidsonc0a14642015-05-05 18:37:06 -040018#include <linux/cdev.h>
Erik Arfvidson46168812015-05-05 18:36:14 -040019#include <linux/ctype.h>
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040020#include <linux/fs.h>
21#include <linux/mm.h>
Ken Cox12e364b2014-03-04 07:58:07 -060022#include <linux/nls.h>
23#include <linux/netdevice.h>
24#include <linux/platform_device.h>
Benjamin Romer90addb02014-05-06 09:58:23 -040025#include <linux/uuid.h>
Benjamin Romer1ba00982015-04-06 10:27:40 -040026#include <linux/crash_dump.h>
Ken Cox12e364b2014-03-04 07:58:07 -060027
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040028#include "visorbus.h"
29#include "visorbus_private.h"
David Kershner5f3a7e32015-05-13 13:22:10 -040030#include "vmcallinterface.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040031
Ken Cox12e364b2014-03-04 07:58:07 -060032#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
Ken Cox12e364b2014-03-04 07:58:07 -060033
Ken Cox12e364b2014-03-04 07:58:07 -060034#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
35#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
36
Bhaktipriya Shridhar2c7e1d42015-12-09 20:57:05 +053037#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -040038
39#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000
40
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -040041#define UNISYS_SPAR_LEAF_ID 0x40000000
42
43/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
44#define UNISYS_SPAR_ID_EBX 0x73696e55
45#define UNISYS_SPAR_ID_ECX 0x70537379
46#define UNISYS_SPAR_ID_EDX 0x34367261
47
Jes Sorensenb615d622015-05-05 18:35:38 -040048/*
49 * Module parameters
50 */
Jes Sorensenb615d622015-05-05 18:35:38 -040051static int visorchipset_major;
Jes Sorensenb615d622015-05-05 18:35:38 -040052
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040053static int
54visorchipset_open(struct inode *inode, struct file *file)
55{
Tim Selle4feb2f2016-04-04 23:31:11 -040056 unsigned int minor_number = iminor(inode);
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040057
58 if (minor_number)
59 return -ENODEV;
60 file->private_data = NULL;
61 return 0;
62}
63
64static int
65visorchipset_release(struct inode *inode, struct file *file)
66{
67 return 0;
68}
69
David Binderec17f452016-06-10 21:48:18 -040070/*
71 * When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
72 * we switch to slow polling mode. As soon as we get a controlvm
73 * message, we switch back to fast polling mode.
74 */
Ken Cox12e364b2014-03-04 07:58:07 -060075#define MIN_IDLE_SECONDS 10
Jes Sorensen52063ec2015-04-13 10:28:41 -040076static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Erik Arfvidson2ee0d052016-02-08 10:41:44 -050077/* when we got our last controlvm message */
78static unsigned long most_recent_message_jiffies;
Ken Cox12e364b2014-03-04 07:58:07 -060079
Erik Arfvidson46168812015-05-05 18:36:14 -040080struct parser_context {
81 unsigned long allocbytes;
82 unsigned long param_bytes;
83 u8 *curr;
84 unsigned long bytes_remaining;
85 bool byte_stream;
86 char data[0];
87};
88
Benjamin Romer9232d2d2015-03-16 13:57:57 -040089static struct delayed_work periodic_controlvm_work;
Ken Cox12e364b2014-03-04 07:58:07 -060090
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040091static struct cdev file_cdev;
92static struct visorchannel **file_controlvm_channel;
Ken Cox12e364b2014-03-04 07:58:07 -060093
Benjamin Romerc3d9a222015-03-16 13:58:05 -040094static struct visorchannel *controlvm_channel;
Ken Cox12e364b2014-03-04 07:58:07 -060095
Benjamin Romer84982fb2015-03-16 13:58:07 -040096/* Manages the request payload in the controlvm channel */
Jes Sorensenc1f834e2015-04-13 10:28:39 -040097struct visor_controlvm_payload_info {
Dan Williams3103dc02015-08-10 23:07:06 -040098 u8 *ptr; /* pointer to base address of payload pool */
David Binderec17f452016-06-10 21:48:18 -040099 u64 offset; /*
100 * offset from beginning of controlvm
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500101 * channel to beginning of payload * pool
102 */
Benjamin Romerb3c55b12014-07-31 12:00:50 -0400103 u32 bytes; /* number of bytes in payload pool */
Jes Sorensenc1f834e2015-04-13 10:28:39 -0400104};
105
106static struct visor_controlvm_payload_info controlvm_payload_info;
Jon Frischc071b6f2016-09-19 17:09:19 -0400107static unsigned long controlvm_payload_bytes_buffered;
Ken Cox12e364b2014-03-04 07:58:07 -0600108
David Binderec17f452016-06-10 21:48:18 -0400109/*
110 * The following globals are used to handle the scenario where we are unable to
111 * offload the payload from a controlvm message due to memory requirements. In
Ken Cox12e364b2014-03-04 07:58:07 -0600112 * this scenario, we simply stash the controlvm message, then attempt to
113 * process it again the next time controlvm_periodic_work() runs.
114 */
Benjamin Romer7166ed12015-03-16 13:58:38 -0400115static struct controlvm_message controlvm_pending_msg;
Prarit Bhargavac79b28f2015-05-05 18:36:15 -0400116static bool controlvm_pending_msg_valid;
Ken Cox12e364b2014-03-04 07:58:07 -0600117
David Binderec17f452016-06-10 21:48:18 -0400118/*
David Binderec17f452016-06-10 21:48:18 -0400119 * This describes a buffer and its current state of transfer (e.g., how many
Ken Cox12e364b2014-03-04 07:58:07 -0600120 * bytes have already been supplied as putfile data, and how many bytes are
121 * remaining) for a putfile_request.
122 */
123struct putfile_active_buffer {
124 /* a payload from a controlvm message, containing a file data buffer */
Benjamin Romer317d9612015-03-16 13:57:51 -0400125 struct parser_context *parser_ctx;
Ken Cox12e364b2014-03-04 07:58:07 -0600126 /* points within data area of parser_ctx to next byte of data */
Ken Cox12e364b2014-03-04 07:58:07 -0600127 size_t bytes_remaining;
128};
129
130#define PUTFILE_REQUEST_SIG 0x0906101302281211
David Binderec17f452016-06-10 21:48:18 -0400131/*
132 * This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE
133 * conversation. Structs of this type are dynamically linked into
Ken Cox12e364b2014-03-04 07:58:07 -0600134 * <Putfile_request_list>.
135 */
136struct putfile_request {
137 u64 sig; /* PUTFILE_REQUEST_SIG */
138
139 /* header from original TransmitFile request */
Benjamin Romer98d7b592014-10-23 14:30:26 -0400140 struct controlvm_message_header controlvm_header;
Ken Cox12e364b2014-03-04 07:58:07 -0600141
142 /* link to next struct putfile_request */
143 struct list_head next_putfile_request;
144
David Binderec17f452016-06-10 21:48:18 -0400145 /*
146 * head of putfile_buffer_entry list, which describes the data to be
Ken Cox12e364b2014-03-04 07:58:07 -0600147 * supplied as putfile data;
148 * - this list is added to when controlvm messages come in that supply
149 * file data
150 * - this list is removed from via the hotplug program that is actually
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500151 * consuming these buffers to write as file data
152 */
Ken Cox12e364b2014-03-04 07:58:07 -0600153 struct list_head input_buffer_list;
154 spinlock_t req_list_lock; /* lock for input_buffer_list */
155
156 /* waiters for input_buffer_list to go non-empty */
157 wait_queue_head_t input_buffer_wq;
158
159 /* data not yet read within current putfile_buffer_entry */
160 struct putfile_active_buffer active_buf;
161
David Binderec17f452016-06-10 21:48:18 -0400162 /*
163 * <0 = failed, 0 = in-progress, >0 = successful;
164 * note that this must be set with req_list_lock, and if you set <0,
165 * it is your responsibility to also free up all of the other objects
166 * in this struct (like input_buffer_list, active_buf.parser_ctx)
167 * before releasing the lock
168 */
Ken Cox12e364b2014-03-04 07:58:07 -0600169 int completion_status;
170};
171
Ken Cox12e364b2014-03-04 07:58:07 -0600172struct parahotplug_request {
173 struct list_head list;
174 int id;
175 unsigned long expiration;
Benjamin Romer3ab47702014-10-23 14:30:31 -0400176 struct controlvm_message msg;
Ken Cox12e364b2014-03-04 07:58:07 -0600177};
178
Ken Cox12e364b2014-03-04 07:58:07 -0600179/* info for /dev/visorchipset */
David Binderec17f452016-06-10 21:48:18 -0400180static dev_t major_dev = -1; /*< indicates major num for device */
Ken Cox12e364b2014-03-04 07:58:07 -0600181
Benjamin Romer19f66342014-07-22 09:56:25 -0400182/* prototypes for attributes */
183static ssize_t toolaction_show(struct device *dev,
David Kershner84efd202016-09-19 17:09:29 -0400184 struct device_attribute *attr,
185 char *buf)
186{
187 u8 tool_action = 0;
188
189 visorchannel_read(controlvm_channel,
190 offsetof(struct spar_controlvm_channel_protocol,
191 tool_action), &tool_action, sizeof(u8));
192 return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
193}
194
Benjamin Romer19f66342014-07-22 09:56:25 -0400195static ssize_t toolaction_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400196 struct device_attribute *attr,
David Kershner84efd202016-09-19 17:09:29 -0400197 const char *buf, size_t count)
198{
199 u8 tool_action;
200 int ret;
201
202 if (kstrtou8(buf, 10, &tool_action))
203 return -EINVAL;
204
205 ret = visorchannel_write
206 (controlvm_channel,
207 offsetof(struct spar_controlvm_channel_protocol,
208 tool_action),
209 &tool_action, sizeof(u8));
210
211 if (ret)
212 return ret;
213 return count;
214}
Benjamin Romer19f66342014-07-22 09:56:25 -0400215static DEVICE_ATTR_RW(toolaction);
216
Benjamin Romer54b31222014-07-22 09:56:26 -0400217static ssize_t boottotool_show(struct device *dev,
David Kershner1b1d4632016-09-19 17:09:30 -0400218 struct device_attribute *attr,
219 char *buf)
220{
221 struct efi_spar_indication efi_spar_indication;
222
223 visorchannel_read(controlvm_channel,
224 offsetof(struct spar_controlvm_channel_protocol,
225 efi_spar_ind), &efi_spar_indication,
226 sizeof(struct efi_spar_indication));
227 return scnprintf(buf, PAGE_SIZE, "%u\n",
228 efi_spar_indication.boot_to_tool);
229}
230
Benjamin Romer54b31222014-07-22 09:56:26 -0400231static ssize_t boottotool_store(struct device *dev,
David Kershner1b1d4632016-09-19 17:09:30 -0400232 struct device_attribute *attr,
233 const char *buf, size_t count)
234{
235 int val, ret;
236 struct efi_spar_indication efi_spar_indication;
237
238 if (kstrtoint(buf, 10, &val))
239 return -EINVAL;
240
241 efi_spar_indication.boot_to_tool = val;
242 ret = visorchannel_write
243 (controlvm_channel,
244 offsetof(struct spar_controlvm_channel_protocol,
245 efi_spar_ind), &(efi_spar_indication),
246 sizeof(struct efi_spar_indication));
247
248 if (ret)
249 return ret;
250 return count;
251}
Benjamin Romer54b31222014-07-22 09:56:26 -0400252static DEVICE_ATTR_RW(boottotool);
253
Benjamin Romer422af172014-07-24 14:08:42 -0400254static ssize_t error_show(struct device *dev, struct device_attribute *attr,
David Kershner8a4a8a02016-09-19 17:09:31 -0400255 char *buf)
256{
257 u32 error = 0;
258
259 visorchannel_read(controlvm_channel,
260 offsetof(struct spar_controlvm_channel_protocol,
261 installation_error),
262 &error, sizeof(u32));
263 return scnprintf(buf, PAGE_SIZE, "%i\n", error);
264}
265
Benjamin Romer422af172014-07-24 14:08:42 -0400266static ssize_t error_store(struct device *dev, struct device_attribute *attr,
David Kershner8a4a8a02016-09-19 17:09:31 -0400267 const char *buf, size_t count)
268{
269 u32 error;
270 int ret;
271
272 if (kstrtou32(buf, 10, &error))
273 return -EINVAL;
274
275 ret = visorchannel_write
276 (controlvm_channel,
277 offsetof(struct spar_controlvm_channel_protocol,
278 installation_error),
279 &error, sizeof(u32));
280 if (ret)
281 return ret;
282 return count;
283}
Benjamin Romer422af172014-07-24 14:08:42 -0400284static DEVICE_ATTR_RW(error);
285
286static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
David Kershner79730c72016-09-19 17:09:32 -0400287 char *buf)
288{
289 u32 text_id = 0;
290
291 visorchannel_read
292 (controlvm_channel,
293 offsetof(struct spar_controlvm_channel_protocol,
294 installation_text_id),
295 &text_id, sizeof(u32));
296 return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
297}
298
Benjamin Romer422af172014-07-24 14:08:42 -0400299static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
David Kershner79730c72016-09-19 17:09:32 -0400300 const char *buf, size_t count)
301{
302 u32 text_id;
303 int ret;
304
305 if (kstrtou32(buf, 10, &text_id))
306 return -EINVAL;
307
308 ret = visorchannel_write
309 (controlvm_channel,
310 offsetof(struct spar_controlvm_channel_protocol,
311 installation_text_id),
312 &text_id, sizeof(u32));
313 if (ret)
314 return ret;
315 return count;
316}
Benjamin Romer422af172014-07-24 14:08:42 -0400317static DEVICE_ATTR_RW(textid);
318
319static ssize_t remaining_steps_show(struct device *dev,
David Kershner97f792e2016-09-19 17:09:33 -0400320 struct device_attribute *attr, char *buf)
321{
322 u16 remaining_steps = 0;
323
324 visorchannel_read(controlvm_channel,
325 offsetof(struct spar_controlvm_channel_protocol,
326 installation_remaining_steps),
327 &remaining_steps, sizeof(u16));
328 return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
329}
330
Benjamin Romer422af172014-07-24 14:08:42 -0400331static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400332 struct device_attribute *attr,
David Kershner97f792e2016-09-19 17:09:33 -0400333 const char *buf, size_t count)
334{
335 u16 remaining_steps;
336 int ret;
337
338 if (kstrtou16(buf, 10, &remaining_steps))
339 return -EINVAL;
340
341 ret = visorchannel_write
342 (controlvm_channel,
343 offsetof(struct spar_controlvm_channel_protocol,
344 installation_remaining_steps),
345 &remaining_steps, sizeof(u16));
346 if (ret)
347 return ret;
348 return count;
349}
Benjamin Romer422af172014-07-24 14:08:42 -0400350static DEVICE_ATTR_RW(remaining_steps);
351
Jes Sorensen464129e2015-05-05 18:37:12 -0400352static uuid_le
Erik Arfvidson46168812015-05-05 18:36:14 -0400353parser_id_get(struct parser_context *ctx)
354{
355 struct spar_controlvm_parameters_header *phdr = NULL;
356
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500357 if (!ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400358 return NULL_UUID_LE;
359 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
360 return phdr->id;
361}
362
David Binderec17f452016-06-10 21:48:18 -0400363/*
364 * Describes the state from the perspective of which controlvm messages have
365 * been received for a bus or device.
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400366 */
367
368enum PARSER_WHICH_STRING {
369 PARSERSTRING_INITIATOR,
370 PARSERSTRING_TARGET,
371 PARSERSTRING_CONNECTION,
372 PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
373};
374
Jes Sorensen464129e2015-05-05 18:37:12 -0400375static void
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400376parser_param_start(struct parser_context *ctx,
377 enum PARSER_WHICH_STRING which_string)
Erik Arfvidson46168812015-05-05 18:36:14 -0400378{
379 struct spar_controlvm_parameters_header *phdr = NULL;
380
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500381 if (!ctx)
Benjamin Romerb4d4dfb2016-02-08 10:41:53 -0500382 return;
383
Erik Arfvidson46168812015-05-05 18:36:14 -0400384 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
385 switch (which_string) {
386 case PARSERSTRING_INITIATOR:
387 ctx->curr = ctx->data + phdr->initiator_offset;
388 ctx->bytes_remaining = phdr->initiator_length;
389 break;
390 case PARSERSTRING_TARGET:
391 ctx->curr = ctx->data + phdr->target_offset;
392 ctx->bytes_remaining = phdr->target_length;
393 break;
394 case PARSERSTRING_CONNECTION:
395 ctx->curr = ctx->data + phdr->connection_offset;
396 ctx->bytes_remaining = phdr->connection_length;
397 break;
398 case PARSERSTRING_NAME:
399 ctx->curr = ctx->data + phdr->name_offset;
400 ctx->bytes_remaining = phdr->name_length;
401 break;
402 default:
403 break;
404 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400405}
406
Jes Sorensen464129e2015-05-05 18:37:12 -0400407static void parser_done(struct parser_context *ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400408{
409 if (!ctx)
410 return;
411 controlvm_payload_bytes_buffered -= ctx->param_bytes;
412 kfree(ctx);
413}
414
Jes Sorensen464129e2015-05-05 18:37:12 -0400415static void *
Erik Arfvidson46168812015-05-05 18:36:14 -0400416parser_string_get(struct parser_context *ctx)
417{
418 u8 *pscan;
419 unsigned long nscan;
420 int value_length = -1;
421 void *value = NULL;
422 int i;
423
424 if (!ctx)
425 return NULL;
426 pscan = ctx->curr;
427 nscan = ctx->bytes_remaining;
428 if (nscan == 0)
429 return NULL;
430 if (!pscan)
431 return NULL;
432 for (i = 0, value_length = -1; i < nscan; i++)
433 if (pscan[i] == '\0') {
434 value_length = i;
435 break;
436 }
437 if (value_length < 0) /* '\0' was not included in the length */
438 value_length = nscan;
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500439 value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500440 if (!value)
Erik Arfvidson46168812015-05-05 18:36:14 -0400441 return NULL;
442 if (value_length > 0)
443 memcpy(value, pscan, value_length);
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500444 ((u8 *)(value))[value_length] = '\0';
Erik Arfvidson46168812015-05-05 18:36:14 -0400445 return value;
446}
447
Don Zickusab0592b2015-05-13 13:22:19 -0400448struct visor_busdev {
449 u32 bus_no;
450 u32 dev_no;
451};
452
453static int match_visorbus_dev_by_id(struct device *dev, void *data)
454{
455 struct visor_device *vdev = to_visor_device(dev);
Shraddha Barke7f445822015-10-15 00:58:23 +0530456 struct visor_busdev *id = data;
Don Zickusab0592b2015-05-13 13:22:19 -0400457 u32 bus_no = id->bus_no;
458 u32 dev_no = id->dev_no;
459
Don Zickus65bd6e42015-06-04 09:22:40 -0400460 if ((vdev->chipset_bus_no == bus_no) &&
461 (vdev->chipset_dev_no == dev_no))
Don Zickusab0592b2015-05-13 13:22:19 -0400462 return 1;
463
464 return 0;
465}
Erik Arfvidsond1e08632016-02-08 10:41:47 -0500466
Don Zickusab0592b2015-05-13 13:22:19 -0400467struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
468 struct visor_device *from)
469{
470 struct device *dev;
471 struct device *dev_start = NULL;
472 struct visor_device *vdev = NULL;
473 struct visor_busdev id = {
474 .bus_no = bus_no,
475 .dev_no = dev_no
476 };
477
478 if (from)
479 dev_start = &from->device;
480 dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
481 match_visorbus_dev_by_id);
482 if (dev)
483 vdev = to_visor_device(dev);
484 return vdev;
485}
Don Zickusab0592b2015-05-13 13:22:19 -0400486
Ken Cox12e364b2014-03-04 07:58:07 -0600487static void
David Kershner5f251392016-09-19 17:09:26 -0400488controlvm_init_response(struct controlvm_message *msg,
489 struct controlvm_message_header *msg_hdr, int response)
490{
491 memset(msg, 0, sizeof(struct controlvm_message));
492 memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
493 msg->hdr.payload_bytes = 0;
494 msg->hdr.payload_vm_offset = 0;
495 msg->hdr.payload_max_bytes = 0;
496 if (response < 0) {
497 msg->hdr.flags.failed = 1;
498 msg->hdr.completion_status = (u32)(-response);
499 }
500}
501
502static void
503controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
504 int response,
505 enum ultra_chipset_feature features)
506{
507 struct controlvm_message outmsg;
508
509 controlvm_init_response(&outmsg, msg_hdr, response);
510 outmsg.cmd.init_chipset.features = features;
David Binder264f7b82016-09-26 11:03:49 -0400511 if (visorchannel_signalinsert(controlvm_channel,
512 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
David Kershner5f251392016-09-19 17:09:26 -0400513 return;
514 }
515}
516
517static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400518chipset_init(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600519{
520 static int chipset_inited;
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400521 enum ultra_chipset_feature features = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600522 int rc = CONTROLVM_RESP_SUCCESS;
523
524 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
525 if (chipset_inited) {
Ken Cox22ad57b2014-03-19 13:06:25 -0500526 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershner5233d1e2016-03-11 17:01:41 -0500527 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600528 }
529 chipset_inited = 1;
530 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
531
David Binderec17f452016-06-10 21:48:18 -0400532 /*
533 * Set features to indicate we support parahotplug (if Command
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500534 * also supports it).
535 */
Ken Cox12e364b2014-03-04 07:58:07 -0600536 features =
Benjamin Romer2ea51172014-10-23 14:30:25 -0400537 inmsg->cmd.init_chipset.
Ken Cox12e364b2014-03-04 07:58:07 -0600538 features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
539
David Binderec17f452016-06-10 21:48:18 -0400540 /*
541 * Set the "reply" bit so Command knows this is a
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500542 * features-aware driver.
543 */
Ken Cox12e364b2014-03-04 07:58:07 -0600544 features |= ULTRA_CHIPSET_FEATURE_REPLY;
545
David Kershner5233d1e2016-03-11 17:01:41 -0500546out_respond:
Benjamin Romer98d7b592014-10-23 14:30:26 -0400547 if (inmsg->hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -0600548 controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
549}
550
551static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400552controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600553{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400554 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400555
Benjamin Romerb3168c72015-03-16 13:58:46 -0400556 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500557 if (outmsg.hdr.flags.test_message == 1)
Ken Cox12e364b2014-03-04 07:58:07 -0600558 return;
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500559
David Binder264f7b82016-09-26 11:03:49 -0400560 if (visorchannel_signalinsert(controlvm_channel,
561 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600562 return;
563 }
564}
565
Benjamin Romer98d7b592014-10-23 14:30:26 -0400566static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400567 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400568 struct spar_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -0600569{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400570 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400571
Benjamin Romerb3168c72015-03-16 13:58:46 -0400572 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400573 outmsg.cmd.device_change_state.state = state;
574 outmsg.cmd.device_change_state.flags.phys_device = 1;
David Binder264f7b82016-09-26 11:03:49 -0400575 if (visorchannel_signalinsert(controlvm_channel,
576 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600577 return;
578 }
579}
580
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400581enum crash_obj_type {
582 CRASH_DEV,
583 CRASH_BUS,
584};
585
Ken Cox12e364b2014-03-04 07:58:07 -0600586static void
Tim Sell12c957d2016-03-01 19:45:04 -0500587save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
588{
589 u32 local_crash_msg_offset;
590 u16 local_crash_msg_count;
591
592 if (visorchannel_read(controlvm_channel,
593 offsetof(struct spar_controlvm_channel_protocol,
594 saved_crash_message_count),
595 &local_crash_msg_count, sizeof(u16)) < 0) {
596 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
597 POSTCODE_SEVERITY_ERR);
598 return;
599 }
600
601 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
602 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
603 local_crash_msg_count,
604 POSTCODE_SEVERITY_ERR);
605 return;
606 }
607
608 if (visorchannel_read(controlvm_channel,
609 offsetof(struct spar_controlvm_channel_protocol,
610 saved_crash_message_offset),
611 &local_crash_msg_offset, sizeof(u32)) < 0) {
612 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
613 POSTCODE_SEVERITY_ERR);
614 return;
615 }
616
617 if (typ == CRASH_BUS) {
618 if (visorchannel_write(controlvm_channel,
619 local_crash_msg_offset,
620 msg,
621 sizeof(struct controlvm_message)) < 0) {
622 POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
623 POSTCODE_SEVERITY_ERR);
624 return;
625 }
626 } else {
627 local_crash_msg_offset += sizeof(struct controlvm_message);
628 if (visorchannel_write(controlvm_channel,
629 local_crash_msg_offset,
630 msg,
631 sizeof(struct controlvm_message)) < 0) {
632 POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
633 POSTCODE_SEVERITY_ERR);
634 return;
635 }
636 }
637}
638
639static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400640bus_responder(enum controlvm_id cmd_id,
641 struct controlvm_message_header *pending_msg_hdr,
Don Zickus3032aed2015-05-13 13:22:24 -0400642 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600643{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500644 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600645 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400646
647 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600648 return;
Don Zickus0274b5a2015-06-01 13:00:27 -0400649
650 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600651}
652
653static void
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400654device_changestate_responder(enum controlvm_id cmd_id,
Don Zickusa298bc02015-06-04 09:22:42 -0400655 struct visor_device *p, int response,
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400656 struct spar_segment_state response_state)
Ken Cox12e364b2014-03-04 07:58:07 -0600657{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400658 struct controlvm_message outmsg;
Don Zickusa298bc02015-06-04 09:22:42 -0400659 u32 bus_no = p->chipset_bus_no;
660 u32 dev_no = p->chipset_dev_no;
Ken Cox12e364b2014-03-04 07:58:07 -0600661
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500662 if (!p->pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600663 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400664 if (p->pending_msg_hdr->id != cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600665 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600666
Don Zickus0274b5a2015-06-01 13:00:27 -0400667 controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600668
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400669 outmsg.cmd.device_change_state.bus_no = bus_no;
670 outmsg.cmd.device_change_state.dev_no = dev_no;
671 outmsg.cmd.device_change_state.state = response_state;
Ken Cox12e364b2014-03-04 07:58:07 -0600672
David Binder264f7b82016-09-26 11:03:49 -0400673 if (visorchannel_signalinsert(controlvm_channel,
674 CONTROLVM_QUEUE_REQUEST, &outmsg))
Ken Cox12e364b2014-03-04 07:58:07 -0600675 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600676}
677
678static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400679device_responder(enum controlvm_id cmd_id,
680 struct controlvm_message_header *pending_msg_hdr,
Don Zickusb4b598f2015-05-13 13:22:25 -0400681 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600682{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500683 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600684 return; /* no controlvm response needed */
Benjamin Romer0aca78442015-03-04 12:14:25 -0500685
Don Zickus0274b5a2015-06-01 13:00:27 -0400686 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600687 return;
Benjamin Romer0aca78442015-03-04 12:14:25 -0500688
Don Zickus0274b5a2015-06-01 13:00:27 -0400689 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600690}
691
692static void
Don Zickusd32517e2015-06-04 09:22:41 -0400693bus_epilog(struct visor_device *bus_info,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400694 u32 cmd, struct controlvm_message_header *msg_hdr,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400695 int response, bool need_response)
Ken Cox12e364b2014-03-04 07:58:07 -0600696{
Don Zickus0274b5a2015-06-01 13:00:27 -0400697 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600698
Don Zickus0274b5a2015-06-01 13:00:27 -0400699 if (!bus_info) {
David Binderec17f452016-06-10 21:48:18 -0400700 /*
701 * relying on a valid passed in response code
702 * be lazy and re-use msg_hdr for this failure, is this ok??
703 */
Don Zickus0274b5a2015-06-01 13:00:27 -0400704 pmsg_hdr = msg_hdr;
David Binder87241ab2016-06-10 21:48:21 -0400705 goto out_respond;
Don Zickus0274b5a2015-06-01 13:00:27 -0400706 }
707
708 if (bus_info->pending_msg_hdr) {
709 /* only non-NULL if dev is still waiting on a response */
710 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
711 pmsg_hdr = bus_info->pending_msg_hdr;
David Binder87241ab2016-06-10 21:48:21 -0400712 goto out_respond;
Don Zickus0274b5a2015-06-01 13:00:27 -0400713 }
Benjamin Romer0aca78442015-03-04 12:14:25 -0500714
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400715 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -0400716 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
717 if (!pmsg_hdr) {
David Kershner368acb32016-03-11 17:01:43 -0500718 POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd,
719 bus_info->chipset_bus_no,
720 POSTCODE_SEVERITY_ERR);
David Binder87241ab2016-06-10 21:48:21 -0400721 return;
Don Zickus0274b5a2015-06-01 13:00:27 -0400722 }
723
724 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400725 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -0400726 bus_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -0400727 }
Ken Cox12e364b2014-03-04 07:58:07 -0600728
Ken Cox12e364b2014-03-04 07:58:07 -0600729 if (response == CONTROLVM_RESP_SUCCESS) {
730 switch (cmd) {
731 case CONTROLVM_BUS_CREATE:
David Binder87241ab2016-06-10 21:48:21 -0400732 chipset_bus_create(bus_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600733 break;
734 case CONTROLVM_BUS_DESTROY:
David Binder87241ab2016-06-10 21:48:21 -0400735 chipset_bus_destroy(bus_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600736 break;
737 }
738 }
David Kershner368acb32016-03-11 17:01:43 -0500739
David Binder87241ab2016-06-10 21:48:21 -0400740out_respond:
David Kershner4a185e52016-04-04 23:31:39 -0400741 bus_responder(cmd, pmsg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600742}
743
744static void
Don Zickusa298bc02015-06-04 09:22:42 -0400745device_epilog(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -0400746 struct spar_segment_state state, u32 cmd,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400747 struct controlvm_message_header *msg_hdr, int response,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400748 bool need_response, bool for_visorbus)
Ken Cox12e364b2014-03-04 07:58:07 -0600749{
Don Zickus0274b5a2015-06-01 13:00:27 -0400750 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600751
Don Zickus0274b5a2015-06-01 13:00:27 -0400752 if (!dev_info) {
David Binderec17f452016-06-10 21:48:18 -0400753 /*
754 * relying on a valid passed in response code
755 * be lazy and re-use msg_hdr for this failure, is this ok??
756 */
Don Zickus0274b5a2015-06-01 13:00:27 -0400757 pmsg_hdr = msg_hdr;
David Binder87241ab2016-06-10 21:48:21 -0400758 goto out_respond;
Don Zickus0274b5a2015-06-01 13:00:27 -0400759 }
760
761 if (dev_info->pending_msg_hdr) {
762 /* only non-NULL if dev is still waiting on a response */
763 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
764 pmsg_hdr = dev_info->pending_msg_hdr;
David Binder87241ab2016-06-10 21:48:21 -0400765 goto out_respond;
Don Zickus0274b5a2015-06-01 13:00:27 -0400766 }
767
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400768 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -0400769 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
770 if (!pmsg_hdr) {
771 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Binder87241ab2016-06-10 21:48:21 -0400772 goto out_respond;
Don Zickus0274b5a2015-06-01 13:00:27 -0400773 }
774
775 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400776 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -0400777 dev_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -0400778 }
Ken Cox12e364b2014-03-04 07:58:07 -0600779
Ken Cox12e364b2014-03-04 07:58:07 -0600780 if (response >= 0) {
781 switch (cmd) {
782 case CONTROLVM_DEVICE_CREATE:
David Binder87241ab2016-06-10 21:48:21 -0400783 chipset_device_create(dev_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600784 break;
785 case CONTROLVM_DEVICE_CHANGESTATE:
786 /* ServerReady / ServerRunning / SegmentStateRunning */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -0400787 if (state.alive == segment_state_running.alive &&
788 state.operating ==
789 segment_state_running.operating) {
David Binder87241ab2016-06-10 21:48:21 -0400790 chipset_device_resume(dev_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600791 }
792 /* ServerNotReady / ServerLost / SegmentStateStandby */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -0400793 else if (state.alive == segment_state_standby.alive &&
Benjamin Romer3f833b52014-10-23 14:30:12 -0400794 state.operating ==
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -0400795 segment_state_standby.operating) {
David Binderec17f452016-06-10 21:48:18 -0400796 /*
797 * technically this is standby case
Ken Cox12e364b2014-03-04 07:58:07 -0600798 * where server is lost
799 */
David Binder87241ab2016-06-10 21:48:21 -0400800 chipset_device_pause(dev_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600801 }
802 break;
803 case CONTROLVM_DEVICE_DESTROY:
David Binder87241ab2016-06-10 21:48:21 -0400804 chipset_device_destroy(dev_info);
Ken Cox12e364b2014-03-04 07:58:07 -0600805 break;
806 }
807 }
David Kershner3cb3fa32016-04-04 23:31:38 -0400808
David Binder87241ab2016-06-10 21:48:21 -0400809out_respond:
David Kershner3cb3fa32016-04-04 23:31:38 -0400810 device_responder(cmd, pmsg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600811}
812
813static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400814bus_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600815{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400816 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400817 u32 bus_no = cmd->create_bus.bus_no;
Ken Cox12e364b2014-03-04 07:58:07 -0600818 int rc = CONTROLVM_RESP_SUCCESS;
Don Zickusd32517e2015-06-04 09:22:41 -0400819 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -0400820 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -0600821
Don Zickusd32517e2015-06-04 09:22:41 -0400822 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer6c5fed32015-03-16 13:58:20 -0400823 if (bus_info && (bus_info->state.created == 1)) {
824 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600825 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500826 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershner9fd04062016-03-11 17:01:42 -0500827 goto out_bus_epilog;
Ken Cox12e364b2014-03-04 07:58:07 -0600828 }
Benjamin Romer6c5fed32015-03-16 13:58:20 -0400829 bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
830 if (!bus_info) {
831 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600832 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500833 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Kershner9fd04062016-03-11 17:01:42 -0500834 goto out_bus_epilog;
Ken Cox12e364b2014-03-04 07:58:07 -0600835 }
836
David Kershner4abce832015-06-04 09:22:49 -0400837 INIT_LIST_HEAD(&bus_info->list_all);
Don Zickusd32517e2015-06-04 09:22:41 -0400838 bus_info->chipset_bus_no = bus_no;
839 bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
Ken Cox12e364b2014-03-04 07:58:07 -0600840
Benjamin Romer6c5fed32015-03-16 13:58:20 -0400841 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -0600842
Don Zickusb32c4992015-06-01 13:00:26 -0400843 visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
844 cmd->create_bus.channel_bytes,
845 GFP_KERNEL,
846 cmd->create_bus.bus_data_type_uuid);
847
848 if (!visorchannel) {
849 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
850 POSTCODE_SEVERITY_ERR);
851 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
852 kfree(bus_info);
853 bus_info = NULL;
David Kershner9fd04062016-03-11 17:01:42 -0500854 goto out_bus_epilog;
Don Zickusb32c4992015-06-01 13:00:26 -0400855 }
856 bus_info->visorchannel = visorchannel;
Jon Frisch820b11b2016-09-19 17:09:18 -0400857 if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0)
Tim Sell12c957d2016-03-01 19:45:04 -0500858 save_crash_message(inmsg, CRASH_BUS);
Ken Cox12e364b2014-03-04 07:58:07 -0600859
Benjamin Romer6c5fed32015-03-16 13:58:20 -0400860 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -0600861
David Kershner9fd04062016-03-11 17:01:42 -0500862out_bus_epilog:
Don Zickus3032aed2015-05-13 13:22:24 -0400863 bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400864 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -0600865}
866
867static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400868bus_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600869{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400870 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400871 u32 bus_no = cmd->destroy_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400872 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -0600873 int rc = CONTROLVM_RESP_SUCCESS;
874
Don Zickusd32517e2015-06-04 09:22:41 -0400875 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerdff54cd2015-03-16 13:58:21 -0400876 if (!bus_info)
Ken Cox22ad57b2014-03-19 13:06:25 -0500877 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerdff54cd2015-03-16 13:58:21 -0400878 else if (bus_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -0500879 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -0600880
Don Zickus3032aed2015-05-13 13:22:24 -0400881 bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400882 rc, inmsg->hdr.flags.response_expected == 1);
Don Zickusd32517e2015-06-04 09:22:41 -0400883
884 /* bus_info is freed as part of the busdevice_release function */
Ken Cox12e364b2014-03-04 07:58:07 -0600885}
886
887static void
Benjamin Romer317d9612015-03-16 13:57:51 -0400888bus_configure(struct controlvm_message *inmsg,
889 struct parser_context *parser_ctx)
Ken Cox12e364b2014-03-04 07:58:07 -0600890{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400891 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -0400892 u32 bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -0400893 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -0600894 int rc = CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -0600895
Benjamin Romer654bada2015-03-16 13:58:22 -0400896 bus_no = cmd->configure_bus.bus_no;
897 POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
898 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -0600899
Don Zickusd32517e2015-06-04 09:22:41 -0400900 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer654bada2015-03-16 13:58:22 -0400901 if (!bus_info) {
902 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600903 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500904 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romer654bada2015-03-16 13:58:22 -0400905 } else if (bus_info->state.created == 0) {
906 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600907 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500908 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500909 } else if (bus_info->pending_msg_hdr) {
Benjamin Romer654bada2015-03-16 13:58:22 -0400910 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600911 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500912 rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
Benjamin Romer654bada2015-03-16 13:58:22 -0400913 } else {
Tim Sella07d7c32016-04-04 23:31:12 -0400914 visorchannel_set_clientpartition
915 (bus_info->visorchannel,
916 cmd->configure_bus.guest_handle);
Benjamin Romer654bada2015-03-16 13:58:22 -0400917 bus_info->partition_uuid = parser_id_get(parser_ctx);
918 parser_param_start(parser_ctx, PARSERSTRING_NAME);
919 bus_info->name = parser_string_get(parser_ctx);
920
Benjamin Romer654bada2015-03-16 13:58:22 -0400921 POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
922 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -0600923 }
Don Zickus3032aed2015-05-13 13:22:24 -0400924 bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400925 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -0600926}
927
928static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400929my_device_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600930{
Benjamin Romer2ea51172014-10-23 14:30:25 -0400931 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -0400932 u32 bus_no = cmd->create_device.bus_no;
933 u32 dev_no = cmd->create_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -0400934 struct visor_device *dev_info = NULL;
Don Zickusd32517e2015-06-04 09:22:41 -0400935 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -0400936 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -0600937 int rc = CONTROLVM_RESP_SUCCESS;
938
Don Zickusa298bc02015-06-04 09:22:42 -0400939 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400940 if (!bus_info) {
941 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600942 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500943 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
David Kershnerc6af7a92016-03-11 17:01:44 -0500944 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600945 }
Don Zickusa298bc02015-06-04 09:22:42 -0400946
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400947 if (bus_info->state.created == 0) {
948 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600949 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500950 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
David Kershnerc6af7a92016-03-11 17:01:44 -0500951 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600952 }
Don Zickusa298bc02015-06-04 09:22:42 -0400953
954 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
955 if (dev_info && (dev_info->state.created == 1)) {
956 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
957 POSTCODE_SEVERITY_ERR);
958 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershnerc6af7a92016-03-11 17:01:44 -0500959 goto out_respond;
Don Zickusa298bc02015-06-04 09:22:42 -0400960 }
961
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400962 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
963 if (!dev_info) {
964 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600965 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -0500966 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Kershnerc6af7a92016-03-11 17:01:44 -0500967 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600968 }
Andreea-Cristina Bernat97a84f12014-03-14 04:20:06 +0200969
Don Zickusa298bc02015-06-04 09:22:42 -0400970 dev_info->chipset_bus_no = bus_no;
971 dev_info->chipset_dev_no = dev_no;
972 dev_info->inst = cmd->create_device.dev_inst_uuid;
973
974 /* not sure where the best place to set the 'parent' */
975 dev_info->device.parent = &bus_info->device;
976
Benjamin Romerc60c8e22015-03-16 13:58:23 -0400977 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -0600978 POSTCODE_SEVERITY_INFO);
979
David Kershnera3ef1a82015-07-14 14:43:29 -0400980 visorchannel =
981 visorchannel_create_with_lock(cmd->create_device.channel_addr,
982 cmd->create_device.channel_bytes,
983 GFP_KERNEL,
984 cmd->create_device.data_type_uuid);
Don Zickusb32c4992015-06-01 13:00:26 -0400985
986 if (!visorchannel) {
987 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
988 POSTCODE_SEVERITY_ERR);
989 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
990 kfree(dev_info);
991 dev_info = NULL;
David Kershnerc6af7a92016-03-11 17:01:44 -0500992 goto out_respond;
Don Zickusb32c4992015-06-01 13:00:26 -0400993 }
994 dev_info->visorchannel = visorchannel;
995 dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
Tim Sell12c957d2016-03-01 19:45:04 -0500996 if (uuid_le_cmp(cmd->create_device.data_type_uuid,
997 spar_vhba_channel_protocol_uuid) == 0)
998 save_crash_message(inmsg, CRASH_DEV);
999
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001000 POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001001 POSTCODE_SEVERITY_INFO);
David Kershnerc6af7a92016-03-11 17:01:44 -05001002out_respond:
Don Zickusb4b598f2015-05-13 13:22:25 -04001003 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001004 CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001005 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001006}
1007
1008static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001009my_device_changestate(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001010{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001011 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001012 u32 bus_no = cmd->device_change_state.bus_no;
1013 u32 dev_no = cmd->device_change_state.dev_no;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001014 struct spar_segment_state state = cmd->device_change_state.state;
Don Zickusa298bc02015-06-04 09:22:42 -04001015 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001016 int rc = CONTROLVM_RESP_SUCCESS;
1017
Don Zickusa298bc02015-06-04 09:22:42 -04001018 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer0278a902015-03-16 13:58:24 -04001019 if (!dev_info) {
1020 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001021 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001022 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer0278a902015-03-16 13:58:24 -04001023 } else if (dev_info->state.created == 0) {
1024 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001025 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001026 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Ken Cox12e364b2014-03-04 07:58:07 -06001027 }
Benjamin Romer0278a902015-03-16 13:58:24 -04001028 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001029 device_epilog(dev_info, state,
Benjamin Romer0278a902015-03-16 13:58:24 -04001030 CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001031 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001032}
1033
1034static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001035my_device_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001036{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001037 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001038 u32 bus_no = cmd->destroy_device.bus_no;
1039 u32 dev_no = cmd->destroy_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001040 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001041 int rc = CONTROLVM_RESP_SUCCESS;
1042
Don Zickusa298bc02015-06-04 09:22:42 -04001043 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer61715c82015-03-16 13:58:25 -04001044 if (!dev_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001045 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer61715c82015-03-16 13:58:25 -04001046 else if (dev_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001047 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001048
Benjamin Romer61715c82015-03-16 13:58:25 -04001049 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001050 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001051 CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001052 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001053}
1054
David Binderec17f452016-06-10 21:48:18 -04001055/**
1056 * initialize_controlvm_payload_info() - init controlvm_payload_info struct
1057 * @phys_addr: the physical address of controlvm channel
1058 * @offset: the offset to payload
1059 * @bytes: the size of the payload in bytes
1060 * @info: the returning valid struct
1061 *
1062 * When provided with the physical address of the controlvm channel
Ken Cox12e364b2014-03-04 07:58:07 -06001063 * (phys_addr), the offset to the payload area we need to manage
1064 * (offset), and the size of this payload area (bytes), fills in the
David Binderec17f452016-06-10 21:48:18 -04001065 * controlvm_payload_info struct.
1066 *
1067 * Return: CONTROLVM_RESP_SUCCESS for success or a negative for failure
Ken Cox12e364b2014-03-04 07:58:07 -06001068 */
1069static int
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001070initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001071 struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001072{
Dan Williams3103dc02015-08-10 23:07:06 -04001073 u8 *payload = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001074
David Kershnerdde29992016-03-11 17:01:39 -05001075 if (!info)
1076 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1077
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001078 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
David Kershnerdde29992016-03-11 17:01:39 -05001079 if ((offset == 0) || (bytes == 0))
1080 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1081
Dan Williams3103dc02015-08-10 23:07:06 -04001082 payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
David Kershnerdde29992016-03-11 17:01:39 -05001083 if (!payload)
1084 return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
Ken Cox12e364b2014-03-04 07:58:07 -06001085
1086 info->offset = offset;
1087 info->bytes = bytes;
1088 info->ptr = payload;
Ken Cox12e364b2014-03-04 07:58:07 -06001089
David Kershnerdde29992016-03-11 17:01:39 -05001090 return CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001091}
1092
1093static void
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001094destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001095{
Benjamin Romer597c3382015-03-16 13:58:27 -04001096 if (info->ptr) {
Dan Williams3103dc02015-08-10 23:07:06 -04001097 memunmap(info->ptr);
Ken Cox12e364b2014-03-04 07:58:07 -06001098 info->ptr = NULL;
1099 }
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001100 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06001101}
1102
1103static void
1104initialize_controlvm_payload(void)
1105{
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001106 u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
Benjamin Romercafefc02015-03-16 13:58:28 -04001107 u64 payload_offset = 0;
1108 u32 payload_bytes = 0;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001109
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001110 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001111 offsetof(struct spar_controlvm_channel_protocol,
1112 request_payload_offset),
Benjamin Romercafefc02015-03-16 13:58:28 -04001113 &payload_offset, sizeof(payload_offset)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001114 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1115 POSTCODE_SEVERITY_ERR);
1116 return;
1117 }
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001118 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001119 offsetof(struct spar_controlvm_channel_protocol,
1120 request_payload_bytes),
Benjamin Romercafefc02015-03-16 13:58:28 -04001121 &payload_bytes, sizeof(payload_bytes)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001122 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1123 POSTCODE_SEVERITY_ERR);
1124 return;
1125 }
1126 initialize_controlvm_payload_info(phys_addr,
Benjamin Romercafefc02015-03-16 13:58:28 -04001127 payload_offset, payload_bytes,
Benjamin Romer84982fb2015-03-16 13:58:07 -04001128 &controlvm_payload_info);
Ken Cox12e364b2014-03-04 07:58:07 -06001129}
1130
Ken Cox12e364b2014-03-04 07:58:07 -06001131/*
David Binderec17f452016-06-10 21:48:18 -04001132 * The general parahotplug flow works as follows. The visorchipset
Ken Cox12e364b2014-03-04 07:58:07 -06001133 * driver receives a DEVICE_CHANGESTATE message from Command
David Binderec17f452016-06-10 21:48:18 -04001134 * specifying a physical device to enable or disable. The CONTROLVM
Ken Cox12e364b2014-03-04 07:58:07 -06001135 * message handler calls parahotplug_process_message, which then adds
1136 * the message to a global list and kicks off a udev event which
1137 * causes a user level script to enable or disable the specified
David Binderec17f452016-06-10 21:48:18 -04001138 * device. The udev script then writes to
Ken Cox12e364b2014-03-04 07:58:07 -06001139 * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
1140 * to get called, at which point the appropriate CONTROLVM message is
1141 * retrieved from the list and responded to.
1142 */
1143
1144#define PARAHOTPLUG_TIMEOUT_MS 2000
1145
David Binderec17f452016-06-10 21:48:18 -04001146/**
1147 * parahotplug_next_id() - generate unique int to match an outstanding CONTROLVM
1148 * message with a udev script /proc response
1149 *
1150 * Return: a unique integer value
Ken Cox12e364b2014-03-04 07:58:07 -06001151 */
1152static int
1153parahotplug_next_id(void)
1154{
1155 static atomic_t id = ATOMIC_INIT(0);
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001156
Ken Cox12e364b2014-03-04 07:58:07 -06001157 return atomic_inc_return(&id);
1158}
1159
David Binderec17f452016-06-10 21:48:18 -04001160/**
1161 * parahotplug_next_expiration() - returns the time (in jiffies) when a
1162 * CONTROLVM message on the list should expire
1163 * -- PARAHOTPLUG_TIMEOUT_MS in the future
1164 *
1165 * Return: expected expiration time (in jiffies)
Ken Cox12e364b2014-03-04 07:58:07 -06001166 */
1167static unsigned long
1168parahotplug_next_expiration(void)
1169{
Nicholas Mc Guire2cc1a1b2015-01-31 12:02:08 +01001170 return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
Ken Cox12e364b2014-03-04 07:58:07 -06001171}
1172
David Binderec17f452016-06-10 21:48:18 -04001173/**
1174 * parahotplug_request_create() - create a parahotplug_request, which is
1175 * basically a wrapper for a CONTROLVM_MESSAGE
1176 * that we can stick on a list
1177 * @msg: the message to insert in the request
1178 *
1179 * Return: the request containing the provided message
Ken Cox12e364b2014-03-04 07:58:07 -06001180 */
1181static struct parahotplug_request *
Benjamin Romer3ab47702014-10-23 14:30:31 -04001182parahotplug_request_create(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001183{
Quentin Lambertea0dcfc2015-02-10 15:12:07 +01001184 struct parahotplug_request *req;
1185
Benjamin Romer6a55e3c2015-03-16 13:58:30 -04001186 req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001187 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001188 return NULL;
1189
1190 req->id = parahotplug_next_id();
1191 req->expiration = parahotplug_next_expiration();
1192 req->msg = *msg;
1193
1194 return req;
1195}
1196
David Binderec17f452016-06-10 21:48:18 -04001197/**
1198 * parahotplug_request_destroy() - free a parahotplug_request
1199 * @req: the request to deallocate
Ken Cox12e364b2014-03-04 07:58:07 -06001200 */
1201static void
1202parahotplug_request_destroy(struct parahotplug_request *req)
1203{
1204 kfree(req);
1205}
1206
David Kershner51319662016-09-19 17:09:37 -04001207static LIST_HEAD(parahotplug_request_list);
1208static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
1209
David Binderec17f452016-06-10 21:48:18 -04001210/**
David Binderec17f452016-06-10 21:48:18 -04001211 * parahotplug_request_complete() - mark request as complete
1212 * @id: the id of the request
1213 * @active: indicates whether the request is assigned to active partition
1214 *
Ken Cox12e364b2014-03-04 07:58:07 -06001215 * Called from the /proc handler, which means the user script has
David Binderec17f452016-06-10 21:48:18 -04001216 * finished the enable/disable. Find the matching identifier, and
Ken Cox12e364b2014-03-04 07:58:07 -06001217 * respond to the CONTROLVM message with success.
David Binderec17f452016-06-10 21:48:18 -04001218 *
1219 * Return: 0 on success or -EINVAL on failure
Ken Cox12e364b2014-03-04 07:58:07 -06001220 */
1221static int
Benjamin Romerb06bdf72014-07-31 12:00:49 -04001222parahotplug_request_complete(int id, u16 active)
Ken Cox12e364b2014-03-04 07:58:07 -06001223{
Jes Sorensene82ba622015-05-05 18:35:45 -04001224 struct list_head *pos;
1225 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001226
Benjamin Romerddf5de52015-03-16 13:58:41 -04001227 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001228
1229 /* Look for a request matching "id". */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001230 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001231 struct parahotplug_request *req =
1232 list_entry(pos, struct parahotplug_request, list);
1233 if (req->id == id) {
David Binderec17f452016-06-10 21:48:18 -04001234 /*
1235 * Found a match. Remove it from the list and
Ken Cox12e364b2014-03-04 07:58:07 -06001236 * respond.
1237 */
1238 list_del(pos);
Benjamin Romerddf5de52015-03-16 13:58:41 -04001239 spin_unlock(&parahotplug_request_list_lock);
Benjamin Romer2ea51172014-10-23 14:30:25 -04001240 req->msg.cmd.device_change_state.state.active = active;
Benjamin Romer98d7b592014-10-23 14:30:26 -04001241 if (req->msg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001242 controlvm_respond_physdev_changestate(
1243 &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
Benjamin Romer2ea51172014-10-23 14:30:25 -04001244 req->msg.cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001245 parahotplug_request_destroy(req);
1246 return 0;
1247 }
1248 }
1249
Benjamin Romerddf5de52015-03-16 13:58:41 -04001250 spin_unlock(&parahotplug_request_list_lock);
Erik Arfvidson119296e2016-05-13 23:17:20 -04001251 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -06001252}
1253
David Binderec17f452016-06-10 21:48:18 -04001254/**
David Kershnerebeff052016-09-19 17:09:34 -04001255 * devicedisabled_store() - disables the hotplug device
1256 * @dev: sysfs interface variable not utilized in this function
1257 * @attr: sysfs interface variable not utilized in this function
1258 * @buf: buffer containing the device id
1259 * @count: the size of the buffer
1260 *
1261 * The parahotplug/devicedisabled interface gets called by our support script
1262 * when an SR-IOV device has been shut down. The ID is passed to the script
1263 * and then passed back when the device has been removed.
1264 *
1265 * Return: the size of the buffer for success or negative for error
1266 */
1267static ssize_t devicedisabled_store(struct device *dev,
1268 struct device_attribute *attr,
1269 const char *buf, size_t count)
1270{
1271 unsigned int id;
1272 int err;
1273
1274 if (kstrtouint(buf, 10, &id))
1275 return -EINVAL;
1276
1277 err = parahotplug_request_complete(id, 0);
1278 if (err < 0)
1279 return err;
1280 return count;
1281}
1282static DEVICE_ATTR_WO(devicedisabled);
1283
1284/**
1285 * deviceenabled_store() - enables the hotplug device
1286 * @dev: sysfs interface variable not utilized in this function
1287 * @attr: sysfs interface variable not utilized in this function
1288 * @buf: buffer containing the device id
1289 * @count: the size of the buffer
1290 *
1291 * The parahotplug/deviceenabled interface gets called by our support script
1292 * when an SR-IOV device has been recovered. The ID is passed to the script
1293 * and then passed back when the device has been brought back up.
1294 *
1295 * Return: the size of the buffer for success or negative for error
1296 */
1297static ssize_t deviceenabled_store(struct device *dev,
1298 struct device_attribute *attr,
1299 const char *buf, size_t count)
1300{
1301 unsigned int id;
1302
1303 if (kstrtouint(buf, 10, &id))
1304 return -EINVAL;
1305
1306 parahotplug_request_complete(id, 1);
1307 return count;
1308}
1309static DEVICE_ATTR_WO(deviceenabled);
1310
1311static struct attribute *visorchipset_install_attrs[] = {
1312 &dev_attr_toolaction.attr,
1313 &dev_attr_boottotool.attr,
1314 &dev_attr_error.attr,
1315 &dev_attr_textid.attr,
1316 &dev_attr_remaining_steps.attr,
1317 NULL
1318};
1319
1320static struct attribute_group visorchipset_install_group = {
1321 .name = "install",
1322 .attrs = visorchipset_install_attrs
1323};
1324
1325static struct attribute *visorchipset_parahotplug_attrs[] = {
1326 &dev_attr_devicedisabled.attr,
1327 &dev_attr_deviceenabled.attr,
1328 NULL
1329};
1330
1331static struct attribute_group visorchipset_parahotplug_group = {
1332 .name = "parahotplug",
1333 .attrs = visorchipset_parahotplug_attrs
1334};
1335
1336static const struct attribute_group *visorchipset_dev_groups[] = {
1337 &visorchipset_install_group,
1338 &visorchipset_parahotplug_group,
1339 NULL
1340};
1341
1342static void visorchipset_dev_release(struct device *dev)
1343{
1344}
1345
1346/* /sys/devices/platform/visorchipset */
1347static struct platform_device visorchipset_platform_device = {
1348 .name = "visorchipset",
1349 .id = -1,
1350 .dev.groups = visorchipset_dev_groups,
1351 .dev.release = visorchipset_dev_release,
1352};
1353
1354/**
1355 * parahotplug_request_kickoff() - initiate parahotplug request
1356 * @req: the request to initiate
1357 *
1358 * Cause uevent to run the user level script to do the disable/enable specified
1359 * in the parahotplug_request.
1360 */
1361static void
1362parahotplug_request_kickoff(struct parahotplug_request *req)
1363{
1364 struct controlvm_message_packet *cmd = &req->msg.cmd;
1365 char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
1366 env_func[40];
1367 char *envp[] = {
1368 env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
1369 };
1370
1371 sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
1372 sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
1373 sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
1374 cmd->device_change_state.state.active);
1375 sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
1376 cmd->device_change_state.bus_no);
1377 sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
1378 cmd->device_change_state.dev_no >> 3);
1379 sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
1380 cmd->device_change_state.dev_no & 0x7);
1381
1382 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
1383 envp);
1384}
1385
1386/**
David Binderec17f452016-06-10 21:48:18 -04001387 * parahotplug_process_message() - enables or disables a PCI device by kicking
1388 * off a udev script
1389 * @inmsg: the message indicating whether to enable or disable
Ken Cox12e364b2014-03-04 07:58:07 -06001390 */
Ken Coxbd5b9b32014-03-13 15:39:22 -05001391static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001392parahotplug_process_message(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001393{
1394 struct parahotplug_request *req;
1395
1396 req = parahotplug_request_create(inmsg);
1397
Benjamin Romer38f736e2015-03-16 13:58:13 -04001398 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001399 return;
Ken Cox12e364b2014-03-04 07:58:07 -06001400
Benjamin Romer2ea51172014-10-23 14:30:25 -04001401 if (inmsg->cmd.device_change_state.state.active) {
David Binderec17f452016-06-10 21:48:18 -04001402 /*
1403 * For enable messages, just respond with success
1404 * right away. This is a bit of a hack, but there are
1405 * issues with the early enable messages we get (with
1406 * either the udev script not detecting that the device
1407 * is up, or not getting called at all). Fortunately
1408 * the messages that get lost don't matter anyway, as
1409 *
1410 * devices are automatically enabled at
1411 * initialization.
Ken Cox12e364b2014-03-04 07:58:07 -06001412 */
1413 parahotplug_request_kickoff(req);
Tim Sella07d7c32016-04-04 23:31:12 -04001414 controlvm_respond_physdev_changestate
1415 (&inmsg->hdr,
1416 CONTROLVM_RESP_SUCCESS,
1417 inmsg->cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001418 parahotplug_request_destroy(req);
1419 } else {
David Binderec17f452016-06-10 21:48:18 -04001420 /*
1421 * For disable messages, add the request to the
1422 * request list before kicking off the udev script. It
1423 * won't get responded to until the script has
1424 * indicated it's done.
1425 */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001426 spin_lock(&parahotplug_request_list_lock);
1427 list_add_tail(&req->list, &parahotplug_request_list);
1428 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001429
1430 parahotplug_request_kickoff(req);
1431 }
1432}
1433
David Kershnerebeff052016-09-19 17:09:34 -04001434/**
1435 * visorchipset_chipset_ready() - sends chipset_ready action
1436 *
1437 * Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1438 *
1439 * Return: CONTROLVM_RESP_SUCCESS
1440 */
1441static int
1442visorchipset_chipset_ready(void)
1443{
1444 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
1445 return CONTROLVM_RESP_SUCCESS;
1446}
1447
1448static int
1449visorchipset_chipset_selftest(void)
1450{
1451 char env_selftest[20];
1452 char *envp[] = { env_selftest, NULL };
1453
1454 sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
1455 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
1456 envp);
1457 return CONTROLVM_RESP_SUCCESS;
1458}
1459
1460/**
1461 * visorchipset_chipset_notready() - sends chipset_notready action
1462 *
1463 * Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
1464 *
1465 * Return: CONTROLVM_RESP_SUCCESS
1466 */
1467static int
1468visorchipset_chipset_notready(void)
1469{
1470 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
1471 return CONTROLVM_RESP_SUCCESS;
1472}
1473
1474static void
1475chipset_ready(struct controlvm_message_header *msg_hdr)
1476{
1477 int rc = visorchipset_chipset_ready();
1478
1479 if (rc != CONTROLVM_RESP_SUCCESS)
1480 rc = -rc;
1481 if (msg_hdr->flags.response_expected)
1482 controlvm_respond(msg_hdr, rc);
1483}
1484
1485static void
1486chipset_selftest(struct controlvm_message_header *msg_hdr)
1487{
1488 int rc = visorchipset_chipset_selftest();
1489
1490 if (rc != CONTROLVM_RESP_SUCCESS)
1491 rc = -rc;
1492 if (msg_hdr->flags.response_expected)
1493 controlvm_respond(msg_hdr, rc);
1494}
1495
1496static void
1497chipset_notready(struct controlvm_message_header *msg_hdr)
1498{
1499 int rc = visorchipset_chipset_notready();
1500
1501 if (rc != CONTROLVM_RESP_SUCCESS)
1502 rc = -rc;
1503 if (msg_hdr->flags.response_expected)
1504 controlvm_respond(msg_hdr, rc);
1505}
1506
David Kershner5f3a7e32015-05-13 13:22:10 -04001507static inline unsigned int
1508issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
1509{
1510 struct vmcall_io_controlvm_addr_params params;
1511 int result = VMCALL_SUCCESS;
1512 u64 physaddr;
1513
1514 physaddr = virt_to_phys(&params);
1515 ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
1516 if (VMCALL_SUCCESSFUL(result)) {
1517 *control_addr = params.address;
1518 *control_bytes = params.channel_bytes;
1519 }
1520 return result;
1521}
1522
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001523static u64 controlvm_get_channel_address(void)
Benjamin Romer524b0b62014-07-17 12:39:57 -04001524{
Benjamin Romer5fc02292014-07-31 12:00:51 -04001525 u64 addr = 0;
Benjamin Romerb3c55b12014-07-31 12:00:50 -04001526 u32 size = 0;
Benjamin Romer524b0b62014-07-17 12:39:57 -04001527
Benjamin Romer0aca78442015-03-04 12:14:25 -05001528 if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
Benjamin Romer524b0b62014-07-17 12:39:57 -04001529 return 0;
Benjamin Romer0aca78442015-03-04 12:14:25 -05001530
Benjamin Romer524b0b62014-07-17 12:39:57 -04001531 return addr;
1532}
1533
Ken Cox12e364b2014-03-04 07:58:07 -06001534static void
Ken Cox12e364b2014-03-04 07:58:07 -06001535setup_crash_devices_work_queue(struct work_struct *work)
1536{
Benjamin Romere6bdb902015-03-16 13:58:33 -04001537 struct controlvm_message local_crash_bus_msg;
1538 struct controlvm_message local_crash_dev_msg;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001539 struct controlvm_message msg;
Benjamin Romere6bdb902015-03-16 13:58:33 -04001540 u32 local_crash_msg_offset;
1541 u16 local_crash_msg_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001542
Ken Cox12e364b2014-03-04 07:58:07 -06001543 POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1544
1545 /* send init chipset msg */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001546 msg.hdr.id = CONTROLVM_CHIPSET_INIT;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001547 msg.cmd.init_chipset.bus_count = 23;
1548 msg.cmd.init_chipset.switch_count = 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001549
1550 chipset_init(&msg);
1551
Ken Cox12e364b2014-03-04 07:58:07 -06001552 /* get saved message count */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001553 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001554 offsetof(struct spar_controlvm_channel_protocol,
1555 saved_crash_message_count),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001556 &local_crash_msg_count, sizeof(u16)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001557 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1558 POSTCODE_SEVERITY_ERR);
1559 return;
1560 }
1561
Benjamin Romere6bdb902015-03-16 13:58:33 -04001562 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
Ken Cox12e364b2014-03-04 07:58:07 -06001563 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001564 local_crash_msg_count,
Ken Cox12e364b2014-03-04 07:58:07 -06001565 POSTCODE_SEVERITY_ERR);
1566 return;
1567 }
1568
1569 /* get saved crash message offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001570 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001571 offsetof(struct spar_controlvm_channel_protocol,
1572 saved_crash_message_offset),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001573 &local_crash_msg_offset, sizeof(u32)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001574 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1575 POSTCODE_SEVERITY_ERR);
1576 return;
1577 }
1578
1579 /* read create device message for storage bus offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001580 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001581 local_crash_msg_offset,
1582 &local_crash_bus_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001583 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001584 POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
1585 POSTCODE_SEVERITY_ERR);
1586 return;
1587 }
1588
1589 /* read create device message for storage device */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001590 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001591 local_crash_msg_offset +
Benjamin Romer3ab47702014-10-23 14:30:31 -04001592 sizeof(struct controlvm_message),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001593 &local_crash_dev_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001594 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001595 POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
1596 POSTCODE_SEVERITY_ERR);
1597 return;
1598 }
1599
1600 /* reuse IOVM create bus message */
Jes Sorensenebec8962015-05-05 18:35:57 -04001601 if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04001602 bus_create(&local_crash_bus_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001603 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001604 POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
1605 POSTCODE_SEVERITY_ERR);
1606 return;
1607 }
1608
1609 /* reuse create device message for storage device */
Jes Sorensenebec8962015-05-05 18:35:57 -04001610 if (local_crash_dev_msg.cmd.create_device.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04001611 my_device_create(&local_crash_dev_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001612 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001613 POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
1614 POSTCODE_SEVERITY_ERR);
1615 return;
1616 }
Ken Cox12e364b2014-03-04 07:58:07 -06001617 POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001618}
1619
David Binder87241ab2016-06-10 21:48:21 -04001620void
Don Zickusd32517e2015-06-04 09:22:41 -04001621bus_create_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001622{
Alessandro Parini4b4fd432015-06-13 17:40:48 +02001623 if (response >= 0)
Don Zickus0274b5a2015-06-01 13:00:27 -04001624 bus_info->state.created = 1;
Don Zickus0274b5a2015-06-01 13:00:27 -04001625
1626 bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
1627 response);
1628
1629 kfree(bus_info->pending_msg_hdr);
1630 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001631}
1632
David Binder87241ab2016-06-10 21:48:21 -04001633void
Don Zickusd32517e2015-06-04 09:22:41 -04001634bus_destroy_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001635{
Don Zickus0274b5a2015-06-01 13:00:27 -04001636 bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
1637 response);
1638
1639 kfree(bus_info->pending_msg_hdr);
1640 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001641}
1642
David Binder87241ab2016-06-10 21:48:21 -04001643void
Don Zickusa298bc02015-06-04 09:22:42 -04001644device_create_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001645{
Don Zickus0274b5a2015-06-01 13:00:27 -04001646 if (response >= 0)
1647 dev_info->state.created = 1;
1648
1649 device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
1650 response);
1651
1652 kfree(dev_info->pending_msg_hdr);
Tim Selladdce192015-07-09 13:27:41 -04001653 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001654}
1655
David Binder87241ab2016-06-10 21:48:21 -04001656void
Don Zickusa298bc02015-06-04 09:22:42 -04001657device_destroy_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001658{
Don Zickus0274b5a2015-06-01 13:00:27 -04001659 device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
1660 response);
1661
1662 kfree(dev_info->pending_msg_hdr);
1663 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001664}
1665
David Binder87241ab2016-06-10 21:48:21 -04001666void
David Binderea3a5aaf2016-06-10 21:48:22 -04001667device_pause_response(struct visor_device *dev_info,
1668 int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001669{
Ken Cox12e364b2014-03-04 07:58:07 -06001670 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04001671 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001672 segment_state_standby);
Don Zickus0274b5a2015-06-01 13:00:27 -04001673
1674 kfree(dev_info->pending_msg_hdr);
1675 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001676}
Ken Cox12e364b2014-03-04 07:58:07 -06001677
David Binder87241ab2016-06-10 21:48:21 -04001678void
Don Zickusa298bc02015-06-04 09:22:42 -04001679device_resume_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001680{
1681 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04001682 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001683 segment_state_running);
Don Zickus0274b5a2015-06-01 13:00:27 -04001684
1685 kfree(dev_info->pending_msg_hdr);
1686 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001687}
1688
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001689static int
1690visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
1691{
1692 unsigned long physaddr = 0;
1693 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
Erik Arfvidson780fcad2015-05-05 18:36:35 -04001694 u64 addr = 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001695
1696 /* sv_enable_dfp(); */
1697 if (offset & (PAGE_SIZE - 1))
1698 return -ENXIO; /* need aligned offsets */
1699
1700 switch (offset) {
1701 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
1702 vma->vm_flags |= VM_IO;
1703 if (!*file_controlvm_channel)
1704 return -ENXIO;
1705
Tim Sella07d7c32016-04-04 23:31:12 -04001706 visorchannel_read
1707 (*file_controlvm_channel,
1708 offsetof(struct spar_controlvm_channel_protocol,
1709 gp_control_channel),
1710 &addr, sizeof(addr));
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001711 if (!addr)
1712 return -ENXIO;
1713
1714 physaddr = (unsigned long)addr;
1715 if (remap_pfn_range(vma, vma->vm_start,
1716 physaddr >> PAGE_SHIFT,
1717 vma->vm_end - vma->vm_start,
1718 /*pgprot_noncached */
1719 (vma->vm_page_prot))) {
1720 return -EAGAIN;
1721 }
1722 break;
1723 default:
1724 return -ENXIO;
1725 }
1726 return 0;
1727}
1728
David Kershner5f3a7e32015-05-13 13:22:10 -04001729static inline s64 issue_vmcall_query_guest_virtual_time_offset(void)
1730{
1731 u64 result = VMCALL_SUCCESS;
1732 u64 physaddr = 0;
1733
1734 ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
1735 result);
1736 return result;
1737}
1738
1739static inline int issue_vmcall_update_physical_time(u64 adjustment)
1740{
1741 int result = VMCALL_SUCCESS;
1742
1743 ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
1744 return result;
1745}
1746
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001747static long visorchipset_ioctl(struct file *file, unsigned int cmd,
1748 unsigned long arg)
1749{
David Kershner25002762016-03-03 13:00:38 -05001750 u64 adjustment;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001751 s64 vrtc_offset;
1752
1753 switch (cmd) {
1754 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
1755 /* get the physical rtc offset */
1756 vrtc_offset = issue_vmcall_query_guest_virtual_time_offset();
1757 if (copy_to_user((void __user *)arg, &vrtc_offset,
1758 sizeof(vrtc_offset))) {
1759 return -EFAULT;
1760 }
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001761 return 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001762 case VMCALL_UPDATE_PHYSICAL_TIME:
1763 if (copy_from_user(&adjustment, (void __user *)arg,
1764 sizeof(adjustment))) {
1765 return -EFAULT;
1766 }
1767 return issue_vmcall_update_physical_time(adjustment);
1768 default:
1769 return -EFAULT;
1770 }
1771}
1772
1773static const struct file_operations visorchipset_fops = {
1774 .owner = THIS_MODULE,
1775 .open = visorchipset_open,
1776 .read = NULL,
1777 .write = NULL,
1778 .unlocked_ioctl = visorchipset_ioctl,
1779 .release = visorchipset_release,
1780 .mmap = visorchipset_mmap,
1781};
1782
Jes Sorensen0f570fc2015-05-13 13:21:55 -04001783static int
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001784visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
1785{
1786 int rc = 0;
1787
1788 file_controlvm_channel = controlvm_channel;
1789 cdev_init(&file_cdev, &visorchipset_fops);
1790 file_cdev.owner = THIS_MODULE;
1791 if (MAJOR(major_dev) == 0) {
Erik Arfvidson46168812015-05-05 18:36:14 -04001792 rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001793 /* dynamic major device number registration required */
1794 if (rc < 0)
1795 return rc;
1796 } else {
1797 /* static major device number registration required */
Erik Arfvidson46168812015-05-05 18:36:14 -04001798 rc = register_chrdev_region(major_dev, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04001799 if (rc < 0)
1800 return rc;
1801 }
1802 rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
1803 if (rc < 0) {
1804 unregister_chrdev_region(major_dev, 1);
1805 return rc;
1806 }
1807 return 0;
1808}
1809
David Kershner1366a3d2016-04-04 23:31:37 -04001810static void
1811visorchipset_file_cleanup(dev_t major_dev)
1812{
1813 if (file_cdev.ops)
1814 cdev_del(&file_cdev);
1815 file_cdev.ops = NULL;
1816 unregister_chrdev_region(major_dev, 1);
1817}
1818
David Kershner612b81c2016-09-19 17:09:22 -04001819static struct parser_context *
1820parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
1821{
1822 int allocbytes = sizeof(struct parser_context) + bytes;
1823 struct parser_context *ctx;
1824
1825 if (retry)
1826 *retry = false;
1827
1828 /*
1829 * alloc an 0 extra byte to ensure payload is
1830 * '\0'-terminated
1831 */
1832 allocbytes++;
1833 if ((controlvm_payload_bytes_buffered + bytes)
1834 > MAX_CONTROLVM_PAYLOAD_BYTES) {
1835 if (retry)
1836 *retry = true;
1837 return NULL;
1838 }
1839 ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
1840 if (!ctx) {
1841 if (retry)
1842 *retry = true;
1843 return NULL;
1844 }
1845
1846 ctx->allocbytes = allocbytes;
1847 ctx->param_bytes = bytes;
1848 ctx->curr = NULL;
1849 ctx->bytes_remaining = 0;
1850 ctx->byte_stream = false;
1851 if (local) {
1852 void *p;
1853
1854 if (addr > virt_to_phys(high_memory - 1))
1855 goto err_finish_ctx;
1856 p = __va((unsigned long)(addr));
1857 memcpy(ctx->data, p, bytes);
1858 } else {
1859 void *mapping = memremap(addr, bytes, MEMREMAP_WB);
1860
1861 if (!mapping)
1862 goto err_finish_ctx;
1863 memcpy(ctx->data, mapping, bytes);
1864 memunmap(mapping);
1865 }
1866
1867 ctx->byte_stream = true;
1868 controlvm_payload_bytes_buffered += ctx->param_bytes;
1869
1870 return ctx;
1871
1872err_finish_ctx:
1873 parser_done(ctx);
1874 return NULL;
1875}
1876
David Kershner511474a2016-09-19 17:09:21 -04001877/**
1878 * handle_command() - process a controlvm message
1879 * @inmsg: the message to process
1880 * @channel_addr: address of the controlvm channel
1881 *
1882 * Return:
1883 * false - this function will return false only in the case where the
1884 * controlvm message was NOT processed, but processing must be
1885 * retried before reading the next controlvm message; a
1886 * scenario where this can occur is when we need to throttle
1887 * the allocation of memory in which to copy out controlvm
1888 * payload data
1889 * true - processing of the controlvm message completed,
1890 * either successfully or with an error
1891 */
1892static bool
1893handle_command(struct controlvm_message inmsg, u64 channel_addr)
1894{
1895 struct controlvm_message_packet *cmd = &inmsg.cmd;
1896 u64 parm_addr;
1897 u32 parm_bytes;
1898 struct parser_context *parser_ctx = NULL;
1899 bool local_addr;
1900 struct controlvm_message ackmsg;
1901
1902 /* create parsing context if necessary */
1903 local_addr = (inmsg.hdr.flags.test_message == 1);
1904 if (channel_addr == 0)
1905 return true;
1906 parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
1907 parm_bytes = inmsg.hdr.payload_bytes;
1908
1909 /*
1910 * Parameter and channel addresses within test messages actually lie
1911 * within our OS-controlled memory. We need to know that, because it
1912 * makes a difference in how we compute the virtual address.
1913 */
1914 if (parm_addr && parm_bytes) {
1915 bool retry = false;
1916
1917 parser_ctx =
1918 parser_init_byte_stream(parm_addr, parm_bytes,
1919 local_addr, &retry);
1920 if (!parser_ctx && retry)
1921 return false;
1922 }
1923
1924 if (!local_addr) {
1925 controlvm_init_response(&ackmsg, &inmsg.hdr,
1926 CONTROLVM_RESP_SUCCESS);
1927 if (controlvm_channel)
1928 visorchannel_signalinsert(controlvm_channel,
1929 CONTROLVM_QUEUE_ACK,
1930 &ackmsg);
1931 }
1932 switch (inmsg.hdr.id) {
1933 case CONTROLVM_CHIPSET_INIT:
1934 chipset_init(&inmsg);
1935 break;
1936 case CONTROLVM_BUS_CREATE:
1937 bus_create(&inmsg);
1938 break;
1939 case CONTROLVM_BUS_DESTROY:
1940 bus_destroy(&inmsg);
1941 break;
1942 case CONTROLVM_BUS_CONFIGURE:
1943 bus_configure(&inmsg, parser_ctx);
1944 break;
1945 case CONTROLVM_DEVICE_CREATE:
1946 my_device_create(&inmsg);
1947 break;
1948 case CONTROLVM_DEVICE_CHANGESTATE:
1949 if (cmd->device_change_state.flags.phys_device) {
1950 parahotplug_process_message(&inmsg);
1951 } else {
1952 /*
1953 * save the hdr and cmd structures for later use
1954 * when sending back the response to Command
1955 */
1956 my_device_changestate(&inmsg);
1957 break;
1958 }
1959 break;
1960 case CONTROLVM_DEVICE_DESTROY:
1961 my_device_destroy(&inmsg);
1962 break;
1963 case CONTROLVM_DEVICE_CONFIGURE:
1964 /* no op for now, just send a respond that we passed */
1965 if (inmsg.hdr.flags.response_expected)
1966 controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
1967 break;
1968 case CONTROLVM_CHIPSET_READY:
1969 chipset_ready(&inmsg.hdr);
1970 break;
1971 case CONTROLVM_CHIPSET_SELFTEST:
1972 chipset_selftest(&inmsg.hdr);
1973 break;
1974 case CONTROLVM_CHIPSET_STOP:
1975 chipset_notready(&inmsg.hdr);
1976 break;
1977 default:
1978 if (inmsg.hdr.flags.response_expected)
1979 controlvm_respond
1980 (&inmsg.hdr,
1981 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
1982 break;
1983 }
1984
1985 if (parser_ctx) {
1986 parser_done(parser_ctx);
1987 parser_ctx = NULL;
1988 }
1989 return true;
1990}
1991
David Kershner8a285322016-09-19 17:09:23 -04001992/**
1993 * read_controlvm_event() - retreives the next message from the
1994 * CONTROLVM_QUEUE_EVENT queue in the controlvm
1995 * channel
1996 * @msg: pointer to the retrieved message
1997 *
1998 * Return: true if a valid message was retrieved or false otherwise
1999 */
2000static bool
2001read_controlvm_event(struct controlvm_message *msg)
2002{
David Binderf621a962016-09-26 11:03:48 -04002003 if (!visorchannel_signalremove(controlvm_channel,
2004 CONTROLVM_QUEUE_EVENT, msg)) {
David Kershner8a285322016-09-19 17:09:23 -04002005 /* got a message */
2006 if (msg->hdr.flags.test_message == 1)
2007 return false;
2008 return true;
2009 }
2010 return false;
2011}
2012
David Kershnera9c73932016-09-19 17:09:24 -04002013/**
2014 * parahotplug_process_list() - remove any request from the list that's been on
2015 * there too long and respond with an error
2016 */
2017static void
2018parahotplug_process_list(void)
2019{
2020 struct list_head *pos;
2021 struct list_head *tmp;
2022
2023 spin_lock(&parahotplug_request_list_lock);
2024
2025 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
2026 struct parahotplug_request *req =
2027 list_entry(pos, struct parahotplug_request, list);
2028
2029 if (!time_after_eq(jiffies, req->expiration))
2030 continue;
2031
2032 list_del(pos);
2033 if (req->msg.hdr.flags.response_expected)
2034 controlvm_respond_physdev_changestate(
2035 &req->msg.hdr,
2036 CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
2037 req->msg.cmd.device_change_state.state);
2038 parahotplug_request_destroy(req);
2039 }
2040
2041 spin_unlock(&parahotplug_request_list_lock);
2042}
2043
David Kershner3d8394c2016-09-19 17:09:20 -04002044static void
2045controlvm_periodic_work(struct work_struct *work)
2046{
2047 struct controlvm_message inmsg;
2048 bool got_command = false;
2049 bool handle_command_failed = false;
2050
David Binderf621a962016-09-26 11:03:48 -04002051 while (!visorchannel_signalremove(controlvm_channel,
2052 CONTROLVM_QUEUE_RESPONSE,
2053 &inmsg))
David Kershner3d8394c2016-09-19 17:09:20 -04002054 ;
2055 if (!got_command) {
2056 if (controlvm_pending_msg_valid) {
2057 /*
2058 * we throttled processing of a prior
2059 * msg, so try to process it again
2060 * rather than reading a new one
2061 */
2062 inmsg = controlvm_pending_msg;
2063 controlvm_pending_msg_valid = false;
2064 got_command = true;
2065 } else {
2066 got_command = read_controlvm_event(&inmsg);
2067 }
2068 }
2069
2070 handle_command_failed = false;
2071 while (got_command && (!handle_command_failed)) {
2072 most_recent_message_jiffies = jiffies;
2073 if (handle_command(inmsg,
2074 visorchannel_get_physaddr
2075 (controlvm_channel)))
2076 got_command = read_controlvm_event(&inmsg);
2077 else {
2078 /*
2079 * this is a scenario where throttling
2080 * is required, but probably NOT an
2081 * error...; we stash the current
2082 * controlvm msg so we will attempt to
2083 * reprocess it on our next loop
2084 */
2085 handle_command_failed = true;
2086 controlvm_pending_msg = inmsg;
2087 controlvm_pending_msg_valid = true;
2088 }
2089 }
2090
2091 /* parahotplug_worker */
2092 parahotplug_process_list();
2093
2094 if (time_after(jiffies,
2095 most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
2096 /*
2097 * it's been longer than MIN_IDLE_SECONDS since we
2098 * processed our last controlvm message; slow down the
2099 * polling
2100 */
2101 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
2102 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
2103 } else {
2104 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
2105 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
2106 }
2107
2108 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
2109}
2110
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002111static int
2112visorchipset_init(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002113{
David Kershner1366a3d2016-04-04 23:31:37 -04002114 int err = -ENODEV;
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002115 u64 addr;
Jes Sorensend3368a52015-05-13 13:21:57 -04002116 uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
2117
2118 addr = controlvm_get_channel_address();
2119 if (!addr)
David Kershner1366a3d2016-04-04 23:31:37 -04002120 goto error;
Ken Cox12e364b2014-03-04 07:58:07 -06002121
Benjamin Romer84982fb2015-03-16 13:58:07 -04002122 memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06002123
Tim Sellc732623b2016-03-01 19:45:03 -05002124 controlvm_channel = visorchannel_create_with_lock(addr, 0,
Jes Sorensend3368a52015-05-13 13:21:57 -04002125 GFP_KERNEL, uuid);
Tim Sellc732623b2016-03-01 19:45:03 -05002126 if (!controlvm_channel)
David Kershner1366a3d2016-04-04 23:31:37 -04002127 goto error;
2128
Jes Sorensend3368a52015-05-13 13:21:57 -04002129 if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
2130 visorchannel_get_header(controlvm_channel))) {
2131 initialize_controlvm_payload();
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002132 } else {
David Kershner1366a3d2016-04-04 23:31:37 -04002133 goto error_destroy_channel;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002134 }
2135
Benjamin Romer5aa8ae52015-03-16 13:58:44 -04002136 major_dev = MKDEV(visorchipset_major, 0);
David Kershner1366a3d2016-04-04 23:31:37 -04002137 err = visorchipset_file_init(major_dev, &controlvm_channel);
2138 if (err < 0)
2139 goto error_destroy_payload;
Ken Cox12e364b2014-03-04 07:58:07 -06002140
David Kershner4da33362015-05-05 18:36:39 -04002141 /* if booting in a crash kernel */
2142 if (is_kdump_kernel())
2143 INIT_DELAYED_WORK(&periodic_controlvm_work,
2144 setup_crash_devices_work_queue);
2145 else
2146 INIT_DELAYED_WORK(&periodic_controlvm_work,
2147 controlvm_periodic_work);
Ken Cox12e364b2014-03-04 07:58:07 -06002148
David Kershner4da33362015-05-05 18:36:39 -04002149 most_recent_message_jiffies = jiffies;
2150 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302151 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06002152
Benjamin Romereb34e872015-03-16 13:58:45 -04002153 visorchipset_platform_device.dev.devt = major_dev;
2154 if (platform_device_register(&visorchipset_platform_device) < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002155 POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
David Kershner1366a3d2016-04-04 23:31:37 -04002156 err = -ENODEV;
2157 goto error_cancel_work;
Ken Cox4cb005a2014-03-19 13:06:20 -05002158 }
Ken Cox12e364b2014-03-04 07:58:07 -06002159 POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002160
David Kershner1366a3d2016-04-04 23:31:37 -04002161 err = visorbus_init();
2162 if (err < 0)
2163 goto error_unregister;
Ken Cox12e364b2014-03-04 07:58:07 -06002164
David Kershner1366a3d2016-04-04 23:31:37 -04002165 return 0;
2166
2167error_unregister:
2168 platform_device_unregister(&visorchipset_platform_device);
2169
2170error_cancel_work:
2171 cancel_delayed_work_sync(&periodic_controlvm_work);
2172 visorchipset_file_cleanup(major_dev);
2173
2174error_destroy_payload:
2175 destroy_controlvm_payload_info(&controlvm_payload_info);
2176
2177error_destroy_channel:
2178 visorchannel_destroy(controlvm_channel);
2179
2180error:
2181 POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
2182 return err;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002183}
2184
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002185static int
2186visorchipset_exit(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002187{
Ken Cox12e364b2014-03-04 07:58:07 -06002188 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
2189
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002190 visorbus_exit();
2191
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302192 cancel_delayed_work_sync(&periodic_controlvm_work);
David Kershner4da33362015-05-05 18:36:39 -04002193 destroy_controlvm_payload_info(&controlvm_payload_info);
Benjamin Romer17833192014-07-15 13:30:41 -04002194
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002195 visorchannel_destroy(controlvm_channel);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002196
Sudip Mukherjeeaddceb12015-03-24 20:47:28 +05302197 visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
Don Zickus04dacac2015-06-04 09:22:48 -04002198 platform_device_unregister(&visorchipset_platform_device);
Ken Cox12e364b2014-03-04 07:58:07 -06002199 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002200
2201 return 0;
2202}
2203
2204static const struct acpi_device_id unisys_device_ids[] = {
2205 {"PNP0A07", 0},
2206 {"", 0},
2207};
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002208
2209static struct acpi_driver unisys_acpi_driver = {
2210 .name = "unisys_acpi",
2211 .class = "unisys_acpi_class",
2212 .owner = THIS_MODULE,
2213 .ids = unisys_device_ids,
2214 .ops = {
2215 .add = visorchipset_init,
2216 .remove = visorchipset_exit,
2217 },
2218};
David Kershner1fc07f92015-07-09 13:27:53 -04002219
2220MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
2221
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002222static __init uint32_t visorutil_spar_detect(void)
2223{
2224 unsigned int eax, ebx, ecx, edx;
2225
Borislav Petkov0c9f3532016-03-29 17:41:55 +02002226 if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002227 /* check the ID */
2228 cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
2229 return (ebx == UNISYS_SPAR_ID_EBX) &&
2230 (ecx == UNISYS_SPAR_ID_ECX) &&
2231 (edx == UNISYS_SPAR_ID_EDX);
2232 } else {
2233 return 0;
2234 }
2235}
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002236
2237static int init_unisys(void)
2238{
2239 int result;
Alessandro Parini35e606d2015-06-13 17:40:49 +02002240
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002241 if (!visorutil_spar_detect())
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002242 return -ENODEV;
2243
2244 result = acpi_bus_register_driver(&unisys_acpi_driver);
2245 if (result)
2246 return -ENODEV;
2247
2248 pr_info("Unisys Visorchipset Driver Loaded.\n");
2249 return 0;
2250};
2251
2252static void exit_unisys(void)
2253{
2254 acpi_bus_unregister_driver(&unisys_acpi_driver);
Ken Cox12e364b2014-03-04 07:58:07 -06002255}
2256
Ken Cox12e364b2014-03-04 07:58:07 -06002257module_param_named(major, visorchipset_major, int, S_IRUGO);
Jes Sorensenb615d622015-05-05 18:35:38 -04002258MODULE_PARM_DESC(visorchipset_major,
2259 "major device number to use for the device node");
Jes Sorensenb615d622015-05-05 18:35:38 -04002260
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002261module_init(init_unisys);
2262module_exit(exit_unisys);
Ken Cox12e364b2014-03-04 07:58:07 -06002263
2264MODULE_AUTHOR("Unisys");
2265MODULE_LICENSE("GPL");
Jon Frischbff8c1a2016-09-26 11:03:46 -04002266MODULE_DESCRIPTION("s-Par visorbus driver for virtual device buses");